diff --git a/legend-engine-core/legend-engine-core-pure/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/binding/executionPlan/executionPlan_generation.pure b/legend-engine-core/legend-engine-core-pure/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/binding/executionPlan/executionPlan_generation.pure index daba5b5336f..66bb88459d3 100644 --- a/legend-engine-core/legend-engine-core-pure/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/binding/executionPlan/executionPlan_generation.pure +++ b/legend-engine-core/legend-engine-core-pure/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/binding/executionPlan/executionPlan_generation.pure @@ -252,7 +252,12 @@ function meta::external::format::shared::executionPlan::extractPackageableElemen )->concatenate($p.subType), s:SubTypeGraphFetchTree[1] | $s.subTypeClass ])->cast(@PackageableElement); - $classesFromTree->concatenate($tree.subTrees->map(s | $s->extractPackageableElementFromTree()))->concatenate($tree.subTypeTrees->map(s | $s->extractPackageableElementFromTree())); + let specializations = $classesFromTree->filter(c | $c->instanceOf(Class))->map(c | $c->cast(@Class)->meta::pure::functions::meta::findAllSpecializations())->filter(x | $x->elementToPath() != Any->elementToPath()); + let generalizations = $classesFromTree->filter(c | $c->instanceOf(Class))->map(c | $c->cast(@Class)->meta::pure::functions::meta::getAllTypeGeneralisations())->filter(x | $x->elementToPath() != Any->elementToPath()) + ->filter(x | $x->instanceOf(PackageableElement))->cast(@PackageableElement); + let currentLevelClasses = $classesFromTree->concatenate($specializations)->concatenate($generalizations)->removeDuplicates({a, b | $a->elementToPath() == $b->elementToPath()}); + + $currentLevelClasses->concatenate($tree.subTrees->map(s | $s->extractPackageableElementFromTree()))->concatenate($tree.subTypeTrees->map(s | $s->extractPackageableElementFromTree())); } function <> meta::external::format::shared::executionPlan::getFunctionProcessor(f:SimpleFunctionExpression[1], extensions:meta::pure::extension::Extension[*]):meta::pure::metamodel::function::Function<{FunctionExpression[1], ExternalFormatPlanGenerationState[1], Extension[*], DebugContext[1] -> ExecutionNode[1]}>[1] diff --git a/legend-engine-xts-json/legend-engine-xt-json-pure/src/main/resources/core_external_format_json/executionPlan/tests/simple.pure b/legend-engine-xts-json/legend-engine-xt-json-pure/src/main/resources/core_external_format_json/executionPlan/tests/simple.pure index c62d46f16e0..4e33245688e 100644 --- a/legend-engine-xts-json/legend-engine-xt-json-pure/src/main/resources/core_external_format_json/executionPlan/tests/simple.pure +++ b/legend-engine-xts-json/legend-engine-xt-json-pure/src/main/resources/core_external_format_json/executionPlan/tests/simple.pure @@ -147,6 +147,15 @@ function <> meta::external::format::json::executionPlan::test::simple::testSimpleJsonQueryWithChildSubType(): Boolean[1] +{ + let query = {data:String[1]| Target.all()->graphFetch(#{Target{targetProductId}}#)->serialize(#{Target{targetProductId}}#)->from(M2MMappingWithChild, Source->getRuntimeWithModelQueryConnection('application/json', $data))}; + + let result = meta::external::format::json::executionPlan::test::executeJsonSchemaBindingQuery($query, pair('data', '{"@type": "Source", "child": {"@type": "ProductExtended", "productId": "123"}}')); + + assertEquals('{"builder":{"_type":"json"},"values":{"targetProductId":"123"}}', $result); +} + function <> meta::external::format::json::executionPlan::test::simple::testM2MChainingWithJson(): Boolean[1] { let binding = getTestBinding(); @@ -357,6 +366,20 @@ Class meta::external::format::json::executionPlan::test::simple::Product description: String[1]; } +Class meta::external::format::json::executionPlan::test::simple::ProductExtended extends meta::external::format::json::executionPlan::test::simple::Product +{ +} + +Class meta::external::format::json::executionPlan::test::simple::Target +{ + targetProductId: String[1]; +} + +Class meta::external::format::json::executionPlan::test::simple::Source +{ + child: meta::external::format::json::executionPlan::test::simple::Product[1]; +} + Class meta::external::format::json::executionPlan::test::simple::Synonym { name: String[1]; @@ -507,6 +530,15 @@ Mapping meta::external::format::json::executionPlan::test::simple::M2MMapping2 } ) +Mapping meta::external::format::json::executionPlan::test::simple::M2MMappingWithChild +( + meta::external::format::json::executionPlan::test::simple::Target: Pure + { + ~src meta::external::format::json::executionPlan::test::simple::Source + targetProductId: $src.child.productId + } +) + Mapping meta::external::format::json::executionPlan::test::simple::M2MCrossStoreMapping ( meta::external::format::json::executionPlan::test::simple::Trade[trade_set]: Pure