Skip to content

Commit

Permalink
fix result modifiers for typed tds (#3834)
Browse files Browse the repository at this point in the history
  • Loading branch information
MauricioUyaguari authored Jan 24, 2025
1 parent f6028bc commit bf5dfbc
Show file tree
Hide file tree
Showing 14 changed files with 585 additions and 154 deletions.
4 changes: 4 additions & 0 deletions .changeset/weak-pillows-wave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
'@finos/legend-query-builder': patch
'@finos/legend-graph': patch
---
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ import type {
ColSpec,
ColSpecArray,
ColSpecArrayInstance,
ColSpecInstanceValue,
} from '../../../graph/metamodel/pure/valueSpecification/RelationValueSpecification.js';

const observe_Abstract_ValueSpecification = (
Expand Down Expand Up @@ -194,6 +195,10 @@ export const observe_ColSpecArrayInstance = skipObservedWithContext(
_observe_ColSpecArrayInstance,
);

export const observe_ColSpecInstance = skipObservedWithContext(
_observe_ColSpecInstance,
);

const observe_LambdaFunction = skipObservedWithContext(_observe_LambdaFunction);

const observe_LambdaFunctionInstanceValue = skipObservedWithContext(
Expand Down Expand Up @@ -344,6 +349,10 @@ class ValueSpecificationObserver implements ValueSpecificationVisitor<void> {
visit_ColSpecArrayInstance(valueSpeciciation: ColSpecArrayInstance): void {
observe_ColSpecArrayInstance(valueSpeciciation, this.observerContext);
}

visit_ColSpecInstance(valueSpeciciation: ColSpecInstanceValue): void {
observe_ColSpecInstance(valueSpeciciation, this.observerContext);
}
}

export const observe_ValueSpecification = skipObservedWithContext(
Expand Down Expand Up @@ -513,6 +522,18 @@ function _observe_ColSpecArrayInstance(
return metamodel;
}

function _observe_ColSpecInstance(
metamodel: ColSpecInstanceValue,
context: ObserverContext,
): ColSpecInstanceValue {
observe_Abstract_InstanceValue(metamodel, context);
makeObservable(metamodel, {
hashCode: override,
});
metamodel.values.forEach((value) => observe_ColSpec(value, context));
return metamodel;
}

function _observe_ColSpec(
metamodel: ColSpec,
context: ObserverContext,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,10 @@ import { V1_ClassInstance } from '../../../model/valueSpecification/raw/V1_Class
import { V1_ClassInstanceType } from '../../pureProtocol/serializationHelpers/V1_ValueSpecificationSerializer.js';
import type { KeyExpressionInstanceValue } from '../../../../../../../graph/metamodel/pure/valueSpecification/KeyExpressionInstanceValue.js';
import { V1_CByteArray } from '../../../model/valueSpecification/raw/V1_CByteArray.js';
import type { ColSpecArrayInstance } from '../../../../../../../graph/metamodel/pure/valueSpecification/RelationValueSpecification.js';
import type {
ColSpecArrayInstance,
ColSpecInstanceValue,
} from '../../../../../../../graph/metamodel/pure/valueSpecification/RelationValueSpecification.js';
import { V1_ColSpecArray } from '../../../model/valueSpecification/raw/classInstance/relation/V1_ColSpecArray.js';
import { V1_ColSpec } from '../../../model/valueSpecification/raw/classInstance/relation/V1_ColSpec.js';
import { RelationColumn } from '../../../../../../../graph/metamodel/pure/packageableElements/relation/RelationType.js';
Expand Down Expand Up @@ -424,6 +427,29 @@ class V1_ValueSpecificationTransformer
classInstance.value = colSpecArray;
return classInstance;
}

visit_ColSpecInstance(
valueSpecification: ColSpecInstanceValue,
): V1_ValueSpecification {
const classInstance = new V1_ClassInstance();
classInstance.type = V1_ClassInstanceType.COL_SPEC;
const val = guaranteeNonNullable(valueSpecification.values[0]);
const colProtocol = new V1_ColSpec();
colProtocol.name = val.name;
const fun1 = val.function1?.accept_ValueSpecificationVisitor(
new V1_ValueSpecificationTransformer(
this.inScope,
this.open,
this.isParameter,
this.useAppliedFunction,
),
);
if (fun1) {
colProtocol.function1 = guaranteeType(fun1, V1_Lambda);
}
classInstance.value = colProtocol;
return classInstance;
}
}

export function V1_transformGraphFetchTree(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,11 @@ import {
V1_getGenericTypeFullPath,
V1_createGenericTypeWithElementPath,
} from '../../../../helpers/V1_DomainHelper.js';
import {
ColSpec,
ColSpecInstanceValue,
} from '../../../../../../../../graph/metamodel/pure/valueSpecification/RelationValueSpecification.js';
import { V1_ColSpec } from '../../../../model/valueSpecification/raw/classInstance/relation/V1_ColSpec.js';

const buildPrimtiveInstanceValue = (
type: PRIMITIVE_TYPE,
Expand Down Expand Up @@ -458,6 +463,17 @@ export class V1_ValueSpecificationBuilder
instanceValue.values = [tree];
return instanceValue;
}
case V1_ClassInstanceType.COL_SPEC: {
const instanceValue = new ColSpecInstanceValue(
Multiplicity.ONE,
undefined,
);
const protocol = guaranteeType(valueSpecification.value, V1_ColSpec);
const value = new ColSpec();
value.name = protocol.name;
instanceValue.values = [value];
return instanceValue;
}
default: {
const builders = this.context.extensions.plugins.flatMap(
(plugin) => plugin.V1_getExtraClassInstanceValueBuilders?.() ?? [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,23 @@ export class ColSpec implements Hashable {
]);
}
}
export class ColSpecInstanceValue extends InstanceValue implements Hashable {
override values: ColSpec[] = [];

override get hashCode(): string {
return hashArray([
CORE_HASH_STRUCTURE.RELATION_COL_SPEC,
this.genericType?.ownerReference.valueForSerialization ?? '',
this.multiplicity,
hashArray(this.values),
]);
}
override accept_ValueSpecificationVisitor<T>(
visitor: ValueSpecificationVisitor<T>,
): T {
return visitor.visit_ColSpecInstance(this);
}
}
export class ColSpecArray implements Hashable {
colSpecs: ColSpec[] = [];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ import type { VariableExpression } from './VariableExpression.js';
import type { INTERNAL__PropagatedValue } from './INTERNAL__PropagatedValue.js';
import type { Hashable } from '@finos/legend-shared';
import type { KeyExpressionInstanceValue } from './KeyExpressionInstanceValue.js';
import type { ColSpecArrayInstance } from './RelationValueSpecification.js';
import type {
ColSpecArrayInstance,
ColSpecInstanceValue,
} from './RelationValueSpecification.js';

export interface ValueSpecificationVisitor<T> {
visit_INTERNAL__UnknownValueSpecification(
Expand All @@ -55,6 +58,7 @@ export interface ValueSpecificationVisitor<T> {

visit_InstanceValue(valueSpecification: InstanceValue): T;
visit_ColSpecArrayInstance(valueSpeciciation: ColSpecArrayInstance): T;
visit_ColSpecInstance(valueSpeciciation: ColSpecInstanceValue): T;

visit_CollectionInstanceValue(valueSpecification: CollectionInstanceValue): T;
visit_EnumValueInstanceValue(valueSpecification: EnumValueInstanceValue): T;
Expand Down
1 change: 1 addition & 0 deletions packages/legend-graph/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ export {
} from './graph/metamodel/pure/valueSpecification/KeyExpressionInstanceValue.js';
export {
ColSpec,
ColSpecInstanceValue,
ColSpecArray,
ColSpecArrayInstance,
} from './graph/metamodel/pure/valueSpecification/RelationValueSpecification.js';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,37 @@ const TEST_CASES: QueryTestCase[] = [
model: 'Relational_Business',
queryGrammar:
"var_1: String[0..1]|model::pure::tests::model::simple::Person.all()->project([x|$x.firstName, x|$x.lastName], ['Edited First Name', 'Last Name'])",
convertedRelation: `var_1: String[0..1]|model::pure::tests::model::simple::Person.all()->project(~['Edited First Name':x|$x.firstName, 'Last Name':x|$x.lastName])`,
},
{
testName: '[LEGACY] Result Modifier: Sort',
model: 'Northwind',
queryGrammar: `|showcase::northwind::model::crm::Customer.all()->project([x|$x.companyName, x|$x.companyTitle], ['Company Name', 'Company Title'])->sort([asc('Company Name'), desc('Company Title')])`,
convertedRelation: `|showcase::northwind::model::crm::Customer.all()->project(~['Company Name':x|$x.companyName, 'Company Title':x|$x.companyTitle])->sort([~'Company Name'->ascending(), ~'Company Title'->descending()])`,
},
{
testName: '[LEGACY] Result Modifier: Distinct',
model: 'Northwind',
queryGrammar: `|showcase::northwind::model::crm::Customer.all()->project([x|$x.companyName], ['name'])->distinct()`,
convertedRelation: `|showcase::northwind::model::crm::Customer.all()->project(~[name:x|$x.companyName])->distinct()`,
},
{
testName: '[LEGACY] Result Modifier: Take',
model: 'Northwind',
queryGrammar: `|showcase::northwind::model::crm::Customer.all()->project([x|$x.companyName], ['Company Name'])->take(27)`,
convertedRelation: `|showcase::northwind::model::crm::Customer.all()->project(~['Company Name':x|$x.companyName])->limit(27)`,
},
{
testName: '[LEGACY] Result Modifier: Slice',
model: 'Northwind',
queryGrammar: `|showcase::northwind::model::crm::Customer.all()->project([x|$x.companyName], ['Company Name'])->slice(1, 7)`,
convertedRelation: `|showcase::northwind::model::crm::Customer.all()->project(~['Company Name':x|$x.companyName])->slice(1, 7)`,
},
{
testName: '[LEGACY] Result Modifier: For Watermark',
model: 'Northwind',
queryGrammar: `|showcase::northwind::model::crm::Customer.all()->forWatermark('testing')->project([x|$x.companyName], ['Company Name'])`,
convertedRelation: `|showcase::northwind::model::crm::Customer.all()->forWatermark('testing')->project(~['Company Name':x|$x.companyName])`,
},
// Relation
{
Expand All @@ -93,6 +124,26 @@ const TEST_CASES: QueryTestCase[] = [
queryGrammar:
"|showcase::northwind::model::crm::Customer.all()->filter(x|$x.companyTitle == 'company title')->project(~['Company Name':x|$x.companyName, 'Company Title':x|$x.companyTitle])->filter(row|$row.'Company Name' == 'company name')",
},
{
testName: '[LEGACY] Result Modifier: Sort',
model: 'Northwind',
queryGrammar: `|showcase::northwind::model::crm::Customer.all()->project([x|$x.companyName, x|$x.companyTitle], ['Company Name', 'Company Title'])->sort([asc('Company Name'), desc('Company Title')])`,
},
{
testName: '[LEGACY] Result Modifier: Distinct',
model: 'Northwind',
queryGrammar: `|showcase::northwind::model::crm::Customer.all()->project(~[name:x|$x.companyName])->distinct()`,
},
{
testName: '[LEGACY] Result Modifier: Take',
model: 'Northwind',
queryGrammar: `|showcase::northwind::model::crm::Customer.all()->project(~['Company Name':x|$x.companyName])->limit(27)`,
},
{
testName: '[LEGACY] Result Modifier: Slice',
model: 'Northwind',
queryGrammar: `|showcase::northwind::model::crm::Customer.all()->project(~['Company Name':x|$x.companyName])->slice(1, 7)`,
},
// conversion
{
testName: '[CONVERSION] Convert Query With Pre/Post Filter to Relation',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,11 @@ export enum QUERY_BUILDER_SUPPORTED_FUNCTIONS {
// Relation
RELATION_PROJECT = 'meta::pure::functions::relation::project',
RELATION_LIMIT = 'meta::pure::functions::relation::limit',

RELATION_ASC = 'meta::pure::functions::relation::ascending',
RELATION_DESC = 'meta::pure::functions::relation::descending',
RELATION_DISTINCT = 'meta::pure::functions::relation::distinct',
RELATION_SORT = 'meta::pure::functions::relation::sort',
RELATION_SLICE = 'meta::pure::functions::relation::slice',
// filter
CONTAINS = 'meta::pure::functions::string::contains',
ENDS_WITH = 'meta::pure::functions::string::endsWith',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import {
RuntimePointer,
PackageableElementExplicitReference,
MILESTONING_STEREOTYPE,
type ColSpecInstanceValue,
} from '@finos/legend-graph';
import { processTDSPostFilterExpression } from './fetch-structure/tds/post-filter/QueryBuilderPostFilterStateBuilder.js';
import { processFilterExpression } from './filter/QueryBuilderFilterStateBuilder.js';
Expand All @@ -69,6 +70,7 @@ import {
processInternalizeExpression,
} from './fetch-structure/graph-fetch/QueryBuilderGraphFetchTreeStateBuilder.js';
import {
processRelationSortDirectionExpression,
processTDSColExpression,
processTDSDistinctExpression,
processTDSProjectExpression,
Expand Down Expand Up @@ -669,10 +671,10 @@ export class QueryBuilderValueSpecificationProcessor
processTDSColExpression(valueSpecification, this.queryBuilderState);
return;
} else if (
matchFunctionName(
functionName,
matchFunctionName(functionName, [
QUERY_BUILDER_SUPPORTED_FUNCTIONS.TDS_TAKE,
)
QUERY_BUILDER_SUPPORTED_FUNCTIONS.RELATION_LIMIT,
])
) {
processTDSTakeExpression(
valueSpecification,
Expand Down Expand Up @@ -725,6 +727,18 @@ export class QueryBuilderValueSpecificationProcessor
this.queryBuilderState,
);
return;
} else if (
matchFunctionName(functionName, [
QUERY_BUILDER_SUPPORTED_FUNCTIONS.RELATION_ASC,
QUERY_BUILDER_SUPPORTED_FUNCTIONS.RELATION_DESC,
])
) {
processRelationSortDirectionExpression(
valueSpecification,
this.parentExpression,
this.queryBuilderState,
);
return;
} else if (
matchFunctionName(
functionName,
Expand Down Expand Up @@ -994,6 +1008,10 @@ export class QueryBuilderValueSpecificationProcessor
`Can't process col spec array expression with parent expression of function ${this.parentExpression.functionName}()`,
);
}

visit_ColSpecInstance(valueSpeciciation: ColSpecInstanceValue): void {
throw new Error('Method not implemented.');
}
}

export const processParameters = (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export const TEST_DATA_simpleTypedRelationProjection = {
body: [
{
_type: 'func',
function: 'take',
function: 'limit',
parameters: [
{
_type: 'func',
Expand Down
Loading

0 comments on commit bf5dfbc

Please sign in to comment.