Skip to content

Commit b9e2761

Browse files
authored
Enable Calcite by default and implicit fallback the unsupported commands (#4372)
* Enable Calcite by default and implicit fallback the unsupported commands Signed-off-by: Lantao Jin <[email protected]> * Update docs Signed-off-by: Lantao Jin <[email protected]> * remove cmd/information_schema.rst file and move the content to ppl/admin/datasources.rst Signed-off-by: Lantao Jin <[email protected]> * remove information_schema.rst from category.json Signed-off-by: Lantao Jin <[email protected]> --------- Signed-off-by: Lantao Jin <[email protected]>
1 parent 585a04c commit b9e2761

File tree

34 files changed

+249
-174
lines changed

34 files changed

+249
-174
lines changed

core/src/main/java/org/opensearch/sql/analysis/Analyzer.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
import org.opensearch.sql.ast.tree.Rename;
8787
import org.opensearch.sql.ast.tree.Reverse;
8888
import org.opensearch.sql.ast.tree.Rex;
89+
import org.opensearch.sql.ast.tree.SPath;
8990
import org.opensearch.sql.ast.tree.Search;
9091
import org.opensearch.sql.ast.tree.Sort;
9192
import org.opensearch.sql.ast.tree.Sort.SortOption;
@@ -95,6 +96,7 @@
9596
import org.opensearch.sql.ast.tree.Trendline;
9697
import org.opensearch.sql.ast.tree.UnresolvedPlan;
9798
import org.opensearch.sql.ast.tree.Values;
99+
import org.opensearch.sql.ast.tree.Window;
98100
import org.opensearch.sql.common.antlr.SyntaxCheckException;
99101
import org.opensearch.sql.data.model.ExprMissingValue;
100102
import org.opensearch.sql.data.type.ExprCoreType;
@@ -755,11 +757,21 @@ public LogicalPlan visitReverse(Reverse node, AnalysisContext context) {
755757
throw getOnlyForCalciteException("Reverse");
756758
}
757759

760+
@Override
761+
public LogicalPlan visitSpath(SPath node, AnalysisContext context) {
762+
throw getOnlyForCalciteException("Spath");
763+
}
764+
758765
@Override
759766
public LogicalPlan visitTimechart(Timechart node, AnalysisContext context) {
760767
throw getOnlyForCalciteException("Timechart");
761768
}
762769

770+
@Override
771+
public LogicalPlan visitWindow(Window node, AnalysisContext context) {
772+
throw getOnlyForCalciteException("Window");
773+
}
774+
763775
@Override
764776
public LogicalPlan visitRegex(Regex node, AnalysisContext context) {
765777
throw getOnlyForCalciteException("Regex");

core/src/main/java/org/opensearch/sql/analysis/ExpressionAnalyzer.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import org.opensearch.sql.ast.expression.HighlightFunction;
3939
import org.opensearch.sql.ast.expression.In;
4040
import org.opensearch.sql.ast.expression.Interval;
41+
import org.opensearch.sql.ast.expression.LambdaFunction;
4142
import org.opensearch.sql.ast.expression.Literal;
4243
import org.opensearch.sql.ast.expression.Not;
4344
import org.opensearch.sql.ast.expression.Or;
@@ -479,6 +480,11 @@ public Expression visitInSubquery(InSubquery node, AnalysisContext context) {
479480
throw getOnlyForCalciteException("Subsearch");
480481
}
481482

483+
@Override
484+
public Expression visitLambdaFunction(LambdaFunction node, AnalysisContext context) {
485+
throw getOnlyForCalciteException("Lambda function");
486+
}
487+
482488
/**
483489
* If QualifiedName is actually a reserved metadata field, return the expr type associated with
484490
* the metadata field.

core/src/main/java/org/opensearch/sql/calcite/CalciteRelNodeVisitor.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package org.opensearch.sql.calcite;
77

88
import static org.apache.calcite.sql.SqlKind.AS;
9+
import static org.opensearch.sql.analysis.DataSourceSchemaIdentifierNameResolver.INFORMATION_SCHEMA_NAME;
910
import static org.opensearch.sql.ast.tree.Join.JoinType.ANTI;
1011
import static org.opensearch.sql.ast.tree.Join.JoinType.SEMI;
1112
import static org.opensearch.sql.ast.tree.Sort.NullOrder.NULL_FIRST;
@@ -20,6 +21,7 @@
2021
import static org.opensearch.sql.calcite.utils.PlanUtils.getRelation;
2122
import static org.opensearch.sql.calcite.utils.PlanUtils.getRexCall;
2223
import static org.opensearch.sql.calcite.utils.PlanUtils.transformPlanToAttachChild;
24+
import static org.opensearch.sql.utils.SystemIndexUtils.DATASOURCES_TABLE_NAME;
2325

2426
import com.google.common.base.Strings;
2527
import com.google.common.collect.ImmutableList;
@@ -65,6 +67,7 @@
6567
import org.apache.commons.lang3.ArrayUtils;
6668
import org.apache.commons.lang3.tuple.Pair;
6769
import org.checkerframework.checker.nullness.qual.Nullable;
70+
import org.opensearch.sql.analysis.DataSourceSchemaIdentifierNameResolver;
6871
import org.opensearch.sql.ast.AbstractNodeVisitor;
6972
import org.opensearch.sql.ast.EmptySourcePropagateVisitor;
7073
import org.opensearch.sql.ast.Node;
@@ -136,6 +139,7 @@
136139
import org.opensearch.sql.calcite.utils.WildcardUtils;
137140
import org.opensearch.sql.common.patterns.PatternUtils;
138141
import org.opensearch.sql.common.utils.StringUtils;
142+
import org.opensearch.sql.datasource.DataSourceService;
139143
import org.opensearch.sql.exception.CalciteUnsupportedException;
140144
import org.opensearch.sql.exception.SemanticCheckException;
141145
import org.opensearch.sql.expression.function.BuiltinFunctionName;
@@ -148,10 +152,12 @@ public class CalciteRelNodeVisitor extends AbstractNodeVisitor<RelNode, CalciteP
148152

149153
private final CalciteRexNodeVisitor rexVisitor;
150154
private final CalciteAggCallVisitor aggVisitor;
155+
private final DataSourceService dataSourceService;
151156

152-
public CalciteRelNodeVisitor() {
157+
public CalciteRelNodeVisitor(DataSourceService dataSourceService) {
153158
this.rexVisitor = new CalciteRexNodeVisitor(this);
154159
this.aggVisitor = new CalciteAggCallVisitor(rexVisitor);
160+
this.dataSourceService = dataSourceService;
155161
}
156162

157163
public RelNode analyze(UnresolvedPlan unresolved, CalcitePlanContext context) {
@@ -160,6 +166,21 @@ public RelNode analyze(UnresolvedPlan unresolved, CalcitePlanContext context) {
160166

161167
@Override
162168
public RelNode visitRelation(Relation node, CalcitePlanContext context) {
169+
DataSourceSchemaIdentifierNameResolver nameResolver =
170+
new DataSourceSchemaIdentifierNameResolver(
171+
dataSourceService, node.getTableQualifiedName().getParts());
172+
if (!nameResolver
173+
.getDataSourceName()
174+
.equals(DataSourceSchemaIdentifierNameResolver.DEFAULT_DATASOURCE_NAME)) {
175+
throw new CalciteUnsupportedException(
176+
"Datasource " + nameResolver.getDataSourceName() + " is unsupported in Calcite");
177+
}
178+
if (nameResolver.getIdentifierName().equals(DATASOURCES_TABLE_NAME)) {
179+
throw new CalciteUnsupportedException("SHOW DATASOURCES is unsupported in Calcite");
180+
}
181+
if (nameResolver.getSchemaName().equals(INFORMATION_SCHEMA_NAME)) {
182+
throw new CalciteUnsupportedException("information_schema is unsupported in Calcite");
183+
}
163184
context.relBuilder.scan(node.getTableQualifiedName().getParts());
164185
return context.relBuilder.peek();
165186
}
@@ -1364,7 +1385,7 @@ public RelNode visitDedupe(Dedupe node, CalcitePlanContext context) {
13641385
throw new IllegalArgumentException("Number of duplicate events must be greater than 0");
13651386
}
13661387
if (consecutive) {
1367-
throw new UnsupportedOperationException("Consecutive deduplication is not supported");
1388+
throw new CalciteUnsupportedException("Consecutive deduplication is unsupported in Calcite");
13681389
}
13691390
// Columns to deduplicate
13701391
List<RexNode> dedupeFields =

core/src/main/java/org/opensearch/sql/calcite/CalciteRexNodeVisitor.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import org.opensearch.sql.ast.expression.Compare;
4848
import org.opensearch.sql.ast.expression.EqualTo;
4949
import org.opensearch.sql.ast.expression.Function;
50+
import org.opensearch.sql.ast.expression.HighlightFunction;
5051
import org.opensearch.sql.ast.expression.In;
5152
import org.opensearch.sql.ast.expression.Interval;
5253
import org.opensearch.sql.ast.expression.LambdaFunction;
@@ -56,6 +57,7 @@
5657
import org.opensearch.sql.ast.expression.Or;
5758
import org.opensearch.sql.ast.expression.QualifiedName;
5859
import org.opensearch.sql.ast.expression.RelevanceFieldList;
60+
import org.opensearch.sql.ast.expression.ScoreFunction;
5961
import org.opensearch.sql.ast.expression.Span;
6062
import org.opensearch.sql.ast.expression.SpanUnit;
6163
import org.opensearch.sql.ast.expression.UnresolvedArgument;
@@ -649,6 +651,16 @@ public RexNode visitWhen(When node, CalcitePlanContext context) {
649651
throw new CalciteUnsupportedException("CastWhen function is unsupported in Calcite");
650652
}
651653

654+
@Override
655+
public RexNode visitHighlightFunction(HighlightFunction node, CalcitePlanContext context) {
656+
throw new CalciteUnsupportedException("Highlight function is unsupported in Calcite");
657+
}
658+
659+
@Override
660+
public RexNode visitScoreFunction(ScoreFunction node, CalcitePlanContext context) {
661+
throw new CalciteUnsupportedException("Score function is unsupported in Calcite");
662+
}
663+
652664
@Override
653665
public RexNode visitRelevanceFieldList(RelevanceFieldList node, CalcitePlanContext context) {
654666
List<RexNode> varArgRexNodeList = new ArrayList<>();

core/src/main/java/org/opensearch/sql/executor/QueryService.java

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.security.PrivilegedAction;
1010
import java.util.List;
1111
import java.util.Optional;
12+
import javax.annotation.Nullable;
1213
import lombok.AllArgsConstructor;
1314
import lombok.Getter;
1415
import lombok.RequiredArgsConstructor;
@@ -54,13 +55,12 @@ public class QueryService {
5455
private final Analyzer analyzer;
5556
private final ExecutionEngine executionEngine;
5657
private final Planner planner;
57-
58-
@Getter(lazy = true)
59-
private final CalciteRelNodeVisitor relNodeVisitor = new CalciteRelNodeVisitor();
60-
6158
private DataSourceService dataSourceService;
6259
private Settings settings;
6360

61+
@Getter(lazy = true)
62+
private final CalciteRelNodeVisitor relNodeVisitor = new CalciteRelNodeVisitor(dataSourceService);
63+
6464
/** Execute the {@link UnresolvedPlan}, using {@link ResponseListener} to get response.<br> */
6565
public void execute(
6666
UnresolvedPlan plan,
@@ -104,7 +104,7 @@ public void executeWithCalcite(
104104
return null;
105105
});
106106
} catch (Throwable t) {
107-
if (isCalciteFallbackAllowed() && !(t instanceof NonFallbackCalciteException)) {
107+
if (isCalciteFallbackAllowed(t) && !(t instanceof NonFallbackCalciteException)) {
108108
log.warn("Fallback to V2 query engine since got exception", t);
109109
executeWithLegacy(plan, queryType, listener, Optional.of(t));
110110
} else {
@@ -140,7 +140,7 @@ public void explainWithCalcite(
140140
return null;
141141
});
142142
} catch (Throwable t) {
143-
if (isCalciteFallbackAllowed()) {
143+
if (isCalciteFallbackAllowed(t)) {
144144
log.warn("Fallback to V2 query engine since got exception", t);
145145
explainWithLegacy(plan, queryType, listener, format, Optional.of(t));
146146
} else {
@@ -162,7 +162,7 @@ public void executeWithLegacy(
162162
try {
163163
executePlan(analyze(plan, queryType), PlanContext.emptyPlanContext(), listener);
164164
} catch (Exception e) {
165-
if (shouldUseCalcite(queryType) && isCalciteFallbackAllowed()) {
165+
if (shouldUseCalcite(queryType) && isCalciteFallbackAllowed(null)) {
166166
// if there is a failure thrown from Calcite and execution after fallback V2
167167
// keeps failure, we should throw the failure from Calcite.
168168
calciteFailure.ifPresentOrElse(
@@ -195,7 +195,7 @@ public void explainWithLegacy(
195195
}
196196
executionEngine.explain(plan(analyze(plan, queryType)), listener);
197197
} catch (Exception e) {
198-
if (shouldUseCalcite(queryType) && isCalciteFallbackAllowed()) {
198+
if (shouldUseCalcite(queryType) && isCalciteFallbackAllowed(null)) {
199199
// if there is a failure thrown from Calcite and execution after fallback V2
200200
// keeps failure, we should throw the failure from Calcite.
201201
calciteFailure.ifPresentOrElse(
@@ -260,15 +260,21 @@ public RelNode optimize(RelNode plan, CalcitePlanContext context) {
260260
SystemLimitType.QUERY_SIZE_LIMIT, plan, context.relBuilder.literal(context.querySizeLimit));
261261
}
262262

263-
private boolean isCalciteFallbackAllowed() {
264-
if (settings != null) {
265-
Boolean fallback_allowed = settings.getSettingValue(Settings.Key.CALCITE_FALLBACK_ALLOWED);
266-
if (fallback_allowed == null) {
267-
return false;
268-
}
269-
return fallback_allowed;
270-
} else {
263+
private boolean isCalciteFallbackAllowed(@Nullable Throwable t) {
264+
// We always allow fallback the query failed with CalciteUnsupportedException.
265+
// This is for avoiding breaking changes when enable Calcite by default.
266+
if (t instanceof CalciteUnsupportedException) {
271267
return true;
268+
} else {
269+
if (settings != null) {
270+
Boolean fallback_allowed = settings.getSettingValue(Settings.Key.CALCITE_FALLBACK_ALLOWED);
271+
if (fallback_allowed == null) {
272+
return false;
273+
}
274+
return fallback_allowed;
275+
} else {
276+
return true;
277+
}
272278
}
273279
}
274280

core/src/test/java/org/opensearch/sql/calcite/CalciteRelNodeVisitorSearchSimpleTest.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@
1111

1212
import org.junit.jupiter.api.BeforeEach;
1313
import org.junit.jupiter.api.Test;
14+
import org.mockito.Mock;
1415
import org.opensearch.sql.ast.dsl.AstDSL;
1516
import org.opensearch.sql.ast.tree.Relation;
1617
import org.opensearch.sql.ast.tree.Search;
18+
import org.opensearch.sql.datasource.DataSourceService;
1719

1820
/**
1921
* Simple tests for CalciteRelNodeVisitor.visitSearch method. Tests basic functionality without
@@ -22,10 +24,11 @@
2224
public class CalciteRelNodeVisitorSearchSimpleTest {
2325

2426
private CalciteRelNodeVisitor visitor;
27+
@Mock DataSourceService dataSourceService;
2528

2629
@BeforeEach
2730
public void setUp() {
28-
visitor = new CalciteRelNodeVisitor();
31+
visitor = new CalciteRelNodeVisitor(dataSourceService);
2932
}
3033

3134
@Test

core/src/test/java/org/opensearch/sql/calcite/CalciteRexNodeVisitorTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.opensearch.sql.ast.expression.LambdaFunction;
3030
import org.opensearch.sql.ast.expression.QualifiedName;
3131
import org.opensearch.sql.calcite.utils.CalciteToolsHelper;
32+
import org.opensearch.sql.datasource.DataSourceService;
3233
import org.opensearch.sql.executor.QueryType;
3334

3435
@ExtendWith(MockitoExtension.class)
@@ -44,6 +45,7 @@ public class CalciteRexNodeVisitorTest {
4445
@Mock RelDataType accType;
4546
@Mock QualifiedName functionArg1;
4647
@Mock QualifiedName functionArg2;
48+
@Mock DataSourceService dataSourceService;
4749

4850
static CalciteRexNodeVisitor visitor;
4951
static CalciteRelNodeVisitor relNodeVisitor;
@@ -57,7 +59,7 @@ public class CalciteRexNodeVisitorTest {
5759

5860
@BeforeEach
5961
public void setUpContext() {
60-
relNodeVisitor = new CalciteRelNodeVisitor();
62+
relNodeVisitor = new CalciteRelNodeVisitor(dataSourceService);
6163
visitor = new CalciteRexNodeVisitor(relNodeVisitor);
6264
when(relBuilder.getRexBuilder()).thenReturn(rexBuilder);
6365
when(rexBuilder.getTypeFactory()).thenReturn(TYPE_FACTORY);

docs/category.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
"user/ppl/cmd/dedup.rst",
1212
"user/ppl/cmd/describe.rst",
1313
"user/ppl/cmd/showdatasources.rst",
14-
"user/ppl/cmd/information_schema.rst",
1514
"user/ppl/cmd/eval.rst",
1615
"user/ppl/cmd/fillnull.rst",
1716
"user/ppl/cmd/grok.rst",

docs/dev/intro-v3-engine.md

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# PPL Engine V3 (for 3.0.0)
1+
# PPL Engine V3
22

33
---
44
## 1. Motivations
@@ -30,6 +30,8 @@ In the initial release of the V3 engine (3.0.0), the main new features focus on
3030
* **[Lookup](../user/ppl/cmd/lookup.rst) Command**
3131
* **[Subquery](../user/ppl/cmd/subquery.rst) Command**
3232

33+
V3 (Calcite integration) engine is enabled by default in 3.3.0.
34+
3335
---
3436
## 3.What are Changed
3537

@@ -51,7 +53,8 @@ Because of implementation changed internally, following behaviors are changed fr
5153

5254
### 3.2 Fallback Mechanism
5355

54-
As v3 engine is experimental in 3.0.0, not all PPL commands could work under this new engine. Those unsupported queries will be forwarded to V2 engine by fallback mechanism. To avoid impact on your side, normally you won't see any difference in a query response. If you want to check if and why your query falls back to be handled by V2 engine, please check OpenSearch log for "Fallback to V2 query engine since ...".
56+
- As v3 engine is experimental in 3.0.0, not all PPL commands could work under this new engine. Those unsupported queries will be forwarded to V2 engine by fallback mechanism. To avoid impact on your side, normally you won't see any difference in a query response. If you want to check if and why your query falls back to be handled by V2 engine, please check OpenSearch log for "Fallback to V2 query engine since ...".
57+
- Since 3.2.0, the fallback mechanism is disabled by default, to enable fallback, set `plugins.calcite.fallback.allowed=true`.
5558

5659
### 3.3 Limitations
5760

@@ -64,22 +67,15 @@ For the following commands or functions, we add some defensive restrictions to e
6467

6568
For the following functionalities in V3 engine, the query will be forwarded to the V2 query engine and thus you cannot use new features in [2. What's New](#2-whats-new).
6669

67-
#### Unsupported functionalities
70+
#### Unsupported functionalities (up to latest)
6871
- All SQL queries
72+
- PPL queries against non-OpenSearch data sources
6973
- `dedup` with `consecutive=true`
7074
- Search relevant commands
7175
- AD
7276
- ML
7377
- Kmeans
7478
- Commands with `fetch_size` parameter
75-
- Search relevant functions
76-
- match
77-
- match_phrase
78-
- match_bool_prefix
79-
- match_phrase_prefix
80-
- simple_query_string
81-
- query_string
82-
- multi_match
8379
- [Existed limitations of V2](intro-v2-engine.md#33-limitations)
8480

8581
---

docs/user/admin/settings.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -751,9 +751,10 @@ Description
751751

752752
You can enable Calcite as new query optimizer and execution engine to all coming requests.
753753

754-
1. The default value is false since 3.0.0.
755-
2. This setting is node scope.
756-
3. This setting can be updated dynamically.
754+
1. The default value is false in 3.0, 3.1 and 3.2.
755+
2. The default value is true since 3.3.0.
756+
3. This setting is node scope.
757+
4. This setting can be updated dynamically.
757758

758759
Check `introduce v3 engine <../../../dev/intro-v3-engine.md>`_ for more details.
759760
Check `join doc <../../ppl/cmd/join.rst>`_ for example.

0 commit comments

Comments
 (0)