diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c45963caf..e3969a809 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: # node 10 is the minimum supported version for Sequelize 6 # node 14 is the minimum supported version for Sequelize 7 # node 16 is latest LTS (to keep updated) - node: [10, 14, 16] + node: [10] name: SQLite (sequelize 6 & 7, node ${{ matrix.node }}) runs-on: ubuntu-latest env: @@ -31,14 +31,14 @@ jobs: strategy: fail-fast: false matrix: - postgres-version: [9.5, 10] # Does not work with 12 + postgres-version: [9.5, 10, 11, 12, 16] native: [true, false] - node: [10, 14, 16] + node: [10] name: Postgres ${{ matrix.postgres-version }}${{ matrix.native && ' (native)' || '' }} (sequelize 6 & 7, node ${{ matrix.node }}) runs-on: ubuntu-latest services: postgres: - image: sushantdhiman/postgres:${{ matrix.postgres-version }} + image: postgres:${{ matrix.postgres-version }} env: POSTGRES_USER: sequelize_test POSTGRES_DB: sequelize_test @@ -61,7 +61,7 @@ jobs: strategy: fail-fast: false matrix: - node: [10, 14, 16] + node: [10] db: - '{ name: "MySQL 5.7", image: "mysql:5.7", dialect: "mysql" }' - '{ name: "MariaDB 10.3", image: "mariadb:10.3", dialect: "mariadb" }' @@ -93,7 +93,7 @@ jobs: strategy: fail-fast: false matrix: - node: [10, 14, 16] + node: [10] mssql-version: [2017, 2019] name: MSSQL ${{ matrix.mssql-version }} (sequelize 6 & 7, node ${{ matrix.node }}) runs-on: ubuntu-latest diff --git a/src/sscce-sequelize-6.ts b/src/sscce-sequelize-6.ts index c90761b96..3e0993557 100644 --- a/src/sscce-sequelize-6.ts +++ b/src/sscce-sequelize-6.ts @@ -1,4 +1,4 @@ -import { DataTypes, Model } from 'sequelize'; +import { DataTypes, Model, QueryTypes, Op } from 'sequelize'; import { createSequelize6Instance } from '../setup/create-sequelize-instance'; import { expect } from 'chai'; import sinon from 'sinon'; @@ -22,20 +22,297 @@ export async function run() { }); class Foo extends Model {} - Foo.init({ + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true + }, name: DataTypes.TEXT, }, { sequelize, - modelName: 'Foo', + modelName: 'foo', + underscored: true, + }); + + class Bar extends Model {} + Bar.init({ + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true + }, + fooId: { + type: DataTypes.INTEGER, + references: { model: 'foos' }, + }, + data: DataTypes.TEXT, + }, { + sequelize, + modelName: 'bar', + underscored: true, }); + Foo.hasMany(Bar); + Bar.belongsTo(Foo); + // You can use sinon and chai assertions directly in your SSCCE. const spy = sinon.spy(); sequelize.afterBulkSync(() => spy()); await sequelize.sync({ force: true }); expect(spy).to.have.been.called; - console.log(await Foo.create({ name: 'TS foo' })); - expect(await Foo.count()).to.equal(1); + await Promise.all([ + sequelize.query(` + insert into foos ( + id, name + ) + select + i::integer, + md5(random()::text) + from generate_series(1, 10000000) s(i) + `), + sequelize.query(` + insert into bars ( + id, foo_id, data + ) + select + i::integer, + i::integer, + md5(random()::text) + from generate_series(1, 10000000) s(i) + `), + ]); + + { + console.log("TEST 1.1") + const offset = 0; + const limit = 10; + const result = await Foo.findAll({ + logging: console.log, + benchmark: true, + limit, + offset, + where: { id: { [Op.between]: [345, 5678] } }, + include: { + model: Bar, + required: true, + where: { id: { [Op.between]: [2345, 8678] } } + }, + }); + } + + { + console.log("TEST 1.2") + const result = await sequelize.query( + `SELECT "foo".*, "bars"."id" AS "bars.id", "bars"."foo_id" AS "bars.fooId", "bars"."data" AS "bars.data" FROM ( + SELECT "foo"."id", "foo"."name" FROM "foos" AS "foo" + WHERE "foo"."id" BETWEEN 345 AND 5678 AND + ( + SELECT "foo_id" FROM "bars" AS "bars" + WHERE ("bars"."id" BETWEEN 2345 AND 8678 AND "bars"."foo_id" = "foo"."id") LIMIT 1 + ) IS NOT NULL + LIMIT 10 OFFSET 0 + ) AS "foo" + INNER JOIN "bars" AS "bars" ON "foo"."id" = "bars"."foo_id" AND "bars"."id" BETWEEN 2345 AND 8678;`, + { + logging: console.log, + benchmark: true, + } + ); + } + + { + console.log("TEST 1.3") + const result = await sequelize.query( + `SELECT "foo".*, "bars"."id" AS "bars.id", "bars"."foo_id" AS "bars.fooId", "bars"."data" AS "bars.data" FROM ( + SELECT "foo"."id", "foo"."name" FROM "foos" AS "foo" + WHERE "foo"."id" BETWEEN 345 AND 5678 AND + EXISTS ( + SELECT "foo_id" FROM "bars" AS "bars" + WHERE ("bars"."id" BETWEEN 2345 AND 8678 AND "bars"."foo_id" = "foo"."id") LIMIT 1 + ) + LIMIT 10 OFFSET 0 + ) AS "foo" + INNER JOIN "bars" AS "bars" ON "foo"."id" = "bars"."foo_id" AND "bars"."id" BETWEEN 2345 AND 8678;`, + { + logging: console.log, + benchmark: true, + } + ); + } + + { + console.log("TEST 2.1") + const offset = 0; + const limit = 10; + const result = await Foo.findAll({ + logging: console.log, + benchmark: true, + limit, + offset, + where: { id: { [Op.between]: [345, 5678] } }, + include: { + model: Bar, + required: true, + where: { id: { [Op.gt]: 123 } } + }, + }); + } + + { + console.log("TEST 2.2") + const result = await sequelize.query( + `SELECT "foo".*, "bars"."id" AS "bars.id", "bars"."foo_id" AS "bars.fooId", "bars"."data" AS "bars.data" FROM ( + SELECT "foo"."id", "foo"."name" FROM "foos" AS "foo" + WHERE "foo"."id" BETWEEN 345 AND 5678 AND + ( + SELECT "foo_id" FROM "bars" AS "bars" + WHERE ("bars"."id" > 123 AND "bars"."foo_id" = "foo"."id") LIMIT 1 + ) IS NOT NULL + LIMIT 10 OFFSET 0 + ) AS "foo" + INNER JOIN "bars" AS "bars" ON "foo"."id" = "bars"."foo_id" AND "bars"."id" > 123;`, + { + logging: console.log, + benchmark: true, + } + ); + } + + { + console.log("TEST 2.3") + const result = await sequelize.query( + `SELECT "foo".*, "bars"."id" AS "bars.id", "bars"."foo_id" AS "bars.fooId", "bars"."data" AS "bars.data" FROM ( + SELECT "foo"."id", "foo"."name" FROM "foos" AS "foo" + WHERE "foo"."id" BETWEEN 345 AND 5678 AND + EXISTS ( + SELECT "foo_id" FROM "bars" AS "bars" + WHERE ("bars"."id" > 123 AND "bars"."foo_id" = "foo"."id") LIMIT 1 + ) + LIMIT 10 OFFSET 0 + ) AS "foo" + INNER JOIN "bars" AS "bars" ON "foo"."id" = "bars"."foo_id" AND "bars"."id" > 123;`, + { + logging: console.log, + benchmark: true, + } + ); + } + + { + console.log("TEST 3.1") + const offset = 0; + const limit = 10; + const result = await Foo.findAll({ + logging: console.log, + benchmark: true, + limit, + offset, + where: { id: { [Op.gt]: 123 } }, + include: { + model: Bar, + required: true, + where: { id: { [Op.gt]: 123 } } + }, + }); + } + + { + console.log("TEST 3.2") + const result = await sequelize.query( + `SELECT "foo".*, "bars"."id" AS "bars.id", "bars"."foo_id" AS "bars.fooId", "bars"."data" AS "bars.data" FROM ( + SELECT "foo"."id", "foo"."name" FROM "foos" AS "foo" + WHERE "foo"."id" > 123 AND + ( + SELECT "foo_id" FROM "bars" AS "bars" + WHERE ("bars"."id" > 123 AND "bars"."foo_id" = "foo"."id") LIMIT 1 + ) IS NOT NULL + LIMIT 10 OFFSET 0 + ) AS "foo" + INNER JOIN "bars" AS "bars" ON "foo"."id" = "bars"."foo_id" AND "bars"."id" > 123;`, + { + logging: console.log, + benchmark: true, + } + ); + } + + { + console.log("TEST 3.3") + const result = await sequelize.query( + `SELECT "foo".*, "bars"."id" AS "bars.id", "bars"."foo_id" AS "bars.fooId", "bars"."data" AS "bars.data" FROM ( + SELECT "foo"."id", "foo"."name" FROM "foos" AS "foo" + WHERE "foo"."id" > 123 AND + EXISTS ( + SELECT "foo_id" FROM "bars" AS "bars" + WHERE ("bars"."id" > 123 AND "bars"."foo_id" = "foo"."id") LIMIT 1 + ) + LIMIT 10 OFFSET 0 + ) AS "foo" + INNER JOIN "bars" AS "bars" ON "foo"."id" = "bars"."foo_id" AND "bars"."id" > 123;`, + { + logging: console.log, + benchmark: true, + } + ); + } + + { + console.log("TEST 4.1") + const offset = 0; + const limit = 10; + const result = await Foo.findAll({ + logging: console.log, + benchmark: true, + limit, + offset, + where: { id: { [Op.gt]: 123 } }, + include: { + model: Bar, + required: true, + where: { id: { [Op.between]: [345, 5678] } } + }, + }); + } + + { + console.log("TEST 4.2") + const result = await sequelize.query( + `SELECT "foo".*, "bars"."id" AS "bars.id", "bars"."foo_id" AS "bars.fooId", "bars"."data" AS "bars.data" FROM ( + SELECT "foo"."id", "foo"."name" FROM "foos" AS "foo" + WHERE "foo"."id" > 123 AND + ( + SELECT "foo_id" FROM "bars" AS "bars" + WHERE ("bars"."id" BETWEEN 345 AND 5678 AND "bars"."foo_id" = "foo"."id") LIMIT 1 + ) IS NOT NULL + LIMIT 10 OFFSET 0 + ) AS "foo" + INNER JOIN "bars" AS "bars" ON "foo"."id" = "bars"."foo_id" AND "bars"."id" BETWEEN 345 AND 5678;`, + { + logging: console.log, + benchmark: true, + } + ); + } + + { + console.log("TEST 4.3") + const result = await sequelize.query( + `SELECT "foo".*, "bars"."id" AS "bars.id", "bars"."foo_id" AS "bars.fooId", "bars"."data" AS "bars.data" FROM ( + SELECT "foo"."id", "foo"."name" FROM "foos" AS "foo" + WHERE "foo"."id" > 123 AND + EXISTS ( + SELECT "foo_id" FROM "bars" AS "bars" + WHERE ("bars"."id" BETWEEN 345 AND 5678 AND "bars"."foo_id" = "foo"."id") LIMIT 1 + ) + LIMIT 10 OFFSET 0 + ) AS "foo" + INNER JOIN "bars" AS "bars" ON "foo"."id" = "bars"."foo_id" AND "bars"."id" BETWEEN 345 AND 5678;`, + { + logging: console.log, + benchmark: true, + } + ); + } } diff --git a/src/sscce-sequelize-7.ts b/src/sscce-sequelize-7.ts deleted file mode 100644 index 861b9fdea..000000000 --- a/src/sscce-sequelize-7.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { DataTypes, Model } from '@sequelize/core'; -import { createSequelize7Instance } from '../setup/create-sequelize-instance'; -import { expect } from 'chai'; -import sinon from 'sinon'; - -// if your issue is dialect specific, remove the dialects you don't need to test on. -export const testingOnDialects = new Set(['mssql', 'sqlite', 'mysql', 'mariadb', 'postgres', 'postgres-native']); - -// You can delete this file if you don't want your SSCCE to be tested against Sequelize 7 - -// Your SSCCE goes inside this function. -export async function run() { - // This function should be used instead of `new Sequelize()`. - // It applies the config for your SSCCE to work on CI. - const sequelize = createSequelize7Instance({ - logQueryParameters: true, - benchmark: true, - define: { - // For less clutter in the SSCCE - timestamps: false, - }, - }); - - class Foo extends Model {} - - Foo.init({ - name: DataTypes.TEXT, - }, { - sequelize, - modelName: 'Foo', - }); - - // You can use sinon and chai assertions directly in your SSCCE. - const spy = sinon.spy(); - sequelize.afterBulkSync(() => spy()); - await sequelize.sync({ force: true }); - expect(spy).to.have.been.called; - - console.log(await Foo.create({ name: 'TS foo' })); - expect(await Foo.count()).to.equal(1); -}