fix(mysql): strip CLI \G suffix before executing queries
This commit is contained in:
5 files changed
+82
-8
No files matched your search
@@ -1,6 +1,6 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { executionCandidateForMode } from "@/lib/sql/sqlExecutionTarget";
|
||||
import { buildExecutionCandidates, currentExecutableStatementRange, executableStatementRanges, fullSqlRange, hasMultipleExecutionTargets, splitSqlStatementRanges, statementRangeAtCursor, supportsExecutionTargetPicker } from "@/lib/sql/sqlStatementRanges";
|
||||
import { buildExecutionCandidates, currentExecutableStatementRange, executableStatementRanges, fullSqlRange, hasMultipleExecutionTargets, splitSqlStatementRanges, statementRangeAtCursor, stripMysqlClientDisplayCommand, supportsExecutionTargetPicker } from "@/lib/sql/sqlStatementRanges";
|
||||
|
||||
function indexOf(sql: string, needle: string, occurrence = 1): number {
|
||||
let from = 0;
|
||||
@@ -377,6 +377,25 @@ BEGIN
|
||||
END;
|
||||
SELECT 3 FROM DUMMY;`;
|
||||
|
||||
describe("stripMysqlClientDisplayCommand", () => {
|
||||
it("removes a trailing MySQL CLI vertical-output command", () => {
|
||||
expect(stripMysqlClientDisplayCommand("SHOW CREATE FUNCTION fun_grade \\G")).toBe("SHOW CREATE FUNCTION fun_grade");
|
||||
expect(stripMysqlClientDisplayCommand("SHOW CREATE FUNCTION fun_grade \\G;")).toBe("SHOW CREATE FUNCTION fun_grade;");
|
||||
expect(stripMysqlClientDisplayCommand("SELECT 1\\G\n")).toBe("SELECT 1\n");
|
||||
});
|
||||
|
||||
it("removes the lowercase terminator and a command following the semicolon", () => {
|
||||
expect(stripMysqlClientDisplayCommand("SHOW STATUS \\g")).toBe("SHOW STATUS");
|
||||
expect(stripMysqlClientDisplayCommand("SELECT 1; \\G")).toBe("SELECT 1;");
|
||||
});
|
||||
|
||||
it("does not rewrite ordinary SQL or a command inside a line comment", () => {
|
||||
expect(stripMysqlClientDisplayCommand("SELECT '\\G'")).toBe("SELECT '\\G'");
|
||||
expect(stripMysqlClientDisplayCommand("SELECT 1 -- keep \\G")).toBe("SELECT 1 -- keep \\G");
|
||||
expect(stripMysqlClientDisplayCommand("SELECT 1 # keep \\G")).toBe("SELECT 1 # keep \\G");
|
||||
});
|
||||
});
|
||||
|
||||
describe("splitSqlStatementRanges", () => {
|
||||
it("splits multiple top-level statements", () => {
|
||||
const sql = "SELECT 1;\nSELECT 2;\nSELECT 3;";
|
||||
|
||||
@@ -32,6 +32,22 @@ export function supportsExecutionTargetPicker(databaseType?: DatabaseType): bool
|
||||
return !!databaseType && (databaseType === "redis" || isHttpJsonRestDatabaseType(databaseType) || !NON_SQL_EXECUTION_TARGET_TYPES.has(databaseType));
|
||||
}
|
||||
|
||||
/** Remove the MySQL CLI's trailing vertical-output command before execution. */
|
||||
export function stripMysqlClientDisplayCommand(sql: string): string {
|
||||
const trimmed = sql.trimEnd();
|
||||
const hasTrailingSemicolon = trimmed.endsWith(";");
|
||||
const withoutTrailingSemicolon = hasTrailingSemicolon ? trimmed.slice(0, -1).trimEnd() : trimmed;
|
||||
if (!withoutTrailingSemicolon.endsWith("\\G") && !withoutTrailingSemicolon.endsWith("\\g")) return sql;
|
||||
|
||||
const markerStart = withoutTrailingSemicolon.length - 2;
|
||||
const lineStart = withoutTrailingSemicolon.lastIndexOf("\n", markerStart - 1) + 1;
|
||||
const linePrefix = withoutTrailingSemicolon.slice(lineStart, markerStart);
|
||||
if (linePrefix.includes("--") || linePrefix.includes("#")) return sql;
|
||||
|
||||
const executableSql = withoutTrailingSemicolon.slice(0, markerStart).trimEnd();
|
||||
return `${executableSql}${hasTrailingSemicolon ? ";" : ""}${sql.slice(trimmed.length)}`;
|
||||
}
|
||||
|
||||
export function hasMultipleExecutionTargets(sql: string, databaseType?: DatabaseType, parameterOptions?: SqlParameterOptions): boolean {
|
||||
if (databaseType === "redis") {
|
||||
return redisExecutableCommandCount(sql) > 1;
|
||||
|
||||
Reference in new issue
Block a user