123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- 'use strict';
- import { DataTypes, DatabaseError } from '@sequelize/core';
- import { expect } from 'chai';
- import { getTestDialect, getTestDialectTeaser, sequelize } from './support';
- const dialect = getTestDialect();
- describe(getTestDialectTeaser('Indexes'), () => {
- describe('Indexes with include', () => {
- it('creates unique index', async () => {
- const User = sequelize.define(
- 'user',
- {
- username: { type: DataTypes.STRING, unique: true },
- first_name: DataTypes.STRING,
- last_name: DataTypes.STRING,
- },
- {
- indexes: [{ name: 'unique_names', fields: ['first_name', 'last_name'], unique: true }],
- },
- );
- await sequelize.sync({ force: true });
- const indexes = await sequelize.queryInterface.showIndex(User.table);
- const indexCheck = indexes.find(index => index.name === 'unique_names');
- expect(indexCheck?.name).to.equal('unique_names');
- expect(indexCheck?.unique).to.equal(true);
- expect(indexCheck?.fields).to.have.length(2);
- expect(indexCheck?.fields[0].attribute).to.equal('first_name');
- expect(indexCheck?.fields[1].attribute).to.equal('last_name');
- });
- if (sequelize.dialect.supports.schemas) {
- it('creates unique index with a custom schema', async () => {
- await sequelize.createSchema('test_schema');
- const User = sequelize.define(
- 'user',
- {
- username: { type: DataTypes.STRING, unique: true },
- first_name: DataTypes.STRING,
- last_name: DataTypes.STRING,
- },
- {
- schema: 'test_schema',
- indexes: [{ name: 'unique_names', fields: ['first_name', 'last_name'], unique: true }],
- },
- );
- await sequelize.sync({ force: true });
- const indexes = await sequelize.queryInterface.showIndex(User.table);
- const indexCheck = indexes.find(index => index.name === 'unique_names');
- expect(indexCheck?.name).to.equal('unique_names');
- expect(indexCheck?.unique).to.equal(true);
- expect(indexCheck?.fields).to.have.length(2);
- expect(indexCheck?.fields[0].attribute).to.equal('first_name');
- expect(indexCheck?.fields[1].attribute).to.equal('last_name');
- });
- }
- if (sequelize.dialect.supports.index.include) {
- it('creates non-unique index with include columns', async () => {
- const User = 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: false,
- },
- ],
- },
- );
- if (dialect === 'db2') {
- try {
- await sequelize.sync({ force: true });
- expect.fail('This should have failed');
- } catch (error: any) {
- expect(error.message).to.equal(
- 'DB2 does not support non-unique indexes with INCLUDE syntax.',
- );
- }
- } else {
- await sequelize.sync({ force: true });
- const indexes = await sequelize.queryInterface.showIndex(User.table);
- const indexCheck = indexes.find(index => index.name === 'user_username');
- expect(indexCheck?.name).to.equal('user_username');
- expect(indexCheck?.fields).to.have.length(1);
- expect(indexCheck?.fields[0].attribute).to.equal('username');
- expect(indexCheck?.includes).to.have.length(2);
- expect(indexCheck?.includes).to.include('first_name');
- expect(indexCheck?.includes).to.include('last_name');
- }
- });
- it('creates unique index with include columns', async () => {
- const User = 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,
- },
- ],
- },
- );
- await sequelize.sync({ force: true });
- const indexes = await sequelize.queryInterface.showIndex(User.table);
- const indexCheck = indexes.find(index => index.name === 'user_username');
- expect(indexCheck?.name).to.equal('user_username');
- expect(indexCheck?.unique).to.equal(true);
- expect(indexCheck?.fields).to.have.length(1);
- expect(indexCheck?.fields[0].attribute).to.equal('username');
- expect(indexCheck?.includes).to.have.length(2);
- expect(indexCheck?.includes).to.include('first_name');
- expect(indexCheck?.includes).to.include('last_name');
- });
- it('throws an error with duplicate column names', async () => {
- const User = sequelize.define(
- 'user',
- {
- username: DataTypes.STRING,
- first_name: DataTypes.STRING,
- last_name: DataTypes.STRING,
- },
- {
- indexes: [
- {
- name: 'user_username',
- fields: ['username'],
- include: ['username', 'first_name', 'last_name'],
- unique: true,
- },
- ],
- },
- );
- try {
- await sequelize.sync({ force: true });
- if (dialect === 'postgres') {
- const indexes = await sequelize.queryInterface.showIndex(User.table);
- const indexCheck = indexes.find(index => index.name === 'user_username');
- expect(indexCheck?.name).to.equal('user_username');
- expect(indexCheck?.unique).to.equal(true);
- expect(indexCheck?.fields).to.have.length(1);
- expect(indexCheck?.fields[0].attribute).to.equal('username');
- expect(indexCheck?.includes).to.have.length(3);
- expect(indexCheck?.includes).to.include('username');
- expect(indexCheck?.includes).to.include('first_name');
- expect(indexCheck?.includes).to.include('last_name');
- } else {
- expect.fail('This should have failed');
- }
- } catch (error: any) {
- 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', async () => {
- 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', 'email'],
- unique: true,
- },
- ],
- },
- );
- try {
- await sequelize.sync({ force: true });
- expect.fail('This should have failed');
- } catch (error: any) {
- 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', async () => {
- sequelize.define(
- 'user',
- {
- username: DataTypes.TEXT,
- first_name: DataTypes.STRING,
- last_name: DataTypes.STRING,
- },
- {
- indexes: [
- {
- name: 'user_username',
- fields: ['username'],
- include: ['first_name', 'last_name', 'email'],
- unique: true,
- },
- ],
- },
- );
- try {
- await sequelize.sync({ force: true });
- expect.fail('This should have failed');
- } catch (error: any) {
- 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.$/,
- );
- }
- });
- }
- });
- });
|