fixing index on relations (#12602)
## Why After the changes on relations, index on relations were skipped by the syncmetadata service, so no more migrations were generated for relation fields. We wanted to fix this. ## Test This PR adds unit tests for the `createIndexMigration` utility in the workspace migration builder. The tests cover: - Creating index migrations for simple fields (e.g., text fields) - Creating index migrations for relation fields (ensuring correct column naming, e.g., `authorId` for the `author` objectmetadataname) ## Excluded The delete index on relation does not need the column names so i don't think i needed to work on this method. I might be wrong. ## Checklist - [x] Added/updated unit tests for index migration creation - [x] Verified correct handling of simple and relation fields - [x] Ensured all tests pass --------- Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@ -3,7 +3,7 @@ import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metad
|
|||||||
import { computeTableName } from './compute-table-name.util';
|
import { computeTableName } from './compute-table-name.util';
|
||||||
|
|
||||||
export const computeObjectTargetTable = (
|
export const computeObjectTargetTable = (
|
||||||
objectMetadata: ObjectMetadataInterface,
|
objectMetadata: Pick<ObjectMetadataInterface, 'nameSingular' | 'isCustom'>,
|
||||||
) => {
|
) => {
|
||||||
return computeTableName(objectMetadata.nameSingular, objectMetadata.isCustom);
|
return computeTableName(objectMetadata.nameSingular, objectMetadata.isCustom);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -8,7 +8,7 @@ export function isFieldMetadataInterfaceOfType<
|
|||||||
Field extends FieldMetadataInterface<FieldMetadataType>,
|
Field extends FieldMetadataInterface<FieldMetadataType>,
|
||||||
Type extends FieldMetadataType,
|
Type extends FieldMetadataType,
|
||||||
>(
|
>(
|
||||||
fieldMetadata: Field,
|
fieldMetadata: Pick<Field, 'type'>,
|
||||||
type: Type,
|
type: Type,
|
||||||
): fieldMetadata is Field & FieldMetadataInterface<Type> {
|
): fieldMetadata is Field & FieldMetadataInterface<Type> {
|
||||||
return fieldMetadata.type === type;
|
return fieldMetadata.type === type;
|
||||||
@ -18,7 +18,7 @@ export function isFieldMetadataEntityOfType<
|
|||||||
Field extends FieldMetadataEntity<FieldMetadataType>,
|
Field extends FieldMetadataEntity<FieldMetadataType>,
|
||||||
Type extends FieldMetadataType,
|
Type extends FieldMetadataType,
|
||||||
>(
|
>(
|
||||||
fieldMetadata: Field,
|
fieldMetadata: Pick<Field, 'type'>,
|
||||||
type: Type,
|
type: Type,
|
||||||
): fieldMetadata is Field & FieldMetadataEntity<Type> {
|
): fieldMetadata is Field & FieldMetadataEntity<Type> {
|
||||||
return fieldMetadata.type === type;
|
return fieldMetadata.type === type;
|
||||||
|
|||||||
@ -0,0 +1,77 @@
|
|||||||
|
import { FieldMetadataType } from 'twenty-shared/types';
|
||||||
|
|
||||||
|
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||||
|
|
||||||
|
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||||
|
import { IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-metadata.entity';
|
||||||
|
import { createIndexMigration } from 'src/engine/workspace-manager/workspace-migration-builder/factories/utils/workspace-migration-index.factory.utils';
|
||||||
|
|
||||||
|
describe('WorkspaceMigrationIndexFactory', () => {
|
||||||
|
it('should create index migrations for simple fields', async () => {
|
||||||
|
const objectMetadata = {
|
||||||
|
id: 'obj1',
|
||||||
|
workspaceId: 'ws1',
|
||||||
|
nameSingular: 'Test',
|
||||||
|
fields: [{ id: 'f1', name: 'simpleField', type: FieldMetadataType.TEXT }],
|
||||||
|
isCustom: false,
|
||||||
|
};
|
||||||
|
const indexMetadata = {
|
||||||
|
name: 'idx_simple',
|
||||||
|
isUnique: true,
|
||||||
|
indexType: 'BTREE',
|
||||||
|
indexWhereClause: null,
|
||||||
|
indexFieldMetadatas: [{ fieldMetadataId: 'f1', order: 0 }],
|
||||||
|
} as IndexMetadataEntity;
|
||||||
|
const map = new Map([[objectMetadata, [indexMetadata]]]);
|
||||||
|
const result = (await createIndexMigration(map)) as any;
|
||||||
|
|
||||||
|
expect(result).toHaveLength(1);
|
||||||
|
const firstMigration = result[0].migrations[0];
|
||||||
|
|
||||||
|
expect(firstMigration.action).toBe('alter_indexes');
|
||||||
|
expect(firstMigration.indexes[0].name).toBe('idx_simple');
|
||||||
|
expect(firstMigration.indexes[0].columns).toEqual(['simpleField']);
|
||||||
|
expect(firstMigration.indexes[0].type).toBe('BTREE');
|
||||||
|
expect(firstMigration.indexes[0].isUnique).toBe(true);
|
||||||
|
expect(firstMigration.indexes[0].where).toBe(
|
||||||
|
'"simpleField" != \'\' AND "deletedAt" IS NULL',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create index migrations for relation fields', async () => {
|
||||||
|
const fieldMetadata: Pick<
|
||||||
|
FieldMetadataEntity<FieldMetadataType.RELATION>,
|
||||||
|
'id' | 'name' | 'type' | 'settings' | 'isCustom'
|
||||||
|
> = {
|
||||||
|
id: 'f2',
|
||||||
|
name: 'author',
|
||||||
|
type: FieldMetadataType.RELATION,
|
||||||
|
settings: {
|
||||||
|
relationType: RelationType.MANY_TO_ONE,
|
||||||
|
joinColumnName: 'authorId',
|
||||||
|
},
|
||||||
|
isCustom: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const objectMetadata = {
|
||||||
|
id: 'obj2',
|
||||||
|
workspaceId: 'ws1',
|
||||||
|
nameSingular: 'Attachment',
|
||||||
|
fields: [fieldMetadata],
|
||||||
|
isCustom: false,
|
||||||
|
};
|
||||||
|
const indexMetadata = {
|
||||||
|
name: 'idx_rel',
|
||||||
|
isUnique: false,
|
||||||
|
indexType: 'BTREE',
|
||||||
|
indexWhereClause: null,
|
||||||
|
indexFieldMetadatas: [{ fieldMetadataId: 'f2', order: 0 }],
|
||||||
|
} as IndexMetadataEntity;
|
||||||
|
const map = new Map([[objectMetadata, [indexMetadata]]]);
|
||||||
|
const result = (await createIndexMigration(map)) as any;
|
||||||
|
|
||||||
|
const firstMigration = result[0].migrations[0];
|
||||||
|
|
||||||
|
expect(firstMigration.indexes[0].columns).toEqual(['authorId']);
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,161 @@
|
|||||||
|
import { FieldMetadataType } from 'twenty-shared/types';
|
||||||
|
import { isDefined } from 'twenty-shared/utils';
|
||||||
|
|
||||||
|
import { CompositeType } from 'src/engine/metadata-modules/field-metadata/interfaces/composite-type.interface';
|
||||||
|
|
||||||
|
import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types';
|
||||||
|
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||||
|
import { computeCompositeColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util';
|
||||||
|
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
|
||||||
|
import { IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-metadata.entity';
|
||||||
|
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||||
|
import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util';
|
||||||
|
import {
|
||||||
|
WorkspaceMigrationEntity,
|
||||||
|
WorkspaceMigrationIndexActionType,
|
||||||
|
WorkspaceMigrationTableActionType,
|
||||||
|
} from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
||||||
|
import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util';
|
||||||
|
import { isFieldMetadataEntityOfType } from 'src/engine/utils/is-field-metadata-of-type.util';
|
||||||
|
|
||||||
|
export const createIndexMigration = async (
|
||||||
|
indexMetadataByObjectMetadataMap: Map<
|
||||||
|
Pick<
|
||||||
|
ObjectMetadataEntity,
|
||||||
|
'id' | 'workspaceId' | 'nameSingular' | 'isCustom'
|
||||||
|
> & {
|
||||||
|
fields: Pick<FieldMetadataEntity, 'id' | 'name' | 'type' | 'settings'>[];
|
||||||
|
},
|
||||||
|
IndexMetadataEntity[]
|
||||||
|
>,
|
||||||
|
): Promise<Partial<WorkspaceMigrationEntity>[]> => {
|
||||||
|
const workspaceMigrations: Partial<WorkspaceMigrationEntity>[] = [];
|
||||||
|
|
||||||
|
for (const [
|
||||||
|
objectMetadata,
|
||||||
|
indexMetadataCollection,
|
||||||
|
] of indexMetadataByObjectMetadataMap) {
|
||||||
|
const targetTable = computeObjectTargetTable(objectMetadata);
|
||||||
|
|
||||||
|
const fieldsById = Object.fromEntries(
|
||||||
|
objectMetadata.fields.map((field) => [field.id, field]),
|
||||||
|
);
|
||||||
|
|
||||||
|
const indexes = indexMetadataCollection.map((indexMetadata) => {
|
||||||
|
const columns = indexMetadata.indexFieldMetadatas
|
||||||
|
.sort((a, b) => a.order - b.order)
|
||||||
|
.map((indexFieldMetadata) => {
|
||||||
|
const fieldMetadata = fieldsById[indexFieldMetadata.fieldMetadataId];
|
||||||
|
|
||||||
|
if (!fieldMetadata) {
|
||||||
|
throw new Error(
|
||||||
|
`Field metadata with id ${indexFieldMetadata.fieldMetadataId} not found in object metadata with id ${objectMetadata.id}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
isFieldMetadataEntityOfType(
|
||||||
|
fieldMetadata,
|
||||||
|
FieldMetadataType.RELATION,
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
if (!fieldMetadata.settings) {
|
||||||
|
throw new Error(
|
||||||
|
`Join column name is not supported for relation fields`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fieldMetadata.settings.joinColumnName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isCompositeFieldMetadataType(fieldMetadata.type)) {
|
||||||
|
return fieldMetadata.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
const compositeType = compositeTypeDefinitions.get(
|
||||||
|
fieldMetadata.type,
|
||||||
|
) as CompositeType;
|
||||||
|
|
||||||
|
const columns = compositeType.properties
|
||||||
|
.filter((property) => property.isIncludedInUniqueConstraint)
|
||||||
|
.map((property) =>
|
||||||
|
computeCompositeColumnName(fieldMetadata, property),
|
||||||
|
);
|
||||||
|
|
||||||
|
return columns;
|
||||||
|
})
|
||||||
|
.flat()
|
||||||
|
.filter(isDefined);
|
||||||
|
|
||||||
|
const defaultWhereClause = indexMetadata.isUnique
|
||||||
|
? `${columns.map((column) => `"${column}"`).join(" != '' AND ")} != '' AND "deletedAt" IS NULL`
|
||||||
|
: null;
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: indexMetadata.name,
|
||||||
|
action: WorkspaceMigrationIndexActionType.CREATE,
|
||||||
|
isUnique: indexMetadata.isUnique,
|
||||||
|
columns,
|
||||||
|
type: indexMetadata.indexType,
|
||||||
|
where: indexMetadata.indexWhereClause ?? defaultWhereClause,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
workspaceMigrations.push({
|
||||||
|
workspaceId: objectMetadata.workspaceId,
|
||||||
|
name: generateMigrationName(
|
||||||
|
`create-${objectMetadata.nameSingular}-indexes`,
|
||||||
|
),
|
||||||
|
isCustom: false,
|
||||||
|
migrations: [
|
||||||
|
{
|
||||||
|
name: targetTable,
|
||||||
|
action: WorkspaceMigrationTableActionType.ALTER_INDEXES,
|
||||||
|
indexes,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return workspaceMigrations;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deleteIndexMigration = async (
|
||||||
|
indexMetadataByObjectMetadataMap: Map<
|
||||||
|
ObjectMetadataEntity,
|
||||||
|
IndexMetadataEntity[]
|
||||||
|
>,
|
||||||
|
): Promise<Partial<WorkspaceMigrationEntity>[]> => {
|
||||||
|
const workspaceMigrations: Partial<WorkspaceMigrationEntity>[] = [];
|
||||||
|
|
||||||
|
for (const [
|
||||||
|
objectMetadata,
|
||||||
|
indexMetadataCollection,
|
||||||
|
] of indexMetadataByObjectMetadataMap) {
|
||||||
|
const targetTable = computeObjectTargetTable(objectMetadata);
|
||||||
|
|
||||||
|
const indexes = indexMetadataCollection.map((indexMetadata) => ({
|
||||||
|
name: indexMetadata.name,
|
||||||
|
action: WorkspaceMigrationIndexActionType.DROP,
|
||||||
|
columns: [],
|
||||||
|
isUnique: indexMetadata.isUnique,
|
||||||
|
}));
|
||||||
|
|
||||||
|
workspaceMigrations.push({
|
||||||
|
workspaceId: objectMetadata.workspaceId,
|
||||||
|
name: generateMigrationName(
|
||||||
|
`delete-${objectMetadata.nameSingular}-indexes`,
|
||||||
|
),
|
||||||
|
isCustom: false,
|
||||||
|
migrations: [
|
||||||
|
{
|
||||||
|
name: targetTable,
|
||||||
|
action: WorkspaceMigrationTableActionType.ALTER_INDEXES,
|
||||||
|
indexes,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return workspaceMigrations;
|
||||||
|
};
|
||||||
@ -1,20 +1,14 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
import { CompositeType } from 'src/engine/metadata-modules/field-metadata/interfaces/composite-type.interface';
|
|
||||||
import { WorkspaceMigrationBuilderAction } from 'src/engine/workspace-manager/workspace-migration-builder/interfaces/workspace-migration-builder-action.interface';
|
import { WorkspaceMigrationBuilderAction } from 'src/engine/workspace-manager/workspace-migration-builder/interfaces/workspace-migration-builder-action.interface';
|
||||||
|
|
||||||
import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types';
|
|
||||||
import { computeCompositeColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util';
|
|
||||||
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
|
|
||||||
import { IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-metadata.entity';
|
import { IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-metadata.entity';
|
||||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||||
import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util';
|
import { WorkspaceMigrationEntity } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
||||||
import {
|
import {
|
||||||
WorkspaceMigrationEntity,
|
createIndexMigration,
|
||||||
WorkspaceMigrationIndexActionType,
|
deleteIndexMigration,
|
||||||
WorkspaceMigrationTableActionType,
|
} from 'src/engine/workspace-manager/workspace-migration-builder/factories/utils/workspace-migration-index.factory.utils';
|
||||||
} from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
|
||||||
import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class WorkspaceMigrationIndexFactory {
|
export class WorkspaceMigrationIndexFactory {
|
||||||
@ -55,131 +49,11 @@ export class WorkspaceMigrationIndexFactory {
|
|||||||
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case WorkspaceMigrationBuilderAction.CREATE:
|
case WorkspaceMigrationBuilderAction.CREATE:
|
||||||
return this.createIndexMigration(indexMetadataByObjectMetadataMap);
|
return createIndexMigration(indexMetadataByObjectMetadataMap);
|
||||||
case WorkspaceMigrationBuilderAction.DELETE:
|
case WorkspaceMigrationBuilderAction.DELETE:
|
||||||
return this.deleteIndexMigration(indexMetadataByObjectMetadataMap);
|
return deleteIndexMigration(indexMetadataByObjectMetadataMap);
|
||||||
default:
|
default:
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createIndexMigration(
|
|
||||||
indexMetadataByObjectMetadataMap: Map<
|
|
||||||
ObjectMetadataEntity,
|
|
||||||
IndexMetadataEntity[]
|
|
||||||
>,
|
|
||||||
): Promise<Partial<WorkspaceMigrationEntity>[]> {
|
|
||||||
const workspaceMigrations: Partial<WorkspaceMigrationEntity>[] = [];
|
|
||||||
|
|
||||||
for (const [
|
|
||||||
objectMetadata,
|
|
||||||
indexMetadataCollection,
|
|
||||||
] of indexMetadataByObjectMetadataMap) {
|
|
||||||
const targetTable = computeObjectTargetTable(objectMetadata);
|
|
||||||
|
|
||||||
const fieldsById = Object.fromEntries(
|
|
||||||
objectMetadata.fields.map((field) => [field.id, field]),
|
|
||||||
);
|
|
||||||
|
|
||||||
const indexes = indexMetadataCollection.map((indexMetadata) => {
|
|
||||||
const columns = indexMetadata.indexFieldMetadatas
|
|
||||||
.sort((a, b) => a.order - b.order)
|
|
||||||
.map((indexFieldMetadata) => {
|
|
||||||
const fieldMetadata =
|
|
||||||
fieldsById[indexFieldMetadata.fieldMetadataId];
|
|
||||||
|
|
||||||
if (!fieldMetadata) {
|
|
||||||
throw new Error(
|
|
||||||
`Field metadata with id ${indexFieldMetadata.fieldMetadataId} not found in object metadata with id ${objectMetadata.id}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isCompositeFieldMetadataType(fieldMetadata.type)) {
|
|
||||||
return fieldMetadata.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
const compositeType = compositeTypeDefinitions.get(
|
|
||||||
fieldMetadata.type,
|
|
||||||
) as CompositeType;
|
|
||||||
|
|
||||||
return compositeType.properties
|
|
||||||
.filter((property) => property.isIncludedInUniqueConstraint)
|
|
||||||
.map((property) =>
|
|
||||||
computeCompositeColumnName(fieldMetadata, property),
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.flat();
|
|
||||||
|
|
||||||
const defaultWhereClause = indexMetadata.isUnique
|
|
||||||
? `${columns.map((column) => `"${column}"`).join(" != '' AND ")} != '' AND "deletedAt" IS NULL`
|
|
||||||
: null;
|
|
||||||
|
|
||||||
return {
|
|
||||||
name: indexMetadata.name,
|
|
||||||
action: WorkspaceMigrationIndexActionType.CREATE,
|
|
||||||
isUnique: indexMetadata.isUnique,
|
|
||||||
columns,
|
|
||||||
type: indexMetadata.indexType,
|
|
||||||
where: indexMetadata.indexWhereClause ?? defaultWhereClause,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
workspaceMigrations.push({
|
|
||||||
workspaceId: objectMetadata.workspaceId,
|
|
||||||
name: generateMigrationName(
|
|
||||||
`create-${objectMetadata.nameSingular}-indexes`,
|
|
||||||
),
|
|
||||||
isCustom: false,
|
|
||||||
migrations: [
|
|
||||||
{
|
|
||||||
name: targetTable,
|
|
||||||
action: WorkspaceMigrationTableActionType.ALTER_INDEXES,
|
|
||||||
indexes,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return workspaceMigrations;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async deleteIndexMigration(
|
|
||||||
indexMetadataByObjectMetadataMap: Map<
|
|
||||||
ObjectMetadataEntity,
|
|
||||||
IndexMetadataEntity[]
|
|
||||||
>,
|
|
||||||
): Promise<Partial<WorkspaceMigrationEntity>[]> {
|
|
||||||
const workspaceMigrations: Partial<WorkspaceMigrationEntity>[] = [];
|
|
||||||
|
|
||||||
for (const [
|
|
||||||
objectMetadata,
|
|
||||||
indexMetadataCollection,
|
|
||||||
] of indexMetadataByObjectMetadataMap) {
|
|
||||||
const targetTable = computeObjectTargetTable(objectMetadata);
|
|
||||||
|
|
||||||
const indexes = indexMetadataCollection.map((indexMetadata) => ({
|
|
||||||
name: indexMetadata.name,
|
|
||||||
action: WorkspaceMigrationIndexActionType.DROP,
|
|
||||||
columns: [],
|
|
||||||
isUnique: indexMetadata.isUnique,
|
|
||||||
}));
|
|
||||||
|
|
||||||
workspaceMigrations.push({
|
|
||||||
workspaceId: objectMetadata.workspaceId,
|
|
||||||
name: generateMigrationName(
|
|
||||||
`delete-${objectMetadata.nameSingular}-indexes`,
|
|
||||||
),
|
|
||||||
isCustom: false,
|
|
||||||
migrations: [
|
|
||||||
{
|
|
||||||
name: targetTable,
|
|
||||||
action: WorkspaceMigrationTableActionType.ALTER_INDEXES,
|
|
||||||
indexes,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return workspaceMigrations;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -69,46 +69,30 @@ export class StandardIndexFactory {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return workspaceIndexMetadataArgsCollection.map(
|
||||||
workspaceIndexMetadataArgsCollection
|
(workspaceIndexMetadataArgs) => {
|
||||||
.map((workspaceIndexMetadataArgs) => {
|
const objectMetadata =
|
||||||
const objectMetadata =
|
originalStandardObjectMetadataMap[workspaceEntity.nameSingular];
|
||||||
originalStandardObjectMetadataMap[workspaceEntity.nameSingular];
|
|
||||||
|
|
||||||
if (!objectMetadata) {
|
if (!objectMetadata) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Object metadata not found for ${workspaceEntity.nameSingular}`,
|
`Object metadata not found for ${workspaceEntity.nameSingular}`,
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const indexMetadata: PartialIndexMetadata = {
|
|
||||||
workspaceId: context.workspaceId,
|
|
||||||
objectMetadataId: objectMetadata.id,
|
|
||||||
name: workspaceIndexMetadataArgs.name,
|
|
||||||
columns: workspaceIndexMetadataArgs.columns,
|
|
||||||
isUnique: workspaceIndexMetadataArgs.isUnique,
|
|
||||||
isCustom: false,
|
|
||||||
indexWhereClause: workspaceIndexMetadataArgs.whereClause,
|
|
||||||
indexType: workspaceIndexMetadataArgs.type,
|
|
||||||
};
|
|
||||||
|
|
||||||
return indexMetadata;
|
|
||||||
})
|
|
||||||
// TODO: remove this filter when we have a way to handle index on relations
|
|
||||||
.filter((workspaceIndexMetadataArgs) => {
|
|
||||||
const objectMetadata =
|
|
||||||
originalStandardObjectMetadataMap[workspaceEntity.nameSingular];
|
|
||||||
|
|
||||||
const hasAllFields = workspaceIndexMetadataArgs.columns.every(
|
|
||||||
(expectedField) => {
|
|
||||||
return objectMetadata.fields.some(
|
|
||||||
(field) => field.name === expectedField,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return hasAllFields;
|
const indexMetadata: PartialIndexMetadata = {
|
||||||
})
|
workspaceId: context.workspaceId,
|
||||||
|
objectMetadataId: objectMetadata.id,
|
||||||
|
name: workspaceIndexMetadataArgs.name,
|
||||||
|
columns: workspaceIndexMetadataArgs.columns,
|
||||||
|
isUnique: workspaceIndexMetadataArgs.isUnique,
|
||||||
|
isCustom: false,
|
||||||
|
indexWhereClause: workspaceIndexMetadataArgs.whereClause,
|
||||||
|
indexType: workspaceIndexMetadataArgs.type,
|
||||||
|
};
|
||||||
|
|
||||||
|
return indexMetadata;
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user