Skip to content

Commit 7baebae

Browse files
committed
feat: Add UPDATE WHERE SQL statement
1 parent 17082fe commit 7baebae

2 files changed

Lines changed: 64 additions & 15 deletions

File tree

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@
168168
"INSERT INTO SELECT VALUES",
169169
"INSERT INTO",
170170
"DELETE WHERE",
171+
"UPDATE WHERE",
171172
"CREATE TABLE"
172173
],
173174
"default": "INSERT INTO VALUES",

src/paste-sql.js

Lines changed: 63 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,21 @@ const { parseClipboard } = require("./parse-table");
33
const { addTrailingZeroes, normalizeBool } = require("./utils");
44

55
async 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

Comments
 (0)