Skip to content

Commit

Permalink
Stereotypes support for Relational Databases (#2858)
Browse files Browse the repository at this point in the history
* Stereotypes support for Relational Databases

* Remove dependency
  • Loading branch information
mrudula-gs committed May 24, 2024
1 parent 6aa8774 commit b41fe4d
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ identifier: unquotedIdentifier | STRING
definition: (database)*
EOF
;
database: DATABASE qualifiedName
database: DATABASE stereotypes? qualifiedName
PAREN_OPEN
include*
(
Expand All @@ -44,6 +44,11 @@ database: DATABASE qualifiedName
include: INCLUDE qualifiedName
;

// -------------------------------------- STEREOTYPE --------------------------------------

stereotypes: LESS_THAN LESS_THAN stereotype (COMMA stereotype)* GREATER_THAN GREATER_THAN;

stereotype: qualifiedName DOT identifier;

// -------------------------------------- SCHEMA & TABLE --------------------------------------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,8 @@ public Iterable<? extends Processor<?>> getExtraProcessors()
org.finos.legend.pure.m3.coreinstance.meta.relational.metamodel.Database database = HelperRelationalBuilder.getDatabase(context.pureModel.buildPackageString(srcDatabase._package, srcDatabase.name), srcDatabase.sourceInformation, context);
// TODO checkForDuplicatesByName for filters/joins
database._joins(srcDatabase.joins == null ? Lists.fixedSize.empty() : ListIterate.collect(srcDatabase.joins, join -> HelperRelationalBuilder.processDatabaseJoin(join, context, database)))
._filters(srcDatabase.filters == null ? Lists.fixedSize.empty() : ListIterate.collect(srcDatabase.filters, filter -> HelperRelationalBuilder.processDatabaseFilter(filter, context, database)));
._filters(srcDatabase.filters == null ? Lists.fixedSize.empty() : ListIterate.collect(srcDatabase.filters, filter -> HelperRelationalBuilder.processDatabaseFilter(filter, context, database)))
._stereotypes(srcDatabase.stereotypes == null ? Lists.fixedSize.empty() : ListIterate.collect(srcDatabase.stereotypes, stereotypePointer -> context.resolveStereotype(stereotypePointer.profile, stereotypePointer.value, stereotypePointer.profileSourceInformation, stereotypePointer.sourceInformation)));
},
(Database srcDatabase, CompileContext context) ->
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.eclipse.collections.api.factory.Sets;
import org.eclipse.collections.api.list.MutableList;
import org.eclipse.collections.api.set.ImmutableSet;
import org.eclipse.collections.impl.factory.Lists;
import org.eclipse.collections.impl.list.mutable.FastList;
import org.eclipse.collections.impl.utility.ListIterate;
import org.finos.legend.engine.language.pure.grammar.from.antlr4.RelationalParserGrammar;
Expand All @@ -28,6 +29,7 @@
import org.finos.legend.engine.protocol.pure.v1.model.context.EngineErrorType;
import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement;
import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Multiplicity;
import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.StereotypePtr;
import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.externalFormat.BindingTransformer;
import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.mapping.LocalMappingPropertyInfo;
import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.mapping.PropertyMapping;
Expand Down Expand Up @@ -118,6 +120,7 @@ private Database visitDatabase(RelationalParserGrammar.DatabaseContext ctx)
ScopeInfo scopeInfo = ScopeInfo.Builder.newInstance().withDatabase(PureGrammarParserUtility.fromQualifiedName(ctx.qualifiedName().packagePath() == null ? Collections.emptyList() : ctx.qualifiedName().packagePath().identifier(), ctx.qualifiedName().identifier())).build();
database.includedStores = ListIterate.collect(ctx.include(), includeContext -> PureGrammarParserUtility.fromQualifiedName(includeContext.qualifiedName().packagePath() == null ? Collections.emptyList() : includeContext.qualifiedName().packagePath().identifier(), includeContext.qualifiedName().identifier()));
database.schemas = ListIterate.collect(ctx.schema(), schemaCtx -> this.visitSchema(schemaCtx, scopeInfo));
database.stereotypes = ctx.stereotypes() == null ? Lists.mutable.empty() : this.visitStereotypes(ctx.stereotypes());
// NOTE: if tables and views are defined without a schema, create a default schema to hold these
List<Table> tables = ListIterate.collect(ctx.table(), this::visitTable);
List<View> views = ListIterate.collect(ctx.view(), viewCtx -> this.visitView(viewCtx, scopeInfo));
Expand All @@ -140,6 +143,21 @@ private Database visitDatabase(RelationalParserGrammar.DatabaseContext ctx)
return database;
}

