diff --git a/.changeset/dirty-insects-help.md b/.changeset/dirty-insects-help.md new file mode 100644 index 0000000000..cac4817337 --- /dev/null +++ b/.changeset/dirty-insects-help.md @@ -0,0 +1,5 @@ +--- +'@finos/legend-application-repl': patch +'@finos/legend-query-builder': patch +'@finos/legend-data-cube': patch +--- diff --git a/.changeset/neat-chicken-pretend.md b/.changeset/neat-chicken-pretend.md new file mode 100644 index 0000000000..5cc34a46be --- /dev/null +++ b/.changeset/neat-chicken-pretend.md @@ -0,0 +1,6 @@ +--- +'@finos/legend-application-query': patch +'@finos/legend-application-repl': patch +'@finos/legend-query-builder': patch +'@finos/legend-data-cube': patch +--- diff --git a/packages/legend-application-query/src/components/data-cube/ExistingQueryDataCubeViewer.tsx b/packages/legend-application-query/src/components/data-cube/ExistingQueryDataCubeViewer.tsx index dfde1df308..57472dc31c 100644 --- a/packages/legend-application-query/src/components/data-cube/ExistingQueryDataCubeViewer.tsx +++ b/packages/legend-application-query/src/components/data-cube/ExistingQueryDataCubeViewer.tsx @@ -27,8 +27,7 @@ import { } from './ExistingQueryEditorStoreProviderProvider.js'; import { useEffect } from 'react'; import { flowResult } from 'mobx'; -import { DataCube, DataCubeProvider } from '@finos/legend-data-cube'; -import { QueryBuilderDataCubeApplicationEngine } from '@finos/legend-query-builder'; +import { DataCube } from '@finos/legend-data-cube'; import { guaranteeNonNullable } from '@finos/legend-shared'; export const DataCubeWrapper = observer(() => { @@ -42,15 +41,7 @@ export const DataCubeWrapper = observer(() => { if (!store.engine) { return null; } - const _appEngine = new QueryBuilderDataCubeApplicationEngine( - applicationStore, - ); - - return ( - - - - ); + return ; }); export const ExistingQueryDataCubeViewer = observer(() => { diff --git a/packages/legend-application-repl/package.json b/packages/legend-application-repl/package.json index c0430ceca9..7914b9dfce 100644 --- a/packages/legend-application-repl/package.json +++ b/packages/legend-application-repl/package.json @@ -53,7 +53,8 @@ "mobx": "6.13.3", "mobx-react-lite": "4.0.7", "react": "18.3.1", - "react-dom": "18.3.1" + "react-dom": "18.3.1", + "serializr": "3.0.2" }, "devDependencies": { "@finos/legend-dev-utils": "workspace:*", diff --git a/packages/legend-application-repl/src/components/LegendREPLApplication.tsx b/packages/legend-application-repl/src/components/LegendREPLApplication.tsx index ec6ff1b507..f664c7021a 100644 --- a/packages/legend-application-repl/src/components/LegendREPLApplication.tsx +++ b/packages/legend-application-repl/src/components/LegendREPLApplication.tsx @@ -22,14 +22,14 @@ import { import { observer } from 'mobx-react-lite'; import { useEffect, useMemo } from 'react'; import { + formatDate, guaranteeNonNullable, LogEvent, NetworkClient, } from '@finos/legend-shared'; import { LegendREPLServerClient } from '../stores/LegendREPLServerClient.js'; -import { LegendREPLDataCubeApplicationEngine } from '../stores/LegendREPLDataCubeApplicationEngine.js'; import { LegendREPLDataCubeEngine } from '../stores/LegendREPLDataCubeEngine.js'; -import { DataCube, DataCubeProvider } from '@finos/legend-data-cube'; +import { DataCube, DataCubeSettingKey } from '@finos/legend-data-cube'; import { APPLICATION_EVENT, ApplicationFrameworkProvider, @@ -38,53 +38,81 @@ import { type LegendApplicationPluginManager, } from '@finos/legend-application'; import type { LegendREPLApplicationConfig } from '../application/LegendREPLApplicationConfig.js'; +import { LegendREPLDataCubeSource } from '../stores/LegendREPLDataCubeSource.js'; const LegendREPLDataCube = observer(() => { - const applicationStore = useApplicationStore< + const application = useApplicationStore< LegendREPLApplicationConfig, LegendApplicationPluginManager >(); - const application = useMemo( - () => new LegendREPLDataCubeApplicationEngine(applicationStore), - [applicationStore], - ); - const engine = new LegendREPLDataCubeEngine( - application, - new LegendREPLServerClient( - new NetworkClient({ - baseUrl: applicationStore.config.useDynamicREPLServer - ? window.location.origin + - guaranteeNonNullable(applicationStore.config.baseAddress).replace( - '/repl/', - '', - ) - : applicationStore.config.replUrl, - }), - ), + const config = application.config; + const engine = useMemo( + () => + new LegendREPLDataCubeEngine( + application, + new LegendREPLServerClient( + new NetworkClient({ + baseUrl: config.useDynamicREPLServer + ? window.location.origin + + guaranteeNonNullable(config.baseAddress).replace('/repl/', '') + : config.replUrl, + }), + ), + ), + [application, config], ); useEffect(() => { - application.blockNavigation( + engine.blockNavigation( // Only block navigation in production // eslint-disable-next-line no-process-env [() => process.env.NODE_ENV === 'production'], undefined, () => { - application.logWarning( + engine.logWarning( LogEvent.create(APPLICATION_EVENT.NAVIGATION_BLOCKED), `Navigation from the application is blocked`, ); }, ); return (): void => { - application.unblockNavigation(); + engine.unblockNavigation(); }; - }, [application]); + }, [engine]); return ( - - - + ); }); diff --git a/packages/legend-application-repl/src/stores/LegendREPLDataCubeApplicationEngine.ts b/packages/legend-application-repl/src/stores/LegendREPLDataCubeApplicationEngine.ts deleted file mode 100644 index 915878655c..0000000000 --- a/packages/legend-application-repl/src/stores/LegendREPLDataCubeApplicationEngine.ts +++ /dev/null @@ -1,137 +0,0 @@ -/** - * 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 { - shouldDisplayVirtualAssistantDocumentationEntry, - APPLICATION_EVENT, -} from '@finos/legend-application'; -import { type DocumentationEntry, LogEvent } from '@finos/legend-shared'; -import { DataCubeApplicationEngine } from '@finos/legend-data-cube'; -import type { LegendREPLApplicationStore } from '../application/LegendREPLApplicationStore.js'; - -export class LegendREPLDataCubeApplicationEngine extends DataCubeApplicationEngine { - private readonly application: LegendREPLApplicationStore; - - constructor(application: LegendREPLApplicationStore) { - super(); - - this.application = application; - } - - get documentationUrl(): string | undefined { - return this.application.documentationService.url; - } - - getDocumentationEntry(key: string) { - return this.application.documentationService.getDocEntry(key); - } - - openDocumentationEntry(entry: DocumentationEntry) { - this.currentDocumentationEntry = entry; - } - - shouldDisplayDocumentationEntry(entry: DocumentationEntry) { - return shouldDisplayVirtualAssistantDocumentationEntry(entry); - } - - openLink(url: string) { - this.application.navigationService.navigator.visitAddress(url); - } - - setWindowTitle(title: string) { - this.application.layoutService.setWindowTitle(title); - } - - blockNavigation( - blockCheckers: (() => boolean)[], - onBlock?: ((onProceed: () => void) => void) | undefined, - onNativePlatformNavigationBlock?: (() => void) | undefined, - ) { - this.application.navigationService.navigator.blockNavigation( - blockCheckers, - onBlock, - onNativePlatformNavigationBlock, - ); - } - - unblockNavigation() { - this.application.navigationService.navigator.unblockNavigation(); - } - - logDebug(message: string, ...data: unknown[]) { - this.application.logService.debug( - LogEvent.create(APPLICATION_EVENT.DEBUG), - message, - ...data, - ); - } - - debugProcess(processName: string, ...data: [string, unknown][]) { - this.application.logService.debug( - LogEvent.create(APPLICATION_EVENT.DEBUG), - `\n------ START DEBUG PROCESS: ${processName} ------`, - ...data.flatMap(([key, value]) => [`\n[${key.toUpperCase()}]:`, value]), - `\n------- END DEBUG PROCESS: ${processName} -------\n\n`, - ); - } - - logInfo(event: LogEvent, ...data: unknown[]) { - this.application.logService.info(event, ...data); - } - - logWarning(event: LogEvent, ...data: unknown[]) { - this.application.logService.warn(event, ...data); - } - - logError(event: LogEvent, ...data: unknown[]) { - this.application.logService.error(event, ...data); - } - - logUnhandledError(error: Error) { - this.application.logUnhandledError(error); - } - - logIllegalStateError(message: string, error?: Error) { - this.logError( - LogEvent.create(APPLICATION_EVENT.ILLEGAL_APPLICATION_STATE_OCCURRED), - message, - error, - ); - } - - getPersistedNumericValue(key: string): number | undefined { - return this.application.settingService.getNumericValue(key); - } - - getPersistedStringValue(key: string): string | undefined { - return this.application.settingService.getStringValue(key); - } - - getPersistedBooleanValue(key: string): boolean | undefined { - return this.application.settingService.getBooleanValue(key); - } - - getPersistedObjectValue(key: string): object | undefined { - return this.application.settingService.getObjectValue(key); - } - - persistValue( - key: string, - value: string | number | boolean | object | undefined, - ): void { - this.application.settingService.persistValue(key, value); - } -} diff --git a/packages/legend-application-repl/src/stores/LegendREPLDataCubeEngine.ts b/packages/legend-application-repl/src/stores/LegendREPLDataCubeEngine.ts index ea17e2742d..f012255c2d 100644 --- a/packages/legend-application-repl/src/stores/LegendREPLDataCubeEngine.ts +++ b/packages/legend-application-repl/src/stores/LegendREPLDataCubeEngine.ts @@ -14,20 +14,22 @@ * limitations under the License. */ -import type { LegendREPLServerClient } from './LegendREPLServerClient.js'; import { + GetBaseQueryResult, + type LegendREPLServerClient, +} from './LegendREPLServerClient.js'; +import { + _elementPtr, + _function, + _lambda, DataCubeEngine, - DataCubeGetBaseQueryResult, - DEFAULT_ENABLE_DEBUG_MODE, - DEFAULT_GRID_CLIENT_PURGE_CLOSED_ROW_NODES, - DEFAULT_GRID_CLIENT_ROW_BUFFER, - DEFAULT_GRID_CLIENT_SUPPRESS_LARGE_DATASET_WARNING, - type CompletionItem, - type DataCubeInfrastructureInfo, - type RelationType, + DataCubeFunction, + type DataCubeAPI, + type DataCubeSource, } from '@finos/legend-data-cube'; import { TDSExecutionResult, + type V1_AppliedFunction, V1_buildExecutionResult, V1_deserializeValueSpecification, V1_serializeExecutionResult, @@ -35,116 +37,123 @@ import { type V1_Lambda, type V1_ValueSpecification, } from '@finos/legend-graph'; -import { guaranteeType } from '@finos/legend-shared'; -import type { LegendREPLDataCubeApplicationEngine } from './LegendREPLDataCubeApplicationEngine.js'; -import { LEGEND_REPL_SETTING_KEY } from '../__lib__/LegendREPLSetting.js'; +import { + type DocumentationEntry, + guaranteeType, + isNonNullable, + LogEvent, + type PlainObject, +} from '@finos/legend-shared'; +import { LegendREPLDataCubeSource } from './LegendREPLDataCubeSource.js'; +import type { LegendREPLApplicationStore } from '../application/LegendREPLApplicationStore.js'; +import { + APPLICATION_EVENT, + shouldDisplayVirtualAssistantDocumentationEntry, +} from '@finos/legend-application'; export class LegendREPLDataCubeEngine extends DataCubeEngine { - readonly application: LegendREPLDataCubeApplicationEngine; + readonly application: LegendREPLApplicationStore; readonly client: LegendREPLServerClient; constructor( - application: LegendREPLDataCubeApplicationEngine, + application: LegendREPLApplicationStore, client: LegendREPLServerClient, ) { super(); this.application = application; this.client = client; - - this.enableDebugMode = - this.application.getPersistedBooleanValue( - LEGEND_REPL_SETTING_KEY.ENABLE_DEBUG_MODE, - ) ?? DEFAULT_ENABLE_DEBUG_MODE; - this.gridClientRowBuffer = - this.application.getPersistedNumericValue( - LEGEND_REPL_SETTING_KEY.GRID_CLIENT_ROW_BUFFER, - ) ?? DEFAULT_GRID_CLIENT_ROW_BUFFER; - this.gridClientPurgeClosedRowNodes = - this.application.getPersistedBooleanValue( - LEGEND_REPL_SETTING_KEY.GRID_CLIENT_PURGE_CLOSED_ROW_NODES, - ) ?? DEFAULT_GRID_CLIENT_PURGE_CLOSED_ROW_NODES; - this.gridClientSuppressLargeDatasetWarning = - this.application.getPersistedBooleanValue( - LEGEND_REPL_SETTING_KEY.GRID_CLIENT_SUPPRESS_LARGE_DATASET_WARNING, - ) ?? DEFAULT_GRID_CLIENT_SUPPRESS_LARGE_DATASET_WARNING; - } - - override setEnableDebugMode(value: boolean) { - super.setEnableDebugMode(value); - this.application.persistValue( - LEGEND_REPL_SETTING_KEY.ENABLE_DEBUG_MODE, - value, - ); } - override setGridClientRowBuffer(value: number) { - super.setGridClientRowBuffer(value); - this.application.persistValue( - LEGEND_REPL_SETTING_KEY.GRID_CLIENT_ROW_BUFFER, - value, + blockNavigation( + blockCheckers: (() => boolean)[], + onBlock?: ((onProceed: () => void) => void) | undefined, + onNativePlatformNavigationBlock?: (() => void) | undefined, + ) { + this.application.navigationService.navigator.blockNavigation( + blockCheckers, + onBlock, + onNativePlatformNavigationBlock, ); } - override setGridClientPurgeClosedRowNodes(value: boolean) { - super.setGridClientPurgeClosedRowNodes(value); - this.application.persistValue( - LEGEND_REPL_SETTING_KEY.GRID_CLIENT_PURGE_CLOSED_ROW_NODES, - value, - ); + unblockNavigation() { + this.application.navigationService.navigator.unblockNavigation(); } - override setGridClientSuppressLargeDatasetWarning(value: boolean) { - super.setGridClientSuppressLargeDatasetWarning(value); - this.application.persistValue( - LEGEND_REPL_SETTING_KEY.GRID_CLIENT_SUPPRESS_LARGE_DATASET_WARNING, - value, - ); + persistSettingValue( + key: string, + value: string | number | boolean | object | undefined, + ): void { + this.application.settingService.persistValue(key, value); } - async getInfrastructureInfo(): Promise { - return this.client.getInfrastructureInfo(); + // ---------------------------------- IMPLEMENTATION ---------------------------------- + + override async fetchConfiguration() { + const info = await this.client.getInfrastructureInfo(); + return { + gridClientLicense: info.gridClientLicense, + }; } - async getQueryTypeahead( - code: string, - query: V1_ValueSpecification, - ): Promise { - return this.client.getQueryTypeahead({ - code, - baseQuery: V1_serializeValueSpecification(query, []), - }); + override async getInitialInput() { + const baseQuery = GetBaseQueryResult.serialization.fromJson( + await this.client.getBaseQuery(), + ); + const source = new LegendREPLDataCubeSource(); + source.mapping = baseQuery.source.mapping; + source.query = await this.parseValueSpecification( + baseQuery.source.query, + false, + ); + source.runtime = baseQuery.source.runtime; + source.timestamp = baseQuery.source.timestamp; + source.sourceColumns = ( + await this.getQueryRelationType(_lambda([], [source.query]), source) + ).columns; + + return { + query: baseQuery.query, + source, + }; } - async parseQuery( + async parseValueSpecification( code: string, returnSourceInformation?: boolean, ): Promise { return V1_deserializeValueSpecification( - await this.client.parseQuery({ code, returnSourceInformation }), + await this.client.parseValueSpecification({ + code, + returnSourceInformation, + }), [], ); } - override getQueryCode( - query: V1_ValueSpecification, + override getValueSpecificationCode( + value: V1_ValueSpecification, pretty?: boolean, - ): Promise { - return this.client.getQueryCode({ - query: V1_serializeValueSpecification(query, []), + ) { + return this.client.getValueSpecificationCode({ + value: V1_serializeValueSpecification(value, []), pretty, }); } - async getBaseQuery(): Promise { - return DataCubeGetBaseQueryResult.serialization.fromJson( - await this.client.getBaseQuery(), - ); + async getQueryTypeahead( + code: string, + baseQuery: V1_Lambda, + source: DataCubeSource, + ) { + return this.client.getQueryTypeahead({ + code, + baseQuery: V1_serializeValueSpecification(baseQuery, []), + }); } - async getQueryRelationType( - query: V1_ValueSpecification, - ): Promise { + async getQueryRelationType(query: V1_Lambda, source: DataCubeSource) { return this.client.getQueryRelationReturnType({ query: V1_serializeValueSpecification(query, []), }); @@ -153,21 +162,22 @@ export class LegendREPLDataCubeEngine extends DataCubeEngine { async getQueryCodeRelationReturnType( code: string, baseQuery: V1_ValueSpecification, - ): Promise { + source: DataCubeSource, + ) { return this.client.getQueryCodeRelationReturnType({ code, baseQuery: V1_serializeValueSpecification(baseQuery, []), }); } - async executeQuery(query: V1_Lambda): Promise<{ - result: TDSExecutionResult; - executedQuery: string; - executedSQL: string; - }> { + async executeQuery( + query: V1_Lambda, + source: DataCubeSource, + api: DataCubeAPI, + ) { const result = await this.client.executeQuery({ query: V1_serializeValueSpecification(query, []), - debug: this.enableDebugMode, + debug: api.getSettings().enableDebugMode, }); return { result: guaranteeType( @@ -180,4 +190,80 @@ export class LegendREPLDataCubeEngine extends DataCubeEngine { executedSQL: result.executedSQL, }; } + + override buildExecutionContext( + source: DataCubeSource, + ): V1_AppliedFunction | undefined { + if (source instanceof LegendREPLDataCubeSource) { + return _function( + DataCubeFunction.FROM, + [ + source.mapping ? _elementPtr(source.mapping) : undefined, + _elementPtr(source.runtime), + ].filter(isNonNullable), + ); + } + return undefined; + } + + override getDocumentationURL(): string | undefined { + return this.application.documentationService.url; + } + + override getDocumentationEntry(key: string) { + return this.application.documentationService.getDocEntry(key); + } + + override shouldDisplayDocumentationEntry(entry: DocumentationEntry) { + return shouldDisplayVirtualAssistantDocumentationEntry(entry); + } + + override openLink(url: string) { + this.application.navigationService.navigator.visitAddress(url); + } + + override sendTelemetry(event: string, data: PlainObject) { + this.application.telemetryService.logEvent(event, data); + } + + override logDebug(message: string, ...data: unknown[]) { + this.application.logService.debug( + LogEvent.create(APPLICATION_EVENT.DEBUG), + message, + ...data, + ); + } + + override debugProcess(processName: string, ...data: [string, unknown][]) { + this.application.logService.debug( + LogEvent.create(APPLICATION_EVENT.DEBUG), + `\n------ START DEBUG PROCESS: ${processName} ------`, + ...data.flatMap(([key, value]) => [`\n[${key.toUpperCase()}]:`, value]), + `\n------- END DEBUG PROCESS: ${processName} -------\n\n`, + ); + } + + override logInfo(event: LogEvent, ...data: unknown[]) { + this.application.logService.info(event, ...data); + } + + override logWarning(event: LogEvent, ...data: unknown[]) { + this.application.logService.warn(event, ...data); + } + + override logError(event: LogEvent, ...data: unknown[]) { + this.application.logService.error(event, ...data); + } + + override logUnhandledError(error: Error) { + this.application.logUnhandledError(error); + } + + override logIllegalStateError(message: string, error?: Error) { + this.logError( + LogEvent.create(APPLICATION_EVENT.ILLEGAL_APPLICATION_STATE_OCCURRED), + message, + error, + ); + } } diff --git a/packages/legend-application-repl/src/stores/LegendREPLDataCubeSource.ts b/packages/legend-application-repl/src/stores/LegendREPLDataCubeSource.ts new file mode 100644 index 0000000000..4995f6027c --- /dev/null +++ b/packages/legend-application-repl/src/stores/LegendREPLDataCubeSource.ts @@ -0,0 +1,23 @@ +/** + * 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 { DataCubeSource } from '@finos/legend-data-cube'; + +export class LegendREPLDataCubeSource extends DataCubeSource { + runtime!: string; + mapping?: string | undefined; + timestamp!: number; +} diff --git a/packages/legend-application-repl/src/stores/LegendREPLServerClient.ts b/packages/legend-application-repl/src/stores/LegendREPLServerClient.ts index 065dcb3ad3..997c307f07 100644 --- a/packages/legend-application-repl/src/stores/LegendREPLServerClient.ts +++ b/packages/legend-application-repl/src/stores/LegendREPLServerClient.ts @@ -18,52 +18,86 @@ import { ContentType, guaranteeNonNullable, HttpHeader, + SerializationFactory, + usingModelSchema, type NetworkClient, type PlainObject, } from '@finos/legend-shared'; -import type { - CompletionItem, - RelationType, - DataCubeGetBaseQueryResult, - DataCubeInfrastructureInfo, +import { + DataCubeQuery, + type CompletionItem, + type RelationType, } from '@finos/legend-data-cube'; import type { V1_Lambda, V1_ValueSpecification } from '@finos/legend-graph'; +import { createModelSchema, optional, primitive } from 'serializr'; -type DataCubeGetQueryCodeInput = { - query: PlainObject; +type GetValueSpecificationCodeInput = { + value: PlainObject; pretty?: boolean | undefined; }; -type DataCubeParseQueryInput = { +type ParseValueSpecificationInput = { code: string; returnSourceInformation?: boolean | undefined; }; -type DataCubeQueryTypeaheadInput = { +type QueryTypeaheadInput = { code: string; - baseQuery?: PlainObject; + baseQuery?: PlainObject; }; -type DataCubeGetQueryRelationReturnTypeInput = { +type GetQueryRelationReturnTypeInput = { query: PlainObject; }; -type DataCubeGetQueryCodeRelationReturnTypeInput = { +type GetQueryCodeRelationReturnTypeInput = { code: string; baseQuery?: PlainObject; }; -type DataCubeExecutionInput = { +type ExecutionInput = { query: PlainObject; debug?: boolean | undefined; }; -type DataCubeExecutionResult = { +type ExecutionResult = { result: string; executedQuery: string; executedSQL: string; }; +type InfrastructureInfo = { + gridClientLicense?: string | undefined; +}; + +class QuerySource { + runtime!: string; + mapping?: string | undefined; + query!: string; + timestamp!: number; + + static readonly serialization = new SerializationFactory( + createModelSchema(QuerySource, { + mapping: optional(primitive()), + query: primitive(), + runtime: primitive(), + timestamp: primitive(), + }), + ); +} + +export class GetBaseQueryResult { + query!: DataCubeQuery; + source!: QuerySource; + + static readonly serialization = new SerializationFactory( + createModelSchema(GetBaseQueryResult, { + query: usingModelSchema(DataCubeQuery.serialization.schema), + source: usingModelSchema(QuerySource.serialization.schema), + }), + ); +} + export class LegendREPLServerClient { private readonly networkClient: NetworkClient; @@ -82,37 +116,42 @@ export class LegendREPLServerClient { return `${this.baseUrl}/api/dataCube`; } - async getInfrastructureInfo(): Promise { + async getInfrastructureInfo(): Promise { return this.networkClient.get(`${this.dataCube}/infrastructureInfo`); } async getQueryTypeahead( - input: DataCubeQueryTypeaheadInput, + input: QueryTypeaheadInput, ): Promise { return this.networkClient.post(`${this.dataCube}/typeahead`, input); } - async parseQuery( - input: DataCubeParseQueryInput, + async parseValueSpecification( + input: ParseValueSpecificationInput, ): Promise> { - return this.networkClient.post(`${this.dataCube}/parseQuery`, input); + return this.networkClient.post( + `${this.dataCube}/parseValueSpecification`, + input, + ); } - async getQueryCode(input: DataCubeGetQueryCodeInput): Promise { + async getValueSpecificationCode( + input: GetValueSpecificationCodeInput, + ): Promise { return this.networkClient.post( - `${this.dataCube}/getQueryCode`, + `${this.dataCube}/getValueSpecificationCode`, input, {}, { [HttpHeader.ACCEPT]: ContentType.TEXT_PLAIN }, ); } - async getBaseQuery(): Promise> { + async getBaseQuery(): Promise> { return this.networkClient.get(`${this.dataCube}/getBaseQuery`); } async getQueryRelationReturnType( - input: DataCubeGetQueryRelationReturnTypeInput, + input: GetQueryRelationReturnTypeInput, ): Promise { return this.networkClient.post( `${this.dataCube}/getRelationReturnType`, @@ -121,7 +160,7 @@ export class LegendREPLServerClient { } async getQueryCodeRelationReturnType( - input: DataCubeGetQueryCodeRelationReturnTypeInput, + input: GetQueryCodeRelationReturnTypeInput, ): Promise { return this.networkClient.post( `${this.dataCube}/getRelationReturnType/code`, @@ -130,8 +169,8 @@ export class LegendREPLServerClient { } async executeQuery( - input: PlainObject, - ): Promise { + input: PlainObject, + ): Promise { return this.networkClient.post(`${this.dataCube}/executeQuery`, input); } } diff --git a/packages/legend-data-cube/src/components/DataCube.tsx b/packages/legend-data-cube/src/components/DataCube.tsx index aec13d3bb7..b735a83270 100644 --- a/packages/legend-data-cube/src/components/DataCube.tsx +++ b/packages/legend-data-cube/src/components/DataCube.tsx @@ -14,70 +14,27 @@ * limitations under the License. */ -import { observer } from 'mobx-react-lite'; -import { useEffect } from 'react'; -import { DataCubeGrid } from './view/grid/DataCubeGrid.js'; +import { observer, useLocalObservable } from 'mobx-react-lite'; import { DataCubeIcon, DropdownMenu, DropdownMenuItem, - ProgressBar, useDropdownMenu, } from '@finos/legend-art'; import { DataCubeLayoutManager } from './core/DataCubeLayoutManager.js'; -import type { DataCubeViewState } from '../stores/view/DataCubeViewState.js'; import { INTERNAL__MonacoEditorWidgetsRoot } from './core/DataCubePureCodeEditorUtils.js'; -import { useDataCube } from './DataCubeProvider.js'; import { DataCubeBlockingActionAlert } from './core/DataCubeAlert.js'; +import { DataCubeView } from './DataCubeView.js'; +import { useEffect } from 'react'; +import type { DataCubeEngine } from '../stores/core/DataCubeEngine.js'; +import { DataCubeState } from '../stores/DataCubeState.js'; +import { type DataCubeOptions } from '../stores/DataCubeOptions.js'; +import { DataCubeContextProvider, useDataCube } from './DataCubeProvider.js'; -const DataCubeStatusBar = observer((props: { view: DataCubeViewState }) => { - const { view } = props; - - return ( -
-
- -
- -
-
-
-
- {view.runningTasks.size > 0 && ( - - )} -
-
-
- ); -}); - -// TODO?: we might need to move this up a level to accomondate for multi-view use case -// as only the top-level view should have their own title bar -const DataCubeTitleBar = observer((props: { view: DataCubeViewState }) => { - const { view } = props; - const application = view.application; +const DataCubeTitleBar = observer(() => { + const dataCube = useDataCube(); + const engine = dataCube.engine; + const view = dataCube.view; const [openMenuDropdown, closeMenuDropdown, menuDropdownProps] = useDropdownMenu(); @@ -108,8 +65,9 @@ const DataCubeTitleBar = observer((props: { view: DataCubeViewState }) => { { - if (application.documentationUrl) { - application.openLink(application.documentationUrl); + const url = engine.getDocumentationURL(); + if (url) { + engine.openLink(url); } closeMenuDropdown(); }} @@ -133,26 +91,51 @@ const DataCubeTitleBar = observer((props: { view: DataCubeViewState }) => { ); }); -export const DataCube = observer(() => { +const DataCubeRoot = observer(() => { const dataCube = useDataCube(); - const application = dataCube.application; + const engine = dataCube.engine; const view = dataCube.view; useEffect(() => { - view.initialize().catch((error) => application.logUnhandledError(error)); - }, [view, application]); + dataCube.view + .initialize() + .catch((error) => dataCube.engine.logUnhandledError(error)); + }, [dataCube]); return (
- + - - + - {/* TODO: move this to upper layer component when we have multi-view support */} - +
); }); + +export const DataCube = observer( + (props: { + engine: DataCubeEngine; + options?: DataCubeOptions | undefined; + }): React.ReactElement => { + const { engine, options } = props; + const state = useLocalObservable(() => new DataCubeState(engine, options)); + + useEffect(() => { + state + .initialize() + .catch((error) => state.engine.logUnhandledError(error)); + }, [state]); + + if (!state.initState.hasSucceeded) { + return <>; + } + return ( + + + + ); + }, +); diff --git a/packages/legend-data-cube/src/components/DataCubeProvider.tsx b/packages/legend-data-cube/src/components/DataCubeProvider.tsx index fe9a7ceea9..8826ffafb0 100644 --- a/packages/legend-data-cube/src/components/DataCubeProvider.tsx +++ b/packages/legend-data-cube/src/components/DataCubeProvider.tsx @@ -14,43 +14,15 @@ * limitations under the License. */ -import { createContext, useContext, useEffect } from 'react'; -import { observer, useLocalObservable } from 'mobx-react-lite'; +import { createContext, useContext } from 'react'; import { guaranteeNonNullable } from '@finos/legend-shared'; -import { DataCubeState } from '../stores/DataCubeState.js'; -import type { DataCubeApplicationEngine } from '../stores/core/DataCubeApplicationEngine.js'; -import type { DataCubeEngine } from '../stores/core/DataCubeEngine.js'; +import { type DataCubeState } from '../stores/DataCubeState.js'; const DataCubeStateContext = createContext( undefined, ); -export const DataCubeProvider = observer( - (props: { - children: React.ReactNode; - application: DataCubeApplicationEngine; - engine: DataCubeEngine; - }): React.ReactElement => { - const { children, application, engine } = props; - const store = useLocalObservable( - () => new DataCubeState(application, engine), - ); - - useEffect(() => { - store.initialize().catch((error) => application.logUnhandledError(error)); - }, [store, application]); - - if (!store.initState.hasSucceeded) { - return <>; - } - return ( - - {children} - - ); - }, -); - +export const DataCubeContextProvider = DataCubeStateContext.Provider; export const useDataCube = () => guaranteeNonNullable( useContext(DataCubeStateContext), diff --git a/packages/legend-data-cube/src/components/DataCubeView.tsx b/packages/legend-data-cube/src/components/DataCubeView.tsx new file mode 100644 index 0000000000..365c2e93e4 --- /dev/null +++ b/packages/legend-data-cube/src/components/DataCubeView.tsx @@ -0,0 +1,74 @@ +/** + * 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 { DataCubeIcon, ProgressBar } from '@finos/legend-art'; +import { observer } from 'mobx-react-lite'; +import type { DataCubeViewState } from '../stores/view/DataCubeViewState.js'; +import { DataCubeGrid } from './view/grid/DataCubeGrid.js'; + +const DataCubeStatusBar = observer((props: { view: DataCubeViewState }) => { + const { view } = props; + + return ( +
+
+ +
+ +
+
+
+
+ {view.runningTasks.size > 0 && ( + + )} +
+
+
+ ); +}); + +export const DataCubeView = observer((props: { view: DataCubeViewState }) => { + const { view } = props; + + return ( + <> + + + + ); +}); diff --git a/packages/legend-data-cube/src/components/core/DataCubeAlert.tsx b/packages/legend-data-cube/src/components/core/DataCubeAlert.tsx index 2035d2638f..bcbdae0348 100644 --- a/packages/legend-data-cube/src/components/core/DataCubeAlert.tsx +++ b/packages/legend-data-cube/src/components/core/DataCubeAlert.tsx @@ -100,7 +100,6 @@ const BlockingActionAlertContent = observer((props: { alert: ActionAlert }) => { const { title, message, prompt, type, onClose, actions } = alert; const ref = useRef(null); const dataCube = useDataCube(); - const application = dataCube.application; // set the width and height of the dialog to make sure content overflow works properly const handleEnter = () => { @@ -151,7 +150,7 @@ const BlockingActionAlertContent = observer((props: { alert: ActionAlert }) => { handler: () => { action.handler(); onClose?.(); - application.alertAction(undefined); + dataCube.alertAction(undefined); }, }))} /> @@ -163,8 +162,7 @@ const BlockingActionAlertContent = observer((props: { alert: ActionAlert }) => { export const DataCubeBlockingActionAlert = observer(() => { const dataCube = useDataCube(); - const application = dataCube.application; - const actionAlert = application.currentActionAlert; + const actionAlert = dataCube.currentActionAlert; if (!actionAlert) { return null; diff --git a/packages/legend-data-cube/src/components/core/DataCubeDocumentationPanel.tsx b/packages/legend-data-cube/src/components/core/DataCubeDocumentationPanel.tsx index 719379a37f..28390c0c90 100644 --- a/packages/legend-data-cube/src/components/core/DataCubeDocumentationPanel.tsx +++ b/packages/legend-data-cube/src/components/core/DataCubeDocumentationPanel.tsx @@ -21,8 +21,7 @@ import { useDataCube } from '../DataCubeProvider.js'; export const DocumentationPanel = observer(() => { const dataCube = useDataCube(); - const application = dataCube.application; - const entry = application.currentDocumentationEntry; + const entry = dataCube.currentDocumentationEntry; if (!entry) { return null; diff --git a/packages/legend-data-cube/src/components/core/DataCubeFormUtils.tsx b/packages/legend-data-cube/src/components/core/DataCubeFormUtils.tsx index bc541aa88a..9fd9f97d8e 100644 --- a/packages/legend-data-cube/src/components/core/DataCubeFormUtils.tsx +++ b/packages/legend-data-cube/src/components/core/DataCubeFormUtils.tsx @@ -538,19 +538,18 @@ export const FormDocumentation: React.FC<{ className?: string | undefined; }> = ({ documentationKey, title, className }) => { const dataCube = useDataCube(); - const application = dataCube.application; - const documentationEntry = - application.getDocumentationEntry(documentationKey); + const engine = dataCube.engine; + const documentationEntry = engine.getDocumentationEntry(documentationKey); const openDocLink: React.MouseEventHandler = (event) => { event.preventDefault(); event.stopPropagation(); - const entry = application.getDocumentationEntry(documentationKey); + const entry = engine.getDocumentationEntry(documentationKey); if (entry) { - if (application.shouldDisplayDocumentationEntry(entry)) { - application.openDocumentationEntry(entry); + if (engine.shouldDisplayDocumentationEntry(entry)) { + dataCube.openDocumentationEntry(entry); dataCube.documentationDisplay.open(); } else if (entry.url) { - application.openLink(entry.url); + engine.openLink(entry.url); } } }; @@ -558,7 +557,7 @@ export const FormDocumentation: React.FC<{ if ( !documentationEntry || (!documentationEntry.url && - !application.shouldDisplayDocumentationEntry(documentationEntry)) + !engine.shouldDisplayDocumentationEntry(documentationEntry)) ) { return null; } diff --git a/packages/legend-data-cube/src/components/core/DataCubePureCodeEditorUtils.tsx b/packages/legend-data-cube/src/components/core/DataCubePureCodeEditorUtils.tsx index d043da7213..5ae191e049 100644 --- a/packages/legend-data-cube/src/components/core/DataCubePureCodeEditorUtils.tsx +++ b/packages/legend-data-cube/src/components/core/DataCubePureCodeEditorUtils.tsx @@ -19,11 +19,9 @@ import { languages as monacoLanguagesAPI, type IPosition, } from 'monaco-editor'; -import type { - CompletionItem, - DataCubeEngine, -} from '../../stores/core/DataCubeEngine.js'; -import type { V1_ValueSpecification } from '@finos/legend-graph'; +import type { CompletionItem } from '../../stores/core/DataCubeEngine.js'; +import type { V1_Lambda } from '@finos/legend-graph'; +import type { DataCubeViewState } from '../../stores/view/DataCubeViewState.js'; // Since we render the editor in a window which has been CSS transformed, and monaco-editor renders // the widgets with position=fixed, the position of the widgets will be off, we need to move the root @@ -45,8 +43,8 @@ export async function getCodeSuggestions( position: IPosition, model: monacoEditorAPI.ITextModel, prefix: string | undefined, - engine: DataCubeEngine, - baseQueryBuilder: () => V1_ValueSpecification, + view: DataCubeViewState, + baseQueryBuilder: () => V1_Lambda, ) { const textUntilPosition = model.getValueInRange({ startLineNumber: 1, @@ -59,9 +57,10 @@ export async function getCodeSuggestions( let suggestions: CompletionItem[] = []; try { - suggestions = await engine.getQueryTypeahead( + suggestions = await view.engine.getQueryTypeahead( (prefix ?? '') + textUntilPosition, baseQueryBuilder(), + view.source, ); } catch { // do nothing: provide no suggestions when error ocurred diff --git a/packages/legend-data-cube/src/components/core/DataCubeSettingsPanel.tsx b/packages/legend-data-cube/src/components/core/DataCubeSettingsPanel.tsx index f2a60acaba..1ad977362f 100644 --- a/packages/legend-data-cube/src/components/core/DataCubeSettingsPanel.tsx +++ b/packages/legend-data-cube/src/components/core/DataCubeSettingsPanel.tsx @@ -17,51 +17,54 @@ import { observer } from 'mobx-react-lite'; import { DataCubeIcon } from '@finos/legend-art'; import { FormCheckbox, FormNumberInput } from './DataCubeFormUtils.js'; -import { - DEFAULT_ENABLE_DEBUG_MODE, - DEFAULT_GRID_CLIENT_PURGE_CLOSED_ROW_NODES, - DEFAULT_GRID_CLIENT_ROW_BUFFER, - DEFAULT_GRID_CLIENT_SUPPRESS_LARGE_DATASET_WARNING, -} from '../../stores/core/DataCubeEngine.js'; import { useState } from 'react'; import { useDataCube } from '../DataCubeProvider.js'; +import { + DataCubeSettingKey, + DEFAULT_SETTINGS, +} from '../../stores/DataCubeSettings.js'; export const DataCubeSettingsPanel = observer(() => { const dataCube = useDataCube(); - const engine = dataCube.engine; // NOTE: this makes sure the changes are not applied until saved, but it generates // a lot of boilerplate code, consider using a more ergonomic approach when we need // to scale this to more settings. const [enableDebugMode, setEnableDebugMode] = useState( - engine.enableDebugMode, + dataCube.settings.enableDebugMode, ); const [gridClientRowBuffer, setGridClientRowBuffer] = useState( - engine.gridClientRowBuffer, + dataCube.settings.gridClientRowBuffer, ); const [gridClientPurgeClosedRowNodes, setGridClientPurgeClosedRowNodes] = - useState(engine.gridClientPurgeClosedRowNodes); + useState(dataCube.settings.gridClientPurgeClosedRowNodes); const [ gridClientSuppressLargeDatasetWarning, setGridClientSuppressLargeDatasetWarning, - ] = useState(engine.gridClientSuppressLargeDatasetWarning); + ] = useState(dataCube.settings.gridClientSuppressLargeDatasetWarning); const save = () => { - engine.setEnableDebugMode(enableDebugMode); - engine.setGridClientRowBuffer(gridClientRowBuffer); - engine.setGridClientPurgeClosedRowNodes(gridClientPurgeClosedRowNodes); - engine.setGridClientSuppressLargeDatasetWarning( + dataCube.settings.setEnableDebugMode(enableDebugMode); + dataCube.settings.setGridClientRowBuffer(gridClientRowBuffer); + dataCube.settings.setGridClientPurgeClosedRowNodes( + gridClientPurgeClosedRowNodes, + ); + dataCube.settings.setGridClientSuppressLargeDatasetWarning( gridClientSuppressLargeDatasetWarning, ); }; const restoreDefaults = () => { - setGridClientRowBuffer(DEFAULT_GRID_CLIENT_ROW_BUFFER); + setEnableDebugMode(DEFAULT_SETTINGS[DataCubeSettingKey.ENABLE_DEBUG_MODE]); + setGridClientRowBuffer( + DEFAULT_SETTINGS[DataCubeSettingKey.GRID_CLIENT_ROW_BUFFER], + ); setGridClientPurgeClosedRowNodes( - DEFAULT_GRID_CLIENT_PURGE_CLOSED_ROW_NODES, + DEFAULT_SETTINGS[DataCubeSettingKey.GRID_CLIENT_PURGE_CLOSED_ROW_NODES], ); - setEnableDebugMode(DEFAULT_ENABLE_DEBUG_MODE); setGridClientSuppressLargeDatasetWarning( - DEFAULT_GRID_CLIENT_SUPPRESS_LARGE_DATASET_WARNING, + DEFAULT_SETTINGS[ + DataCubeSettingKey.GRID_CLIENT_SUPPRESS_LARGE_DATASET_WARNING + ], ); save(); }; @@ -102,7 +105,7 @@ export const DataCubeSettingsPanel = observer(() => {
@@ -132,11 +135,16 @@ export const DataCubeSettingsPanel = observer(() => { className="w-16 text-sm" min={10} step={10} - defaultValue={DEFAULT_GRID_CLIENT_ROW_BUFFER} + defaultValue={ + DEFAULT_SETTINGS[DataCubeSettingKey.GRID_CLIENT_ROW_BUFFER] + } value={gridClientRowBuffer} setValue={(value) => { setGridClientRowBuffer( - value ?? DEFAULT_GRID_CLIENT_ROW_BUFFER, + value ?? + DEFAULT_SETTINGS[ + DataCubeSettingKey.GRID_CLIENT_ROW_BUFFER + ], ); }} /> diff --git a/packages/legend-data-cube/src/components/view/editor/DataCubeEditor.tsx b/packages/legend-data-cube/src/components/view/editor/DataCubeEditor.tsx index f1155026ed..46739ca6fe 100644 --- a/packages/legend-data-cube/src/components/view/editor/DataCubeEditor.tsx +++ b/packages/legend-data-cube/src/components/view/editor/DataCubeEditor.tsx @@ -28,7 +28,7 @@ import type { DataCubeViewState } from '../../../stores/view/DataCubeViewState.j export const DataCubeEditor = observer((props: { view: DataCubeViewState }) => { const { view } = props; const editor = view.editor; - const application = view.application; + const engine = view.engine; const selectedTab = editor.currentTab; const tabs = [ DataCubeEditorTab.COLUMNS, @@ -86,7 +86,7 @@ export const DataCubeEditor = observer((props: { view: DataCubeViewState }) => { onClick={() => { editor .applyChanges({ closeAfterApply: true }) - .catch((error) => application.alertUnhandledError(error)); + .catch((error) => engine.alertUnhandledError(error)); }} > OK @@ -103,7 +103,7 @@ export const DataCubeEditor = observer((props: { view: DataCubeViewState }) => { onClick={() => { editor .applyChanges() - .catch((error) => application.alertUnhandledError(error)); + .catch((error) => engine.alertUnhandledError(error)); }} > Apply diff --git a/packages/legend-data-cube/src/components/view/editor/DataCubeEditorColumnPropertiesPanel.tsx b/packages/legend-data-cube/src/components/view/editor/DataCubeEditorColumnPropertiesPanel.tsx index ba34318fdb..4ab302dcdd 100644 --- a/packages/legend-data-cube/src/components/view/editor/DataCubeEditorColumnPropertiesPanel.tsx +++ b/packages/legend-data-cube/src/components/view/editor/DataCubeEditorColumnPropertiesPanel.tsx @@ -45,7 +45,7 @@ import { } from '../../../stores/core/DataCubeQueryEngine.js'; import { DocumentationKey } from '../../../__lib__/DataCubeDocumentation.js'; import type { DataCubeViewState } from '../../../stores/view/DataCubeViewState.js'; -import { _sortByColName } from '../../../stores/core/DataCubeQuerySnapshot.js'; +import { _sortByColName } from '../../../stores/core/models/DataCubeColumn.js'; export const DataCubeEditorColumnPropertiesPanel = observer( (props: { view: DataCubeViewState }) => { diff --git a/packages/legend-data-cube/src/components/view/editor/DataCubeEditorGeneralPropertiesPanel.tsx b/packages/legend-data-cube/src/components/view/editor/DataCubeEditorGeneralPropertiesPanel.tsx index 44d23eb271..9cb113a69b 100644 --- a/packages/legend-data-cube/src/components/view/editor/DataCubeEditorGeneralPropertiesPanel.tsx +++ b/packages/legend-data-cube/src/components/view/editor/DataCubeEditorGeneralPropertiesPanel.tsx @@ -98,9 +98,9 @@ export const DataCubeEditorGeneralPropertiesPanel = observer(
{ - panel.setName(event.target.value); + configuration.setName(event.target.value); }} /> diff --git a/packages/legend-data-cube/src/components/view/extend/DataCubeColumnEditor.tsx b/packages/legend-data-cube/src/components/view/extend/DataCubeColumnEditor.tsx index 7fc0e6e8ee..76cffc8290 100644 --- a/packages/legend-data-cube/src/components/view/extend/DataCubeColumnEditor.tsx +++ b/packages/legend-data-cube/src/components/view/extend/DataCubeColumnEditor.tsx @@ -60,7 +60,7 @@ export const DataCubeColumnCreator = observer( (props: { state: DataCubeColumnBaseEditorState }) => { const { state } = props; const view = state.view; - const application = view.application; + const engine = view.engine; const nameInputRef = useRef(null); const currentColumnKind = state.isGroupLevel @@ -91,9 +91,9 @@ export const DataCubeColumnCreator = observer( debounce((): void => { state .getReturnType() - .catch((error) => application.alertUnhandledError(error)); + .catch((error) => engine.alertUnhandledError(error)); }, 500), - [state, application], + [state, engine], ); useEffect(() => { @@ -136,7 +136,7 @@ export const DataCubeColumnCreator = observer( position, model, state.codePrefix, - view.engine, + view, () => state.buildExtendBaseQuery(), ), ); @@ -351,7 +351,7 @@ export const DataCubeColumnCreator = observer( onClick={() => { state .applyChanges() - .catch((error) => application.alertUnhandledError(error)); + .catch((error) => engine.alertUnhandledError(error)); }} > OK @@ -363,7 +363,7 @@ export const DataCubeColumnCreator = observer( onClick={() => { state.manager .deleteColumn(state.initialData.name) - .catch((error) => application.alertUnhandledError(error)); + .catch((error) => engine.alertUnhandledError(error)); }} > Delete @@ -373,7 +373,7 @@ export const DataCubeColumnCreator = observer( onClick={() => { state .reset() - .catch((error) => application.alertUnhandledError(error)); + .catch((error) => engine.alertUnhandledError(error)); }} > Reset diff --git a/packages/legend-data-cube/src/components/view/grid/DataCubeGrid.tsx b/packages/legend-data-cube/src/components/view/grid/DataCubeGrid.tsx index b106557fc4..58a5468946 100644 --- a/packages/legend-data-cube/src/components/view/grid/DataCubeGrid.tsx +++ b/packages/legend-data-cube/src/components/view/grid/DataCubeGrid.tsx @@ -49,7 +49,7 @@ import { isNonNullable } from '@finos/legend-shared'; import type { DataCubeConfiguration, DataCubeConfigurationColorKey, -} from '../../../stores/core/DataCubeConfiguration.js'; +} from '../../../stores/core/models/DataCubeConfiguration.js'; import { generateBaseGridOptions } from '../../../stores/view/grid/DataCubeGridConfigurationBuilder.js'; import type { DataCubeViewState } from '../../../stores/view/DataCubeViewState.js'; @@ -58,10 +58,13 @@ import type { DataCubeViewState } from '../../../stores/view/DataCubeViewState.j // We MUST NEVER completely surpress this warning in production, else it's a violation of the ag-grid license! // See https://www.ag-grid.com/react-data-grid/licensing/ const __INTERNAL__original_console_error = console.error; // eslint-disable-line no-console -// eslint-disable-next-line no-console -console.error = (message?: unknown, ...agrs: unknown[]) => { - console.debug(`%c ${message}`, 'color: silver'); // eslint-disable-line no-console -}; +// eslint-disable-next-line no-process-env +if (process.env.NODE_ENV === 'development') { + // eslint-disable-next-line no-console + console.error = (message?: unknown, ...agrs: unknown[]) => { + console.debug(`%c ${message}`, 'color: silver'); // eslint-disable-line no-console + }; +} function textColorStyle( key: DataCubeConfigurationColorKey, @@ -348,8 +351,11 @@ const DataCubeGridClient = observer((props: { view: DataCubeViewState }) => { }} onGridReady={(params) => { grid.configureClient(params.api); - // restore original error logging - console.error = __INTERNAL__original_console_error; // eslint-disable-line no-console + // eslint-disable-next-line no-process-env + if (process.env.NODE_ENV === 'development') { + // restore original error logging + console.error = __INTERNAL__original_console_error; // eslint-disable-line no-console + } }} modules={[ // community diff --git a/packages/legend-data-cube/src/index.tsx b/packages/legend-data-cube/src/index.tsx index 7d4792cb8f..dff350dca7 100644 --- a/packages/legend-data-cube/src/index.tsx +++ b/packages/legend-data-cube/src/index.tsx @@ -14,11 +14,15 @@ * limitations under the License. */ +export * from './stores/core/models/DataCubeQuery.js'; +export * from './stores/core/models/DataCubeSource.js'; + export * from './stores/core/DataCubeEngine.js'; -export * from './stores/core/DataCubeApplicationEngine.js'; -export * from './stores/core/DataCubeQuery.js'; +export * from './stores/core/DataCubeQueryEngine.js'; export * from './stores/core/DataCubeQueryBuilderUtils.js'; - export * from './components/core/DataCubeAlert.js'; + export * from './components/DataCube.js'; -export * from './components/DataCubeProvider.js'; +export * from './stores/DataCubeAPI.js'; +export * from './stores/DataCubeOptions.js'; +export { DataCubeSettingKey } from './stores/DataCubeSettings.js'; diff --git a/packages/legend-data-cube/src/stores/DataCubeAPI.ts b/packages/legend-data-cube/src/stores/DataCubeAPI.ts new file mode 100644 index 0000000000..36bc2d6ea9 --- /dev/null +++ b/packages/legend-data-cube/src/stores/DataCubeAPI.ts @@ -0,0 +1,22 @@ +/** + * 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 type { DataCubeSettings } from './DataCubeSettings.js'; + +export interface DataCubeAPI { + getSettings(): DataCubeSettings; + refreshFailedDataFetches(): void; +} diff --git a/packages/legend-data-cube/src/stores/DataCubeOptions.ts b/packages/legend-data-cube/src/stores/DataCubeOptions.ts new file mode 100644 index 0000000000..7ca2bf4b27 --- /dev/null +++ b/packages/legend-data-cube/src/stores/DataCubeOptions.ts @@ -0,0 +1,34 @@ +/** + * 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 type { DataCubeInitialInput } from './core/DataCubeEngine.js'; +import type { DataCubeSource } from './core/models/DataCubeSource.js'; + +export type DataCubeOptions = { + enableDebugMode?: boolean | undefined; + gridClientRowBuffer?: number | undefined; + gridClientPurgeClosedRowNodes?: boolean | undefined; + gridClientSuppressLargeDatasetWarning?: boolean | undefined; + initialInput?: DataCubeInitialInput | undefined; + + onNameChanged?: ((name: string, source: DataCubeSource) => void) | undefined; + onSettingChanged?: + | (( + key: string, + value: string | number | boolean | object | undefined, + ) => void) + | undefined; +}; diff --git a/packages/legend-data-cube/src/stores/DataCubeSettings.ts b/packages/legend-data-cube/src/stores/DataCubeSettings.ts new file mode 100644 index 0000000000..8882a45ea3 --- /dev/null +++ b/packages/legend-data-cube/src/stores/DataCubeSettings.ts @@ -0,0 +1,107 @@ +/** + * 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 { makeObservable, observable, action } from 'mobx'; +import type { DataCubeState } from './DataCubeState.js'; + +export enum DataCubeSettingKey { + ENABLE_DEBUG_MODE = 'engine.enableDebugMode', + GRID_CLIENT_ROW_BUFFER = 'engine.grid-client.rowBuffer', + GRID_CLIENT_PURGE_CLOSED_ROW_NODES = 'engine.grid-client.purgeClosedRowNodes', + GRID_CLIENT_SUPPRESS_LARGE_DATASET_WARNING = 'engine.grid-client.suppressLargeDatasetWarning', +} + +export const DEFAULT_SETTINGS = { + [DataCubeSettingKey.ENABLE_DEBUG_MODE]: false, + [DataCubeSettingKey.GRID_CLIENT_ROW_BUFFER]: 50, + [DataCubeSettingKey.GRID_CLIENT_PURGE_CLOSED_ROW_NODES]: false, + [DataCubeSettingKey.GRID_CLIENT_SUPPRESS_LARGE_DATASET_WARNING]: false, +}; + +export class DataCubeSettings { + readonly dataCube: DataCubeState; + + constructor(dataCube: DataCubeState) { + makeObservable(this, { + enableDebugMode: observable, + setEnableDebugMode: action, + + gridClientRowBuffer: observable, + setGridClientRowBuffer: action, + + gridClientPurgeClosedRowNodes: observable, + setGridClientPurgeClosedRowNodes: action, + + gridClientSuppressLargeDatasetWarning: observable, + setGridClientSuppressLargeDatasetWarning: action, + }); + + this.dataCube = dataCube; + } + + enableDebugMode = DEFAULT_SETTINGS[DataCubeSettingKey.ENABLE_DEBUG_MODE]; + gridClientRowBuffer = + DEFAULT_SETTINGS[DataCubeSettingKey.GRID_CLIENT_ROW_BUFFER]; + gridClientPurgeClosedRowNodes = + DEFAULT_SETTINGS[DataCubeSettingKey.GRID_CLIENT_PURGE_CLOSED_ROW_NODES]; + gridClientSuppressLargeDatasetWarning = + DEFAULT_SETTINGS[ + DataCubeSettingKey.GRID_CLIENT_SUPPRESS_LARGE_DATASET_WARNING + ]; + + setEnableDebugMode(value: boolean) { + this.enableDebugMode = value; + this.dataCube.onSettingChanged?.( + DataCubeSettingKey.ENABLE_DEBUG_MODE, + value, + ); + } + + setGridClientRowBuffer(value: number) { + this.gridClientRowBuffer = value; + this.dataCube.onSettingChanged?.( + DataCubeSettingKey.GRID_CLIENT_ROW_BUFFER, + value, + ); + this.propagateGridOptionUpdates(); + } + + setGridClientPurgeClosedRowNodes(value: boolean) { + this.gridClientPurgeClosedRowNodes = value; + this.dataCube.onSettingChanged?.( + DataCubeSettingKey.GRID_CLIENT_PURGE_CLOSED_ROW_NODES, + value, + ); + this.propagateGridOptionUpdates(); + } + + setGridClientSuppressLargeDatasetWarning(value: boolean) { + this.gridClientSuppressLargeDatasetWarning = value; + this.dataCube.onSettingChanged?.( + DataCubeSettingKey.GRID_CLIENT_SUPPRESS_LARGE_DATASET_WARNING, + value, + ); + } + + private propagateGridOptionUpdates() { + this.dataCube.runTaskForEachView((view) => { + view.grid.client.updateGridOptions({ + rowBuffer: this.gridClientRowBuffer, + purgeClosedRowNodes: this.gridClientPurgeClosedRowNodes, + }); + }); + } +} diff --git a/packages/legend-data-cube/src/stores/DataCubeState.tsx b/packages/legend-data-cube/src/stores/DataCubeState.tsx index bcb3e46f8c..aa765d22e9 100644 --- a/packages/legend-data-cube/src/stores/DataCubeState.tsx +++ b/packages/legend-data-cube/src/stores/DataCubeState.tsx @@ -14,39 +14,65 @@ * limitations under the License. */ -import { type DataCubeEngine } from './core/DataCubeEngine.js'; +import { + type DataCubeEngine, + type DataCubeInitialInput, +} from './core/DataCubeEngine.js'; import { DataCubeViewState } from './view/DataCubeViewState.js'; import type { DisplayState } from './core/DataCubeLayoutManagerState.js'; import { DocumentationPanel } from '../components/core/DataCubeDocumentationPanel.js'; import { DataCubeSettingsPanel } from '../components/core/DataCubeSettingsPanel.js'; -import { ActionState, assertErrorThrown } from '@finos/legend-shared'; -import { AlertType } from '../components/core/DataCubeAlert.js'; -import { type DataCubeApplicationEngine } from './core/DataCubeApplicationEngine.js'; +import { + ActionState, + assertErrorThrown, + type DocumentationEntry, +} from '@finos/legend-shared'; +import { + AlertType, + type ActionAlert, +} from '../components/core/DataCubeAlert.js'; +import type { DataCubeSource } from './core/models/DataCubeSource.js'; +import { action, makeObservable, observable } from 'mobx'; +import { DataCubeSettings } from './DataCubeSettings.js'; +import type { DataCubeAPI } from './DataCubeAPI.js'; +import type { DataCubeOptions } from './DataCubeOptions.js'; -export class DataCubeState { - readonly application: DataCubeApplicationEngine; +export class DataCubeState implements DataCubeAPI { readonly engine: DataCubeEngine; - + readonly settings!: DataCubeSettings; readonly initState = ActionState.create(); - readonly settingsDisplay: DisplayState; readonly documentationDisplay: DisplayState; - // NOTE: when we support multiview, there can be multiple view states to support // the first one in that list will be taken as the main view state readonly view: DataCubeViewState; - constructor(application: DataCubeApplicationEngine, engine: DataCubeEngine) { - this.application = application; + onNameChanged?: ((name: string, source: DataCubeSource) => void) | undefined; + onSettingChanged?: + | (( + key: string, + value: string | number | boolean | object | undefined, + ) => void) + | undefined; + + initialInput?: DataCubeInitialInput | undefined; + currentDocumentationEntry?: DocumentationEntry | undefined; + currentActionAlert?: ActionAlert | undefined; + + constructor(engine: DataCubeEngine, options?: DataCubeOptions | undefined) { + makeObservable(this, { + currentDocumentationEntry: observable, + openDocumentationEntry: action, + + currentActionAlert: observable, + alertAction: action, + }); + this.engine = engine; - this.engine.gridClientTaskRunner = (task) => { - // TODO: When we support multi-view (i.e. multiple instances of DataCubes) we would need - // to traverse through and update the configurations of all of their grid clients - task(this.view.grid.client); - }; + this.settings = new DataCubeSettings(this); this.view = new DataCubeViewState(this); - this.settingsDisplay = this.application.layout.newDisplay( + this.settingsDisplay = this.engine.layout.newDisplay( 'Settings', () => , { @@ -59,7 +85,7 @@ export class DataCubeState { center: false, }, ); - this.documentationDisplay = this.application.layout.newDisplay( + this.documentationDisplay = this.engine.layout.newDisplay( 'Documentation', () => , { @@ -72,11 +98,56 @@ export class DataCubeState { center: false, }, ); + + this.onNameChanged = options?.onNameChanged; + this.onSettingChanged = options?.onSettingChanged; + this.initialInput = options?.initialInput; + + this.settings.enableDebugMode = + options?.enableDebugMode !== undefined + ? options.enableDebugMode + : this.settings.enableDebugMode; + this.settings.gridClientRowBuffer = + options?.gridClientRowBuffer !== undefined + ? options.gridClientRowBuffer + : this.settings.gridClientRowBuffer; + this.settings.gridClientPurgeClosedRowNodes = + options?.gridClientPurgeClosedRowNodes !== undefined + ? options.gridClientPurgeClosedRowNodes + : this.settings.gridClientPurgeClosedRowNodes; + this.settings.gridClientSuppressLargeDatasetWarning = + options?.gridClientSuppressLargeDatasetWarning !== undefined + ? options.gridClientSuppressLargeDatasetWarning + : this.settings.gridClientSuppressLargeDatasetWarning; + } + + getSettings() { + return this.settings; + } + + openDocumentationEntry(entry: DocumentationEntry | undefined) { + this.currentDocumentationEntry = entry; + } + + alertAction(alert: ActionAlert | undefined) { + this.currentActionAlert = alert; + } + + refreshFailedDataFetches() { + this.runTaskForEachView((view) => { + view.grid.client.retryServerSideLoads(); + }); + } + + runTaskForEachView(runner: (view: DataCubeViewState) => void) { + // TODO: When we support multi-view (i.e. multiple instances of DataCubes) we would need + // to traverse through and update the configurations of all of their grid clients + runner(this.view); } async initialize() { if (!this.initState.isInInitialState) { - this.application.logDebug('REPL store is re-initialized'); + this.engine.logDebug('REPL store is re-initialized'); return; } this.initState.inProgress(); @@ -86,9 +157,9 @@ export class DataCubeState { this.initState.pass(); } catch (error: unknown) { assertErrorThrown(error); - this.application.alertAction({ + this.alertAction({ message: `Initialization Failure: ${error.message}`, - prompt: `Resolve the issue and reload the application.`, + prompt: `Resolve the issue and reload the engine.`, type: AlertType.ERROR, actions: [], }); diff --git a/packages/legend-data-cube/src/stores/core/DataCubeApplicationEngine.tsx b/packages/legend-data-cube/src/stores/core/DataCubeApplicationEngine.tsx deleted file mode 100644 index 469b26d3c6..0000000000 --- a/packages/legend-data-cube/src/stores/core/DataCubeApplicationEngine.tsx +++ /dev/null @@ -1,200 +0,0 @@ -/** - * 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 { - type LogEvent, - type DocumentationEntry, - uuid, -} from '@finos/legend-shared'; -import { action, makeObservable, observable } from 'mobx'; -import { - Alert, - AlertType, - type ActionAlert, - type ActionAlertAction, -} from '../../components/core/DataCubeAlert.js'; -import { - DEFAULT_SMALL_ALERT_WINDOW_CONFIG, - LayoutConfiguration, - LayoutManagerState, - WindowState, - type WindowConfiguration, -} from './DataCubeLayoutManagerState.js'; -import type { DataCubeQueryBuilderError } from './DataCubeEngine.js'; -import { CODE_EDITOR_LANGUAGE } from '@finos/legend-code-editor'; -import { editor as monacoEditorAPI, Uri } from 'monaco-editor'; -import { DataCubeCodeCheckErrorAlert } from '../../components/core/DataCubeCodeCheckErrorAlert.js'; - -export abstract class DataCubeApplicationEngine { - readonly layout: LayoutManagerState; - - currentDocumentationEntry: DocumentationEntry | undefined; - currentActionAlert: ActionAlert | undefined; - - constructor() { - makeObservable(this, { - currentDocumentationEntry: observable, - openDocumentationEntry: action, - - currentActionAlert: observable, - alertAction: action, - }); - - this.layout = new LayoutManagerState(); - } - - abstract get documentationUrl(): string | undefined; - abstract getDocumentationEntry(key: string): DocumentationEntry | undefined; - abstract openDocumentationEntry(entry: DocumentationEntry): void; - abstract shouldDisplayDocumentationEntry(entry: DocumentationEntry): boolean; - - abstract openLink(url: string): void; - abstract setWindowTitle(title: string): void; - - abstract logDebug(message: string, ...data: unknown[]): void; - abstract debugProcess( - processName: string, - ...data: [string, unknown][] - ): void; - abstract logInfo(event: LogEvent, ...data: unknown[]): void; - abstract logWarning(event: LogEvent, ...data: unknown[]): void; - abstract logError(event: LogEvent, ...data: unknown[]): void; - abstract logUnhandledError(error: Error): void; - abstract logIllegalStateError(message: string, error?: Error): void; - - alert(options: { - message: string; - type: AlertType; - text?: string | undefined; - actions?: ActionAlertAction[] | undefined; - windowTitle?: string | undefined; - windowConfig?: WindowConfiguration | undefined; - }) { - const { message, type, text, actions, windowTitle, windowConfig } = options; - const window = new WindowState( - new LayoutConfiguration(windowTitle ?? '', () => ( - this.layout.closeWindow(window)} - /> - )), - ); - window.configuration.window = - windowConfig ?? DEFAULT_SMALL_ALERT_WINDOW_CONFIG; - this.layout.newWindow(window); - } - - alertAction(alertInfo: ActionAlert | undefined) { - this.currentActionAlert = alertInfo; - } - - alertError( - error: Error, - options: { - message: string; - text?: string | undefined; - actions?: ActionAlertAction[] | undefined; - windowTitle?: string | undefined; - windowConfig?: WindowConfiguration | undefined; - }, - ) { - const { message, text, actions, windowTitle, windowConfig } = options; - const window = new WindowState( - new LayoutConfiguration(windowTitle ?? 'Error', () => ( - - )), - ); - window.configuration.window = - windowConfig ?? DEFAULT_SMALL_ALERT_WINDOW_CONFIG; - this.layout.newWindow(window); - } - - alertUnhandledError(error: Error) { - this.logUnhandledError(error); - this.alertError(error, { - message: error.message, - }); - } - - alertCodeCheckError( - error: DataCubeQueryBuilderError, - code: string, - codePrefix: string, - options: { - message: string; - text?: string | undefined; - actions?: ActionAlertAction[] | undefined; - windowTitle?: string | undefined; - windowConfig?: WindowConfiguration | undefined; - }, - ) { - const { message, text, windowTitle, windowConfig } = options; - // correct the source information since we added prefix to the code - // and reveal error in the editor - if (error.sourceInformation) { - error.sourceInformation.startColumn -= - error.sourceInformation.startLine === 1 ? codePrefix.length : 0; - error.sourceInformation.endColumn -= - error.sourceInformation.endLine === 1 ? codePrefix.length : 0; - const editorModel = monacoEditorAPI.createModel( - code, - CODE_EDITOR_LANGUAGE.PURE, - Uri.file(`/${uuid()}.pure`), - ); - - const fullRange = editorModel.getFullModelRange(); - if ( - error.sourceInformation.startLine < 1 || - (error.sourceInformation.startLine === 1 && - error.sourceInformation.startColumn < 1) || - error.sourceInformation.endLine > fullRange.endLineNumber || - (error.sourceInformation.endLine === fullRange.endLineNumber && - error.sourceInformation.endColumn > fullRange.endColumn) - ) { - error.sourceInformation.startColumn = fullRange.startColumn; - error.sourceInformation.startLine = fullRange.startLineNumber; - error.sourceInformation.endColumn = fullRange.endColumn; - error.sourceInformation.endLine = fullRange.endLineNumber; - } - const window = new WindowState( - new LayoutConfiguration(windowTitle ?? 'Error', () => ( - - )), - ); - window.configuration.window = windowConfig ?? { - width: 500, - height: 400, - minWidth: 300, - minHeight: 300, - center: true, - }; - this.layout.newWindow(window); - } - } -} diff --git a/packages/legend-data-cube/src/stores/core/DataCubeConfigurationBuilder.ts b/packages/legend-data-cube/src/stores/core/DataCubeConfigurationBuilder.ts index 30b76052ac..6618324aaa 100644 --- a/packages/legend-data-cube/src/stores/core/DataCubeConfigurationBuilder.ts +++ b/packages/legend-data-cube/src/stores/core/DataCubeConfigurationBuilder.ts @@ -18,17 +18,17 @@ import { PRIMITIVE_TYPE } from '@finos/legend-graph'; import { DataCubeColumnConfiguration, DataCubeConfiguration, -} from './DataCubeConfiguration.js'; +} from './models/DataCubeConfiguration.js'; import { DataCubeQueryAggregateOperator, DataCubeColumnKind, DataCubeFontTextAlignment, } from './DataCubeQueryEngine.js'; +import type { DataCubeColumn } from './models/DataCubeColumn.js'; -export function buildDefaultColumnConfiguration(column: { - name: string; - type: string; -}): DataCubeColumnConfiguration { +export function buildDefaultColumnConfiguration( + column: DataCubeColumn, +): DataCubeColumnConfiguration { const { name, type } = column; const config = new DataCubeColumnConfiguration(name, type); switch (type) { @@ -57,7 +57,7 @@ export function buildDefaultColumnConfiguration(column: { } export function buildDefaultConfiguration( - columns: { name: string; type: string }[], + columns: DataCubeColumn[], ): DataCubeConfiguration { const configuration = new DataCubeConfiguration(); configuration.columns = columns.map((column) => diff --git a/packages/legend-data-cube/src/stores/core/DataCubeEngine.ts b/packages/legend-data-cube/src/stores/core/DataCubeEngine.ts deleted file mode 100644 index fe3cbe55ae..0000000000 --- a/packages/legend-data-cube/src/stores/core/DataCubeEngine.ts +++ /dev/null @@ -1,327 +0,0 @@ -/** - * 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 { - type V1_ValueSpecification, - type V1_Lambda, - type TDSExecutionResult, - V1_deserializeValueSpecification, - V1_serializeValueSpecification, - V1_CString, -} from '@finos/legend-graph'; -import { getFilterOperation } from '../core/filter/DataCubeQueryFilterOperation.js'; -import { getAggregateOperation } from '../core/aggregation/DataCubeQueryAggregateOperation.js'; -import { DataCubeQueryAggregateOperation__Sum } from '../core/aggregation/DataCubeQueryAggregateOperation__Sum.js'; -import { DataCubeQueryAggregateOperation__Average } from '../core/aggregation/DataCubeQueryAggregateOperation__Average.js'; -import { DataCubeQueryAggregateOperation__Count } from '../core/aggregation/DataCubeQueryAggregateOperation__Count.js'; -import { DataCubeQueryAggregateOperation__Min } from '../core/aggregation/DataCubeQueryAggregateOperation__Min.js'; -import { DataCubeQueryAggregateOperation__Max } from '../core/aggregation/DataCubeQueryAggregateOperation__Max.js'; -import { DataCubeQueryAggregateOperation__UniqueValue } from '../core/aggregation/DataCubeQueryAggregateOperation__UniqueValue.js'; -import { DataCubeQueryAggregateOperation__First } from '../core/aggregation/DataCubeQueryAggregateOperation__First.js'; -import { DataCubeQueryAggregateOperation__Last } from '../core/aggregation/DataCubeQueryAggregateOperation__Last.js'; -import { DataCubeQueryAggregateOperation__VariancePopulation } from '../core/aggregation/DataCubeQueryAggregateOperation__VariancePopulation.js'; -import { DataCubeQueryAggregateOperation__VarianceSample } from '../core/aggregation/DataCubeQueryAggregateOperation__VarianceSample.js'; -import { DataCubeQueryAggregateOperation__StdDevPopulation } from '../core/aggregation/DataCubeQueryAggregateOperation__StdDevPopulation.js'; -import { DataCubeQueryAggregateOperation__StdDevSample } from '../core/aggregation/DataCubeQueryAggregateOperation__StdDevSample.js'; -import { DataCubeQueryAggregateOperation__JoinStrings } from '../core/aggregation/DataCubeQueryAggregateOperation__JoinStrings.js'; -import { DataCubeQueryFilterOperation__Equal } from '../core/filter/DataCubeQueryFilterOperation__Equal.js'; -import { DataCubeQueryFilterOperation__LessThanOrEqual } from '../core/filter/DataCubeQueryFilterOperation__LessThanOrEqual.js'; -import { DataCubeQueryFilterOperation__LessThan } from '../core/filter/DataCubeQueryFilterOperation__LessThan.js'; -import { DataCubeQueryFilterOperation__GreaterThanOrEqual } from '../core/filter/DataCubeQueryFilterOperation__GreaterThanOrEqual.js'; -import { DataCubeQueryFilterOperation__GreaterThan } from '../core/filter/DataCubeQueryFilterOperation__GreaterThan.js'; -import { DataCubeQueryFilterOperation__NotEqual } from '../core/filter/DataCubeQueryFilterOperation__NotEqual.js'; -import { DataCubeQueryFilterOperation__EqualColumn } from '../core/filter/DataCubeQueryFilterOperation__EqualColumn.js'; -import { DataCubeQueryFilterOperation__EqualCaseInsensitive } from '../core/filter/DataCubeQueryFilterOperation__EqualCaseInsensitive.js'; -import { DataCubeQueryFilterOperation__NotEqualCaseInsensitive } from '../core/filter/DataCubeQueryFilterOperation__NotEqualCaseInsensitive.js'; -import { DataCubeQueryFilterOperation__EqualCaseInsensitiveColumn } from '../core/filter/DataCubeQueryFilterOperation__EqualCaseInsensitiveColumn.js'; -import { DataCubeQueryFilterOperation__NotEqualCaseInsensitiveColumn } from '../core/filter/DataCubeQueryFilterOperation__NotEqualCaseInsensitiveColumn.js'; -import { DataCubeQueryFilterOperation__NotEqualColumn } from '../core/filter/DataCubeQueryFilterOperation__NotEqualColumn.js'; -import { DataCubeQueryFilterOperation__LessThanColumn } from '../core/filter/DataCubeQueryFilterOperation__LessThanColumn.js'; -import { DataCubeQueryFilterOperation__LessThanOrEqualColumn } from '../core/filter/DataCubeQueryFilterOperation__LessThanOrEqualColumn.js'; -import { DataCubeQueryFilterOperation__GreaterThanColumn } from '../core/filter/DataCubeQueryFilterOperation__GreaterThanColumn.js'; -import { DataCubeQueryFilterOperation__GreaterThanOrEqualColumn } from '../core/filter/DataCubeQueryFilterOperation__GreaterThanOrEqualColumn.js'; -import { DataCubeQueryFilterOperation__Contain } from '../core/filter/DataCubeQueryFilterOperation__Contain.js'; -import { DataCubeQueryFilterOperation__ContainCaseInsensitive } from '../core/filter/DataCubeQueryFilterOperation__ContainCaseInsensitive.js'; -import { DataCubeQueryFilterOperation__NotContain } from '../core/filter/DataCubeQueryFilterOperation__NotContain.js'; -import { DataCubeQueryFilterOperation__StartWith } from '../core/filter/DataCubeQueryFilterOperation__StartWith.js'; -import { DataCubeQueryFilterOperation__StartWithCaseInsensitive } from '../core/filter/DataCubeQueryFilterOperation__StartWithCaseInsensitive.js'; -import { DataCubeQueryFilterOperation__NotStartWith } from '../core/filter/DataCubeQueryFilterOperation__NotStartWith.js'; -import { DataCubeQueryFilterOperation__EndWith } from '../core/filter/DataCubeQueryFilterOperation__EndWith.js'; -import { DataCubeQueryFilterOperation__EndWithCaseInsensitive } from '../core/filter/DataCubeQueryFilterOperation__EndWithCaseInsensitive.js'; -import { DataCubeQueryFilterOperation__NotEndWith } from '../core/filter/DataCubeQueryFilterOperation__NotEndWith.js'; -import { DataCubeQueryFilterOperation__IsNull } from '../core/filter/DataCubeQueryFilterOperation__IsNull.js'; -import { DataCubeQueryFilterOperation__IsNotNull } from '../core/filter/DataCubeQueryFilterOperation__IsNotNull.js'; -import { LicenseManager } from '@ag-grid-enterprise/core'; -import { - configureCodeEditor, - setupPureLanguageService, -} from '@finos/legend-code-editor'; -import { SerializationFactory, usingModelSchema } from '@finos/legend-shared'; -import { createModelSchema, custom, primitive } from 'serializr'; -import { type DataCubeQueryColumn, DataCubeQuery } from './DataCubeQuery.js'; -import { DataCubeFont } from '../core/DataCubeQueryEngine.js'; -import { action, makeObservable, observable } from 'mobx'; -import type { GridApi } from '@ag-grid-community/core'; -import type { DataCubeQuerySnapshot } from './DataCubeQuerySnapshot.js'; -import { buildExecutableQuery } from './DataCubeQueryBuilder.js'; - -export type CompletionItem = { - completion: string; - display: string; -}; - -export type DataCubeQueryBuilderError = { - type: string; - message: string; - sourceInformation?: { - startLine: number; - startColumn: number; - endLine: number; - endColumn: number; - }; -}; - -export type DataCubeInfrastructureInfo = { - gridClientLicense?: string | undefined; - simpleSampleDataTableName: string; - complexSampleDataTableName: string; -}; - -export type RelationType = { - columns: DataCubeQueryColumn[]; -}; - -export class DataCubeGetBaseQueryResult { - query!: DataCubeQuery; - timestamp!: number; - partialQuery!: V1_ValueSpecification; - sourceQuery!: V1_ValueSpecification; - - static readonly serialization = new SerializationFactory( - createModelSchema(DataCubeGetBaseQueryResult, { - partialQuery: custom( - (val) => V1_serializeValueSpecification(val, []), - (val) => V1_deserializeValueSpecification(val, []), - ), - query: usingModelSchema(DataCubeQuery.serialization.schema), - sourceQuery: custom( - (val) => V1_serializeValueSpecification(val, []), - (val) => V1_deserializeValueSpecification(val, []), - ), - timestamp: primitive(), - }), - ); -} - -export const DEFAULT_ENABLE_DEBUG_MODE = false; -export const DEFAULT_GRID_CLIENT_ROW_BUFFER = 50; -export const DEFAULT_GRID_CLIENT_PURGE_CLOSED_ROW_NODES = false; -export const DEFAULT_GRID_CLIENT_SUPPRESS_LARGE_DATASET_WARNING = false; - -export abstract class DataCubeEngine { - gridClientLicense?: string | undefined; - gridClientTaskRunner?: - | ((task: (gridClient: GridApi) => void) => void) - | undefined; - - readonly filterOperations = [ - new DataCubeQueryFilterOperation__LessThan(), - new DataCubeQueryFilterOperation__LessThanOrEqual(), - new DataCubeQueryFilterOperation__Equal(), - new DataCubeQueryFilterOperation__NotEqual(), - new DataCubeQueryFilterOperation__GreaterThanOrEqual(), - new DataCubeQueryFilterOperation__GreaterThan(), - - new DataCubeQueryFilterOperation__IsNull(), - new DataCubeQueryFilterOperation__IsNotNull(), - - new DataCubeQueryFilterOperation__EqualCaseInsensitive(), - new DataCubeQueryFilterOperation__NotEqualCaseInsensitive(), - new DataCubeQueryFilterOperation__Contain(), - new DataCubeQueryFilterOperation__ContainCaseInsensitive(), - new DataCubeQueryFilterOperation__NotContain(), - new DataCubeQueryFilterOperation__StartWith(), - new DataCubeQueryFilterOperation__StartWithCaseInsensitive(), - new DataCubeQueryFilterOperation__NotStartWith(), - new DataCubeQueryFilterOperation__EndWith(), - new DataCubeQueryFilterOperation__EndWithCaseInsensitive(), - new DataCubeQueryFilterOperation__NotEndWith(), - - new DataCubeQueryFilterOperation__LessThanColumn(), - new DataCubeQueryFilterOperation__LessThanOrEqualColumn(), - new DataCubeQueryFilterOperation__EqualColumn(), - new DataCubeQueryFilterOperation__NotEqualColumn(), - new DataCubeQueryFilterOperation__EqualCaseInsensitiveColumn(), - new DataCubeQueryFilterOperation__NotEqualCaseInsensitiveColumn(), - new DataCubeQueryFilterOperation__GreaterThanColumn(), - new DataCubeQueryFilterOperation__GreaterThanOrEqualColumn(), - ]; - readonly aggregateOperations = [ - new DataCubeQueryAggregateOperation__Sum(), - new DataCubeQueryAggregateOperation__Average(), - new DataCubeQueryAggregateOperation__Count(), - new DataCubeQueryAggregateOperation__Min(), - new DataCubeQueryAggregateOperation__Max(), - new DataCubeQueryAggregateOperation__UniqueValue(), - new DataCubeQueryAggregateOperation__First(), - new DataCubeQueryAggregateOperation__Last(), - new DataCubeQueryAggregateOperation__VariancePopulation(), - new DataCubeQueryAggregateOperation__VarianceSample(), - new DataCubeQueryAggregateOperation__StdDevPopulation(), - new DataCubeQueryAggregateOperation__StdDevSample(), - new DataCubeQueryAggregateOperation__JoinStrings(), - ]; - - enableDebugMode = DEFAULT_ENABLE_DEBUG_MODE; - - gridClientRowBuffer = DEFAULT_GRID_CLIENT_ROW_BUFFER; - gridClientPurgeClosedRowNodes = DEFAULT_GRID_CLIENT_PURGE_CLOSED_ROW_NODES; - gridClientSuppressLargeDatasetWarning = - DEFAULT_GRID_CLIENT_SUPPRESS_LARGE_DATASET_WARNING; - - constructor() { - makeObservable(this, { - enableDebugMode: observable, - setEnableDebugMode: action, - - gridClientRowBuffer: observable, - setGridClientRowBuffer: action, - - gridClientPurgeClosedRowNodes: observable, - setGridClientPurgeClosedRowNodes: action, - - gridClientSuppressLargeDatasetWarning: observable, - setGridClientSuppressLargeDatasetWarning: action, - }); - } - - getFilterOperation(value: string) { - return getFilterOperation(value, this.filterOperations); - } - - getAggregateOperation(value: string) { - return getAggregateOperation(value, this.aggregateOperations); - } - - setEnableDebugMode(value: boolean) { - this.enableDebugMode = value; - } - - setGridClientRowBuffer(value: number) { - this.gridClientRowBuffer = value; - this.propagateGridOptionUpdates(); - } - - setGridClientPurgeClosedRowNodes(value: boolean) { - this.gridClientPurgeClosedRowNodes = value; - this.propagateGridOptionUpdates(); - } - - setGridClientSuppressLargeDatasetWarning(value: boolean) { - this.gridClientSuppressLargeDatasetWarning = value; - } - - async initialize(): Promise { - const info = await this.getInfrastructureInfo(); - if (info.gridClientLicense) { - this.gridClientLicense = info.gridClientLicense; - LicenseManager.setLicenseKey(info.gridClientLicense); - } - - await configureCodeEditor(DataCubeFont.ROBOTO_MONO, (error) => { - throw error; - }); - setupPureLanguageService({}); - } - - private propagateGridOptionUpdates() { - this.gridClientTaskRunner?.((client) => { - client.updateGridOptions({ - rowBuffer: this.gridClientRowBuffer, - purgeClosedRowNodes: this.gridClientPurgeClosedRowNodes, - }); - }); - } - - refreshFailedDataFetches() { - this.gridClientTaskRunner?.((client) => { - client.retryServerSideLoads(); - }); - } - - abstract getInfrastructureInfo(): Promise; - - abstract getQueryTypeahead( - code: string, - query: V1_ValueSpecification, - ): Promise; - - abstract parseQuery( - code: string, - returnSourceInformation?: boolean | undefined, - ): Promise; - - abstract getQueryCode( - query: V1_ValueSpecification, - pretty?: boolean | undefined, - ): Promise; - - abstract getBaseQuery(): Promise; - - abstract getQueryRelationType( - query: V1_ValueSpecification, - ): Promise; - - abstract getQueryCodeRelationReturnType( - code: string, - baseQuery: V1_ValueSpecification, - ): Promise; - - abstract executeQuery(query: V1_Lambda): Promise<{ - result: TDSExecutionResult; - executedQuery: string; - executedSQL: string; - }>; - - /** - * By default, for a function chain, Pure grammar composer will extract the first parameter of the first function - * and render it as the caller of that function rather than a parameter - * e.g. fx(fy(p1, p2), p3) will be rendered as p1->fy(p2)->fx(p3) instead of fy(p1, p2)-> fx(p3) - * - * We do a hack to get around this by setting a dummy value as the first parameter of the first function in the chain. - * Then remove this dummy value from the final code. - */ - async getPartialQueryCode( - snapshot: DataCubeQuerySnapshot, - pretty?: boolean | undefined, - ) { - const dummySourceQuery = new V1_CString(); - dummySourceQuery.value = ''; - return ( - await this.getQueryCode( - buildExecutableQuery( - snapshot, - this.filterOperations, - this.aggregateOperations, - { - sourceQuery: dummySourceQuery, - }, - ), - true, - ) - ).substring(`''->`.length); - } -} diff --git a/packages/legend-data-cube/src/stores/core/DataCubeEngine.tsx b/packages/legend-data-cube/src/stores/core/DataCubeEngine.tsx new file mode 100644 index 0000000000..49659f8a97 --- /dev/null +++ b/packages/legend-data-cube/src/stores/core/DataCubeEngine.tsx @@ -0,0 +1,459 @@ +/** + * 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 { + type V1_ValueSpecification, + type V1_Lambda, + type TDSExecutionResult, + type V1_AppliedFunction, + PRIMITIVE_TYPE, +} from '@finos/legend-graph'; +import { getFilterOperation } from './filter/DataCubeQueryFilterOperation.js'; +import { getAggregateOperation } from './aggregation/DataCubeQueryAggregateOperation.js'; +import { DataCubeQueryAggregateOperation__Sum } from './aggregation/DataCubeQueryAggregateOperation__Sum.js'; +import { DataCubeQueryAggregateOperation__Average } from './aggregation/DataCubeQueryAggregateOperation__Average.js'; +import { DataCubeQueryAggregateOperation__Count } from './aggregation/DataCubeQueryAggregateOperation__Count.js'; +import { DataCubeQueryAggregateOperation__Min } from './aggregation/DataCubeQueryAggregateOperation__Min.js'; +import { DataCubeQueryAggregateOperation__Max } from './aggregation/DataCubeQueryAggregateOperation__Max.js'; +import { DataCubeQueryAggregateOperation__UniqueValue } from './aggregation/DataCubeQueryAggregateOperation__UniqueValue.js'; +import { DataCubeQueryAggregateOperation__First } from './aggregation/DataCubeQueryAggregateOperation__First.js'; +import { DataCubeQueryAggregateOperation__Last } from './aggregation/DataCubeQueryAggregateOperation__Last.js'; +import { DataCubeQueryAggregateOperation__VariancePopulation } from './aggregation/DataCubeQueryAggregateOperation__VariancePopulation.js'; +import { DataCubeQueryAggregateOperation__VarianceSample } from './aggregation/DataCubeQueryAggregateOperation__VarianceSample.js'; +import { DataCubeQueryAggregateOperation__StdDevPopulation } from './aggregation/DataCubeQueryAggregateOperation__StdDevPopulation.js'; +import { DataCubeQueryAggregateOperation__StdDevSample } from './aggregation/DataCubeQueryAggregateOperation__StdDevSample.js'; +import { DataCubeQueryAggregateOperation__JoinStrings } from './aggregation/DataCubeQueryAggregateOperation__JoinStrings.js'; +import { DataCubeQueryFilterOperation__Equal } from './filter/DataCubeQueryFilterOperation__Equal.js'; +import { DataCubeQueryFilterOperation__LessThanOrEqual } from './filter/DataCubeQueryFilterOperation__LessThanOrEqual.js'; +import { DataCubeQueryFilterOperation__LessThan } from './filter/DataCubeQueryFilterOperation__LessThan.js'; +import { DataCubeQueryFilterOperation__GreaterThanOrEqual } from './filter/DataCubeQueryFilterOperation__GreaterThanOrEqual.js'; +import { DataCubeQueryFilterOperation__GreaterThan } from './filter/DataCubeQueryFilterOperation__GreaterThan.js'; +import { DataCubeQueryFilterOperation__NotEqual } from './filter/DataCubeQueryFilterOperation__NotEqual.js'; +import { DataCubeQueryFilterOperation__EqualColumn } from './filter/DataCubeQueryFilterOperation__EqualColumn.js'; +import { DataCubeQueryFilterOperation__EqualCaseInsensitive } from './filter/DataCubeQueryFilterOperation__EqualCaseInsensitive.js'; +import { DataCubeQueryFilterOperation__NotEqualCaseInsensitive } from './filter/DataCubeQueryFilterOperation__NotEqualCaseInsensitive.js'; +import { DataCubeQueryFilterOperation__EqualCaseInsensitiveColumn } from './filter/DataCubeQueryFilterOperation__EqualCaseInsensitiveColumn.js'; +import { DataCubeQueryFilterOperation__NotEqualCaseInsensitiveColumn } from './filter/DataCubeQueryFilterOperation__NotEqualCaseInsensitiveColumn.js'; +import { DataCubeQueryFilterOperation__NotEqualColumn } from './filter/DataCubeQueryFilterOperation__NotEqualColumn.js'; +import { DataCubeQueryFilterOperation__LessThanColumn } from './filter/DataCubeQueryFilterOperation__LessThanColumn.js'; +import { DataCubeQueryFilterOperation__LessThanOrEqualColumn } from './filter/DataCubeQueryFilterOperation__LessThanOrEqualColumn.js'; +import { DataCubeQueryFilterOperation__GreaterThanColumn } from './filter/DataCubeQueryFilterOperation__GreaterThanColumn.js'; +import { DataCubeQueryFilterOperation__GreaterThanOrEqualColumn } from './filter/DataCubeQueryFilterOperation__GreaterThanOrEqualColumn.js'; +import { DataCubeQueryFilterOperation__Contain } from './filter/DataCubeQueryFilterOperation__Contain.js'; +import { DataCubeQueryFilterOperation__ContainCaseInsensitive } from './filter/DataCubeQueryFilterOperation__ContainCaseInsensitive.js'; +import { DataCubeQueryFilterOperation__NotContain } from './filter/DataCubeQueryFilterOperation__NotContain.js'; +import { DataCubeQueryFilterOperation__StartWith } from './filter/DataCubeQueryFilterOperation__StartWith.js'; +import { DataCubeQueryFilterOperation__StartWithCaseInsensitive } from './filter/DataCubeQueryFilterOperation__StartWithCaseInsensitive.js'; +import { DataCubeQueryFilterOperation__NotStartWith } from './filter/DataCubeQueryFilterOperation__NotStartWith.js'; +import { DataCubeQueryFilterOperation__EndWith } from './filter/DataCubeQueryFilterOperation__EndWith.js'; +import { DataCubeQueryFilterOperation__EndWithCaseInsensitive } from './filter/DataCubeQueryFilterOperation__EndWithCaseInsensitive.js'; +import { DataCubeQueryFilterOperation__NotEndWith } from './filter/DataCubeQueryFilterOperation__NotEndWith.js'; +import { DataCubeQueryFilterOperation__IsNull } from './filter/DataCubeQueryFilterOperation__IsNull.js'; +import { DataCubeQueryFilterOperation__IsNotNull } from './filter/DataCubeQueryFilterOperation__IsNotNull.js'; +import { + CODE_EDITOR_LANGUAGE, + configureCodeEditor, + setupPureLanguageService, +} from '@finos/legend-code-editor'; +import { DataCubeFont } from './DataCubeQueryEngine.js'; +import type { DataCubeQuerySnapshot } from './DataCubeQuerySnapshot.js'; +import { buildExecutableQuery } from './DataCubeQueryBuilder.js'; +import type { DataCubeColumn } from './models/DataCubeColumn.js'; +import { LicenseManager } from '@ag-grid-enterprise/core'; +import type { DataCubeQuery } from './models/DataCubeQuery.js'; +import { + type DataCubeSource, + INTERNAL__DataCubeSource, +} from './models/DataCubeSource.js'; +import { _primitiveValue } from './DataCubeQueryBuilderUtils.js'; +import { + uuid, + type DocumentationEntry, + type LogEvent, + type PlainObject, +} from '@finos/legend-shared'; +import { + Alert, + AlertType, + type ActionAlertAction, +} from '../../components/core/DataCubeAlert.js'; +import { + DEFAULT_SMALL_ALERT_WINDOW_CONFIG, + LayoutConfiguration, + LayoutManagerState, + WindowState, + type WindowConfiguration, +} from './DataCubeLayoutManagerState.js'; +import { editor as monacoEditorAPI, Uri } from 'monaco-editor'; +import { DataCubeCodeCheckErrorAlert } from '../../components/core/DataCubeCodeCheckErrorAlert.js'; +import type { DataCubeAPI } from '../DataCubeAPI.js'; + +export type CompletionItem = { + completion: string; + display: string; +}; + +export type RelationType = { + columns: DataCubeColumn[]; +}; + +export type DataCubeQueryBuilderError = { + type: string; + message: string; + sourceInformation?: { + startLine: number; + startColumn: number; + endLine: number; + endColumn: number; + }; +}; + +type DataCubeExecutionResult = { + result: TDSExecutionResult; + executedQuery: string; + executedSQL: string; +}; + +export type DataCubeInitialInput = { + query: DataCubeQuery; + source: DataCubeSource; +}; + +export type DataCubeEngineConfiguration = { + gridClientLicense?: string | undefined; +}; + +export abstract class DataCubeEngine { + readonly layout = new LayoutManagerState(); + readonly filterOperations = [ + new DataCubeQueryFilterOperation__LessThan(), + new DataCubeQueryFilterOperation__LessThanOrEqual(), + new DataCubeQueryFilterOperation__Equal(), + new DataCubeQueryFilterOperation__NotEqual(), + new DataCubeQueryFilterOperation__GreaterThanOrEqual(), + new DataCubeQueryFilterOperation__GreaterThan(), + + new DataCubeQueryFilterOperation__IsNull(), + new DataCubeQueryFilterOperation__IsNotNull(), + + new DataCubeQueryFilterOperation__EqualCaseInsensitive(), + new DataCubeQueryFilterOperation__NotEqualCaseInsensitive(), + new DataCubeQueryFilterOperation__Contain(), + new DataCubeQueryFilterOperation__ContainCaseInsensitive(), + new DataCubeQueryFilterOperation__NotContain(), + new DataCubeQueryFilterOperation__StartWith(), + new DataCubeQueryFilterOperation__StartWithCaseInsensitive(), + new DataCubeQueryFilterOperation__NotStartWith(), + new DataCubeQueryFilterOperation__EndWith(), + new DataCubeQueryFilterOperation__EndWithCaseInsensitive(), + new DataCubeQueryFilterOperation__NotEndWith(), + + new DataCubeQueryFilterOperation__LessThanColumn(), + new DataCubeQueryFilterOperation__LessThanOrEqualColumn(), + new DataCubeQueryFilterOperation__EqualColumn(), + new DataCubeQueryFilterOperation__NotEqualColumn(), + new DataCubeQueryFilterOperation__EqualCaseInsensitiveColumn(), + new DataCubeQueryFilterOperation__NotEqualCaseInsensitiveColumn(), + new DataCubeQueryFilterOperation__GreaterThanColumn(), + new DataCubeQueryFilterOperation__GreaterThanOrEqualColumn(), + ]; + readonly aggregateOperations = [ + new DataCubeQueryAggregateOperation__Sum(), + new DataCubeQueryAggregateOperation__Average(), + new DataCubeQueryAggregateOperation__Count(), + new DataCubeQueryAggregateOperation__Min(), + new DataCubeQueryAggregateOperation__Max(), + new DataCubeQueryAggregateOperation__UniqueValue(), + new DataCubeQueryAggregateOperation__First(), + new DataCubeQueryAggregateOperation__Last(), + new DataCubeQueryAggregateOperation__VariancePopulation(), + new DataCubeQueryAggregateOperation__VarianceSample(), + new DataCubeQueryAggregateOperation__StdDevPopulation(), + new DataCubeQueryAggregateOperation__StdDevSample(), + new DataCubeQueryAggregateOperation__JoinStrings(), + ]; + + protected async fetchConfiguration(): Promise { + return { + gridClientLicense: undefined, + }; + } + + async initialize(): Promise { + const config = await this.fetchConfiguration(); + if (config.gridClientLicense) { + LicenseManager.setLicenseKey(config.gridClientLicense); + } + await configureCodeEditor(DataCubeFont.ROBOTO_MONO, (error) => { + throw error; + }); + setupPureLanguageService({}); + } + + // ------------------------------- CORE OPERATIONS ------------------------------- + + getFilterOperation(value: string) { + return getFilterOperation(value, this.filterOperations); + } + + getAggregateOperation(value: string) { + return getAggregateOperation(value, this.aggregateOperations); + } + + async getInitialInput(): Promise { + return undefined; + } + + abstract parseValueSpecification( + code: string, + returnSourceInformation?: boolean | undefined, + ): Promise; + + abstract getValueSpecificationCode( + value: V1_ValueSpecification, + pretty?: boolean | undefined, + ): Promise; + + abstract getQueryTypeahead( + code: string, + baseQuery: V1_Lambda, + source: DataCubeSource, + ): Promise; + + abstract getQueryRelationType( + query: V1_Lambda, + source: DataCubeSource, + ): Promise; + + abstract getQueryCodeRelationReturnType( + code: string, + baseQuery: V1_ValueSpecification, + source: DataCubeSource, + ): Promise; + + abstract executeQuery( + query: V1_Lambda, + source: DataCubeSource, + api: DataCubeAPI, + ): Promise; + + abstract buildExecutionContext( + source: DataCubeSource, + ): V1_AppliedFunction | undefined; + + /** + * By default, for a function chain, Pure grammar composer will extract the first parameter of the first function + * and render it as the caller of that function rather than a parameter + * e.g. fx(fy(p1, p2), p3) will be rendered as p1->fy(p2)->fx(p3) instead of fy(p1, p2)-> fx(p3) + * + * We do a hack to get around this by setting a dummy value as the first parameter of the first function in the chain. + * Then remove this dummy value from the final code. + */ + async getPartialQueryCode( + snapshot: DataCubeQuerySnapshot, + pretty?: boolean | undefined, + ) { + const source = new INTERNAL__DataCubeSource(); + source.query = _primitiveValue(PRIMITIVE_TYPE.STRING, ''); + return ( + await this.getValueSpecificationCode( + buildExecutableQuery( + snapshot, + source, + () => undefined, + this.filterOperations, + this.aggregateOperations, + ), + pretty, + ) + ).substring(`''->`.length); + } + + // ---------------------------------- DOCUMENTATION ---------------------------------- + + getDocumentationURL(): string | undefined { + return undefined; + } + + getDocumentationEntry(key: string): DocumentationEntry | undefined { + return undefined; + } + + shouldDisplayDocumentationEntry(entry: DocumentationEntry) { + return false; + } + + // ---------------------------------- LOGGING ---------------------------------- + + logDebug(message: string, ...data: unknown[]) { + // do nothing + } + + debugProcess(processName: string, ...data: [string, unknown][]) { + // do nothing + } + + logInfo(event: LogEvent, ...data: unknown[]) { + // do nothing + } + + logWarning(event: LogEvent, ...data: unknown[]) { + // do nothing + } + + logError(event: LogEvent, ...data: unknown[]) { + // do nothing + } + + logUnhandledError(error: Error) { + // do nothing + } + + logIllegalStateError(message: string, error?: Error) { + // do nothing + } + + // ---------------------------------- ALERT ---------------------------------- + + alert(options: { + message: string; + type: AlertType; + text?: string | undefined; + actions?: ActionAlertAction[] | undefined; + windowTitle?: string | undefined; + windowConfig?: WindowConfiguration | undefined; + }) { + const { message, type, text, actions, windowTitle, windowConfig } = options; + const window = new WindowState( + new LayoutConfiguration(windowTitle ?? '', () => ( + this.layout.closeWindow(window)} + /> + )), + ); + window.configuration.window = + windowConfig ?? DEFAULT_SMALL_ALERT_WINDOW_CONFIG; + this.layout.newWindow(window); + } + + alertError( + error: Error, + options: { + message: string; + text?: string | undefined; + actions?: ActionAlertAction[] | undefined; + windowTitle?: string | undefined; + windowConfig?: WindowConfiguration | undefined; + }, + ) { + const { message, text, actions, windowTitle, windowConfig } = options; + const window = new WindowState( + new LayoutConfiguration(windowTitle ?? 'Error', () => ( + + )), + ); + window.configuration.window = + windowConfig ?? DEFAULT_SMALL_ALERT_WINDOW_CONFIG; + this.layout.newWindow(window); + } + + alertUnhandledError(error: Error) { + this.logUnhandledError(error); + this.alertError(error, { + message: error.message, + }); + } + + alertCodeCheckError( + error: DataCubeQueryBuilderError, + code: string, + codePrefix: string, + options: { + message: string; + text?: string | undefined; + actions?: ActionAlertAction[] | undefined; + windowTitle?: string | undefined; + windowConfig?: WindowConfiguration | undefined; + }, + ) { + const { message, text, windowTitle, windowConfig } = options; + // correct the source information since we added prefix to the code + // and reveal error in the editor + if (error.sourceInformation) { + error.sourceInformation.startColumn -= + error.sourceInformation.startLine === 1 ? codePrefix.length : 0; + error.sourceInformation.endColumn -= + error.sourceInformation.endLine === 1 ? codePrefix.length : 0; + const editorModel = monacoEditorAPI.createModel( + code, + CODE_EDITOR_LANGUAGE.PURE, + Uri.file(`/${uuid()}.pure`), + ); + + const fullRange = editorModel.getFullModelRange(); + if ( + error.sourceInformation.startLine < 1 || + (error.sourceInformation.startLine === 1 && + error.sourceInformation.startColumn < 1) || + error.sourceInformation.endLine > fullRange.endLineNumber || + (error.sourceInformation.endLine === fullRange.endLineNumber && + error.sourceInformation.endColumn > fullRange.endColumn) + ) { + error.sourceInformation.startColumn = fullRange.startColumn; + error.sourceInformation.startLine = fullRange.startLineNumber; + error.sourceInformation.endColumn = fullRange.endColumn; + error.sourceInformation.endLine = fullRange.endLineNumber; + } + const window = new WindowState( + new LayoutConfiguration(windowTitle ?? 'Error', () => ( + + )), + ); + window.configuration.window = windowConfig ?? { + width: 500, + height: 400, + minWidth: 300, + minHeight: 300, + center: true, + }; + this.layout.newWindow(window); + } + } + + // ---------------------------------- MISC ---------------------------------- + + openLink(url: string) { + // do nothing + } + + sendTelemetry(event: string, data: PlainObject) { + // do nothing + } +} diff --git a/packages/legend-data-cube/src/stores/core/DataCubeEngineUtils.ts b/packages/legend-data-cube/src/stores/core/DataCubeEngineUtils.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/packages/legend-data-cube/src/stores/core/DataCubeQuery.ts b/packages/legend-data-cube/src/stores/core/DataCubeQuery.ts deleted file mode 100644 index 8a44503803..0000000000 --- a/packages/legend-data-cube/src/stores/core/DataCubeQuery.ts +++ /dev/null @@ -1,130 +0,0 @@ -/** - * 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 { - SerializationFactory, - UnsupportedOperationError, - usingConstantValueSchema, - usingModelSchema, - type PlainObject, -} from '@finos/legend-shared'; -import { - createModelSchema, - custom, - deserialize, - list, - optional, - primitive, - raw, - serialize, -} from 'serializr'; - -export abstract class DataCubeQuerySource { - columns: DataCubeQueryColumn[] = []; - query!: string; - runtime!: string; - mapping?: string | undefined; -} - -export class DataCubeQueryColumn { - name!: string; - type!: string; - - static readonly serialization = new SerializationFactory( - createModelSchema(DataCubeQueryColumn, { - name: primitive(), - type: primitive(), - }), - ); -} - -enum DataCubeQuerySourceType { - REPL_EXECUTED_QUERY = 'REPLExecutedQuery', -} - -export class DataCubeQuerySourceREPLExecutedQuery extends DataCubeQuerySource { - static readonly serialization = new SerializationFactory( - createModelSchema(DataCubeQuerySourceREPLExecutedQuery, { - _type: usingConstantValueSchema( - DataCubeQuerySourceType.REPL_EXECUTED_QUERY, - ), - columns: list(usingModelSchema(DataCubeQueryColumn.serialization.schema)), - mapping: optional(primitive()), - query: primitive(), - runtime: primitive(), - }), - ); -} - -function deserializeQuerySource( - json: PlainObject, -): DataCubeQuerySource { - switch (json._type) { - case DataCubeQuerySourceType.REPL_EXECUTED_QUERY: - return deserialize( - DataCubeQuerySourceREPLExecutedQuery.serialization.schema, - json, - ); - default: - throw new UnsupportedOperationError( - `Can't deserialize data cube query source of type '${json._type}'`, - ); - } -} - -function serializeQuerySource( - object: DataCubeQuerySource, -): PlainObject { - if (object instanceof DataCubeQuerySourceREPLExecutedQuery) { - return serialize( - DataCubeQuerySourceREPLExecutedQuery.serialization.schema, - object, - ); - } - throw new UnsupportedOperationError( - `Can't serialize data cube query source`, - object, - ); -} - -export class DataCubeQuery { - name!: string; - query!: string; - partialQuery!: string; - source!: DataCubeQuerySource; - configuration?: PlainObject | undefined; - - constructor( - name: string, - query: string, - configuration?: PlainObject | undefined, - ) { - this.name = name; - this.query = query; - this.configuration = configuration; - } - - static readonly serialization = new SerializationFactory( - createModelSchema(DataCubeQuery, { - /** TODO: @datacube roundtrip - populate this once we know the shape better */ - configuration: raw(), - name: primitive(), - partialQuery: primitive(), - query: primitive(), - source: custom(serializeQuerySource, deserializeQuerySource), - }), - ); -} diff --git a/packages/legend-data-cube/src/stores/core/DataCubeQueryBuilder.ts b/packages/legend-data-cube/src/stores/core/DataCubeQueryBuilder.ts index 743f975fa6..439da37f7f 100644 --- a/packages/legend-data-cube/src/stores/core/DataCubeQueryBuilder.ts +++ b/packages/legend-data-cube/src/stores/core/DataCubeQueryBuilder.ts @@ -21,20 +21,15 @@ * the query snapshot. The executable query is then used to fetch data. ***************************************************************************************/ -import { - PRIMITIVE_TYPE, - type V1_AppliedFunction, - type V1_ValueSpecification, - V1_deserializeValueSpecification, -} from '@finos/legend-graph'; +import { PRIMITIVE_TYPE, type V1_AppliedFunction } from '@finos/legend-graph'; import { type DataCubeQuerySnapshot } from './DataCubeQuerySnapshot.js'; -import { guaranteeNonNullable, isNonNullable } from '@finos/legend-shared'; +import { guaranteeNonNullable } from '@finos/legend-shared'; import { DataCubeFunction, DataCubeQuerySortDirection, type DataCubeQueryFunctionMap, } from './DataCubeQueryEngine.js'; -import { DataCubeConfiguration } from './DataCubeConfiguration.js'; +import { DataCubeConfiguration } from './models/DataCubeConfiguration.js'; import type { DataCubeQueryFilterOperation } from './filter/DataCubeQueryFilterOperation.js'; import { _col, @@ -42,7 +37,6 @@ import { _cols, _colSpec, _deserializeLambda, - _elementPtr, _filter, _function, _groupByAggCols, @@ -54,13 +48,17 @@ import { _functionCompositionProcessor, } from './DataCubeQueryBuilderUtils.js'; import type { DataCubeQueryAggregateOperation } from './aggregation/DataCubeQueryAggregateOperation.js'; +import type { DataCubeSource } from './models/DataCubeSource.js'; export function buildExecutableQuery( snapshot: DataCubeQuerySnapshot, + source: DataCubeSource, + executionContextBuilder: ( + source: DataCubeSource, + ) => V1_AppliedFunction | undefined, filterOperations: DataCubeQueryFilterOperation[], aggregateOperations: DataCubeQueryAggregateOperation[], options?: { - sourceQuery?: V1_ValueSpecification | null | undefined; postProcessor?: ( snapshot: DataCubeQuerySnapshot, sequence: V1_AppliedFunction[], @@ -78,7 +76,6 @@ export function buildExecutableQuery( }, ) { const data = snapshot.data; - const sourceQuery = V1_deserializeValueSpecification(data.sourceQuery, []); const configuration = DataCubeConfiguration.serialization.fromJson( data.configuration, ); @@ -254,20 +251,13 @@ export function buildExecutableQuery( ); } - // --------------------------------- FROM --------------------------------- - - sequence.push( - _function( - DataCubeFunction.FROM, - [ - data.mapping ? _elementPtr(data.mapping) : undefined, - _elementPtr(data.runtime), - ].filter(isNonNullable), - ), - ); - // --------------------------------- FINALIZE --------------------------------- + const executionContext = executionContextBuilder(source); + if (executionContext) { + sequence.push(executionContext); + } + options?.postProcessor?.( snapshot, sequence, @@ -277,16 +267,12 @@ export function buildExecutableQuery( aggregateOperations, ); - if (!sequence.length) { - return sourceQuery; + if (sequence.length === 0) { + return source.query; } - - const omitSourceQuery = options?.sourceQuery === null; - for (let i = omitSourceQuery ? 1 : 0; i < sequence.length; i++) { + for (let i = 0; i < sequence.length; i++) { guaranteeNonNullable(sequence[i]).parameters.unshift( - i === 0 - ? (options?.sourceQuery ?? sourceQuery) - : guaranteeNonNullable(sequence[i - 1]), + i === 0 ? source.query : guaranteeNonNullable(sequence[i - 1]), ); } return guaranteeNonNullable(sequence[sequence.length - 1]); diff --git a/packages/legend-data-cube/src/stores/core/DataCubeQueryBuilderUtils.ts b/packages/legend-data-cube/src/stores/core/DataCubeQueryBuilderUtils.ts index 9749e284c7..fb8d2bee98 100644 --- a/packages/legend-data-cube/src/stores/core/DataCubeQueryBuilderUtils.ts +++ b/packages/legend-data-cube/src/stores/core/DataCubeQueryBuilderUtils.ts @@ -53,9 +53,9 @@ import { import { type DataCubeQuerySnapshotFilterCondition, type DataCubeQuerySnapshotFilter, - type DataCubeQuerySnapshotColumn, type DataCubeQuerySnapshot, } from './DataCubeQuerySnapshot.js'; +import { type DataCubeColumn } from './models/DataCubeColumn.js'; import { guaranteeNonNullable, guaranteeIsString, @@ -81,7 +81,7 @@ import type { DataCubeQueryAggregateOperation } from './aggregation/DataCubeQuer import { DataCubeColumnConfiguration, type DataCubeConfiguration, -} from './DataCubeConfiguration.js'; +} from './models/DataCubeConfiguration.js'; // --------------------------------- UTILITIES --------------------------------- @@ -336,10 +336,7 @@ function fixEmptyAggCols(aggCols: V1_ColSpec[]) { ]; } -export function _aggCol_basic( - column: DataCubeQuerySnapshotColumn, - func: string, -) { +export function _aggCol_basic(column: DataCubeColumn, func: string) { const variable = _var(); return _colSpec( column.name, @@ -349,7 +346,7 @@ export function _aggCol_basic( } export function _pivotAggCols( - pivotColumns: DataCubeQuerySnapshotColumn[], + pivotColumns: DataCubeColumn[], snapshot: DataCubeQuerySnapshot, configuration: DataCubeConfiguration, aggregateOperations: DataCubeQueryAggregateOperation[], @@ -382,7 +379,7 @@ export function _pivotAggCols( ); } -export function _castCols(columns: DataCubeQuerySnapshotColumn[]) { +export function _castCols(columns: DataCubeColumn[]) { const genericType = new V1_GenericTypeInstance(); genericType.fullPath = CORE_PURE_PATH.RELATION; genericType.typeArguments = [ @@ -394,7 +391,7 @@ export function _castCols(columns: DataCubeQuerySnapshotColumn[]) { } export function _groupByAggCols( - groupByColumns: DataCubeQuerySnapshotColumn[], + groupByColumns: DataCubeColumn[], snapshot: DataCubeQuerySnapshot, configuration: DataCubeConfiguration, aggregateOperations: DataCubeQueryAggregateOperation[], diff --git a/packages/legend-data-cube/src/stores/core/DataCubeQuerySnapshot.ts b/packages/legend-data-cube/src/stores/core/DataCubeQuerySnapshot.ts index 25bb1eb9bd..83ca3815b8 100644 --- a/packages/legend-data-cube/src/stores/core/DataCubeQuerySnapshot.ts +++ b/packages/legend-data-cube/src/stores/core/DataCubeQuerySnapshot.ts @@ -14,12 +14,8 @@ * limitations under the License. */ -import type { - V1_AppliedFunction, - V1_Lambda, - V1_ValueSpecification, -} from '@finos/legend-graph'; -import type { DataCubeConfiguration } from './DataCubeConfiguration.js'; +import type { V1_AppliedFunction, V1_Lambda } from '@finos/legend-graph'; +import type { DataCubeConfiguration } from './models/DataCubeConfiguration.js'; import { IllegalStateError, hashObject, @@ -32,13 +28,13 @@ import type { DataCubeOperationValue, DataCubeQuerySortDirection, } from './DataCubeQueryEngine.js'; +import type { DataCubeColumn } from './models/DataCubeColumn.js'; -export type DataCubeQuerySnapshotFilterCondition = - DataCubeQuerySnapshotColumn & { - value: DataCubeOperationValue | undefined; - operator: string; - not?: boolean | undefined; - }; +export type DataCubeQuerySnapshotFilterCondition = DataCubeColumn & { + value: DataCubeOperationValue | undefined; + operator: string; + not?: boolean | undefined; +}; export type DataCubeQuerySnapshotFilter = { groupOperator: string; @@ -49,41 +45,31 @@ export type DataCubeQuerySnapshotFilter = { not?: boolean | undefined; }; -export type DataCubeQuerySnapshotColumn = { - name: string; - type: string; +export type DataCubeQuerySnapshotExtendedColumn = DataCubeColumn & { + windowFn?: PlainObject | undefined; + mapFn: PlainObject; + reduceFn?: PlainObject | undefined; }; -export type DataCubeQuerySnapshotExtendedColumn = - DataCubeQuerySnapshotColumn & { - windowFn?: PlainObject | undefined; - mapFn: PlainObject; - reduceFn?: PlainObject | undefined; - }; - -export type DataCubeQuerySnapshotSortColumn = DataCubeQuerySnapshotColumn & { +export type DataCubeQuerySnapshotSortColumn = DataCubeColumn & { direction: DataCubeQuerySortDirection; }; export type DataCubeQuerySnapshotGroupBy = { - columns: DataCubeQuerySnapshotColumn[]; + columns: DataCubeColumn[]; }; export type DataCubeQuerySnapshotPivot = { - columns: DataCubeQuerySnapshotColumn[]; - castColumns: DataCubeQuerySnapshotColumn[]; + columns: DataCubeColumn[]; + castColumns: DataCubeColumn[]; }; export type DataCubeQuerySnapshotData = { - name: string; - runtime: string; - mapping: string | undefined; - sourceQuery: PlainObject; configuration: PlainObject; - sourceColumns: DataCubeQuerySnapshotColumn[]; + sourceColumns: DataCubeColumn[]; leafExtendedColumns: DataCubeQuerySnapshotExtendedColumn[]; filter?: DataCubeQuerySnapshotFilter | undefined; - selectColumns: DataCubeQuerySnapshotColumn[]; + selectColumns: DataCubeColumn[]; groupBy?: DataCubeQuerySnapshotGroupBy | undefined; pivot?: DataCubeQuerySnapshotPivot | undefined; groupExtendedColumns: DataCubeQuerySnapshotExtendedColumn[]; @@ -93,25 +79,14 @@ export type DataCubeQuerySnapshotData = { export class DataCubeQuerySnapshot { readonly uuid = uuid(); - readonly timestamp = Date.now(); readonly data: DataCubeQuerySnapshotData; private _isPatchChange = false; private _finalized = false; private _hashCode?: string | undefined; - private constructor( - name: string, - runtime: string, - mapping: string | undefined, - sourceQuery: PlainObject, - configuration: PlainObject, - ) { + private constructor(configuration: PlainObject) { this.data = { - name, - runtime, - mapping, - sourceQuery, configuration, sourceColumns: [], leafExtendedColumns: [], @@ -125,20 +100,8 @@ export class DataCubeQuerySnapshot { }; } - static create( - name: string, - runtime: string, - mapping: string | undefined, - sourceQuery: PlainObject, - configuration: PlainObject, - ) { - return new DataCubeQuerySnapshot( - name, - runtime, - mapping, - sourceQuery, - configuration, - ); + static create(configuration: PlainObject) { + return new DataCubeQuerySnapshot(configuration); } /** @@ -187,7 +150,7 @@ export class DataCubeQuerySnapshot { } clone() { - const clone = new DataCubeQuerySnapshot('', '', '', {}, {}); + const clone = new DataCubeQuerySnapshot({}); (clone.data as Writable) = JSON.parse( JSON.stringify(this.data), ) as DataCubeQuerySnapshotData; @@ -199,9 +162,8 @@ export class DataCubeQuerySnapshot { * This should rarely be used, and ideally by core engine only. */ INTERNAL__fullClone() { - const clone = new DataCubeQuerySnapshot('', '', '', {}, {}); + const clone = new DataCubeQuerySnapshot({}); (clone as Writable).uuid = this.uuid; - (clone as Writable).timestamp = this.timestamp; (clone as Writable).data = JSON.parse( JSON.stringify(this.data), ) as DataCubeQuerySnapshotData; @@ -210,30 +172,4 @@ export class DataCubeQuerySnapshot { clone._hashCode = this._hashCode; return clone; } - - /** - * Only use this if programatic setting of timestamp is needed. - * e.g. for the first-ever snapshot where we want to sync the timestamp - * to the timestamp provided by the engine. - */ - INTERNAL__setTimestamp(timestamp: number) { - (this as Writable).timestamp = timestamp; - } -} - -export function _findCol( - cols: T[] | undefined, - name: string, -): T | undefined { - return cols?.find((c) => c.name === name); } - -export function _toCol(col: { - name: string; - type: string; -}): DataCubeQuerySnapshotColumn { - return { name: col.name, type: col.type }; -} - -export const _sortByColName = (a: { name: string }, b: { name: string }) => - a.name.localeCompare(b.name); diff --git a/packages/legend-data-cube/src/stores/core/DataCubeQuerySnapshotBuilder.ts b/packages/legend-data-cube/src/stores/core/DataCubeQuerySnapshotBuilder.ts index cd5c6a0a7b..2cfe3b2c7e 100644 --- a/packages/legend-data-cube/src/stores/core/DataCubeQuerySnapshotBuilder.ts +++ b/packages/legend-data-cube/src/stores/core/DataCubeQuerySnapshotBuilder.ts @@ -18,7 +18,7 @@ * [CORE] * * This and its corresponding utilitites are used to build the query snapshot from the - * executable query. This is needed when we initialize the application by loading a + * executable query. This is needed when we initialize the engine by loading a * persisted query. ***************************************************************************************/ @@ -27,24 +27,20 @@ import { V1_CInteger, type V1_ColSpec, V1_Collection, - V1_serializeValueSpecification, extractElementNameFromPath as _name, matchFunctionName, type V1_ValueSpecification, } from '@finos/legend-graph'; -import type { DataCubeQuery } from '../core/DataCubeQuery.js'; -import { - _toCol, - DataCubeQuerySnapshot, - type DataCubeQuerySnapshotColumn, -} from './DataCubeQuerySnapshot.js'; +import type { DataCubeQuery } from './models/DataCubeQuery.js'; +import { DataCubeQuerySnapshot } from './DataCubeQuerySnapshot.js'; +import { _toCol, type DataCubeColumn } from './models/DataCubeColumn.js'; import { assertType, guaranteeNonNullable } from '@finos/legend-shared'; import { DataCubeQuerySortDirection, DataCubeFunction, type DataCubeQueryFunctionMap, } from './DataCubeQueryEngine.js'; -import { DataCubeConfiguration } from './DataCubeConfiguration.js'; +import { DataCubeConfiguration } from './models/DataCubeConfiguration.js'; import { buildDefaultConfiguration } from './DataCubeConfigurationBuilder.js'; import { _colSpecArrayParam, @@ -52,6 +48,7 @@ import { _funcMatch, _param, } from './DataCubeQuerySnapshotBuilderUtils.js'; +import type { DataCubeSource } from './models/DataCubeSource.js'; // --------------------------------- BUILDING BLOCKS --------------------------------- @@ -286,7 +283,7 @@ function extractFunctionMap( */ export function validateAndBuildQuerySnapshot( partialQuery: V1_ValueSpecification, - sourceQuery: V1_ValueSpecification, + source: DataCubeSource, baseQuery: DataCubeQuery, ) { // --------------------------------- BASE --------------------------------- @@ -294,15 +291,9 @@ export function validateAndBuildQuerySnapshot( // analysis more ergonomic const funcMap = extractFunctionMap(partialQuery); - const snapshot = DataCubeQuerySnapshot.create( - baseQuery.name, - baseQuery.source.runtime, - baseQuery.source.mapping, - V1_serializeValueSpecification(sourceQuery, []), - {}, - ); + const snapshot = DataCubeQuerySnapshot.create({}); const data = snapshot.data; - const colsMap = new Map(); + const colsMap = new Map(); const _col = (colSpec: V1_ColSpec) => { const column = guaranteeNonNullable( colsMap.get(colSpec.name), @@ -313,7 +304,7 @@ export function validateAndBuildQuerySnapshot( // --------------------------------- SOURCE --------------------------------- - data.sourceColumns = baseQuery.source.columns.map(_toCol); + data.sourceColumns = source.sourceColumns; data.sourceColumns.map((col) => colsMap.set(col.name, col)); // --------------------------------- LEAF-LEVEL EXTEND --------------------------------- @@ -398,7 +389,7 @@ export function validateAndBuildQuerySnapshot( const configuration = baseQuery.configuration ? DataCubeConfiguration.serialization.fromJson(baseQuery.configuration) : buildDefaultConfiguration([ - ...baseQuery.source.columns, + ...source.sourceColumns, ...data.leafExtendedColumns, ...data.groupExtendedColumns, ]); diff --git a/packages/legend-data-cube/src/stores/core/DataCubeQuerySnapshotBuilderUtils.ts b/packages/legend-data-cube/src/stores/core/DataCubeQuerySnapshotBuilderUtils.ts index 0d14dc1073..539ade4e1c 100644 --- a/packages/legend-data-cube/src/stores/core/DataCubeQuerySnapshotBuilderUtils.ts +++ b/packages/legend-data-cube/src/stores/core/DataCubeQuerySnapshotBuilderUtils.ts @@ -23,7 +23,7 @@ import { matchFunctionName, type V1_ValueSpecification, } from '@finos/legend-graph'; -import { type DataCubeQuerySnapshotColumn } from './DataCubeQuerySnapshot.js'; +import { type DataCubeColumn } from './models/DataCubeColumn.js'; import { assertTrue, assertType, @@ -94,8 +94,8 @@ export function _funcMatch( * prune the expanded paths beyond that point. */ export function _pruneExpandedPaths( - prevGroupByCols: DataCubeQuerySnapshotColumn[], - currentGroupByCols: DataCubeQuerySnapshotColumn[], + prevGroupByCols: DataCubeColumn[], + currentGroupByCols: DataCubeColumn[], expandedPaths: string[], ) { const length = Math.min(prevGroupByCols.length, currentGroupByCols.length); diff --git a/packages/legend-data-cube/src/stores/core/__tests__/DataCubeQuerySnapshotBuilder.repl-test.ts b/packages/legend-data-cube/src/stores/core/__tests__/DataCubeQuerySnapshotBuilder.repl-test.ts index eb35007176..1e4c0f93d9 100644 --- a/packages/legend-data-cube/src/stores/core/__tests__/DataCubeQuerySnapshotBuilder.repl-test.ts +++ b/packages/legend-data-cube/src/stores/core/__tests__/DataCubeQuerySnapshotBuilder.repl-test.ts @@ -14,19 +14,14 @@ * limitations under the License. */ -import { - V1_Lambda, - V1_deserializeValueSpecification, -} from '@finos/legend-graph'; +import { V1_deserializeValueSpecification } from '@finos/legend-graph'; import { ENGINE_TEST_SUPPORT__grammarToJSON_valueSpecification } from '@finos/legend-graph/test'; import { unitTest } from '@finos/legend-shared/test'; import { describe, expect, test } from '@jest/globals'; import { validateAndBuildQuerySnapshot } from '../DataCubeQuerySnapshotBuilder.js'; import { assertErrorThrown } from '@finos/legend-shared'; -import { - DataCubeQuery, - DataCubeQuerySourceREPLExecutedQuery, -} from '../DataCubeQuery.js'; +import { DataCubeQuery } from '../models/DataCubeQuery.js'; +import { INTERNAL__DataCubeSource } from '../models/DataCubeSource.js'; type BaseSnapshotAnalysisTestCase = [ string, // name @@ -139,12 +134,9 @@ describe(unitTest('Analyze and build base snapshot'), () => { await ENGINE_TEST_SUPPORT__grammarToJSON_valueSpecification(code), [], ); - const baseQuery = new DataCubeQuery('', '', undefined); - baseQuery.source = new DataCubeQuerySourceREPLExecutedQuery(); - baseQuery.partialQuery = code; - baseQuery.source.query = ''; - baseQuery.source.runtime = 'local::TestRuntime'; - baseQuery.source.columns = columns.map((entry) => { + const baseQuery = new DataCubeQuery(undefined); + const source = new INTERNAL__DataCubeSource(); + source.sourceColumns = columns.map((entry) => { const parts = entry.split(':'); return { name: parts[0] as string, @@ -152,7 +144,7 @@ describe(unitTest('Analyze and build base snapshot'), () => { }; }); try { - validateAndBuildQuerySnapshot(partialQuery, new V1_Lambda(), baseQuery); + validateAndBuildQuerySnapshot(partialQuery, source, baseQuery); expect('').toEqual(problem); } catch (error: unknown) { assertErrorThrown(error); diff --git a/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation.ts b/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation.ts index c184eec7ac..9ef70e5702 100644 --- a/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation.ts +++ b/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation.ts @@ -15,9 +15,9 @@ */ import { guaranteeNonNullable } from '@finos/legend-shared'; -import type { DataCubeQuerySnapshotColumn } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { type V1_ColSpec } from '@finos/legend-graph'; -import type { DataCubeColumnConfiguration } from '../DataCubeConfiguration.js'; +import type { DataCubeColumnConfiguration } from '../models/DataCubeConfiguration.js'; // --------------------------------- UTILITIES --------------------------------- @@ -39,7 +39,7 @@ export abstract class DataCubeQueryAggregateOperation { abstract get description(): string; abstract get operator(): string; - abstract isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn): boolean; + abstract isCompatibleWithColumn(column: DataCubeColumn): boolean; abstract buildAggregateColumn( column: DataCubeColumnConfiguration, diff --git a/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__Average.tsx b/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__Average.tsx index f2c0d35025..4af6c0697d 100644 --- a/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__Average.tsx +++ b/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__Average.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import type { DataCubeQuerySnapshotColumn } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeQueryAggregateOperation } from './DataCubeQueryAggregateOperation.js'; import { DataCubeQueryAggregateOperator, @@ -23,7 +23,7 @@ import { ofDataType, } from '../DataCubeQueryEngine.js'; import { _aggCol_basic } from '../DataCubeQueryBuilderUtils.js'; -import type { DataCubeColumnConfiguration } from '../DataCubeConfiguration.js'; +import type { DataCubeColumnConfiguration } from '../models/DataCubeConfiguration.js'; export class DataCubeQueryAggregateOperation__Average extends DataCubeQueryAggregateOperation { override get label() { @@ -42,7 +42,7 @@ export class DataCubeQueryAggregateOperation__Average extends DataCubeQueryAggre return DataCubeQueryAggregateOperator.AVERAGE; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [DataCubeColumnDataType.NUMBER]); } diff --git a/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__Count.tsx b/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__Count.tsx index eac3415e69..f7a7c2f6ac 100644 --- a/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__Count.tsx +++ b/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__Count.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import type { DataCubeQuerySnapshotColumn } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeQueryAggregateOperation } from './DataCubeQueryAggregateOperation.js'; import { DataCubeQueryAggregateOperator, @@ -23,7 +23,7 @@ import { ofDataType, } from '../DataCubeQueryEngine.js'; import { _aggCol_basic } from '../DataCubeQueryBuilderUtils.js'; -import type { DataCubeColumnConfiguration } from '../DataCubeConfiguration.js'; +import type { DataCubeColumnConfiguration } from '../models/DataCubeConfiguration.js'; export class DataCubeQueryAggregateOperation__Count extends DataCubeQueryAggregateOperation { override get label() { @@ -42,7 +42,7 @@ export class DataCubeQueryAggregateOperation__Count extends DataCubeQueryAggrega return DataCubeQueryAggregateOperator.COUNT; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [ // NOTE: technically all data types are suported, // but we can't because we must preserve the type diff --git a/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__First.tsx b/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__First.tsx index df0c32e654..191759d926 100644 --- a/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__First.tsx +++ b/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__First.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import type { DataCubeQuerySnapshotColumn } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeQueryAggregateOperation } from './DataCubeQueryAggregateOperation.js'; import { DataCubeQueryAggregateOperator, @@ -23,7 +23,7 @@ import { ofDataType, } from '../DataCubeQueryEngine.js'; import { _aggCol_basic } from '../DataCubeQueryBuilderUtils.js'; -import type { DataCubeColumnConfiguration } from '../DataCubeConfiguration.js'; +import type { DataCubeColumnConfiguration } from '../models/DataCubeConfiguration.js'; export class DataCubeQueryAggregateOperation__First extends DataCubeQueryAggregateOperation { override get label() { @@ -42,7 +42,7 @@ export class DataCubeQueryAggregateOperation__First extends DataCubeQueryAggrega return DataCubeQueryAggregateOperator.FIRST; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [ DataCubeColumnDataType.TEXT, DataCubeColumnDataType.NUMBER, diff --git a/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__JoinStrings.tsx b/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__JoinStrings.tsx index 12bbe6d348..664897ba0c 100644 --- a/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__JoinStrings.tsx +++ b/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__JoinStrings.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import type { DataCubeQuerySnapshotColumn } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { PRIMITIVE_TYPE } from '@finos/legend-graph'; import { DataCubeQueryAggregateOperation } from './DataCubeQueryAggregateOperation.js'; import { @@ -32,7 +32,7 @@ import { _property, _var, } from '../DataCubeQueryBuilderUtils.js'; -import type { DataCubeColumnConfiguration } from '../DataCubeConfiguration.js'; +import type { DataCubeColumnConfiguration } from '../models/DataCubeConfiguration.js'; export class DataCubeQueryAggregateOperation__JoinStrings extends DataCubeQueryAggregateOperation { override get label() { @@ -51,7 +51,7 @@ export class DataCubeQueryAggregateOperation__JoinStrings extends DataCubeQueryA return DataCubeQueryAggregateOperator.JOIN_STRINGS; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [ // NOTE: technically all data types should be suported, // i.e. we can use meta::pure::functions::string::makeString diff --git a/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__Last.tsx b/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__Last.tsx index 079198b285..7783be8d20 100644 --- a/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__Last.tsx +++ b/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__Last.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import type { DataCubeQuerySnapshotColumn } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeQueryAggregateOperation } from './DataCubeQueryAggregateOperation.js'; import { DataCubeQueryAggregateOperator, @@ -23,7 +23,7 @@ import { ofDataType, } from '../DataCubeQueryEngine.js'; import { _aggCol_basic } from '../DataCubeQueryBuilderUtils.js'; -import type { DataCubeColumnConfiguration } from '../DataCubeConfiguration.js'; +import type { DataCubeColumnConfiguration } from '../models/DataCubeConfiguration.js'; export class DataCubeQueryAggregateOperation__Last extends DataCubeQueryAggregateOperation { override get label() { @@ -42,7 +42,7 @@ export class DataCubeQueryAggregateOperation__Last extends DataCubeQueryAggregat return DataCubeQueryAggregateOperator.LAST; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [ DataCubeColumnDataType.TEXT, DataCubeColumnDataType.NUMBER, diff --git a/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__Max.tsx b/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__Max.tsx index 57998e6de7..61a741d357 100644 --- a/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__Max.tsx +++ b/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__Max.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import type { DataCubeQuerySnapshotColumn } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeQueryAggregateOperation } from './DataCubeQueryAggregateOperation.js'; import { DataCubeQueryAggregateOperator, @@ -23,7 +23,7 @@ import { ofDataType, } from '../DataCubeQueryEngine.js'; import { _aggCol_basic } from '../DataCubeQueryBuilderUtils.js'; -import type { DataCubeColumnConfiguration } from '../DataCubeConfiguration.js'; +import type { DataCubeColumnConfiguration } from '../models/DataCubeConfiguration.js'; export class DataCubeQueryAggregateOperation__Max extends DataCubeQueryAggregateOperation { override get label() { @@ -42,7 +42,7 @@ export class DataCubeQueryAggregateOperation__Max extends DataCubeQueryAggregate return DataCubeQueryAggregateOperator.MAX; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [DataCubeColumnDataType.NUMBER]); } diff --git a/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__Min.tsx b/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__Min.tsx index 332f5c6ce1..b6008044d8 100644 --- a/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__Min.tsx +++ b/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__Min.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import type { DataCubeQuerySnapshotColumn } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeQueryAggregateOperation } from './DataCubeQueryAggregateOperation.js'; import { DataCubeQueryAggregateOperator, @@ -23,7 +23,7 @@ import { ofDataType, } from '../DataCubeQueryEngine.js'; import { _aggCol_basic } from '../DataCubeQueryBuilderUtils.js'; -import type { DataCubeColumnConfiguration } from '../DataCubeConfiguration.js'; +import type { DataCubeColumnConfiguration } from '../models/DataCubeConfiguration.js'; export class DataCubeQueryAggregateOperation__Min extends DataCubeQueryAggregateOperation { override get label() { @@ -42,7 +42,7 @@ export class DataCubeQueryAggregateOperation__Min extends DataCubeQueryAggregate return DataCubeQueryAggregateOperator.MIN; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [DataCubeColumnDataType.NUMBER]); } diff --git a/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__StdDevPopulation.tsx b/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__StdDevPopulation.tsx index 18041c82cb..335a014895 100644 --- a/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__StdDevPopulation.tsx +++ b/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__StdDevPopulation.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import type { DataCubeQuerySnapshotColumn } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeQueryAggregateOperation } from './DataCubeQueryAggregateOperation.js'; import { DataCubeQueryAggregateOperator, @@ -23,7 +23,7 @@ import { ofDataType, } from '../DataCubeQueryEngine.js'; import { _aggCol_basic } from '../DataCubeQueryBuilderUtils.js'; -import type { DataCubeColumnConfiguration } from '../DataCubeConfiguration.js'; +import type { DataCubeColumnConfiguration } from '../models/DataCubeConfiguration.js'; export class DataCubeQueryAggregateOperation__StdDevPopulation extends DataCubeQueryAggregateOperation { override get label() { @@ -42,7 +42,7 @@ export class DataCubeQueryAggregateOperation__StdDevPopulation extends DataCubeQ return DataCubeQueryAggregateOperator.STANDARD_DEVIATION_POPULATION; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [DataCubeColumnDataType.NUMBER]); } diff --git a/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__StdDevSample.tsx b/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__StdDevSample.tsx index a2fe30be21..ea9d78aadf 100644 --- a/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__StdDevSample.tsx +++ b/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__StdDevSample.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import type { DataCubeQuerySnapshotColumn } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeQueryAggregateOperation } from './DataCubeQueryAggregateOperation.js'; import { DataCubeQueryAggregateOperator, @@ -23,7 +23,7 @@ import { ofDataType, } from '../DataCubeQueryEngine.js'; import { _aggCol_basic } from '../DataCubeQueryBuilderUtils.js'; -import type { DataCubeColumnConfiguration } from '../DataCubeConfiguration.js'; +import type { DataCubeColumnConfiguration } from '../models/DataCubeConfiguration.js'; export class DataCubeQueryAggregateOperation__StdDevSample extends DataCubeQueryAggregateOperation { override get label() { @@ -42,7 +42,7 @@ export class DataCubeQueryAggregateOperation__StdDevSample extends DataCubeQuery return DataCubeQueryAggregateOperator.STANDARD_DEVIATION_SAMPLE; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [DataCubeColumnDataType.NUMBER]); } diff --git a/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__Sum.tsx b/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__Sum.tsx index 412d197a5f..cefc1bebdf 100644 --- a/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__Sum.tsx +++ b/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__Sum.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import type { DataCubeQuerySnapshotColumn } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeQueryAggregateOperation } from './DataCubeQueryAggregateOperation.js'; import { DataCubeQueryAggregateOperator, @@ -23,7 +23,7 @@ import { ofDataType, } from '../DataCubeQueryEngine.js'; import { _aggCol_basic } from '../DataCubeQueryBuilderUtils.js'; -import type { DataCubeColumnConfiguration } from '../DataCubeConfiguration.js'; +import type { DataCubeColumnConfiguration } from '../models/DataCubeConfiguration.js'; export class DataCubeQueryAggregateOperation__Sum extends DataCubeQueryAggregateOperation { override get label() { @@ -42,7 +42,7 @@ export class DataCubeQueryAggregateOperation__Sum extends DataCubeQueryAggregate return DataCubeQueryAggregateOperator.SUM; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [DataCubeColumnDataType.NUMBER]); } diff --git a/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__UniqueValue.tsx b/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__UniqueValue.tsx index efd682f74b..a94ce709d6 100644 --- a/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__UniqueValue.tsx +++ b/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__UniqueValue.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import type { DataCubeQuerySnapshotColumn } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeQueryAggregateOperation } from './DataCubeQueryAggregateOperation.js'; import { DataCubeQueryAggregateOperator, @@ -23,7 +23,7 @@ import { ofDataType, } from '../DataCubeQueryEngine.js'; import { _aggCol_basic } from '../DataCubeQueryBuilderUtils.js'; -import type { DataCubeColumnConfiguration } from '../DataCubeConfiguration.js'; +import type { DataCubeColumnConfiguration } from '../models/DataCubeConfiguration.js'; export class DataCubeQueryAggregateOperation__UniqueValue extends DataCubeQueryAggregateOperation { override get label() { @@ -42,7 +42,7 @@ export class DataCubeQueryAggregateOperation__UniqueValue extends DataCubeQueryA return DataCubeQueryAggregateOperator.UNIQUE; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [ DataCubeColumnDataType.TEXT, DataCubeColumnDataType.NUMBER, diff --git a/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__VariancePopulation.tsx b/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__VariancePopulation.tsx index adf63bc5cc..5c8ead2d21 100644 --- a/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__VariancePopulation.tsx +++ b/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__VariancePopulation.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import type { DataCubeQuerySnapshotColumn } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeQueryAggregateOperation } from './DataCubeQueryAggregateOperation.js'; import { DataCubeQueryAggregateOperator, @@ -23,7 +23,7 @@ import { ofDataType, } from '../DataCubeQueryEngine.js'; import { _aggCol_basic } from '../DataCubeQueryBuilderUtils.js'; -import type { DataCubeColumnConfiguration } from '../DataCubeConfiguration.js'; +import type { DataCubeColumnConfiguration } from '../models/DataCubeConfiguration.js'; export class DataCubeQueryAggregateOperation__VariancePopulation extends DataCubeQueryAggregateOperation { override get label() { @@ -42,7 +42,7 @@ export class DataCubeQueryAggregateOperation__VariancePopulation extends DataCub return DataCubeQueryAggregateOperator.VARIANCE_POPULATION; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [DataCubeColumnDataType.NUMBER]); } diff --git a/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__VarianceSample.tsx b/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__VarianceSample.tsx index dc0e6093ae..1db12b20b3 100644 --- a/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__VarianceSample.tsx +++ b/packages/legend-data-cube/src/stores/core/aggregation/DataCubeQueryAggregateOperation__VarianceSample.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import type { DataCubeQuerySnapshotColumn } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeQueryAggregateOperation } from './DataCubeQueryAggregateOperation.js'; import { DataCubeQueryAggregateOperator, @@ -23,7 +23,7 @@ import { ofDataType, } from '../DataCubeQueryEngine.js'; import { _aggCol_basic } from '../DataCubeQueryBuilderUtils.js'; -import type { DataCubeColumnConfiguration } from '../DataCubeConfiguration.js'; +import type { DataCubeColumnConfiguration } from '../models/DataCubeConfiguration.js'; export class DataCubeQueryAggregateOperation__VarianceSample extends DataCubeQueryAggregateOperation { override get label() { @@ -42,7 +42,7 @@ export class DataCubeQueryAggregateOperation__VarianceSample extends DataCubeQue return DataCubeQueryAggregateOperator.VARIANCE_SAMPLE; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [DataCubeColumnDataType.NUMBER]); } diff --git a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterEditorState.ts b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterEditorState.ts index a92e48cf72..b31ba25682 100644 --- a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterEditorState.ts +++ b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterEditorState.ts @@ -25,10 +25,10 @@ import { DataCubeQueryFilterGroupOperator, } from '../DataCubeQueryEngine.js'; import type { - DataCubeQuerySnapshotColumn, DataCubeQuerySnapshotFilter, DataCubeQuerySnapshotFilterCondition, } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import type { DataCubeQueryFilterOperation } from './DataCubeQueryFilterOperation.js'; export abstract class DataCubeFilterEditorTreeNode { @@ -62,13 +62,13 @@ export abstract class DataCubeFilterEditorTreeNode { } export class DataCubeFilterEditorConditionTreeNode extends DataCubeFilterEditorTreeNode { - column: DataCubeQuerySnapshotColumn; + column: DataCubeColumn; operation: DataCubeQueryFilterOperation; value: DataCubeOperationValue | undefined; constructor( parent: DataCubeFilterEditorConditionGroupTreeNode | undefined, - column: DataCubeQuerySnapshotColumn, + column: DataCubeColumn, operation: DataCubeQueryFilterOperation, value: DataCubeOperationValue | undefined, not: boolean | undefined, @@ -92,7 +92,7 @@ export class DataCubeFilterEditorConditionTreeNode extends DataCubeFilterEditorT this.setValue(value); } - setColumn(col: DataCubeQuerySnapshotColumn) { + setColumn(col: DataCubeColumn) { this.column = col; } diff --git a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation.ts b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation.ts index 21c00017bb..3a77ba45fd 100644 --- a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation.ts +++ b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation.ts @@ -20,10 +20,8 @@ import { UnsupportedOperationError, } from '@finos/legend-shared'; import type { DataCubeOperationValue } from '../DataCubeQueryEngine.js'; -import type { - DataCubeQuerySnapshotColumn, - DataCubeQuerySnapshotFilterCondition, -} from '../DataCubeQuerySnapshot.js'; +import type { DataCubeQuerySnapshotFilterCondition } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DATE_FORMAT, DATE_TIME_FORMAT, @@ -79,11 +77,11 @@ export abstract class DataCubeQueryFilterOperation { abstract get description(): string; abstract get operator(): string; - abstract isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn): boolean; + abstract isCompatibleWithColumn(column: DataCubeColumn): boolean; abstract isCompatibleWithValue(value: DataCubeOperationValue): boolean; abstract generateDefaultValue( - column: DataCubeQuerySnapshotColumn, + column: DataCubeColumn, ): DataCubeOperationValue | undefined; abstract buildConditionSnapshot( diff --git a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__Contain.tsx b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__Contain.tsx index 654350285c..4ca3f3c78f 100644 --- a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__Contain.tsx +++ b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__Contain.tsx @@ -19,10 +19,8 @@ import { DataCubeQueryFilterOperation, generateDefaultFilterConditionPrimitiveTypeValue, } from './DataCubeQueryFilterOperation.js'; -import type { - DataCubeQuerySnapshotColumn, - DataCubeQuerySnapshotFilterCondition, -} from '../DataCubeQuerySnapshot.js'; +import type { DataCubeQuerySnapshotFilterCondition } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeColumnDataType, DataCubeFunction, @@ -55,7 +53,7 @@ export class DataCubeQueryFilterOperation__Contain extends DataCubeQueryFilterOp return DataCubeQueryFilterOperator.CONTAIN; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [DataCubeColumnDataType.TEXT]); } @@ -67,7 +65,7 @@ export class DataCubeQueryFilterOperation__Contain extends DataCubeQueryFilterOp ); } - generateDefaultValue(column: DataCubeQuerySnapshotColumn) { + generateDefaultValue(column: DataCubeColumn) { return { type: column.type, value: generateDefaultFilterConditionPrimitiveTypeValue(column.type), diff --git a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__ContainCaseInsensitive.tsx b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__ContainCaseInsensitive.tsx index 1e2b6a3e2d..5940e1fb6e 100644 --- a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__ContainCaseInsensitive.tsx +++ b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__ContainCaseInsensitive.tsx @@ -19,10 +19,8 @@ import { DataCubeQueryFilterOperation, generateDefaultFilterConditionPrimitiveTypeValue, } from './DataCubeQueryFilterOperation.js'; -import type { - DataCubeQuerySnapshotColumn, - DataCubeQuerySnapshotFilterCondition, -} from '../DataCubeQuerySnapshot.js'; +import type { DataCubeQuerySnapshotFilterCondition } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeColumnDataType, DataCubeFunction, @@ -56,7 +54,7 @@ export class DataCubeQueryFilterOperation__ContainCaseInsensitive extends DataCu return DataCubeQueryFilterOperator.CONTAIN_CASE_INSENSITIVE; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [DataCubeColumnDataType.TEXT]); } @@ -68,7 +66,7 @@ export class DataCubeQueryFilterOperation__ContainCaseInsensitive extends DataCu ); } - generateDefaultValue(column: DataCubeQuerySnapshotColumn) { + generateDefaultValue(column: DataCubeColumn) { return { type: column.type, value: generateDefaultFilterConditionPrimitiveTypeValue(column.type), diff --git a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__EndWith.tsx b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__EndWith.tsx index 9a315a0c9d..c60c64a159 100644 --- a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__EndWith.tsx +++ b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__EndWith.tsx @@ -19,10 +19,8 @@ import { DataCubeQueryFilterOperation, generateDefaultFilterConditionPrimitiveTypeValue, } from './DataCubeQueryFilterOperation.js'; -import type { - DataCubeQuerySnapshotColumn, - DataCubeQuerySnapshotFilterCondition, -} from '../DataCubeQuerySnapshot.js'; +import type { DataCubeQuerySnapshotFilterCondition } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeColumnDataType, DataCubeFunction, @@ -55,7 +53,7 @@ export class DataCubeQueryFilterOperation__EndWith extends DataCubeQueryFilterOp return DataCubeQueryFilterOperator.END_WITH; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [DataCubeColumnDataType.TEXT]); } @@ -67,7 +65,7 @@ export class DataCubeQueryFilterOperation__EndWith extends DataCubeQueryFilterOp ); } - generateDefaultValue(column: DataCubeQuerySnapshotColumn) { + generateDefaultValue(column: DataCubeColumn) { return { type: column.type, value: generateDefaultFilterConditionPrimitiveTypeValue(column.type), diff --git a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__EndWithCaseInsensitive.tsx b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__EndWithCaseInsensitive.tsx index b2d109567f..c550185219 100644 --- a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__EndWithCaseInsensitive.tsx +++ b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__EndWithCaseInsensitive.tsx @@ -19,10 +19,8 @@ import { DataCubeQueryFilterOperation, generateDefaultFilterConditionPrimitiveTypeValue, } from './DataCubeQueryFilterOperation.js'; -import type { - DataCubeQuerySnapshotColumn, - DataCubeQuerySnapshotFilterCondition, -} from '../DataCubeQuerySnapshot.js'; +import type { DataCubeQuerySnapshotFilterCondition } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeColumnDataType, DataCubeFunction, @@ -56,7 +54,7 @@ export class DataCubeQueryFilterOperation__EndWithCaseInsensitive extends DataCu return DataCubeQueryFilterOperator.END_WITH_CASE_INSENSITIVE; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [DataCubeColumnDataType.TEXT]); } @@ -68,7 +66,7 @@ export class DataCubeQueryFilterOperation__EndWithCaseInsensitive extends DataCu ); } - generateDefaultValue(column: DataCubeQuerySnapshotColumn) { + generateDefaultValue(column: DataCubeColumn) { return { type: column.type, value: generateDefaultFilterConditionPrimitiveTypeValue(column.type), diff --git a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__Equal.tsx b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__Equal.tsx index 7208d6d0f5..1351132389 100644 --- a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__Equal.tsx +++ b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__Equal.tsx @@ -19,10 +19,8 @@ import { DataCubeQueryFilterOperation, generateDefaultFilterConditionPrimitiveTypeValue, } from './DataCubeQueryFilterOperation.js'; -import type { - DataCubeQuerySnapshotColumn, - DataCubeQuerySnapshotFilterCondition, -} from '../DataCubeQuerySnapshot.js'; +import type { DataCubeQuerySnapshotFilterCondition } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeColumnDataType, DataCubeFunction, @@ -55,7 +53,7 @@ export class DataCubeQueryFilterOperation__Equal extends DataCubeQueryFilterOper return DataCubeQueryFilterOperator.EQUAL; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [ DataCubeColumnDataType.TEXT, DataCubeColumnDataType.NUMBER, @@ -77,7 +75,7 @@ export class DataCubeQueryFilterOperation__Equal extends DataCubeQueryFilterOper ); } - generateDefaultValue(column: DataCubeQuerySnapshotColumn) { + generateDefaultValue(column: DataCubeColumn) { return { type: column.type, value: generateDefaultFilterConditionPrimitiveTypeValue(column.type), diff --git a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__EqualCaseInsensitive.tsx b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__EqualCaseInsensitive.tsx index 6b61a55219..40424c5789 100644 --- a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__EqualCaseInsensitive.tsx +++ b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__EqualCaseInsensitive.tsx @@ -19,10 +19,8 @@ import { DataCubeQueryFilterOperation, generateDefaultFilterConditionPrimitiveTypeValue, } from './DataCubeQueryFilterOperation.js'; -import type { - DataCubeQuerySnapshotColumn, - DataCubeQuerySnapshotFilterCondition, -} from '../DataCubeQuerySnapshot.js'; +import type { DataCubeQuerySnapshotFilterCondition } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeColumnDataType, DataCubeFunction, @@ -56,7 +54,7 @@ export class DataCubeQueryFilterOperation__EqualCaseInsensitive extends DataCube return DataCubeQueryFilterOperator.EQUAL_CASE_INSENSITIVE; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [DataCubeColumnDataType.TEXT]); } @@ -68,7 +66,7 @@ export class DataCubeQueryFilterOperation__EqualCaseInsensitive extends DataCube ); } - generateDefaultValue(column: DataCubeQuerySnapshotColumn) { + generateDefaultValue(column: DataCubeColumn) { return { type: column.type, value: generateDefaultFilterConditionPrimitiveTypeValue(column.type), diff --git a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__EqualCaseInsensitiveColumn.tsx b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__EqualCaseInsensitiveColumn.tsx index c2ce27a35c..fbff1a7291 100644 --- a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__EqualCaseInsensitiveColumn.tsx +++ b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__EqualCaseInsensitiveColumn.tsx @@ -16,10 +16,8 @@ import { type V1_AppliedFunction } from '@finos/legend-graph'; import { DataCubeQueryFilterOperation } from './DataCubeQueryFilterOperation.js'; -import type { - DataCubeQuerySnapshotColumn, - DataCubeQuerySnapshotFilterCondition, -} from '../DataCubeQuerySnapshot.js'; +import type { DataCubeQuerySnapshotFilterCondition } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeColumnDataType, DataCubeFunction, @@ -54,7 +52,7 @@ export class DataCubeQueryFilterOperation__EqualCaseInsensitiveColumn extends Da return DataCubeQueryFilterOperator.EQUAL_CASE_INSENSITIVE_COLUMN; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [DataCubeColumnDataType.TEXT]); } @@ -66,7 +64,7 @@ export class DataCubeQueryFilterOperation__EqualCaseInsensitiveColumn extends Da ); } - generateDefaultValue(column: DataCubeQuerySnapshotColumn) { + generateDefaultValue(column: DataCubeColumn) { return { type: DataCubeOperationAdvancedValueType.COLUMN, value: column.name, diff --git a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__EqualColumn.tsx b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__EqualColumn.tsx index 65a6a702a8..588e71dbd3 100644 --- a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__EqualColumn.tsx +++ b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__EqualColumn.tsx @@ -16,10 +16,8 @@ import { type V1_AppliedFunction } from '@finos/legend-graph'; import { DataCubeQueryFilterOperation } from './DataCubeQueryFilterOperation.js'; -import type { - DataCubeQuerySnapshotColumn, - DataCubeQuerySnapshotFilterCondition, -} from '../DataCubeQuerySnapshot.js'; +import type { DataCubeQuerySnapshotFilterCondition } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeColumnDataType, DataCubeFunction, @@ -54,7 +52,7 @@ export class DataCubeQueryFilterOperation__EqualColumn extends DataCubeQueryFilt return DataCubeQueryFilterOperator.EQUAL_COLUMN; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [ DataCubeColumnDataType.TEXT, DataCubeColumnDataType.NUMBER, @@ -71,7 +69,7 @@ export class DataCubeQueryFilterOperation__EqualColumn extends DataCubeQueryFilt ); } - generateDefaultValue(column: DataCubeQuerySnapshotColumn) { + generateDefaultValue(column: DataCubeColumn) { return { type: DataCubeOperationAdvancedValueType.COLUMN, value: column.name, diff --git a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__GreaterThan.tsx b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__GreaterThan.tsx index f60343d69a..f1dfac3a96 100644 --- a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__GreaterThan.tsx +++ b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__GreaterThan.tsx @@ -19,10 +19,8 @@ import { DataCubeQueryFilterOperation, generateDefaultFilterConditionPrimitiveTypeValue, } from './DataCubeQueryFilterOperation.js'; -import type { - DataCubeQuerySnapshotColumn, - DataCubeQuerySnapshotFilterCondition, -} from '../DataCubeQuerySnapshot.js'; +import type { DataCubeQuerySnapshotFilterCondition } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeColumnDataType, DataCubeFunction, @@ -55,7 +53,7 @@ export class DataCubeQueryFilterOperation__GreaterThan extends DataCubeQueryFilt return DataCubeQueryFilterOperator.GREATER_THAN; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [ DataCubeColumnDataType.NUMBER, DataCubeColumnDataType.DATE, @@ -75,7 +73,7 @@ export class DataCubeQueryFilterOperation__GreaterThan extends DataCubeQueryFilt ); } - generateDefaultValue(column: DataCubeQuerySnapshotColumn) { + generateDefaultValue(column: DataCubeColumn) { return { type: column.type, value: generateDefaultFilterConditionPrimitiveTypeValue(column.type), diff --git a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__GreaterThanColumn.tsx b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__GreaterThanColumn.tsx index fa4678a94c..98d36e31c8 100644 --- a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__GreaterThanColumn.tsx +++ b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__GreaterThanColumn.tsx @@ -16,10 +16,8 @@ import { type V1_AppliedFunction } from '@finos/legend-graph'; import { DataCubeQueryFilterOperation } from './DataCubeQueryFilterOperation.js'; -import type { - DataCubeQuerySnapshotColumn, - DataCubeQuerySnapshotFilterCondition, -} from '../DataCubeQuerySnapshot.js'; +import type { DataCubeQuerySnapshotFilterCondition } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeColumnDataType, DataCubeFunction, @@ -54,7 +52,7 @@ export class DataCubeQueryFilterOperation__GreaterThanColumn extends DataCubeQue return DataCubeQueryFilterOperator.GREATER_THAN_COLUMN; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [ DataCubeColumnDataType.NUMBER, DataCubeColumnDataType.DATE, @@ -70,7 +68,7 @@ export class DataCubeQueryFilterOperation__GreaterThanColumn extends DataCubeQue ); } - generateDefaultValue(column: DataCubeQuerySnapshotColumn) { + generateDefaultValue(column: DataCubeColumn) { return { type: DataCubeOperationAdvancedValueType.COLUMN, value: column.name, diff --git a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__GreaterThanOrEqual.tsx b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__GreaterThanOrEqual.tsx index 2f163dcb40..24866824b6 100644 --- a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__GreaterThanOrEqual.tsx +++ b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__GreaterThanOrEqual.tsx @@ -19,10 +19,8 @@ import { DataCubeQueryFilterOperation, generateDefaultFilterConditionPrimitiveTypeValue, } from './DataCubeQueryFilterOperation.js'; -import type { - DataCubeQuerySnapshotColumn, - DataCubeQuerySnapshotFilterCondition, -} from '../DataCubeQuerySnapshot.js'; +import type { DataCubeQuerySnapshotFilterCondition } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeColumnDataType, DataCubeFunction, @@ -55,7 +53,7 @@ export class DataCubeQueryFilterOperation__GreaterThanOrEqual extends DataCubeQu return DataCubeQueryFilterOperator.GREATER_THAN_OR_EQUAL; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [ DataCubeColumnDataType.NUMBER, DataCubeColumnDataType.DATE, @@ -75,7 +73,7 @@ export class DataCubeQueryFilterOperation__GreaterThanOrEqual extends DataCubeQu ); } - generateDefaultValue(column: DataCubeQuerySnapshotColumn) { + generateDefaultValue(column: DataCubeColumn) { return { type: column.type, value: generateDefaultFilterConditionPrimitiveTypeValue(column.type), diff --git a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__GreaterThanOrEqualColumn.tsx b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__GreaterThanOrEqualColumn.tsx index 3e9e4d36f5..8217ca56ff 100644 --- a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__GreaterThanOrEqualColumn.tsx +++ b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__GreaterThanOrEqualColumn.tsx @@ -16,10 +16,8 @@ import { type V1_AppliedFunction } from '@finos/legend-graph'; import { DataCubeQueryFilterOperation } from './DataCubeQueryFilterOperation.js'; -import type { - DataCubeQuerySnapshotColumn, - DataCubeQuerySnapshotFilterCondition, -} from '../DataCubeQuerySnapshot.js'; +import type { DataCubeQuerySnapshotFilterCondition } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeColumnDataType, DataCubeFunction, @@ -54,7 +52,7 @@ export class DataCubeQueryFilterOperation__GreaterThanOrEqualColumn extends Data return DataCubeQueryFilterOperator.GREATER_THAN_OR_EQUAL_COLUMN; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [ DataCubeColumnDataType.NUMBER, DataCubeColumnDataType.DATE, @@ -70,7 +68,7 @@ export class DataCubeQueryFilterOperation__GreaterThanOrEqualColumn extends Data ); } - generateDefaultValue(column: DataCubeQuerySnapshotColumn) { + generateDefaultValue(column: DataCubeColumn) { return { type: DataCubeOperationAdvancedValueType.COLUMN, value: column.name, diff --git a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__IsNotNull.tsx b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__IsNotNull.tsx index 913d57da64..524c5692c2 100644 --- a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__IsNotNull.tsx +++ b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__IsNotNull.tsx @@ -16,10 +16,8 @@ import { type V1_AppliedFunction } from '@finos/legend-graph'; import { DataCubeQueryFilterOperation } from './DataCubeQueryFilterOperation.js'; -import type { - DataCubeQuerySnapshotColumn, - DataCubeQuerySnapshotFilterCondition, -} from '../DataCubeQuerySnapshot.js'; +import type { DataCubeQuerySnapshotFilterCondition } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeColumnDataType, DataCubeFunction, @@ -51,7 +49,7 @@ export class DataCubeQueryFilterOperation__IsNotNull extends DataCubeQueryFilter return DataCubeQueryFilterOperator.IS_NOT_NULL; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [ DataCubeColumnDataType.TEXT, DataCubeColumnDataType.NUMBER, @@ -73,7 +71,7 @@ export class DataCubeQueryFilterOperation__IsNotNull extends DataCubeQueryFilter ); } - generateDefaultValue(column: DataCubeQuerySnapshotColumn) { + generateDefaultValue(column: DataCubeColumn) { return undefined; } diff --git a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__IsNull.tsx b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__IsNull.tsx index a98eb91cbc..06512d1590 100644 --- a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__IsNull.tsx +++ b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__IsNull.tsx @@ -16,10 +16,8 @@ import { type V1_AppliedFunction } from '@finos/legend-graph'; import { DataCubeQueryFilterOperation } from './DataCubeQueryFilterOperation.js'; -import type { - DataCubeQuerySnapshotColumn, - DataCubeQuerySnapshotFilterCondition, -} from '../DataCubeQuerySnapshot.js'; +import type { DataCubeQuerySnapshotFilterCondition } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeColumnDataType, DataCubeFunction, @@ -50,7 +48,7 @@ export class DataCubeQueryFilterOperation__IsNull extends DataCubeQueryFilterOpe return DataCubeQueryFilterOperator.IS_NULL; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [ DataCubeColumnDataType.TEXT, DataCubeColumnDataType.NUMBER, @@ -72,7 +70,7 @@ export class DataCubeQueryFilterOperation__IsNull extends DataCubeQueryFilterOpe ); } - generateDefaultValue(column: DataCubeQuerySnapshotColumn) { + generateDefaultValue(column: DataCubeColumn) { return undefined; } diff --git a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__LessThan.tsx b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__LessThan.tsx index 61f22f04f6..53ef07b674 100644 --- a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__LessThan.tsx +++ b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__LessThan.tsx @@ -19,10 +19,8 @@ import { DataCubeQueryFilterOperation, generateDefaultFilterConditionPrimitiveTypeValue, } from './DataCubeQueryFilterOperation.js'; -import type { - DataCubeQuerySnapshotColumn, - DataCubeQuerySnapshotFilterCondition, -} from '../DataCubeQuerySnapshot.js'; +import type { DataCubeQuerySnapshotFilterCondition } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeColumnDataType, DataCubeFunction, @@ -55,7 +53,7 @@ export class DataCubeQueryFilterOperation__LessThan extends DataCubeQueryFilterO return DataCubeQueryFilterOperator.LESS_THAN; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [ DataCubeColumnDataType.NUMBER, DataCubeColumnDataType.DATE, @@ -75,7 +73,7 @@ export class DataCubeQueryFilterOperation__LessThan extends DataCubeQueryFilterO ); } - generateDefaultValue(column: DataCubeQuerySnapshotColumn) { + generateDefaultValue(column: DataCubeColumn) { return { type: column.type, value: generateDefaultFilterConditionPrimitiveTypeValue(column.type), diff --git a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__LessThanColumn.tsx b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__LessThanColumn.tsx index 9915871de2..054de472b9 100644 --- a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__LessThanColumn.tsx +++ b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__LessThanColumn.tsx @@ -16,10 +16,8 @@ import { type V1_AppliedFunction } from '@finos/legend-graph'; import { DataCubeQueryFilterOperation } from './DataCubeQueryFilterOperation.js'; -import type { - DataCubeQuerySnapshotColumn, - DataCubeQuerySnapshotFilterCondition, -} from '../DataCubeQuerySnapshot.js'; +import type { DataCubeQuerySnapshotFilterCondition } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeColumnDataType, DataCubeFunction, @@ -54,7 +52,7 @@ export class DataCubeQueryFilterOperation__LessThanColumn extends DataCubeQueryF return DataCubeQueryFilterOperator.LESS_THAN_COLUMN; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [ DataCubeColumnDataType.NUMBER, DataCubeColumnDataType.DATE, @@ -70,7 +68,7 @@ export class DataCubeQueryFilterOperation__LessThanColumn extends DataCubeQueryF ); } - generateDefaultValue(column: DataCubeQuerySnapshotColumn) { + generateDefaultValue(column: DataCubeColumn) { return { type: DataCubeOperationAdvancedValueType.COLUMN, value: column.name, diff --git a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__LessThanOrEqual.tsx b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__LessThanOrEqual.tsx index 0dbf688745..0810308cc1 100644 --- a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__LessThanOrEqual.tsx +++ b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__LessThanOrEqual.tsx @@ -19,10 +19,8 @@ import { DataCubeQueryFilterOperation, generateDefaultFilterConditionPrimitiveTypeValue, } from './DataCubeQueryFilterOperation.js'; -import type { - DataCubeQuerySnapshotColumn, - DataCubeQuerySnapshotFilterCondition, -} from '../DataCubeQuerySnapshot.js'; +import type { DataCubeQuerySnapshotFilterCondition } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeColumnDataType, DataCubeFunction, @@ -55,7 +53,7 @@ export class DataCubeQueryFilterOperation__LessThanOrEqual extends DataCubeQuery return DataCubeQueryFilterOperator.LESS_THAN_OR_EQUAL; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [ DataCubeColumnDataType.NUMBER, DataCubeColumnDataType.DATE, @@ -75,7 +73,7 @@ export class DataCubeQueryFilterOperation__LessThanOrEqual extends DataCubeQuery ); } - generateDefaultValue(column: DataCubeQuerySnapshotColumn) { + generateDefaultValue(column: DataCubeColumn) { return { type: column.type, value: generateDefaultFilterConditionPrimitiveTypeValue(column.type), diff --git a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__LessThanOrEqualColumn.tsx b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__LessThanOrEqualColumn.tsx index 7bf7af275b..97392e1e31 100644 --- a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__LessThanOrEqualColumn.tsx +++ b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__LessThanOrEqualColumn.tsx @@ -16,10 +16,8 @@ import { type V1_AppliedFunction } from '@finos/legend-graph'; import { DataCubeQueryFilterOperation } from './DataCubeQueryFilterOperation.js'; -import type { - DataCubeQuerySnapshotColumn, - DataCubeQuerySnapshotFilterCondition, -} from '../DataCubeQuerySnapshot.js'; +import type { DataCubeQuerySnapshotFilterCondition } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeColumnDataType, DataCubeFunction, @@ -54,7 +52,7 @@ export class DataCubeQueryFilterOperation__LessThanOrEqualColumn extends DataCub return DataCubeQueryFilterOperator.LESS_THAN_OR_EQUAL_COLUMN; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [ DataCubeColumnDataType.NUMBER, DataCubeColumnDataType.DATE, @@ -70,7 +68,7 @@ export class DataCubeQueryFilterOperation__LessThanOrEqualColumn extends DataCub ); } - generateDefaultValue(column: DataCubeQuerySnapshotColumn) { + generateDefaultValue(column: DataCubeColumn) { return { type: DataCubeOperationAdvancedValueType.COLUMN, value: column.name, diff --git a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__NotContain.tsx b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__NotContain.tsx index 45a22b814f..6715b72c99 100644 --- a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__NotContain.tsx +++ b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__NotContain.tsx @@ -19,10 +19,8 @@ import { DataCubeQueryFilterOperation, generateDefaultFilterConditionPrimitiveTypeValue, } from './DataCubeQueryFilterOperation.js'; -import type { - DataCubeQuerySnapshotColumn, - DataCubeQuerySnapshotFilterCondition, -} from '../DataCubeQuerySnapshot.js'; +import type { DataCubeQuerySnapshotFilterCondition } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeColumnDataType, DataCubeFunction, @@ -56,7 +54,7 @@ export class DataCubeQueryFilterOperation__NotContain extends DataCubeQueryFilte return DataCubeQueryFilterOperator.NOT_CONTAIN; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [DataCubeColumnDataType.TEXT]); } @@ -68,7 +66,7 @@ export class DataCubeQueryFilterOperation__NotContain extends DataCubeQueryFilte ); } - generateDefaultValue(column: DataCubeQuerySnapshotColumn) { + generateDefaultValue(column: DataCubeColumn) { return { type: column.type, value: generateDefaultFilterConditionPrimitiveTypeValue(column.type), diff --git a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__NotEndWith.tsx b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__NotEndWith.tsx index fb1bc5c123..5670304511 100644 --- a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__NotEndWith.tsx +++ b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__NotEndWith.tsx @@ -19,10 +19,8 @@ import { DataCubeQueryFilterOperation, generateDefaultFilterConditionPrimitiveTypeValue, } from './DataCubeQueryFilterOperation.js'; -import type { - DataCubeQuerySnapshotColumn, - DataCubeQuerySnapshotFilterCondition, -} from '../DataCubeQuerySnapshot.js'; +import type { DataCubeQuerySnapshotFilterCondition } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeColumnDataType, DataCubeFunction, @@ -56,7 +54,7 @@ export class DataCubeQueryFilterOperation__NotEndWith extends DataCubeQueryFilte return DataCubeQueryFilterOperator.NOT_END_WITH; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [DataCubeColumnDataType.TEXT]); } @@ -68,7 +66,7 @@ export class DataCubeQueryFilterOperation__NotEndWith extends DataCubeQueryFilte ); } - generateDefaultValue(column: DataCubeQuerySnapshotColumn) { + generateDefaultValue(column: DataCubeColumn) { return { type: column.type, value: generateDefaultFilterConditionPrimitiveTypeValue(column.type), diff --git a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__NotEqual.tsx b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__NotEqual.tsx index adc6da8113..5209f0987f 100644 --- a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__NotEqual.tsx +++ b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__NotEqual.tsx @@ -19,10 +19,8 @@ import { DataCubeQueryFilterOperation, generateDefaultFilterConditionPrimitiveTypeValue, } from './DataCubeQueryFilterOperation.js'; -import type { - DataCubeQuerySnapshotColumn, - DataCubeQuerySnapshotFilterCondition, -} from '../DataCubeQuerySnapshot.js'; +import type { DataCubeQuerySnapshotFilterCondition } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeColumnDataType, DataCubeFunction, @@ -56,7 +54,7 @@ export class DataCubeQueryFilterOperation__NotEqual extends DataCubeQueryFilterO return DataCubeQueryFilterOperator.NOT_EQUAL; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [ DataCubeColumnDataType.TEXT, DataCubeColumnDataType.NUMBER, @@ -78,7 +76,7 @@ export class DataCubeQueryFilterOperation__NotEqual extends DataCubeQueryFilterO ); } - generateDefaultValue(column: DataCubeQuerySnapshotColumn) { + generateDefaultValue(column: DataCubeColumn) { return { type: column.type, value: generateDefaultFilterConditionPrimitiveTypeValue(column.type), diff --git a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__NotEqualCaseInsensitive.tsx b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__NotEqualCaseInsensitive.tsx index a8336759ca..3415121a2b 100644 --- a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__NotEqualCaseInsensitive.tsx +++ b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__NotEqualCaseInsensitive.tsx @@ -19,10 +19,8 @@ import { DataCubeQueryFilterOperation, generateDefaultFilterConditionPrimitiveTypeValue, } from './DataCubeQueryFilterOperation.js'; -import type { - DataCubeQuerySnapshotColumn, - DataCubeQuerySnapshotFilterCondition, -} from '../DataCubeQuerySnapshot.js'; +import type { DataCubeQuerySnapshotFilterCondition } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeColumnDataType, DataCubeFunction, @@ -57,7 +55,7 @@ export class DataCubeQueryFilterOperation__NotEqualCaseInsensitive extends DataC return DataCubeQueryFilterOperator.NOT_EQUAL_CASE_INSENSITIVE; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [DataCubeColumnDataType.TEXT]); } @@ -69,7 +67,7 @@ export class DataCubeQueryFilterOperation__NotEqualCaseInsensitive extends DataC ); } - generateDefaultValue(column: DataCubeQuerySnapshotColumn) { + generateDefaultValue(column: DataCubeColumn) { return { type: column.type, value: generateDefaultFilterConditionPrimitiveTypeValue(column.type), diff --git a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__NotEqualCaseInsensitiveColumn.tsx b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__NotEqualCaseInsensitiveColumn.tsx index e8fe163c21..b7957c46ba 100644 --- a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__NotEqualCaseInsensitiveColumn.tsx +++ b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__NotEqualCaseInsensitiveColumn.tsx @@ -16,10 +16,8 @@ import { type V1_AppliedFunction } from '@finos/legend-graph'; import { DataCubeQueryFilterOperation } from './DataCubeQueryFilterOperation.js'; -import type { - DataCubeQuerySnapshotColumn, - DataCubeQuerySnapshotFilterCondition, -} from '../DataCubeQuerySnapshot.js'; +import type { DataCubeQuerySnapshotFilterCondition } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeColumnDataType, DataCubeFunction, @@ -55,7 +53,7 @@ export class DataCubeQueryFilterOperation__NotEqualCaseInsensitiveColumn extends return DataCubeQueryFilterOperator.NOT_EQUAL_CASE_INSENSITIVE_COLUMN; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [DataCubeColumnDataType.TEXT]); } @@ -67,7 +65,7 @@ export class DataCubeQueryFilterOperation__NotEqualCaseInsensitiveColumn extends ); } - generateDefaultValue(column: DataCubeQuerySnapshotColumn) { + generateDefaultValue(column: DataCubeColumn) { return { type: DataCubeOperationAdvancedValueType.COLUMN, value: column.name, diff --git a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__NotEqualColumn.tsx b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__NotEqualColumn.tsx index c2ea5004ae..a808892cdd 100644 --- a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__NotEqualColumn.tsx +++ b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__NotEqualColumn.tsx @@ -16,10 +16,8 @@ import { type V1_AppliedFunction } from '@finos/legend-graph'; import { DataCubeQueryFilterOperation } from './DataCubeQueryFilterOperation.js'; -import type { - DataCubeQuerySnapshotColumn, - DataCubeQuerySnapshotFilterCondition, -} from '../DataCubeQuerySnapshot.js'; +import type { DataCubeQuerySnapshotFilterCondition } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeColumnDataType, DataCubeFunction, @@ -55,7 +53,7 @@ export class DataCubeQueryFilterOperation__NotEqualColumn extends DataCubeQueryF return DataCubeQueryFilterOperator.NOT_EQUAL_COLUMN; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [ DataCubeColumnDataType.TEXT, DataCubeColumnDataType.NUMBER, @@ -72,7 +70,7 @@ export class DataCubeQueryFilterOperation__NotEqualColumn extends DataCubeQueryF ); } - generateDefaultValue(column: DataCubeQuerySnapshotColumn) { + generateDefaultValue(column: DataCubeColumn) { return { type: DataCubeOperationAdvancedValueType.COLUMN, value: column.name, diff --git a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__NotStartWith.tsx b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__NotStartWith.tsx index 913c3a28d8..20384ab557 100644 --- a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__NotStartWith.tsx +++ b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__NotStartWith.tsx @@ -19,10 +19,8 @@ import { DataCubeQueryFilterOperation, generateDefaultFilterConditionPrimitiveTypeValue, } from './DataCubeQueryFilterOperation.js'; -import type { - DataCubeQuerySnapshotColumn, - DataCubeQuerySnapshotFilterCondition, -} from '../DataCubeQuerySnapshot.js'; +import type { DataCubeQuerySnapshotFilterCondition } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeColumnDataType, DataCubeFunction, @@ -56,7 +54,7 @@ export class DataCubeQueryFilterOperation__NotStartWith extends DataCubeQueryFil return DataCubeQueryFilterOperator.NOT_START_WITH; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [DataCubeColumnDataType.TEXT]); } @@ -68,7 +66,7 @@ export class DataCubeQueryFilterOperation__NotStartWith extends DataCubeQueryFil ); } - generateDefaultValue(column: DataCubeQuerySnapshotColumn) { + generateDefaultValue(column: DataCubeColumn) { return { type: column.type, value: generateDefaultFilterConditionPrimitiveTypeValue(column.type), diff --git a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__StartWith.tsx b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__StartWith.tsx index 8d6a1f1bbe..9c6b6e2ce3 100644 --- a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__StartWith.tsx +++ b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__StartWith.tsx @@ -19,10 +19,8 @@ import { DataCubeQueryFilterOperation, generateDefaultFilterConditionPrimitiveTypeValue, } from './DataCubeQueryFilterOperation.js'; -import type { - DataCubeQuerySnapshotColumn, - DataCubeQuerySnapshotFilterCondition, -} from '../DataCubeQuerySnapshot.js'; +import type { DataCubeQuerySnapshotFilterCondition } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeColumnDataType, DataCubeFunction, @@ -55,7 +53,7 @@ export class DataCubeQueryFilterOperation__StartWith extends DataCubeQueryFilter return DataCubeQueryFilterOperator.START_WITH; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [DataCubeColumnDataType.TEXT]); } @@ -67,7 +65,7 @@ export class DataCubeQueryFilterOperation__StartWith extends DataCubeQueryFilter ); } - generateDefaultValue(column: DataCubeQuerySnapshotColumn) { + generateDefaultValue(column: DataCubeColumn) { return { type: column.type, value: generateDefaultFilterConditionPrimitiveTypeValue(column.type), diff --git a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__StartWithCaseInsensitive.tsx b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__StartWithCaseInsensitive.tsx index e0d28c30b2..381602a48b 100644 --- a/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__StartWithCaseInsensitive.tsx +++ b/packages/legend-data-cube/src/stores/core/filter/DataCubeQueryFilterOperation__StartWithCaseInsensitive.tsx @@ -19,10 +19,8 @@ import { DataCubeQueryFilterOperation, generateDefaultFilterConditionPrimitiveTypeValue, } from './DataCubeQueryFilterOperation.js'; -import type { - DataCubeQuerySnapshotColumn, - DataCubeQuerySnapshotFilterCondition, -} from '../DataCubeQuerySnapshot.js'; +import type { DataCubeQuerySnapshotFilterCondition } from '../DataCubeQuerySnapshot.js'; +import type { DataCubeColumn } from '../models/DataCubeColumn.js'; import { DataCubeColumnDataType, DataCubeFunction, @@ -56,7 +54,7 @@ export class DataCubeQueryFilterOperation__StartWithCaseInsensitive extends Data return DataCubeQueryFilterOperator.START_WITH_CASE_INSENSITIVE; } - isCompatibleWithColumn(column: DataCubeQuerySnapshotColumn) { + isCompatibleWithColumn(column: DataCubeColumn) { return ofDataType(column.type, [DataCubeColumnDataType.TEXT]); } @@ -68,7 +66,7 @@ export class DataCubeQueryFilterOperation__StartWithCaseInsensitive extends Data ); } - generateDefaultValue(column: DataCubeQuerySnapshotColumn) { + generateDefaultValue(column: DataCubeColumn) { return { type: column.type, value: generateDefaultFilterConditionPrimitiveTypeValue(column.type), diff --git a/packages/legend-data-cube/src/stores/core/models/DataCubeColumn.ts b/packages/legend-data-cube/src/stores/core/models/DataCubeColumn.ts new file mode 100644 index 0000000000..0e885252b4 --- /dev/null +++ b/packages/legend-data-cube/src/stores/core/models/DataCubeColumn.ts @@ -0,0 +1,34 @@ +/** + * 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. + */ + +export type DataCubeColumn = { + name: string; + type: string; +}; + +export function _findCol( + cols: T[] | undefined, + name: string, +): T | undefined { + return cols?.find((c) => c.name === name); +} + +export function _toCol(col: { name: string; type: string }): DataCubeColumn { + return { name: col.name, type: col.type }; +} + +export const _sortByColName = (a: { name: string }, b: { name: string }) => + a.name.localeCompare(b.name); diff --git a/packages/legend-data-cube/src/stores/core/DataCubeConfiguration.ts b/packages/legend-data-cube/src/stores/core/models/DataCubeConfiguration.ts similarity index 98% rename from packages/legend-data-cube/src/stores/core/DataCubeConfiguration.ts rename to packages/legend-data-cube/src/stores/core/models/DataCubeConfiguration.ts index d6ef530246..c00c933c7c 100644 --- a/packages/legend-data-cube/src/stores/core/DataCubeConfiguration.ts +++ b/packages/legend-data-cube/src/stores/core/models/DataCubeConfiguration.ts @@ -40,7 +40,8 @@ import { type DataCubeOperationValue, DEFAULT_PIVOT_STATISTIC_COLUMN_NAME, DEFAULT_TREE_COLUMN_SORT_DIRECTION, -} from './DataCubeQueryEngine.js'; + DEFAULT_REPORT_NAME, +} from '../DataCubeQueryEngine.js'; import { SerializationFactory, usingModelSchema } from '@finos/legend-shared'; import { createModelSchema, list, optional, primitive, raw } from 'serializr'; @@ -178,6 +179,7 @@ export class DataCubePivotLayoutConfiguration { } export class DataCubeConfiguration { + name = DEFAULT_REPORT_NAME; description?: string | undefined; columns: DataCubeColumnConfiguration[] = []; @@ -242,6 +244,7 @@ export class DataCubeConfiguration { fontUnderline: optional(primitive()), gridLineColor: primitive(), initialExpandLevel: optional(primitive()), + name: primitive(), negativeBackgroundColor: primitive(), negativeForegroundColor: primitive(), normalBackgroundColor: primitive(), diff --git a/packages/legend-data-cube/src/stores/core/models/DataCubeQuery.ts b/packages/legend-data-cube/src/stores/core/models/DataCubeQuery.ts new file mode 100644 index 0000000000..213181ae04 --- /dev/null +++ b/packages/legend-data-cube/src/stores/core/models/DataCubeQuery.ts @@ -0,0 +1,41 @@ +/** + * 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 { + SerializationFactory, + usingModelSchema, + type PlainObject, +} from '@finos/legend-shared'; +import { createModelSchema, primitive } from 'serializr'; +import { DataCubeConfiguration } from './DataCubeConfiguration.js'; + +export class DataCubeQuery { + query!: string; + configuration?: PlainObject | undefined; + + constructor(configuration?: PlainObject | undefined) { + this.configuration = configuration; + } + + static readonly serialization = new SerializationFactory( + createModelSchema(DataCubeQuery, { + configuration: usingModelSchema( + DataCubeConfiguration.serialization.schema, + ), + query: primitive(), + }), + ); +} diff --git a/packages/legend-data-cube/src/stores/core/models/DataCubeSource.ts b/packages/legend-data-cube/src/stores/core/models/DataCubeSource.ts new file mode 100644 index 0000000000..9a00125ade --- /dev/null +++ b/packages/legend-data-cube/src/stores/core/models/DataCubeSource.ts @@ -0,0 +1,25 @@ +/** + * 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 type { V1_ValueSpecification } from '@finos/legend-graph'; +import type { DataCubeColumn } from './DataCubeColumn.js'; + +export abstract class DataCubeSource { + sourceColumns: DataCubeColumn[] = []; + query!: V1_ValueSpecification; +} + +export class INTERNAL__DataCubeSource extends DataCubeSource {} diff --git a/packages/legend-data-cube/src/stores/view/DataCubeInfoState.ts b/packages/legend-data-cube/src/stores/view/DataCubeInfoState.ts index 431abd8734..a3591a7b08 100644 --- a/packages/legend-data-cube/src/stores/view/DataCubeInfoState.ts +++ b/packages/legend-data-cube/src/stores/view/DataCubeInfoState.ts @@ -18,9 +18,7 @@ import { action, makeObservable, observable } from 'mobx'; import type { DataCubeViewState } from './DataCubeViewState.js'; import { DataCubeQuerySnapshotController } from './DataCubeQuerySnapshotManager.js'; import type { DataCubeQuerySnapshot } from '../core/DataCubeQuerySnapshot.js'; -import type { DataCubeQuery } from '../core/DataCubeQuery.js'; -import { formatDate } from '@finos/legend-shared'; -import { DEFAULT_REPORT_NAME } from '../core/DataCubeQueryEngine.js'; +import { DataCubeConfiguration } from '../core/models/DataCubeConfiguration.js'; /** * Unlike other query editor state, this state does not support making any @@ -28,21 +26,17 @@ import { DEFAULT_REPORT_NAME } from '../core/DataCubeQueryEngine.js'; * from the latest snapshot to help display latest static info about the query. */ export class DataCubeInfoState extends DataCubeQuerySnapshotController { - baseQuery!: DataCubeQuery; - name = DEFAULT_REPORT_NAME; - private editionStartTime?: number | undefined; + name = ''; + // TODO: filter preview text constructor(view: DataCubeViewState) { super(view); - makeObservable(this, { + makeObservable(this, { name: observable, - setName: action, - }); - } - private setName(val: string) { - this.name = val; + applySnapshot: action, + }); } override getSnapshotSubscriberName() { @@ -54,12 +48,16 @@ export class DataCubeInfoState extends DataCubeQuerySnapshotController { previousSnapshot: DataCubeQuerySnapshot | undefined, ) { const data = snapshot.data; - this.setName(data.name); - if (!this.editionStartTime) { - this.editionStartTime = snapshot.timestamp; - } - this.view.application.setWindowTitle( - `\u229E ${data.name}${this.editionStartTime ? ` - ${formatDate(new Date(this.editionStartTime), 'HH:mm:ss EEE MMM dd yyyy')}` : ''}`, + const configuration = DataCubeConfiguration.serialization.fromJson( + data.configuration, ); + + if (configuration.name !== this.name) { + this.name = configuration.name; + // TODO: make sure we only call this for the main view of data cube when we support multi views + this.view.dataCube.onNameChanged?.(this.name, this.view.source); + } + + // TODO: filter preview text } } diff --git a/packages/legend-data-cube/src/stores/view/DataCubeQuerySnapshotManager.ts b/packages/legend-data-cube/src/stores/view/DataCubeQuerySnapshotManager.ts index 39bc2fdc19..cc58206f74 100644 --- a/packages/legend-data-cube/src/stores/view/DataCubeQuerySnapshotManager.ts +++ b/packages/legend-data-cube/src/stores/view/DataCubeQuerySnapshotManager.ts @@ -22,7 +22,7 @@ import { deepDiff, guaranteeNonNullable, } from '@finos/legend-shared'; -import type { DataCubeQuery } from '../core/DataCubeQuery.js'; +import type { DataCubeQuery } from '../core/models/DataCubeQuery.js'; // TODO: set a stack depth when we implement undo/redo // const DATA_CUBE_MAX_SNAPSHOT_COUNT = 100; @@ -64,8 +64,8 @@ export abstract class DataCubeQuerySnapshotController const previousSnapshot = this.latestSnapshot; this.latestSnapshot = snapshot; - if (this.view.engine.enableDebugMode) { - this.view.application.debugProcess( + if (this.view.dataCube.settings.enableDebugMode) { + this.view.engine.debugProcess( `New Snapshot`, ['Publisher', this.getSnapshotSubscriberName()], ['Snapshot', snapshot], @@ -141,7 +141,7 @@ export class DataCubeQuerySnapshotManager { broadcastSnapshot(snapshot: DataCubeQuerySnapshot) { if (!snapshot.isFinalized()) { - this.view.application.logIllegalStateError( + this.view.engine.logIllegalStateError( `Snapshot must be finalized before broadcasting`, ); return; @@ -152,7 +152,7 @@ export class DataCubeQuerySnapshotManager { if (currentSnapshot?.uuid !== snapshot.uuid) { subscriber.receiveSnapshot(snapshot).catch((error: unknown) => { assertErrorThrown(error); - this.view.application.logIllegalStateError( + this.view.engine.logIllegalStateError( `Error occured while subscribers receiving and applying new snapshot should be handled gracefully`, error, ); diff --git a/packages/legend-data-cube/src/stores/view/DataCubeViewState.ts b/packages/legend-data-cube/src/stores/view/DataCubeViewState.ts index 701589746d..465360c9b0 100644 --- a/packages/legend-data-cube/src/stores/view/DataCubeViewState.ts +++ b/packages/legend-data-cube/src/stores/view/DataCubeViewState.ts @@ -16,7 +16,11 @@ import { DataCubeGridState } from './grid/DataCubeGridState.js'; import { DataCubeEditorState } from './editor/DataCubeEditorState.js'; -import { assertErrorThrown, uuid } from '@finos/legend-shared'; +import { + assertErrorThrown, + IllegalStateError, + uuid, +} from '@finos/legend-shared'; import { DataCubeQuerySnapshotManager } from './DataCubeQuerySnapshotManager.js'; import { DataCubeInfoState } from './DataCubeInfoState.js'; import { validateAndBuildQuerySnapshot } from '../core/DataCubeQuerySnapshotBuilder.js'; @@ -24,9 +28,12 @@ import { action, makeObservable, observable } from 'mobx'; import { DataCubeFilterEditorState } from './filter/DataCubeFilterEditorState.js'; import { DataCubeExtendManagerState } from './extend/DataCubeExtendManagerState.js'; import type { DataCubeState } from '../DataCubeState.js'; -import type { DataCubeEngine } from '../core/DataCubeEngine.js'; -import { type DataCubeApplicationEngine } from '../core/DataCubeApplicationEngine.js'; +import type { + DataCubeEngine, + DataCubeInitialInput, +} from '../core/DataCubeEngine.js'; import { AlertType } from '../../components/core/DataCubeAlert.js'; +import type { DataCubeSource } from '../core/models/DataCubeSource.js'; class DataCubeTask { uuid = uuid(); @@ -45,7 +52,6 @@ class DataCubeTask { export class DataCubeViewState { readonly dataCube: DataCubeState; - readonly application: DataCubeApplicationEngine; readonly engine: DataCubeEngine; readonly snapshotManager: DataCubeQuerySnapshotManager; @@ -58,6 +64,8 @@ export class DataCubeViewState { readonly runningTasks = new Map(); + private _source?: DataCubeSource | undefined; + constructor(dataCube: DataCubeState) { makeObservable(this, { runningTasks: observable, @@ -66,7 +74,7 @@ export class DataCubeViewState { }); this.dataCube = dataCube; - this.application = dataCube.application; + this.engine = dataCube.engine; this.engine = dataCube.engine; // NOTE: snapshot manager must be instantiated before subscribers @@ -79,6 +87,13 @@ export class DataCubeViewState { this.extend = new DataCubeExtendManagerState(this); } + get source(): DataCubeSource { + if (!this._source) { + throw new IllegalStateError('Source is not initialized'); + } + return this._source; + } + newTask(name: string) { const task = new DataCubeTask(name); this.runningTasks.set(task.uuid, task); @@ -91,7 +106,7 @@ export class DataCubeViewState { return task; } - async initialize() { + async initialize(initialInput?: DataCubeInitialInput | undefined) { const task = this.newTask('Initializing'); try { await Promise.all( @@ -106,19 +121,31 @@ export class DataCubeViewState { this.snapshotManager.registerSubscriber(state); }), ); - const result = await this.engine.getBaseQuery(); + const input = initialInput ?? (await this.engine.getInitialInput()); + if (!input) { + this.dataCube.alertAction({ + message: `Initialization Failure: No initial input provided`, + prompt: `Make sure to either specify the initial input when setting up DataCube or the initial input getter in engine.`, + type: AlertType.ERROR, + actions: [], + }); + return; + } + this._source = input.source; + const partialQuery = await this.engine.parseValueSpecification( + input.query.query, + ); const initialSnapshot = validateAndBuildQuerySnapshot( - result.partialQuery, - result.sourceQuery, - result.query, + partialQuery, + this.source, + input.query, ); - initialSnapshot.INTERNAL__setTimestamp(result.timestamp); this.snapshotManager.broadcastSnapshot(initialSnapshot); } catch (error: unknown) { assertErrorThrown(error); - this.application.alertAction({ + this.dataCube.alertAction({ message: `Initialization Failure: ${error.message}`, - prompt: `Resolve the issue and reload the application.`, + prompt: `Resolve the issue and reload the engine.`, type: AlertType.ERROR, actions: [], }); diff --git a/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorColumnPropertiesPanelState.ts b/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorColumnPropertiesPanelState.ts index 255c09dbad..c56f9270f4 100644 --- a/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorColumnPropertiesPanelState.ts +++ b/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorColumnPropertiesPanelState.ts @@ -25,7 +25,7 @@ import { guaranteeNonNullable, type PlainObject, } from '@finos/legend-shared'; -import type { DataCubeConfiguration } from '../../core/DataCubeConfiguration.js'; +import type { DataCubeConfiguration } from '../../core/models/DataCubeConfiguration.js'; export class DataCubeEditorColumnPropertiesPanelState implements DataCubeQueryEditorPanelState diff --git a/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorColumnSelectorState.ts b/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorColumnSelectorState.ts index 08911e4da9..1781b1c5c4 100644 --- a/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorColumnSelectorState.ts +++ b/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorColumnSelectorState.ts @@ -18,7 +18,7 @@ import { makeObservable, observable, action, computed } from 'mobx'; import type { DataCubeViewState } from '../DataCubeViewState.js'; import type { DataCubeEditorState } from './DataCubeEditorState.js'; import { guaranteeNonNullable } from '@finos/legend-shared'; -import { _sortByColName } from '../../core/DataCubeQuerySnapshot.js'; +import { _sortByColName } from '../../core/models/DataCubeColumn.js'; export class DataCubeEditorColumnSelectorColumnState { readonly name: string; diff --git a/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorColumnsPanelState.ts b/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorColumnsPanelState.ts index 572562ca02..1dcf80661e 100644 --- a/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorColumnsPanelState.ts +++ b/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorColumnsPanelState.ts @@ -16,17 +16,15 @@ import { action, makeObservable, observable, override } from 'mobx'; import type { DataCubeViewState } from '../DataCubeViewState.js'; -import { - _toCol, - type DataCubeQuerySnapshot, -} from '../../core/DataCubeQuerySnapshot.js'; +import { type DataCubeQuerySnapshot } from '../../core/DataCubeQuerySnapshot.js'; +import { _toCol } from '../../core/models/DataCubeColumn.js'; import type { DataCubeQueryEditorPanelState } from './DataCubeEditorPanelState.js'; import { DataCubeEditorColumnSelectorColumnState, DataCubeEditorColumnSelectorState, } from './DataCubeEditorColumnSelectorState.js'; import type { DataCubeEditorState } from './DataCubeEditorState.js'; -import { type DataCubeConfiguration } from '../../core/DataCubeConfiguration.js'; +import { type DataCubeConfiguration } from '../../core/models/DataCubeConfiguration.js'; export class DataCubeEditorBasicColumnSelectorState extends DataCubeEditorColumnSelectorState { showHiddenColumns = false; diff --git a/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorGeneralPropertiesPanelState.ts b/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorGeneralPropertiesPanelState.ts index 4b6ab8773c..58bad9cc46 100644 --- a/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorGeneralPropertiesPanelState.ts +++ b/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorGeneralPropertiesPanelState.ts @@ -20,7 +20,7 @@ import { type DataCubeQuerySnapshot } from '../../core/DataCubeQuerySnapshot.js' import type { DataCubeQueryEditorPanelState } from './DataCubeEditorPanelState.js'; import type { DataCubeEditorState } from './DataCubeEditorState.js'; import { DataCubeEditorMutableConfiguration } from './DataCubeEditorMutableConfiguration.js'; -import type { DataCubeConfiguration } from '../../core/DataCubeConfiguration.js'; +import type { DataCubeConfiguration } from '../../core/models/DataCubeConfiguration.js'; export class DataCubeEditorGeneralPropertiesPanelState implements DataCubeQueryEditorPanelState @@ -28,7 +28,6 @@ export class DataCubeEditorGeneralPropertiesPanelState readonly view!: DataCubeViewState; readonly editor!: DataCubeEditorState; - name = ''; limit = -1; configuration = new DataCubeEditorMutableConfiguration(); @@ -36,9 +35,6 @@ export class DataCubeEditorGeneralPropertiesPanelState makeObservable(this, { configuration: observable, - name: observable, - setName: action, - limit: observable, setLimit: action, @@ -49,10 +45,6 @@ export class DataCubeEditorGeneralPropertiesPanelState this.view = editor.view; } - setName(val: string) { - this.name = val; - } - setLimit(val: number) { this.limit = val; } @@ -61,7 +53,6 @@ export class DataCubeEditorGeneralPropertiesPanelState snapshot: DataCubeQuerySnapshot, configuration: DataCubeConfiguration, ) { - this.setName(snapshot.data.name); this.setLimit( snapshot.data.limit !== undefined && snapshot.data.limit >= 0 ? snapshot.data.limit @@ -77,7 +68,6 @@ export class DataCubeEditorGeneralPropertiesPanelState baseSnapshot: DataCubeQuerySnapshot, ) { const data = newSnapshot.data; - data.name = this.name; data.limit = this.limit < 0 ? undefined : this.limit; data.configuration = this.configuration.serialize(); } diff --git a/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorHorizontalPivotsPanelState.ts b/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorHorizontalPivotsPanelState.ts index c9ce4eef6c..5c36f7bb1e 100644 --- a/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorHorizontalPivotsPanelState.ts +++ b/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorHorizontalPivotsPanelState.ts @@ -16,16 +16,16 @@ import { action, computed, makeObservable, observable } from 'mobx'; import type { DataCubeViewState } from '../DataCubeViewState.js'; -import type { DataCubeConfiguration } from '../../core/DataCubeConfiguration.js'; +import type { DataCubeConfiguration } from '../../core/models/DataCubeConfiguration.js'; import { DataCubeColumnKind, isPivotResultColumnName, } from '../../core/DataCubeQueryEngine.js'; +import { type DataCubeQuerySnapshot } from '../../core/DataCubeQuerySnapshot.js'; import { _toCol, - type DataCubeQuerySnapshot, - type DataCubeQuerySnapshotColumn, -} from '../../core/DataCubeQuerySnapshot.js'; + type DataCubeColumn, +} from '../../core/models/DataCubeColumn.js'; import { DataCubeEditorColumnSelectorColumnState, DataCubeEditorColumnSelectorState, @@ -68,7 +68,7 @@ export class DataCubeEditorHorizontalPivotsPanelState readonly editor!: DataCubeEditorState; readonly selector!: DataCubeEditorHorizontalPivotColumnSelectorState; - castColumns: DataCubeQuerySnapshotColumn[] = []; + castColumns: DataCubeColumn[] = []; constructor(editor: DataCubeEditorState) { makeObservable(this, { @@ -86,13 +86,13 @@ export class DataCubeEditorHorizontalPivotsPanelState ); } - get pivotResultColumns(): DataCubeQuerySnapshotColumn[] { + get pivotResultColumns(): DataCubeColumn[] { return this.castColumns .filter((col) => isPivotResultColumnName(col.name)) .map(_toCol); } - setCastColumns(value: DataCubeQuerySnapshotColumn[]) { + setCastColumns(value: DataCubeColumn[]) { this.castColumns = value; } diff --git a/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorMutableConfiguration.ts b/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorMutableConfiguration.ts index 86608fa2b3..e937ab148c 100644 --- a/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorMutableConfiguration.ts +++ b/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorMutableConfiguration.ts @@ -45,7 +45,7 @@ import { DataCubeColumnConfiguration, DataCubeConfiguration, DataCubePivotLayoutConfiguration, -} from '../../core/DataCubeConfiguration.js'; +} from '../../core/models/DataCubeConfiguration.js'; import { buildDefaultColumnConfiguration } from '../../core/DataCubeConfigurationBuilder.js'; import { type DataCubeQuerySnapshot } from '../../core/DataCubeQuerySnapshot.js'; import { @@ -428,6 +428,9 @@ export class DataCubeEditorMutableConfiguration extends DataCubeConfiguration { configuration.columns = []; makeObservable(configuration, { + name: observable, + setName: action, + description: observable, setDescription: action, @@ -569,6 +572,10 @@ export class DataCubeEditorMutableConfiguration extends DataCubeConfiguration { this.errorBackgroundColor = DEFAULT_BACKGROUND_COLOR; } + setName(value: string) { + this.name = value; + } + setDescription(value: string | undefined) { this.description = value; } diff --git a/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorPanelState.ts b/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorPanelState.ts index bd8db24628..d9b16eb714 100644 --- a/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorPanelState.ts +++ b/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorPanelState.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import type { DataCubeConfiguration } from '../../core/DataCubeConfiguration.js'; +import type { DataCubeConfiguration } from '../../core/models/DataCubeConfiguration.js'; import type { DataCubeQuerySnapshot } from '../../core/DataCubeQuerySnapshot.js'; export interface DataCubeQueryEditorPanelState { diff --git a/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorPivotLayoutPanelState.ts b/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorPivotLayoutPanelState.ts index cb9a25ded7..be2b64524e 100644 --- a/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorPivotLayoutPanelState.ts +++ b/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorPivotLayoutPanelState.ts @@ -20,7 +20,7 @@ import { type DataCubeQuerySnapshot } from '../../core/DataCubeQuerySnapshot.js' import type { DataCubeQueryEditorPanelState } from './DataCubeEditorPanelState.js'; import type { DataCubeEditorState } from './DataCubeEditorState.js'; import { DataCubeEditorMutablePivotLayoutConfiguration } from './DataCubeEditorMutableConfiguration.js'; -import type { DataCubeConfiguration } from '../../core/DataCubeConfiguration.js'; +import type { DataCubeConfiguration } from '../../core/models/DataCubeConfiguration.js'; import type { PlainObject } from '@finos/legend-shared'; import { _pruneExpandedPaths } from '../../core/DataCubeQuerySnapshotBuilderUtils.js'; diff --git a/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorSortsPanelState.ts b/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorSortsPanelState.ts index e8a4a2ef29..2e9233c259 100644 --- a/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorSortsPanelState.ts +++ b/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorSortsPanelState.ts @@ -16,10 +16,8 @@ import { action, makeObservable, observable } from 'mobx'; import type { DataCubeViewState } from '../DataCubeViewState.js'; -import { - _toCol, - type DataCubeQuerySnapshot, -} from '../../core/DataCubeQuerySnapshot.js'; +import { type DataCubeQuerySnapshot } from '../../core/DataCubeQuerySnapshot.js'; +import { _toCol } from '../../core/models/DataCubeColumn.js'; import { DataCubeColumnKind, DataCubeQuerySortDirection, @@ -30,7 +28,7 @@ import { DataCubeEditorColumnSelectorState, } from './DataCubeEditorColumnSelectorState.js'; import type { DataCubeEditorState } from './DataCubeEditorState.js'; -import type { DataCubeConfiguration } from '../../core/DataCubeConfiguration.js'; +import type { DataCubeConfiguration } from '../../core/models/DataCubeConfiguration.js'; import { uniqBy } from '@finos/legend-shared'; export class DataCubeEditorSortColumnState extends DataCubeEditorColumnSelectorColumnState { diff --git a/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorState.tsx b/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorState.tsx index 86c7d45164..c1c6c38a6c 100644 --- a/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorState.tsx +++ b/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorState.tsx @@ -19,11 +19,13 @@ import type { DataCubeViewState } from '../DataCubeViewState.js'; import { DataCubeEditorSortsPanelState } from './DataCubeEditorSortsPanelState.js'; import { DataCubeQuerySnapshotController } from '../DataCubeQuerySnapshotManager.js'; import { - _toCol, type DataCubeQuerySnapshot, - type DataCubeQuerySnapshotColumn, type DataCubeQuerySnapshotExtendedColumn, } from '../../core/DataCubeQuerySnapshot.js'; +import { + _toCol, + type DataCubeColumn, +} from '../../core/models/DataCubeColumn.js'; import { ActionState, assertErrorThrown, @@ -34,14 +36,14 @@ import { import { DataCubeEditorGeneralPropertiesPanelState } from './DataCubeEditorGeneralPropertiesPanelState.js'; import { DataCubeEditorColumnPropertiesPanelState } from './DataCubeEditorColumnPropertiesPanelState.js'; import { DataCubeEditorColumnsPanelState } from './DataCubeEditorColumnsPanelState.js'; -import { DataCubeConfiguration } from '../../core/DataCubeConfiguration.js'; +import { DataCubeConfiguration } from '../../core/models/DataCubeConfiguration.js'; import { DataCubeEditorVerticalPivotsPanelState } from './DataCubeEditorVerticalPivotsPanelState.js'; import type { DisplayState } from '../../core/DataCubeLayoutManagerState.js'; import { DataCubeEditor } from '../../../components/view/editor/DataCubeEditor.js'; import { DataCubeEditorHorizontalPivotsPanelState } from './DataCubeEditorHorizontalPivotsPanelState.js'; import { DataCubeEditorPivotLayoutPanelState } from './DataCubeEditorPivotLayoutPanelState.js'; import type { DataCubeQueryBuilderError } from '../../core/DataCubeEngine.js'; -import { V1_deserializeValueSpecification } from '@finos/legend-graph'; +import { _lambda } from '../../core/DataCubeQueryBuilderUtils.js'; export enum DataCubeEditorTab { GENERAL_PROPERTIES = 'General Properties', @@ -54,7 +56,7 @@ export enum DataCubeEditorTab { /** * This query editor state backs the main form editor of data cube. It supports - * batching changes before application, i.e. allowing user to make multiple edits before + * batching changes before engine, i.e. allowing user to make multiple edits before * applying and propgating them. * * NOTE: It allows almost FULL 1-1 control over the data cube query state. @@ -76,7 +78,7 @@ export class DataCubeEditorState extends DataCubeQuerySnapshotController { currentTab = DataCubeEditorTab.GENERAL_PROPERTIES; - sourceColumns: DataCubeQuerySnapshotColumn[] = []; + sourceColumns: DataCubeColumn[] = []; leafExtendColumns: DataCubeQuerySnapshotExtendedColumn[] = []; groupExtendColumns: DataCubeQuerySnapshotExtendedColumn[] = []; @@ -95,7 +97,7 @@ export class DataCubeEditorState extends DataCubeQuerySnapshotController { applyChanges: action, }); - this.display = this.view.application.layout.newDisplay('Properties', () => ( + this.display = this.view.engine.layout.newDisplay('Properties', () => ( )); this.generalProperties = new DataCubeEditorGeneralPropertiesPanelState( @@ -189,7 +191,8 @@ export class DataCubeEditorState extends DataCubeQuerySnapshotController { try { await this.view.engine.getQueryCodeRelationReturnType( codePrefix + code, - V1_deserializeValueSpecification(tempSnapshot.data.sourceQuery, []), + _lambda([], [this.view.source.query]), + this.view.source, ); } catch (error) { assertErrorThrown(error); @@ -197,7 +200,7 @@ export class DataCubeEditorState extends DataCubeQuerySnapshotController { error instanceof NetworkClientError && error.response.status === HttpStatus.BAD_REQUEST ) { - this.view.application.alertCodeCheckError( + this.view.engine.alertCodeCheckError( error.payload as DataCubeQueryBuilderError, code, codePrefix, @@ -207,7 +210,7 @@ export class DataCubeEditorState extends DataCubeQuerySnapshotController { }, ); } else { - this.view.application.alertError(error, { + this.view.engine.alertError(error, { message: `Query Validation Failure: Can't safely apply changes.`, text: `Error: ${error.message}`, }); diff --git a/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorVerticalPivotsPanelState.ts b/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorVerticalPivotsPanelState.ts index 9d1ba1d635..b4d1ee8ede 100644 --- a/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorVerticalPivotsPanelState.ts +++ b/packages/legend-data-cube/src/stores/view/editor/DataCubeEditorVerticalPivotsPanelState.ts @@ -16,12 +16,10 @@ import { uniqBy } from '@finos/legend-shared'; import type { DataCubeViewState } from '../DataCubeViewState.js'; -import type { DataCubeConfiguration } from '../../core/DataCubeConfiguration.js'; +import type { DataCubeConfiguration } from '../../core/models/DataCubeConfiguration.js'; import { DataCubeColumnKind } from '../../core/DataCubeQueryEngine.js'; -import { - _toCol, - type DataCubeQuerySnapshot, -} from '../../core/DataCubeQuerySnapshot.js'; +import { type DataCubeQuerySnapshot } from '../../core/DataCubeQuerySnapshot.js'; +import { _toCol } from '../../core/models/DataCubeColumn.js'; import { DataCubeEditorColumnSelectorColumnState, DataCubeEditorColumnSelectorState, diff --git a/packages/legend-data-cube/src/stores/view/extend/DataCubeColumnEditorState.tsx b/packages/legend-data-cube/src/stores/view/extend/DataCubeColumnEditorState.tsx index 3c4c036c8d..7c06cb23f0 100644 --- a/packages/legend-data-cube/src/stores/view/extend/DataCubeColumnEditorState.tsx +++ b/packages/legend-data-cube/src/stores/view/extend/DataCubeColumnEditorState.tsx @@ -49,8 +49,9 @@ import { V1_serializeValueSpecification, type V1_ValueSpecification, } from '@finos/legend-graph'; -import type { DataCubeColumnConfiguration } from '../../core/DataCubeConfiguration.js'; +import type { DataCubeColumnConfiguration } from '../../core/models/DataCubeConfiguration.js'; import type { DataCubeQuerySnapshotExtendedColumn } from '../../core/DataCubeQuerySnapshot.js'; +import { _lambda } from '../../core/DataCubeQueryBuilderUtils.js'; export abstract class DataCubeColumnBaseEditorState { readonly uuid = uuid(); @@ -215,15 +216,21 @@ export abstract class DataCubeColumnBaseEditorState { snapshot.data.groupExtendedColumns = []; snapshot.data.sortColumns = []; snapshot.data.limit = undefined; - return buildExecutableQuery( - snapshot, - this.manager.view.engine.filterOperations, - this.manager.view.engine.aggregateOperations, + return _lambda( + [], + [ + buildExecutableQuery( + snapshot, + this.manager.view.source, + () => undefined, + this.manager.view.engine.filterOperations, + this.manager.view.engine.aggregateOperations, + ), + ], ); } async getReturnType() { - const baseQuery = this.buildExtendBaseQuery(); this.validationState.inProgress(); // properly reset the error state before revalidating @@ -234,7 +241,8 @@ export abstract class DataCubeColumnBaseEditorState { const returnRelationType = await this.view.engine.getQueryCodeRelationReturnType( this.codePrefix + this.code + this.codeSuffix, - baseQuery, + this.buildExtendBaseQuery(), + this.view.source, ); let returnType = returnRelationType.columns.find( (col) => col.name === this._name, @@ -281,7 +289,7 @@ export abstract class DataCubeColumnBaseEditorState { this.showError(err.payload as DataCubeQueryBuilderError); return undefined; } - this.view.application.alertError(err, { + this.view.engine.alertError(err, { message: `Expression Validation Failure: ${err.message}`, }); } finally { @@ -329,7 +337,7 @@ export class DataCubeNewColumnState extends DataCubeColumnBaseEditorState { } override newDisplay(state: DataCubeColumnBaseEditorState): DisplayState { - return this.view.application.layout.newDisplay( + return this.view.engine.layout.newDisplay( 'Add New Column', () => , { @@ -359,12 +367,12 @@ export class DataCubeNewColumnState extends DataCubeColumnBaseEditorState { let returnType: string | undefined; try { [query, returnType] = await Promise.all([ - this.view.engine.parseQuery(this.code, false), + this.view.engine.parseValueSpecification(this.code, false), this.getReturnType(), // recompile to get the return type ]); } catch (error) { assertErrorThrown(error); - this.view.application.alertError(error, { + this.view.engine.alertError(error, { message: `Expression Validation Failure: ${error.message}`, }); return; @@ -373,14 +381,14 @@ export class DataCubeNewColumnState extends DataCubeColumnBaseEditorState { } if (!(query instanceof V1_Lambda)) { - this.view.application.alertError(new Error(), { + this.view.engine.alertError(new Error(), { message: `Expression Validation Failure: Expression must be a lambda.`, }); return; } if (!returnType) { - this.view.application.alertError(new Error(), { + this.view.engine.alertError(new Error(), { message: `Expression Validation Failure: Can't compute expression return type.`, }); return; @@ -439,14 +447,14 @@ export class DataCubeExistingColumnEditorState extends DataCubeColumnBaseEditorS } override async getInitialCode(): Promise { - return this.view.engine.getQueryCode( + return this.view.engine.getValueSpecificationCode( V1_deserializeValueSpecification(this.initialData.mapFn, []), true, ); } override newDisplay(state: DataCubeColumnBaseEditorState): DisplayState { - return this.view.application.layout.newDisplay( + return this.view.engine.layout.newDisplay( 'Edit Column', () => , { @@ -484,12 +492,12 @@ export class DataCubeExistingColumnEditorState extends DataCubeColumnBaseEditorS let returnType: string | undefined; try { [query, returnType] = await Promise.all([ - this.view.engine.parseQuery(this.code, false), + this.view.engine.parseValueSpecification(this.code, false), this.getReturnType(), // recompile to get the return type ]); } catch (error) { assertErrorThrown(error); - this.view.application.alertError(error, { + this.view.engine.alertError(error, { message: `Expression Validation Failure: ${error.message}`, }); return; @@ -498,14 +506,14 @@ export class DataCubeExistingColumnEditorState extends DataCubeColumnBaseEditorS } if (!(query instanceof V1_Lambda)) { - this.view.application.alertError(new Error(), { + this.view.engine.alertError(new Error(), { message: `Expression Validation Failure: Expression must be a lambda.`, }); return; } if (!returnType) { - this.view.application.alertError(new Error(), { + this.view.engine.alertError(new Error(), { message: `Expression Validation Failure: Can't compute expression return type.`, }); return; diff --git a/packages/legend-data-cube/src/stores/view/extend/DataCubeExtendManagerState.tsx b/packages/legend-data-cube/src/stores/view/extend/DataCubeExtendManagerState.tsx index a5a1e3ceea..f495e63787 100644 --- a/packages/legend-data-cube/src/stores/view/extend/DataCubeExtendManagerState.tsx +++ b/packages/legend-data-cube/src/stores/view/extend/DataCubeExtendManagerState.tsx @@ -16,11 +16,13 @@ import { action, computed, makeObservable, observable } from 'mobx'; import { - _toCol, type DataCubeQuerySnapshot, - type DataCubeQuerySnapshotColumn, type DataCubeQuerySnapshotExtendedColumn, } from '../../core/DataCubeQuerySnapshot.js'; +import { + _toCol, + type DataCubeColumn, +} from '../../core/models/DataCubeColumn.js'; import { assertErrorThrown, deleteEntry, @@ -35,7 +37,7 @@ import { DataCubeQuerySnapshotController } from '../DataCubeQuerySnapshotManager import { DataCubeConfiguration, type DataCubeColumnConfiguration, -} from '../../core/DataCubeConfiguration.js'; +} from '../../core/models/DataCubeConfiguration.js'; import { DataCubeExistingColumnEditorState, DataCubeNewColumnState, @@ -46,8 +48,8 @@ import { getDataType, } from '../../core/DataCubeQueryEngine.js'; import { buildDefaultColumnConfiguration } from '../../core/DataCubeConfigurationBuilder.js'; -import { V1_deserializeValueSpecification } from '@finos/legend-graph'; import type { DataCubeQueryBuilderError } from '../../core/DataCubeEngine.js'; +import { _lambda } from '../../core/DataCubeQueryBuilderUtils.js'; class DataCubeQueryExtendedColumnState { name: string; @@ -71,9 +73,9 @@ class DataCubeQueryExtendedColumnState { */ export class DataCubeExtendManagerState extends DataCubeQuerySnapshotController { columnConfigurations: DataCubeColumnConfiguration[] = []; - selectColumns: DataCubeQuerySnapshotColumn[] = []; - sourceColumns: DataCubeQuerySnapshotColumn[] = []; - horizontalPivotCastColumns: DataCubeQuerySnapshotColumn[] = []; + selectColumns: DataCubeColumn[] = []; + sourceColumns: DataCubeColumn[] = []; + horizontalPivotCastColumns: DataCubeColumn[] = []; leafExtendedColumns: DataCubeQueryExtendedColumnState[] = []; groupExtendedColumns: DataCubeQueryExtendedColumnState[] = []; @@ -250,7 +252,8 @@ export class DataCubeExtendManagerState extends DataCubeQuerySnapshotController try { await this.view.engine.getQueryCodeRelationReturnType( codePrefix + code, - V1_deserializeValueSpecification(tempSnapshot.data.sourceQuery, []), + _lambda([], [this.view.source.query]), + this.view.source, ); } catch (error) { assertErrorThrown(error); @@ -258,7 +261,7 @@ export class DataCubeExtendManagerState extends DataCubeQuerySnapshotController error instanceof NetworkClientError && error.response.status === HttpStatus.BAD_REQUEST ) { - this.view.application.alertCodeCheckError( + this.view.engine.alertCodeCheckError( error.payload as DataCubeQueryBuilderError, code, codePrefix, @@ -268,7 +271,7 @@ export class DataCubeExtendManagerState extends DataCubeQuerySnapshotController }, ); } else { - this.view.application.alertError(error, { + this.view.engine.alertError(error, { message: `Column Update Check Failure: Can't safely update column '${columnName}'.`, text: `Error: ${error.message}`, }); @@ -362,7 +365,8 @@ export class DataCubeExtendManagerState extends DataCubeQuerySnapshotController try { await this.view.engine.getQueryCodeRelationReturnType( codePrefix + code, - V1_deserializeValueSpecification(tempSnapshot.data.sourceQuery, []), + _lambda([], [this.view.source.query]), + this.view.source, ); } catch (error) { assertErrorThrown(error); @@ -370,7 +374,7 @@ export class DataCubeExtendManagerState extends DataCubeQuerySnapshotController error instanceof NetworkClientError && error.response.status === HttpStatus.BAD_REQUEST ) { - this.view.application.alertCodeCheckError( + this.view.engine.alertCodeCheckError( error.payload as DataCubeQueryBuilderError, code, codePrefix, @@ -380,7 +384,7 @@ export class DataCubeExtendManagerState extends DataCubeQuerySnapshotController }, ); } else { - this.view.application.alertError(error, { + this.view.engine.alertError(error, { message: `Column Delete Check Failure: Can't safely delete column '${columnName}'.`, text: `Error: ${error.message}`, }); diff --git a/packages/legend-data-cube/src/stores/view/filter/DataCubeFilterEditorState.tsx b/packages/legend-data-cube/src/stores/view/filter/DataCubeFilterEditorState.tsx index 844554f250..c52f180aae 100644 --- a/packages/legend-data-cube/src/stores/view/filter/DataCubeFilterEditorState.tsx +++ b/packages/legend-data-cube/src/stores/view/filter/DataCubeFilterEditorState.tsx @@ -38,7 +38,7 @@ import { DataCubeQuerySnapshotController } from '../DataCubeQuerySnapshotManager import { DataCubeConfiguration, type DataCubeColumnConfiguration, -} from '../../core/DataCubeConfiguration.js'; +} from '../../core/models/DataCubeConfiguration.js'; import type { DisplayState } from '../../core/DataCubeLayoutManagerState.js'; import { DataCubeFilterEditor } from '../../../components/view/filter/DataCubeFilterEditor.js'; @@ -73,7 +73,7 @@ export class DataCubeFilterEditorState extends DataCubeQuerySnapshotController { layerFilterNode: action, }); - this.display = this.view.application.layout.newDisplay( + this.display = this.view.engine.layout.newDisplay( 'Filter', () => , { diff --git a/packages/legend-data-cube/src/stores/view/grid/DataCubeGridClientEngine.ts b/packages/legend-data-cube/src/stores/view/grid/DataCubeGridClientEngine.ts index 41df42e85a..100a08b45d 100644 --- a/packages/legend-data-cube/src/stores/view/grid/DataCubeGridClientEngine.ts +++ b/packages/legend-data-cube/src/stores/view/grid/DataCubeGridClientEngine.ts @@ -31,33 +31,24 @@ import { pruneObject, } from '@finos/legend-shared'; import { buildExecutableQuery } from '../../core/DataCubeQueryBuilder.js'; -import { - type TabularDataSet, - type V1_AppliedFunction, - V1_Lambda, -} from '@finos/legend-graph'; +import { type TabularDataSet, V1_Lambda } from '@finos/legend-graph'; import { generateRowGroupingDrilldownExecutableQueryPostProcessor } from './DataCubeGridQueryBuilder.js'; import { makeObservable, observable, runInAction } from 'mobx'; import type { DataCubeConfiguration, DataCubeConfigurationColorKey, -} from '../../core/DataCubeConfiguration.js'; +} from '../../core/models/DataCubeConfiguration.js'; import { DEFAULT_LARGE_ALERT_WINDOW_CONFIG } from '../../core/DataCubeLayoutManagerState.js'; -import { - _sortByColName, - type DataCubeQuerySnapshot, - type DataCubeQuerySnapshotData, -} from '../../core/DataCubeQuerySnapshot.js'; -import type { DataCubeEngine } from '../../core/DataCubeEngine.js'; +import { type DataCubeQuerySnapshot } from '../../core/DataCubeQuerySnapshot.js'; +import { _sortByColName } from '../../core/models/DataCubeColumn.js'; import { isPivotResultColumnName, type DataCubeQueryFunctionMap, } from '../../core/DataCubeQueryEngine.js'; -import type { DataCubeQueryFilterOperation } from '../../core/filter/DataCubeQueryFilterOperation.js'; -import type { DataCubeQueryAggregateOperation } from '../../core/aggregation/DataCubeQueryAggregateOperation.js'; import { buildQuerySnapshot } from './DataCubeGridQuerySnapshotBuilder.js'; import { AlertType } from '../../../components/core/DataCubeAlert.js'; import { sum } from 'mathjs'; +import type { DataCubeViewState } from '../DataCubeViewState.js'; type GridClientCellValue = string | number | boolean | null | undefined; type GridClientRowData = { @@ -125,7 +116,7 @@ export const generateBackgroundColorUtilityClassName = ( export const INTERNAL__GRID_CLIENT_DEFAULT_CACHE_BLOCK_SIZE = 500; export const INTERNAL__GRID_CLIENT_DEFAULT_ENABLE_PAGINATION = true; // NOTE: The cache block size is used by ag-grid to pre-allocate memory for the grid -// so the value set must be reasonable, or else it can crash the application! +// so the value set must be reasonable, or else it can crash the engine! export const INTERNAL__GRID_CLIENT_MAX_CACHE_BLOCK_SIZE = 1e4; export const INTERNAL__GRID_CLIENT_PIVOT_COLUMN_GROUP_COLOR_ROTATION_SIZE = 5; @@ -186,8 +177,6 @@ export function computeHashCodeForDataFetchManualTrigger( ) { return hashObject( pruneObject({ - ...snapshot.data, - name: '', // name change should not trigger data fetching configuration: { showRootAggregation: configuration.showRootAggregation, pivotStatisticColumnPlacement: @@ -208,11 +197,12 @@ export function computeHashCodeForDataFetchManualTrigger( })) .sort(_sortByColName), // sort to make sure column reordering does not trigger data fetching }, + leafExtendedColumns: snapshot.data.leafExtendedColumns, + filter: snapshot.data.filter, selectColumns: snapshot.data.selectColumns.slice().sort(_sortByColName), // sort to make sure column reordering does not trigger data fetching - pivot: undefined, - groupBy: undefined, - sortColumns: [], - } satisfies DataCubeQuerySnapshotData), + groupExtendedColumns: snapshot.data.groupExtendedColumns, + limit: snapshot.data.limit, + }), ); } @@ -253,7 +243,7 @@ function buildRowData( async function getCastColumns( currentSnapshot: DataCubeQuerySnapshot, - engine: DataCubeEngine, + view: DataCubeViewState, ) { if (!currentSnapshot.data.pivot) { throw new IllegalStateError( @@ -267,16 +257,18 @@ async function getCastColumns( snapshot.data.limit = 0; const query = buildExecutableQuery( snapshot, - engine.filterOperations, - engine.aggregateOperations, + view.source, + (source) => view.engine.buildExecutionContext(source), + view.engine.filterOperations, + view.engine.aggregateOperations, { postProcessor: ( - _snapshot: DataCubeQuerySnapshot, - sequence: V1_AppliedFunction[], - funcMap: DataCubeQueryFunctionMap, - configuration: DataCubeConfiguration, - filterOperations: DataCubeQueryFilterOperation[], - aggregateOperations: DataCubeQueryAggregateOperation[], + _snapshot, + sequence, + funcMap, + configuration, + filterOperations, + aggregateOperations, ) => { const _unprocess = (funcMapKey: keyof DataCubeQueryFunctionMap) => { const func = funcMap[funcMapKey]; @@ -295,7 +287,11 @@ async function getCastColumns( const lambda = new V1_Lambda(); lambda.body.push(query); - const result = await engine.executeQuery(lambda); + const result = await view.engine.executeQuery( + lambda, + view.source, + view.dataCube, + ); return result.result.builder.columns.map((column) => ({ name: column.name, @@ -357,7 +353,7 @@ export class DataCubeGridClientServerSideDataSource try { const castColumns = await getCastColumns( newSnapshot, - this.grid.view.engine, + this.grid.view, ); newSnapshot.data.pivot.castColumns = castColumns; newSnapshot.data.sortColumns = newSnapshot.data.sortColumns.filter( @@ -368,7 +364,7 @@ export class DataCubeGridClientServerSideDataSource ); } catch (error) { assertErrorThrown(error); - this.grid.view.application.alertError(error, { + this.grid.view.engine.alertError(error, { message: `Query Validation Failure: Can't retrieve pivot results column metadata. ${error.message}`, }); // fail early since we can't proceed without the cast columns validated @@ -396,6 +392,8 @@ export class DataCubeGridClientServerSideDataSource try { const executableQuery = buildExecutableQuery( newSnapshot, + this.grid.view.source, + (source) => this.grid.view.engine.buildExecutionContext(source), this.grid.view.engine.filterOperations, this.grid.view.engine.aggregateOperations, { @@ -416,10 +414,14 @@ export class DataCubeGridClientServerSideDataSource ); const lambda = new V1_Lambda(); lambda.body.push(executableQuery); - const result = await this.grid.view.engine.executeQuery(lambda); + const result = await this.grid.view.engine.executeQuery( + lambda, + this.grid.view.source, + this.grid.view.dataCube, + ); const rowData = buildRowData(result.result.result, newSnapshot); - if (this.grid.view.engine.enableDebugMode) { - this.grid.view.application.debugProcess( + if (this.grid.view.dataCube.settings.enableDebugMode) { + this.grid.view.engine.debugProcess( `Execution`, ['Query', result.executedQuery], ['Config', `pagination=${this.grid.isPaginationEnabled}`], @@ -464,10 +466,13 @@ export class DataCubeGridClientServerSideDataSource // When there are just too many rows (exceeding the maximum cache block size), we will fallback to a slightly less ideal // behavior by forcing a scroll top for every data fetch and also reset the cache block size to the default value to save memory if (rowData.length > INTERNAL__GRID_CLIENT_MAX_CACHE_BLOCK_SIZE) { - if (!this.grid.view.engine.gridClientSuppressLargeDatasetWarning) { - this.grid.view.application.alert({ + if ( + !this.grid.view.dataCube.settings + .gridClientSuppressLargeDatasetWarning + ) { + this.grid.view.engine.alert({ message: `Large dataset (>${INTERNAL__GRID_CLIENT_MAX_CACHE_BLOCK_SIZE} rows) detected!`, - text: `Overall app performance can be impacted by large dataset due to longer query execution time and increased memory usage. At its limit, the application can crash!\nTo boost performance, consider enabling pagination while working with large dataset.`, + text: `Overall app performance can be impacted by large dataset due to longer query execution time and increased memory usage. At its limit, the engine can crash!\nTo boost performance, consider enabling pagination while working with large dataset.`, type: AlertType.WARNING, actions: [ { @@ -479,7 +484,7 @@ export class DataCubeGridClientServerSideDataSource { label: 'Dismiss Warning', handler: () => { - this.grid.view.engine.setGridClientSuppressLargeDatasetWarning( + this.grid.view.dataCube.settings.setGridClientSuppressLargeDatasetWarning( true, ); }, @@ -516,7 +521,7 @@ export class DataCubeGridClientServerSideDataSource } } catch (error) { assertErrorThrown(error); - this.grid.view.application.alertError(error, { + this.grid.view.engine.alertError(error, { message: `Data Fetch Failure: ${error.message}`, }); params.fail(); @@ -528,7 +533,7 @@ export class DataCubeGridClientServerSideDataSource getRows(params: IServerSideGetRowsParams) { this.fetchRows(params).catch((error: unknown) => { assertErrorThrown(error); - this.grid.view.application.logIllegalStateError( + this.grid.view.engine.logIllegalStateError( `Error ocurred while fetching data for grid should have been handled gracefully`, error, ); diff --git a/packages/legend-data-cube/src/stores/view/grid/DataCubeGridClientExportEngine.ts b/packages/legend-data-cube/src/stores/view/grid/DataCubeGridClientExportEngine.ts index 724e0b904b..ed72504097 100644 --- a/packages/legend-data-cube/src/stores/view/grid/DataCubeGridClientExportEngine.ts +++ b/packages/legend-data-cube/src/stores/view/grid/DataCubeGridClientExportEngine.ts @@ -90,7 +90,7 @@ export class DataCubeGridClientExportEngine { } private generateFileName() { - return `${this.view.info.name} - ${formatDate(new Date(), 'EEE MMM dd yyyy HH_mm_ss')}`; + return `${this.grid.queryConfiguration.name} - ${formatDate(new Date(), 'EEE MMM dd yyyy HH_mm_ss')}`; } exportFile(format: DataCubeGridClientExportFormat) { diff --git a/packages/legend-data-cube/src/stores/view/grid/DataCubeGridConfigurationBuilder.tsx b/packages/legend-data-cube/src/stores/view/grid/DataCubeGridConfigurationBuilder.tsx index e6fd7b01d6..0ade304d12 100644 --- a/packages/legend-data-cube/src/stores/view/grid/DataCubeGridConfigurationBuilder.tsx +++ b/packages/legend-data-cube/src/stores/view/grid/DataCubeGridConfigurationBuilder.tsx @@ -21,11 +21,11 @@ * AG Grid, from the query snapshot. ***************************************************************************************/ +import { type DataCubeQuerySnapshot } from '../../core/DataCubeQuerySnapshot.js'; import { _findCol, - type DataCubeQuerySnapshot, - type DataCubeQuerySnapshotColumn, -} from '../../core/DataCubeQuerySnapshot.js'; + type DataCubeColumn, +} from '../../core/models/DataCubeColumn.js'; import type { ColDef, ColGroupDef, @@ -69,7 +69,7 @@ import { import type { DataCubeColumnConfiguration, DataCubeConfiguration, -} from '../../core/DataCubeConfiguration.js'; +} from '../../core/models/DataCubeConfiguration.js'; import { DataCubeColumnDataType, DataCubeColumnPinPlacement, @@ -659,7 +659,7 @@ function generatePivotResultColumnHeaderTooltip( } function generateDefinitionForPivotResultColumns( - pivotResultColumns: DataCubeQuerySnapshotColumn[], + pivotResultColumns: DataCubeColumn[], snapshot: DataCubeQuerySnapshot, configuration: DataCubeConfiguration, view: DataCubeViewState, @@ -798,7 +798,7 @@ export function generateColumnDefs( (column) => column.name === col.name, ), ); - let pivotResultColumns: DataCubeQuerySnapshotColumn[] = []; + let pivotResultColumns: DataCubeColumn[] = []; if (snapshot.data.pivot) { const castColumns = snapshot.data.pivot.castColumns; diff --git a/packages/legend-data-cube/src/stores/view/grid/DataCubeGridControllerState.ts b/packages/legend-data-cube/src/stores/view/grid/DataCubeGridControllerState.ts index de6e8bf825..98202f44b8 100644 --- a/packages/legend-data-cube/src/stores/view/grid/DataCubeGridControllerState.ts +++ b/packages/legend-data-cube/src/stores/view/grid/DataCubeGridControllerState.ts @@ -20,13 +20,15 @@ import { uniq, uniqBy, } from '@finos/legend-shared'; -import { DataCubeConfiguration } from '../../core/DataCubeConfiguration.js'; +import { DataCubeConfiguration } from '../../core/models/DataCubeConfiguration.js'; import { - _toCol, type DataCubeQuerySnapshot, - type DataCubeQuerySnapshotColumn, type DataCubeQuerySnapshotSortColumn, } from '../../core/DataCubeQuerySnapshot.js'; +import { + _toCol, + type DataCubeColumn, +} from '../../core/models/DataCubeColumn.js'; import { DataCubeQuerySnapshotController } from '../DataCubeQuerySnapshotManager.js'; import { type DataCubeQuerySortDirection, @@ -146,9 +148,9 @@ export class DataCubeGridControllerState extends DataCubeQuerySnapshotController // --------------------------------- COLUMNS --------------------------------- - selectColumns: DataCubeQuerySnapshotColumn[] = []; - leafExtendedColumns: DataCubeQuerySnapshotColumn[] = []; - groupExtendedColumns: DataCubeQuerySnapshotColumn[] = []; + selectColumns: DataCubeColumn[] = []; + leafExtendedColumns: DataCubeColumn[] = []; + groupExtendedColumns: DataCubeColumn[] = []; pinColumn( colName: string | undefined, @@ -200,8 +202,8 @@ export class DataCubeGridControllerState extends DataCubeQuerySnapshotController // --------------------------------- PIVOT --------------------------------- - horizontalPivotColumns: DataCubeQuerySnapshotColumn[] = []; - horizontalPivotCastColumns: DataCubeQuerySnapshotColumn[] = []; + horizontalPivotColumns: DataCubeColumn[] = []; + horizontalPivotCastColumns: DataCubeColumn[] = []; private get horizontalPivotResultColumns() { return this.horizontalPivotCastColumns @@ -263,7 +265,7 @@ export class DataCubeGridControllerState extends DataCubeQuerySnapshotController // --------------------------------- GROUP BY --------------------------------- - verticalPivotColumns: DataCubeQuerySnapshotColumn[] = []; + verticalPivotColumns: DataCubeColumn[] = []; getVerticalPivotableColumn(colName: string) { return this.configuration.columns diff --git a/packages/legend-data-cube/src/stores/view/grid/DataCubeGridMenuBuilder.tsx b/packages/legend-data-cube/src/stores/view/grid/DataCubeGridMenuBuilder.tsx index 481a40b914..e20cb63672 100644 --- a/packages/legend-data-cube/src/stores/view/grid/DataCubeGridMenuBuilder.tsx +++ b/packages/legend-data-cube/src/stores/view/grid/DataCubeGridMenuBuilder.tsx @@ -42,7 +42,7 @@ import { INTERNAL__GRID_CLIENT_TREE_COLUMN_ID, } from './DataCubeGridClientEngine.js'; import { PRIMITIVE_TYPE } from '@finos/legend-graph'; -import type { DataCubeColumnConfiguration } from '../../core/DataCubeConfiguration.js'; +import type { DataCubeColumnConfiguration } from '../../core/models/DataCubeConfiguration.js'; import { DataCubeFilterEditorConditionTreeNode } from '../../core/filter/DataCubeQueryFilterEditorState.js'; import { DataCubeEditorTab } from '../editor/DataCubeEditorState.js'; @@ -163,7 +163,7 @@ export function generateMenuBuilder( fromHeader: boolean, ) => (string | MenuItemDef)[] { const view = controller.view; - const application = view.application; + const engine = view.engine; // NOTE: we need to minimize the usage of these states // since the grid context-menu should be solely driven @@ -421,7 +421,7 @@ export function generateMenuBuilder( action: () => { view.grid.exportEngine .exportEmail(DataCubeGridClientExportFormat.EXCEL) - .catch((error) => application.logUnhandledError(error)); + .catch((error) => engine.logUnhandledError(error)); }, }, { @@ -429,7 +429,7 @@ export function generateMenuBuilder( action: () => { view.grid.exportEngine .exportEmail(DataCubeGridClientExportFormat.CSV) - .catch((error) => application.logUnhandledError(error)); + .catch((error) => engine.logUnhandledError(error)); }, }, { @@ -587,7 +587,7 @@ export function generateMenuBuilder( action: () => { extend .openNewColumnEditor() - .catch((error) => application.alertUnhandledError(error)); + .catch((error) => engine.alertUnhandledError(error)); }, }, ...(columnConfiguration && columnName @@ -597,7 +597,7 @@ export function generateMenuBuilder( action: () => { extend .openNewColumnEditor(columnConfiguration) - .catch((error) => application.alertUnhandledError(error)); + .catch((error) => engine.alertUnhandledError(error)); }, }, ] @@ -610,7 +610,7 @@ export function generateMenuBuilder( action: () => { extend .openExistingColumnEditor(columnName) - .catch((error) => application.alertUnhandledError(error)); + .catch((error) => engine.alertUnhandledError(error)); }, }, { @@ -618,7 +618,7 @@ export function generateMenuBuilder( action: () => { extend .deleteColumn(columnName) - .catch((error) => application.alertUnhandledError(error)); + .catch((error) => engine.alertUnhandledError(error)); }, }, ] diff --git a/packages/legend-data-cube/src/stores/view/grid/DataCubeGridQueryBuilder.ts b/packages/legend-data-cube/src/stores/view/grid/DataCubeGridQueryBuilder.ts index 07962bc3dd..5969512a14 100644 --- a/packages/legend-data-cube/src/stores/view/grid/DataCubeGridQueryBuilder.ts +++ b/packages/legend-data-cube/src/stores/view/grid/DataCubeGridQueryBuilder.ts @@ -52,7 +52,7 @@ import { INTERNAL__GRID_CLIENT_MISSING_VALUE, INTERNAL__GRID_CLIENT_ROW_GROUPING_COUNT_AGG_COLUMN_ID, } from './DataCubeGridClientEngine.js'; -import type { DataCubeConfiguration } from '../../core/DataCubeConfiguration.js'; +import type { DataCubeConfiguration } from '../../core/models/DataCubeConfiguration.js'; import type { DataCubeQueryFilterOperation } from '../../core/filter/DataCubeQueryFilterOperation.js'; import type { DataCubeQueryAggregateOperation } from '../../core/aggregation/DataCubeQueryAggregateOperation.js'; import { _colSpecArrayParam } from '../../core/DataCubeQuerySnapshotBuilderUtils.js'; diff --git a/packages/legend-data-cube/src/stores/view/grid/DataCubeGridQuerySnapshotBuilder.ts b/packages/legend-data-cube/src/stores/view/grid/DataCubeGridQuerySnapshotBuilder.ts index 4922117402..c74163b2c3 100644 --- a/packages/legend-data-cube/src/stores/view/grid/DataCubeGridQuerySnapshotBuilder.ts +++ b/packages/legend-data-cube/src/stores/view/grid/DataCubeGridQuerySnapshotBuilder.ts @@ -22,10 +22,8 @@ ***************************************************************************************/ import type { IServerSideGetRowsRequest } from '@ag-grid-community/core'; -import { - _toCol, - type DataCubeQuerySnapshot, -} from '../../core/DataCubeQuerySnapshot.js'; +import { type DataCubeQuerySnapshot } from '../../core/DataCubeQuerySnapshot.js'; +import { _toCol } from '../../core/models/DataCubeColumn.js'; import { GridClientSortDirection, INTERNAL__GRID_CLIENT_TREE_COLUMN_ID, @@ -35,7 +33,7 @@ import { getPivotResultColumnBaseColumnName, isPivotResultColumnName, } from '../../core/DataCubeQueryEngine.js'; -import { DataCubeConfiguration } from '../../core/DataCubeConfiguration.js'; +import { DataCubeConfiguration } from '../../core/models/DataCubeConfiguration.js'; import { guaranteeNonNullable, uniqBy } from '@finos/legend-shared'; import { _pruneExpandedPaths } from '../../core/DataCubeQuerySnapshotBuilderUtils.js'; diff --git a/packages/legend-data-cube/src/stores/view/grid/DataCubeGridState.ts b/packages/legend-data-cube/src/stores/view/grid/DataCubeGridState.ts index d3de3058e7..8fb0be14ba 100644 --- a/packages/legend-data-cube/src/stores/view/grid/DataCubeGridState.ts +++ b/packages/legend-data-cube/src/stores/view/grid/DataCubeGridState.ts @@ -29,7 +29,7 @@ import { import { DataCubeQuerySnapshotController } from '../DataCubeQuerySnapshotManager.js'; import type { DataCubeQuerySnapshot } from '../../core/DataCubeQuerySnapshot.js'; import { generateGridOptionsFromSnapshot } from './DataCubeGridConfigurationBuilder.js'; -import { DataCubeConfiguration } from '../../core/DataCubeConfiguration.js'; +import { DataCubeConfiguration } from '../../core/models/DataCubeConfiguration.js'; import { DataCubeGridControllerState } from './DataCubeGridControllerState.js'; import { DataCubeGridClientExportEngine } from './DataCubeGridClientExportEngine.js'; @@ -133,15 +133,15 @@ export class DataCubeGridState extends DataCubeQuerySnapshotController { configuration, this.view, ); - if (this.view.engine.enableDebugMode) { - this.view.application.debugProcess(`New Grid Options`, [ + if (this.view.dataCube.settings.enableDebugMode) { + this.view.engine.debugProcess(`New Grid Options`, [ 'Grid Options', gridOptions, ]); } this.client.updateGridOptions({ ...gridOptions, - rowBuffer: this.view.engine.gridClientRowBuffer, + rowBuffer: this.view.dataCube.settings.gridClientRowBuffer, // NOTE: ag-grid uses the cache block size as page size, so it's important to set this // in corresponding to the pagination setting, else it would cause unexpected scrolling behavior cacheBlockSize: this.isPaginationEnabled diff --git a/packages/legend-query-builder/src/components/data-cube/QueryBuilderDataCube.tsx b/packages/legend-query-builder/src/components/data-cube/QueryBuilderDataCube.tsx index bd991c46a4..b73e442567 100644 --- a/packages/legend-query-builder/src/components/data-cube/QueryBuilderDataCube.tsx +++ b/packages/legend-query-builder/src/components/data-cube/QueryBuilderDataCube.tsx @@ -14,10 +14,9 @@ * limitations under the License. */ -import { DataCube, DataCubeProvider } from '@finos/legend-data-cube'; +import { DataCube } from '@finos/legend-data-cube'; import type { QueryBuilderState } from '../../stores/QueryBuilderState.js'; import { observer } from 'mobx-react-lite'; -import { QueryBuilderDataCubeApplicationEngine } from '../../stores/data-cube/QueryBuilderDataCubeApplicationEngine.js'; import { clsx, Dialog, @@ -31,23 +30,12 @@ import { createDataCubeEngineFromQueryBuilder } from '../../stores/data-cube/Que const QueryBuilderDataCube = observer( (props: { queryBuilderState: QueryBuilderState }) => { const { queryBuilderState } = props; - const applicationStore = new QueryBuilderDataCubeApplicationEngine( - queryBuilderState.applicationStore, - ); - const queryBuilderEngine = - createDataCubeEngineFromQueryBuilder(queryBuilderState); - if (!queryBuilderEngine) { + const engine = createDataCubeEngineFromQueryBuilder(queryBuilderState); + + if (!engine) { return null; } - - return ( - - - - ); + return ; }, ); diff --git a/packages/legend-query-builder/src/index.ts b/packages/legend-query-builder/src/index.ts index 1628673286..a570d05b36 100644 --- a/packages/legend-query-builder/src/index.ts +++ b/packages/legend-query-builder/src/index.ts @@ -127,5 +127,4 @@ export * from './stores/filter/QueryBuilderFilterValueSpecificationBuilder.js'; export * from './stores/QueryBuilderValueSpecificationHelper.js'; export * from './stores/filter/QueryBuilderFilterState.js'; export * from './stores/filter/QueryBuilderFilterStateBuilder.js'; -export * from './stores/data-cube/QueryBuilderDataCubeApplicationEngine.js'; export * from './stores/data-cube/QueryBuilderDataCubeEngine.js'; diff --git a/packages/legend-query-builder/src/stores/data-cube/QueryBuilderDataCubeApplicationEngine.ts b/packages/legend-query-builder/src/stores/data-cube/QueryBuilderDataCubeApplicationEngine.ts deleted file mode 100644 index 9acb876902..0000000000 --- a/packages/legend-query-builder/src/stores/data-cube/QueryBuilderDataCubeApplicationEngine.ts +++ /dev/null @@ -1,98 +0,0 @@ -/** - * 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 { - APPLICATION_EVENT, - shouldDisplayVirtualAssistantDocumentationEntry, - type GenericLegendApplicationStore, -} from '@finos/legend-application'; -import { DataCubeApplicationEngine } from '@finos/legend-data-cube'; -import { LogEvent, type DocumentationEntry } from '@finos/legend-shared'; - -export class QueryBuilderDataCubeApplicationEngine extends DataCubeApplicationEngine { - private readonly application: GenericLegendApplicationStore; - - constructor(application: GenericLegendApplicationStore) { - super(); - - this.application = application; - } - - get documentationUrl(): string | undefined { - return this.application.documentationService.url; - } - - getDocumentationEntry(key: string) { - return this.application.documentationService.getDocEntry(key); - } - - openDocumentationEntry(entry: DocumentationEntry) { - this.currentDocumentationEntry = entry; - } - - shouldDisplayDocumentationEntry(entry: DocumentationEntry) { - return shouldDisplayVirtualAssistantDocumentationEntry(entry); - } - - openLink(url: string) { - this.application.navigationService.navigator.visitAddress(url); - } - - setWindowTitle(title: string) { - this.application.layoutService.setWindowTitle(title); - } - - logDebug(message: string, ...data: unknown[]) { - this.application.logService.debug( - LogEvent.create(APPLICATION_EVENT.DEBUG), - message, - ...data, - ); - } - - debugProcess(processName: string, ...data: unknown[]) { - this.application.logService.debug( - LogEvent.create(APPLICATION_EVENT.DEBUG), - `\n------ START DEBUG PROCESS: ${processName} ------\n`, - ...data, - `\n------- END DEBUG PROCESS: ${processName} -------\n`, - ); - } - - logInfo(event: LogEvent, ...data: unknown[]) { - this.application.logService.info(event, ...data); - } - - logWarning(event: LogEvent, ...data: unknown[]) { - this.application.logService.warn(event, ...data); - } - - logError(event: LogEvent, ...data: unknown[]) { - this.application.logService.error(event, ...data); - } - - logUnhandledError(error: Error) { - this.application.logUnhandledError(error); - } - - logIllegalStateError(message: string, error?: Error) { - this.logError( - LogEvent.create(APPLICATION_EVENT.ILLEGAL_APPLICATION_STATE_OCCURRED), - message, - error, - ); - } -} diff --git a/packages/legend-query-builder/src/stores/data-cube/QueryBuilderDataCubeEngine.ts b/packages/legend-query-builder/src/stores/data-cube/QueryBuilderDataCubeEngine.ts index 4effa7337e..f15f3cc773 100644 --- a/packages/legend-query-builder/src/stores/data-cube/QueryBuilderDataCubeEngine.ts +++ b/packages/legend-query-builder/src/stores/data-cube/QueryBuilderDataCubeEngine.ts @@ -33,36 +33,22 @@ import { import { _elementPtr, _functionName, - DataCubeGetBaseQueryResult, DataCubeEngine, - type CompletionItem, - DataCubeQuerySource, - type DataCubeInfrastructureInfo, + DataCubeSource, type RelationType, DataCubeQuery, + type DataCubeInitialInput, + type CompletionItem, + _function, + DataCubeFunction, } from '@finos/legend-data-cube'; -import { guaranteeType, LogService } from '@finos/legend-shared'; +import { guaranteeType, isNonNullable, LogService } from '@finos/legend-shared'; -export class _DataCubeQuery { - name: string; - query: string; - partialQuery: string; - source: DataCubeQuerySource; - - constructor( - name: string, - query: string, - partialQuery: string, - source: DataCubeQuerySource, - ) { - this.name = name; - this.query = query; - this.partialQuery = partialQuery; - this.source = source; - } +class QueryBuilderDataCubeSource extends DataCubeSource { + mapping?: string | undefined; + runtime!: string; } -export class QueryBuilderDataCubeQuerySource extends DataCubeQuerySource {} export class QueryBuilderDataCubeEngine extends DataCubeEngine { readonly logService = new LogService(); readonly graphState: GraphManagerState; @@ -90,12 +76,12 @@ export class QueryBuilderDataCubeEngine extends DataCubeEngine { get sourceLabel(): string { return `Query Builder Report`; } - override getBaseQuery(): Promise { + + override getInitialInput(): Promise { return this.buildBaseQuery(); } - async buildBaseQuery(): Promise { - const timestamp = Date.now(); + async buildBaseQuery(): Promise { let srcFuncExp = V1_deserializeValueSpecification( this.graphState.graphManager.serializeRawValueSpecification( this.selectInitialQuery, @@ -121,60 +107,44 @@ export class QueryBuilderDataCubeEngine extends DataCubeEngine { if (this.runtimePath) { fromFuncExp.parameters.push(_elementPtr(this.runtimePath)); } - const [relationType, queryString, fromQuerystring] = await Promise.all([ - this.getRelationalType(this.selectInitialQuery), - this.graphState.graphManager.valueSpecificationToPureCode( - V1_serializeValueSpecification(srcFuncExp, []), - ), - this.graphState.graphManager.valueSpecificationToPureCode( - V1_serializeValueSpecification(fromFuncExp, []), - ), - ]); - const columns = relationType.columns; - const source = new QueryBuilderDataCubeQuerySource(); - source.columns = columns; + const columns = (await this.getRelationalType(this.selectInitialQuery)) + .columns; + const query = new DataCubeQuery(); + query.query = `~[${columns.map((e) => `'${e.name}'`)}]->select()`; + const source = new QueryBuilderDataCubeSource(); + source.sourceColumns = columns; source.mapping = this.mappingPath; source.runtime = this.runtimePath; - source.query = queryString; - const partialQuery = `~[${columns.map((e) => `'${e.name}'`)}]->select()`; - const result = new DataCubeQuery(this.sourceLabel, fromQuerystring); - result.partialQuery = partialQuery; - result.source = source; - const baseQueryResult = new DataCubeGetBaseQueryResult(); - baseQueryResult.timestamp = timestamp; - baseQueryResult.query = result; - baseQueryResult.partialQuery = await this.parseQuery(partialQuery); - baseQueryResult.sourceQuery = srcFuncExp; - return baseQueryResult; + source.query = srcFuncExp; + return { + query, + source, + }; } get graph(): PureModel { return this.graphState.graph; } - private buildRawLambdaFromValueSpec(query: V1_ValueSpecification): RawLambda { + private buildRawLambdaFromValueSpec(query: V1_Lambda): RawLambda { const json = guaranteeType( V1_deserializeRawValueSpecification( - V1_serializeValueSpecification(query, []), + V1_serializeValueSpecification( + query.body[0] as V1_ValueSpecification, + [], + ), ), V1_RawLambda, ); return new RawLambda(json.parameters, json.body); } - override getInfrastructureInfo(): Promise { - // we return undefined as we assume the grid license is set at the application level where query builder is built - return Promise.resolve({ - gridClientLicense: undefined, - simpleSampleDataTableName: '', - complexSampleDataTableName: '', - }); - } - override async getQueryTypeahead( + async getQueryTypeahead( code: string, - query: V1_ValueSpecification, - ): Promise { - const lambda = this.buildRawLambdaFromValueSpec(query); + baseQuery: V1_Lambda, + source: DataCubeSource, + ) { + const lambda = this.buildRawLambdaFromValueSpec(baseQuery); const queryString = await this.graphState.graphManager.lambdaToPureCode(lambda); const offset = queryString.length; @@ -184,13 +154,13 @@ export class QueryBuilderDataCubeEngine extends DataCubeEngine { this.graph, offset, ); - return result.completions; + return result.completions as CompletionItem[]; } - override async parseQuery( + override async parseValueSpecification( code: string, returnSourceInformation?: boolean, - ): Promise { + ) { return V1_deserializeValueSpecification( await this.graphState.graphManager.pureCodeToValueSpecification( code, @@ -200,36 +170,35 @@ export class QueryBuilderDataCubeEngine extends DataCubeEngine { ); } - override getQueryCode( - query: V1_ValueSpecification, + override getValueSpecificationCode( + value: V1_ValueSpecification, pretty?: boolean | undefined, - ): Promise { + ) { return this.graphState.graphManager.valueSpecificationToPureCode( - V1_serializeValueSpecification(query, []), + V1_serializeValueSpecification(value, []), pretty, ); } - override getQueryRelationType( - query: V1_ValueSpecification, - ): Promise { - const lambda = this.buildRawLambdaFromValueSpec(query); - return this.getRelationalType(lambda); - } - - async getRelationalType(query: RawLambda): Promise { - const realtion_type = + private async getRelationalType(query: RawLambda): Promise { + const relationType = await this.graphState.graphManager.getLambdaRelationType( query, this.graph, ); - return realtion_type; + return relationType; + } + + override getQueryRelationType(query: V1_Lambda, source: DataCubeSource) { + const lambda = this.buildRawLambdaFromValueSpec(query); + return this.getRelationalType(lambda); } override async getQueryCodeRelationReturnType( code: string, baseQuery: V1_ValueSpecification, - ): Promise { + source: DataCubeSource, + ) { const queryString = await this.graphState.graphManager.valueSpecificationToPureCode( V1_serializeValueSpecification(baseQuery, []), @@ -240,11 +209,7 @@ export class QueryBuilderDataCubeEngine extends DataCubeEngine { ); } - override async executeQuery(query: V1_Lambda): Promise<{ - result: TDSExecutionResult; - executedQuery: string; - executedSQL: string; - }> { + override async executeQuery(query: V1_Lambda, source: DataCubeSource) { const lambda = this.buildRawLambdaFromValueSpec(query); lambda.parameters = this._parameters; const [executionWithMetadata, queryString] = await Promise.all([ @@ -275,4 +240,19 @@ export class QueryBuilderDataCubeEngine extends DataCubeEngine { executedSQL: sqlString, }; } + + override buildExecutionContext( + source: DataCubeSource, + ): V1_AppliedFunction | undefined { + if (source instanceof QueryBuilderDataCubeSource) { + return _function( + DataCubeFunction.FROM, + [ + source.mapping ? _elementPtr(source.mapping) : undefined, + _elementPtr(source.runtime), + ].filter(isNonNullable), + ); + } + return undefined; + } } diff --git a/yarn.lock b/yarn.lock index 765475b1fb..1036454a4f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2519,6 +2519,7 @@ __metadata: react-dom: "npm:18.3.1" rimraf: "npm:6.0.1" sass: "npm:1.79.4" + serializr: "npm:3.0.2" typescript: "npm:5.6.3" peerDependencies: react: ^18.0.0