Skip to content

Commit 3551fab

Browse files
committed
First commit for Calcite integration
Signed-off-by: Lantao Jin <[email protected]>
1 parent e7be8ca commit 3551fab

File tree

88 files changed

+3995
-224
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

88 files changed

+3995
-224
lines changed

build.gradle

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,18 @@ allprojects {
119119
resolutionStrategy.force "org.jetbrains.kotlin:kotlin-stdlib:1.9.10"
120120
resolutionStrategy.force "org.jetbrains.kotlin:kotlin-stdlib-common:1.9.10"
121121
resolutionStrategy.force "net.bytebuddy:byte-buddy:1.14.9"
122+
resolutionStrategy.force "org.apache.httpcomponents.client5:httpclient5:5.3.1"
123+
resolutionStrategy.force 'org.apache.httpcomponents.core5:httpcore5:5.2.5'
124+
resolutionStrategy.force 'org.apache.httpcomponents.core5:httpcore5-h2:5.2.5'
125+
resolutionStrategy.force 'com.fasterxml.jackson.core:jackson-annotations:2.17.2'
126+
resolutionStrategy.force 'com.google.protobuf:protobuf-java:3.25.5'
127+
resolutionStrategy.force 'org.locationtech.jts:jts-core:1.19.0'
128+
resolutionStrategy.force 'com.google.errorprone:error_prone_annotations:2.28.0'
129+
resolutionStrategy.force 'org.checkerframework:checker-qual:3.43.0'
130+
resolutionStrategy.force 'org.apache.commons:commons-lang3:3.13.0'
131+
resolutionStrategy.force 'org.apache.commons:commons-text:1.11.0'
132+
resolutionStrategy.force 'commons-io:commons-io:2.15.0'
133+
resolutionStrategy.force 'org.yaml:snakeyaml:2.2'
122134
}
123135
}
124136

