Skip to content

Commit

Permalink
Display TDS using REPL print API (#254)
Browse files Browse the repository at this point in the history
* Display TDS using REPL print API

* Update engine to 4.64.1
  • Loading branch information
rafaelbey authored Oct 30, 2024
1 parent bb86ef0 commit 1760878
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -298,11 +298,7 @@ static void executePlan(GlobalState globalState, FunctionExecutionSupport execut
}
else
{
PlanExecutor planExecutor = extension.getPlanExecutor();
MutableMap<String, Result> parametersToConstantResult = Maps.mutable.empty();
ExecuteNodeParameterTransformationHelper.buildParameterToConstantResult(executionPlan, inputParameters, parametersToConstantResult);
Identity identity = getIdentity();
Result result = planExecutor.execute(executionPlan, parametersToConstantResult, identity.getName(), identity, context);
Result result = executePlan(executionPlan, context, inputParameters, extension);
collectResults(executionSupport, entityPath, result, docId, sectionNum, inputParameters, format, results::add);
}
}
Expand All @@ -312,6 +308,15 @@ static void executePlan(GlobalState globalState, FunctionExecutionSupport execut
}
}

static Result executePlan(SingleExecutionPlan executionPlan, PlanExecutionContext context, Map<String, Object> inputParameters, AbstractLSPGrammarExtension extension)
{
PlanExecutor planExecutor = extension.getPlanExecutor();
MutableMap<String, Result> parametersToConstantResult = Maps.mutable.empty();
ExecuteNodeParameterTransformationHelper.buildParameterToConstantResult(executionPlan, inputParameters, parametersToConstantResult);
Identity identity = getIdentity();
return planExecutor.execute(executionPlan, parametersToConstantResult, identity.getName(), identity, context);
}

static Iterable<? extends LegendExecutionResult> generateExecutionPlan(FunctionExecutionSupport executionSupport, SectionState section, String entityPath, Map<String, String> executableArgs, Map<String, Object> inputParameters)
{
AbstractLSPGrammarExtension extension = executionSupport.getExtension();
Expand Down Expand Up @@ -474,7 +479,7 @@ private static Identity getIdentity()
return Optional.ofNullable(subject).map(Identity::makeIdentity).orElseGet(Identity::getAnonymousIdentity);
}

