1 parent
3dd034bf06
commit
5375bd1473
2 files changed
+75
-1
No files matched your search
@@ -67,6 +67,39 @@ describe("executableStatementRangeCacheForDoc", () => {
|
||||
expect(executableStatementRangeStartingAt(cache, doc.line(5).from)).toBeNull();
|
||||
});
|
||||
|
||||
it.each(["/*& tenant:'gdx' */", "/*&tenant:mctest*/", "/*+ MAX_EXECUTION_TIME(1000) */", "/*@global:true*/", "/*proxy*/"])("resolves the SQL line after a preserved leading directive for gutter execution: %s", (directive) => {
|
||||
const sql = `SELECT 0;\n${directive}\nSELECT 1;`;
|
||||
const doc = Text.of(sql.split("\n"));
|
||||
const cache = executableStatementRangeCacheForDoc(null, doc, "mysql");
|
||||
|
||||
expect(executableStatementRangeStartingAt(cache, doc.line(3).from)?.sql).toBe(`${directive}\nSELECT 1`);
|
||||
});
|
||||
|
||||
it("keeps a same-line tenant hint in the gutter execution range", () => {
|
||||
const sql = "/*& tenant:'gdx' */ SELECT\n*\nFROM table";
|
||||
const doc = Text.of(sql.split("\n"));
|
||||
const cache = executableStatementRangeCacheForDoc(null, doc, "mysql");
|
||||
|
||||
expect(executableStatementRangeStartingAt(cache, doc.line(1).from)?.sql).toBe(sql);
|
||||
});
|
||||
|
||||
it("treats a SQL Server temporary table after a hint as executable content", () => {
|
||||
const sql = "/*+ hint */\n#temporary_table";
|
||||
const doc = Text.of(sql.split("\n"));
|
||||
const cache = executableStatementRangeCacheForDoc(null, doc, "sqlserver");
|
||||
|
||||
expect(executableStatementRangeStartingAt(cache, doc.line(2).from)?.sql).toBe(sql);
|
||||
});
|
||||
|
||||
it("does not attach ordinary leading block comments to gutter execution", () => {
|
||||
const doc = Text.of(["/* comment */", "SELECT 1;", "/* comment only */"]);
|
||||
const cache = executableStatementRangeCacheForDoc(null, doc, "mysql");
|
||||
|
||||
expect(executableStatementRangeStartingAt(cache, doc.line(1).from)).toBeNull();
|
||||
expect(executableStatementRangeStartingAt(cache, doc.line(2).from)?.sql).toBe("SELECT 1");
|
||||
expect(executableStatementRangeStartingAt(cache, doc.line(3).from)).toBeNull();
|
||||
});
|
||||
|
||||
it("does not resolve gutter run buttons when non-whitespace precedes the statement on the same line", () => {
|
||||
const doc = Text.of(["/* comment */ SELECT 1;"]);
|
||||
const cache = executableStatementRangeCacheForDoc(null, doc, "mysql");
|
||||
|
||||
@@ -30,17 +30,58 @@ export function executableStatementRangeCacheForDoc(
|
||||
|
||||
const byStart = new Map<number, SqlTextRange>();
|
||||
const byExecutableLineStart = new Map<number, SqlTextRange>();
|
||||
const ranges = parse(doc.toString(), databaseType, parameterOptions);
|
||||
const sql = doc.toString();
|
||||
const ranges = parse(sql, databaseType, parameterOptions);
|
||||
for (const range of ranges) {
|
||||
byStart.set(range.from, range);
|
||||
const line = doc.lineAt(range.from);
|
||||
if (doc.sliceString(line.from, range.from).trim() === "") {
|
||||
byExecutableLineStart.set(line.from, range);
|
||||
}
|
||||
const executableStart = executableStartAfterLeadingDirective(sql, range, databaseType, parameterOptions);
|
||||
if (executableStart !== null) {
|
||||
byExecutableLineStart.set(doc.lineAt(executableStart).from, range);
|
||||
}
|
||||
}
|
||||
return { doc, databaseType, parameterOptions, parameterSyntaxKey, byStart, byExecutableLineStart, ranges };
|
||||
}
|
||||
|
||||
function executableStartAfterLeadingDirective(sql: string, range: SqlTextRange, databaseType?: DatabaseType, parameterOptions?: SqlParameterOptions): number | null {
|
||||
const text = range.sql;
|
||||
const hasExecutableDirective = text.startsWith("/*+") || text.startsWith("/*@") || text.startsWith("/*&") || (databaseType === "mysql" && text.startsWith("/*proxy*/"));
|
||||
if (!hasExecutableDirective) return null;
|
||||
|
||||
let offset = 0;
|
||||
while (offset < text.length) {
|
||||
while (/\s/.test(text[offset] ?? "")) offset += 1;
|
||||
|
||||
if (text.startsWith("/*", offset)) {
|
||||
const close = text.indexOf("*/", offset + 2);
|
||||
if (close < 0) return null;
|
||||
offset = close + 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (text.startsWith("--", offset)) {
|
||||
const newline = text.indexOf("\n", offset + 2);
|
||||
if (newline < 0) return null;
|
||||
offset = newline + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (databaseType !== "sqlserver" && text[offset] === "#" && readSqlBracedParameterAt(sql, range.from + offset, parameterOptions)?.syntax !== "mybatis") {
|
||||
const newline = text.indexOf("\n", offset + 1);
|
||||
if (newline < 0) return null;
|
||||
offset = newline + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
return offset < text.length ? range.from + offset : null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export function executableStatementRangeStartingAt(cache: ExecutableStatementRangeCache, lineFrom: number): SqlTextRange | null {
|
||||
return cache.byStart.get(lineFrom) ?? cache.byExecutableLineStart.get(lineFrom) ?? null;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user