From 208b5ad8195b169cedabf40e04d086e9580a135f Mon Sep 17 00:00:00 2001 From: aby-jo <173944472+aby-jo@users.noreply.github.com> Date: Tue, 24 Jun 2025 21:40:57 +0530 Subject: [PATCH 1/3] Improve SQL Beautify: use sql-formatter and support bind variables --- package-lock.json | 74 +++++++++++++++++++++++++++++ package.json | 1 + src/core/operations/SQLBeautify.mjs | 28 +++++++++-- 3 files changed, 99 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index b374df4bc9..05c9f57206 100644 --- a/package-lock.json +++ b/package-lock.json @@ -91,6 +91,7 @@ "snackbarjs": "^1.1.0", "sortablejs": "^1.15.2", "split.js": "^1.6.5", + "sql-formatter": "^15.6.5", "ssdeep.js": "0.0.3", "stream-browserify": "^3.0.0", "tesseract.js": "5.1.0", @@ -8340,6 +8341,11 @@ "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", "license": "MIT" }, + "node_modules/discontinuous-range": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", + "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==" + }, "node_modules/dns-packet": { "version": "5.6.1", "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", @@ -13573,6 +13579,11 @@ "node": "*" } }, + "node_modules/moo": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", + "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==" + }, "node_modules/more-entropy": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/more-entropy/-/more-entropy-0.0.7.tgz", @@ -13678,6 +13689,32 @@ "dev": true, "license": "MIT" }, + "node_modules/nearley": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", + "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", + "dependencies": { + "commander": "^2.19.0", + "moo": "^0.5.0", + "railroad-diagrams": "^1.0.0", + "randexp": "0.4.6" + }, + "bin": { + "nearley-railroad": "bin/nearley-railroad.js", + "nearley-test": "bin/nearley-test.js", + "nearley-unparse": "bin/nearley-unparse.js", + "nearleyc": "bin/nearleyc.js" + }, + "funding": { + "type": "individual", + "url": "https://nearley.js.org/#give-to-nearley" + } + }, + "node_modules/nearley/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -15664,6 +15701,23 @@ ], "license": "MIT" }, + "node_modules/railroad-diagrams": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", + "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==" + }, + "node_modules/randexp": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", + "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", + "dependencies": { + "discontinuous-range": "1.0.0", + "ret": "~0.1.10" + }, + "engines": { + "node": ">=0.12" + } + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -16103,6 +16157,14 @@ "node": ">=8" } }, + "node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "engines": { + "node": ">=0.12" + } + }, "node_modules/retry": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", @@ -17035,6 +17097,18 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/sql-formatter": { + "version": "15.6.5", + "resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-15.6.5.tgz", + "integrity": "sha512-fr4TyM1udCSrOHOmouotwUi8dxIDhSLpYNmPePGFVzxq8/i8jd828IapE49QXG7Gzkswxo5WwdAGnYX4YpKoTg==", + "dependencies": { + "argparse": "^2.0.1", + "nearley": "^2.20.1" + }, + "bin": { + "sql-formatter": "bin/sql-formatter-cli.cjs" + } + }, "node_modules/ssdeep.js": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/ssdeep.js/-/ssdeep.js-0.0.3.tgz", diff --git a/package.json b/package.json index 9191ab6f03..b7a5c22b4d 100644 --- a/package.json +++ b/package.json @@ -177,6 +177,7 @@ "snackbarjs": "^1.1.0", "sortablejs": "^1.15.2", "split.js": "^1.6.5", + "sql-formatter": "^15.6.5", "ssdeep.js": "0.0.3", "stream-browserify": "^3.0.0", "tesseract.js": "5.1.0", diff --git a/src/core/operations/SQLBeautify.mjs b/src/core/operations/SQLBeautify.mjs index 0f3d2e3c28..ddd78b0cad 100644 --- a/src/core/operations/SQLBeautify.mjs +++ b/src/core/operations/SQLBeautify.mjs @@ -4,7 +4,6 @@ * @license Apache-2.0 */ -import vkbeautify from "vkbeautify"; import Operation from "../Operation.mjs"; /** @@ -35,11 +34,32 @@ class SQLBeautify extends Operation { /** * @param {string} input * @param {Object[]} args - * @returns {string} + * @returns {Promise} */ - run(input, args) { + async run(input, args) { const indentStr = args[0]; - return vkbeautify.sql(input, indentStr); + // Lazy import of sql-formatter for performance + const {format}= await import("sql-formatter"); + // Extract and replace bind variables like :Bind1 with __BIND_0__ + const bindRegex = /:\w+/g; + const bindMap = {}; + let bindCounter=0; + const placeholderInput = input.replace(bindRegex, (match) => { + const placeholder = `__BIND_${bindCounter++}__`; + bindMap[placeholder] = match; + return placeholder; + }); + // Format the SQL with chosen options + let formatted= format(placeholderInput, { + language: "mysql", // Use MySQL as the default dialect for better compatibility with real-world SQL + useTabs: indentStr==="\t", // true if tab, false if spaces + tabWidth: indentStr.length || 4, // fallback if empty + indentStyle: "standard" // fine for most SQL + }); + // Replace placeholders back with original bind variables + formatted = formatted.replace(/__BIND_\d+__/g, match => bindMap[match] || match); + + return formatted; } } From e5d732d49497b9e2691fe23df1e9f47d182012b7 Mon Sep 17 00:00:00 2001 From: aby-jo <173944472+aby-jo@users.noreply.github.com> Date: Tue, 24 Jun 2025 22:48:03 +0530 Subject: [PATCH 2/3] Fix SQL Beautify test output to align with updated formatter --- tests/node/tests/operations.mjs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/tests/node/tests/operations.mjs b/tests/node/tests/operations.mjs index 022b070133..41eddd821e 100644 --- a/tests/node/tests/operations.mjs +++ b/tests/node/tests/operations.mjs @@ -867,13 +867,15 @@ pCGTErs= }), it("SQL Beautify", () => { - const result = chef.SQLBeautify(`SELECT MONTH, ID, RAIN_I, TEMP_F -FROM STATS;`); - const expected = `SELECT MONTH, - ID, - RAIN_I, - TEMP_F -FROM STATS;`; + const result = chef.SQLBeautify(`SELECT MONTH, ID, RAIN_I, TEMP_F FROM STATS;`); + const expected = +`SELECT + MONTH, + ID, + RAIN_I, + TEMP_F +FROM + STATS;`; assert.strictEqual(result.toString(), expected); }), From 194dbbd59d8cbd0095c08d410f9dfac747b61e72 Mon Sep 17 00:00:00 2001 From: aby-jo <173944472+aby-jo@users.noreply.github.com> Date: Tue, 24 Jun 2025 22:58:15 +0530 Subject: [PATCH 3/3] Make SQLBeautify synchronous --- src/core/operations/SQLBeautify.mjs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/core/operations/SQLBeautify.mjs b/src/core/operations/SQLBeautify.mjs index ddd78b0cad..2171f7fc16 100644 --- a/src/core/operations/SQLBeautify.mjs +++ b/src/core/operations/SQLBeautify.mjs @@ -3,7 +3,7 @@ * @copyright Crown Copyright 2016 * @license Apache-2.0 */ - +import { format } from "sql-formatter"; import Operation from "../Operation.mjs"; /** @@ -34,12 +34,10 @@ class SQLBeautify extends Operation { /** * @param {string} input * @param {Object[]} args - * @returns {Promise} + * @returns {string} */ - async run(input, args) { + run(input, args) { const indentStr = args[0]; - // Lazy import of sql-formatter for performance - const {format}= await import("sql-formatter"); // Extract and replace bind variables like :Bind1 with __BIND_0__ const bindRegex = /:\w+/g; const bindMap = {};