@@ -3,20 +3,21 @@ const { parseClipboard } = require("./parse-table");
33const { addTrailingZeroes, normalizeBool } = require ( "./utils" ) ;
44
55async function clipboardToSql ( statement = null ) {
6+
7+ function abortOnError ( message ) {
8+ vscode . window . showErrorMessage ( message ) ;
9+ }
10+
611 try {
712 // 1: Read the clipboard content
813 const clipboardContent = await vscode . env . clipboard . readText ( ) ;
914
1015 if ( ! clipboardContent ) {
11- vscode . window . showErrorMessage (
12- "Clipboard is empty or contains unsupported content."
13- ) ;
14- return ;
16+ return abortOnError ( "Clipboard is empty or contains unsupported content." ) ;
1517 }
1618
1719 // 2: Try to extract the table from clipboard content
18- let formattedData = null ;
19- formattedData = parseClipboard ( clipboardContent ) ;
20+ let tableData = parseClipboard ( clipboardContent ) ;
2021
2122 // 3: Ask the user which statement they want to use
2223 if ( statement === null ) {
@@ -27,6 +28,7 @@ async function clipboardToSql(statement = null) {
2728 "INSERT INTO SELECT VALUES" ,
2829 "INSERT INTO" ,
2930 "DELETE WHERE" ,
31+ "UPDATE WHERE" ,
3032 "CREATE TABLE"
3133 ] ;
3234 statement = await vscode . window . showQuickPick (
@@ -38,16 +40,28 @@ async function clipboardToSql(statement = null) {
3840 }
3941
4042 if ( ! statement ) {
41- vscode . window . showErrorMessage ( "No statement selected." ) ;
42- return ;
43+ return abortOnError ( "No SQL statement selected." ) ;
44+ }
45+
46+ let keyColumns = [ ] ;
47+ if ( statement === "UPDATE WHERE" ) {
48+ keyColumns = await vscode . window . showQuickPick (
49+ tableData . headers ,
50+ {
51+ placeHolder : "Select the key columns for matching rows" ,
52+ canPickMany : true
53+ }
54+ ) ;
55+ if ( ! keyColumns || keyColumns . length === 0 ) {
56+ return abortOnError ( "No key columns for matching rows selected." ) ;
57+ }
4358 }
4459
4560 // 4: Generate the Sql code using the selected statement
46- const sqlCode = createSql ( formattedData , statement ) ;
61+ const sqlCode = createSql ( tableData , statement , keyColumns ) ;
4762
4863 if ( ! sqlCode ) {
49- vscode . window . showErrorMessage ( "Failed to generate Sql code." ) ;
50- return ;
64+ return abortOnError ( "Failed to generate Sql code." ) ;
5165 }
5266
5367 // 5: Insert the generated code into the active editor
@@ -58,14 +72,14 @@ async function clipboardToSql(statement = null) {
5872 } ) ;
5973 }
6074 } catch ( error ) {
61- vscode . window . showErrorMessage ( `Error: ${ error . message } ` ) ;
75+ abortOnError ( `Error: ${ error . message } ` ) ;
6276 }
6377}
6478
6579/**
6680 * Generates a Sql script based on the provided table data.
6781 */
68- function createSql ( tableData , statement ) {
82+ function createSql ( tableData , statement , keyColumns ) {
6983
7084 /**
7185 * Formats a value according to its column type for SQL syntax
@@ -123,18 +137,41 @@ function createSql(tableData, statement) {
123137 return "" ;
124138 }
125139
140+ function getRowsAs2Columns (
141+ rows , cols , keys ,
142+ template1 , col1start , col1sep , col1end ,
143+ template2 , col2start , col2sep , col2end ) {
144+
145+ const lines = rows . map ( function ( row , j ) {
146+ const vals = row . map ( function ( value , i ) {
147+ let nam1 = cols [ i ] ;
148+ let val2 = formatValue ( value , i ) ;
149+ let pos = keys . indexOf ( nam1 ) < 0 ? 1 : 2 ;
150+ let tpl = pos === 1 ? template1 : template2 ;
151+ let res = tpl . replace ( "{1}" , nam1 ) . replace ( "{2}" , val2 ) ;
152+ return [ res , pos ] ;
153+ } ) ;
154+ let val1 = vals . filter ( v => v [ 1 ] === 1 ) . map ( v => v [ 0 ] ) ;
155+ let val2 = vals . filter ( v => v [ 1 ] === 2 ) . map ( v => v [ 0 ] ) ;
156+ let text1 = col1start + val1 . join ( col1sep ) + col1end ;
157+ let text2 = col2start + val2 . join ( col2sep ) + col2end ;
158+ return [ text1 , text2 ] ;
159+ } ) ;
160+ return lines ;
161+ }
162+
126163 // Pads a value to the target width
127164 function padToWidth ( value , width , padding ) {
128165 let wide = width - value . toString ( ) . length ;
129- return value + padding . repeat ( wide ) ;
166+ return value + padding . repeat ( wide ) ;
130167 }
131168
132169 function getRowsAsTuple ( rows , cols ) {
133170 return getRowsAs ( rows , cols , "{2}" , " (" , ", " , ")" , ",\n" ) ;
134171 }
135172
136173 function getRowsAsUnionAll ( rows , cols ) {
137- return getRowsAs ( rows , cols , "{2} AS {1}" , " SELECT" , ", " , "" , " UNION ALL\n" ) ;
174+ return getRowsAs ( rows , cols , "{2} AS {1}" , " SELECT " , ", " , "" , " UNION ALL\n" ) ;
138175 }
139176
140177 function getColumnsAsTuple ( cols ) {
@@ -195,6 +232,15 @@ function createSql(tableData, statement) {
195232 return res ;
196233 }
197234
235+ function getSqlAsUpdateWhere ( rows , cols , keys ) {
236+ const vals = getRowsAs2Columns (
237+ rows , cols , keys , "{1} = {2}" , "" , ", " , "" , "{1} = {2}" , "" , " AND " , ""
238+ ) ;
239+ let stmt = `UPDATE mytable SET {1} WHERE {2};` ;
240+ let sql = vals . map ( v => stmt . replace ( "{1}" , v [ 0 ] ) . replace ( "{2}" , v [ 1 ] . replaceAll ( "= NULL" , "IS NULL" ) ) ) ;
241+ return sql . join ( "\n" ) + "\n\n" ;
242+ }
243+
198244 const { headers, data, columnTypes } = tableData ;
199245 switch ( statement ) {
200246 case "SELECT FROM VALUES" :
@@ -209,6 +255,8 @@ function createSql(tableData, statement) {
209255 return getSqlAsInsertIntoMultiple ( data , headers ) ;
210256 case "DELETE WHERE" :
211257 return getSqlAsDeleteWhere ( data , headers ) ;
258+ case "UPDATE WHERE" :
259+ return getSqlAsUpdateWhere ( data , headers , keyColumns ) ;
212260 case "CREATE TABLE" :
213261 return getSqlAsCreateTable ( data , headers ) ;
214262 }
0 commit comments