109 lines
5.4 KiB
TypeScript
Vendored
109 lines
5.4 KiB
TypeScript
Vendored
import { describe, expect, it } from "vitest";
|
|
import { expandSqlVariables } from "@/lib/sql/sqlVariables";
|
|
|
|
describe("expandSqlVariables", () => {
|
|
it("returns the SQL unchanged when there is no @set declaration", () => {
|
|
const sql = "select * from t where id = @id";
|
|
expect(expandSqlVariables(sql)).toEqual({ sql, expanded: false });
|
|
});
|
|
|
|
it("inlines a declared IN-list verbatim across the script", () => {
|
|
const sql = ["@set client_id = (606,322,634);", "select * from invoices where client_id in @client_id"].join("\n");
|
|
const { sql: result, expanded } = expandSqlVariables(sql);
|
|
expect(expanded).toBe(true);
|
|
expect(result).toBe("select * from invoices where client_id in (606,322,634)");
|
|
});
|
|
|
|
it("inlines a quoted string value verbatim", () => {
|
|
const sql = ["@set date_start = '2026-07-04 00:00:00';", "select * from t where created_at < @date_start"].join("\n");
|
|
expect(expandSqlVariables(sql).sql).toBe("select * from t where created_at < '2026-07-04 00:00:00'");
|
|
});
|
|
|
|
it("inlines a declared shell-style reference", () => {
|
|
const sql = ["@set postid = '224';", "select * from t where post_id = ${postid}"].join("\n");
|
|
expect(expandSqlVariables(sql).sql).toBe("select * from t where post_id = '224'");
|
|
});
|
|
|
|
it("recognizes a declaration after a leading line comment", () => {
|
|
const sql = ["-- saved query", "@set devid=7062;", "select * from t where device_id = ${devid}"].join("\n");
|
|
expect(expandSqlVariables(sql).sql).toBe("-- saved query\nselect * from t where device_id = 7062");
|
|
});
|
|
|
|
it("recognizes declarations after comments at a statement boundary", () => {
|
|
const sql = ["select 1;", "/* next statement */", "@set devid = 7062;", "select ${devid}"].join("\n");
|
|
expect(expandSqlVariables(sql).sql).toBe("select 1;\n/* next statement */\nselect 7062");
|
|
});
|
|
|
|
it("does not recognize a declaration after an unterminated statement", () => {
|
|
const sql = ["select 1", "-- same statement", "@set devid = 7062;", "select ${devid}"].join("\n");
|
|
expect(expandSqlVariables(sql)).toEqual({ sql, expanded: false });
|
|
});
|
|
|
|
it("uses declarations from the surrounding document for a selected statement", () => {
|
|
const selectedSql = "select * from t where post_id = ${postid}";
|
|
const declarationSql = ["@set postid = '224';", selectedSql].join("\n");
|
|
expect(expandSqlVariables(selectedSql, { declarationSql }).sql).toBe("select * from t where post_id = '224'");
|
|
});
|
|
|
|
it("leaves undeclared shell-style references for parameter prompting", () => {
|
|
const sql = ["@set postid = '224';", "select ${postid}, ${missing}"].join("\n");
|
|
expect(expandSqlVariables(sql).sql).toBe("select '224', ${missing}");
|
|
});
|
|
|
|
it("expands the same variable in multiple places", () => {
|
|
const sql = ["@set tenant = 42;", "select @tenant, count(*) from t where tenant_id = @tenant"].join("\n");
|
|
expect(expandSqlVariables(sql).sql).toBe("select 42, count(*) from t where tenant_id = 42");
|
|
});
|
|
|
|
it("supports several declarations", () => {
|
|
const sql = ["@set a = 1;", "@set b = 'x';", "select @a, @b"].join("\n");
|
|
expect(expandSqlVariables(sql).sql).toBe("select 1, 'x'");
|
|
});
|
|
|
|
it("leaves undeclared @name references untouched", () => {
|
|
const sql = ["@set a = 1;", "select @a, @b, @@version"].join("\n");
|
|
expect(expandSqlVariables(sql).sql).toBe("select 1, @b, @@version");
|
|
});
|
|
|
|
it("does not expand references inside strings, comments, or quoted identifiers", () => {
|
|
const sql = ["@set a = 1;", "select '@a' as s, \"@a\" as q, `@a` as b -- @a"].join("\n");
|
|
expect(expandSqlVariables(sql).sql).toBe("select '@a' as s, \"@a\" as q, `@a` as b -- @a");
|
|
});
|
|
|
|
it("does not treat @set inside a string as a declaration", () => {
|
|
const sql = "select '@set a = 1;' as note, @a";
|
|
expect(expandSqlVariables(sql)).toEqual({ sql, expanded: false });
|
|
});
|
|
|
|
it("keeps PostgreSQL ARRAY literals from corrupting later variable references", () => {
|
|
const sql = ["@set selected = 7;", "select ARRAY[']']::varchar[], @selected, ${missing}"].join("\n");
|
|
expect(expandSqlVariables(sql, { databaseType: "postgres" }).sql).toBe("select ARRAY[']']::varchar[], 7, ${missing}");
|
|
});
|
|
|
|
it("keeps multiline PostgreSQL ARRAY values in @set declarations", () => {
|
|
const sql = ["@set values = ARRAY[", " 'first',", " 'second'", "];", "select @values;"].join("\n");
|
|
|
|
expect(expandSqlVariables(sql, { databaseType: "postgres" }).sql).toBe("select ARRAY[\n 'first',\n 'second'\n];");
|
|
});
|
|
|
|
it.each(["sqlserver", "sqlite", "jdbc"] as const)("preserves %s bracket identifiers during variable expansion", (databaseType) => {
|
|
const sql = ["@set selected = 7;", "select [column:@ignored], @selected"].join("\n");
|
|
expect(expandSqlVariables(sql, { databaseType }).sql).toBe("select [column:@ignored], 7");
|
|
});
|
|
|
|
it("keeps a value's own quotes and parentheses intact", () => {
|
|
const sql = ["@set filter = (status = 'drafted' and deleted_at is null);", "select * from t where @filter"].join("\n");
|
|
expect(expandSqlVariables(sql).sql).toBe("select * from t where (status = 'drafted' and deleted_at is null)");
|
|
});
|
|
|
|
it("matches @set case-insensitively", () => {
|
|
const sql = ["@SET a = 7;", "select @a"].join("\n");
|
|
expect(expandSqlVariables(sql).sql).toBe("select 7");
|
|
});
|
|
|
|
it("does not treat @settings as an @set declaration", () => {
|
|
const sql = "select @settings from t";
|
|
expect(expandSqlVariables(sql)).toEqual({ sql, expanded: false });
|
|
});
|
|
});
|