private static void collectResults(FunctionExecutionSupport executionSupport, String entityPath, org.finos.legend.engine.plan.execution.result.Result result, String docId, int secNum, Map<String, Object> inputParameters, SerializationFormat format, Consumer<? super LegendExecutionResult> consumer)
static void collectResults(FunctionExecutionSupport executionSupport, String entityPath, org.finos.legend.engine.plan.execution.result.Result result, String docId, int secNum, Map<String, Object> inputParameters, SerializationFormat format, Consumer<? super LegendExecutionResult> consumer)
{
AbstractLSPGrammarExtension extension = executionSupport.getExtension();

Expand Down Expand Up @@ -544,9 +549,9 @@ class FunctionLegendExecutionResult extends LegendExecutionResult
private final int sectionNum;
private final Map<String, Object> inputParameters;

public FunctionLegendExecutionResult(List<String> ids, Type type, String message, String logMessage, String uri, int sectionNum, Map<String, Object> inputParameters)
private FunctionLegendExecutionResult(List<String> ids, Type type, String message, String logMessage, String uri, int sectionNum, Map<String, Object> inputParameters, String messageType)
{
super(ids, type, message, logMessage, null);
super(ids, type, message, logMessage, null, messageType);
this.uri = uri;
this.sectionNum = sectionNum;
this.inputParameters = inputParameters;
Expand All @@ -567,9 +572,14 @@ public Map<String, Object> getInputParameters()
return inputParameters;
}

public static FunctionLegendExecutionResult newResult(String id, Type type, String message, String logMessage, String uri, int sectionNum, Map<String, Object> inputParameters, String messageType)
{
return new FunctionLegendExecutionResult(Collections.singletonList(id), type, message, logMessage, uri, sectionNum, inputParameters, messageType);
}

public static FunctionLegendExecutionResult newResult(String id, Type type, String message, String logMessage, String uri, int sectionNum, Map<String, Object> inputParameters)
{
return new FunctionLegendExecutionResult(Collections.singletonList(id), type, message, logMessage, uri, sectionNum, inputParameters);
return newResult(id, type, message, logMessage, uri, sectionNum, inputParameters, "json");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.collections.api.factory.Lists;
import org.eclipse.collections.api.list.MutableList;
Expand All @@ -40,6 +41,7 @@
import org.finos.legend.engine.ide.lsp.extension.diagnostic.LegendDiagnostic;
import org.finos.legend.engine.ide.lsp.extension.execution.LegendExecutionResult;
import org.finos.legend.engine.ide.lsp.extension.reference.LegendReference;
import org.finos.legend.engine.ide.lsp.extension.repl.extension.LegendREPLExtensionFeature;
import org.finos.legend.engine.ide.lsp.extension.state.DocumentState;
import org.finos.legend.engine.ide.lsp.extension.state.GlobalState;
import org.finos.legend.engine.ide.lsp.extension.state.NotebookDocumentState;
Expand All @@ -52,13 +54,16 @@
import org.finos.legend.engine.language.pure.grammar.from.domain.DomainParser;
import org.finos.legend.engine.language.pure.grammar.from.extension.PureGrammarParserExtensions;
import org.finos.legend.engine.plan.execution.PlanExecutionContext;
import org.finos.legend.engine.plan.execution.result.Result;
import org.finos.legend.engine.plan.execution.result.serialization.SerializationFormat;
import org.finos.legend.engine.protocol.pure.v1.model.SourceInformation;
import org.finos.legend.engine.protocol.pure.v1.model.context.EngineErrorType;
import org.finos.legend.engine.protocol.pure.v1.model.executionPlan.SingleExecutionPlan;
import org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.raw.Lambda;
import org.finos.legend.engine.repl.autocomplete.Completer;
import org.finos.legend.engine.repl.autocomplete.CompleterExtension;
import org.finos.legend.engine.repl.autocomplete.CompletionResult;
import org.finos.legend.engine.repl.relational.autocomplete.RelationalCompleterExtension;
import org.finos.legend.engine.repl.core.ReplExtension;
import org.finos.legend.engine.shared.core.operational.errorManagement.EngineException;
import org.finos.legend.engine.shared.javaCompiler.JavaCompileException;
import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.LambdaFunction;
Expand All @@ -74,6 +79,8 @@ public class PureBookLSPGrammarExtension implements LegendLSPGrammarExtension
private DomainParser domainParser;
private PureGrammarParserContext parserContext;
private PureLSPGrammarExtension pureGrammarExtension;
private MutableList<ReplExtension> replExtensions;
private MutableList<CompleterExtension> completerExtensions;

@Override
public String getName()
Expand All @@ -89,6 +96,20 @@ public void startup(GlobalState globalState)
this.pureGrammarExtension = globalState.findGrammarExtensionThatImplements(PureLSPGrammarExtension.class)
.findAny()
.orElseThrow(() -> new UnsupportedOperationException("Notebook requires pure grammar extension"));

List<LegendREPLExtensionFeature> replFeatures = globalState
.findFeatureThatImplements(LegendREPLExtensionFeature.class)
.collect(Collectors.toList());

this.replExtensions = replFeatures.stream()
.map(LegendREPLExtensionFeature::getReplExtensions)
.flatMap(List::stream)
.collect(Collectors.toCollection(Lists.mutable::empty));

this.completerExtensions = replFeatures.stream()
.map(LegendREPLExtensionFeature::getCompleterExtensions)
.flatMap(List::stream)
.collect(Collectors.toCollection(Lists.mutable::empty));
}

@Override
Expand Down Expand Up @@ -219,9 +240,9 @@ public Stream<LegendReference> getLegendReferences(SectionState sectionState)
pureModel.getContext()
);
}
catch (Exception ignore)
catch (Exception e)
{
// ignore for now...
LOGGER.warn("Failed to compute references", e);
}
return Stream.empty();
}
Expand Down Expand Up @@ -273,7 +294,25 @@ private Iterable<? extends LegendExecutionResult> executeCell(SectionState secti
private MutableList<LegendExecutionResult> executePlan(SectionState section, Pair<SingleExecutionPlan, PlanExecutionContext> planContext, Map<String, Object> inputParameters)
{
MutableList<LegendExecutionResult> results = Lists.mutable.empty();
FunctionExecutionSupport.executePlan(section.getDocumentState().getGlobalState(), this.pureGrammarExtension, section.getDocumentState().getDocumentId(), section.getSectionNumber(), planContext.getOne(), planContext.getTwo(), "notebook_cell", inputParameters, results);
Result result = FunctionExecutionSupport.executePlan(planContext.getOne(), planContext.getTwo(), inputParameters, this.pureGrammarExtension);

Optional<ReplExtension> extension = this.replExtensions
.stream()
.filter(x -> x.supports(result))
.findAny();

String docId = section.getDocumentState().getDocumentId();
int secNum = section.getSectionNumber();

if (extension.isPresent())
{
results.add(FunctionExecutionSupport.FunctionLegendExecutionResult.newResult("notebook_cell", LegendExecutionResult.Type.SUCCESS, extension.get().print(result), null, docId, secNum, inputParameters, "text"));
}
else
{
FunctionExecutionSupport.collectResults(this.pureGrammarExtension, "notebook_cell", result, docId, secNum, inputParameters, SerializationFormat.DEFAULT, results::add);
}

return results;
}

Expand Down Expand Up @@ -311,7 +350,7 @@ public Iterable<? extends LegendCompletion> getCompletions(SectionState section,
String functionExpression = section.getSection().getInterval(section.getSection().getStartLine(), 0, location.getLine(), column).trim();
functionExpression = functionExpression.replace("\n", "").replace("\r", "");
PureModel pureModel = this.pureGrammarExtension.getCompileResult(section).getPureModel();
CompletionResult completionResult = new Completer(pureModel, Lists.mutable.with(new RelationalCompleterExtension())).complete(functionExpression);
CompletionResult completionResult = new Completer(pureModel, this.completerExtensions).complete(functionExpression);
return completionResult.getCompletion().collect(c -> new LegendCompletion(c.getDisplay(), c.getCompletion()));
}
catch (Exception e)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,72 @@ void executeCell()
);
}

