core_persistence.persistence.validations_rules.pure Maven / Gradle / Ivy
// Copyright 2022 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::legend::service::metamodel::*;
import meta::pure::executionPlan::*;
import meta::pure::extension::*;
import meta::pure::functions::collection::*;
import meta::pure::graphFetch::*;
import meta::pure::persistence::metamodel::*;
import meta::pure::persistence::metamodel::persister::*;
import meta::pure::persistence::metamodel::persister::targetshape::*;
import meta::pure::persistence::metamodel::service::*;
import meta::pure::persistence::validation::*;
function meta::pure::persistence::validation::commonRules(extensions: Extension[*]): ValidationRuleSet[1]
{
^ValidationRuleSet(
name = 'Common',
rules = [
c: PersistenceContext[1] | validateTarget($c.persistence.persister->cast(@BatchPersister).targetShape),
c: PersistenceContext[1] | validateServiceAndTarget($c.persistence.service, $c.persistence.persister->cast(@BatchPersister).targetShape, $extensions)
]
);
}
/**********
* service output target validations
**********/
function meta::pure::persistence::validation::validateServiceAndOutput(service: Service[1], serviceOutput: ServiceOutput[1], extensions: Extension[*]): ValidationResult[1]
{
$service.execution->match([
se: PureSingleExecution[1] | $serviceOutput->match([
tds: TdsServiceOutput[1] | validateSingleExecutionServiceAndTdsServiceOutput($service, $se, $tds, $extensions),
graphFetch: GraphFetchServiceOutput[1] | if ($graphFetch.path->isEmpty(),
| validateSingleExecutionServiceAndGraphFetchRootServiceOutput($service, $se, $graphFetch, $extensions),
| validateSingleExecutionServiceAndGraphFetchPathServiceOutput($service, $se, $graphFetch, $extensions)),
any: Any[1] | failure('Unknown service output')
]),
me: PureMultiExecution[1] | $serviceOutput->match([
tds: TdsServiceOutput[1] | validateMultiExecutionServiceAndTdsServiceOutput($service, $me, $tds, $extensions),
graphFetch: GraphFetchServiceOutput[1] | if ($graphFetch.path->isEmpty(),
| validateMultiExecutionServiceAndGraphFetchRootServiceOutput($service, $me, $graphFetch, $extensions),
| validateMultiExecutionServiceAndGraphFetchPathServiceOutput($service, $me, $graphFetch, $extensions)),
any: Any[1] | failure('Unknown target shape')
]),
any: Any[1] | failure('Unknown service output')
]);
}
function meta::pure::persistence::validation::validateSingleExecutionServiceAndTdsServiceOutput(service: Service[1], execution: PureSingleExecution[1], serviceOutput: TdsServiceOutput[1], extensions: Extension[*]): ValidationResult[1]
{
let classification = $execution->classify($extensions);
if ($classification->instanceOf(TdsExecutionClassification),
| success(),
| failure('TDS service output requires a service that returns a TDS'));
}
function meta::pure::persistence::validation::validateSingleExecutionServiceAndGraphFetchRootServiceOutput(service: Service[1], execution: PureSingleExecution[1], serviceOutput: GraphFetchServiceOutput[1], extensions: Extension[*]): ValidationResult[1]
{
let classification = $execution->classify($extensions);
if ($classification->instanceOf(FlatGraphFetchSerialize),
| success(),
| failure('Graph fetch root service output requires a service that ends with a "graphFetch()->serialize()" expression that has only primitive properties off the root node'));
}
function meta::pure::persistence::validation::validateSingleExecutionServiceAndGraphFetchPathServiceOutput(service: Service[1], execution: PureSingleExecution[1], serviceOutput: GraphFetchServiceOutput[1], extensions: Extension[*]): ValidationResult[1]
{
let classification = $execution->classify($extensions);
if ($classification->instanceOf(OneLevelGraphFetchSerialize),
| success(),
| failure('Graph fetch path service output requires a service that ends with a "graphFetch()->serialize()" expression that has 1) only complex properties off the root node and 2) only primitive properties off nodes at depth 1'));
}
function meta::pure::persistence::validation::validateMultiExecutionServiceAndTdsServiceOutput(service: Service[1], execution: PureMultiExecution[1], serviceOutput: TdsServiceOutput[1], extensions: Extension[*]): ValidationResult[1]
{
//TODO: ledav -- implement
success();
}
function meta::pure::persistence::validation::validateMultiExecutionServiceAndGraphFetchRootServiceOutput(service: Service[1], execution: PureMultiExecution[1], serviceOutput: GraphFetchServiceOutput[1], extensions: Extension[*]): ValidationResult[1]
{
//TODO: ledav -- implement
success();
}
function meta::pure::persistence::validation::validateMultiExecutionServiceAndGraphFetchPathServiceOutput(service: Service[1], execution: PureMultiExecution[1], serviceOutput: GraphFetchServiceOutput[1], extensions: Extension[*]): ValidationResult[1]
{
//TODO: ledav -- implement
success();
}
/**********
* target validations
**********/
function meta::pure::persistence::validation::validateTarget(target: TargetShape[0..1]): ValidationResult[1]
{
$target->match([
f: FlatTarget[1] | if ($f.targetName->isEmpty(), | failure('Flat target name must not be empty'), | success()),
mf: MultiFlatTarget[1] | if ($mf.parts->exists(p | $p.targetName->isEmpty()), | failure('Multi flat part target names must not be empty'), | success())
]);
}
/**********
* service + target validations
**********/
function meta::pure::persistence::validation::validateServiceAndTarget(service: Service[1], target: TargetShape[0..1], extensions: Extension[*]): ValidationResult[1]
{
$service.execution->match([
se: PureSingleExecution[1] | $target->match([
f: FlatTarget[1] | validateSingleExecutionServiceAndFlatTarget($service, $se, $f, $extensions),
mf: MultiFlatTarget[1] | validateSingleExecutionServiceAndMultiFlatTarget($service, $se, $mf, $extensions),
any: Any[1] | failure('Unknown target shape')
]),
me: PureMultiExecution[1] | $target->match([
f: FlatTarget[1] | validateMultiExecutionServiceAndFlatTarget($service, $me, $f, $extensions),
mf: MultiFlatTarget[1] | validateMultiExecutionServiceAndMultiFlatTarget($service, $me, $mf, $extensions),
any: Any[1] | failure('Unknown target shape')
]),
any: Any[1] | failure('Unknown service execution')
]);
}
function meta::pure::persistence::validation::validateSingleExecutionServiceAndFlatTarget(service: Service[1], execution: PureSingleExecution[1], target: FlatTarget[1], extensions: Extension[*]): ValidationResult[1]
{
let classification = $execution->classify($extensions);
if ($classification->instanceOf(TdsExecutionClassification) || $classification->instanceOf(FlatGraphFetchSerialize),
| success(),
| failure('Flat target requires a service that returns a TDS or ends with a "graphFetch()->serialize()" expression that has only primitive properties off the root node'));
}
function meta::pure::persistence::validation::validateSingleExecutionServiceAndMultiFlatTarget(service: Service[1], execution: PureSingleExecution[1], target: MultiFlatTarget[1], extensions: Extension[*]): ValidationResult[1]
{
let classification = $execution->classify($extensions);
if ($classification->instanceOf(OneLevelGraphFetchSerialize),
| success(),
| failure('Multi flat target requires a service that ends with a "graphFetch()->serialize()" expression that has 1) only complex properties off the root node and 2) only primitive properties off nodes at depth 1'));
}
function meta::pure::persistence::validation::validateMultiExecutionServiceAndFlatTarget(service: Service[1], execution: PureMultiExecution[1], target: FlatTarget[1], extensions: Extension[*]): ValidationResult[1]
{
//TODO: ledav -- implement flat validations
success();
}
function meta::pure::persistence::validation::validateMultiExecutionServiceAndMultiFlatTarget(service: Service[1], execution: PureMultiExecution[1], target: MultiFlatTarget[1], extensions: Extension[*]): ValidationResult[1]
{
//TODO: ledav -- implement multi flat validations
success();
}
/**********
* execution validations
**********/
Class
<>
meta::pure::persistence::validation::ExecutionClassification
{
}
Class meta::pure::persistence::validation::TdsExecutionClassification extends ExecutionClassification
{
columnByName: Map[*];
}
Class meta::pure::persistence::validation::FlatGraphFetchSerialize extends ExecutionClassification
{
validLeafProperties: PropertyGraphFetchTree[*];
invalidLeafProperties: PropertyGraphFetchTree[*];
}
Class meta::pure::persistence::validation::OneLevelGraphFetchSerialize extends ExecutionClassification
{
validRootProperties: PropertyGraphFetchTree[*];
invalidRootProperties: PropertyGraphFetchTree[*];
validLeafProperties: PropertyGraphFetchTree[*];
invalidLeafProperties: PropertyGraphFetchTree[*];
}
Class meta::pure::persistence::validation::OtherExecutionClassification extends ExecutionClassification
{
}
function meta::pure::persistence::validation::classify(execution: PureSingleExecution[1], extensions: Extension[*]): ExecutionClassification[1]
{
assert($execution->cast(@PureSingleExecution).mapping->isNotEmpty() && $execution->cast(@PureSingleExecution).runtime->isNotEmpty(),'Please provide mapping and runtime as part of execution');
$execution.func.expressionSequence->evaluateAndDeactivate()->last()->match([
fe: FunctionExpression[1] | if ($fe.func == meta::pure::graphFetch::execution::serialize_T_MANY__RootGraphFetchTree_1__String_1_,
| classifyFunctionExpression($execution.func, $fe),
| let plan = executionPlan($execution.func, $execution.mapping->toOne(), $execution.runtime->toOne(), $extensions);
$plan.rootExecutionNode.resultType->match([
tds: TDSResultType[1] |
let columnByName = $tds.tdsColumns->map(c | pair($c.name, $c))->newMap();
^TdsExecutionClassification(columnByName = $columnByName);,
any: Any[1] | ^OtherExecutionClassification()
]);
),
any: Any[1] | ^OtherExecutionClassification()
]);
}
function <> meta::pure::persistence::validation::classifyFunctionExpression(functionDefinition: FunctionDefinition[1], functionExpression: FunctionExpression[1]): ExecutionClassification[1]
{
let root = $functionExpression->instanceValuesAtParameter(1, $functionDefinition->openVariableValues())->toOne()->cast(@RootGraphFetchTree);
let firstLevelChildren = $root.subTrees->cast(@PropertyGraphFetchTree);
let secondLevelChildren = $firstLevelChildren.subTrees->cast(@PropertyGraphFetchTree);
if ($firstLevelChildren->forAll(p | $p.isPrimitive()),
| ^FlatGraphFetchSerialize(
validLeafProperties = $firstLevelChildren->filter(p | $p->validLeafGraphFetchProperty()),
invalidLeafProperties = $firstLevelChildren->filter(p | !$p->validLeafGraphFetchProperty())),
| if ($firstLevelChildren->forAll(p | !$p.isPrimitive()) && $secondLevelChildren->forAll(p | $p.isPrimitive()),
| ^OneLevelGraphFetchSerialize(
validRootProperties = $firstLevelChildren->filter(p | $p->validRootGraphFetchRootProperty()),
invalidRootProperties = $firstLevelChildren->filter(p | !$p->validRootGraphFetchRootProperty()),
validLeafProperties = $secondLevelChildren->filter(p | $p->validLeafGraphFetchProperty()),
invalidLeafProperties = $secondLevelChildren->filter(p | !$p->validLeafGraphFetchProperty())),
| ^OtherExecutionClassification())
);
}
function <> meta::pure::persistence::validation::validRootGraphFetchRootProperty(property: PropertyGraphFetchTree[1]): Boolean[1]
{
!$property.isPrimitive() && $property.alias->isEmpty() && $property.parameters->isEmpty() && $property.subType->isEmpty();
}
function <> meta::pure::persistence::validation::validLeafGraphFetchProperty(property: PropertyGraphFetchTree[1]): Boolean[1]
{
$property.isPrimitive() && $property.alias->isEmpty() && $property.parameters->isEmpty() && $property.subType->isEmpty();
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy