UNPKG

@jakub.knejzlik/ts-query

Version:

TypeScript implementation of SQL builder

200 lines (172 loc) 7.72 kB
import { Cond } from "./Condition"; import { CreateTableAsSelect } from "./CreateTableAsSelect"; import { Q } from "./Query"; import { MySQLFlavor } from "./flavors/mysql"; import { MetadataOperationType } from "./interfaces"; describe("CreateTableAsSelect", () => { const initialSelectQuery = Q.select() .from("users", "u") .where(Cond.equal("u.id", 1)); const tableName = "new_users_table"; it("should clone itself correctly", () => { const ctas = Q.createTableAs(tableName, initialSelectQuery); const clone = ctas.clone(); expect(clone).not.toBe(ctas); expect(clone.toSQL(new MySQLFlavor())).toBe(ctas.toSQL(new MySQLFlavor())); }); it("should generate the correct SQL", () => { const ctas = Q.createTableAs(tableName, initialSelectQuery); const expectedSQL = `CREATE TABLE \`${tableName}\` AS SELECT * FROM \`users\` AS \`u\` WHERE \`u\`.\`id\` = 1`; expect(ctas.toSQL(new MySQLFlavor())).toBe(expectedSQL); }); it("should serialize and deserialize correctly", () => { const ctas = Q.createTableAs(tableName, initialSelectQuery); const serialized = ctas.serialize(); const deserialized = Q.deserialize(serialized); expect(deserialized).toEqual(ctas); expect(deserialized.toSQL(new MySQLFlavor())).toBe( ctas.toSQL(new MySQLFlavor()) ); }); it("should serialize and deserialize correctly with compression", () => { const ctas = Q.createTableAs(tableName, initialSelectQuery); const serializedCompressed = ctas.serialize({ compress: true }); const deserializedCompressed = Q.deserialize(serializedCompressed); expect(deserializedCompressed).toEqual(ctas); expect(deserializedCompressed.toSQL(new MySQLFlavor())).toBe( ctas.toSQL(new MySQLFlavor()) ); }); it("should fetch table names correctly", () => { const ctas = Q.createTableAs(tableName, initialSelectQuery); expect(ctas.getTableNames()).toEqual([tableName, "users"]); }); it("should return correct operation type", () => { const ctas = Q.createTableAs(tableName, initialSelectQuery); expect(ctas.getOperationType()).toEqual( MetadataOperationType.CREATE_TABLE_AS ); }); it("should return correct values from accessorts", () => { const cvas = Q.createTableAs(tableName, initialSelectQuery); expect(cvas.getTableName()).toEqual(tableName); expect(cvas.getSelect().toSQL()).toEqual(initialSelectQuery.toSQL()); }); describe("composition - CTAS as table reference", () => { it("should use CTAS as table source in from()", () => { const ctas = Q.createTableAs( "users_v1", Q.select().from(Q.values([{ id: 1, name: "Alice" }])) ); const query = Q.select().from(ctas); expect(query.toSQL(new MySQLFlavor())).toBe( "SELECT * FROM `users_v1`" ); }); it("should use CTAS as table source in another CTAS", () => { const ctas1 = Q.createTableAs( "users_v1", Q.select().from(Q.values([{ id: 1, name: "Alice" }])) ); const ctas2 = Q.createTableAs("users_v2", Q.select().from(ctas1)); expect(ctas2.toSQL(new MySQLFlavor())).toBe( "CREATE TABLE `users_v2` AS SELECT * FROM `users_v1`" ); }); it("should support alias when using CTAS as table source", () => { const ctas = Q.createTableAs( "users_v1", Q.select().from(Q.values([{ id: 1, name: "Alice" }])) ); const query = Q.select().from(ctas, "u"); expect(query.toSQL(new MySQLFlavor())).toBe( "SELECT * FROM `users_v1` AS `u`" ); }); it("should return correct table names when using CTAS as table source", () => { const ctas = Q.createTableAs("users_v1", Q.select().from("raw_users")); const query = Q.select().from(ctas); expect(query.getTableNames()).toEqual(["users_v1"]); }); it("should use CVAS as table source in from()", () => { const cvas = Q.createViewAs("users_view", Q.select().from("users")); const query = Q.select().from(cvas); expect(query.toSQL(new MySQLFlavor())).toBe( "SELECT * FROM `users_view`" ); }); it("should serialize and deserialize query referencing CTAS", () => { const ctas = Q.createTableAs("users_v1", Q.select().from("raw_users")); const query = Q.select().from(ctas).where(Cond.equal("id", 1)); const serialized = query.serialize(); const deserialized = Q.deserialize(serialized); expect(deserialized.toSQL(new MySQLFlavor())).toBe( query.toSQL(new MySQLFlavor()) ); }); }); describe("OR REPLACE", () => { it("should generate CREATE OR REPLACE TABLE SQL", () => { const ctas = Q.createOrReplaceTableAs(tableName, initialSelectQuery); const expectedSQL = `CREATE OR REPLACE TABLE \`${tableName}\` AS SELECT * FROM \`users\` AS \`u\` WHERE \`u\`.\`id\` = 1`; expect(ctas.toSQL(new MySQLFlavor())).toBe(expectedSQL); }); it("should clone and preserve orReplace flag", () => { const ctas = Q.createOrReplaceTableAs(tableName, initialSelectQuery); const clone = ctas.clone(); expect(clone.toSQL(new MySQLFlavor())).toBe(ctas.toSQL(new MySQLFlavor())); }); it("should serialize and deserialize correctly", () => { const ctas = Q.createOrReplaceTableAs(tableName, initialSelectQuery); const serialized = ctas.serialize(); const deserialized = Q.deserialize(serialized); expect(deserialized.toSQL(new MySQLFlavor())).toBe( ctas.toSQL(new MySQLFlavor()) ); }); }); describe("IF NOT EXISTS", () => { it("should generate CREATE TABLE IF NOT EXISTS SQL", () => { const ctas = Q.createTableIfNotExistsAs(tableName, initialSelectQuery); const expectedSQL = `CREATE TABLE IF NOT EXISTS \`${tableName}\` AS SELECT * FROM \`users\` AS \`u\` WHERE \`u\`.\`id\` = 1`; expect(ctas.toSQL(new MySQLFlavor())).toBe(expectedSQL); }); it("should clone and preserve ifNotExists flag", () => { const ctas = Q.createTableIfNotExistsAs(tableName, initialSelectQuery); const clone = ctas.clone(); expect(clone.getIfNotExists()).toBe(true); expect(clone.toSQL(new MySQLFlavor())).toBe(ctas.toSQL(new MySQLFlavor())); }); it("should serialize and deserialize correctly", () => { const ctas = Q.createTableIfNotExistsAs(tableName, initialSelectQuery); const serialized = ctas.serialize(); const deserialized = Q.deserialize(serialized); expect(deserialized).toEqual(ctas); expect(deserialized.toSQL(new MySQLFlavor())).toBe( ctas.toSQL(new MySQLFlavor()) ); }); it("should include ifNotExists field in JSON serialization", () => { const ctas = Q.createTableIfNotExistsAs(tableName, initialSelectQuery); expect(ctas.toJSON().ifNotExists).toBe(true); const plain = Q.createTableAs(tableName, initialSelectQuery); expect(plain.toJSON().ifNotExists).toBe(false); }); it("should deserialize legacy JSON without ifNotExists field (backwards compatible)", () => { const ctas = Q.createTableAs(tableName, initialSelectQuery); const json = ctas.toJSON() as any; delete json.ifNotExists; const deserialized = Q.deserialize(JSON.stringify(json)); expect((deserialized as any).getIfNotExists()).toBe(false); expect(deserialized.toSQL(new MySQLFlavor())).toBe( ctas.toSQL(new MySQLFlavor()) ); }); it("should throw when both orReplace and ifNotExists are set", () => { expect( () => new CreateTableAsSelect(tableName, initialSelectQuery, true, true) ).toThrow(/mutually exclusive/); }); }); });