core/build.gradle

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,14 @@ dependencies {
5656
api "com.fasterxml.jackson.core:jackson-annotations:${versions.jackson}"
5757
api group: 'com.google.code.gson', name: 'gson', version: '2.8.9'
5858
api group: 'com.tdunning', name: 't-digest', version: '3.3'
59+
api 'org.apache.calcite:calcite-core:1.38.0'
60+
api 'org.apache.calcite:calcite-linq4j:1.38.0'
5961
api project(':common')
6062
implementation "com.github.seancfoley:ipaddress:5.4.2"
6163

64+
annotationProcessor('org.immutables:value:2.8.8')
65+
compileOnly('org.immutables:value-annotations:2.8.8')
66+
6267
testImplementation('org.junit.jupiter:junit-jupiter:5.9.3')
6368
testImplementation group: 'org.hamcrest', name: 'hamcrest-library', version: '2.1'
6469
testImplementation group: 'org.mockito', name: 'mockito-core', version: '5.7.0'

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

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
import org.opensearch.sql.ast.tree.Rename;
6666
import org.opensearch.sql.ast.tree.Sort;
6767
import org.opensearch.sql.ast.tree.Sort.SortOption;
68+
import org.opensearch.sql.ast.tree.SubqueryAlias;
6869
import org.opensearch.sql.ast.tree.TableFunction;
6970
import org.opensearch.sql.ast.tree.Trendline;
7071
import org.opensearch.sql.ast.tree.UnresolvedPlan;
@@ -143,6 +144,27 @@ public LogicalPlan analyze(UnresolvedPlan unresolved, AnalysisContext context) {
143144
return unresolved.accept(this, context);
144145
}
145146

147+
@Override
148+
public LogicalPlan visitSubqueryAlias(SubqueryAlias node, AnalysisContext context) {
149+
LogicalPlan child = analyze(node.getChild().get(0), context);
150+
if (child instanceof LogicalRelation) {
151+
// Put index name or its alias in index namespace on type environment so qualifier
152+
// can be removed when analyzing qualified name. The value (expr type) here doesn't matter.
153+
TypeEnvironment curEnv = context.peek();
154+
curEnv.define(
155+
new Symbol(
156+
Namespace.INDEX_NAME,
157+
(node.getAlias() == null)
158+
? ((LogicalRelation) child).getRelationName()
159+
: node.getAlias()),
160+
STRUCT);
161+
return child;
162+
} else {
163+
// TODO
164+
throw new UnsupportedOperationException("SubqueryAlias is only supported in table alias");
165+
}
166+
}
167+
146168
@Override
147169
public LogicalPlan visitRelation(Relation node, AnalysisContext context) {
148170
QualifiedName qualifiedName = node.getTableQualifiedName();
@@ -170,12 +192,6 @@ public LogicalPlan visitRelation(Relation node, AnalysisContext context) {
170192
.getReservedFieldTypes()
171193
.forEach((k, v) -> curEnv.define(new Symbol(Namespace.HIDDEN_FIELD_NAME, k), v));
172194

173-
// Put index name or its alias in index namespace on type environment so qualifier
174-
// can be removed when analyzing qualified name. The value (expr type) here doesn't matter.
175-
curEnv.define(
176-
new Symbol(Namespace.INDEX_NAME, (node.getAlias() == null) ? tableName : node.getAlias()),
177-
STRUCT);
178-
179195
return new LogicalRelation(tableName, table);
180196
}
181197

@@ -306,7 +322,7 @@ public LogicalPlan visitAggregation(Aggregation node, AnalysisContext context) {
306322
for (UnresolvedExpression expr : node.getAggExprList()) {
307323
NamedExpression aggExpr = namedExpressionAnalyzer.analyze(expr, context);
308324
aggregatorBuilder.add(
309-
new NamedAggregator(aggExpr.getNameOrAlias(), (Aggregator) aggExpr.getDelegated()));
325+
new NamedAggregator(aggExpr.getName(), (Aggregator) aggExpr.getDelegated()));
310326
}
311327

312328
ImmutableList.Builder<NamedExpression> groupbyBuilder = new ImmutableList.Builder<>();
@@ -331,8 +347,7 @@ public LogicalPlan visitAggregation(Aggregation node, AnalysisContext context) {
331347
newEnv.define(
332348
new Symbol(Namespace.FIELD_NAME, aggregator.getName()), aggregator.type()));
333349
groupBys.forEach(
334-
group ->
335-
newEnv.define(new Symbol(Namespace.FIELD_NAME, group.getNameOrAlias()), group.type()));
350+
group -> newEnv.define(new Symbol(Namespace.FIELD_NAME, group.getName()), group.type()));
336351
return new LogicalAggregation(child, aggregators, groupBys);
337352
}
338353

@@ -425,8 +440,7 @@ public LogicalPlan visitProject(Project node, AnalysisContext context) {
425440
context.push();
426441
TypeEnvironment newEnv = context.peek();
427442
namedExpressions.forEach(
428-
expr ->
429-
newEnv.define(new Symbol(Namespace.FIELD_NAME, expr.getNameOrAlias()), expr.type()));
443+
expr -> newEnv.define(new Symbol(Namespace.FIELD_NAME, expr.getName()), expr.type()));
430444
List<NamedExpression> namedParseExpressions = context.getNamedParseExpressions();
431445
return new LogicalProject(child, namedExpressions, namedParseExpressions);
432446
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ private Expression visitMetadata(
416416
private Expression visitIdentifier(String ident, AnalysisContext context) {
417417
// ParseExpression will always override ReferenceExpression when ident conflicts
418418
for (NamedExpression expr : context.getNamedParseExpressions()) {
419-
if (expr.getNameOrAlias().equals(ident) && expr.getDelegated() instanceof ParseExpression) {
419+
if (expr.getName().equals(ident) && expr.getDelegated() instanceof ParseExpression) {
420420
return expr.getDelegated();
421421
}
422422
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ public Void visitAggregation(LogicalAggregation plan, Void context) {
144144
groupBy ->
145145
expressionMap.put(
146146
groupBy.getDelegated(),
147-
new ReferenceExpression(groupBy.getNameOrAlias(), groupBy.type())));
147+
new ReferenceExpression(groupBy.getName(), groupBy.type())));
148148
return null;
149149
}
150150

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

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import lombok.RequiredArgsConstructor;
99
import org.opensearch.sql.ast.AbstractNodeVisitor;
1010
import org.opensearch.sql.ast.expression.Alias;
11-
import org.opensearch.sql.ast.expression.QualifiedName;
1211
import org.opensearch.sql.ast.expression.UnresolvedExpression;
1312
import org.opensearch.sql.expression.DSL;
1413
import org.opensearch.sql.expression.NamedExpression;
@@ -28,18 +27,6 @@ public NamedExpression analyze(UnresolvedExpression expression, AnalysisContext
2827

2928
@Override
3029
public NamedExpression visitAlias(Alias node, AnalysisContext context) {
31-
return DSL.named(
32-
unqualifiedNameIfFieldOnly(node, context),
33-
node.getDelegated().accept(expressionAnalyzer, context),
34-
node.getAlias());
35-
}
36-
37-
private String unqualifiedNameIfFieldOnly(Alias node, AnalysisContext context) {
38-
UnresolvedExpression selectItem = node.getDelegated();
39-
if (selectItem instanceof QualifiedName) {
40-
QualifierAnalyzer qualifierAnalyzer = new QualifierAnalyzer(context);
41-
return qualifierAnalyzer.unqualified((QualifiedName) selectItem);
42-
}
43-
return node.getName();
30+
return DSL.named(node.getName(), node.getDelegated().accept(expressionAnalyzer, context));
4431
}
4532
}

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

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,7 @@ public List<NamedExpression> visitAlias(Alias node, AnalysisContext context) {
6565
}
6666

6767
Expression expr = referenceIfSymbolDefined(node, context);
68-
return Collections.singletonList(
69-
DSL.named(unqualifiedNameIfFieldOnly(node, context), expr, node.getAlias()));
68+
return Collections.singletonList(DSL.named(node.getName(), expr));
7069
}
7170