// ----------------------------------------------- STEREOTYPE -----------------------------------------------

public List<StereotypePtr> visitStereotypes(RelationalParserGrammar.StereotypesContext ctx)
{
return ListIterate.collect(ctx.stereotype(), stereotypeContext ->
{
StereotypePtr stereotypePtr = new StereotypePtr();
stereotypePtr.profile = PureGrammarParserUtility.fromQualifiedName(stereotypeContext.qualifiedName().packagePath() == null ? Collections.emptyList() : stereotypeContext.qualifiedName().packagePath().identifier(), stereotypeContext.qualifiedName().identifier());
stereotypePtr.value = PureGrammarParserUtility.fromIdentifier(stereotypeContext.identifier());
stereotypePtr.profileSourceInformation = this.walkerSourceInformation.getSourceInformation(stereotypeContext.qualifiedName());
stereotypePtr.sourceInformation = this.walkerSourceInformation.getSourceInformation(stereotypeContext);
return stereotypePtr;
});
}


// ----------------------------------------------- SCHEMA -----------------------------------------------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
import java.util.Collections;
import java.util.List;

import static org.finos.legend.engine.language.pure.grammar.to.HelperDomainGrammarComposer.renderAnnotations;
import static org.finos.legend.engine.language.pure.grammar.to.PureGrammarComposer.buildSectionComposer;
import static org.finos.legend.engine.language.pure.grammar.to.PureGrammarComposerUtility.*;

Expand Down Expand Up @@ -259,7 +260,7 @@ private static String renderDatabase(Database database, PureGrammarComposerConte
Schema defaultSchema = ListIterate.select(database.schemas, schema -> "default".equals(schema.name)).getFirst();
RelationalGrammarComposerContext context = RelationalGrammarComposerContext.Builder.newInstance().withCurrentDatabase(PureGrammarComposerUtility.convertPath(database.getPath())).withNoDynaFunctionNames().withRenderStyle(PUREcontext.getRenderStyle()).build();
StringBuilder builder = new StringBuilder();
builder.append("Database ").append(PureGrammarComposerUtility.convertPath(database.getPath())).append("\n(\n");
builder.append("Database ").append(renderAnnotations(database.stereotypes, null)).append(PureGrammarComposerUtility.convertPath(database.getPath())).append("\n(\n");
boolean nonEmpty = false;
if (!database.includedStores.isEmpty())
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,52 @@ public void testRelationalDatabase()
}, productSchemaTablesDb);
}

@Test
public void testDatabaseStereotype()
{
test("###Pure\n" +
"Profile meta::pure::profiles::storeType\n" +
"{\n" +
" stereotypes: [type1, type2];\n" +
"}\n" +
"\n" +
"###Relational\n" +
"Database <<meta::pure::profiles::storeType.type2>> app::dbInc\n" +
"(\n" +
" Table Product\n" +
" (\n" +
" ProductID VARCHAR(30) PRIMARY KEY\n" +
" )\n" +
")\n" +
"\n" +
"###Relational\n" +
"Database <<meta::pure::profiles::storeType.type2, meta::pure::profiles::storeType.type1>> app::db\n" +
"(\n" +
" Table Product\n" +
" (\n" +
" ProductID VARCHAR(30) PRIMARY KEY\n" +
" )\n" +
")");

test("###Pure\n" +
"Profile meta::pure::profiles::storeType\n" +
"{\n" +
" stereotypes: [type1, type2];\n" +
"}\n" +
"\n" +
"###Relational\n" +
"Database <<meta::pure::profiles::storeType.type3>> app::dbInc\n" +
"(\n" +
" Table Product\n" +
" (\n" +
" ProductID VARCHAR(30) PRIMARY KEY,\n" +
" ProductID VARCHAR(30) PRIMARY KEY\n" +
" )\n" +
")",
"COMPILATION error at [8:12-48]: Can't find stereotype 'type3' in profile 'meta::pure::profiles::storeType'"
);
}

