diff --git a/.changeset/odd-games-live.md b/.changeset/odd-games-live.md new file mode 100644 index 0000000000..8f10b5ad7d --- /dev/null +++ b/.changeset/odd-games-live.md @@ -0,0 +1,5 @@ +--- +'@finos/legend-graph': patch +--- + +Add TabularFunction in metamodel diff --git a/packages/legend-graph/src/graph-manager/protocol/pure/v1/model/packageableElements/store/relational/model/V1_Schema.ts b/packages/legend-graph/src/graph-manager/protocol/pure/v1/model/packageableElements/store/relational/model/V1_Schema.ts index 7e44cb4805..510379aa48 100644 --- a/packages/legend-graph/src/graph-manager/protocol/pure/v1/model/packageableElements/store/relational/model/V1_Schema.ts +++ b/packages/legend-graph/src/graph-manager/protocol/pure/v1/model/packageableElements/store/relational/model/V1_Schema.ts @@ -32,6 +32,7 @@ export class V1_Schema implements Hashable { this.name, hashArray(this.tables), hashArray(this.views), + hashArray(this.tabularFunctions), ]); } } diff --git a/packages/legend-graph/src/graph-manager/protocol/pure/v1/model/packageableElements/store/relational/model/V1_TabularFunction.ts b/packages/legend-graph/src/graph-manager/protocol/pure/v1/model/packageableElements/store/relational/model/V1_TabularFunction.ts index 78bf16af59..9ef0a4e89e 100644 --- a/packages/legend-graph/src/graph-manager/protocol/pure/v1/model/packageableElements/store/relational/model/V1_TabularFunction.ts +++ b/packages/legend-graph/src/graph-manager/protocol/pure/v1/model/packageableElements/store/relational/model/V1_TabularFunction.ts @@ -14,8 +14,19 @@ * limitations under the License. */ -export class V1_TabularFunction { - // TODO params ? +import { CORE_HASH_STRUCTURE } from '../../../../../../../../../graph/Core_HashUtils.js'; +import { type Hashable, hashArray } from '@finos/legend-shared'; +import type { V1_Column } from './V1_Column.js'; + +export class V1_TabularFunction implements Hashable { name!: string; - // columns: Column[] = []; + columns: V1_Column[] = []; + + get hashCode(): string { + return hashArray([ + CORE_HASH_STRUCTURE.DATABASE_SCHEMA_TABULARFUNCTION, + this.name, + hashArray(this.columns), + ]); + } } diff --git a/packages/legend-graph/src/graph-manager/protocol/pure/v1/transformation/pureGraph/from/V1_DatabaseTransformer.ts b/packages/legend-graph/src/graph-manager/protocol/pure/v1/transformation/pureGraph/from/V1_DatabaseTransformer.ts index b9eb457f82..6f0fd1cf4c 100644 --- a/packages/legend-graph/src/graph-manager/protocol/pure/v1/transformation/pureGraph/from/V1_DatabaseTransformer.ts +++ b/packages/legend-graph/src/graph-manager/protocol/pure/v1/transformation/pureGraph/from/V1_DatabaseTransformer.ts @@ -109,6 +109,8 @@ import { V1_FilterPointer } from '../../../model/packageableElements/store/relat import type { TablePtr } from '../../../../../../../graph/metamodel/pure/packageableElements/service/TablePtr.js'; import { V1_transformStereotype } from './V1_DomainTransformer.js'; import { V1_PackageableElementPointer } from '../../../model/packageableElements/V1_PackageableElement.js'; +import type { TabularFunction } from '../../../../../../../graph/metamodel/pure/packageableElements/store/relational/model/TabularFunction.js'; +import { V1_TabularFunction } from '../../../model/packageableElements/store/relational/model/V1_TabularFunction.js'; const transformRelationalDataType = ( type: RelationalDataType, @@ -344,6 +346,18 @@ const transformTable = ( return table; }; +const transformTabularFunction = ( + element: TabularFunction, + context: V1_GraphTransformerContext, +): V1_TabularFunction => { + const tabularFunction = new V1_TabularFunction(); + tabularFunction.columns = element.columns.map((val) => + transformColumn(val as Column), + ); + tabularFunction.name = element.name; + return tabularFunction; +}; + const transformJoin = ( element: Join, context: V1_GraphTransformerContext, @@ -411,6 +425,9 @@ const transformSchema = ( schema.name = element.name; schema.tables = element.tables.map((table) => transformTable(table, context)); schema.views = element.views.map((view) => transformView(view, context)); + schema.tabularFunctions = element.tabularFunctions.map((tabularFunction) => + transformTabularFunction(tabularFunction, context), + ); return schema; }; diff --git a/packages/legend-graph/src/graph-manager/protocol/pure/v1/transformation/pureGraph/to/helpers/V1_DatabaseBuilderHelper.ts b/packages/legend-graph/src/graph-manager/protocol/pure/v1/transformation/pureGraph/to/helpers/V1_DatabaseBuilderHelper.ts index f901daec87..30f7fa0a25 100644 --- a/packages/legend-graph/src/graph-manager/protocol/pure/v1/transformation/pureGraph/to/helpers/V1_DatabaseBuilderHelper.ts +++ b/packages/legend-graph/src/graph-manager/protocol/pure/v1/transformation/pureGraph/to/helpers/V1_DatabaseBuilderHelper.ts @@ -131,6 +131,8 @@ import { FilterImplicitReference } from '../../../../../../../../graph/metamodel import { PackageableElementImplicitReference } from '../../../../../../../../graph/metamodel/pure/packageableElements/PackageableElementReference.js'; import type { V1_TablePtr } from '../../../../model/packageableElements/store/relational/model/V1_TablePtr.js'; import { TablePtr } from '../../../../../../../../graph/metamodel/pure/packageableElements/service/TablePtr.js'; +import type { TabularFunction } from '../../../../../../../../graph/metamodel/pure/packageableElements/store/relational/model/TabularFunction.js'; +import type { V1_TabularFunction } from '../../../../model/packageableElements/store/relational/model/V1_TabularFunction.js'; const _schemaExists = ( db: Database, @@ -186,6 +188,11 @@ export const V1_findRelation = ( if (!relation) { relation = schema.views.find((view) => view.name === tableName); } + if (!relation) { + relation = schema.tabularFunctions.find( + (tabularFunction) => tabularFunction.name === tableName, + ); + } if (relation) { relations.push(relation); } @@ -447,6 +454,22 @@ const buildDatabaseTable = ( return table; }; +const buildDatabaseTabularFunction = ( + srcTabularFunction: V1_TabularFunction, + schema: Schema, +): TabularFunction => { + assertNonEmptyString( + srcTabularFunction.name, + `TabularFunction 'name' field is missing or empty`, + ); + const tabularFunction = new Table(srcTabularFunction.name, schema); + const columns = srcTabularFunction.columns.map((column) => + buildColumn(column, tabularFunction), + ); + tabularFunction.columns = columns; + return tabularFunction; +}; + export const V1_buildSchema = ( srcSchema: V1_Schema, database: Database, @@ -460,6 +483,9 @@ export const V1_buildSchema = ( schema.tables = srcSchema.tables.map((table) => buildDatabaseTable(table, schema, context), ); + schema.tabularFunctions = srcSchema.tabularFunctions.map((tabularFunction) => + buildDatabaseTabularFunction(tabularFunction, schema), + ); return schema; }; diff --git a/packages/legend-graph/src/graph-manager/protocol/pure/v1/transformation/pureProtocol/serializationHelpers/V1_DatabaseSerializationHelper.ts b/packages/legend-graph/src/graph-manager/protocol/pure/v1/transformation/pureProtocol/serializationHelpers/V1_DatabaseSerializationHelper.ts index 72934bd767..0cbb5ffb2f 100644 --- a/packages/legend-graph/src/graph-manager/protocol/pure/v1/transformation/pureProtocol/serializationHelpers/V1_DatabaseSerializationHelper.ts +++ b/packages/legend-graph/src/graph-manager/protocol/pure/v1/transformation/pureProtocol/serializationHelpers/V1_DatabaseSerializationHelper.ts @@ -466,6 +466,7 @@ export function V1_deserializeRelationalOperationElement( const V1_tabularFunctionModelSchema = createModelSchema(V1_TabularFunction, { name: primitive(), + columns: list(usingModelSchema(columnModelSchema)), }); export const V1_filterMappingModelSchema = createModelSchema(V1_FilterMapping, { @@ -540,6 +541,15 @@ const V1_setupTableSerialization = ( }); }; +const V1_setupTabularFunctionSerialization = ( + plugins: PureProtocolProcessorPlugin[], +): void => { + createModelSchema(V1_TabularFunction, { + columns: list(usingModelSchema(columnModelSchema)), + name: primitive(), + }); +}; + const V1_setupRelationalDatabaseConnectionModelSchema = ( plugins: PureProtocolProcessorPlugin[], ): void => { @@ -579,6 +589,7 @@ export const V1_setupDatabaseSerialization = ( plugins: PureProtocolProcessorPlugin[], ): void => { V1_setupTableSerialization(plugins); + V1_setupTabularFunctionSerialization(plugins); V1_setupRelationalDatabaseConnectionModelSchema(plugins); }; diff --git a/packages/legend-graph/src/graph/Core_HashUtils.ts b/packages/legend-graph/src/graph/Core_HashUtils.ts index 28d23fd210..6c487875f4 100644 --- a/packages/legend-graph/src/graph/Core_HashUtils.ts +++ b/packages/legend-graph/src/graph/Core_HashUtils.ts @@ -249,8 +249,8 @@ export enum CORE_HASH_STRUCTURE { DATABASE_FILTER = 'DATABASE_FILTER', DATBASE_VIEW = 'DATBASE_VIEW', DATABASE_SCHEMA_TABLE = 'DATABASE_SCHEMA_TABLE', + DATABASE_SCHEMA_TABULARFUNCTION = 'DATABASE_SCHEMA_TABULARFUNCTION', DATABASE_TABLE_COLUMN = 'DATABASE_TABLE_COLUMN', - // relational operation element RELATIONAL = 'RELATIONAL', RELATIONAL_OPERATION_DYNA_FUNC = 'RELATIONAL_OPERATION_DYNA_FUNC', diff --git a/packages/legend-graph/src/graph/metamodel/pure/packageableElements/store/relational/model/Schema.ts b/packages/legend-graph/src/graph/metamodel/pure/packageableElements/store/relational/model/Schema.ts index 7ea6cdee9b..b3449c1d1e 100644 --- a/packages/legend-graph/src/graph/metamodel/pure/packageableElements/store/relational/model/Schema.ts +++ b/packages/legend-graph/src/graph/metamodel/pure/packageableElements/store/relational/model/Schema.ts @@ -19,6 +19,7 @@ import { type Hashable, hashArray } from '@finos/legend-shared'; import type { Database } from './Database.js'; import type { Table } from './Table.js'; import type { View } from './View.js'; +import type { TabularFunction } from './TabularFunction.js'; export class Schema implements Hashable { readonly _OWNER: Database; @@ -26,6 +27,7 @@ export class Schema implements Hashable { name: string; tables: Table[] = []; views: View[] = []; + tabularFunctions: TabularFunction[] = []; constructor(name: string, owner: Database) { this.name = name; @@ -38,6 +40,7 @@ export class Schema implements Hashable { this.name, hashArray(this.tables), hashArray(this.views), + hashArray(this.tabularFunctions), ]); } } diff --git a/packages/legend-graph/src/graph/metamodel/pure/packageableElements/store/relational/model/TabularFunction.ts b/packages/legend-graph/src/graph/metamodel/pure/packageableElements/store/relational/model/TabularFunction.ts new file mode 100644 index 0000000000..be4c436808 --- /dev/null +++ b/packages/legend-graph/src/graph/metamodel/pure/packageableElements/store/relational/model/TabularFunction.ts @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2020-present, Goldman Sachs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CORE_HASH_STRUCTURE } from '../../../../../../../graph/Core_HashUtils.js'; +import { type Hashable, hashArray } from '@finos/legend-shared'; +import { NamedRelation } from './RelationalOperationElement.js'; +import type { Schema } from './Schema.js'; + +export class TabularFunction extends NamedRelation implements Hashable { + schema!: Schema; + + constructor(name: string, schema: Schema) { + super(name); + this.schema = schema; + } + + override get hashCode(): string { + return hashArray([ + CORE_HASH_STRUCTURE.DATABASE_SCHEMA_TABULARFUNCTION, + this.name, + hashArray(this.columns), + ]); + } +}