7271
/**
@@ -89,7 +88,9 @@ private Expression referenceIfSymbolDefined(Alias expr, AnalysisContext context)
8988
// (OVER clause) and thus depends on name in alias to be replaced correctly
9089
return optimizer.optimize(
9190
DSL.named(
92-
expr.getName(), delegatedExpr.accept(expressionAnalyzer, context), expr.getAlias()),
91+
delegatedExpr.toString(),
92+
delegatedExpr.accept(expressionAnalyzer, context),
93+
expr.getName()),
9394
context);
9495
}
9596

@@ -128,21 +129,4 @@ public List<NamedExpression> visitNestedAllTupleFields(
128129
})
129130
.collect(Collectors.toList());
130131
}
131-
132-
/**
133-
* Get unqualified name if select item is just a field. For example, suppose an index named
134-
* "accounts", return "age" for "SELECT accounts.age". But do nothing for expression in "SELECT
135-
* ABS(accounts.age)". Note that an assumption is made implicitly that original name field in
136-
* Alias must be the same as the values in QualifiedName. This is true because AST builder does
137-
* this. Otherwise, what unqualified() returns will override Alias's name as NamedExpression's
138-
* name even though the QualifiedName doesn't have qualifier.
139-
*/
140-
private String unqualifiedNameIfFieldOnly(Alias node, AnalysisContext context) {
141-
UnresolvedExpression selectItem = node.getDelegated();
142-
if (selectItem instanceof QualifiedName) {
143-
QualifierAnalyzer qualifierAnalyzer = new QualifierAnalyzer(context);
144-
return qualifierAnalyzer.unqualified((QualifiedName) selectItem);
145-
}
146-
return node.getName();
147-
}
148132
}

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,7 @@ public LogicalPlan visitAlias(Alias node, AnalysisContext context) {
6565
List<Pair<SortOption, Expression>> sortList = analyzeSortList(unresolved, context);
6666

6767
WindowDefinition windowDefinition = new WindowDefinition(partitionByList, sortList);
68-
NamedExpression namedWindowFunction =
69-
new NamedExpression(node.getName(), windowFunction, node.getAlias());
68+
NamedExpression namedWindowFunction = new NamedExpression(node.getName(), windowFunction);
7069
List<Pair<SortOption, Expression>> allSortItems = windowDefinition.getAllSortItems();
7170

7271
if (allSortItems.isEmpty()) {

core/src/main/java/org/opensearch/sql/ast/AbstractNodeVisitor.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,10 @@
4848
import org.opensearch.sql.ast.tree.FillNull;
4949
import org.opensearch.sql.ast.tree.Filter;
5050
import org.opensearch.sql.ast.tree.Head;
51+
import org.opensearch.sql.ast.tree.Join;
5152
import org.opensearch.sql.ast.tree.Kmeans;
5253
import org.opensearch.sql.ast.tree.Limit;
54+
import org.opensearch.sql.ast.tree.Lookup;
5355
import org.opensearch.sql.ast.tree.ML;
5456
import org.opensearch.sql.ast.tree.Paginate;
5557
import org.opensearch.sql.ast.tree.Parse;
@@ -59,6 +61,7 @@
5961
import org.opensearch.sql.ast.tree.RelationSubquery;
6062
import org.opensearch.sql.ast.tree.Rename;
6163
import org.opensearch.sql.ast.tree.Sort;
64+
import org.opensearch.sql.ast.tree.SubqueryAlias;
6265
import org.opensearch.sql.ast.tree.TableFunction;
6366
import org.opensearch.sql.ast.tree.Trendline;
6467
import org.opensearch.sql.ast.tree.Values;
@@ -326,4 +329,16 @@ public T visitCloseCursor(CloseCursor closeCursor, C context) {
326329
public T visitFillNull(FillNull fillNull, C context) {
327330
return visitChildren(fillNull, context);
328331
}
332+
333+
public T visitJoin(Join node, C context) {
334+
return visitChildren(node, context);
335+
}
336+
337+
public T visitLookup(Lookup node, C context) {
338+
return visitChildren(node, context);
339+
}
340+
341+
public T visitSubqueryAlias(SubqueryAlias node, C context) {
342+
return visitChildren(node, context);
343+
}
329344
}

core/src/main/java/org/opensearch/sql/ast/dsl/AstDSL.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import org.opensearch.sql.ast.expression.Xor;
4949
import org.opensearch.sql.ast.tree.Aggregation;
5050
import org.opensearch.sql.ast.tree.Dedupe;
51+
import org.opensearch.sql.ast.tree.DescribeRelation;
5152
import org.opensearch.sql.ast.tree.Eval;
5253
import org.opensearch.sql.ast.tree.FillNull;
5354
import org.opensearch.sql.ast.tree.Filter;
@@ -62,6 +63,7 @@
6263
import org.opensearch.sql.ast.tree.Rename;
6364
import org.opensearch.sql.ast.tree.Sort;
6465
import org.opensearch.sql.ast.tree.Sort.SortOption;
66+
import org.opensearch.sql.ast.tree.SubqueryAlias;
6567
import org.opensearch.sql.ast.tree.TableFunction;
6668
import org.opensearch.sql.ast.tree.Trendline;
6769
import org.opensearch.sql.ast.tree.UnresolvedPlan;
@@ -89,7 +91,15 @@ public UnresolvedPlan relation(QualifiedName tableName) {
8991
}
9092

9193
public UnresolvedPlan relation(String tableName, String alias) {
92-
return new Relation(qualifiedName(tableName), alias);
94+
return new SubqueryAlias(alias, new Relation(qualifiedName(tableName)));
95+
}
96+
97+
public UnresolvedPlan describe(String tableName) {
98+
return new DescribeRelation(qualifiedName(tableName));
99+
}
100+
101+
public UnresolvedPlan subqueryAlias(UnresolvedPlan child, String alias) {
102+
return new SubqueryAlias(child, alias);
93103
}
94104

95105
public UnresolvedPlan tableFunction(List<String> functionName, UnresolvedExpression... args) {
@@ -385,8 +395,13 @@ public Alias alias(String name, UnresolvedExpression expr) {
385395
return new Alias(name, expr);
386396
}
387397

398+
@Deprecated
388399
public Alias alias(String name, UnresolvedExpression expr, String alias) {
389-
return new Alias(name, expr, alias);
400+
if (alias == null) {
401+
return new Alias(name, expr);
402+
} else {
403+
return new Alias(alias, expr);
404+
}
390405
}
391406

392407
public NestedAllTupleFields nestedAllTupleFields(String path) {

0 commit comments

Comments
 (0)