@Test
void relationRendering()
{
SectionState notebook = stateForTestFactory.newPureBookSectionState("notebook.purebook", "#>{test::h2Store.personTable}#->select()->from(test::h2Runtime)");
GlobalState gs = notebook.getDocumentState().getGlobalState();
stateForTestFactory.newSectionState(gs, "database.pure",
"###Relational\n" +
"Database test::h2Store\n" +
"(\n" +
" Table personTable\n" +
" (\n" +
" fullName VARCHAR(100),\n" +
" firmName VARCHAR(100),\n" +
" addressName VARCHAR(100)\n" +
" )\n" +
" Table anotherPersonTable\n" +
" (\n" +
" fullName VARCHAR(100),\n" +
" firmName VARCHAR(100),\n" +
" addressName VARCHAR(100)\n" +
" )\n" +
")");

stateForTestFactory.newSectionState(gs, "connection.pure",
"###Connection\n" +
"RelationalDatabaseConnection test::h2Conn\n" +
"{\n" +
" store: test::h2Store; \n" +
" type: H2;\n" +
" specification: LocalH2\n" +
" {\n" +
" testDataSetupCSV: 'default\\npersonTable\\nfullName,firmName,addressName\\nP1,F1,A1\\nP2,F2,A2\\nP3,,\\nP4,,A3\\nP5,F1,A1\\n---';\n" +
" };\n" +
" auth: DefaultH2;\n" +
"}");

stateForTestFactory.newSectionState(gs, "runtime.pure",
"###Runtime\n" +
"Runtime test::h2Runtime\n" +
"{\n" +
" mappings: [];\n" +
" connectionStores:\n" +
" [\n" +
" test::h2Conn: [ test::h2Store ]\n" +
" ];\n" +
"}");

Assertions.assertEquals(
List.of(FunctionExecutionSupport.FunctionLegendExecutionResult.newResult("notebook_cell", LegendExecutionResult.Type.SUCCESS,
"+--------------+--------------+--------------+\n" +
"| fullName | firmName | addressName |\n" +
"| VARCHAR(100) | VARCHAR(100) | VARCHAR(100) |\n" +
"+--------------+--------------+--------------+\n" +
"| P1 | F1 | A1 |\n" +
"| P2 | F2 | A2 |\n" +
"| P3 | | |\n" +
"| P4 | | A3 |\n" +
"| P5 | F1 | A1 |\n" +
"+--------------+--------------+--------------+\n" +
"5 rows -- 3 columns", null, notebook.getDocumentState().getDocumentId(), 0, Map.of())),
this.extension.execute(notebook, "notebook", "executeCell", Map.of())
);


}

@Test
void completions()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@ public class LegendExecutionResult
private final List<String> ids;
private final Type type;
private final String message;
private final String messageType;
private final String logMessage;
private final TextLocation location;

protected LegendExecutionResult(List<String> ids, Type type, String message, String logMessage, TextLocation location)
protected LegendExecutionResult(List<String> ids, Type type, String message, String logMessage, TextLocation location, String messageType)
{
Objects.requireNonNull(ids, "ids may not be null").forEach(id -> Objects.requireNonNull(id, "id may not be null"));
if (ids.isEmpty())
Expand All @@ -42,6 +43,7 @@ protected LegendExecutionResult(List<String> ids, Type type, String message, Str
this.ids = ids;
this.type = Objects.requireNonNull(type, "type is required");
this.message = Objects.requireNonNull(message, "message is required");
this.messageType = messageType;
this.logMessage = logMessage;
this.location = location;
}
Expand All @@ -57,6 +59,11 @@ public TextLocation getLocation()
return this.location;
}

public String getMessageType()
{
return messageType;
}

public static LegendExecutionResult errorResult(Throwable t, String message, String entityPath, TextLocation location)
{
StringWriter writer = new StringWriter();
Expand Down Expand Up @@ -182,7 +189,7 @@ public String toString()
*/
public static LegendExecutionResult newResult(List<String> ids, Type type, String message, String logMessage, TextLocation location)
{
return new LegendExecutionResult(ids, type, message, logMessage, location);
return new LegendExecutionResult(ids, type, message, logMessage, location, null);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
</modules>

<properties>
<legend.engine.version>4.63.1</legend.engine.version>
<legend.engine.version>4.64.1</legend.engine.version>
<legend.sdlc.version>0.177.0</legend.sdlc.version>

<logback.version>1.4.14</logback.version>
Expand Down

0 comments on commit 1760878

Please sign in to comment.