123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451 |
- 'use strict';
- const Support = require('../../support');
- const { DataTypes } = require('@sequelize/core');
- const { expect } = require('chai');
- const expectsql = Support.expectsql;
- const current = Support.sequelize;
- const sql = current.dialect.queryGenerator;
- const dialect = current.dialect;
- // Notice: [] will be replaced by dialect specific tick/quote character when there is not dialect specific expectation but only a default expectation
- describe(Support.getTestDialectTeaser('SQL'), () => {
- describe('insert', () => {
- it('with temp table for trigger', () => {
- const User = Support.sequelize.define(
- 'user',
- {
- username: {
- type: DataTypes.STRING,
- field: 'user_name',
- },
- },
- {
- timestamps: false,
- hasTrigger: true,
- },
- );
- const options = {
- returning: true,
- hasTrigger: true,
- };
- expectsql(
- sql.insertQuery(User.table, { user_name: 'triggertest' }, User.getAttributes(), options),
- {
- query: {
- ibmi: 'SELECT * FROM FINAL TABLE (INSERT INTO "users" ("user_name") VALUES ($sequelize_1))',
- mssql:
- 'DECLARE @tmp TABLE ([id] INTEGER,[user_name] NVARCHAR(255)); INSERT INTO [users] ([user_name]) OUTPUT INSERTED.[id], INSERTED.[user_name] INTO @tmp VALUES ($sequelize_1); SELECT * FROM @tmp;',
- sqlite3:
- 'INSERT INTO `users` (`user_name`) VALUES ($sequelize_1) RETURNING `id`, `user_name`;',
- postgres:
- 'INSERT INTO "users" ("user_name") VALUES ($sequelize_1) RETURNING "id", "user_name";',
- db2: 'SELECT * FROM FINAL TABLE (INSERT INTO "users" ("user_name") VALUES ($sequelize_1));',
- snowflake: 'INSERT INTO "users" ("user_name") VALUES ($sequelize_1);',
- default: 'INSERT INTO `users` (`user_name`) VALUES ($sequelize_1);',
- },
- bind: { sequelize_1: 'triggertest' },
- },
- );
- });
- it('allow insert primary key with 0', () => {
- const M = Support.sequelize.define('m', {
- id: {
- type: DataTypes.INTEGER,
- primaryKey: true,
- autoIncrement: true,
- },
- });
- expectsql(sql.insertQuery(M.table, { id: 0 }, M.getAttributes()), {
- query: {
- mssql:
- 'SET IDENTITY_INSERT [ms] ON; INSERT INTO [ms] ([id]) VALUES ($sequelize_1); SET IDENTITY_INSERT [ms] OFF;',
- db2: 'SELECT * FROM FINAL TABLE (INSERT INTO "ms" ("id") VALUES ($sequelize_1));',
- ibmi: 'SELECT * FROM FINAL TABLE (INSERT INTO "ms" ("id") VALUES ($sequelize_1))',
- postgres: 'INSERT INTO "ms" ("id") VALUES ($sequelize_1);',
- snowflake: 'INSERT INTO "ms" ("id") VALUES ($sequelize_1);',
- default: 'INSERT INTO `ms` (`id`) VALUES ($sequelize_1);',
- },
- bind: { sequelize_1: 0 },
- });
- });
- it(
- current.dialect.supports.inserts.onConflictWhere
- ? 'adds conflictWhere clause to generated queries'
- : 'throws error if conflictWhere is provided',
- () => {
- const User = Support.sequelize.define(
- 'user',
- {
- username: {
- type: DataTypes.STRING,
- field: 'user_name',
- primaryKey: true,
- },
- password: {
- type: DataTypes.STRING,
- field: 'pass_word',
- },
- createdAt: {
- type: DataTypes.DATE,
- field: 'created_at',
- },
- updatedAt: {
- type: DataTypes.DATE,
- field: 'updated_at',
- },
- },
- {
- timestamps: true,
- },
- );
- const upsertKeys = ['user_name'];
- let result;
- try {
- result = sql.insertQuery(
- User.table,
- { user_name: 'testuser', pass_word: '12345' },
- User.fieldRawAttributesMap,
- {
- updateOnDuplicate: ['user_name', 'pass_word', 'updated_at'],
- conflictWhere: {
- user_name: 'test where value',
- },
- upsertKeys,
- },
- );
- } catch (error) {
- result = error;
- }
- expectsql(result, {
- default: new Error('missing dialect support for conflictWhere option'),
- 'postgres sqlite3': `INSERT INTO [users] ([user_name],[pass_word]) VALUES ($sequelize_1,$sequelize_2) ON CONFLICT ([user_name]) WHERE [user_name] = 'test where value' DO UPDATE SET [user_name]=EXCLUDED.[user_name],[pass_word]=EXCLUDED.[pass_word],[updated_at]=EXCLUDED.[updated_at];`,
- });
- },
- );
- });
- describe('dates', () => {
- if (!dialect.supports.globalTimeZoneConfig) {
- it('rejects specifying the global timezone option', () => {
- expect(() => Support.createSequelizeInstance({ timezone: 'CET' })).to.throw(
- 'Setting a custom timezone is not supported',
- );
- });
- } else {
- it('supports the global timezone option', () => {
- const timezoneSequelize = Support.createSequelizeInstance({
- timezone: 'CET',
- });
- const User = timezoneSequelize.define(
- 'user',
- {
- date: {
- type: DataTypes.DATE(3),
- },
- },
- {
- timestamps: false,
- },
- );
- expectsql(
- timezoneSequelize.dialect.queryGenerator.insertQuery(
- User.table,
- { date: new Date(Date.UTC(2015, 0, 20)) },
- User.getAttributes(),
- {},
- ),
- {
- query: {
- default: 'INSERT INTO [users] ([date]) VALUES ($sequelize_1);',
- },
- bind: {
- // these dialects change the DB-side timezone, and the input doesn't specify the timezone offset, so we have to offset the value ourselves
- // because it will be interpreted as CET by the dialect.
- snowflake: { sequelize_1: '2015-01-20 01:00:00.000' },
- mysql: { sequelize_1: '2015-01-20 01:00:00.000' },
- mariadb: { sequelize_1: '2015-01-20 01:00:00.000' },
- // These dialects do specify the offset, so they can use whichever offset they want.
- postgres: { sequelize_1: '2015-01-20 01:00:00.000 +01:00' },
- },
- },
- );
- });
- }
- it('formats the date correctly when inserting', () => {
- const User = current.define(
- 'user',
- {
- date: {
- type: DataTypes.DATE(3),
- },
- },
- {
- timestamps: false,
- },
- );
- expectsql(
- current.dialect.queryGenerator.insertQuery(
- User.table,
- { date: new Date(Date.UTC(2015, 0, 20)) },
- User.getAttributes(),
- {},
- ),
- {
- query: {
- ibmi: 'SELECT * FROM FINAL TABLE (INSERT INTO "users" ("date") VALUES ($sequelize_1))',
- postgres: 'INSERT INTO "users" ("date") VALUES ($sequelize_1);',
- db2: 'SELECT * FROM FINAL TABLE (INSERT INTO "users" ("date") VALUES ($sequelize_1));',
- snowflake: 'INSERT INTO "users" ("date") VALUES ($sequelize_1);',
- mssql: 'INSERT INTO [users] ([date]) VALUES ($sequelize_1);',
- default: 'INSERT INTO `users` (`date`) VALUES ($sequelize_1);',
- },
- bind: {
- ibmi: { sequelize_1: '2015-01-20 00:00:00.000' },
- db2: { sequelize_1: '2015-01-20 00:00:00.000' },
- snowflake: { sequelize_1: '2015-01-20 00:00:00.000' },
- mysql: { sequelize_1: '2015-01-20 00:00:00.000' },
- mariadb: { sequelize_1: '2015-01-20 00:00:00.000' },
- sqlite3: { sequelize_1: '2015-01-20 00:00:00.000 +00:00' },
- mssql: { sequelize_1: '2015-01-20 00:00:00.000 +00:00' },
- postgres: { sequelize_1: '2015-01-20 00:00:00.000 +00:00' },
- },
- },
- );
- });
- it('formats date correctly when sub-second precision is explicitly specified', () => {
- const User = current.define(
- 'user',
- {
- date: {
- type: DataTypes.DATE(3),
- },
- },
- {
- timestamps: false,
- },
- );
- expectsql(
- current.dialect.queryGenerator.insertQuery(
- User.table,
- { date: new Date(Date.UTC(2015, 0, 20, 1, 2, 3, 89)) },
- User.getAttributes(),
- {},
- ),
- {
- query: {
- ibmi: 'SELECT * FROM FINAL TABLE (INSERT INTO "users" ("date") VALUES ($sequelize_1))',
- postgres: 'INSERT INTO "users" ("date") VALUES ($sequelize_1);',
- db2: 'SELECT * FROM FINAL TABLE (INSERT INTO "users" ("date") VALUES ($sequelize_1));',
- snowflake: 'INSERT INTO "users" ("date") VALUES ($sequelize_1);',
- mssql: 'INSERT INTO [users] ([date]) VALUES ($sequelize_1);',
- default: 'INSERT INTO `users` (`date`) VALUES ($sequelize_1);',
- },
- bind: {
- ibmi: { sequelize_1: '2015-01-20 01:02:03.089' },
- db2: { sequelize_1: '2015-01-20 01:02:03.089' },
- snowflake: { sequelize_1: '2015-01-20 01:02:03.089' },
- mariadb: { sequelize_1: '2015-01-20 01:02:03.089' },
- mysql: { sequelize_1: '2015-01-20 01:02:03.089' },
- sqlite3: { sequelize_1: '2015-01-20 01:02:03.089 +00:00' },
- postgres: { sequelize_1: '2015-01-20 01:02:03.089 +00:00' },
- mssql: { sequelize_1: '2015-01-20 01:02:03.089 +00:00' },
- },
- },
- );
- });
- });
- describe('strings', () => {
- it('formats null characters correctly when inserting', () => {
- const User = Support.sequelize.define(
- 'user',
- {
- username: {
- type: DataTypes.STRING,
- field: 'user_name',
- },
- },
- {
- timestamps: false,
- },
- );
- expectsql(sql.insertQuery(User.table, { user_name: 'null\0test' }, User.getAttributes()), {
- query: {
- ibmi: 'SELECT * FROM FINAL TABLE (INSERT INTO "users" ("user_name") VALUES ($sequelize_1))',
- postgres: 'INSERT INTO "users" ("user_name") VALUES ($sequelize_1);',
- db2: 'SELECT * FROM FINAL TABLE (INSERT INTO "users" ("user_name") VALUES ($sequelize_1));',
- snowflake: 'INSERT INTO "users" ("user_name") VALUES ($sequelize_1);',
- mssql: 'INSERT INTO [users] ([user_name]) VALUES ($sequelize_1);',
- default: 'INSERT INTO `users` (`user_name`) VALUES ($sequelize_1);',
- },
- bind: {
- postgres: { sequelize_1: 'null\u0000test' },
- default: { sequelize_1: 'null\0test' },
- },
- });
- });
- });
- describe('bulkCreate', () => {
- it('bulk create with onDuplicateKeyUpdate', () => {
- const User = Support.sequelize.define(
- 'user',
- {
- username: {
- type: DataTypes.STRING,
- field: 'user_name',
- primaryKey: true,
- },
- password: {
- type: DataTypes.STRING,
- field: 'pass_word',
- },
- createdAt: {
- field: 'created_at',
- },
- updatedAt: {
- field: 'updated_at',
- },
- },
- {
- timestamps: true,
- },
- );
- // mapping primary keys to their "field" override values
- const primaryKeys = User.primaryKeyAttributes.map(
- attr => User.getAttributes()[attr].field || attr,
- );
- expectsql(
- sql.bulkInsertQuery(
- User.table,
- [{ user_name: 'testuser', pass_word: '12345' }],
- { updateOnDuplicate: ['user_name', 'pass_word', 'updated_at'], upsertKeys: primaryKeys },
- User.fieldRawAttributesMap,
- ),
- {
- default: "INSERT INTO `users` (`user_name`,`pass_word`) VALUES ('testuser','12345');",
- ibmi: 'SELECT * FROM FINAL TABLE (INSERT INTO "users" ("user_name","pass_word") VALUES (\'testuser\',\'12345\'))',
- snowflake:
- 'INSERT INTO "users" ("user_name","pass_word") VALUES (\'testuser\',\'12345\');',
- postgres:
- 'INSERT INTO "users" ("user_name","pass_word") VALUES (\'testuser\',\'12345\') ON CONFLICT ("user_name") DO UPDATE SET "user_name"=EXCLUDED."user_name","pass_word"=EXCLUDED."pass_word","updated_at"=EXCLUDED."updated_at";',
- mssql: "INSERT INTO [users] ([user_name],[pass_word]) VALUES (N'testuser',N'12345');",
- db2: 'INSERT INTO "users" ("user_name","pass_word") VALUES (\'testuser\',\'12345\');',
- mariadb:
- "INSERT INTO `users` (`user_name`,`pass_word`) VALUES ('testuser','12345') ON DUPLICATE KEY UPDATE `user_name`=VALUES(`user_name`),`pass_word`=VALUES(`pass_word`),`updated_at`=VALUES(`updated_at`);",
- mysql:
- "INSERT INTO `users` (`user_name`,`pass_word`) VALUES ('testuser','12345') ON DUPLICATE KEY UPDATE `user_name`=VALUES(`user_name`),`pass_word`=VALUES(`pass_word`),`updated_at`=VALUES(`updated_at`);",
- sqlite3:
- "INSERT INTO `users` (`user_name`,`pass_word`) VALUES ('testuser','12345') ON CONFLICT (`user_name`) DO UPDATE SET `user_name`=EXCLUDED.`user_name`,`pass_word`=EXCLUDED.`pass_word`,`updated_at`=EXCLUDED.`updated_at`;",
- },
- );
- });
- it('allow bulk insert primary key with 0', () => {
- const M = Support.sequelize.define('m', {
- id: {
- type: DataTypes.INTEGER,
- primaryKey: true,
- autoIncrement: true,
- },
- });
- expectsql(
- sql.bulkInsertQuery(M.table, [{ id: 0 }, { id: null }], {}, M.fieldRawAttributesMap),
- {
- query: {
- mssql:
- 'SET IDENTITY_INSERT [ms] ON; INSERT INTO [ms] DEFAULT VALUES;INSERT INTO [ms] ([id]) VALUES (0),(NULL); SET IDENTITY_INSERT [ms] OFF;',
- postgres: 'INSERT INTO "ms" ("id") VALUES (0),(DEFAULT);',
- db2: 'INSERT INTO "ms" VALUES (1);INSERT INTO "ms" ("id") VALUES (0),(NULL);',
- ibmi: 'SELECT * FROM FINAL TABLE (INSERT INTO "ms" ("id") VALUES (0),(DEFAULT))',
- snowflake: 'INSERT INTO "ms" ("id") VALUES (0),(NULL);',
- default: 'INSERT INTO `ms` (`id`) VALUES (0),(NULL);',
- },
- },
- );
- });
- if (current.dialect.supports.inserts.updateOnDuplicate) {
- it('correctly generates SQL for conflictWhere', () => {
- const User = Support.sequelize.define(
- 'user',
- {
- username: {
- type: DataTypes.STRING,
- field: 'user_name',
- primaryKey: true,
- },
- password: {
- type: DataTypes.STRING,
- field: 'pass_word',
- },
- createdAt: {
- type: DataTypes.DATE,
- field: 'created_at',
- },
- updatedAt: {
- type: DataTypes.DATE,
- field: 'updated_at',
- },
- deletedAt: {
- type: DataTypes.DATE,
- field: 'deleted_at',
- },
- },
- {
- timestamps: true,
- },
- );
- // mapping primary keys to their "field" override values
- const primaryKeys = User.primaryKeyAttributes.map(
- attr => User.getAttributes()[attr].field || attr,
- );
- let result;
- try {
- result = sql.bulkInsertQuery(
- User.table,
- [{ user_name: 'testuser', pass_word: '12345' }],
- {
- updateOnDuplicate: ['user_name', 'pass_word', 'updated_at'],
- upsertKeys: primaryKeys,
- conflictWhere: { deleted_at: null },
- },
- User.fieldRawAttributesMap,
- );
- } catch (error) {
- result = error;
- }
- expectsql(result, {
- default: new Error(`conflictWhere not supported for dialect ${dialect.name}`),
- 'postgres sqlite3':
- "INSERT INTO [users] ([user_name],[pass_word]) VALUES ('testuser','12345') ON CONFLICT ([user_name]) WHERE [deleted_at] IS NULL DO UPDATE SET [user_name]=EXCLUDED.[user_name],[pass_word]=EXCLUDED.[pass_word],[updated_at]=EXCLUDED.[updated_at];",
- });
- });
- }
- });
- });
|