Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

package org.opensearch.sql.ast.statement;

import java.util.Locale;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import org.opensearch.sql.ast.AbstractNodeVisitor;
Expand All @@ -18,37 +17,20 @@ public class Explain extends Statement {

private final Statement statement;
private final QueryType queryType;
private final ExplainFormat format;
private final ExplainMode mode;

public Explain(Statement statement, QueryType queryType) {
this(statement, queryType, null);
}

public Explain(Statement statement, QueryType queryType, String format) {
public Explain(Statement statement, QueryType queryType, String mode) {
this.statement = statement;
this.queryType = queryType;
this.format = Explain.format(format);
this.mode = ExplainMode.of(mode);
}

@Override
public <R, C> R accept(AbstractNodeVisitor<R, C> visitor, C context) {
return visitor.visitExplain(this, context);
}

public enum ExplainFormat {
SIMPLE,
STANDARD,
EXTENDED,
COST,
/** Formats explain output in yaml format. */
YAML
}

public static ExplainFormat format(String format) {
try {
return ExplainFormat.valueOf(format.toUpperCase(Locale.ROOT));
} catch (Exception e) {
return ExplainFormat.STANDARD;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

package org.opensearch.sql.ast.statement;

import java.util.Locale;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
public enum ExplainMode {
SIMPLE("simple"),
STANDARD("standard"),
EXTENDED("extended"),
COST("cost");

@Getter private final String modeName;

public static ExplainMode of(String mode) {
if (mode == null || mode.isEmpty()) return STANDARD;
try {
return ExplainMode.valueOf(mode.toUpperCase(Locale.ROOT));
} catch (Exception e) {
return ExplainMode.STANDARD;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import lombok.RequiredArgsConstructor;
import lombok.ToString;
import org.apache.calcite.rel.RelNode;
import org.opensearch.sql.ast.statement.Explain;
import org.opensearch.sql.ast.statement.ExplainMode;
import org.opensearch.sql.calcite.CalcitePlanContext;
import org.opensearch.sql.common.response.ResponseListener;
import org.opensearch.sql.data.model.ExprValue;
Expand Down Expand Up @@ -53,7 +53,7 @@ default void execute(

default void explain(
RelNode plan,
Explain.ExplainFormat format,
ExplainMode mode,
CalcitePlanContext context,
ResponseListener<ExplainResponse> listener) {}

Expand Down
21 changes: 10 additions & 11 deletions core/src/main/java/org/opensearch/sql/executor/QueryService.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import org.apache.calcite.tools.Programs;
import org.opensearch.sql.analysis.AnalysisContext;
import org.opensearch.sql.analysis.Analyzer;
import org.opensearch.sql.ast.statement.Explain;
import org.opensearch.sql.ast.statement.ExplainMode;
import org.opensearch.sql.ast.tree.UnresolvedPlan;
import org.opensearch.sql.calcite.CalcitePlanContext;
import org.opensearch.sql.calcite.CalciteRelNodeVisitor;
Expand Down Expand Up @@ -81,11 +81,11 @@ public void explain(
UnresolvedPlan plan,
QueryType queryType,
ResponseListener<ExecutionEngine.ExplainResponse> listener,
Explain.ExplainFormat format) {
ExplainMode mode) {
if (shouldUseCalcite(queryType)) {
explainWithCalcite(plan, queryType, listener, format);
explainWithCalcite(plan, queryType, listener, mode);
} else {
explainWithLegacy(plan, queryType, listener, format, Optional.empty());
explainWithLegacy(plan, queryType, listener, mode, Optional.empty());
}
}

Expand Down Expand Up @@ -134,7 +134,7 @@ public void explainWithCalcite(
UnresolvedPlan plan,
QueryType queryType,
ResponseListener<ExecutionEngine.ExplainResponse> listener,
Explain.ExplainFormat format) {
ExplainMode mode) {
CalcitePlanContext.run(
() -> {
try {
Expand All @@ -146,13 +146,13 @@ public void explainWithCalcite(
() -> {
RelNode relNode = analyze(plan, context);
RelNode calcitePlan = convertToCalcitePlan(relNode, context);
executionEngine.explain(calcitePlan, format, context, listener);
executionEngine.explain(calcitePlan, mode, context, listener);
},
settings);
} catch (Throwable t) {
if (isCalciteFallbackAllowed(t)) {
log.warn("Fallback to V2 query engine since got exception", t);
explainWithLegacy(plan, queryType, listener, format, Optional.of(t));
explainWithLegacy(plan, queryType, listener, mode, Optional.of(t));
} else {
if (t instanceof Error) {
// Calcite may throw AssertError during query execution.
Expand Down Expand Up @@ -198,13 +198,12 @@ public void explainWithLegacy(
UnresolvedPlan plan,
QueryType queryType,
ResponseListener<ExecutionEngine.ExplainResponse> listener,
Explain.ExplainFormat format,
ExplainMode mode,
Optional<Throwable> calciteFailure) {
try {
if (format != null
&& (format != Explain.ExplainFormat.STANDARD && format != Explain.ExplainFormat.YAML)) {
if (mode != null && (mode != ExplainMode.STANDARD)) {
throw new UnsupportedOperationException(
"Explain mode " + format.name() + " is not supported in v2 engine");
"Explain mode " + mode.name() + " is not supported in v2 engine");
}
executionEngine.explain(plan(analyze(plan, queryType)), listener);
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.opensearch.sql.ast.statement.Explain;
import org.opensearch.sql.ast.statement.ExplainMode;
import org.opensearch.sql.common.response.ResponseListener;
import org.opensearch.sql.executor.ExecutionEngine;
import org.opensearch.sql.executor.QueryId;
Expand All @@ -31,5 +31,5 @@ public abstract class AbstractPlan {
* @param listener query explain response listener.
*/
public abstract void explain(
ResponseListener<ExecutionEngine.ExplainResponse> listener, Explain.ExplainFormat format);
ResponseListener<ExecutionEngine.ExplainResponse> listener, ExplainMode mode);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

package org.opensearch.sql.executor.execution;

import org.opensearch.sql.ast.statement.Explain;
import org.opensearch.sql.ast.statement.ExplainMode;
import org.opensearch.sql.ast.tree.UnresolvedPlan;
import org.opensearch.sql.common.response.ResponseListener;
import org.opensearch.sql.executor.ExecutionEngine;
Expand Down Expand Up @@ -47,7 +47,7 @@ public void execute() {

@Override
public void explain(
ResponseListener<ExecutionEngine.ExplainResponse> listener, Explain.ExplainFormat format) {
ResponseListener<ExecutionEngine.ExplainResponse> listener, ExplainMode mode) {
throw new UnsupportedOperationException("CommandPlan does not support explain");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

package org.opensearch.sql.executor.execution;

import org.opensearch.sql.ast.statement.Explain;
import org.opensearch.sql.ast.statement.ExplainMode;
import org.opensearch.sql.common.response.ResponseListener;
import org.opensearch.sql.executor.ExecutionEngine;
import org.opensearch.sql.executor.QueryId;
Expand All @@ -15,7 +15,7 @@
public class ExplainPlan extends AbstractPlan {

private final AbstractPlan plan;
private final Explain.ExplainFormat format;
private final ExplainMode mode;

private final ResponseListener<ExecutionEngine.ExplainResponse> explainListener;

Expand All @@ -24,22 +24,22 @@ public ExplainPlan(
QueryId queryId,
QueryType queryType,
AbstractPlan plan,
Explain.ExplainFormat format,
ExplainMode mode,
ResponseListener<ExecutionEngine.ExplainResponse> explainListener) {
super(queryId, queryType);
this.plan = plan;
this.format = format;
this.mode = mode;
this.explainListener = explainListener;
}

@Override
public void execute() {
plan.explain(explainListener, format);
plan.explain(explainListener, mode);
}

@Override
public void explain(
ResponseListener<ExecutionEngine.ExplainResponse> listener, Explain.ExplainFormat format) {
ResponseListener<ExecutionEngine.ExplainResponse> listener, ExplainMode mode) {
throw new UnsupportedOperationException("explain query can not been explained.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import java.util.Optional;
import org.apache.commons.lang3.NotImplementedException;
import org.opensearch.sql.ast.statement.Explain;
import org.opensearch.sql.ast.statement.ExplainMode;
import org.opensearch.sql.ast.tree.Paginate;
import org.opensearch.sql.ast.tree.UnresolvedPlan;
import org.opensearch.sql.common.response.ResponseListener;
Expand Down Expand Up @@ -69,13 +69,13 @@ public void execute() {

@Override
public void explain(
ResponseListener<ExecutionEngine.ExplainResponse> listener, Explain.ExplainFormat format) {
ResponseListener<ExecutionEngine.ExplainResponse> listener, ExplainMode mode) {
if (pageSize.isPresent()) {
listener.onFailure(
new NotImplementedException(
"`explain` feature for paginated requests is not implemented yet."));
} else {
queryService.explain(plan, getQueryType(), listener, format);
queryService.explain(plan, getQueryType(), listener, mode);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.apache.commons.lang3.tuple.Pair;
import org.opensearch.sql.ast.AbstractNodeVisitor;
import org.opensearch.sql.ast.statement.Explain;
import org.opensearch.sql.ast.statement.ExplainMode;
import org.opensearch.sql.ast.statement.Query;
import org.opensearch.sql.ast.statement.Statement;
import org.opensearch.sql.ast.tree.CloseCursor;
Expand Down Expand Up @@ -77,7 +78,7 @@ public AbstractPlan create(
new QueryPlan(
queryId, queryType, new FetchCursor(cursor), queryService, queryResponseListener);
return isExplain
? new ExplainPlan(queryId, queryType, plan, Explain.format(format), explainListener)
? new ExplainPlan(queryId, queryType, plan, ExplainMode.of(format), explainListener)
: plan;
}

Expand Down Expand Up @@ -137,7 +138,7 @@ public AbstractPlan visitExplain(
QueryId.queryId(),
node.getQueryType(),
create(node.getStatement(), NO_CONSUMER_RESPONSE_LISTENER, context.getRight()),
node.getFormat(),
node.getMode(),
context.getRight());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.opensearch.sql.analysis.Analyzer;
import org.opensearch.sql.ast.statement.Explain;
import org.opensearch.sql.ast.statement.ExplainMode;
import org.opensearch.sql.ast.tree.UnresolvedPlan;
import org.opensearch.sql.common.response.ResponseListener;
import org.opensearch.sql.common.setting.Settings;
Expand Down Expand Up @@ -59,7 +59,7 @@ class QueryServiceTest {

@Mock private Split split;

private final Explain.ExplainFormat format = Explain.ExplainFormat.STANDARD;
private final ExplainMode mode = ExplainMode.STANDARD;

@Test
public void executeWithoutContext() {
Expand Down Expand Up @@ -222,7 +222,7 @@ public void onFailure(Exception e) {
fail();
}
},
format);
mode);
}

void handledByExplainOnFailure() {
Expand All @@ -240,7 +240,7 @@ public void onFailure(Exception e) {
assertTrue(e instanceof IllegalStateException);
}
},
format);
mode);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import org.junit.jupiter.api.DisplayNameGeneration;
import org.junit.jupiter.api.DisplayNameGenerator;
import org.junit.jupiter.api.Test;
import org.opensearch.sql.ast.statement.Explain;
import org.opensearch.sql.ast.statement.ExplainMode;
import org.opensearch.sql.ast.tree.UnresolvedPlan;
import org.opensearch.sql.common.response.ResponseListener;
import org.opensearch.sql.executor.QueryId;
Expand Down Expand Up @@ -63,7 +63,7 @@ public void explain_not_supported() {
QueryService qs = mock(QueryService.class);
ResponseListener listener = mock(ResponseListener.class);
ResponseListener explainListener = mock(ResponseListener.class);
Explain.ExplainFormat format = mock(Explain.ExplainFormat.class);
ExplainMode mode = mock(ExplainMode.class);

var exception =
assertThrows(
Expand All @@ -75,7 +75,7 @@ public void explain_not_supported() {
mock(UnresolvedPlan.class),
qs,
listener)
.explain(explainListener, format));
.explain(explainListener, mode));
assertEquals("CommandPlan does not support explain", exception.getMessage());

verify(listener, never()).onResponse(any());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.opensearch.sql.ast.statement.Explain;
import org.opensearch.sql.ast.statement.ExplainMode;
import org.opensearch.sql.common.response.ResponseListener;
import org.opensearch.sql.executor.ExecutionEngine;
import org.opensearch.sql.executor.QueryId;
Expand All @@ -32,29 +32,27 @@ public class ExplainPlanTest {

@Mock private ResponseListener<ExecutionEngine.ExplainResponse> explainListener;

@Mock private Explain.ExplainFormat format;
@Mock private ExplainMode mode;

@Test
public void execute() {
doNothing().when(queryPlan).explain(any(), any());

ExplainPlan explainPlan =
new ExplainPlan(queryId, queryType, queryPlan, format, explainListener);
ExplainPlan explainPlan = new ExplainPlan(queryId, queryType, queryPlan, mode, explainListener);
explainPlan.execute();

verify(queryPlan, times(1)).explain(explainListener, format);
verify(queryPlan, times(1)).explain(explainListener, mode);
}

@Test
public void explainThrowException() {
ExplainPlan explainPlan =
new ExplainPlan(queryId, queryType, queryPlan, format, explainListener);
ExplainPlan explainPlan = new ExplainPlan(queryId, queryType, queryPlan, mode, explainListener);

UnsupportedOperationException unsupportedExplainException =
assertThrows(
UnsupportedOperationException.class,
() -> {
explainPlan.explain(explainListener, format);
explainPlan.explain(explainListener, mode);
});
assertEquals("explain query can not been explained.", unsupportedExplainException.getMessage());
}
Expand Down
Loading
Loading