Skip to content

Commit

Permalink
fix: update index include test for db2 & postgres
Browse files Browse the repository at this point in the history
  • Loading branch information
lohart13 committed Oct 28, 2022
1 parent 8d3ee09 commit 60d1bbc
Show file tree
Hide file tree
Showing 2 changed files with 170 additions and 32 deletions.
145 changes: 121 additions & 24 deletions test/integration/index.test.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
'use strict';

const chai = require('chai');
const semver = require('semver');

const expect = chai.expect;
const Support = require('./support');

const current = Support.sequelize;
const dialect = Support.getTestDialect();
const { DataTypes, Sequelize } = require('@sequelize/core');

describe(Support.getTestDialectTeaser('Indexes'), () => {
Expand All @@ -14,23 +16,81 @@ describe(Support.getTestDialectTeaser('Indexes'), () => {
return;
}

it('creates index with include columns', function () {
it('creates non-unique index with include columns', async function () {
this.User = this.sequelize.define('user', {
username: DataTypes.STRING,
first_name: DataTypes.STRING,
last_name: DataTypes.STRING,
}, {
indexes: [{ name: 'user_username', fields: ['username'], include: ['first_name', 'last_name'] }],
indexes: [{ name: 'user_username', fields: ['username'], include: ['first_name', 'last_name'], unique: false }],
});

return this.sequelize.sync({ force: true }).then(() => {
return this.sequelize.queryInterface.showIndex(this.User.tableName);
}).then(indexes => {
expect(indexes).to.have.length(2);
expect(indexes[1].name).to.equal('user_username');
expect(indexes[1].fields).to.have.length(1);
expect(indexes[1].fields[0].attribute).to.equal('username');
// DB2 does not support non-unique indexes with include columns
if (dialect === 'db2') {
return this.User.sync({ force: true }).then(() => {
expect.fail('This should have failed');
}).catch(error => {
expect(error.message).to.equal('DB2 does not support non-unique indexes with INCLUDE syntax.');
});
}

// Include columns are only supported by PostgreSQL version 11.0.0 and higher
if (dialect === 'postgres' && semver.lt(current.options.databaseVersion, '11.0.0')) {
return this.User.sync({ force: true }).then(() => {
expect.fail('This should have failed');
}).catch(error => {
expect(error.message).to.equal('Postgres 11.0.0 or higher is required to use INCLUDE syntax for indexes.');
});
}

await this.sequelize.sync({ force: true });
const indexes = await this.sequelize.queryInterface.showIndex(this.User.tableName);
const indexCheck = indexes.filter(index => index.name === 'user_username');

expect(indexCheck).to.have.length(1);
expect(indexCheck[0].name).to.equal('user_username');
// DB2 lists the included columns in the fields array
if (dialect !== 'db2') {
expect(indexCheck[0].fields).to.have.length(1);
} else {
expect(indexCheck[0].fields).to.have.length(3);
}

expect(indexCheck[0].fields[0].attribute).to.equal('username');
});

it('creates unique index with include columns', async function () {
this.User = this.sequelize.define('user', {
username: DataTypes.STRING,
first_name: DataTypes.STRING,
last_name: DataTypes.STRING,
}, {
indexes: [{ name: 'user_username', fields: ['username'], include: ['first_name', 'last_name'], unique: true }],
});

// Include columns are only supported by PostgreSQL version 11.0.0 and higher
if (dialect === 'postgres' && semver.lt(current.options.databaseVersion, '11.0.0')) {
return this.User.sync({ force: true }).then(() => {
expect.fail('This should have failed');
}).catch(error => {
expect(error.message).to.equal('Postgres 11.0.0 or higher is required to use INCLUDE syntax for indexes.');
});
}

await this.sequelize.sync({ force: true });
const indexes = await this.sequelize.queryInterface.showIndex(this.User.tableName);
const indexCheck = indexes.filter(index => index.name === 'user_username');

expect(indexCheck).to.have.length(1);
expect(indexCheck[0].name).to.equal('user_username');
// DB2 lists the included columns in the fields array
if (dialect !== 'db2') {
expect(indexCheck[0].fields).to.have.length(1);
} else {
expect(indexCheck[0].fields).to.have.length(3);
}

expect(indexCheck[0].fields[0].attribute).to.equal('username');
});

it('throws an error with duplicate column names', function () {
Expand All @@ -41,13 +101,28 @@ describe(Support.getTestDialectTeaser('Indexes'), () => {
first_name: DataTypes.STRING,
last_name: DataTypes.STRING,
}, {
indexes: [{ name: 'user_username', fields: ['username'], include: ['username', 'first_name', 'last_name'] }],
indexes: [{ name: 'user_username', fields: ['username'], include: ['username', 'first_name', 'last_name'], unique: true }],
});

return this.sequelize.sync({ force: true }).catch(error => {
expect(error).to.be.instanceOf(DatabaseError);
expect(error.message).to.match(/\s|^Cannot use duplicate column names in index. Column name 'username' listed more than once.$/);
});
// Include columns are only supported by PostgreSQL version 11.0.0 and higher
if (dialect === 'postgres' && semver.lt(current.options.databaseVersion, '11.0.0')) {
return this.User.sync({ force: true }).then(() => {
expect.fail('This should have failed');
}).catch(error => {
expect(error.message).to.equal('Postgres 11.0.0 or higher is required to use INCLUDE syntax for indexes.');
});
}

return this.sequelize.sync({ force: true })
.then(() => {
if (dialect !== 'postgres') {
expect.fail('This should have failed');
}
})
.catch(error => {
expect(error).to.be.instanceOf(DatabaseError);
expect(error.message).to.match(/\s|^Cannot use duplicate column names in index. Column name 'username' listed more than once.$/);
});
});

it('throws an error with missing column names', function () {
Expand All @@ -58,13 +133,24 @@ describe(Support.getTestDialectTeaser('Indexes'), () => {
first_name: DataTypes.STRING,
last_name: DataTypes.STRING,
}, {
indexes: [{ name: 'user_username', fields: ['username'], include: ['first_name', 'last_name', 'email'] }],
indexes: [{ name: 'user_username', fields: ['username'], include: ['first_name', 'last_name', 'email'], unique: true }],
});

return this.sequelize.sync({ force: true }).catch(error => {
expect(error).to.be.instanceOf(DatabaseError);
expect(error.message).to.match(/\s|^Column name 'email' does not exist in the target table or view.$/);
});
// Include columns are only supported by PostgreSQL version 11.0.0 and higher
if (dialect === 'postgres' && semver.lt(current.options.databaseVersion, '11.0.0')) {
return this.User.sync({ force: true }).then(() => {
expect.fail('This should have failed');
}).catch(error => {
expect(error.message).to.equal('Postgres 11.0.0 or higher is required to use INCLUDE syntax for indexes.');
});
}

return this.sequelize.sync({ force: true })
.then(() => expect.fail('This should have failed'))
.catch(error => {
expect(error).to.be.instanceOf(DatabaseError);
expect(error.message).to.match(/\s|^Column name 'email' does not exist in the target table or view.$/);
});
});

it('throws an error with invalid column type', function () {
Expand All @@ -75,13 +161,24 @@ describe(Support.getTestDialectTeaser('Indexes'), () => {
first_name: DataTypes.STRING,
last_name: DataTypes.STRING,
}, {
indexes: [{ name: 'user_username', fields: ['username'], include: ['first_name', 'last_name', 'email'] }],
indexes: [{ name: 'user_username', fields: ['username'], include: ['first_name', 'last_name', 'email'], unique: true }],
});

return this.sequelize.sync({ force: true }).catch(error => {
expect(error).to.be.instanceOf(DatabaseError);
expect(error.message).to.match(/\s|^Column 'username' in table 'users' is of a type that is invalid for use as a key column in an index.$/);
});
// Include columns are only supported by PostgreSQL version 11.0.0 and higher
if (dialect === 'postgres' && semver.lt(current.options.databaseVersion, '11.0.0')) {
return this.User.sync({ force: true }).then(() => {
expect.fail('This should have failed');
}).catch(error => {
expect(error.message).to.equal('Postgres 11.0.0 or higher is required to use INCLUDE syntax for indexes.');
});
}

return this.sequelize.sync({ force: true })
.then(() => expect.fail('This should have failed'))
.catch(error => {
expect(error).to.be.instanceOf(DatabaseError);
expect(error.message).to.match(/\s|^Column 'username' in table 'users' is of a type that is invalid for use as a key column in an index.$/);
});
});
});
});
57 changes: 49 additions & 8 deletions test/unit/sql/index.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use strict';

const semver = require('semver');
const { expect } = require('chai');
const Support = require('../support');
const { Op } = require('@sequelize/core');

Expand Down Expand Up @@ -255,14 +257,53 @@ describe(Support.getTestDialectTeaser('SQL'), () => {
}

if (current.dialect.supports.index.include) {
it('INCLUDE', () => {
expectsql(sql.addIndexQuery('User', {
name: 'email_include_name',
fields: ['email'],
include: ['first_name', 'last_name'],
}), {
default: 'CREATE INDEX [email_include_name] ON [User] ([email]) INCLUDE ([first_name], [last_name])',
});
it('include columns with unique index', () => {
if (current.dialect.name === 'postgres' && semver.lt(current.options.databaseVersion, '11.0.0')) {
// Include columns are only supported by PostgreSQL version 11.0.0 and higher
expect(() => sql.addIndexQuery('User', {
name: 'email_include_name',
fields: ['email'],
include: ['first_name', 'last_name'],
unique: true,
})).to.throw('Postgres 11.0.0 or higher is required to use INCLUDE syntax for indexes.');
} else {
expectsql(sql.addIndexQuery('User', {
name: 'email_include_name',
fields: ['email'],
include: ['first_name', 'last_name'],
unique: true,
}), {
mssql: 'CREATE UNIQUE INDEX [email_include_name] ON [User] ([email]) INCLUDE ([first_name], [last_name])',
default: 'CREATE UNIQUE INDEX "email_include_name" ON [User] ("email") INCLUDE ("first_name", "last_name")',
});
}
});

it('include columns with non-unique index', () => {
if (current.dialect.name === 'postgres' && semver.lt(current.options.databaseVersion, '11.0.0')) {
// Include columns are only supported by PostgreSQL version 11.0.0 and higher
expect(() => sql.addIndexQuery('User', {
name: 'email_include_name',
fields: ['email'],
include: ['first_name', 'last_name'],
})).to.throw('Postgres 11.0.0 or higher is required to use INCLUDE syntax for indexes.');
} else if (current.dialect.name === 'db2') {
// DB2 does not support non-unique indexes with include columns
expect(() => sql.addIndexQuery('User', {
name: 'email_include_name',
fields: ['email'],
include: ['first_name', 'last_name'],
})).to.throw('DB2 does not support non-unique indexes with INCLUDE syntax.');
} else {
expectsql(sql.addIndexQuery('User', {
name: 'email_include_name',
fields: ['email'],
include: ['first_name', 'last_name'],
}), {
mssql: 'CREATE INDEX [email_include_name] ON [User] ([email]) INCLUDE ([first_name], [last_name])',
default: 'CREATE INDEX "email_include_name" ON [User] ("email") INCLUDE ("first_name", "last_name")',
});
}
});
}
});
Expand Down

0 comments on commit 60d1bbc

Please sign in to comment.