From 5bc1ee392cc9e032ee6ea7846139d1e4d9938f38 Mon Sep 17 00:00:00 2001 From: "Girdhar, Tanuj [AM Public]" Date: Fri, 24 Nov 2023 08:10:37 -0500 Subject: [PATCH 1/3] * no changes needed for relationalGraphFetch * always route to otherwiseMapping for graphFetchFlow * fix otherwise embedded mapping for graphfetch * behave as if embedded mapping were empty --- .../pure/graphFetch/graphFetch_routing.pure | 11 +- .../core/pure/mapping/mappingExtension.pure | 10 +- .../core/pure/router/router_main.pure | 7 +- .../pure/router/routing/router_routing.pure | 10 +- .../core/pure/router/store/builder.pure | 11 +- .../tests/testGraphFetchEmbdded.pure | 34 +- .../tests/testGraphFetchEmbeddedInline.pure | 96 ++++++ .../testGraphFetchEmbeddedOtherwise.pure | 319 ++++++++++++++++++ .../pureToSQLQuery/pureToSQLQuery.pure | 1 - .../testEmbeddedOtherwiseMapping.pure | 71 +++- 10 files changed, 551 insertions(+), 19 deletions(-) create mode 100644 legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/graphFetch/tests/testGraphFetchEmbeddedInline.pure create mode 100644 legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/graphFetch/tests/testGraphFetchEmbeddedOtherwise.pure diff --git a/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/graphFetch/graphFetch_routing.pure b/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/graphFetch/graphFetch_routing.pure index 27ca6ca105e..2ecc956ecbc 100644 --- a/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/graphFetch/graphFetch_routing.pure +++ b/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/graphFetch/graphFetch_routing.pure @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +import meta::relational::mapping::*; import meta::pure::router::store::routing::*; import meta::pure::lineage::scanProperties::*; import meta::pure::milestoning::*; @@ -64,11 +65,14 @@ function meta::pure::graphFetch::routing::propertyMappingInfo(prop: PropertyGrap let fe = $routedProperty->byPassRouterInfo()->cast(@FunctionExpression); let sourceSets = if($prop.subType->isEmpty(), | $fe, | $fe.parametersValues->evaluateAndDeactivate()->at(0)->byPassRouterInfo()->cast(@FunctionExpression)).parametersValues->evaluateAndDeactivate()->at(0)->cast(@StoreMappingRoutedValueSpecification).sets->resolveOperation($mapping)->cast(@InstanceSetImplementation); $sourceSets->map({ss | - let propMaps = $ss->_propertyMappingsByPropertyName($property.name->toOne())->filter(x | $x.targetSetImplementationId->in($targetSets.id)); + let propMaps = $ss->propertyMappingsByPropertyName($property.name->toOne())->filter(x | $x.targetSetImplementationId->in($targetSets.id)); $propMaps->map(pm | $mapping->classMappingById($pm.targetSetImplementationId)->resolveOperation($mapping)->map(ts | ^$pm(targetSetImplementationId = $ts.id))); });, | $propertyMappings ); + + + ^PropertyMappingInfo(property=$property, propertyMappings=$resolvedPropertyMappings, sets=$sets);); } @@ -218,7 +222,7 @@ function meta::pure::graphFetch::routing::routeRootGraphFetchTree(root: RootGrap let rootGetAllExpression = createGetAllApplicationForRootGraphFetchTree($root, $set); let dummyLambda = {|'ok'}; - let routedFunction = ^$dummyLambda(expressionSequence = $rootGetAllExpression)->routeFunction($mapping, ^Runtime(), ^ExecutionContext(), $extensions, noDebug())->evaluateAndDeactivate()->toOne(); + let routedFunction = ^$dummyLambda(expressionSequence = $rootGetAllExpression)->routeFunction(getRoutingStrategyFromMappingAndRuntime($mapping, ^Runtime()), ^ExecutionContext(), [], true, $extensions, noDebug())->evaluateAndDeactivate()->toOne(); let ext = $routedFunction.expressionSequence->evaluateAndDeactivate()->toOne()->cast(@StoreMappingClusteredValueSpecification).val->cast(@StoreMappingRoutedValueSpecification); let extended = if($exeCtx.enableConstraints->isEmpty() || $exeCtx.enableConstraints->toOne(), @@ -461,7 +465,8 @@ function meta::pure::graphFetch::routing::routePropertyGraphFetchTree(prop: Prop let dummyLambda = {|'ok'}; let cls = $functionExpression.genericType.rawType->toOne()->cast(@Class); // TODO Only allow no mapping routing for expanded (sub)trees - let routedFunctions = ^$dummyLambda(expressionSequence = $propertyApplicationExporession)->routeFunction($mapping, ^Runtime(), $extensions, noDebug())->evaluateAndDeactivate(); + + let routedFunctions = ^$dummyLambda(expressionSequence = $propertyApplicationExporession)->routeFunction(getRoutingStrategyFromMappingAndRuntime($mapping, ^Runtime()), ^ExecutionContext(), [], true, $extensions, noDebug())->evaluateAndDeactivate(); if($routedFunctions->isNotEmpty(), | let routedFunction = $routedFunctions->toOne(); diff --git a/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/mapping/mappingExtension.pure b/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/mapping/mappingExtension.pure index 87af662b22d..9c99e3835c7 100644 --- a/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/mapping/mappingExtension.pure +++ b/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/mapping/mappingExtension.pure @@ -206,9 +206,13 @@ function meta::pure::router::routing::findMappingsFromProperty(p:AbstractPropert ), | if($embeddedMappings->at(0)->instanceOf(InlineEmbeddedSetImplementation), |$embeddedMappings->at(0)->cast(@InlineEmbeddedSetImplementation)->inlineEmbeddedMapping($mapping), - |$embeddedMappings - ) - + | + if($state.graphFetchFlow == true && $embeddedMappings->at(0)->instanceOf(OtherwiseEmbeddedSetImplementation), + | let otherwiseTargetIds = $embeddedMappings->at(0)->cast(@OtherwiseEmbeddedSetImplementation).otherwisePropertyMapping.targetSetImplementationId; + let classMappingsById = if ($otherwiseTargetIds->isEmpty(),|[],|findMappingsFromProperty($p, $mapping, $mapping->_classMappingByIdRecursive($otherwiseTargetIds), $state, $extensions)); + $classMappingsById;, + | $embeddedMappings + )) ); // We don't find anything in the old flow (if the source is an operation and the target type is not directly mapped... diff --git a/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/router/router_main.pure b/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/router/router_main.pure index 7d458751631..42f81ecb0e5 100644 --- a/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/router/router_main.pure +++ b/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/router/router_main.pure @@ -112,6 +112,11 @@ function meta::pure::router::routeFunction(f:FunctionDefinition[1], exeCtx: } function meta::pure::router::routeFunction(f:FunctionDefinition[1], routingStrategy:RoutingStrategy[1], exeCtx: ExecutionContext[1], inScopeVars:Map>[0..1], extensions:meta::pure::extension::Extension[*], debug:DebugContext[1]):FunctionDefinition[1] +{ + routeFunction($f, $routingStrategy, $exeCtx, $inScopeVars, false, $extensions, $debug); +} + +function meta::pure::router::routeFunction(f:FunctionDefinition[1], routingStrategy:RoutingStrategy[1], exeCtx: ExecutionContext[1], inScopeVars:Map>[0..1], graphFetchFlow:Boolean[0..1], extensions:meta::pure::extension::Extension[*], debug:DebugContext[1]):FunctionDefinition[1] { let fOpenVariables = $f->openVariableValues(); let openVariables = if($inScopeVars->isNotEmpty(), @@ -123,7 +128,7 @@ function meta::pure::router::routeFunction(f:FunctionDefinition[1], routing // Enriching Function Expressions with relevant info (mapping / binding / platform) print(if($debug.debug,|'\n'+$debug.space+'Enriching Function Expressions with relevant info (mapping / binding / platform) and assigning routing strategy:\n',|'')); - let enrichedExpressions = enrichFunctionExpressions($functionExpressions, $routingStrategy, $exeCtx, $openVariables, $extensions, $debug); + let enrichedExpressions = enrichFunctionExpressions($functionExpressions, $routingStrategy, $exeCtx, $openVariables, $graphFetchFlow, $extensions, $debug); // Enriching Function Expressions with more information based on type of expression (subTypes of ExtendedRoutedValueSpecification) print(if($debug.debug,|'\n'+$debug.space+'Enriching Function Expressions with strategy based info (mapping / binding / platform):\n',|'')); diff --git a/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/router/routing/router_routing.pure b/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/router/routing/router_routing.pure index 678f458d172..79d1ac43da8 100644 --- a/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/router/routing/router_routing.pure +++ b/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/router/routing/router_routing.pure @@ -42,6 +42,7 @@ Class meta::pure::router::routing::RoutingState routingStrategy : RoutingStrategy[1]; shouldBeRouted : Boolean[1]; value : Any[0..1]; + graphFetchFlow : Boolean[0..1]; } Class meta::pure::router::routing::PropertyMap @@ -49,9 +50,9 @@ Class meta::pure::router::routing::PropertyMap v : Pair[*]; } -function meta::pure::router::routing::enrichFunctionExpressions(expressions:FunctionExpression[*], routingStrategy:RoutingStrategy[1], executionContext:ExecutionContext[1], inScopeVars:Map>[1], extensions:meta::pure::extension::Extension[*], debug:DebugContext[1]):ExtendedRoutedValueSpecification[*] +function meta::pure::router::routing::enrichFunctionExpressions(expressions:FunctionExpression[*], routingStrategy:RoutingStrategy[1], executionContext:ExecutionContext[1], inScopeVars:Map>[1], graphFetchFlow: Boolean[0..1],extensions:meta::pure::extension::Extension[*], debug:DebugContext[1]):ExtendedRoutedValueSpecification[*] { - let processedFunctions = processCollection(^RoutingState(shouldBeRouted=false, lambdaContext=[], counter=0, depth='', propertyMap = ^PropertyMap(), routingStrategy = $routingStrategy), + let processedFunctions = processCollection(^RoutingState(shouldBeRouted=false, lambdaContext=[], counter=0, depth='', propertyMap = ^PropertyMap(), routingStrategy = $routingStrategy, graphFetchFlow = $graphFetchFlow), $expressions, $executionContext, newMap([]->cast(@Pair), VariableExpression->classPropertyByName('name')->cast(@Property)), @@ -67,6 +68,11 @@ function meta::pure::router::routing::enrichFunctionExpressions(expressions:Func ])); } +function meta::pure::router::routing::enrichFunctionExpressions(expressions:FunctionExpression[*], routingStrategy:RoutingStrategy[1], executionContext:ExecutionContext[1], inScopeVars:Map>[1], extensions:meta::pure::extension::Extension[*], debug:DebugContext[1]):ExtendedRoutedValueSpecification[*] +{ + enrichFunctionExpressions($expressions, $routingStrategy, $executionContext, $inScopeVars, false, $extensions, $debug); +} + function meta::pure::router::routing::processCollection(state:RoutingState[1], col:Any[*], executionContext:ExecutionContext[1], vars:Map[1], inScopeVars:Map>[1], shouldProcess:Function<{Any[1]->Boolean[1]}>[1], extensions:meta::pure::extension::Extension[*], debug:DebugContext[1]):RoutingState[*] { $col->fold({c,a| let last = $a->last()->toOne(); diff --git a/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/router/store/builder.pure b/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/router/store/builder.pure index 9153f44fa23..476c924d877 100644 --- a/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/router/store/builder.pure +++ b/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/router/store/builder.pure @@ -137,8 +137,15 @@ function meta::pure::router::store::routing::build(v:ValueSpecification[1], l:Li let res = if($resWithAssoc->isEmpty() && $f.func->instanceOf(Property) && $s->isPropertyAutoMapped($f.func->cast(@Property), $extensions), |$s->cast(@InstanceSetImplementation)->meta::pure::mapping::propertyMappingsByPropertyName($propertyName), |$resWithAssoc); - print(if($debug.debug,|$debug.space+' -> Found: '+$res->size()->toString(),|'')); - $res; + + let withOtherwise = if($res->isEmpty(), // for graphFetch flow, the parent set gets resolved to the otherwiseProperty mapping always. + | let byName = $s->cast(@InstanceSetImplementation)->meta::pure::mapping::propertyMappingsByPropertyName($propertyName)->filter(pm|$pm->instanceOf(OtherwiseEmbeddedSetImplementation))->map(pm|$pm->cast(@OtherwiseEmbeddedSetImplementation)); + let pms = $byName.otherwisePropertyMapping->filter(pm|$pm.targetSetImplementationId->in($targetIds)); + $pms;, + | $res ); + + print(if($debug.debug,|$debug.space+' -> Found: '+$withOtherwise->size()->toString(),|'')); + $withOtherwise; ); ); let fWithBuiltExprSeq = if ($f.func->instanceOf(QualifiedProperty) diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/graphFetch/tests/testGraphFetchEmbdded.pure b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/graphFetch/tests/testGraphFetchEmbdded.pure index 9420de56c13..de658ef175a 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/graphFetch/tests/testGraphFetchEmbdded.pure +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/graphFetch/tests/testGraphFetchEmbdded.pure @@ -93,14 +93,14 @@ function <> {serverVersion.start='v1_19_0'} meta::rel ); } -function <> {serverVersion.start='v1_19_0'} meta::relational::graphFetch::tests::embedded::testEmbeddedMappingQualifiedPropertyAccess(): Boolean[1] +function <> {serverVersion.start='v1_19_0'} meta::relational::graphFetch::tests::embedded::testEmbeddedMappingQualifiedPropertyAccess(): Boolean[1] { let tree = #{ Person { firstName, firm { legalName, - 'employeeByLastNameFirstName': employeeByLastNameFirstName('Smith') + nameAndAddress } } }#; @@ -111,9 +111,33 @@ function <> {serverVersion.start='v1_19_0 let result = execute($query, $mapping, $runtime, meta::relational::extension::relationalExtensions()).values; assertJsonStringsEqual( - '[{"firstName":"Peter","firm":{"legalName":"Firm X","employeeByLastNameFirstName":"Peter"}},' + - '{"firstName":"John","firm":{"legalName":"Firm X","employeeByLastNameFirstName":"Peter"}},' + - '{"firstName":"Fabrice","firm":{"legalName":"Firm A","employeeByLastNameFirstName":null}}]', + '[{"firstName":"Peter","firm":{"legalName":"Firm X","nameAndAddress()":"Firm X,200 west"}},' + + '{"firstName":"John","firm":{"legalName":"Firm X","nameAndAddress()":"Firm X,200 west"}},' + + '{"firstName":"Fabrice","firm":{"legalName":"Firm A","nameAndAddress()":"Firm A,3 somewhere"}}]', + $result + ); +} + + +function <> {serverVersion.start='v1_19_0'} meta::relational::graphFetch::tests::embedded::testEmbeddedMappingQualifiedPropertyAccess2(): Boolean[1] +{ + let tree = #{ + Person { + firstName, + firm { + legalName, + maxEmployeesAge + } + } + }#; + let query = {|Person.all()->graphFetch($tree)->serialize($tree)}; + let mapping = meta::relational::tests::mapping::embedded::model::mapping::testMappingEmbedded; + let runtime = meta::external::store::relational::tests::testRuntime(); + + let result = execute($query, $mapping, $runtime, meta::relational::extension::relationalExtensions()).values; + + assertJsonStringsEqual( + '{}', $result ); } diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/graphFetch/tests/testGraphFetchEmbeddedInline.pure b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/graphFetch/tests/testGraphFetchEmbeddedInline.pure new file mode 100644 index 00000000000..1698f5a92ef --- /dev/null +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/graphFetch/tests/testGraphFetchEmbeddedInline.pure @@ -0,0 +1,96 @@ +// Copyright 2023 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 meta::pure::executionPlan::profiles::*; +import meta::pure::graphFetch::execution::*; +import meta::relational::tests::mapping::embedded::advanced::model::*; + + +function <> meta::relational::graphFetch::tests::embedded::inline::setup(): Boolean[1] +{ + meta::relational::tests::mapping::embedded::advanced::setUp(); +} + + +function <> {serverVersion.start='v1_19_0'} meta::relational::graphFetch::tests::embedded::inline::testInlineEmbeddedMapping(): Boolean[1] +{ + let tree = #{ + Product { + name, + bondDetails { + description + } + } + }#; + let query = {|Product.all()->graphFetch($tree)->serialize($tree)}; + let mapping = meta::relational::tests::mapping::embedded::advanced::mapping::testMappingEmbedded; + let runtime = meta::external::store::relational::tests::testRuntime(); + + let result = execute($query, $mapping, $runtime, meta::relational::extension::relationalExtensions()).values; + + assertJsonStringsEqual( + '[{"name":"Product 1","bondDetails":{"description":"Bond 1"}},' + + '{"name":"Product 2","bondDetails":{"description":"Bond 2"}},' + + '{"name":"Product 3","bondDetails":{"description":"SuperBond 3 super"}}]', + $result + ); +} + +function <> {serverVersion.start='v1_19_0'} meta::relational::graphFetch::tests::embedded::inline::testQualifierWithArgs(): Boolean[1] +{ + let tree = #{ + Product { + name, + bondDetails { + 'duration': durationStartsWith('5') + } + } + }#; + let query = {|Product.all()->graphFetch($tree)->serialize($tree)}; + let mapping = meta::relational::tests::mapping::embedded::advanced::mapping::testMappingEmbedded; + let runtime = meta::external::store::relational::tests::testRuntime(); + + let result = execute($query, $mapping, $runtime, meta::relational::extension::relationalExtensions()).values; + + assertJsonStringsEqual( + '[{"name":"Product 1","bondDetails":{"duration":true}},' + + '{"name":"Product 2","bondDetails":{"duration":true}},' + + '{"name":"Product 3","bondDetails":{"duration":false}}]', + $result + ); +} + +function <> {serverVersion.start='v1_19_0'} meta::relational::graphFetch::tests::embedded::inline::testWithAssociationFromRootMappingWithFilter(): Boolean[1] +{ + let tree = #{ + Product { + name, + bondDetails { + bondClassification { + type + } + } + } + }#; + let query = {|Product.all()->filter(p|$p.name == 'Product 1')->graphFetch($tree)->serialize($tree)}; + let mapping = meta::relational::tests::mapping::embedded::advanced::mapping::testMappingEmbeddedParent; + let runtime = meta::external::store::relational::tests::testRuntime(); + + let result = execute($query, $mapping, $runtime, meta::relational::extension::relationalExtensions()).values; + + assertJsonStringsEqual( + '{"name":"Product 1","bondDetails":{"bondClassification":[{"type":"Corporate"}]}}', + $result + ); +} \ No newline at end of file diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/graphFetch/tests/testGraphFetchEmbeddedOtherwise.pure b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/graphFetch/tests/testGraphFetchEmbeddedOtherwise.pure new file mode 100644 index 00000000000..44b5b0176ce --- /dev/null +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/graphFetch/tests/testGraphFetchEmbeddedOtherwise.pure @@ -0,0 +1,319 @@ +// Copyright 2023 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 meta::pure::executionPlan::profiles::*; +import meta::pure::graphFetch::execution::*; +import meta::relational::tests::mapping::embedded::advanced::model::*; + + +function <> meta::relational::graphFetch::tests::embedded::otherwise::setup(): Boolean[1] +{ + meta::relational::tests::mapping::embedded::advanced::setUp(); +} + + +function <> {serverVersion.start='v1_19_0'} meta::relational::graphFetch::tests::embedded::otherwise::testOtherwiseEmbeddedMapping(): Boolean[1] +{ + let tree = #{ + Product { + name, + bondDetails { + description + } + } + }#; + let query = {|Product.all()->graphFetch($tree)->serialize($tree)}; + let mapping = meta::relational::tests::mapping::embedded::advanced::mapping::testMappingEmbeddedOtherwise; + let runtime = meta::external::store::relational::tests::testRuntime(); + + let result = execute($query, $mapping, $runtime, meta::relational::extension::relationalExtensions()).values; + + assertJsonStringsEqual( + '[{"name":"Product 1","bondDetails":{"description":"P 1"}},' + + '{"name":"Product 2","bondDetails":{"description":"P 2"}},' + + '{"name":"Product 3","bondDetails":{"description":"P 3"}}]', + $result + ); +} + +function <> {serverVersion.start='v1_19_0'} meta::relational::graphFetch::tests::embedded::otherwise::testOtherwiseEmbeddedMappingBothOtherwiseAndJoinProperty(): Boolean[1] +{ + let tree = #{ + Product { + name, + bondDetails { + type, + description + } + } + }#; + let query = {|Product.all()->graphFetch($tree)->serialize($tree)}; + let mapping = meta::relational::tests::mapping::embedded::advanced::mapping::testMappingEmbeddedOtherwise; + let runtime = meta::external::store::relational::tests::testRuntime(); + + let result = execute($query, $mapping, $runtime, meta::relational::extension::relationalExtensions()).values; + + assertJsonStringsEqual( + '[{"name":"Product 1","bondDetails":{"description":"P 1","type":"15 years"}},' + + '{"name":"Product 2","bondDetails":{"description":"P 2","type":"15 years"}},' + + '{"name":"Product 3","bondDetails":{"description":"P 3","type":"5 years"}}]', + $result + ); +} + +function <> {serverVersion.start='v1_19_0'} meta::relational::graphFetch::tests::embedded::otherwise::testOtherwiseGetterDeepTraversal(): Boolean[1] +{ + let tree = #{ + Product { + name, + bondDetails { + type, + description, + holder { + name + } + } + } + }#; + let query = {|Product.all()->graphFetch($tree)->serialize($tree)}; + let mapping = meta::relational::tests::mapping::embedded::advanced::mapping::testMappingEmbeddedOtherwise; + let runtime = meta::external::store::relational::tests::testRuntime(); + + let result = execute($query, $mapping, $runtime, meta::relational::extension::relationalExtensions()).values; + + assertJsonStringsEqual( + '[{"name":"Product 1","bondDetails":{"description":"P 1","holder":{"name":"Party 1"},"type":"15 years"}},' + + '{"name":"Product 2","bondDetails":{"description":"P 2","holder":{"name":"Party 2"},"type":"15 years"}},' + + '{"name":"Product 3","bondDetails":{"description":"P 3","holder":{"name":"Party 3"},"type":"5 years"}}]', + $result + ); +} + +function <> {serverVersion.start='v1_19_0'} meta::relational::graphFetch::tests::embedded::otherwise::testComplexPropertyOtherwiseGetterDeepTraversal(): Boolean[1] +{ + let tree = #{ + Product { + name, + bondDetails { + type, + description, + bondClassification { + type + }, + holder { + name + } + } + } + }#; + let query = {|Product.all()->graphFetch($tree)->serialize($tree)}; + let mapping = meta::relational::tests::mapping::embedded::advanced::mapping::testMappingEmbeddedOtherwise3; + let runtime = meta::external::store::relational::tests::testRuntime(); + + let result = execute($query, $mapping, $runtime, meta::relational::extension::relationalExtensions()).values; + + assertJsonStringsEqual( + '[{"name":"Product 1","bondDetails":{"description":"P 1","bondClassification":[{"type":"Corporate"}],"holder":{"name":"Party 1"},"type":"15 years"}},' + + '{"name":"Product 2","bondDetails":{"description":"P 2","bondClassification":[],"holder":{"name":"Party 2"},"type":"15 years"}},' + + '{"name":"Product 3","bondDetails":{"description":"P 3","bondClassification":[],"holder":{"name":"Party 3"},"type":"5 years"}}]', + $result + ); +} + +function <> {serverVersion.start='v1_19_0'} meta::relational::graphFetch::tests::embedded::otherwise::testOtherwiseEmbeddedToEmbedded(): Boolean[1] +{ + let tree = #{ + Product { + name, + bondDetails { + issuer { + name + } + } + } + }#; + let query = {|Product.all()->graphFetch($tree)->serialize($tree)}; + let mapping = meta::relational::tests::mapping::embedded::advanced::mapping::testMappingEmbeddedOtherwise; + let runtime = meta::external::store::relational::tests::testRuntime(); + + let result = execute($query, $mapping, $runtime, meta::relational::extension::relationalExtensions()).values; + + assertJsonStringsEqual( + '[{"name":"Product 1","bondDetails":{"issuer":{"name":"test"}}},' + + '{"name":"Product 2","bondDetails":{"issuer":{"name":"test"}}},' + + '{"name":"Product 3","bondDetails":{"issuer":{"name":"test"}}}]', + $result + ); +} + +function <> {serverVersion.start='v1_19_0'} meta::relational::graphFetch::tests::embedded::otherwise::testQualifierJoinProperty(): Boolean[1] +{ + let tree = #{ + Product { + name, + bondDetails { + duration + } + } + }#; + let query = {|Product.all()->graphFetch($tree)->serialize($tree)}; + let mapping = meta::relational::tests::mapping::embedded::advanced::mapping::testMappingEmbeddedOtherwise; + let runtime = meta::external::store::relational::tests::testRuntime(); + + let result = execute($query, $mapping, $runtime, meta::relational::extension::relationalExtensions()).values; + + assertJsonStringsEqual( + '[{"name":"Product 1","bondDetails":{"duration()":0}},' + + '{"name":"Product 2","bondDetails":{"duration()":0}},' + + '{"name":"Product 3","bondDetails":{"duration()":5}}]', + $result + ); +} + +function <> {serverVersion.start='v1_19_0'} meta::relational::graphFetch::tests::embedded::otherwise::testQualifierPropertyWithArgs(): Boolean[1] +{ + let tree = #{ + Product { + name, + bondDetails { + 'prefixedDescription': prefixedDescription('test: ') + } + } + }#; + let query = {|Product.all()->graphFetch($tree)->serialize($tree)}; + let mapping = meta::relational::tests::mapping::embedded::advanced::mapping::testMappingEmbeddedOtherwise; + let runtime = meta::external::store::relational::tests::testRuntime(); + + let result = execute($query, $mapping, $runtime, meta::relational::extension::relationalExtensions()).values; + + assertJsonStringsEqual( + '[{"name":"Product 1","bondDetails":{"prefixedDescription":"test: P 1"}},' + + '{"name":"Product 2","bondDetails":{"prefixedDescription":"test: P 2"}},' + + '{"name":"Product 3","bondDetails":{"prefixedDescription":"test: P 3"}}]', + $result + ); +} + +function <> {serverVersion.start='v1_19_0'} meta::relational::graphFetch::tests::embedded::otherwise::testQualifierPropertyExpressionWithEmbeddedPropertyandJoinProperty(): Boolean[1] +{ + let tree = #{ + Product { + name, + bondDetails { + fullName + } + } + }#; + let query = {|Product.all()->graphFetch($tree)->serialize($tree)}; + let mapping = meta::relational::tests::mapping::embedded::advanced::mapping::testMappingEmbeddedOtherwise; + let runtime = meta::external::store::relational::tests::testRuntime(); + + let result = execute($query, $mapping, $runtime, meta::relational::extension::relationalExtensions()).values; + + assertJsonStringsEqual( + '[{"name":"Product 1","bondDetails":{"fullName()":"15 years P 1"}},' + + '{"name":"Product 2","bondDetails":{"fullName()":"15 years P 2"}},' + + '{"name":"Product 3","bondDetails":{"fullName()":"5 years P 3"}}]', + $result + ); +} + +###Pure +import meta::pure::graphFetch::execution::*; +import meta::pure::executionPlan::profiles::*; +import meta::relational::tests::milestoning::*; + +function <> {serverVersion.start='v1_19_0'} meta::relational::graphFetch::tests::embedded::otherwise::testMilestoning(): Boolean[1] +{ + let tree = #{ + Product { + id, + name, + type, + classificationTypeStr + } + }#; + let query = {|Product.all(%2015-10-16)->graphFetch($tree)->serialize($tree)}; + let mapping = meta::relational::tests::milestoning::embedded::otherwiseMapping3; + let runtime = meta::external::store::relational::tests::testRuntime(); + + let result = execute($query, $mapping, $runtime, meta::relational::extension::relationalExtensions()).values; + + assertJsonStringsEqual( + '[{"name":"ProductName2","classificationTypeStr()":"STOCK","id":2,"type":"STOCK"},'+ + '{"name":"ProductName3","classificationTypeStr()":null,"id":3,"type":"OPTION"}]', + $result + ); +} + +function <> {serverVersion.start='v1_19_0'} meta::relational::graphFetch::tests::embedded::otherwise::testMilestoning2(): Boolean[1] +{ + let tree = #{ + Product { + id, + name, + type, + classification(%2015-10-16) { + type + } + } + }#; + let query = {|Product.all(%2015-10-16)->graphFetch($tree)->serialize($tree)}; + let mapping = meta::relational::tests::milestoning::embedded::otherwiseMapping3; + let runtime = meta::external::store::relational::tests::testRuntime(); + + let result = execute($query, $mapping, $runtime, meta::relational::extension::relationalExtensions()).values; + + assertJsonStringsEqual( + '[{"name":"ProductName2","classification(2015-10-16)":{"type":"STOCK"},"id":2,"type":"STOCK"},' + + '{"name":"ProductName3","classification(2015-10-16)":null,"id":3,"type":"OPTION"}]', + $result + ); +} + + +###Mapping +import meta::relational::tests::milestoning::*; +Mapping meta::relational::tests::milestoning::embedded::otherwiseMapping3 +( + meta::relational::tests::milestoning::Order : Relational{ + id : [db]OrderTable.id, + orderDate : [db]OrderTable.orderDate, + product : [db]@Order_Product, + cusipProduct : [db]@Order_CusipSynonym > [db]@Product_Synonym + } + + meta::relational::tests::milestoning::Product : Relational{ + id : [db]ProductTable.id, + name : [db]ProductTable.name, + type : [db]ProductTable.type, + synonyms : [db]@Product_Synonym, + orders : [db]@Order_Product, + classification + ( + type: [db]ProductTable.type + ) Otherwise([ProductClassification]:[db]@Product_Classification) + } + + meta::relational::tests::milestoning::ProductSynonym : Relational{ + synonym : [db]ProductSynonymTable.synonym, + type : [db]ProductSynonymTable.type + } + + meta::relational::tests::milestoning::ProductClassification[ProductClassification] : Relational{ + type : [db]ProductClassificationTable.type, + description : [db]ProductClassificationTable.type_description, + product : [db]@Product_Classification + } +) diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/pureToSQLQuery/pureToSQLQuery.pure b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/pureToSQLQuery/pureToSQLQuery.pure index 1dd9c25367d..e13bfee9e5d 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/pureToSQLQuery/pureToSQLQuery.pure +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/pureToSQLQuery/pureToSQLQuery.pure @@ -3350,7 +3350,6 @@ function meta::relational::functions::pureToSqlQuery::processGetAll(expression: if($setImpls->size()==1,| $processRootSetImpl->eval($setImpls->at(0)) ,| let milestoningContext = getMilestoningContextForAll($expression,$o, $parameters, $state, $vars, $context, $extensions); let union = buildUnion($setImpls, [], false, $state.inProject, $milestoningContext, $nodeId, $state, $context, $extensions); - let propMap = $setImpls->at(0)->cast(@RelationalInstanceSetImplementation)->dataTypePropertyMappings(); let newRoot = ^RootJoinTreeNode(alias = ^TableAlias(name='unionBase', relationalElement=$union)); let fullCols = $union.queries->at(0).columns->cast(@Alias).name->filter(n | $n != 'u_type'); ^SelectWithCursor( select = ^SelectSQLQuery( columns = ^Alias(name= 'u_type', relationalElement = ^TableAliasColumn(alias = $newRoot.alias, column = ^Column(name='u_type', type=^meta::relational::metamodel::datatype::Integer()))) diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/tests/mapping/embedded/testEmbeddedOtherwiseMapping.pure b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/tests/mapping/embedded/testEmbeddedOtherwiseMapping.pure index 438f497f8a0..5faf8ab1b3b 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/tests/mapping/embedded/testEmbeddedOtherwiseMapping.pure +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/tests/mapping/embedded/testEmbeddedOtherwiseMapping.pure @@ -21,6 +21,14 @@ import meta::relational::tests::mapping::embedded::advanced::mapping::*; import meta::relational::tests::mapping::embedded::advanced::model::*; import meta::relational::tests::mapping::embedded::advanced::*; + function <> meta::relational::tests::mapping::embedded::advanced::testProjectionOtherwise():Boolean[1] + { + let result = execute(|Product.all()->project([p| $p.name, p | $p.bondDetails.description], ['name', 'description']) + , testMappingEmbeddedOtherwise, testRuntime(), meta::relational::extension::relationalExtensions()); + + assertEquals('name,description\n' + 'Product 1,Bond 1\n' + 'Product 2,Bond 2\n' + 'Product 3,SuperBond 3 super\n', $result.values->toOne()->toCSV()); + assertEquals('select "root".PRODUCT_NAME as "name", "root".BOND_DETAILS as "description" from PRODUCT_DENORM as "root"', $result->sqlRemoveFormatting()); + } function <> meta::relational::tests::mapping::embedded::advanced::otherwiseTestFilter():Boolean[1] { @@ -60,6 +68,22 @@ function <> meta::relational::tests::mapping::embe assertEquals('Party 3', $result3.values->at(0).bondDetails.holder.name); } + function <> meta::relational::tests::mapping::embedded::advanced::testProjectionOtherwiseDeepTraversal():Boolean[1] + { + let result = execute(|Product.all()->project([p | $p.bondDetails.holder.name], ['holder']) + , testMappingEmbeddedOtherwise, testRuntime(), meta::relational::extension::relationalExtensions()); + + assertEquals('select "party_0".name as "holder" from PRODUCT_DENORM as "root" left outer join BOND_DETAIL as "bond_detail_0" on ("root".PRODUCT_ID = "bond_detail_0".BOND_ID) left outer join Party as "party_0" on ("bond_detail_0".HOLDERID = "party_0".id)', $result->sqlRemoveFormatting()); + } + + function <> meta::relational::tests::mapping::embedded::advanced::testProjectionOtherwiseNonPrimitive():Boolean[1] + { + let result = execute(|Product.all()->project([p | $p.name, p | $p.bondDetails.holder.name, p | $p.bondDetails.bondClassification.type], ['name', 'holder', 'type']) + , testMappingEmbeddedOtherwise3, testRuntime(), meta::relational::extension::relationalExtensions()); + + assertEquals('select "root".PRODUCT_NAME as "name", "party_0".name as "holder", "bondclassificationtable_0".type as "type" from PRODUCT_DENORM as "root" left outer join BOND_DETAIL as "bond_detail_0" on ("root".PRODUCT_ID = "bond_detail_0".BOND_ID) left outer join Party as "party_0" on ("bond_detail_0".HOLDERID = "party_0".id) left outer join BondClassificationTable as "bondclassificationtable_0" on ("root".PRODUCT_ID = "bondclassificationtable_0".PRODUCT_ID)', $result->sqlRemoveFormatting()); + assertEquals('name,holder,type\n' + 'Product 1,Party 1,Corporate\n' + 'Product 2,Party 2,\n' + 'Product 3,Party 3,\n', $result.values->toOne()->toCSV()); + } function <> meta::relational::tests::mapping::embedded::advanced::otherwiseTestProjection():Boolean[1] { @@ -290,7 +314,7 @@ Mapping meta::relational::tests::mapping::embedded::advanced::mapping::testMappi ) } - + BondDetail[bondMapping2]: Relational { scope([eDB]BOND_DETAIL) @@ -309,7 +333,6 @@ Mapping meta::relational::tests::mapping::embedded::advanced::mapping::testMappi { name : [eDB]Party.name } - ) Mapping meta::relational::tests::mapping::embedded::advanced::mapping::testMappingEmbeddedOtherwise2 @@ -359,6 +382,50 @@ Mapping meta::relational::tests::mapping::embedded::advanced::mapping::testMappi ) +Mapping meta::relational::tests::mapping::embedded::advanced::mapping::testMappingEmbeddedOtherwise3 +( + + Product[pMapping1]: Relational + { + scope([eDB]PRODUCT_DENORM) + ( + name: PRODUCT_NAME, + market: MARKET_NAME, + bondDetails + ( + description:BOND_DETAILS, + bondClassification:[eDB]@BondDetailBondClassification + ) Otherwise([bondMapping2]:@BondDetailJoin) + ) + } + + + BondDetail[bondMapping2]: Relational + { + scope([eDB]BOND_DETAIL) + ( + description:NOT_SO_GOOD_DETAIL, + type: TYPE, + issuer + ( + name : 'test' + ), + holder:[eDB]@BondDetailPartyJoin, + bondClassification: [eDB]@BondDetailJoin > [eDB]@BondDetailBondClassification + ) + } + + Party : Relational + { + name : [eDB]Party.name + } + + BondClassification : Relational + { + type: [eDB]BondClassificationTable.type + } +) + Mapping meta::relational::tests::mapping::embedded::advanced::mapping::testMappingEmbeddedOtherwiseWithUnion ( From 7ea528383b7201a3d4030156268d211a6f6ca023 Mon Sep 17 00:00:00 2001 From: "Girdhar, Tanuj [AM Public]" Date: Sat, 25 Nov 2023 07:16:56 -0500 Subject: [PATCH 2/3] milestoning --- .../pure/graphFetch/graphFetch_routing.pure | 2 +- .../core/pure/router/store/builder.pure | 4 +- .../graphFetch/relationalGraphFetch.pure | 4 +- .../tests/testGraphFetchEmbdded.pure | 23 ++++ .../testGraphFetchEmbeddedOtherwise.pure | 119 ++++++++++++++++-- 5 files changed, 136 insertions(+), 16 deletions(-) diff --git a/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/graphFetch/graphFetch_routing.pure b/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/graphFetch/graphFetch_routing.pure index 2ecc956ecbc..1842b88ff2c 100644 --- a/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/graphFetch/graphFetch_routing.pure +++ b/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/graphFetch/graphFetch_routing.pure @@ -65,7 +65,7 @@ function meta::pure::graphFetch::routing::propertyMappingInfo(prop: PropertyGrap let fe = $routedProperty->byPassRouterInfo()->cast(@FunctionExpression); let sourceSets = if($prop.subType->isEmpty(), | $fe, | $fe.parametersValues->evaluateAndDeactivate()->at(0)->byPassRouterInfo()->cast(@FunctionExpression)).parametersValues->evaluateAndDeactivate()->at(0)->cast(@StoreMappingRoutedValueSpecification).sets->resolveOperation($mapping)->cast(@InstanceSetImplementation); $sourceSets->map({ss | - let propMaps = $ss->propertyMappingsByPropertyName($property.name->toOne())->filter(x | $x.targetSetImplementationId->in($targetSets.id)); + let propMaps = $ss->_propertyMappingsByPropertyName($property.name->toOne())->filter(x | $x.targetSetImplementationId->in($targetSets.id)); $propMaps->map(pm | $mapping->classMappingById($pm.targetSetImplementationId)->resolveOperation($mapping)->map(ts | ^$pm(targetSetImplementationId = $ts.id))); });, | $propertyMappings diff --git a/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/router/store/builder.pure b/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/router/store/builder.pure index 476c924d877..ed44652f0bb 100644 --- a/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/router/store/builder.pure +++ b/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/router/store/builder.pure @@ -138,8 +138,8 @@ function meta::pure::router::store::routing::build(v:ValueSpecification[1], l:Li |$s->cast(@InstanceSetImplementation)->meta::pure::mapping::propertyMappingsByPropertyName($propertyName), |$resWithAssoc); - let withOtherwise = if($res->isEmpty(), // for graphFetch flow, the parent set gets resolved to the otherwiseProperty mapping always. - | let byName = $s->cast(@InstanceSetImplementation)->meta::pure::mapping::propertyMappingsByPropertyName($propertyName)->filter(pm|$pm->instanceOf(OtherwiseEmbeddedSetImplementation))->map(pm|$pm->cast(@OtherwiseEmbeddedSetImplementation)); + let withOtherwise = if($res->isEmpty() && $f.func->instanceOf(Property), // for graphFetch flow, the parent set gets resolved to the otherwiseProperty mapping always. + | let byName = $s->cast(@InstanceSetImplementation)->meta::pure::mapping::_propertyMappingsByPropertyName($propertyName)->filter(pm|$pm->instanceOf(OtherwiseEmbeddedSetImplementation))->map(pm|$pm->cast(@OtherwiseEmbeddedSetImplementation)); let pms = $byName.otherwisePropertyMapping->filter(pm|$pm.targetSetImplementationId->in($targetIds)); $pms;, | $res ); diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/graphFetch/relationalGraphFetch.pure b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/graphFetch/relationalGraphFetch.pure index ca22dbd6ed4..ca2a0b47334 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/graphFetch/relationalGraphFetch.pure +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/graphFetch/relationalGraphFetch.pure @@ -766,7 +766,7 @@ function <> meta::relational::graphFetch::executionPlan::generat let res = if ($isQualified, {| let newVars = newVarsForMilestoningContext($propTree, $inScopeVars); - let updatedState = ^$pureToSqlState(inGetterFlow = true, qualifierBase=^OperationWithParentPropertyMapping(element = $base), inScopeVars = $pureToSqlState.inScopeVars->putAll($newVars)); + let updatedState = ^$pureToSqlState(inGetterFlow = true, milestoningUseOtherwise = true, qualifierBase=^OperationWithParentPropertyMapping(element = $base), inScopeVars = $pureToSqlState.inScopeVars->putAll($newVars)); processQualifiedProperty($propTree.property->cast(@QualifiedProperty), [], $base, ^Map(), $updatedState, JoinType.LEFT_OUTER, '_gftq', ^List(), $debug, $extensions).element->cast(@SelectWithCursor); }, {| @@ -796,7 +796,7 @@ function meta::relational::graphFetch::executionPlan::generateNonPrimitiveProper let newVars = newVarsForMilestoningContext($propTree, $inScopeVars); let mcForProperty = milestoningContextFromPropertyTree($propTree, $parentTree, $mc, ^$pureToSqlState(inScopeVars = $pureToSqlState.inScopeVars->putAll($newVars)), $debug->indent(), $extensions); let baseWithMc = ^$base(milestoningContext = $mcForProperty); - let updatedState = ^$pureToSqlState(inGetterFlow = true, qualifierBase = ^OperationWithParentPropertyMapping(element = $baseWithMc), inScopeVars = $pureToSqlState.inScopeVars->putAll($newVars)); + let updatedState = ^$pureToSqlState(inGetterFlow = true, milestoningUseOtherwise = true, qualifierBase = ^OperationWithParentPropertyMapping(element = $baseWithMc), inScopeVars = $pureToSqlState.inScopeVars->putAll($newVars)); let withQualifier = processQualifiedProperty($propTree.property->cast(@QualifiedProperty), [], $baseWithMc, ^Map(), $updatedState, JoinType.LEFT_OUTER, '_gftq', ^List(), $debug, $extensions).element->cast(@SelectWithCursor); let newSelect = $withQualifier.select->pushFilters($extensions); let innerRes = ^$withQualifier(select = ^$newSelect(leftSideOfFilter = [])); diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/graphFetch/tests/testGraphFetchEmbdded.pure b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/graphFetch/tests/testGraphFetchEmbdded.pure index de658ef175a..153a14122a7 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/graphFetch/tests/testGraphFetchEmbdded.pure +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/graphFetch/tests/testGraphFetchEmbdded.pure @@ -141,3 +141,26 @@ function <> {serverVersion.start='v1_19_0 $result ); } + +function <> {serverVersion.start='v1_19_0'} meta::relational::graphFetch::tests::embedded::testEmbeddedMappingQualifiedPropertyAccessWithArgs(): Boolean[1] +{ + let tree = #{ + Person { + firstName, + firm { + legalName, + 'employeeByLastNameFirstName': employeeByLastNameFirstName('Smith') + } + } + }#; + let query = {|Person.all()->graphFetch($tree)->serialize($tree)}; + let mapping = meta::relational::tests::mapping::embedded::model::mapping::testMappingEmbedded; + let runtime = meta::external::store::relational::tests::testRuntime(); + + let result = execute($query, $mapping, $runtime, meta::relational::extension::relationalExtensions()).values; + + assertJsonStringsEqual( + '{}', + $result + ); +} \ No newline at end of file diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/graphFetch/tests/testGraphFetchEmbeddedOtherwise.pure b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/graphFetch/tests/testGraphFetchEmbeddedOtherwise.pure index 44b5b0176ce..19f1dacf050 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/graphFetch/tests/testGraphFetchEmbeddedOtherwise.pure +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-pure/src/main/resources/core_relational/relational/graphFetch/tests/testGraphFetchEmbeddedOtherwise.pure @@ -20,9 +20,10 @@ import meta::relational::tests::mapping::embedded::advanced::model::*; function <> meta::relational::graphFetch::tests::embedded::otherwise::setup(): Boolean[1] { meta::relational::tests::mapping::embedded::advanced::setUp(); + meta::relational::tests::milestoning::initDatabase(); + true; } - function <> {serverVersion.start='v1_19_0'} meta::relational::graphFetch::tests::embedded::otherwise::testOtherwiseEmbeddedMapping(): Boolean[1] { let tree = #{ @@ -234,7 +235,105 @@ import meta::pure::graphFetch::execution::*; import meta::pure::executionPlan::profiles::*; import meta::relational::tests::milestoning::*; -function <> {serverVersion.start='v1_19_0'} meta::relational::graphFetch::tests::embedded::otherwise::testMilestoning(): Boolean[1] + +function <> {serverVersion.start='v1_19_0'} meta::relational::graphFetch::tests::embedded::otherwise::testMilestonedPropertyAllVersions(): Boolean[1] +{ + let tree = #{ + Order { + id, + productAllVersions{ + name, + type + } + } + }#; + let query = {|Order.all()->graphFetch($tree)->serialize($tree)}; + let mapping = meta::relational::tests::milestoning::embedded::otherwiseMapping3; + let runtime = meta::external::store::relational::tests::testRuntime(); + + let result = execute($query, $mapping, $runtime, meta::relational::extension::relationalExtensions()).values; + + assertJsonStringsEqual( + '[{"id":1, "productAllVersions":[{"name":"ProductName","type":"STOCK"}]},'+ + '{"id":2,"productAllVersions":[{"name":"ProductName1","type":"STOCK"},{"name":"ProductName2","type":"STOCK"}]}]', + $result + ); +} + +function <> {serverVersion.start='v1_19_0'} meta::relational::graphFetch::tests::embedded::otherwise::testMilestonedRootWithMilestonedPropertyAllVersions(): Boolean[1] +{ + let tree = #{ Product{ + id, + name, + synonymsAllVersions{ + synonym + } + }}#; + let query = {|Product.all(%2023-10-15T00:00:00)->graphFetch($tree)->serialize($tree)}; + let mapping = meta::relational::tests::milestoning::embedded::otherwiseMapping3; + let runtime = meta::external::store::relational::tests::testRuntime(); + + let result = execute($query, $mapping, $runtime, meta::relational::extension::relationalExtensions()).values; + + assertJsonStringsEqual( + '[{"id":2,"name":"ProductName2","synonymsAllVersions":[{"synonym":"GS-Mod-S0"},{"synonym":"GS-Mod-S1"},{"synonym":"GS-Mod-S2"},{"synonym":"GS-Mod-S3"}]},' + + ' {"id":3,"name":"ProductName3","synonymsAllVersions":[]}]', + $result + ); +} + +function <> {serverVersion.start='v1_19_0'} meta::relational::graphFetch::tests::embedded::otherwise::testMilestonedRootAndMilestonedProperty(): Boolean[1] +{ + let tree = #{Product{ + id, + name, + synonyms(%2023-10-15T00:00:00) + { + synonym + } + }}#; + let query = {|Product.all(%2023-10-15T00:00:00)->graphFetch($tree)->serialize($tree)}; + let mapping = meta::relational::tests::milestoning::embedded::otherwiseMapping3; + let runtime = meta::external::store::relational::tests::testRuntime(); + + + let result = execute($query, $mapping, $runtime, meta::relational::extension::relationalExtensions()).values; + + assertJsonStringsEqual( + '[{"id":2,"name":"ProductName2","synonyms(2023-10-15T00:00:00+0000)":[{"synonym":"GS-Mod-S1"},{"synonym":"GS-Mod-S3"}]},' + + ' {"id":3,"name":"ProductName3","synonyms(2023-10-15T00:00:00+0000)":[]}]"' + ,$result); +} + +function <> {serverVersion.start='v1_19_0'} meta::relational::graphFetch::tests::embedded::otherwise::testMultiLevelMilestoning(): Boolean[1] +{ + let tree = #{ + Order { + id, + product(%2015-10-16) { + id, + name, + type, + classification(%2015-10-16) { + type + } + } + } + }#; + let query = {|Order.all()->graphFetch($tree)->serialize($tree)}; + let mapping = meta::relational::tests::milestoning::embedded::otherwiseMapping3; + let runtime = meta::external::store::relational::tests::testRuntime(); + + let result = execute($query, $mapping, $runtime, meta::relational::extension::relationalExtensions()).values; + + assertJsonStringsEqual( + '[{"id":1,"product(2015-10-16)":[]},' + + '{"id":2,"product(2015-10-16)":[{"name":"ProductName2","classification(2015-10-16)":{"type":"STOCK"},"id":2,"type":"STOCK"}]}]', + $result + ); +} + +function <> {serverVersion.start='v1_19_0'} meta::relational::graphFetch::tests::embedded::otherwise::testMilestonedClassAtRootWithQualifierBD(): Boolean[1] { let tree = #{ Product { @@ -257,27 +356,25 @@ function <> {serverVersion.start='v1_19_0'} meta::rel ); } -function <> {serverVersion.start='v1_19_0'} meta::relational::graphFetch::tests::embedded::otherwise::testMilestoning2(): Boolean[1] +function <> {serverVersion.start='v1_19_0'} meta::relational::graphFetch::tests::embedded::otherwise::testMilestonedClassAtRootWithQualifierNormal(): Boolean[1] { let tree = #{ Product { id, name, type, - classification(%2015-10-16) { - type - } + classificationTypeStr } }#; let query = {|Product.all(%2015-10-16)->graphFetch($tree)->serialize($tree)}; - let mapping = meta::relational::tests::milestoning::embedded::otherwiseMapping3; + let mapping = meta::relational::tests::milestoning::milestoningmap; let runtime = meta::external::store::relational::tests::testRuntime(); let result = execute($query, $mapping, $runtime, meta::relational::extension::relationalExtensions()).values; assertJsonStringsEqual( - '[{"name":"ProductName2","classification(2015-10-16)":{"type":"STOCK"},"id":2,"type":"STOCK"},' + - '{"name":"ProductName3","classification(2015-10-16)":null,"id":3,"type":"OPTION"}]', + '[{"name":"ProductName2","classificationTypeStr()":"STOCK","id":2,"type":"STOCK"},'+ + '{"name":"ProductName3","classificationTypeStr()":null,"id":3,"type":"OPTION"}]', $result ); } @@ -303,7 +400,7 @@ Mapping meta::relational::tests::milestoning::embedded::otherwiseMapping3 classification ( type: [db]ProductTable.type - ) Otherwise([ProductClassification]:[db]@Product_Classification) + ) Otherwise([meta_relational_tests_milestoning_ProductClassification]:[db]@Product_Classification) } meta::relational::tests::milestoning::ProductSynonym : Relational{ @@ -311,7 +408,7 @@ Mapping meta::relational::tests::milestoning::embedded::otherwiseMapping3 type : [db]ProductSynonymTable.type } - meta::relational::tests::milestoning::ProductClassification[ProductClassification] : Relational{ + meta::relational::tests::milestoning::ProductClassification[meta_relational_tests_milestoning_ProductClassification] : Relational{ type : [db]ProductClassificationTable.type, description : [db]ProductClassificationTable.type_description, product : [db]@Product_Classification From d9d0ba00ba0ecae07882b8af4ce6a1b408e44cda Mon Sep 17 00:00:00 2001 From: "Girdhar, Tanuj [AM Public]" Date: Tue, 28 Nov 2023 01:28:10 -0500 Subject: [PATCH 3/3] remove import --- .../resources/core/pure/graphFetch/graphFetch_routing.pure | 4 ---- 1 file changed, 4 deletions(-) diff --git a/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/graphFetch/graphFetch_routing.pure b/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/graphFetch/graphFetch_routing.pure index 1842b88ff2c..c5d1ad201be 100644 --- a/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/graphFetch/graphFetch_routing.pure +++ b/legend-engine-pure/legend-engine-pure-code/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/graphFetch/graphFetch_routing.pure @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -import meta::relational::mapping::*; import meta::pure::router::store::routing::*; import meta::pure::lineage::scanProperties::*; import meta::pure::milestoning::*; @@ -70,9 +69,6 @@ function meta::pure::graphFetch::routing::propertyMappingInfo(prop: PropertyGrap });, | $propertyMappings ); - - - ^PropertyMappingInfo(property=$property, propertyMappings=$resolvedPropertyMappings, sets=$sets);); }