Index v2 side effects (#14567)
# Introduction Honestly this implem is a mess, discussing a potential side effect handler with @weiko before the build and run that would handle each side effect per entity and operation Handling: - [ ] unique index is generated when a field is updated with the `isUnique` - [x] an index is generated when a relation is created - [x] search vector index creation on custom object creation - [x] renaming a field metadata or an object should re-create all related indexes which are composed by their namings - [x] delete object should remove any related indexes - [x] delete field should update related indexes ( if index ends up empty it should be removed ) - [ ] on object renaming that contains morph fields -> triggers update field -> trigger index recompute - [x] on update name renaming should recompute all related indexes ## TODO - [x] Integration testing - [ ] Refactor the index maps cache to be storing a `idsByObjectMetadataId` - [x] Refactor deterministic name to use order sorting - [x] Remove flat index from flat object ## What's next Will handle morph indexes in a new dedicated PR for the moment will stick to this Same for the cache improvement and uniqueness
This commit is contained in:
+2
-2
@@ -208,14 +208,14 @@ export class WorkspaceMigrationBuildOrchestratorService {
|
||||
relatedFlatEntityMapsKeys,
|
||||
actions: [
|
||||
// Object and fields
|
||||
...orchestratorActionsReport.fieldMetadata.deleted,
|
||||
...orchestratorActionsReport.index.deleted,
|
||||
...orchestratorActionsReport.fieldMetadata.deleted,
|
||||
...orchestratorActionsReport.objectMetadata.deleted,
|
||||
...orchestratorActionsReport.objectMetadata.created,
|
||||
...orchestratorActionsReport.index.created,
|
||||
...orchestratorActionsReport.objectMetadata.updated,
|
||||
...orchestratorActionsReport.fieldMetadata.created,
|
||||
...orchestratorActionsReport.fieldMetadata.updated,
|
||||
...orchestratorActionsReport.index.created,
|
||||
...orchestratorActionsReport.index.updated,
|
||||
///
|
||||
|
||||
|
||||
-647
@@ -2408,653 +2408,6 @@ exports[`Workspace migration builder object actions test suite It should build a
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Workspace migration builder object actions test suite It should build a create_object and create_index actions for each of this fieldMetadata 1`] = `
|
||||
{
|
||||
"created": [],
|
||||
"deleted": [],
|
||||
"updated": [],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Workspace migration builder object actions test suite It should build a create_object and create_index actions for each of this fieldMetadata 2`] = `
|
||||
{
|
||||
"created": [
|
||||
{
|
||||
"createFieldActions": [
|
||||
{
|
||||
"flatFieldMetadata": {
|
||||
"createdAt": Any<String>,
|
||||
"defaultValue": "uuid",
|
||||
"description": "Id",
|
||||
"flatRelationTargetFieldMetadata": null,
|
||||
"flatRelationTargetObjectMetadata": null,
|
||||
"icon": "Icon123",
|
||||
"id": Any<String>,
|
||||
"isActive": true,
|
||||
"isCustom": false,
|
||||
"isLabelSyncedWithName": false,
|
||||
"isNullable": false,
|
||||
"isSystem": true,
|
||||
"isUIReadOnly": false,
|
||||
"isUnique": false,
|
||||
"label": "Id",
|
||||
"morphId": null,
|
||||
"name": "id",
|
||||
"objectMetadataId": Any<String>,
|
||||
"options": null,
|
||||
"relationTargetFieldMetadataId": null,
|
||||
"relationTargetObjectMetadataId": null,
|
||||
"settings": null,
|
||||
"standardId": Any<String>,
|
||||
"standardOverrides": null,
|
||||
"type": "UUID",
|
||||
"universalIdentifier": Any<String>,
|
||||
"updatedAt": Any<String>,
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
"type": "create_field",
|
||||
},
|
||||
{
|
||||
"flatFieldMetadata": {
|
||||
"createdAt": Any<String>,
|
||||
"defaultValue": "'Untitled'",
|
||||
"description": "Name",
|
||||
"flatRelationTargetFieldMetadata": null,
|
||||
"flatRelationTargetObjectMetadata": null,
|
||||
"icon": "IconAbc",
|
||||
"id": Any<String>,
|
||||
"isActive": true,
|
||||
"isCustom": false,
|
||||
"isLabelSyncedWithName": false,
|
||||
"isNullable": false,
|
||||
"isSystem": false,
|
||||
"isUIReadOnly": false,
|
||||
"isUnique": false,
|
||||
"label": "Name",
|
||||
"morphId": null,
|
||||
"name": "name",
|
||||
"objectMetadataId": Any<String>,
|
||||
"options": null,
|
||||
"relationTargetFieldMetadataId": null,
|
||||
"relationTargetObjectMetadataId": null,
|
||||
"settings": null,
|
||||
"standardId": Any<String>,
|
||||
"standardOverrides": null,
|
||||
"type": "TEXT",
|
||||
"universalIdentifier": Any<String>,
|
||||
"updatedAt": Any<String>,
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
"type": "create_field",
|
||||
},
|
||||
{
|
||||
"flatFieldMetadata": {
|
||||
"createdAt": Any<String>,
|
||||
"defaultValue": "now",
|
||||
"description": "Creation date",
|
||||
"flatRelationTargetFieldMetadata": null,
|
||||
"flatRelationTargetObjectMetadata": null,
|
||||
"icon": "IconCalendar",
|
||||
"id": Any<String>,
|
||||
"isActive": true,
|
||||
"isCustom": false,
|
||||
"isLabelSyncedWithName": false,
|
||||
"isNullable": false,
|
||||
"isSystem": false,
|
||||
"isUIReadOnly": false,
|
||||
"isUnique": false,
|
||||
"label": "Creation date",
|
||||
"morphId": null,
|
||||
"name": "createdAt",
|
||||
"objectMetadataId": Any<String>,
|
||||
"options": null,
|
||||
"relationTargetFieldMetadataId": null,
|
||||
"relationTargetObjectMetadataId": null,
|
||||
"settings": null,
|
||||
"standardId": Any<String>,
|
||||
"standardOverrides": null,
|
||||
"type": "DATE_TIME",
|
||||
"universalIdentifier": Any<String>,
|
||||
"updatedAt": Any<String>,
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
"type": "create_field",
|
||||
},
|
||||
{
|
||||
"flatFieldMetadata": {
|
||||
"createdAt": Any<String>,
|
||||
"defaultValue": "now",
|
||||
"description": "Last time the record was changed",
|
||||
"flatRelationTargetFieldMetadata": null,
|
||||
"flatRelationTargetObjectMetadata": null,
|
||||
"icon": "IconCalendarClock",
|
||||
"id": Any<String>,
|
||||
"isActive": true,
|
||||
"isCustom": false,
|
||||
"isLabelSyncedWithName": false,
|
||||
"isNullable": false,
|
||||
"isSystem": false,
|
||||
"isUIReadOnly": false,
|
||||
"isUnique": false,
|
||||
"label": "Last update",
|
||||
"morphId": null,
|
||||
"name": "updatedAt",
|
||||
"objectMetadataId": Any<String>,
|
||||
"options": null,
|
||||
"relationTargetFieldMetadataId": null,
|
||||
"relationTargetObjectMetadataId": null,
|
||||
"settings": null,
|
||||
"standardId": Any<String>,
|
||||
"standardOverrides": null,
|
||||
"type": "DATE_TIME",
|
||||
"universalIdentifier": Any<String>,
|
||||
"updatedAt": Any<String>,
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
"type": "create_field",
|
||||
},
|
||||
{
|
||||
"flatFieldMetadata": {
|
||||
"createdAt": Any<String>,
|
||||
"defaultValue": null,
|
||||
"description": "Deletion date",
|
||||
"flatRelationTargetFieldMetadata": null,
|
||||
"flatRelationTargetObjectMetadata": null,
|
||||
"icon": "IconCalendarClock",
|
||||
"id": Any<String>,
|
||||
"isActive": true,
|
||||
"isCustom": false,
|
||||
"isLabelSyncedWithName": false,
|
||||
"isNullable": true,
|
||||
"isSystem": false,
|
||||
"isUIReadOnly": false,
|
||||
"isUnique": false,
|
||||
"label": "Deleted at",
|
||||
"morphId": null,
|
||||
"name": "deletedAt",
|
||||
"objectMetadataId": Any<String>,
|
||||
"options": null,
|
||||
"relationTargetFieldMetadataId": null,
|
||||
"relationTargetObjectMetadataId": null,
|
||||
"settings": null,
|
||||
"standardId": Any<String>,
|
||||
"standardOverrides": null,
|
||||
"type": "DATE_TIME",
|
||||
"universalIdentifier": Any<String>,
|
||||
"updatedAt": Any<String>,
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
"type": "create_field",
|
||||
},
|
||||
{
|
||||
"flatFieldMetadata": {
|
||||
"createdAt": Any<String>,
|
||||
"defaultValue": {
|
||||
"name": "''",
|
||||
"source": "'MANUAL'",
|
||||
},
|
||||
"description": "The creator of the record",
|
||||
"flatRelationTargetFieldMetadata": null,
|
||||
"flatRelationTargetObjectMetadata": null,
|
||||
"icon": "IconCreativeCommonsSa",
|
||||
"id": Any<String>,
|
||||
"isActive": true,
|
||||
"isCustom": false,
|
||||
"isLabelSyncedWithName": false,
|
||||
"isNullable": false,
|
||||
"isSystem": false,
|
||||
"isUIReadOnly": false,
|
||||
"isUnique": false,
|
||||
"label": "Created by",
|
||||
"morphId": null,
|
||||
"name": "createdBy",
|
||||
"objectMetadataId": Any<String>,
|
||||
"options": null,
|
||||
"relationTargetFieldMetadataId": null,
|
||||
"relationTargetObjectMetadataId": null,
|
||||
"settings": null,
|
||||
"standardId": Any<String>,
|
||||
"standardOverrides": null,
|
||||
"type": "ACTOR",
|
||||
"universalIdentifier": Any<String>,
|
||||
"updatedAt": Any<String>,
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
"type": "create_field",
|
||||
},
|
||||
{
|
||||
"flatFieldMetadata": {
|
||||
"createdAt": Any<String>,
|
||||
"defaultValue": 0,
|
||||
"description": "Position",
|
||||
"flatRelationTargetFieldMetadata": null,
|
||||
"flatRelationTargetObjectMetadata": null,
|
||||
"icon": "IconHierarchy2",
|
||||
"id": Any<String>,
|
||||
"isActive": true,
|
||||
"isCustom": false,
|
||||
"isLabelSyncedWithName": false,
|
||||
"isNullable": false,
|
||||
"isSystem": true,
|
||||
"isUIReadOnly": false,
|
||||
"isUnique": false,
|
||||
"label": "Position",
|
||||
"morphId": null,
|
||||
"name": "position",
|
||||
"objectMetadataId": Any<String>,
|
||||
"options": null,
|
||||
"relationTargetFieldMetadataId": null,
|
||||
"relationTargetObjectMetadataId": null,
|
||||
"settings": null,
|
||||
"standardId": Any<String>,
|
||||
"standardOverrides": null,
|
||||
"type": "POSITION",
|
||||
"universalIdentifier": Any<String>,
|
||||
"updatedAt": Any<String>,
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
"type": "create_field",
|
||||
},
|
||||
{
|
||||
"flatFieldMetadata": {
|
||||
"createdAt": Any<String>,
|
||||
"defaultValue": null,
|
||||
"description": "TimelineActivities tied to the Rocket",
|
||||
"flatRelationTargetFieldMetadata": {
|
||||
"createdAt": Any<String>,
|
||||
"defaultValue": null,
|
||||
"description": "TimelineActivities Rocket",
|
||||
"icon": "IconBuildingSkyscraper",
|
||||
"id": Any<String>,
|
||||
"isActive": true,
|
||||
"isCustom": false,
|
||||
"isLabelSyncedWithName": false,
|
||||
"isNullable": true,
|
||||
"isSystem": true,
|
||||
"isUIReadOnly": false,
|
||||
"isUnique": false,
|
||||
"label": "Rocket",
|
||||
"morphId": null,
|
||||
"name": "rocket",
|
||||
"objectMetadataId": Any<String>,
|
||||
"options": null,
|
||||
"relationTargetFieldMetadataId": Any<String>,
|
||||
"relationTargetObjectMetadataId": Any<String>,
|
||||
"settings": {
|
||||
"joinColumnName": "rocketId",
|
||||
"onDelete": "CASCADE",
|
||||
"relationType": "MANY_TO_ONE",
|
||||
},
|
||||
"standardId": Any<String>,
|
||||
"standardOverrides": null,
|
||||
"type": "RELATION",
|
||||
"universalIdentifier": Any<String>,
|
||||
"updatedAt": Any<String>,
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
"flatRelationTargetObjectMetadata": null,
|
||||
"icon": "IconTimelineEvent",
|
||||
"id": Any<String>,
|
||||
"isActive": true,
|
||||
"isCustom": false,
|
||||
"isLabelSyncedWithName": false,
|
||||
"isNullable": true,
|
||||
"isSystem": true,
|
||||
"isUIReadOnly": false,
|
||||
"isUnique": false,
|
||||
"label": "TimelineActivities",
|
||||
"morphId": null,
|
||||
"name": "timelineActivities",
|
||||
"objectMetadataId": Any<String>,
|
||||
"options": null,
|
||||
"relationTargetFieldMetadataId": Any<String>,
|
||||
"relationTargetObjectMetadataId": Any<String>,
|
||||
"settings": {
|
||||
"relationType": "ONE_TO_MANY",
|
||||
},
|
||||
"standardId": Any<String>,
|
||||
"standardOverrides": null,
|
||||
"type": "RELATION",
|
||||
"universalIdentifier": Any<String>,
|
||||
"updatedAt": Any<String>,
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
"type": "create_field",
|
||||
},
|
||||
{
|
||||
"flatFieldMetadata": {
|
||||
"createdAt": Any<String>,
|
||||
"defaultValue": null,
|
||||
"description": "Favorites tied to the Rocket",
|
||||
"flatRelationTargetFieldMetadata": {
|
||||
"createdAt": Any<String>,
|
||||
"defaultValue": null,
|
||||
"description": "Favorites Rocket",
|
||||
"icon": "IconBuildingSkyscraper",
|
||||
"id": Any<String>,
|
||||
"isActive": true,
|
||||
"isCustom": false,
|
||||
"isLabelSyncedWithName": false,
|
||||
"isNullable": true,
|
||||
"isSystem": true,
|
||||
"isUIReadOnly": false,
|
||||
"isUnique": false,
|
||||
"label": "Rocket",
|
||||
"morphId": null,
|
||||
"name": "rocket",
|
||||
"objectMetadataId": Any<String>,
|
||||
"options": null,
|
||||
"relationTargetFieldMetadataId": Any<String>,
|
||||
"relationTargetObjectMetadataId": Any<String>,
|
||||
"settings": {
|
||||
"joinColumnName": "rocketId",
|
||||
"onDelete": "CASCADE",
|
||||
"relationType": "MANY_TO_ONE",
|
||||
},
|
||||
"standardId": Any<String>,
|
||||
"standardOverrides": null,
|
||||
"type": "RELATION",
|
||||
"universalIdentifier": Any<String>,
|
||||
"updatedAt": Any<String>,
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
"flatRelationTargetObjectMetadata": null,
|
||||
"icon": "IconHeart",
|
||||
"id": Any<String>,
|
||||
"isActive": true,
|
||||
"isCustom": false,
|
||||
"isLabelSyncedWithName": false,
|
||||
"isNullable": true,
|
||||
"isSystem": true,
|
||||
"isUIReadOnly": false,
|
||||
"isUnique": false,
|
||||
"label": "Favorites",
|
||||
"morphId": null,
|
||||
"name": "favorites",
|
||||
"objectMetadataId": Any<String>,
|
||||
"options": null,
|
||||
"relationTargetFieldMetadataId": Any<String>,
|
||||
"relationTargetObjectMetadataId": Any<String>,
|
||||
"settings": {
|
||||
"relationType": "ONE_TO_MANY",
|
||||
},
|
||||
"standardId": Any<String>,
|
||||
"standardOverrides": null,
|
||||
"type": "RELATION",
|
||||
"universalIdentifier": Any<String>,
|
||||
"updatedAt": Any<String>,
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
"type": "create_field",
|
||||
},
|
||||
{
|
||||
"flatFieldMetadata": {
|
||||
"createdAt": Any<String>,
|
||||
"defaultValue": null,
|
||||
"description": "Attachments tied to the Rocket",
|
||||
"flatRelationTargetFieldMetadata": {
|
||||
"createdAt": Any<String>,
|
||||
"defaultValue": null,
|
||||
"description": "Attachments Rocket",
|
||||
"icon": "IconBuildingSkyscraper",
|
||||
"id": Any<String>,
|
||||
"isActive": true,
|
||||
"isCustom": false,
|
||||
"isLabelSyncedWithName": false,
|
||||
"isNullable": true,
|
||||
"isSystem": true,
|
||||
"isUIReadOnly": false,
|
||||
"isUnique": false,
|
||||
"label": "Rocket",
|
||||
"morphId": null,
|
||||
"name": "rocket",
|
||||
"objectMetadataId": Any<String>,
|
||||
"options": null,
|
||||
"relationTargetFieldMetadataId": Any<String>,
|
||||
"relationTargetObjectMetadataId": Any<String>,
|
||||
"settings": {
|
||||
"joinColumnName": "rocketId",
|
||||
"onDelete": "CASCADE",
|
||||
"relationType": "MANY_TO_ONE",
|
||||
},
|
||||
"standardId": Any<String>,
|
||||
"standardOverrides": null,
|
||||
"type": "RELATION",
|
||||
"universalIdentifier": Any<String>,
|
||||
"updatedAt": Any<String>,
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
"flatRelationTargetObjectMetadata": null,
|
||||
"icon": "IconFileImport",
|
||||
"id": Any<String>,
|
||||
"isActive": true,
|
||||
"isCustom": false,
|
||||
"isLabelSyncedWithName": false,
|
||||
"isNullable": true,
|
||||
"isSystem": true,
|
||||
"isUIReadOnly": false,
|
||||
"isUnique": false,
|
||||
"label": "Attachments",
|
||||
"morphId": null,
|
||||
"name": "attachments",
|
||||
"objectMetadataId": Any<String>,
|
||||
"options": null,
|
||||
"relationTargetFieldMetadataId": Any<String>,
|
||||
"relationTargetObjectMetadataId": Any<String>,
|
||||
"settings": {
|
||||
"relationType": "ONE_TO_MANY",
|
||||
},
|
||||
"standardId": Any<String>,
|
||||
"standardOverrides": null,
|
||||
"type": "RELATION",
|
||||
"universalIdentifier": Any<String>,
|
||||
"updatedAt": Any<String>,
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
"type": "create_field",
|
||||
},
|
||||
{
|
||||
"flatFieldMetadata": {
|
||||
"createdAt": Any<String>,
|
||||
"defaultValue": null,
|
||||
"description": "NoteTargets tied to the Rocket",
|
||||
"flatRelationTargetFieldMetadata": {
|
||||
"createdAt": Any<String>,
|
||||
"defaultValue": null,
|
||||
"description": "NoteTargets Rocket",
|
||||
"icon": "IconBuildingSkyscraper",
|
||||
"id": Any<String>,
|
||||
"isActive": true,
|
||||
"isCustom": false,
|
||||
"isLabelSyncedWithName": false,
|
||||
"isNullable": true,
|
||||
"isSystem": true,
|
||||
"isUIReadOnly": false,
|
||||
"isUnique": false,
|
||||
"label": "Rocket",
|
||||
"morphId": null,
|
||||
"name": "rocket",
|
||||
"objectMetadataId": Any<String>,
|
||||
"options": null,
|
||||
"relationTargetFieldMetadataId": Any<String>,
|
||||
"relationTargetObjectMetadataId": Any<String>,
|
||||
"settings": {
|
||||
"joinColumnName": "rocketId",
|
||||
"onDelete": "CASCADE",
|
||||
"relationType": "MANY_TO_ONE",
|
||||
},
|
||||
"standardId": Any<String>,
|
||||
"standardOverrides": null,
|
||||
"type": "RELATION",
|
||||
"universalIdentifier": Any<String>,
|
||||
"updatedAt": Any<String>,
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
"flatRelationTargetObjectMetadata": null,
|
||||
"icon": "IconCheckbox",
|
||||
"id": Any<String>,
|
||||
"isActive": true,
|
||||
"isCustom": false,
|
||||
"isLabelSyncedWithName": false,
|
||||
"isNullable": true,
|
||||
"isSystem": true,
|
||||
"isUIReadOnly": false,
|
||||
"isUnique": false,
|
||||
"label": "NoteTargets",
|
||||
"morphId": null,
|
||||
"name": "noteTargets",
|
||||
"objectMetadataId": Any<String>,
|
||||
"options": null,
|
||||
"relationTargetFieldMetadataId": Any<String>,
|
||||
"relationTargetObjectMetadataId": Any<String>,
|
||||
"settings": {
|
||||
"relationType": "ONE_TO_MANY",
|
||||
},
|
||||
"standardId": Any<String>,
|
||||
"standardOverrides": null,
|
||||
"type": "RELATION",
|
||||
"universalIdentifier": Any<String>,
|
||||
"updatedAt": Any<String>,
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
"type": "create_field",
|
||||
},
|
||||
{
|
||||
"flatFieldMetadata": {
|
||||
"createdAt": Any<String>,
|
||||
"defaultValue": null,
|
||||
"description": "TaskTargets tied to the Rocket",
|
||||
"flatRelationTargetFieldMetadata": {
|
||||
"createdAt": Any<String>,
|
||||
"defaultValue": null,
|
||||
"description": "TaskTargets Rocket",
|
||||
"icon": "IconBuildingSkyscraper",
|
||||
"id": Any<String>,
|
||||
"isActive": true,
|
||||
"isCustom": false,
|
||||
"isLabelSyncedWithName": false,
|
||||
"isNullable": true,
|
||||
"isSystem": true,
|
||||
"isUIReadOnly": false,
|
||||
"isUnique": false,
|
||||
"label": "Rocket",
|
||||
"morphId": null,
|
||||
"name": "rocket",
|
||||
"objectMetadataId": Any<String>,
|
||||
"options": null,
|
||||
"relationTargetFieldMetadataId": Any<String>,
|
||||
"relationTargetObjectMetadataId": Any<String>,
|
||||
"settings": {
|
||||
"joinColumnName": "rocketId",
|
||||
"onDelete": "CASCADE",
|
||||
"relationType": "MANY_TO_ONE",
|
||||
},
|
||||
"standardId": Any<String>,
|
||||
"standardOverrides": null,
|
||||
"type": "RELATION",
|
||||
"universalIdentifier": Any<String>,
|
||||
"updatedAt": Any<String>,
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
"flatRelationTargetObjectMetadata": null,
|
||||
"icon": "IconCheckbox",
|
||||
"id": Any<String>,
|
||||
"isActive": true,
|
||||
"isCustom": false,
|
||||
"isLabelSyncedWithName": false,
|
||||
"isNullable": true,
|
||||
"isSystem": true,
|
||||
"isUIReadOnly": false,
|
||||
"isUnique": false,
|
||||
"label": "TaskTargets",
|
||||
"morphId": null,
|
||||
"name": "taskTargets",
|
||||
"objectMetadataId": Any<String>,
|
||||
"options": null,
|
||||
"relationTargetFieldMetadataId": Any<String>,
|
||||
"relationTargetObjectMetadataId": Any<String>,
|
||||
"settings": {
|
||||
"relationType": "ONE_TO_MANY",
|
||||
},
|
||||
"standardId": Any<String>,
|
||||
"standardOverrides": null,
|
||||
"type": "RELATION",
|
||||
"universalIdentifier": Any<String>,
|
||||
"updatedAt": Any<String>,
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
"type": "create_field",
|
||||
},
|
||||
{
|
||||
"flatFieldMetadata": {
|
||||
"createdAt": Any<String>,
|
||||
"defaultValue": null,
|
||||
"description": "Field used for full-text search",
|
||||
"flatRelationTargetFieldMetadata": null,
|
||||
"flatRelationTargetObjectMetadata": null,
|
||||
"icon": null,
|
||||
"id": Any<String>,
|
||||
"isActive": false,
|
||||
"isCustom": false,
|
||||
"isLabelSyncedWithName": false,
|
||||
"isNullable": true,
|
||||
"isSystem": true,
|
||||
"isUIReadOnly": false,
|
||||
"isUnique": false,
|
||||
"label": "Search vector",
|
||||
"morphId": null,
|
||||
"name": "searchVector",
|
||||
"objectMetadataId": Any<String>,
|
||||
"options": null,
|
||||
"relationTargetFieldMetadataId": null,
|
||||
"relationTargetObjectMetadataId": null,
|
||||
"settings": null,
|
||||
"standardId": Any<String>,
|
||||
"standardOverrides": null,
|
||||
"type": "TS_VECTOR",
|
||||
"universalIdentifier": Any<String>,
|
||||
"updatedAt": Any<String>,
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
"type": "create_field",
|
||||
},
|
||||
],
|
||||
"flatObjectMetadataWithoutFields": {
|
||||
"createdAt": Any<String>,
|
||||
"description": "A rocket",
|
||||
"duplicateCriteria": null,
|
||||
"icon": "IconRocket",
|
||||
"id": Any<String>,
|
||||
"imageIdentifierFieldMetadataId": null,
|
||||
"isActive": true,
|
||||
"isAuditLogged": true,
|
||||
"isCustom": true,
|
||||
"isLabelSyncedWithName": false,
|
||||
"isRemote": false,
|
||||
"isSearchable": true,
|
||||
"isSystem": false,
|
||||
"isUIReadOnly": false,
|
||||
"labelIdentifierFieldMetadataId": Any<String>,
|
||||
"labelPlural": "Rockets",
|
||||
"labelSingular": "Rocket",
|
||||
"namePlural": "rockets",
|
||||
"nameSingular": "rocket",
|
||||
"shortcut": null,
|
||||
"standardId": null,
|
||||
"standardOverrides": null,
|
||||
"targetTableName": "DEPRECATED",
|
||||
"universalIdentifier": Any<String>,
|
||||
"updatedAt": Any<String>,
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
"type": "create_object",
|
||||
},
|
||||
],
|
||||
"deleted": [],
|
||||
"updated": [],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Workspace migration builder object actions test suite It should build a delete_object action with custom deactivated object 1`] = `
|
||||
{
|
||||
"created": [],
|
||||
|
||||
-26
@@ -1,4 +1,3 @@
|
||||
import { getFlatIndexMetadataMock } from 'src/engine/metadata-modules/flat-index-metadata/__mocks__/get-flat-index-metadata.mock';
|
||||
import { FLAT_OBJECT_METADATA_MAPS_MOCKS } from 'src/engine/metadata-modules/flat-object-metadata-maps/mocks/flat-object-metadata-maps.mock';
|
||||
import { deleteObjectFromFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/delete-object-from-flat-object-metadata-maps-or-throw.util';
|
||||
import { replaceFlatObjectMetadataInFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/replace-flat-object-metadata-in-flat-object-metadata-maps-or-throw.util';
|
||||
@@ -93,31 +92,6 @@ const CREATE_OBJECT_TEST_CASES: WorkspaceMigrationBuilderTestCase[] = [
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title:
|
||||
'It should build a create_object and create_index actions for each of this fieldMetadata',
|
||||
context: {
|
||||
input: {
|
||||
fromFlatObjectMetadataMaps:
|
||||
fromFlatObjectMetadatasToFlatObjectMetadataMaps([
|
||||
...STANDARD_RELATION_TARGET_FLAT_OBJECT_METADATA_MOCKS,
|
||||
]),
|
||||
toFlatObjectMetadataMaps:
|
||||
fromFlatObjectMetadatasToFlatObjectMetadataMaps([
|
||||
...STANDARD_RELATION_TARGET_FLAT_OBJECT_METADATA_MOCKS,
|
||||
{
|
||||
...ROCKET_FLAT_OBJECT_MOCK,
|
||||
flatIndexMetadatas: [
|
||||
getFlatIndexMetadataMock({
|
||||
objectMetadataId: ROCKET_FLAT_OBJECT_MOCK.id,
|
||||
universalIdentifier: 'field-metadata-unique-identifier-1',
|
||||
}),
|
||||
],
|
||||
},
|
||||
]),
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const UPDATE_OBJECT_TEST_CASES: WorkspaceMigrationBuilderTestCase[] = [
|
||||
|
||||
+5
-1
@@ -1,6 +1,7 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type';
|
||||
import { deleteFlatEntityFromFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/delete-flat-entity-from-flat-entity-maps-or-throw.util';
|
||||
import { FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type';
|
||||
import { compareTwoFlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/utils/compare-two-flat-index-metadata.util';
|
||||
import {
|
||||
@@ -139,7 +140,10 @@ export class WorkspaceMigrationV2IndexActionsBuilderService extends WorkspaceEnt
|
||||
this.flatIndexValidatorService.validateFlatIndexCreation({
|
||||
dependencyOptimisticFlatEntityMaps,
|
||||
flatIndexToValidate: toFlatIndex,
|
||||
optimisticFlatIndexMaps,
|
||||
optimisticFlatIndexMaps: deleteFlatEntityFromFlatEntityMapsOrThrow({
|
||||
entityToDeleteId: fromFlatIndex.id,
|
||||
flatEntityMaps: optimisticFlatIndexMaps,
|
||||
}),
|
||||
});
|
||||
|
||||
if (creationValidationResult.errors.length > 0) {
|
||||
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
import { type FromTo } from 'twenty-shared/types';
|
||||
|
||||
import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type';
|
||||
import {
|
||||
type FlatObjectMetadata,
|
||||
type FlatObjectMetadataWithoutFields,
|
||||
} from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import {
|
||||
type CustomDeletedCreatedUpdatedMatrix,
|
||||
deletedCreatedUpdatedMatrixDispatcher,
|
||||
} from 'src/engine/workspace-manager/workspace-migration-v2/utils/deleted-created-updated-matrix-dispatcher.util';
|
||||
|
||||
export type UpdatedObjectMetadataDeletedCreatedUpdatedIndexMatrix = {
|
||||
flatObjectMetadata: FlatObjectMetadataWithoutFields;
|
||||
} & CustomDeletedCreatedUpdatedMatrix<'indexMetadata', FlatIndexMetadata>;
|
||||
|
||||
export const computeUpdatedObjectMetadataDeletedCreatedUpdatedIndexMatrix = (
|
||||
updatedObjectMetadata: FromTo<FlatObjectMetadata>[],
|
||||
): UpdatedObjectMetadataDeletedCreatedUpdatedIndexMatrix[] => {
|
||||
const matrixAccumulator: UpdatedObjectMetadataDeletedCreatedUpdatedIndexMatrix[] =
|
||||
[];
|
||||
|
||||
for (const { from, to } of updatedObjectMetadata) {
|
||||
const indexMetadataMatrix = deletedCreatedUpdatedMatrixDispatcher({
|
||||
from: from.flatIndexMetadatas,
|
||||
to: to.flatIndexMetadatas,
|
||||
});
|
||||
|
||||
matrixAccumulator.push({
|
||||
flatObjectMetadata: to,
|
||||
createdIndexMetadata: indexMetadataMatrix.created,
|
||||
deletedIndexMetadata: indexMetadataMatrix.deleted,
|
||||
updatedIndexMetadata: indexMetadataMatrix.updated,
|
||||
});
|
||||
}
|
||||
|
||||
return matrixAccumulator;
|
||||
};
|
||||
-1
@@ -5,6 +5,5 @@ import {
|
||||
|
||||
export const fromFlatObjectMetadataToFlatObjectMetadataWithoutFields = ({
|
||||
flatFieldMetadatas: _flatFieldMetadatas,
|
||||
flatIndexMetadatas: _flatIndexMetadatas,
|
||||
...rest
|
||||
}: FlatObjectMetadata): FlatObjectMetadataWithoutFields => rest;
|
||||
|
||||
+2
-2
@@ -94,7 +94,7 @@ export class FlatIndexValidatorService {
|
||||
optimisticFlatIndexMaps.byId,
|
||||
).filter(isDefined);
|
||||
|
||||
const existingFlatIndexOnName = allExistingFlatIndex.some(
|
||||
const existingFlatIndexOnName = allExistingFlatIndex.find(
|
||||
(flatIndexMetadata) =>
|
||||
flatIndexMetadata.name.toLocaleUpperCase() ===
|
||||
flatIndexToValidate.name.toLocaleUpperCase(),
|
||||
@@ -102,7 +102,7 @@ export class FlatIndexValidatorService {
|
||||
|
||||
if (isDefined(existingFlatIndexOnName)) {
|
||||
validationResult.errors.push({
|
||||
code: IndexExceptionCode.INDEX_EMPTY_FIELDS,
|
||||
code: IndexExceptionCode.INDEX_ALREADY_EXISTS,
|
||||
message: t`Index with same name already exists`,
|
||||
userFriendlyMessage: t`Index with same name already exists`,
|
||||
});
|
||||
|
||||
+64
-6
@@ -1,13 +1,26 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
OptimisticallyApplyActionOnAllFlatEntityMapsArgs,
|
||||
WorkspaceMigrationRunnerActionHandler,
|
||||
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface';
|
||||
|
||||
import {
|
||||
WorkspaceQueryRunnerException,
|
||||
WorkspaceQueryRunnerExceptionCode,
|
||||
} from 'src/engine/api/graphql/workspace-query-runner/workspace-query-runner.exception';
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/core-modules/common/exceptions/flat-entity-maps.exception';
|
||||
import { AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type';
|
||||
import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/add-flat-entity-to-flat-entity-maps-or-throw.util';
|
||||
import { isMorphOrRelationFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-morph-or-relation-flat-field-metadata.util';
|
||||
import { findFlatFieldMetadataInFlatObjectMetadataMapsWithOnlyFieldId } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/find-flat-field-metadata-in-flat-object-metadata-maps-with-field-id-only.util';
|
||||
import { findFlatObjectMetadataInFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/find-flat-object-metadata-in-flat-object-metadata-maps-or-throw.util';
|
||||
import { IndexFieldMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-field-metadata.entity';
|
||||
import { IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-metadata.entity';
|
||||
import { WorkspaceSchemaManagerService } from 'src/engine/twenty-orm/workspace-schema-manager/workspace-schema-manager.service';
|
||||
import { type CreateIndexAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-index-action-v2';
|
||||
@@ -44,15 +57,34 @@ export class CreateIndexActionHandlerService extends WorkspaceMigrationRunnerAct
|
||||
queryRunner.manager.getRepository<IndexMetadataEntity>(
|
||||
IndexMetadataEntity,
|
||||
);
|
||||
const indexFieldMetadataRepository =
|
||||
queryRunner.manager.getRepository<IndexFieldMetadataEntity>(
|
||||
IndexFieldMetadataEntity,
|
||||
);
|
||||
|
||||
const {
|
||||
flatIndexMetadata: { flatIndexFieldMetadatas, ...rest },
|
||||
flatIndexMetadata: { flatIndexFieldMetadatas, ...flatIndexMetadata },
|
||||
} = action;
|
||||
|
||||
await indexMetadataRepository.insert({
|
||||
indexFieldMetadatas: flatIndexFieldMetadatas,
|
||||
...rest,
|
||||
});
|
||||
const indexInsertResult =
|
||||
await indexMetadataRepository.insert(flatIndexMetadata);
|
||||
|
||||
if (indexInsertResult.identifiers.length !== 1) {
|
||||
throw new WorkspaceQueryRunnerException(
|
||||
'Failed to create index metadata',
|
||||
WorkspaceQueryRunnerExceptionCode.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
const indexMetadataId = indexInsertResult.identifiers[0].id;
|
||||
|
||||
const indexFieldMetadataToInsert = flatIndexFieldMetadatas.map(
|
||||
(flatIndexFieldMetadata) => ({
|
||||
...flatIndexFieldMetadata,
|
||||
indexMetadataId,
|
||||
}),
|
||||
);
|
||||
|
||||
await indexFieldMetadataRepository.insert(indexFieldMetadataToInsert);
|
||||
}
|
||||
|
||||
async executeForWorkspaceSchema(
|
||||
@@ -76,7 +108,33 @@ export class CreateIndexActionHandlerService extends WorkspaceMigrationRunnerAct
|
||||
});
|
||||
|
||||
const quotedColumns = flatIndexMetadata.flatIndexFieldMetadatas.map(
|
||||
(column) => `"${column}"`,
|
||||
({ fieldMetadataId }) => {
|
||||
const flatFieldMetadata =
|
||||
findFlatFieldMetadataInFlatObjectMetadataMapsWithOnlyFieldId({
|
||||
fieldMetadataId,
|
||||
flatObjectMetadataMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(flatFieldMetadata)) {
|
||||
throw new FlatEntityMapsException(
|
||||
'Index field related field metadata not found',
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
if (isMorphOrRelationFlatFieldMetadata(flatFieldMetadata)) {
|
||||
if (!isDefined(flatFieldMetadata.settings?.joinColumnName)) {
|
||||
throw new FlatEntityMapsException(
|
||||
'Join column name is not defined for relation field',
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
return `"${flatFieldMetadata.settings.joinColumnName}"`;
|
||||
}
|
||||
|
||||
return `"${flatFieldMetadata.name}"`;
|
||||
},
|
||||
);
|
||||
|
||||
await this.workspaceSchemaManagerService.indexManager.createIndex({
|
||||
|
||||
+15
-16
@@ -8,16 +8,22 @@ import {
|
||||
import { AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type';
|
||||
import { deleteFlatEntityFromFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/delete-flat-entity-from-flat-entity-maps-or-throw.util';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { findFlatObjectMetadataInFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/find-flat-object-metadata-in-flat-object-metadata-maps-or-throw.util';
|
||||
import { IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-metadata.entity';
|
||||
import { WorkspaceSchemaManagerService } from 'src/engine/twenty-orm/workspace-schema-manager/workspace-schema-manager.service';
|
||||
import { getWorkspaceSchemaName } from 'src/engine/workspace-datasource/utils/get-workspace-schema-name.util';
|
||||
import { type DeleteIndexAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-index-action-v2';
|
||||
import { type WorkspaceMigrationActionRunnerArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/workspace-migration-action-runner-args.type';
|
||||
import { getWorkspaceSchemaContextForMigration } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/utils/get-workspace-schema-context-for-migration.util';
|
||||
|
||||
@Injectable()
|
||||
export class DeleteIndexActionHandlerService extends WorkspaceMigrationRunnerActionHandler(
|
||||
'delete_index',
|
||||
) {
|
||||
constructor(
|
||||
private readonly workspaceSchemaManagerService: WorkspaceSchemaManagerService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
optimisticallyApplyActionOnAllFlatEntityMaps({
|
||||
action,
|
||||
allFlatEntityMaps: { flatIndexMaps },
|
||||
@@ -51,7 +57,7 @@ export class DeleteIndexActionHandlerService extends WorkspaceMigrationRunnerAct
|
||||
): Promise<void> {
|
||||
const {
|
||||
action,
|
||||
allFlatEntityMaps: { flatObjectMetadataMaps, flatIndexMaps },
|
||||
allFlatEntityMaps: { flatIndexMaps },
|
||||
queryRunner,
|
||||
workspaceId,
|
||||
} = context;
|
||||
@@ -63,19 +69,12 @@ export class DeleteIndexActionHandlerService extends WorkspaceMigrationRunnerAct
|
||||
},
|
||||
);
|
||||
|
||||
const flatObjectMetadata =
|
||||
findFlatObjectMetadataInFlatObjectMetadataMapsOrThrow({
|
||||
flatObjectMetadataMaps,
|
||||
objectMetadataId: flatIndexMetadataToDelete.objectMetadataId,
|
||||
});
|
||||
const { schemaName, tableName } = getWorkspaceSchemaContextForMigration({
|
||||
workspaceId,
|
||||
flatObjectMetadata,
|
||||
});
|
||||
const schemaName = getWorkspaceSchemaName(workspaceId);
|
||||
|
||||
await queryRunner.dropIndex(
|
||||
`${schemaName}.${tableName}`,
|
||||
flatIndexMetadataToDelete.name,
|
||||
);
|
||||
await this.workspaceSchemaManagerService.indexManager.dropIndex({
|
||||
indexName: flatIndexMetadataToDelete.name,
|
||||
queryRunner,
|
||||
schemaName,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
-1
@@ -48,7 +48,6 @@ export class CreateObjectActionHandlerService extends WorkspaceMigrationRunnerAc
|
||||
addFlatObjectMetadataToFlatObjectMetadataMapsOrThrow({
|
||||
flatObjectMetadata: {
|
||||
...flatObjectMetadataWithoutFields,
|
||||
flatIndexMetadatas: [],
|
||||
flatFieldMetadatas,
|
||||
},
|
||||
flatObjectMetadataMaps,
|
||||
|
||||
Reference in New Issue
Block a user