// @ts-check const views = { type: 'views', create1: 'CREATE VIEW ~obj1 AS SELECT ~id FROM ~t1', create2: 'CREATE VIEW ~obj2 AS SELECT ~id FROM ~t2', drop1: 'DROP VIEW ~obj1', drop2: 'DROP VIEW ~obj2', }; const matviews = { type: 'matviews', create1: 'CREATE MATERIALIZED VIEW obj1 AS SELECT id FROM t1', create2: 'CREATE MATERIALIZED VIEW obj2 AS SELECT id FROM t2', drop1: 'DROP MATERIALIZED VIEW obj1', drop2: 'DROP MATERIALIZED VIEW obj2', }; /** @type {import('dbgate-types').TestEngineInfo} */ const mysqlEngine = { label: 'MySQL', connection: { engine: 'mysql@dbgate-plugin-mysql', password: 'Pwd2020Db', user: 'root', server: 'localhost', port: 15001, }, objects: [ views, { type: 'schedulerEvents', create1: 'CREATE EVENT obj1 ON SCHEDULE EVERY 1 HOUR DO BEGIN END', create2: 'CREATE EVENT obj2 ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 DAY DO BEGIN END', drop1: 'DROP EVENT obj1', drop2: 'DROP EVENT obj2', }, { type: 'procedures', create1: 'CREATE PROCEDURE obj1() BEGIN SELECT * FROM t1; END', create2: 'CREATE PROCEDURE obj2() BEGIN SELECT * FROM t2; END', drop1: 'DROP PROCEDURE obj1', drop2: 'DROP PROCEDURE obj2', }, ], supportRenameSqlObject: false, dbSnapshotBySeconds: true, dumpFile: 'data/chinook-mysql.sql', dumpChecks: [ { sql: 'select count(*) as res from genre', res: '25', }, ], parametersOtherSql: ['CREATE PROCEDURE obj2(a int, b int) BEGIN SELECT * FROM t1; END'], parameters: [ { testName: 'simple', create: 'CREATE PROCEDURE obj1(a int) BEGIN SELECT * FROM t1; END', drop: 'DROP PROCEDURE obj1', objectTypeField: 'procedures', list: [ { parameterName: 'a', parameterMode: 'IN', dataType: 'int', }, ], }, { testName: 'paramTypes', create: 'CREATE PROCEDURE obj1(a int, b varchar(50), c numeric(10,2)) BEGIN SELECT * FROM t1; END', drop: 'DROP PROCEDURE obj1', objectTypeField: 'procedures', list: [ { parameterName: 'a', parameterMode: 'IN', dataType: 'int', }, { parameterName: 'b', parameterMode: 'IN', dataType: 'varchar(50)', }, { parameterName: 'c', parameterMode: 'IN', dataType: 'decimal(10,2)', }, ], }, { testName: 'paramModes', create: 'CREATE PROCEDURE obj1(IN a int, OUT b int, INOUT c int) BEGIN SELECT * FROM t1; END', drop: 'DROP PROCEDURE obj1', objectTypeField: 'procedures', list: [ { parameterName: 'a', parameterMode: 'IN', dataType: 'int', }, { parameterName: 'b', parameterMode: 'OUT', dataType: 'int', }, { parameterName: 'c', parameterMode: 'INOUT', dataType: 'int', }, ], }, ], triggers: [ { testName: 'triggers insert after', create: 'CREATE TRIGGER obj1 AFTER INSERT ON t1 FOR EACH ROW BEGIN END', drop: 'DROP TRIGGER obj1;', objectTypeField: 'triggers', expected: { pureName: 'obj1', eventType: 'INSERT', triggerTiming: 'AFTER', }, }, { testName: 'triggers insert before', create: 'CREATE TRIGGER obj1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN END', drop: 'DROP TRIGGER obj1;', objectTypeField: 'triggers', expected: { pureName: 'obj1', eventType: 'INSERT', triggerTiming: 'BEFORE', }, }, ], schedulerEvents: [ { create: 'CREATE EVENT obj1 ON SCHEDULE EVERY 1 HOUR DO BEGIN END', drop: 'DROP EVENT obj1', objectTypeField: 'schedulerEvents', expected: { pureName: 'obj1', status: 'ENABLED', eventType: 'RECURRING', intervalValue: '1', intervalField: 'HOUR', }, }, { create: 'CREATE EVENT obj1 ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 DAY DO BEGIN END', drop: 'DROP EVENT obj1', objectTypeField: 'schedulerEvents', expected: { pureName: 'obj1', status: 'ENABLED', eventType: 'ONE TIME', }, }, ], }; /** @type {import('dbgate-types').TestEngineInfo} */ const mariaDbEngine = { label: 'MariaDB', connection: { engine: 'mariadb@dbgate-plugin-mysql', password: 'Pwd2020Db', user: 'root', server: 'localhost', port: 15004, }, objects: [views], dbSnapshotBySeconds: true, dumpFile: 'data/chinook-mysql.sql', dumpChecks: [ { sql: 'select count(*) as res from genre', res: '25', }, ], }; /** @type {import('dbgate-types').TestEngineInfo} */ const postgreSqlEngine = { label: 'PostgreSQL', connection: { engine: 'postgres@dbgate-plugin-postgres', password: 'Pwd2020Db', user: 'postgres', server: 'localhost', port: 15000, }, objects: [ views, matviews, { type: 'procedures', create1: 'CREATE PROCEDURE obj1() LANGUAGE SQL AS $$ select * from t1 $$', create2: 'CREATE PROCEDURE obj2() LANGUAGE SQL AS $$ select * from t2 $$', drop1: 'DROP PROCEDURE obj1', drop2: 'DROP PROCEDURE obj2', }, { type: 'functions', create1: 'CREATE FUNCTION obj1() returns int LANGUAGE plpgsql AS $$ declare res integer; begin select count(*) into res from t1; return res; end; $$', create2: 'CREATE FUNCTION obj2() returns int LANGUAGE plpgsql AS $$ declare res integer; begin select count(*) into res from t2; return res; end; $$', drop1: 'DROP FUNCTION obj1', drop2: 'DROP FUNCTION obj2', }, ], supportSchemas: true, supportRenameSqlObject: true, defaultSchemaName: 'public', dumpFile: 'data/chinook-postgre.sql', dumpChecks: [ { sql: 'select count(*) as res from "public"."Genre"', res: '25', }, ], parametersOtherSql: ['CREATE PROCEDURE obj2(a integer, b integer) LANGUAGE SQL AS $$ select * from t1 $$'], parameters: [ { testName: 'simple', create: 'CREATE PROCEDURE obj1(a integer) LANGUAGE SQL AS $$ select * from t1 $$', drop: 'DROP PROCEDURE obj1', objectTypeField: 'procedures', list: [ { parameterName: 'a', parameterMode: 'IN', dataType: 'integer', }, ], }, { testName: 'dataTypes', create: 'CREATE PROCEDURE obj1(a integer, b varchar(20), c numeric(18,2)) LANGUAGE SQL AS $$ select * from t1 $$', drop: 'DROP PROCEDURE obj1', objectTypeField: 'procedures', list: [ { parameterName: 'a', parameterMode: 'IN', dataType: 'integer', }, { parameterName: 'b', parameterMode: 'IN', dataType: 'varchar', }, { parameterName: 'c', parameterMode: 'IN', dataType: 'numeric', }, ], }, { testName: 'paramModes', create: 'CREATE PROCEDURE obj1(IN a integer, INOUT b integer) LANGUAGE SQL AS $$ select * from t1 $$', drop: 'DROP PROCEDURE obj1', objectTypeField: 'procedures', list: [ { parameterName: 'a', parameterMode: 'IN', dataType: 'integer', }, { parameterName: 'b', parameterMode: 'INOUT', dataType: 'integer', }, ], }, { testName: 'paramModesFunction', objectTypeField: 'functions', create: ` create or replace function obj1( out min_len int, out max_len int) language plpgsql as $$ begin select min(id), max(id) into min_len, max_len from t1; end;$$`, drop: 'DROP FUNCTION obj1', list: [ { parameterName: 'min_len', parameterMode: 'OUT', dataType: 'integer', }, { parameterName: 'max_len', parameterMode: 'OUT', dataType: 'integer', }, ], }, ], triggers: [ { testName: 'triggers after each row', create: `CREATE TRIGGER obj1 AFTER INSERT ON t1 FOR EACH ROW EXECUTE FUNCTION test_function(); `, drop: 'DROP TRIGGER obj1 ON t1;', triggerOtherCreateSql: `CREATE OR REPLACE FUNCTION test_function() RETURNS TRIGGER AS $$ BEGIN END; $$ LANGUAGE plpgsql;`, triggerOtherDropSql: 'DROP FUNCTION test_function', objectTypeField: 'triggers', expected: { pureName: 'obj1', eventType: 'INSERT', triggerTiming: 'AFTER', }, }, { testName: 'triggers before each row', create: `CREATE TRIGGER obj1 BEFORE INSERT ON t1 FOR EACH ROW EXECUTE FUNCTION test_function(); `, drop: 'DROP TRIGGER obj1 ON t1;', triggerOtherCreateSql: `CREATE OR REPLACE FUNCTION test_function() RETURNS TRIGGER AS $$ BEGIN END; $$ LANGUAGE plpgsql;`, triggerOtherDropSql: 'DROP FUNCTION test_function', objectTypeField: 'triggers', expected: { pureName: 'obj1', eventType: 'INSERT', triggerTiming: 'BEFORE', }, }, ], }; /** @type {import('dbgate-types').TestEngineInfo} */ const sqlServerEngine = { label: 'SQL Server', connection: { engine: 'mssql@dbgate-plugin-mssql', password: 'Pwd2020Db', user: 'sa', server: 'localhost', port: 15002, }, objects: [ views, { type: 'procedures', create1: 'CREATE PROCEDURE obj1 AS SELECT id FROM t1', create2: 'CREATE PROCEDURE obj2 AS SELECT id FROM t2', drop1: 'DROP PROCEDURE obj1', drop2: 'DROP PROCEDURE obj2', }, { type: 'triggers', create1: 'CREATE TRIGGER obj1 ON t1 AFTER INSERT AS BEGIN SELECT * FROM t1 END', create2: 'CREATE TRIGGER obj2 ON t2 AFTER INSERT AS BEGIN SELECT * FROM t2 END', drop1: 'DROP TRIGGER obj1', drop2: 'DROP TRIGGER obj2', }, ], parametersOtherSql: ['CREATE PROCEDURE obj2 (@p1 int, @p2 int) AS SELECT id from t1'], parameters: [ { testName: 'simple', create: 'CREATE PROCEDURE obj1 (@param1 int) AS SELECT id from t1', drop: 'DROP PROCEDURE obj1', objectTypeField: 'procedures', list: [ { parameterName: '@param1', parameterMode: 'IN', dataType: 'int', }, ], }, { testName: 'dataTypes', create: 'CREATE PROCEDURE obj1 (@p1 bit, @p2 nvarchar(20), @p3 decimal(18,2), @p4 float) AS SELECT id from t1', drop: 'DROP PROCEDURE obj1', objectTypeField: 'procedures', list: [ { parameterName: '@p1', parameterMode: 'IN', dataType: 'bit', }, { parameterName: '@p2', parameterMode: 'IN', dataType: 'nvarchar(20)', }, { parameterName: '@p3', parameterMode: 'IN', dataType: 'decimal(18,2)', }, { parameterName: '@p4', parameterMode: 'IN', dataType: 'float', }, ], }, { testName: 'outputParam', create: 'CREATE PROCEDURE obj1 (@p1 int OUTPUT) AS SELECT id from t1', drop: 'DROP PROCEDURE obj1', objectTypeField: 'procedures', list: [ { parameterName: '@p1', parameterMode: 'OUT', dataType: 'int', }, ], }, ], supportSchemas: true, supportRenameSqlObject: true, defaultSchemaName: 'dbo', // skipSeparateSchemas: true, triggers: [ { testName: 'triggers before each row', create: `CREATE TRIGGER obj1 ON t1 AFTER INSERT AS BEGIN SELECT * FROM t1 END`, drop: 'DROP TRIGGER obj1', objectTypeField: 'triggers', expected: { pureName: 'obj1', eventType: 'INSERT', triggerTiming: 'AFTER', }, }, { testName: 'triggers before each row', create: `CREATE TRIGGER obj1 ON t1 AFTER UPDATE AS BEGIN SELECT * FROM t1 END`, drop: 'DROP TRIGGER obj1', objectTypeField: 'triggers', expected: { pureName: 'obj1', eventType: 'UPDATE', triggerTiming: 'AFTER', }, }, ], }; /** @type {import('dbgate-types').TestEngineInfo} */ const sqliteEngine = { label: 'SQLite', generateDbFile: true, connection: { engine: 'sqlite@dbgate-plugin-sqlite', }, objects: [views], skipOnCI: false, skipChangeColumn: true, triggers: [ { testName: 'triggers after each row insert', create: `CREATE TRIGGER obj1 AFTER INSERT ON t1 FOR EACH ROW BEGIN SELECT * FROM t1; END;`, drop: `DROP TRIGGER obj1;`, objectTypeField: 'triggers', expected: { pureName: 'obj1', eventType: 'INSERT', triggerTiming: 'AFTER', }, }, { testName: 'triggers before each row update', create: `CREATE TRIGGER obj1 BEFORE UPDATE ON t1 FOR EACH ROW BEGIN SELECT * FROM t1; END;`, drop: `DROP TRIGGER obj1;`, objectTypeField: 'triggers', expected: { pureName: 'obj1', eventType: 'UPDATE', triggerTiming: 'BEFORE', }, }, ], }; const libsqlFileEngine = { ...sqliteEngine, label: 'LibSQL FILE', connection: { engine: 'libsql@dbgate-plugin-sqlite', }, }; const libsqlWsEngine = { ...sqliteEngine, label: 'LibSQL WS', connection: { engine: 'libsql@dbgate-plugin-sqlite', databaseUrl: 'ws://localhost:8080', }, }; /** @type {import('dbgate-types').TestEngineInfo} */ const cockroachDbEngine = { label: 'CockroachDB', connection: { engine: 'cockroach@dbgate-plugin-postgres', user: 'root', server: 'localhost', port: 15003, }, objects: [views, matviews], }; /** @type {import('dbgate-types').TestEngineInfo} */ const clickhouseEngine = { label: 'ClickHouse', connection: { engine: 'clickhouse@dbgate-plugin-clickhouse', databaseUrl: 'http://localhost:15005', password: 'Pwd2020Db', }, objects: [views], skipDataModifications: true, skipReferences: true, skipIndexes: true, skipNullability: true, skipUnique: true, skipAutoIncrement: true, skipPkColumnTesting: true, skipDataReplicator: true, skipStringLength: true, alterTableAddColumnSyntax: true, dbSnapshotBySeconds: true, skipChangeColumn: true, skipImportModel: true, }; /** @type {import('dbgate-types').TestEngineInfo} */ const oracleEngine = { label: 'Oracle', connection: { engine: 'oracle@dbgate-plugin-oracle', password: 'Pwd2020Db', user: 'system', server: 'localhost', port: 15006, serviceName: 'xe', }, skipOnCI: false, dbSnapshotBySeconds: true, setNullDefaultInsteadOfDrop: true, skipIncrementalAnalysis: true, objects: [ views, { type: 'procedures', create1: 'CREATE PROCEDURE ~obj1 AS BEGIN SELECT ~id FROM ~t1 END', create2: 'CREATE PROCEDURE ~obj2 AS BEGIN SELECT ~id FROM ~t2 END', drop1: 'DROP PROCEDURE ~obj1', drop2: 'DROP PROCEDURE ~obj2', }, { type: 'functions', create1: 'CREATE FUNCTION ~obj1 RETURN NUMBER IS v_count NUMBER; \n BEGIN SELECT COUNT(*) INTO v_count FROM ~t1;\n RETURN v_count;\n END ~obj1', create2: 'CREATE FUNCTION ~obj2 RETURN NUMBER IS v_count NUMBER; \n BEGIN SELECT COUNT(*) INTO v_count FROM ~t2;\n RETURN v_count;\n END ~obj2', drop1: 'DROP FUNCTION ~obj1', drop2: 'DROP FUNCTION ~obj2', }, ], triggers: [ { testName: 'triggers after each row', create: 'CREATE OR REPLACE TRIGGER obj1 AFTER INSERT ON "t1" FOR EACH ROW BEGIN END obj1;', drop: 'DROP TRIGGER obj1;', objectTypeField: 'triggers', expected: { pureName: 'OBJ1', eventType: 'INSERT', triggerTiming: 'AFTER EACH ROW', }, }, { testName: 'triggers before each row', create: 'CREATE OR REPLACE TRIGGER obj1 BEFORE INSERT ON "t1" FOR EACH ROW BEGIN END obj1;', drop: 'DROP TRIGGER obj1;', objectTypeField: 'triggers', expected: { pureName: 'OBJ1', eventType: 'INSERT', triggerTiming: 'BEFORE EACH ROW', }, }, ], }; /** @type {import('dbgate-types').TestEngineInfo} */ const cassandraEngine = { label: 'Cassandra', connection: { server: 'localhost:15942', engine: 'cassandra@dbgate-plugin-cassandra', }, removeNotNull: true, alterTableAddColumnSyntax: false, skipOnCI: false, skipReferences: true, // dbSnapshotBySeconds: true, // setNullDefaultInsteadOfDrop: true, skipIncrementalAnalysis: true, skipNonPkRename: true, skipPkDrop: true, skipDefaultValue: true, skipNullability: true, skipUnique: true, skipIndexes: true, skipOrderBy: true, skipAutoIncrement: true, skipDataModifications: true, skipDataReplicator: true, skipDeploy: true, skipImportModel: true, forceSortResults: true, forceSortStructureColumns: true, useTextTypeForStrings: true, objects: [], }; /** @type {import('dbgate-types').TestEngineInfo} */ const duckdbEngine = { label: 'DuckDB', generateDbFile: true, defaultSchemaName: 'main', connection: { engine: 'duckdb@dbgate-plugin-duckdb', }, objects: [views], skipOnCI: false, skipChangeColumn: true, // skipIndexes: true, skipStringLength: true, skipTriggers: true, skipDataReplicator: true, skipAutoIncrement: true, skipDropColumn: true, skipRenameColumn: true, skipChangeNullability: true, skipDeploy: true, supportRenameSqlObject: true, skipIncrementalAnalysis: true, skipDefaultValue: true, skipDropReferences: true, }; /** @type {import('dbgate-types').TestEngineInfo} */ const firebirdEngine = { label: 'Firebird', generateDbFile: true, databaseFileLocationOnServer: '/var/lib/firebird/data/', defaultSchemaName: 'main', connection: { engine: 'firebird@dbgate-plugin-firebird', server: 'localhost', port: 3050, // databaseUrl: '/var/lib/firebird/data/mydatabase.fdb', // databaseFile: '/var/lib/firebird/data/mydatabase.fdb', user: 'SYSDBA', password: 'masterkey', }, objects: [], triggers: [ { testName: 'triggers after each row', create: `CREATE OR ALTER TRIGGER ~obj1 AFTER INSERT ON ~t1 AS BEGIN END;`, drop: 'DROP TRIGGER ~obj1;', objectTypeField: 'triggers', expected: { pureName: 'obj1', tableName: 't1', eventType: 'INSERT', triggerTiming: 'AFTER', }, }, ], skipOnCI: false, runDeployInTransaction: true, skipDataModifications: true, skipChangeColumn: true, // skipIndexes: true, // skipStringLength: true, // skipTriggers: true, skipDataReplicator: true, skipAutoIncrement: true, // skipDropColumn: true, skipRenameColumn: true, // skipChangeNullability: true, // skipDeploy: true, // supportRenameSqlObject: true, skipIncrementalAnalysis: true, skipRenameTable: true, // skipDefaultValue: true, skipDropReferences: true, }; const enginesOnCi = [ // all engines, which would be run on GitHub actions mysqlEngine, // mariaDbEngine, postgreSqlEngine, sqlServerEngine, sqliteEngine, libsqlFileEngine, libsqlWsEngine, // cockroachDbEngine, clickhouseEngine, oracleEngine, cassandraEngine, duckdbEngine, firebirdEngine, ]; const enginesOnLocal = [ // all engines, which would be run on local test // cassandraEngine, // mysqlEngine, // mariaDbEngine, // postgreSqlEngine, // sqlServerEngine, // sqliteEngine, // cockroachDbEngine, // clickhouseEngine, // libsqlFileEngine, // libsqlWsEngine, // oracleEngine, // duckdbEngine, firebirdEngine, ]; /** @type {import('dbgate-types').TestEngineInfo[] & Record} */ module.exports = process.env.CITEST ? enginesOnCi : enginesOnLocal; module.exports.mysqlEngine = mysqlEngine; module.exports.mariaDbEngine = mariaDbEngine; module.exports.postgreSqlEngine = postgreSqlEngine; module.exports.sqlServerEngine = sqlServerEngine; module.exports.sqliteEngine = sqliteEngine; module.exports.cockroachDbEngine = cockroachDbEngine; module.exports.clickhouseEngine = clickhouseEngine; module.exports.oracleEngine = oracleEngine; module.exports.cassandraEngine = cassandraEngine; module.exports.libsqlFileEngine = libsqlFileEngine; module.exports.libsqlWsEngine = libsqlWsEngine; module.exports.duckdbEngine = duckdbEngine; module.exports.firebirdEngine = firebirdEngine;