New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(ibmi): add database version compatibility check for native boolean + initial unit tests #16909
base: main
Are you sure you want to change the base?
Conversation
Don't worry about the failing artifact download actions, that's a known flaky thing in the new version of the action. I can just rerun the checks if needed but you should be good if unit tests pass. |
@WikiRik sounds good. This is ready to review |
@WikiRik - any update on when this may get reviewed/merged? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add some unit tests that simulate ibmi 7.5.0 (or higher)? You can just do something similar as here;
it('supports sql.uuidV4 default values', async () => { | |
const localSequelize = dialect.name === 'postgres' | |
? createSequelizeInstance({ | |
databaseVersion: '13.0.0', | |
}) | |
: sequelize; | |
const stub = sinon.stub(localSequelize, 'queryRaw'); | |
await localSequelize.queryInterface.createTable('table', { | |
id: { | |
type: DataTypes.UUID, | |
primaryKey: true, | |
defaultValue: sql.uuidV4, | |
}, | |
}); | |
expect(stub.callCount).to.eq(1); | |
const firstCall = stub.getCall(0); | |
expectsql(firstCall.args[0], { | |
postgres: 'CREATE TABLE IF NOT EXISTS "table" ("id" UUID DEFAULT gen_random_uuid(), PRIMARY KEY ("id"));', | |
'mariadb mysql': 'CREATE TABLE IF NOT EXISTS `table` (`id` CHAR(36) BINARY, PRIMARY KEY (`id`)) ENGINE=InnoDB;', | |
mssql: `IF OBJECT_ID(N'[table]', 'U') IS NULL CREATE TABLE [table] ([id] UNIQUEIDENTIFIER DEFAULT NEWID(), PRIMARY KEY ([id]));`, | |
sqlite: 'CREATE TABLE IF NOT EXISTS `table` (`id` TEXT PRIMARY KEY);', | |
snowflake: 'CREATE TABLE IF NOT EXISTS "table" ("id" VARCHAR(36), PRIMARY KEY ("id"));', | |
db2: 'CREATE TABLE IF NOT EXISTS "table" ("id" CHAR(36) FOR BIT DATA NOT NULL, PRIMARY KEY ("id"));', | |
ibmi: `BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE VALUE '42710' BEGIN END; CREATE TABLE "table" ("id" CHAR(36), PRIMARY KEY ("id")); END`, | |
}); | |
}); | |
if (dialect.name === 'postgres') { | |
// gen_random_uuid was added in postgres 13 | |
it('supports sql.uuidV4 default values (postgres < 13)', async () => { | |
const localSequelize = createSequelizeInstance({ | |
databaseVersion: '12.0.0', | |
}); | |
const stub = sinon.stub(localSequelize, 'queryRaw'); | |
await localSequelize.queryInterface.createTable('table', { | |
id: { | |
type: DataTypes.UUID, | |
primaryKey: true, | |
defaultValue: sql.uuidV4, | |
}, | |
}); | |
expect(stub.callCount).to.eq(1); | |
const firstCall = stub.getCall(0); | |
expectsql(firstCall.args[0], { | |
postgres: 'CREATE TABLE IF NOT EXISTS "table" ("id" UUID DEFAULT uuid_generate_v4(), PRIMARY KEY ("id"));', | |
}); | |
}); | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason that this file was not added originally is that we're reducing the amount of dialect specific tests and are moving this per function to separate files. But seeing as we're still in the process of doing that I can see some benefit in having this file so I can go either way. @ephys do you have a strong opinion on this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The functions being tested in this new file already have common test files, so I don't want to approve this file. The new tests should be added to the new files instead, if they're relevant
@@ -20,8 +20,7 @@ describe('QueryGenerator#bulkInsertQuery', () => { | |||
expectsql(sql, { | |||
default: `INSERT INTO [Users] ([firstName]) VALUES ('a string');`, | |||
mssql: `INSERT INTO [Users] ([firstName]) VALUES (N'a string');`, | |||
// TODO: ibmi should be the same as `default`, since the 'returning' option is not specified | |||
ibmi: `SELECT * FROM FINAL TABLE (INSERT INTO "Users" ("firstName") VALUES ('a string'))`, | |||
ibmi: `INSERT INTO "Users" ("firstName") VALUES ('a string')`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should work now
ibmi: `INSERT INTO "Users" ("firstName") VALUES ('a string')`, |
@@ -24,7 +24,7 @@ describe('QueryInterface#bulkInsert', () => { | |||
|
|||
expectPerDialect(() => firstCall, { | |||
default: toMatchRegex(/^INSERT INTO (?:`|")Users(?:`|") \((?:`|")firstName(?:`|")\) VALUES (?:\('\w+'\),){999}\('\w+'\);$/), | |||
ibmi: toMatchRegex(/^SELECT \* FROM FINAL TABLE \(INSERT INTO "Users" \("firstName"\) VALUES (?:\('\w+'\),){999}\('\w+'\)\)$/), | |||
ibmi: toMatchRegex(/^INSERT INTO "Users" \("firstName"\) VALUES (?:\('\w+'\),){999}\('\w+'\)$/), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ibmi: toMatchRegex(/^INSERT INTO "Users" \("firstName"\) VALUES (?:\('\w+'\),){999}\('\w+'\)$/), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe that the custom expectations in the other changed tests can be removed
const databaseVersion | ||
= Number.parseFloat(this._getDialect().sequelize.options.databaseVersion || this._getDialect().defaultVersion); | ||
|
||
return databaseVersion >= 7.5; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can use the gt
function from semver to compare this to getDatabaseVersion()
@@ -96,5 +96,6 @@ export const Config: Record<Dialect, Options> = { | |||
dialectOptions: { | |||
odbcConnectionString: env.SEQ_IBMI_CONN_STR, | |||
}, | |||
databaseVersion: '7.3.0', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
databaseVersion: '7.3.0', |
ibmi has a defaultVersion of 7.3.0 already
@@ -8,16 +8,27 @@ export class UUID extends BaseTypes.UUID { | |||
} | |||
|
|||
export class BOOLEAN extends BaseTypes.BOOLEAN { | |||
protected supportsNativeBooleans() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be hard private
@@ -8,16 +8,27 @@ export class UUID extends BaseTypes.UUID { | |||
} | |||
|
|||
export class BOOLEAN extends BaseTypes.BOOLEAN { | |||
protected supportsNativeBooleans() { | |||
const databaseVersion | |||
= Number.parseFloat(this._getDialect().sequelize.options.databaseVersion || this._getDialect().defaultVersion); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't get the database version like this, but via sequelize.getDatabaseVersion()
@@ -356,7 +355,6 @@ export class IBMiQueryGenerator extends IBMiQueryGeneratorTypeScript { | |||
let query = super.bulkInsertQuery(tableName, fieldValueHashes, options, fieldMappedAttributes); | |||
if (query.at(-1) === ';') { | |||
query = query.slice(0, -1); | |||
query = `SELECT * FROM FINAL TABLE (${query})`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why remove the "select from final table"? :o
Finally circling back to this. To implement with the dialect being split out, how should I approach this pull request? Throw out and redo it? |
Pull Request Checklist
Description Of Change
Added a check within data-types.js for the IBM i dialect to check the database version. If it's the latest known version, it implements the base boolean support, which handles booleans properly within javascript and back to the database. Also copied the DB2 unit tests as a start for IBM i unit testing.
Todos