Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
core.pure.graphFetch.graphFetchExecutionPlan.pure Maven / Gradle / Ivy
// Copyright 2020 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::router::store::metamodel::*;
import meta::pure::dataQuality::*;
import meta::pure::graphFetch::*;
import meta::pure::store::*;
import meta::pure::extension::*;
import meta::pure::graphFetch::routing::*;
import meta::pure::graphFetch::execution::*;
import meta::pure::graphFetch::executionPlan::*;
import meta::pure::executionPlan::*;
import meta::pure::executionPlan::toString::*;
import meta::pure::mapping::*;
import meta::external::store::model::*;
import meta::pure::mapping::modelToModel::graphFetch::executionPlan::*;
import meta::pure::mapping::xStore::*;
import meta::core::runtime::*;
import meta::pure::router::metamodel::*;
import meta::pure::router::utils::*;
Class <> meta::pure::graphFetch::executionPlan::GlobalGraphFetchExecutionNode extends ExecutionNode
{
graphFetchTree : ClusteredGraphFetchTree[1];
children : GlobalGraphFetchExecutionNode[*];
localGraphFetchExecutionNode : LocalGraphFetchExecutionNode[1];
parentIndex : Integer[0..1];
enableConstraints : Boolean[0..1];
checked : Boolean[0..1];
localTreeIndices : Integer[*];
dependencyIndices : Integer[*];
}
Class meta::pure::graphFetch::executionPlan::StoreMappingGlobalGraphFetchExecutionNode extends GlobalGraphFetchExecutionNode
{
store : meta::pure::store::Store[1];
xStorePropertyMapping : meta::pure::mapping::xStore::XStorePropertyMapping[0..1];
xStorePropertyFetchDetails : XStorePropertyFetchDetails[0..1];
}
Class meta::pure::graphFetch::executionPlan::XStorePropertyFetchDetails
{
supportsCaching : Boolean[1];
propertyPath : String[1];
sourceMappingId : String[1];
sourceSetId : String[1];
targetMappingId : String[1];
targetSetId : String[1];
targetPropertiesOrdered : String[*];
subTree : String[1];
}
Class meta::pure::graphFetch::executionPlan::PlatformGlobalGraphFetchExecutionNode extends GlobalGraphFetchExecutionNode
{
}
Class meta::pure::graphFetch::executionPlan::LocalGraphFetchExecutionNode extends ExecutionNode
{
nodeIndex : Integer[1];
parentIndex : Integer[0..1];
graphFetchTree : RoutedGraphFetchTree[1];
}
Class meta::pure::graphFetch::executionPlan::PlatformPrimitiveQualifierLocalGraphFetchExecutionNode extends LocalGraphFetchExecutionNode
{
}
Class meta::pure::graphFetch::executionPlan::StoreMappingLocalGraphFetchExecutionNodeGenerationInput
{
clusteredTree: StoreMappingClusteredGraphFetchTree[1];
orderedPaths: String[*];
enableConstraints: Boolean[1];
checked: Boolean[1];
storeQuery: StoreQuery[1];
ext: RoutedValueSpecification[0..1];
mapping: Mapping[1];
runtime: Runtime[1];
exeCtx: meta::pure::runtime::ExecutionContext[1];
extensions: Extension[*];
debug: DebugContext[1];
}
Class meta::pure::graphFetch::executionPlan::StoreMappingCrossLocalGraphFetchExecutionNodeGenerationInput
{
clusteredTree: StoreMappingClusteredGraphFetchTree[1];
orderedPaths: String[*];
parentPath: String[1];
enableConstraints: Boolean[1];
checked: Boolean[1];
inScopeVars: Map>[1];
mapping: Mapping[1];
runtime: Runtime[1];
exeCtx: meta::pure::runtime::ExecutionContext[1];
extensions: Extension[*];
debug: DebugContext[1];
}
function meta::pure::graphFetch::executionPlan::nodeIsMerged(node:LocalGraphFetchExecutionNode[1]): Boolean[1]
{
let set = $node.graphFetchTree.sets;
let mergeOp = $set->filter(m|$m->instanceOf(OperationSetImplementation))->cast(@OperationSetImplementation)->filter(o|$o.operation==meta::pure::router::operations::merge_OperationSetImplementation_1__SetImplementation_MANY_);
$mergeOp->map(m | assert($m->instanceOf(MergeOperationSetImplementation),'Please specify a merge function for merge operation on class '+ $m.class->elementToPath()));
$mergeOp->isNotEmpty();
}
function meta::pure::graphFetch::executionPlan::planGraphFetchExecution(sq: StoreQuery[1], ext: RoutedValueSpecification[0..1], mapping: Mapping[1], runtime: Runtime[1], exeCtx: meta::pure::runtime::ExecutionContext[1], extensions: Extension[*], debug: DebugContext[1]): ExecutionNode[1]
{
print(if($debug.debug,|$debug.space+'>Generating Graph Fetch Execution Plan:\n',|''));
let fe = $sq.fe->evaluateAndDeactivate();
let resultSize = $fe.parametersValues->evaluateAndDeactivate()->at(0)->match([rvs:ExtendedRoutedValueSpecification[1] | $rvs.value.multiplicity->toOne(),
vs: ValueSpecification[1] | $fe.multiplicity->toOne()]);
assert($fe.func->in(graphFetchFunctions()) || $fe->isUnionOnGraphFetch(true));
let clusteredTreePreFilter = $fe.parametersValues->evaluateAndDeactivate()->at(1)->cast(@InstanceValue).values->at(0)->cast(@ClusteredGraphFetchTree);
let chainConnection = if ($sq.store->instanceOf(ModelStore),
| $runtime.connectionStores->filter(c|$c.element->instanceOf(ModelStore) && $c.connection->instanceOf(ModelChainConnection)).connection;,
| []
);
let possibleFilter = $fe->graphFetchFilter()->evaluateAndDeactivate();
let clusteredTree = if($possibleFilter->isNotEmpty() && $sq.store-> instanceOf(ModelStore) && $chainConnection->isEmpty(),
|meta::pure::graphFetch::executionPlan::enrichTargetTreeForFilterProperties($clusteredTreePreFilter,$possibleFilter->toOne(),$mapping, $exeCtx,$runtime,$extensions,$debug);,
|$clusteredTreePreFilter
);
print(if($debug.debug,|$debug.space+' Clustered Tree: '+$clusteredTree->asString(false)+'\n',|''));
let orderedPaths = $clusteredTree->getPathsOrdered();
let clusterTreesWithParents = $clusteredTree->findAllClusterTreesWithParents([]);
print(if($debug.debug,|$debug.space+' Found '+$clusterTreesWithParents->size()->toString()+' store-mapping/platform cluster tree(s) in main clustered tree\n',|''));
let rootTree = $clusterTreesWithParents->filter(x | $x.second.values->isEmpty()).first->toOne()->cast(@StoreMappingClusteredGraphFetchTree);
let rootTreeOneCluster = $rootTree->recursivelyRemoveClusterTrees();
print(if($debug.debug,|$debug.space+' >Generating store local node for root tree\n',|''));
print(if($debug.debug,|$debug.space+' Store local tree: '+$rootTreeOneCluster->asString(false)+'\n',|''));
let enableConstraints = $exeCtx.enableConstraints->isEmpty() || $exeCtx.enableConstraints->toOne();
let checked = $fe.genericType.rawType == Checked;
let localNodeGenerationInput = ^StoreMappingLocalGraphFetchExecutionNodeGenerationInput
(
clusteredTree = $rootTreeOneCluster->cast(@StoreMappingClusteredGraphFetchTree),
orderedPaths = $orderedPaths,
enableConstraints = $enableConstraints,
checked = $checked,
storeQuery = $sq,
ext = $ext,
mapping = $mapping,
runtime = $runtime,
exeCtx = $exeCtx,
extensions = $extensions,
debug = $debug->indent(3)
);
let localRoot = $rootTree.s.planGraphFetchExecution->toOne()->eval($localNodeGenerationInput);
let rootGlobalNode = ^StoreMappingGlobalGraphFetchExecutionNode
(
resultType = $clusteredTree->resultTypeFromGraphFetchTree(),
resultSizeRange = $resultSize,
graphFetchTree = $clusteredTree,
store = $rootTree.store,
localGraphFetchExecutionNode = $localRoot,
enableConstraints = $enableConstraints,
checked = $checked,
localTreeIndices = $rootTreeOneCluster->getPathsOrdered()->map(p | let idx = $orderedPaths->indexOf($p); assert($idx >= 0, | 'Path ' + $p + ' not found in orderedPaths: ' + $orderedPaths->makeString('[', ', ', ']')); $idx;)
);
print(if($debug.debug,|$debug.space+' >Generated store local node for root tree\n',|''));
$rootGlobalNode->addCrossStoreChildren([], $rootTree, $orderedPaths, $clusterTreesWithParents, $sq.inScopeVars, $mapping, $runtime, $exeCtx, $enableConstraints, $checked, $extensions, $debug->indent(2));
}
function meta::pure::graphFetch::executionPlan::enrichTargetTreeForFilterProperties(originalTree: ClusteredGraphFetchTree[1], fe: SimpleFunctionExpression[1], mapping: Mapping[1], context:meta::pure::runtime::ExecutionContext[1] ,runtime: Runtime[1], extensions: meta::pure::extension::Extension[*], debug: DebugContext[1]): ClusteredGraphFetchTree[1]
{
let class = $originalTree.tree->cast(@RoutedRootGraphFetchTree).class;
let tree = $originalTree.tree->meta::pure::graphFetch::ensureFunctionRequirementsFromLambda($class,$fe->toOne().parametersValues->at(1)->cast(@FunctionRoutedValueSpecification).originalFunction,[],true)->cast(@RootGraphFetchTree);
let routedTrees = $tree->deepByPassRouterInfo()->cast(@RootGraphFetchTree)->routeRootGraphFetchTree($originalTree.tree.sets->at(0),$mapping,$context,$extensions);
^$originalTree(tree=$routedTrees);
}
function meta::pure::graphFetch::executionPlan::planStoreUnionGraphFetchExecution(sq: StoreQuery[1], ext: RoutedValueSpecification[0..1], sets: InstanceSetImplementation[*], mapping: Mapping[1], runtime: Runtime[1], exeCtx: meta::pure::runtime::ExecutionContext[1], extensions: meta::pure::extension::Extension[*], debug: DebugContext[1]): ExecutionNode[1]
{
let fe = $sq.fe->evaluateAndDeactivate();
let params = $fe.parametersValues->evaluateAndDeactivate();
let p1 = $params->at(0);
let p2 = $params->at(1)->cast(@InstanceValue);
let tree = $p2.values->at(0)->cast(@ClusteredGraphFetchTree);
let rf = {set: InstanceSetImplementation[1] | ^$fe(parametersValues = [$p1, ^$p2(values = ^$tree(tree = $tree->byPassClusteringInfoDeep()->cast(@RootGraphFetchTree)->routeRootGraphFetchTree($set, $mapping, $exeCtx, $extensions)))]->evaluateAndDeactivate())->evaluateAndDeactivate()};
let newFe = $sets->tail()->fold({set, agg |
^SimpleFunctionExpression
(
func = union_T_MANY__T_MANY__T_MANY_,
functionName = 'union',
genericType = $fe.genericType,
multiplicity = ZeroMany,
importGroup = system::imports::coreImport,
resolvedTypeParameters = ^GenericType(rawType=Any),
parametersValues = [$agg, $rf->eval($set)]->evaluateAndDeactivate()
)->evaluateAndDeactivate()
}, $rf->eval($sets->at(0)));
planRouterUnionGraphFetchExecution(^$sq(fe = $newFe), $ext, $mapping, $runtime, $exeCtx, $extensions, $debug);
}
function meta::pure::graphFetch::executionPlan::planRouterUnionGraphFetchExecution(sq: StoreQuery[1], ext: RoutedValueSpecification[0..1], mapping: Mapping[1], runtime: Runtime[1], exeCtx: meta::pure::runtime::ExecutionContext[1], extensions: Extension[*], debug: DebugContext[1]): ExecutionNode[1]
{
let fe = $sq.fe->evaluateAndDeactivate();
assert($fe->isUnionOnGraphFetch(true), | 'Non union graphFetch function encountered');
let subClusters = $fe.parametersValues->evaluateAndDeactivate()->map({p | $p->meta::pure::router::clustering::cluster($mapping, $runtime, $sq.inScopeVars, $exeCtx, $extensions, $debug).cluster->evaluateAndDeactivate()})->cast(@meta::pure::router::metamodel::clustering::ClusteredValueSpecification);
let firstCluster = $subClusters->at(0);
let childNodes = $subClusters->map(cls | $cls->plan($sq.inScopeVars, $exeCtx, $extensions, $debug));
^PlatformUnionExecutionNode
(
fromCluster = ^$firstCluster(val = $fe),
resultType = $childNodes->at(0).resultType,
isChildrenExecutionParallelizable = true,
executionNodes = $childNodes
);
}
function <> meta::pure::graphFetch::executionPlan::addCrossStoreChildren(currentNode: GlobalGraphFetchExecutionNode[1], parentPath: String[0..1], currentTree: ClusteredGraphFetchTree[1], orderedPaths: String[*], clusterNodesWithParents: Pair>[*], inScopeVars: Map>[1], m: Mapping[1], runtime: Runtime[1], exeCtx: meta::pure::runtime::ExecutionContext[1], enableConstraints: Boolean[1], checked: Boolean[1], extensions:Extension[*], debug: DebugContext[1]):GlobalGraphFetchExecutionNode[1]
{
let currentNonClusterTrees = $currentTree->recursivelyFindNonClusterTrees();
let childrenClusterNodes = $clusterNodesWithParents->filter(x | $x.second.values->isNotEmpty() && $x.second.values->toOne()->in($currentNonClusterTrees));
if($childrenClusterNodes->isEmpty(),
| $currentNode,
| print(if($debug.debug,|$debug.space+'>Generating cross-store global child nodes\n',|''));
let children = $childrenClusterNodes->map({ch |
let childTreeOneCluster = $ch.first->recursivelyRemoveClusterTrees();
let routedTree = $childTreeOneCluster.tree->cast(@RoutedPropertyGraphFetchTree);
let newParentPath = if($parentPath->isEmpty(),
|$currentTree->toOne()->getPathTo($ch.first)->toOne(),
|$parentPath->toOne()+'.'+$currentTree->getPathTo($ch.first)->toOne()
);
$ch.first->match([
{smct: StoreMappingClusteredGraphFetchTree[1] |
print(if($debug.debug,|$debug.space+' >Generating store local node for cross-store property tree: '+$routedTree.property.name->toOne()+'\n',|''));
print(if($debug.debug,|$debug.space+' Store local tree: '+$childTreeOneCluster->asString(false)+'\n',|''));
let crossLocalNodeGenerationInput = ^StoreMappingCrossLocalGraphFetchExecutionNodeGenerationInput
(
clusteredTree = $childTreeOneCluster->cast(@StoreMappingClusteredGraphFetchTree),
orderedPaths = $orderedPaths,
parentPath = $newParentPath,
enableConstraints = $enableConstraints,
checked = $checked,
inScopeVars = $inScopeVars,
mapping = $m,
runtime = $runtime,
exeCtx = $exeCtx,
extensions = $extensions,
debug = $debug->indent(2)
);
let crossLocalNode = $smct.s.planCrossGraphFetchExecution->toOne()->eval($crossLocalNodeGenerationInput);
let propertyMapping = $routedTree.propertyMapping->toOne()->cast(@XStorePropertyMapping);
let crossExpr = $propertyMapping.crossExpression.expressionSequence->evaluateAndDeactivate()->toOne();
let sourceCls = $m->classMappingById($propertyMapping.sourceSetImplementationId)->toOne()->cast(@InstanceSetImplementation)->map(i | if($i.mappingClass->isNotEmpty(), | $i.mappingClass->toOne(), | $i.class));
let crossExprTree = $crossExpr->fetchTreeInExpression($sourceCls);
let routedDependencyTree = getRoutedDependencyTree($ch.second.values->toOne(), $crossExprTree);
let newCrossNode = ^StoreMappingGlobalGraphFetchExecutionNode
(
resultType = $routedTree->resultTypeFromGraphFetchTree(),
graphFetchTree = $ch.first,
parentIndex = $orderedPaths->indexOf($newParentPath),
xStorePropertyMapping = $propertyMapping,
store = $smct.store,
localGraphFetchExecutionNode = $crossLocalNode,
xStorePropertyFetchDetails = $propertyMapping->buildXStorePropertyFetchDetails($ch.first, $newParentPath, $m),
localTreeIndices = $routedTree->getPathsOrdered()->map(p | $newParentPath + '.' + $p)->map(p | let idx = $orderedPaths->indexOf($p); assert($idx >= 0, | 'Path ' + $p + ' not found in orderedPaths: ' + $orderedPaths->makeString('[', ', ', ']')); $idx;),
dependencyIndices = $routedDependencyTree.subTrees->map(st | $st->getPathsOrdered())->map(p | $newParentPath + '.' + $p)->map(p | let idx = $orderedPaths->indexOf($p); assert($idx >= 0, | 'Path ' + $p + ' not found in orderedPaths: ' + $orderedPaths->makeString('[', ', ', ']')); $idx;)
);
print(if($debug.debug,|$debug.space+' >Generated store local node for cross property tree\n',|''));
$newCrossNode->addCrossStoreChildren($newParentPath, $ch.first, $orderedPaths, $clusterNodesWithParents, $inScopeVars, $m, $runtime, $exeCtx, $enableConstraints, $checked, $extensions, $debug->indent(2));
},
{p: PlatformClusteredGraphFetchTree[1] |
print(if($debug.debug,|$debug.space+' >Generating local node for platform property tree: '+$routedTree.property.name->toOne()+'\n',|''));
assert($routedTree.property->instanceOf(QualifiedProperty) && $routedTree.property->isPrimitiveValueProperty(), | 'Expected primitive qualifier in a platform clustered graph fetch tree');
let qp = $routedTree.property->cast(@QualifiedProperty);
let qualifierTree = $qp.expressionSequence->evaluateAndDeactivate()->toOne()->fetchTreeInExpression($qp->functionType().parameters->evaluateAndDeactivate()->at(0).genericType.rawType->toOne()->cast(@Class));
let routedDependencyTree = getRoutedDependencyTree($ch.second.values->toOne(), $qualifierTree);
let resultType = ^ResultType(type = $qp->functionReturnType().rawType->toOne());
let currentPath = $newParentPath + '.' + $routedTree->nodePathName();
let platformNode = ^PlatformGlobalGraphFetchExecutionNode
(
resultType = $resultType,
graphFetchTree = $ch.first,
parentIndex = $orderedPaths->indexOf($newParentPath),
localGraphFetchExecutionNode = ^PlatformPrimitiveQualifierLocalGraphFetchExecutionNode
(
resultType = $resultType,
nodeIndex = $orderedPaths->indexOf($currentPath),
parentIndex = $orderedPaths->indexOf($newParentPath),
graphFetchTree = $routedTree
),
localTreeIndices = $routedTree->getPathsOrdered()->map(p | $newParentPath + '.' + $p)->map(p | let idx = $orderedPaths->indexOf($p); assert($idx >= 0, | 'Path ' + $p + ' not found in orderedPaths: ' + $orderedPaths->makeString('[', ', ', ']')); $idx;),
dependencyIndices = $routedDependencyTree.subTrees->map(st | $st->getPathsOrdered())->map(p | $newParentPath + '.' + $p)->map(p | let idx = $orderedPaths->indexOf($p); assert($idx >= 0, | 'Path ' + $p + ' not found in orderedPaths: ' + $orderedPaths->makeString('[', ', ', ']')); $idx;)
);
print(if($debug.debug,|$debug.space+' >Generated local node for platform property tree\n',|''));
$platformNode;
}
]);
});
^$currentNode(children = $children);
);
}
function <> meta::pure::graphFetch::executionPlan::getRoutedDependencyTree(routedParentTree :GraphFetchTree[1], UnRoutedParentTree :GraphFetchTree[1]):GraphFetchTree[1]
{
^$routedParentTree(subTrees = $routedParentTree.subTrees->map(s | let routedChildTree = if($s->instanceOf(ClusteredGraphFetchTree),| $s->cast(@ClusteredGraphFetchTree).tree, | $s);
let unRoutedChildTree = $UnRoutedParentTree.subTrees->filter(x | $x->cast(@PropertyGraphFetchTree).property.name == $routedChildTree->cast(@PropertyGraphFetchTree).property.name);
if($unRoutedChildTree->isEmpty(),
| [],
| getRoutedDependencyTree($routedChildTree, $unRoutedChildTree->toOne()));
)
);
}
function <> meta::pure::graphFetch::executionPlan::buildXStorePropertyFetchDetails(xStorePropertyMapping: XStorePropertyMapping[1], subTree: ClusteredGraphFetchTree[1], parentPath: String[1], mapping: Mapping[1]): XStorePropertyFetchDetails[1]
{
let propertyTree = $subTree->byPassClusteringInfo()->cast(@RoutedPropertyGraphFetchTree);
let subTreeString = '{' + $propertyTree.subTrees->map(st | $st->meta::pure::graphFetch::routing::asString(false))->joinStrings(',') + '}';
let propertyPath = $parentPath + '.' + $propertyTree->nodePathName();
let xStoreExpressionSequence = $xStorePropertyMapping.crossExpression.expressionSequence->evaluateAndDeactivate();
let isXStoreMappingMultiEqual = $xStoreExpressionSequence->size() == 1 && $xStoreExpressionSequence->toOne()->isExpressionMultiEqual();
let supportsCaching = $isXStoreMappingMultiEqual && !($subTreeString->contains('$'));
^XStorePropertyFetchDetails
(
supportsCaching = $supportsCaching,
propertyPath = $propertyPath,
sourceMappingId = $mapping->classMappingById($xStorePropertyMapping.sourceSetImplementationId)->toOne().parent->elementToPath(),
sourceSetId = $xStorePropertyMapping.sourceSetImplementationId,
targetMappingId = $mapping->classMappingById($xStorePropertyMapping.targetSetImplementationId)->toOne().parent->elementToPath(),
targetSetId = $xStorePropertyMapping.targetSetImplementationId,
targetPropertiesOrdered = if($supportsCaching, | $xStoreExpressionSequence->toOne()->propertyOrNoArgQualifierPairsInMultiEqual().second.name->sort(), | []),
subTree = $subTreeString
);
}
function <> meta::pure::graphFetch::executionPlan::isPropertyOrNoArgQualifier(f: Function[1]): Boolean[1]
{
$f->instanceOf(Property) || ($f->instanceOf(QualifiedProperty) && $f->functionType().parameters->evaluateAndDeactivate()->size() == 1)
}
function meta::pure::graphFetch::executionPlan::isExpressionMultiEqual(v: ValueSpecification[1]):Boolean[1]
{
$v->evaluateAndDeactivate()->match([
f: FunctionExpression[1] | let params = $f.parametersValues->evaluateAndDeactivate()->map(x| $x->byPassRouterInfo());
if($f.func->in([meta::pure::functions::boolean::equal_Any_MANY__Any_MANY__Boolean_1_, meta::pure::functions::boolean::eq_Any_1__Any_1__Boolean_1_]),
| $params->match([
sfes: SimpleFunctionExpression[*] | $sfes->at(0).func->isPropertyOrNoArgQualifier() && $sfes->at(1).func->isPropertyOrNoArgQualifier(),
a: Any[*] | false
]),
| if($f.functionName == 'and',
| $params->at(0)->isExpressionMultiEqual() && $params->at(1)->isExpressionMultiEqual(),
| false
);
);
])
}
function meta::pure::graphFetch::executionPlan::propertyOrNoArgQualifierPairsInMultiEqual(v: ValueSpecification[1]):Pair, AbstractProperty>[*]
{
$v->evaluateAndDeactivate()->match([
f: FunctionExpression[1] | let params = $f.parametersValues->evaluateAndDeactivate()->map(x| $x->byPassRouterInfo());
if($f.func->in([meta::pure::functions::boolean::equal_Any_MANY__Any_MANY__Boolean_1_, meta::pure::functions::boolean::eq_Any_1__Any_1__Boolean_1_]),
| $params->match([
sfes: SimpleFunctionExpression[*] | assert($sfes->at(0).func->isPropertyOrNoArgQualifier() && $sfes->at(1).func->isPropertyOrNoArgQualifier());
if($sfes->at(0).parametersValues->evaluateAndDeactivate()->cast(@VariableExpression).name == 'this' &&
$sfes->at(1).parametersValues->evaluateAndDeactivate()->cast(@VariableExpression).name == 'that',
| pair($sfes->at(0).func->cast(@AbstractProperty), $sfes->at(1).func->cast(@AbstractProperty)),
| if($sfes->at(0).parametersValues->evaluateAndDeactivate()->cast(@VariableExpression).name == 'that' &&
$sfes->at(1).parametersValues->evaluateAndDeactivate()->cast(@VariableExpression).name == 'this',
| pair($sfes->at(1).func->cast(@AbstractProperty), $sfes->at(0).func->cast(@AbstractProperty)),
| assert(false, 'Complex cross expressions not supported yet!'); [];
)
);,
a: Any[*] | assert(false, 'Complex cross expressions not supported yet!'); [];
]),
| if($f.functionName == 'and',
| $params->at(0)->propertyOrNoArgQualifierPairsInMultiEqual()->concatenate($params->at(1)->propertyOrNoArgQualifierPairsInMultiEqual()),
| assert(false, 'Complex cross expressions not supported yet!'); [];
);
);
])
}
function meta::pure::graphFetch::executionPlan::globalGraphFetchExecutionNodeToString(g: GlobalGraphFetchExecutionNode[1], space: String[1], extensions:meta::pure::extension::Extension[*]):String[1]
{
$g->match([
s: StoreMappingGlobalGraphFetchExecutionNode[1] | $s->storeMappingGlobalGraphFetchExecutionNodeToString($space, $extensions),
p: PlatformGlobalGraphFetchExecutionNode[1] | $p->platformGlobalGraphFetchExecutionNodeToString($space, $extensions)
])
}
function meta::pure::graphFetch::executionPlan::storeMappingGlobalGraphFetchExecutionNodeToString(g: StoreMappingGlobalGraphFetchExecutionNode[1], space: String[1], extensions:meta::pure::extension::Extension[*]):String[1]
{
'StoreMappingGlobalGraphFetch\n' +
$space + '(' + header($g, $space, $extensions) + '\n'+
$space + ' store = ' + $g.store->elementToPath() + '\n'+
$space + ' localGraphFetchExecutionNode = \n' + $g.localGraphFetchExecutionNode->meta::pure::executionPlan::toString::planNodeToString($space+ ' ', $extensions) +
$space + ' children = ' + $g.children->map(x | globalGraphFetchExecutionNodeToString($x, $space + ' ', $extensions))->joinStrings('[\n'+ $space + ' ', '\n' + $space + ' ', '\n' + $space + ' ]\n') +
if($g.parentIndex->isEmpty(), | '', | $space + ' parentIndex = ' + $g.parentIndex->toOne()->toString() + '\n') +
if($g.xStorePropertyMapping->isEmpty(), | '', | $space + ' xStorePropertyMapping = ' + $g.xStorePropertyMapping.property.name->toOne() + '[' + $g.xStorePropertyMapping.sourceSetImplementationId->toOne() + ' -> ' + $g.xStorePropertyMapping.targetSetImplementationId->toOne() + ']' + '\n') +
$space + ' localTreeIndices = ' + $g.localTreeIndices->makeString('[', ', ', ']') + '\n'+
$space + ' dependencyIndices = ' + $g.dependencyIndices->makeString('[', ', ', ']') + '\n'+
$g.implementation->printImplementation('implementation', $space+' ', $extensions)+
$space + ')\n';
}
function meta::pure::graphFetch::executionPlan::platformGlobalGraphFetchExecutionNodeToString(g: PlatformGlobalGraphFetchExecutionNode[1], space: String[1], extensions:meta::pure::extension::Extension[*]):String[1]
{
'PlatformGlobalGraphFetch\n' +
$space + '(' + header($g, $space, $extensions) + '\n'+
$space + ' localGraphFetchExecutionNode = \n' + $g.localGraphFetchExecutionNode->meta::pure::executionPlan::toString::planNodeToString($space+ ' ', $extensions) +
$space + ' children = ' + $g.children->map(x | globalGraphFetchExecutionNodeToString($x, $space + ' ', $extensions))->joinStrings('[\n'+ $space + ' ', '\n' + $space + ' ', '\n' + $space + ' ]\n') +
if($g.parentIndex->isEmpty(), | '', | $space + ' parentIndex = ' + $g.parentIndex->toOne()->toString() + '\n') +
$space + ' localTreeIndices = ' + $g.localTreeIndices->makeString('[', ', ', ']') + '\n'+
$space + ' dependencyIndices = ' + $g.dependencyIndices->makeString('[', ', ', ']') + '\n'+
$g.implementation->printImplementation('implementation', $space+' ', $extensions)+
$space + ')\n';
}
function meta::pure::graphFetch::executionPlan::platformPrimitiveQualifierLocalGraphFetchExecutionNodeToString(g: PlatformPrimitiveQualifierLocalGraphFetchExecutionNode[1], space: String[1], extensions:meta::pure::extension::Extension[*]):String[1]
{
'PlatformPrimitiveQualifierLocalGraphFetch\n' +
$space + '(' + header($g, $space, $extensions) + '\n'+
$space + ' nodeIndex = ' + $g.nodeIndex->toString() + '\n'+
$space + ' qualfifier = ' + $g.graphFetchTree->cast(@PropertyGraphFetchTree).property.name->toOne() + '\n' +
$g.implementation->printImplementation('implementation', $space+' ', $extensions)+
$space + ')\n';
}
function meta::pure::graphFetch::executionPlan::resultTypeFromGraphFetchTree(g: GraphFetchTree[1]):PartialClassResultType[1]
{
^PartialClassResultType
(
type = $g->byPassClusteringInfo()->typeFromGraphFetchTree(),
setImplementations = $g->byPassClusteringInfo()->cast(@RoutedGraphFetchTree).sets,
propertiesWithParameters = $g->byPassClusteringInfo().subTrees->map(x | $x->byPassClusteringInfo()->cast(@PropertyGraphFetchTree)->map(x | ^PropertyWithParameters(property = $x.property, parameters = $x.parameters)))
)
}
function <> meta::pure::graphFetch::executionPlan::findAllClusterTreesWithParents(g : GraphFetchTree[1], parent : RoutedGraphFetchTree[0..1]):Pair>[*]
{
let thisLevel = $g->match([
c : ClusteredGraphFetchTree[1] | pair($c, list($parent)),
r : RoutedGraphFetchTree[1] | [],
s: SystemGeneratedPropertyGraphFetchTree[1] | []
]);
let subClusterTrees = $g->byPassClusteringInfo().subTrees->map(k | $k->findAllClusterTreesWithParents($g->byPassClusteringInfo()->cast(@RoutedGraphFetchTree)));
$thisLevel->concatenate($subClusterTrees);
}
function <> meta::pure::graphFetch::executionPlan::recursivelyFindNonClusterTrees(cls : ClusteredGraphFetchTree[1]):RoutedGraphFetchTree[*]
{
$cls.tree->cast(@RoutedGraphFetchTree)->recursivelyFindNonClusterTrees()
}
function <> meta::pure::graphFetch::executionPlan::recursivelyFindNonClusterTrees(routed : RoutedGraphFetchTree[1]):RoutedGraphFetchTree[*]
{
$routed->concatenate($routed.subTrees->filter(x | !$x->instanceOf(ClusteredGraphFetchTree))->cast(@RoutedGraphFetchTree)->map(x | $x->recursivelyFindNonClusterTrees()))
}
function <> meta::pure::graphFetch::executionPlan::recursivelyRemoveClusterTrees(cls : ClusteredGraphFetchTree[1]):ClusteredGraphFetchTree[1]
{
^$cls(tree = $cls.tree->cast(@RoutedGraphFetchTree)->recursivelyRemoveClusterTrees())
}
function <> meta::pure::graphFetch::executionPlan::recursivelyRemoveClusterTrees(routed : RoutedGraphFetchTree[1]):RoutedGraphFetchTree[1]
{
^$routed(subTrees = $routed.subTrees->filter(x | !$x->instanceOf(ClusteredGraphFetchTree))->cast(@RoutedGraphFetchTree)->map(x | $x->recursivelyRemoveClusterTrees()))
}
function meta::pure::graphFetch::executionPlan::indent(d: DebugContext[1], count: Integer[1]): DebugContext[1]
{
range($count)->fold({x,a | $a->indent()}, $d)
}