mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
Merge pull request #851 from iz-iznogood/indices-fixes
Fixes for issues #833, #834 and #840
This commit is contained in:
commit
b84d95b902
@ -49,7 +49,8 @@ export function Index(nameOrFieldsOrOptions?: string|string[]|((object: any) =>
|
||||
target: propertyName ? clsOrObject.constructor : clsOrObject as Function,
|
||||
name: name,
|
||||
columns: propertyName ? [propertyName] : fields,
|
||||
unique: options && options.unique ? true : false
|
||||
unique: options && options.unique ? true : false,
|
||||
sparse: options && options.sparse ? true : false
|
||||
};
|
||||
getMetadataArgsStorage().indices.push(args);
|
||||
};
|
||||
|
||||
@ -327,7 +327,7 @@ export class MysqlQueryRunner implements QueryRunner {
|
||||
const tableNamesString = tableNames.map(tableName => `'${tableName}'`).join(", ");
|
||||
const tablesSql = `SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '${this.dbName}' AND TABLE_NAME IN (${tableNamesString})`;
|
||||
const columnsSql = `SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '${this.dbName}'`;
|
||||
const indicesSql = `SELECT * FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA = '${this.dbName}' AND INDEX_NAME != 'PRIMARY'`;
|
||||
const indicesSql = `SELECT * FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA = '${this.dbName}' AND INDEX_NAME != 'PRIMARY' ORDER BY SEQ_IN_INDEX`;
|
||||
const foreignKeysSql = `SELECT * FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA = '${this.dbName}' AND REFERENCED_COLUMN_NAME IS NOT NULL`;
|
||||
const [dbTables, dbColumns, dbIndices, dbForeignKeys]: ObjectLiteral[][] = await Promise.all([
|
||||
this.query(tablesSql),
|
||||
@ -425,7 +425,7 @@ export class MysqlQueryRunner implements QueryRunner {
|
||||
}
|
||||
}
|
||||
|
||||
return new IndexSchema(dbTable["TABLE_NAME"], dbIndexName, columnNames, false /* todo: uniqueness */);
|
||||
return new IndexSchema(dbTable["TABLE_NAME"], dbIndexName, columnNames, currentDbIndices[0]["NON_UNIQUE"] === 0);
|
||||
})
|
||||
.filter(index => !!index) as IndexSchema[]; // remove empty returns
|
||||
|
||||
|
||||
@ -336,7 +336,7 @@ export class PostgresQueryRunner implements QueryRunner {
|
||||
const tableNamesString = tableNames.map(name => "'" + name + "'").join(", ");
|
||||
const tablesSql = `SELECT * FROM information_schema.tables WHERE table_catalog = '${this.dbName}' AND table_schema = '${this.schemaName}' AND table_name IN (${tableNamesString})`;
|
||||
const columnsSql = `SELECT * FROM information_schema.columns WHERE table_catalog = '${this.dbName}' AND table_schema = '${this.schemaName}'`;
|
||||
const indicesSql = `SELECT t.relname AS table_name, i.relname AS index_name, a.attname AS column_name FROM pg_class t, pg_class i, pg_index ix, pg_attribute a, pg_namespace ns
|
||||
const indicesSql = `SELECT t.relname AS table_name, i.relname AS index_name, a.attname AS column_name, ix.indisunique AS is_unique, a.attnum, ix.indkey FROM pg_class t, pg_class i, pg_index ix, pg_attribute a, pg_namespace ns
|
||||
WHERE t.oid = ix.indrelid AND i.oid = ix.indexrelid AND a.attrelid = t.oid
|
||||
AND a.attnum = ANY(ix.indkey) AND t.relkind = 'r' AND t.relname IN (${tableNamesString}) AND t.relnamespace = ns.OID AND ns.nspname ='${this.schemaName}' ORDER BY t.relname, i.relname`;
|
||||
const foreignKeysSql = `SELECT table_name, constraint_name FROM information_schema.table_constraints WHERE table_catalog = '${this.dbName}' AND table_schema = '${this.schemaName}' AND constraint_type = 'FOREIGN KEY'`;
|
||||
@ -427,11 +427,14 @@ where constraint_type = 'PRIMARY KEY' AND c.table_schema = '${this.schemaName}'
|
||||
.map(dbIndex => dbIndex["index_name"])
|
||||
.filter((value, index, self) => self.indexOf(value) === index) // unqiue
|
||||
.map(dbIndexName => {
|
||||
const columnNames = dbIndices
|
||||
.filter(dbIndex => dbIndex["table_name"] === tableSchema.name && dbIndex["index_name"] === dbIndexName)
|
||||
.map(dbIndex => dbIndex["column_name"]);
|
||||
const dbIndicesInfos = dbIndices
|
||||
.filter(dbIndex => dbIndex["table_name"] === tableSchema.name && dbIndex["index_name"] === dbIndexName);
|
||||
const columnPositions = dbIndicesInfos[0]["indkey"].split(" ")
|
||||
.map((x: string) => parseInt(x));
|
||||
const columnNames = columnPositions
|
||||
.map((pos: number) => dbIndicesInfos.find(idx => idx.attnum === pos)!["column_name"]);
|
||||
|
||||
return new IndexSchema(dbTable["TABLE_NAME"], dbIndexName, columnNames, false /* todo: uniqueness */);
|
||||
return new IndexSchema(dbTable["TABLE_NAME"], dbIndexName, columnNames, dbIndicesInfos[0]["is_unique"]);
|
||||
});
|
||||
|
||||
return tableSchema;
|
||||
|
||||
@ -300,7 +300,9 @@ export class AbstractSqliteQueryRunner implements QueryRunner {
|
||||
.map(async dbIndexName => {
|
||||
const dbIndex = dbIndices.find(dbIndex => dbIndex["name"] === dbIndexName);
|
||||
const indexInfos: ObjectLiteral[] = await this.query(`PRAGMA index_info("${dbIndex!["name"]}")`);
|
||||
const indexColumns = indexInfos.map(indexInfo => indexInfo["name"]);
|
||||
const indexColumns = indexInfos
|
||||
.sort((indexInfo1, indexInfo2) => parseInt(indexInfo1["seqno"]) - parseInt(indexInfo2["seqno"]))
|
||||
.map(indexInfo => indexInfo["name"]);
|
||||
|
||||
// check if db index is generated by sqlite itself and has special use case
|
||||
if (dbIndex!["name"].substr(0, "sqlite_autoindex".length) === "sqlite_autoindex") {
|
||||
@ -316,7 +318,8 @@ export class AbstractSqliteQueryRunner implements QueryRunner {
|
||||
return Promise.resolve(undefined);
|
||||
|
||||
} else {
|
||||
return new IndexSchema(dbTable["name"], dbIndex!["name"], indexColumns, dbIndex!["unique"] === "1");
|
||||
const isUnique = dbIndex!["unique"] === "1" || dbIndex!["unique"] === 1;
|
||||
return new IndexSchema(dbTable["name"], dbIndex!["name"], indexColumns, isUnique);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -497,9 +497,9 @@ export class SqlServerQueryRunner implements QueryRunner {
|
||||
`LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS tableConstraints ON tableConstraints.CONSTRAINT_NAME = columnUsages.CONSTRAINT_NAME ` +
|
||||
`WHERE columnUsages.TABLE_CATALOG = '${this.dbName}' AND tableConstraints.TABLE_CATALOG = '${this.dbName}'`;
|
||||
const identityColumnsSql = `SELECT COLUMN_NAME, TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_CATALOG = '${this.dbName}' AND COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') = 1;`;
|
||||
const indicesSql = `SELECT TABLE_NAME = t.name, INDEX_NAME = ind.name, IndexId = ind.index_id, ColumnId = ic.index_column_id, COLUMN_NAME = col.name, ind.*, ic.*, col.* ` +
|
||||
const indicesSql = `SELECT TABLE_NAME = t.name, INDEX_NAME = ind.name, IndexId = ind.index_id, ColumnId = ic.index_column_id, COLUMN_NAME = col.name, IS_UNIQUE = ind.is_unique, ind.*, ic.*, col.* ` +
|
||||
`FROM sys.indexes ind INNER JOIN sys.index_columns ic ON ind.object_id = ic.object_id and ind.index_id = ic.index_id INNER JOIN sys.columns col ON ic.object_id = col.object_id and ic.column_id = col.column_id ` +
|
||||
`INNER JOIN sys.tables t ON ind.object_id = t.object_id WHERE ind.is_primary_key = 0 AND ind.is_unique = 0 AND ind.is_unique_constraint = 0 AND t.is_ms_shipped = 0 ORDER BY t.name, ind.name, ind.index_id, ic.index_column_id`;
|
||||
`INNER JOIN sys.tables t ON ind.object_id = t.object_id WHERE ind.is_primary_key = 0 AND ind.is_unique_constraint = 0 AND t.is_ms_shipped = 0 ORDER BY t.name, ind.name, ind.index_id, ic.index_column_id`;
|
||||
const [dbTables, dbColumns, dbConstraints, dbIdentityColumns, dbIndices]: ObjectLiteral[][] = await Promise.all([
|
||||
this.query(tablesSql),
|
||||
this.query(columnsSql),
|
||||
@ -590,7 +590,8 @@ export class SqlServerQueryRunner implements QueryRunner {
|
||||
.filter(dbIndex => dbIndex["TABLE_NAME"] === tableSchema.name && dbIndex["INDEX_NAME"] === dbIndexName)
|
||||
.map(dbIndex => dbIndex["COLUMN_NAME"]);
|
||||
|
||||
return new IndexSchema(dbTable["TABLE_NAME"], dbIndexName, columnNames, false /* todo: uniqueness? */);
|
||||
const isUnique = !!dbIndices.find(dbIndex => dbIndex["TABLE_NAME"] === tableSchema.name && dbIndex["INDEX_NAME"] === dbIndexName && dbIndex["IS_UNIQUE"] === true);
|
||||
return new IndexSchema(dbTable["TABLE_NAME"], dbIndexName, columnNames, isUnique);
|
||||
});
|
||||
|
||||
return tableSchema;
|
||||
|
||||
@ -247,4 +247,29 @@ export interface EntitySchema { // todo: make it-to-date
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Entity indices options.
|
||||
*/
|
||||
indices: {
|
||||
[indexName: string]: {
|
||||
|
||||
/**
|
||||
* Index column names.
|
||||
*/
|
||||
columns: string[];
|
||||
|
||||
/**
|
||||
* Indicates if this index must be unique or not.
|
||||
*/
|
||||
unique: boolean;
|
||||
|
||||
/**
|
||||
* If true, the index only references documents with the specified field.
|
||||
* These indexes use less space but behave differently in some situations (particularly sorts).
|
||||
* This option is only supported for mongodb database.
|
||||
*/
|
||||
sparse?: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
@ -2,6 +2,7 @@ import {EntitySchema} from "./EntitySchema";
|
||||
import {MetadataArgsStorage} from "../metadata-args/MetadataArgsStorage";
|
||||
import {TableMetadataArgs} from "../metadata-args/TableMetadataArgs";
|
||||
import {ColumnMetadataArgs} from "../metadata-args/ColumnMetadataArgs";
|
||||
import {IndexMetadataArgs} from "../metadata-args/IndexMetadataArgs";
|
||||
import {RelationMetadataArgs} from "../metadata-args/RelationMetadataArgs";
|
||||
import {JoinColumnMetadataArgs} from "../metadata-args/JoinColumnMetadataArgs";
|
||||
import {JoinTableMetadataArgs} from "../metadata-args/JoinTableMetadataArgs";
|
||||
@ -147,6 +148,22 @@ export class EntitySchemaTransformer {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// add relation metadata args from the schema
|
||||
if (schema.indices) {
|
||||
Object.keys(schema.indices).forEach(indexName => {
|
||||
const indexSchema = schema.indices[indexName];
|
||||
const indexAgrs: IndexMetadataArgs = {
|
||||
target: schema.target || schema.name,
|
||||
name: indexName,
|
||||
unique: indexSchema.unique,
|
||||
sparse: indexSchema.sparse,
|
||||
columns: indexSchema.columns
|
||||
};
|
||||
metadataArgsStorage.indices.push(indexAgrs);
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return metadataArgsStorage;
|
||||
|
||||
@ -23,4 +23,10 @@ export interface IndexMetadataArgs {
|
||||
*/
|
||||
unique: boolean;
|
||||
|
||||
/**
|
||||
* If true, the index only references documents with the specified field.
|
||||
* These indexes use less space but behave differently in some situations (particularly sorts).
|
||||
* This option is only supported for mongodb database.
|
||||
*/
|
||||
sparse?: boolean;
|
||||
}
|
||||
|
||||
@ -22,6 +22,13 @@ export class IndexMetadata {
|
||||
*/
|
||||
isUnique: boolean = false;
|
||||
|
||||
/**
|
||||
* If true, the index only references documents with the specified field.
|
||||
* These indexes use less space but behave differently in some situations (particularly sorts).
|
||||
* This option is only supported for mongodb database.
|
||||
*/
|
||||
isSparse?: boolean;
|
||||
|
||||
/**
|
||||
* Target class to which metadata is applied.
|
||||
*/
|
||||
@ -76,6 +83,7 @@ export class IndexMetadata {
|
||||
if (options.args) {
|
||||
this.target = options.args.target;
|
||||
this.isUnique = options.args.unique;
|
||||
this.isSparse = options.args.sparse;
|
||||
this.givenName = options.args.name;
|
||||
this.givenColumnNames = options.args.columns;
|
||||
}
|
||||
|
||||
@ -37,7 +37,7 @@ export class MongoSchemaBuilder implements SchemaBuilder {
|
||||
const promises: Promise<any>[] = [];
|
||||
this.connection.entityMetadatas.forEach(metadata => {
|
||||
metadata.indices.forEach(index => {
|
||||
const options = { name: index.name, unique: index.isUnique };
|
||||
const options = { name: index.name, unique: index.isUnique, sparse: index.isSparse };
|
||||
promises.push(queryRunner.createCollectionIndex(metadata.tableName, index.columnNamesWithOrderingMap, options));
|
||||
});
|
||||
});
|
||||
|
||||
@ -357,13 +357,27 @@ export class RdbmsSchemaBuilder implements SchemaBuilder {
|
||||
|
||||
// drop all indices that exist in the table, but does not exist in the given composite indices
|
||||
const dropQueries = tableSchema.indices
|
||||
.filter(indexSchema => !metadata.indices.find(indexMetadata => indexMetadata.name === indexSchema.name))
|
||||
.filter(indexSchema => {
|
||||
const metadataIndex = metadata.indices.find(indexMetadata => indexMetadata.name === indexSchema.name);
|
||||
if (!metadataIndex)
|
||||
return true;
|
||||
if (metadataIndex.isUnique !== indexSchema.isUnique)
|
||||
return true;
|
||||
if (metadataIndex.columns.length !== indexSchema.columnNames.length)
|
||||
return true;
|
||||
if (metadataIndex.columns.findIndex((col, i) => col.databaseName !== indexSchema.columnNames[i]) !== -1)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
})
|
||||
.map(async indexSchema => {
|
||||
this.connection.logger.logSchemaBuild(`dropping an index: ${indexSchema.name}`);
|
||||
tableSchema.removeIndex(indexSchema);
|
||||
await this.queryRunner.dropIndex(metadata.tableName, indexSchema.name);
|
||||
});
|
||||
|
||||
await Promise.all(dropQueries);
|
||||
|
||||
// then create table indices for all composite indices we have
|
||||
const addQueries = metadata.indices
|
||||
.filter(indexMetadata => !tableSchema.indices.find(indexSchema => indexSchema.name === indexMetadata.name))
|
||||
@ -374,7 +388,7 @@ export class RdbmsSchemaBuilder implements SchemaBuilder {
|
||||
await this.queryRunner.createIndex(indexSchema.tableName, indexSchema);
|
||||
});
|
||||
|
||||
await Promise.all(dropQueries.concat(addQueries));
|
||||
await Promise.all(addQueries);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
19
test/functional/database-schema/indices/entity/Person.ts
Normal file
19
test/functional/database-schema/indices/entity/Person.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import {Entity} from "../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Column} from "../../../../../src/decorator/columns/Column";
|
||||
import {Index} from "../../../../../src/decorator/Index";
|
||||
|
||||
@Entity()
|
||||
@Index("IDX_TEST", ["firstname", "lastname"])
|
||||
export class Person {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
firstname: string;
|
||||
|
||||
@Column()
|
||||
lastname: string;
|
||||
|
||||
}
|
||||
@ -0,0 +1,90 @@
|
||||
import "reflect-metadata";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../utils/test-utils";
|
||||
import {Connection} from "../../../../src/connection/Connection";
|
||||
import {expect} from "chai";
|
||||
import {EntityMetadata} from "../../../../src/metadata/EntityMetadata";
|
||||
import {IndexMetadata} from "../../../../src/metadata/IndexMetadata";
|
||||
|
||||
import {Person} from "./entity/Person";
|
||||
|
||||
describe("indices > reading index from entity schema and updating database", () => {
|
||||
|
||||
let connections: Connection[];
|
||||
before(async () => connections = await createTestingConnections({
|
||||
entities: [Person],
|
||||
schemaCreate: true,
|
||||
dropSchema: true
|
||||
}));
|
||||
beforeEach(() => reloadTestingDatabases(connections));
|
||||
after(() => closeTestingConnections(connections));
|
||||
|
||||
describe("create index", function() {
|
||||
|
||||
it("should create a non unique index with 2 columns", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const queryRunner = connection.createQueryRunner();
|
||||
const tableSchema = await queryRunner.loadTableSchema("person");
|
||||
await queryRunner.release();
|
||||
|
||||
expect(tableSchema!.indices.length).to.be.equal(1);
|
||||
expect(tableSchema!.indices[0].name).to.be.equal("IDX_TEST");
|
||||
expect(tableSchema!.indices[0].isUnique).to.be.false;
|
||||
expect(tableSchema!.indices[0].columnNames.length).to.be.equal(2);
|
||||
expect(tableSchema!.indices[0].columnNames[0]).to.be.equal("firstname");
|
||||
expect(tableSchema!.indices[0].columnNames[1]).to.be.equal("lastname");
|
||||
|
||||
})));
|
||||
|
||||
it("should update the index to be unique", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const entityMetadata = connection.entityMetadatas.find(x => x.name === "Person");
|
||||
const indexMetadata = entityMetadata!.indices.find(x => x.name === "IDX_TEST");
|
||||
indexMetadata!.isUnique = true;
|
||||
|
||||
await connection.synchronize(false);
|
||||
|
||||
const queryRunner = connection.createQueryRunner();
|
||||
const tableSchema = await queryRunner.loadTableSchema("person");
|
||||
await queryRunner.release();
|
||||
|
||||
expect(tableSchema!.indices.length).to.be.equal(1);
|
||||
expect(tableSchema!.indices[0].name).to.be.equal("IDX_TEST");
|
||||
expect(tableSchema!.indices[0].isUnique).to.be.true;
|
||||
expect(tableSchema!.indices[0].columnNames.length).to.be.equal(2);
|
||||
expect(tableSchema!.indices[0].columnNames[0]).to.be.equal("firstname");
|
||||
expect(tableSchema!.indices[0].columnNames[1]).to.be.equal("lastname");
|
||||
|
||||
})));
|
||||
|
||||
it("should update the index swaping the 2 columns", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const entityMetadata = connection.entityMetadatas.find(x => x.name === "Person");
|
||||
entityMetadata!.indices = [new IndexMetadata({
|
||||
entityMetadata: <EntityMetadata>entityMetadata,
|
||||
args: {
|
||||
target: Person,
|
||||
name: "IDX_TEST",
|
||||
columns: ["lastname", "firstname"],
|
||||
unique: false
|
||||
}
|
||||
})];
|
||||
entityMetadata!.indices.forEach(index => index.build(connection.namingStrategy));
|
||||
|
||||
await connection.synchronize(false);
|
||||
|
||||
const queryRunner = connection.createQueryRunner();
|
||||
const tableSchema = await queryRunner.loadTableSchema("person");
|
||||
await queryRunner.release();
|
||||
|
||||
expect(tableSchema!.indices.length).to.be.equal(1);
|
||||
expect(tableSchema!.indices[0].name).to.be.equal("IDX_TEST");
|
||||
expect(tableSchema!.indices[0].isUnique).to.be.false;
|
||||
expect(tableSchema!.indices[0].columnNames.length).to.be.equal(2);
|
||||
expect(tableSchema!.indices[0].columnNames[0]).to.be.equal("lastname");
|
||||
expect(tableSchema!.indices[0].columnNames[1]).to.be.equal("firstname");
|
||||
|
||||
})));
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
29
test/functional/entity-schema/indices/entity/Person.ts
Normal file
29
test/functional/entity-schema/indices/entity/Person.ts
Normal file
@ -0,0 +1,29 @@
|
||||
export const PersonSchema = {
|
||||
name: "Person",
|
||||
columns: {
|
||||
Id: {
|
||||
primary: true,
|
||||
type: "int",
|
||||
generated: "increment"
|
||||
},
|
||||
FirstName: {
|
||||
type: String,
|
||||
length: 30
|
||||
},
|
||||
LastName: {
|
||||
type: String,
|
||||
length: 50,
|
||||
nullable: false
|
||||
}
|
||||
},
|
||||
relations: {},
|
||||
indices: {
|
||||
IDX_TEST: {
|
||||
unique: false,
|
||||
columns: [
|
||||
"FirstName",
|
||||
"LastName"
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
90
test/functional/entity-schema/indices/indices-test.ts
Normal file
90
test/functional/entity-schema/indices/indices-test.ts
Normal file
@ -0,0 +1,90 @@
|
||||
import "reflect-metadata";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../utils/test-utils";
|
||||
import {Connection} from "../../../../src/connection/Connection";
|
||||
import {EntityMetadata} from "../../../../src/metadata/EntityMetadata";
|
||||
import {IndexMetadata} from "../../../../src/metadata/IndexMetadata";
|
||||
import {expect} from "chai";
|
||||
|
||||
import {PersonSchema} from "./entity/Person";
|
||||
|
||||
describe("indices > reading index from entity schema and updating database", () => {
|
||||
|
||||
let connections: Connection[];
|
||||
before(async () => connections = await createTestingConnections({
|
||||
entitySchemas: [<any>PersonSchema],
|
||||
schemaCreate: true,
|
||||
dropSchema: true
|
||||
}));
|
||||
beforeEach(() => reloadTestingDatabases(connections));
|
||||
after(() => closeTestingConnections(connections));
|
||||
|
||||
describe("create index", function() {
|
||||
|
||||
it("should create a non unique index with 2 columns", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const queryRunner = connection.createQueryRunner();
|
||||
const tableSchema = await queryRunner.loadTableSchema("person");
|
||||
await queryRunner.release();
|
||||
|
||||
expect(tableSchema!.indices.length).to.be.equal(1);
|
||||
expect(tableSchema!.indices[0].name).to.be.equal("IDX_TEST");
|
||||
expect(tableSchema!.indices[0].isUnique).to.be.false;
|
||||
expect(tableSchema!.indices[0].columnNames.length).to.be.equal(2);
|
||||
expect(tableSchema!.indices[0].columnNames[0]).to.be.equal("FirstName");
|
||||
expect(tableSchema!.indices[0].columnNames[1]).to.be.equal("LastName");
|
||||
|
||||
})));
|
||||
|
||||
it("should update the index to be unique", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const entityMetadata = connection.entityMetadatas.find(x => x.name === "Person");
|
||||
const indexMetadata = entityMetadata!.indices.find(x => x.name === "IDX_TEST");
|
||||
indexMetadata!.isUnique = true;
|
||||
|
||||
await connection.synchronize(false);
|
||||
|
||||
const queryRunner = connection.createQueryRunner();
|
||||
const tableSchema = await queryRunner.loadTableSchema("person");
|
||||
await queryRunner.release();
|
||||
|
||||
expect(tableSchema!.indices.length).to.be.equal(1);
|
||||
expect(tableSchema!.indices[0].name).to.be.equal("IDX_TEST");
|
||||
expect(tableSchema!.indices[0].isUnique).to.be.true;
|
||||
expect(tableSchema!.indices[0].columnNames.length).to.be.equal(2);
|
||||
expect(tableSchema!.indices[0].columnNames[0]).to.be.equal("FirstName");
|
||||
expect(tableSchema!.indices[0].columnNames[1]).to.be.equal("LastName");
|
||||
|
||||
})));
|
||||
|
||||
it("should update the index swaping the 2 columns", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const entityMetadata = connection.entityMetadatas.find(x => x.name === "Person");
|
||||
entityMetadata!.indices = [new IndexMetadata({
|
||||
entityMetadata: <EntityMetadata>entityMetadata,
|
||||
args: {
|
||||
target: entityMetadata!.target,
|
||||
name: "IDX_TEST",
|
||||
columns: ["LastName", "FirstName"],
|
||||
unique: false
|
||||
}
|
||||
})];
|
||||
entityMetadata!.indices.forEach(index => index.build(connection.namingStrategy));
|
||||
|
||||
await connection.synchronize(false);
|
||||
|
||||
const queryRunner = connection.createQueryRunner();
|
||||
const tableSchema = await queryRunner.loadTableSchema("person");
|
||||
await queryRunner.release();
|
||||
|
||||
expect(tableSchema!.indices.length).to.be.equal(1);
|
||||
expect(tableSchema!.indices[0].name).to.be.equal("IDX_TEST");
|
||||
expect(tableSchema!.indices[0].isUnique).to.be.false;
|
||||
expect(tableSchema!.indices[0].columnNames.length).to.be.equal(2);
|
||||
expect(tableSchema!.indices[0].columnNames[0]).to.be.equal("LastName");
|
||||
expect(tableSchema!.indices[0].columnNames[1]).to.be.equal("FirstName");
|
||||
|
||||
})));
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
@ -50,7 +50,7 @@ export interface TestingOptions {
|
||||
/**
|
||||
* Entity schemas needs to be included in the connection for the given test suite.
|
||||
*/
|
||||
entitySchemas?: EntitySchema[];
|
||||
entitySchemas?: string[]|EntitySchema[];
|
||||
|
||||
/**
|
||||
* Indicates if schema sync should be performed or not.
|
||||
@ -141,8 +141,8 @@ export function setupTestingConnections(options?: TestingOptions): ConnectionOpt
|
||||
entities: options && options.entities ? options.entities : [],
|
||||
subscribers: options && options.subscribers ? options.subscribers : [],
|
||||
entitySchemas: options && options.entitySchemas ? options.entitySchemas : [],
|
||||
autoSchemaSync: options && options.entities ? options.schemaCreate : false,
|
||||
dropSchema: options && options.entities ? options.dropSchema : false,
|
||||
autoSchemaSync: options && (options.entities || options.entitySchemas) ? options.schemaCreate : false,
|
||||
dropSchema: options && (options.entities || options.entitySchemas) ? options.dropSchema : false,
|
||||
schema: options && options.schema ? options.schema : undefined,
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user