fix: workspace health showing error for multi select (#5547)

Fix `workspace:health` command not working properly with `MULTI_SELECT`
field metadata type.
This commit is contained in:
Jérémy M
2024-05-23 12:02:40 +02:00
committed by GitHub
parent 7b1bea3a8a
commit 453525ca25
2 changed files with 35 additions and 8 deletions

View File

@ -8,6 +8,7 @@ export interface WorkspaceTableStructure {
isPrimaryKey: boolean; isPrimaryKey: boolean;
isForeignKey: boolean; isForeignKey: boolean;
isUnique: boolean; isUnique: boolean;
isArray: boolean;
onUpdateAction: string; onUpdateAction: string;
onDeleteAction: string; onDeleteAction: string;
} }

View File

@ -24,6 +24,7 @@ import { isRelationFieldMetadataType } from 'src/engine/utils/is-relation-field-
import { isFunctionDefaultValue } from 'src/engine/metadata-modules/field-metadata/utils/is-function-default-value.util'; import { isFunctionDefaultValue } from 'src/engine/metadata-modules/field-metadata/utils/is-function-default-value.util';
import { FieldMetadataDefaultValueFunctionNames } from 'src/engine/metadata-modules/field-metadata/dtos/default-value.input'; import { FieldMetadataDefaultValueFunctionNames } from 'src/engine/metadata-modules/field-metadata/dtos/default-value.input';
import { compositeTypeDefintions } from 'src/engine/metadata-modules/field-metadata/composite-types'; import { compositeTypeDefintions } from 'src/engine/metadata-modules/field-metadata/composite-types';
import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util';
@Injectable() @Injectable()
export class DatabaseStructureService { export class DatabaseStructureService {
@ -75,8 +76,12 @@ export class DatabaseStructureService {
c.table_name AS "tableName", c.table_name AS "tableName",
c.column_name AS "columnName", c.column_name AS "columnName",
CASE CASE
WHEN (c.data_type = 'USER-DEFINED') THEN c.udt_name WHEN c.data_type = 'ARRAY' THEN
ELSE data_type (SELECT typname FROM pg_type WHERE oid = t.typelem)
WHEN c.data_type = 'USER-DEFINED' THEN
c.udt_name
ELSE
c.data_type
END AS "dataType", END AS "dataType",
c.is_nullable AS "isNullable", c.is_nullable AS "isNullable",
c.column_default AS "columnDefault", c.column_default AS "columnDefault",
@ -92,10 +97,15 @@ export class DatabaseStructureService {
WHEN uc.column_name IS NOT NULL THEN 'TRUE' WHEN uc.column_name IS NOT NULL THEN 'TRUE'
ELSE 'FALSE' ELSE 'FALSE'
END AS "isUnique", END AS "isUnique",
CASE
WHEN c.data_type = 'ARRAY' THEN 'TRUE'
ELSE 'FALSE'
END AS "isArray",
rc.update_rule AS "onUpdateAction", rc.update_rule AS "onUpdateAction",
rc.delete_rule AS "onDeleteAction" rc.delete_rule AS "onDeleteAction"
FROM FROM
information_schema.columns AS c information_schema.columns AS c
LEFT JOIN pg_type t ON t.typname = c.udt_name
LEFT JOIN LEFT JOIN
information_schema.constraint_column_usage AS ccu information_schema.constraint_column_usage AS ccu
ON c.column_name = ccu.column_name ON c.column_name = ccu.column_name
@ -132,10 +142,12 @@ export class DatabaseStructureService {
return results.map((item) => ({ return results.map((item) => ({
...item, ...item,
dataType: item.isArray === 'TRUE' ? `${item.dataType}[]` : item.dataType,
isNullable: item.isNullable === 'YES', isNullable: item.isNullable === 'YES',
isPrimaryKey: item.isPrimaryKey === 'TRUE', isPrimaryKey: item.isPrimaryKey === 'TRUE',
isForeignKey: item.isForeignKey === 'TRUE', isForeignKey: item.isForeignKey === 'TRUE',
isUnique: item.isUnique === 'TRUE', isUnique: item.isUnique === 'TRUE',
isArray: item.isArray === 'TRUE',
})); }));
} }
@ -160,14 +172,18 @@ export class DatabaseStructureService {
getPostgresDataTypes(fieldMetadata: FieldMetadataEntity): string[] { getPostgresDataTypes(fieldMetadata: FieldMetadataEntity): string[] {
const mainDataSource = this.typeORMService.getMainDataSource(); const mainDataSource = this.typeORMService.getMainDataSource();
const normalizer = (type: FieldMetadataType, columnName: string) => { const normalizer = (
type: FieldMetadataType,
isArray: boolean | undefined,
columnName: string,
) => {
const typeORMType = fieldMetadataTypeToColumnType(type); const typeORMType = fieldMetadataTypeToColumnType(type);
// Compute enum name to compare data type properly // Compute enum name to compare data type properly
if (typeORMType === 'enum') { if (typeORMType === 'enum') {
const objectName = fieldMetadata.object?.nameSingular; const objectName = computeObjectTargetTable(fieldMetadata.object);
return `${objectName}_${columnName}_enum`; return `${objectName}_${columnName}_enum${isArray ? '[]' : ''}`;
} }
return mainDataSource.driver.normalizeType({ return mainDataSource.driver.normalizeType({
@ -185,11 +201,21 @@ export class DatabaseStructureService {
} }
return compositeType.properties.map((compositeProperty) => return compositeType.properties.map((compositeProperty) =>
normalizer(compositeProperty.type, compositeProperty.name), normalizer(
compositeProperty.type,
compositeProperty.isArray,
compositeProperty.name,
),
); );
} }
return [normalizer(fieldMetadata.type, fieldMetadata.name)]; return [
normalizer(
fieldMetadata.type,
fieldMetadata.type === FieldMetadataType.MULTI_SELECT,
fieldMetadata.name,
),
];
} }
getFieldMetadataTypeFromPostgresDataType( getFieldMetadataTypeFromPostgresDataType(