UNPKG

ddl-manager

Version:

store postgres procedures and triggers in files

622 lines (561 loc) 17.8 kB
import { DatabaseFunction, IDatabaseFunctionArgument } from "../../lib/database/schema/DatabaseFunction"; import assert from "assert"; import { Comment } from "../../lib/database/schema/Comment"; describe("DatabaseFunction", () => { it("equal two similar functions", () => { const func1 = new DatabaseFunction({ schema: "public", name: "my_func", args: [], returns: {type: "bigint"}, body: "begin\nend" }); const func2 = new DatabaseFunction({ schema: "public", name: "my_func", args: [], returns: {type: "bigint"}, body: "begin\nend" }); assert.ok( func1.equal(func2), "func1 == func2" ); assert.ok( func2.equal(func1), "func2 == func1" ); }); it("equal with different body", () => { const func1 = new DatabaseFunction({ schema: "public", name: "my_func", args: [], returns: {type: "bigint"}, body: "body 1" }); const func2 = new DatabaseFunction({ schema: "public", name: "my_func", args: [], returns: {type: "bigint"}, body: "body 2" }); assert.ok( !func1.equal(func2), "func1 != func2" ); assert.ok( !func2.equal(func1), "func2 != func1" ); }); it("equal with different parallel", () => { const func1 = new DatabaseFunction({ schema: "public", name: "my_func", args: [], returns: {type: "bigint"}, body: "body", parallel: ["safe"] }); const func2 = new DatabaseFunction({ schema: "public", name: "my_func", args: [], returns: {type: "bigint"}, body: "body", parallel: ["safe"] }); assert.ok( func1.equal(func2), "func1 == func2" ); assert.ok( func2.equal(func1), "func2 == func1" ); }); it("equal with different args", () => { const func1 = new DatabaseFunction({ schema: "public", name: "my_func", args: [], returns: {type: "bigint"}, body: "body" }); const func2 = new DatabaseFunction({ schema: "public", name: "my_func", args: [{name: "hello", type: "bigint"}], returns: {type: "bigint"}, body: "body" }); assert.ok( !func1.equal(func2), "func1 != func2" ); assert.ok( !func2.equal(func1), "func2 != func1" ); }); it("equal comment: undefined == null", () => { const func1 = new DatabaseFunction({ schema: "public", name: "my_func", args: [], returns: {type: "bigint"}, body: "body", comment: null as any }); const func2 = new DatabaseFunction({ schema: "public", name: "my_func", args: [], returns: {type: "bigint"}, body: "body", comment: undefined as any }); assert.ok( func1.equal(func2), "func1 == func2" ); assert.ok( func2.equal(func1), "func2 == func1" ); }); it("equal with different returns", () => { const func1 = new DatabaseFunction({ schema: "public", name: "my_func", args: [], returns: {type: "integer"}, body: "body" }); const func2 = new DatabaseFunction({ schema: "public", name: "my_func", args: [], returns: {type: "bigint"}, body: "body" }); assert.ok( !func1.equal(func2), "func1 != func2" ); assert.ok( !func2.equal(func1), "func2 != func1" ); }); it("equal with different returns type", () => { const func1 = new DatabaseFunction({ schema: "public", name: "my_func", args: [], returns: {type: "integer"}, body: "body" }); const func2 = new DatabaseFunction({ schema: "public", name: "my_func", args: [], returns: {type: "bigint"}, body: "body" }); assert.ok( !func1.equal(func2), "func1 != func2" ); assert.ok( !func2.equal(func1), "func2 != func1" ); }); it("equal args with similar default", () => { interface IArgCompare { argA: IDatabaseFunctionArgument; argB: IDatabaseFunctionArgument; equal: boolean; } const argsCompares: IArgCompare[] = [ { argA: { name: "_start_date", type: "timestamp without time zone", default: " null" }, argB: { name: "_start_date", type: "timestamp without time zone", default: "null::timestamp without time zone" }, equal: true }, { argA: { name: "_start_date", type: "timestamp without time zone", default: " null" }, argB: { name: "_start_date", type: "timestamp without time zone", default: "null " }, equal: true }, { argA: { name: "_start_date", type: "timestamp without time zone", default: "null::timestamp without time zone" }, argB: { name: "_start_date", type: "timestamp WITHOUT time zone", default: "null::timestamp without time zone " }, equal: true }, { argA: { name: "_start_date", type: "timestamp ", default: "null::timestamp " }, argB: { name: "_start_date", type: "timestamp without time zone", default: "null::timestamp without time zone " }, equal: true }, { argA: { name: "_start_date", type: "numeric", default: "null::NUMERIc(14, 2)" }, argB: { name: "_start_date", type: "numeric", default: "null::numeric" }, equal: true }, { argA: { name: "name", type: "text", default: "''::text" }, argB: { name: "name", type: "text", default: " '' " }, equal: true }, { argA: { name: "name", type: "jsonb", default: "{}::jsonb" }, argB: { name: "name", type: "jsonb", default: " {} " }, equal: true }, { argA: { name: "name", type: "jsonb", default: "'{}'::jsonb" }, argB: { name: "name", type: "jsonb", default: " '{}' " }, equal: true }, { argA: { name: "name", type: "jsonb", default: "{}::jsonb" }, argB: { name: "name", type: "jsonb", default: " '{}' " }, equal: true }, { argA: { name: "name", type: "jsonb", default: "'{}'" }, argB: { name: "name", type: "jsonb", default: " {} " }, equal: true }, { argA: { name: "name", type: "boolean", default: "false::boolean" }, argB: { name: "name", type: "boolean", default: " false " }, equal: true }, { argA: { name: "name", type: "boolean", default: "false::boolean" }, argB: { name: "name", type: "boolean", default: " false " }, equal: true }, { argA: { name: "name", type: "boolean", default: "false ::boolean" }, argB: { name: "name", type: "boolean", default: " false " }, equal: true }, { argA: { name: "name", type: "smallint", default: "0::smallint" }, argB: { name: "name", type: "smallint", default: " 0 " }, equal: true }, { argA: { name: "name", type: "text", default: "'both'::text" }, argB: { name: "name", type: "text", default: " 'both' " }, equal: true }, { argA: { name: "name", type: "text[]", default: "'both'::text[]" }, argB: { name: "name", type: "text[]", default: " 'both' " }, equal: true } ]; for (const {argA, argB, equal} of argsCompares) { const func1 = new DatabaseFunction({ schema: "public", name: "my_func", args: [argA], returns: {type: "bigint"}, body: "body" }); const func2 = new DatabaseFunction({ schema: "public", name: "my_func", args: [argB], returns: {type: "bigint"}, body: "body" }); assert.strictEqual( func1.equal(func2), equal, `equal("${argA.default}", "${argB.default}") => ${equal}` ); } }); // soo, maybe need another way? it("equal cost: 100 == null", () => { const func1 = new DatabaseFunction({ schema: "public", name: "my_func", args: [], returns: {type: "bigint"}, body: "body", cost: 100 as any }); const func2 = new DatabaseFunction({ schema: "public", name: "my_func", args: [], returns: {type: "bigint"}, body: "body", cost: null as any }); assert.ok( func1.equal(func2), "func1 == func2" ); assert.ok( func2.equal(func1), "func2 == func1" ); }); it("returns company == returns public.company", () => { const func1 = new DatabaseFunction({ schema: "public", name: "my_func", args: [], returns: {setof: true, type: "company"}, body: "body" }); const func2 = new DatabaseFunction({ schema: "public", name: "my_func", args: [], returns: {setof: true, type: "public.company"}, body: "body" }); assert.ok( func1.equal(func2), "func1 == func2" ); assert.ok( func2.equal(func1), "func2 == func1" ); }); it("equal arg type: numeric(14, 2) == numeric", () => { const func1 = new DatabaseFunction({ schema: "public", name: "my_func", args: [{ name: "test", type: "numeric(14,2)" }], returns: {type: "numeric(14,2)"}, body: "body" }); const func2 = new DatabaseFunction({ schema: "public", name: "my_func", args: [{ name: "test", type: "numeric" }], returns: {type: "numeric"}, body: "body" }); assert.ok( func1.equal(func2), "func1 == func2" ); assert.ok( func2.equal(func1), "func2 == func1" ); }); it("equal two functions similar comments", () => { const func1 = new DatabaseFunction({ schema: "public", name: "my_func", args: [], returns: {type: "bigint"}, body: "begin\nend", comment: Comment.fromFs({ objectType: "function", }) }); const func2 = new DatabaseFunction({ schema: "public", name: "my_func", args: [], returns: {type: "bigint"}, body: "begin\nend", comment: Comment.fromTotalString("function", "hello\nddl-manager-sync") }); assert.ok( func1.equal(func2), "func1 == func2" ); assert.ok( func2.equal(func1), "func2 == func1" ); }); it("equal arg type: \"order\" == public.order", () => { const func1 = new DatabaseFunction({ schema: "public", name: "my_func", args: [{ name: "test", type: "public.order" }], returns: {type: "public.order"}, body: "body" }); const func2 = new DatabaseFunction({ schema: "public", name: "my_func", args: [{ name: "test", type: "\"order\"" }], returns: {type: "\"order\""}, body: "body" }); assert.ok( func1.equal(func2), "func1 == func2" ); assert.ok( func2.equal(func1), "func2 == func1" ); }); describe("findAssignColumns", () => { it("empty function", () => { shouldBeAssignedColumns( "begin\nend", [] ); }); it("assign one column", () => { shouldBeAssignedColumns(` begin new.my_column = 123; end`, ["my_column"]); }); it("ignore case", () => { shouldBeAssignedColumns(` begin new.MY_COLUMN = 123; end`, ["my_column"]); }); it("assign two columns", () => { shouldBeAssignedColumns(` begin new.column_a = 123; new.column_b = 123; end`, ["column_a", "column_b"]); }); it("dont repeat columns", () => { shouldBeAssignedColumns(` begin new.column_x = 123; new.column_x = 123; end`, ["column_x"]); }); it("ignore if condition", () => { shouldBeAssignedColumns(` begin if new.column_x = 1 or new.column_y = 1 then new.column_z = 123; end if; end`, ["column_z"]); }); it("assign inside loop", () => { shouldBeAssignedColumns(` begin for ... loop new.column_x = 19; end loop; end`, ["column_x"]); }); it("ignore inline comments before assign", () => { shouldBeAssignedColumns(` begin -- comment new.column_x = 19; end`, ["column_x"]); }); it("ignore multiline comments before assign", () => { shouldBeAssignedColumns(` begin /* comment */ new.column_x = 19; end`, ["column_x"]); }); function shouldBeAssignedColumns( body: string, columns: string[] ) { const func = new DatabaseFunction({ schema: "public", name: "my_func", args: [], returns: {type: "bigint"}, body }); assert.deepStrictEqual( func.findAssignColumns(), columns ); } }); })