53 lines
4.0 KiB
TypeScript
Vendored
53 lines
4.0 KiB
TypeScript
Vendored
import { readFileSync } from "node:fs";
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
/**
|
|
* Admin SQL (drop / empty / truncate / clone / copy) is built in Rust from the database type alone,
|
|
* which cannot describe a database whose quote character depends on the connection. Cloud Spanner is
|
|
* the case that forces the connection-reported quote to be threaded through: GoogleSQL quotes with
|
|
* backticks, its PostgreSQL dialect quotes with double quotes, and the dialect is fixed when the
|
|
* database is created. Emitting the static answer produces admin SQL that is a syntax error for
|
|
* every PostgreSQL-dialect Spanner database.
|
|
*
|
|
* These assertions pin the call sites rather than the generated SQL, because the plumbing is what
|
|
* regressed: the backend already knew how to honour a reported quote (`data_grid_sql.rs` carries the
|
|
* same field) and the builders simply were not given one.
|
|
*/
|
|
const mutationRuntimeSource = readFileSync(new URL("../../../composables/useSidebarTableMutationRuntime.ts", import.meta.url), "utf8");
|
|
const treeRuntimeSource = readFileSync(new URL("../../../components/sidebar/SidebarTreeRuntimeHost.vue", import.meta.url), "utf8");
|
|
const objectBrowserSource = readFileSync(new URL("../../../components/objects/ObjectBrowser.vue", import.meta.url), "utf8");
|
|
const adminSqlSource = readFileSync(new URL("../../database/dbAdminSql.ts", import.meta.url), "utf8");
|
|
|
|
describe("admin SQL carries the connection identifier quote", () => {
|
|
it("declares the field on every option type whose SQL qualifies an object name", () => {
|
|
for (const type of ["DropObjectSqlOptions", "TableAdminSqlOptions", "DuplicateTableStructureSqlOptions", "CopyTableDataSqlOptions"]) {
|
|
const body = adminSqlSource.match(new RegExp(`export interface ${type} \\{([\\s\\S]*?)\\n\\}`))?.[1] ?? "";
|
|
expect(body, `${type} must accept identifierQuote`).toContain("identifierQuote?: string;");
|
|
}
|
|
});
|
|
|
|
it("threads the quote through drop, empty and truncate from the sidebar", () => {
|
|
// Both factories: one reads the active node, the other an explicit node during multi-select.
|
|
expect(mutationRuntimeSource).toMatch(/tableName: activeNode\.value\.label,[\s\S]*?identifierQuote: connectionStore\.connectionIdentifierQuote\?\.\(activeNode\.value\.connectionId\)/);
|
|
expect(mutationRuntimeSource).toMatch(/tableName: node\.label,\s*identifierQuote: connectionStore\.connectionIdentifierQuote\?\.\(node\.connectionId\)/);
|
|
});
|
|
|
|
it("threads the quote through dropping a view or routine", () => {
|
|
expect(treeRuntimeSource).toMatch(/signature: node\.signature,[\s\S]*?identifierQuote: connectionStore\.connectionIdentifierQuote\?\.\(node\.connectionId\)/);
|
|
expect(objectBrowserSource).toMatch(/buildDropObjectSql\(\{[\s\S]*?identifierQuote: connectionStore\.connectionIdentifierQuote\?\.\(props\.connection\.id\)/);
|
|
});
|
|
|
|
it("threads the quote through clone and cross-database paste", () => {
|
|
expect(treeRuntimeSource).toMatch(/buildDuplicateTableStructurePlan\(\{[\s\S]*?identifierQuote: connectionStore\.connectionIdentifierQuote\?\.\(node\.connectionId\)/);
|
|
expect(treeRuntimeSource).toMatch(/buildDuplicateTableStructurePlan\(\{[\s\S]*?identifierQuote: connectionStore\.connectionIdentifierQuote\?\.\(entry\.connectionId\)/);
|
|
expect(objectBrowserSource).toMatch(/buildSharedDuplicateTableStructurePlan\(\{[\s\S]*?identifierQuote: connectionStore\.connectionIdentifierQuote\?\.\(props\.connection\.id\)/);
|
|
// The plan helper must forward it to the SQL builder rather than swallowing it.
|
|
expect(adminSqlSource).toMatch(/buildDuplicateTableStructureSql\(\{[\s\S]*?identifierQuote: options\.identifierQuote/);
|
|
});
|
|
|
|
it("threads the quote through copying table data", () => {
|
|
expect(treeRuntimeSource).toMatch(/buildCopyTableDataSql\(\{[\s\S]*?identifierQuote: connectionStore\.connectionIdentifierQuote\?\.\(entry\.connectionId\)/);
|
|
expect(objectBrowserSource).toMatch(/buildCopyTableDataSql\(\{[\s\S]*?identifierQuote: connectionStore\.connectionIdentifierQuote\?\.\(props\.connection\.id\)/);
|
|
});
|
|
});
|