@Test
public void testSelfJoin()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,34 @@ public void testJsonColumn()
")\n");
}

@Test
public void testDatabaseStereotype()
{
test("###Relational\n" +
"Database <<meta::pure::profiles::storeType.type2>> app::dbInc\n" +
"(\n" +
" Table Product\n" +
" (\n" +
" ProductID VARCHAR(30) PRIMARY KEY\n" +
" )\n" +
")\n" +
"\n" +
"Database <<meta::pure::profiles::storeType.type2, meta::pure::profiles::storeType.type1>> app::db\n" +
"(\n" +
" Table Product\n" +
" (\n" +
" ProductID VARCHAR(30) PRIMARY KEY\n" +
" )\n" +
")\n" +
"\n" +
"\n" +
"###Pure\n" +
"Profile meta::pure::profiles::storeType\n" +
"{\n" +
" stereotypes: [type1, type2];\n" +
"}\n");
}

@Test
public void testRelationalPropertyMappingWithBindingTransformer()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package org.finos.legend.engine.protocol.pure.v1.model.packageableElement.store.relational.model;

import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElementVisitor;
import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.StereotypePtr;
import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.store.Store;

import java.util.Collections;
Expand All @@ -25,6 +26,7 @@ public class Database extends Store
public List<Schema> schemas = Collections.emptyList();
public List<Join> joins = Collections.emptyList();
public List<Filter> filters = Collections.emptyList();
public List<StereotypePtr> stereotypes = Collections.emptyList();

@Override
public <T> T accept(PackageableElementVisitor<T> visitor)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import meta::pure::mapping::*;
import meta::core::runtime::*;
function meta::relational::mapping::userPlanPostProcessors(result:PostProcessorResult[1], runtime:Runtime[1], ext:RoutedValueSpecification[0..1], m:Mapping[0..1], store:Database[0..1], exeCtx:meta::pure::runtime::ExecutionContext[1]): PostProcessorResult[1]
{
let postProcessorsWithParameters = $runtime.connectionStores->filter(c|$c.connection->instanceOf(DatabaseConnection)).connection->cast(@DatabaseConnection).queryPostProcessorsWithParameter;
let postProcessorsWithParameters = $runtime.connectionStores->filter(c|$c.connection->instanceOf(meta::external::store::relational::runtime::DatabaseConnection)).connection->cast(@meta::external::store::relational::runtime::DatabaseConnection).queryPostProcessorsWithParameter->removeDuplicates();
let postProcessorResult = if($postProcessorsWithParameters->isNotEmpty(),
| $postProcessorsWithParameters->fold({i, prevResult|let struct = $i.postProcessor->cast(@ConcreteFunctionDefinition<{->PostProcessor[1]}>)->eval();
let res = $struct.sqlQueryPostProcessorForPlan->cast(@ConcreteFunctionDefinition<{SQLQuery[1], Mapping[0..1], Runtime[1], Database[0..1], meta::pure::runtime::ExecutionContext[1], PostProcessorParameter[*]->PostProcessorResult[1]}>)->toOne()->eval($prevResult.query,$m,$runtime->toOne(),$store,$exeCtx,$i.parameters)->toOne();
Expand Down

0 comments on commit b41fe4d

Please sign in to comment.