Skip to content

Commit 2100019

Browse files
committed
Merge origin/main into pushdown-limit
Signed-off-by: Yuanchun Shen <[email protected]>
2 parents 51c1411 + 92cb089 commit 2100019

File tree

116 files changed

+2332
-605
lines changed

Some content is hidden

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

116 files changed

+2332
-605
lines changed

.github/workflows/maven-publish.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,30 @@ jobs:
2929
with:
3030
role-to-assume: ${{ secrets.PUBLISH_SNAPSHOTS_ROLE }}
3131
aws-region: us-east-1
32+
33+
# Create the initial direct-query directory structure
34+
- name: Create direct-query directory structure in repository
35+
run: |
36+
# Get credentials for publishing
37+
export SONATYPE_USERNAME=$(aws secretsmanager get-secret-value --secret-id maven-snapshots-username --query SecretString --output text)
38+
export SONATYPE_PASSWORD=$(aws secretsmanager get-secret-value --secret-id maven-snapshots-password --query SecretString --output text)
39+
echo "::add-mask::$SONATYPE_USERNAME"
40+
echo "::add-mask::$SONATYPE_PASSWORD"
41+
42+
# Create a placeholder file
43+
TEMP_DIR=$(mktemp -d)
44+
echo "Directory placeholder - $(date)" > "${TEMP_DIR}/.placeholder"
45+
46+
# Upload the placeholder file to create the directory structure
47+
echo "Creating initial directory structure..."
48+
curl -X PUT -u "${SONATYPE_USERNAME}:${SONATYPE_PASSWORD}" \
49+
--upload-file "${TEMP_DIR}/.placeholder" \
50+
"https://aws.oss.sonatype.org/content/repositories/snapshots/org/opensearch/direct-query/.placeholder"
51+
52+
# Clean up
53+
rm -rf "${TEMP_DIR}"
54+
echo "Directory structure created"
55+
3256
- name: publish snapshots to maven
3357
run: |
3458
export SONATYPE_USERNAME=$(aws secretsmanager get-secret-value --secret-id maven-snapshots-username --query SecretString --output text)

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

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ public LogicalPlan visitRareTopN(RareTopN node, AnalysisContext context) {
382382
fields.forEach(
383383
field -> newEnv.define(new Symbol(Namespace.FIELD_NAME, field.toString()), field.type()));
384384

385-
List<Argument> options = node.getNoOfResults();
385+
List<Argument> options = node.getArguments();
386386
Integer noOfResults = (Integer) options.get(0).getValue().getValue();
387387

388388
return new LogicalRareTopN(child, node.getCommandType(), noOfResults, fields, groupBys);
@@ -593,20 +593,22 @@ public LogicalPlan visitFillNull(final FillNull node, final AnalysisContext cont
593593

594594
ImmutableList.Builder<Pair<ReferenceExpression, Expression>> expressionsBuilder =
595595
new Builder<>();
596-
for (FillNull.NullableFieldFill fieldFill : node.getNullableFieldFills()) {
597-
Expression fieldExpr =
598-
expressionAnalyzer.analyze(fieldFill.getNullableFieldReference(), context);
596+
for (Pair<Field, UnresolvedExpression> fieldFill : node.getReplacementPairs()) {
597+
Expression fieldExpr = expressionAnalyzer.analyze(fieldFill.getLeft(), context);
599598
ReferenceExpression ref =
600-
DSL.ref(fieldFill.getNullableFieldReference().getField().toString(), fieldExpr.type());
599+
DSL.ref(fieldFill.getLeft().getField().toString(), fieldExpr.type());
601600
FunctionExpression ifNullFunction =
602-
DSL.ifnull(ref, expressionAnalyzer.analyze(fieldFill.getReplaceNullWithMe(), context));
601+
DSL.ifnull(ref, expressionAnalyzer.analyze(fieldFill.getRight(), context));
603602
expressionsBuilder.add(new ImmutablePair<>(ref, ifNullFunction));
604603
TypeEnvironment typeEnvironment = context.peek();
605604
// define the new reference in type env.
606605
typeEnvironment.define(ref);
607606
}
608-
609-
return new LogicalEval(child, expressionsBuilder.build());
607+
List<Pair<ReferenceExpression, Expression>> expressions = expressionsBuilder.build();
608+
if (expressions.isEmpty()) {
609+
throw new SemanticCheckException("At least one field is required for fillnull in V2.");
610+
}
611+
return new LogicalEval(child, expressions);
610612
}
611613

612614
/** Build {@link LogicalML} for ml command. */

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

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
import java.util.Optional;
1414
import java.util.stream.Collectors;
1515
import lombok.experimental.UtilityClass;
16-
import org.apache.commons.lang3.tuple.ImmutablePair;
1716
import org.apache.commons.lang3.tuple.Pair;
1817
import org.opensearch.sql.ast.expression.AggregateFunction;
1918
import org.opensearch.sql.ast.expression.Alias;
@@ -524,21 +523,23 @@ public static Patterns patterns(
524523
input);
525524
}
526525

527-
public static FillNull fillNull(UnresolvedExpression replaceNullWithMe, Field... fields) {
528-
return new FillNull(
529-
FillNull.ContainNullableFieldFill.ofSameValue(
530-
replaceNullWithMe, ImmutableList.copyOf(fields)));
526+
public static FillNull fillNull(UnresolvedPlan input, UnresolvedExpression replacement) {
527+
return FillNull.ofSameValue(replacement, ImmutableList.of()).attach(input);
531528
}
532529

533530
public static FillNull fillNull(
534-
List<ImmutablePair<Field, UnresolvedExpression>> fieldAndReplacements) {
535-
ImmutableList.Builder<FillNull.NullableFieldFill> replacementsBuilder = ImmutableList.builder();
536-
for (ImmutablePair<Field, UnresolvedExpression> fieldAndReplacement : fieldAndReplacements) {
531+
UnresolvedPlan input, UnresolvedExpression replacement, Field... fields) {
532+
return FillNull.ofSameValue(replacement, ImmutableList.copyOf(fields)).attach(input);
533+
}
534+
535+
public static FillNull fillNull(
536+
UnresolvedPlan input, List<Pair<Field, UnresolvedExpression>> fieldAndReplacements) {
537+
ImmutableList.Builder<Pair<Field, UnresolvedExpression>> replacementsBuilder =
538+
ImmutableList.builder();
539+
for (Pair<Field, UnresolvedExpression> fieldAndReplacement : fieldAndReplacements) {
537540
replacementsBuilder.add(
538-
new FillNull.NullableFieldFill(
539-
fieldAndReplacement.getLeft(), fieldAndReplacement.getRight()));
541+
Pair.of(fieldAndReplacement.getLeft(), fieldAndReplacement.getRight()));
540542
}
541-
return new FillNull(
542-
FillNull.ContainNullableFieldFill.ofVariousValue(replacementsBuilder.build()));
543+
return FillNull.ofVariousValue(replacementsBuilder.build()).attach(input);
543544
}
544545
}

core/src/main/java/org/opensearch/sql/ast/expression/Argument.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import java.util.Arrays;
99
import java.util.List;
10+
import java.util.Map;
1011
import lombok.EqualsAndHashCode;
1112
import lombok.Getter;
1213
import lombok.RequiredArgsConstructor;
@@ -32,4 +33,29 @@ public List<UnresolvedExpression> getChild() {
3233
public <R, C> R accept(AbstractNodeVisitor<R, C> nodeVisitor, C context) {
3334
return nodeVisitor.visitArgument(this, context);
3435
}
36+
37+
/** ArgumentMap is a helper class to get argument value by name. */
38+
public static class ArgumentMap {
39+
private final Map<String, Literal> map;
40+
41+
public ArgumentMap(List<Argument> arguments) {
42+
this.map =
43+
arguments.stream()
44+
.collect(java.util.stream.Collectors.toMap(Argument::getArgName, Argument::getValue));
45+
}
46+
47+
public static ArgumentMap of(List<Argument> arguments) {
48+
return new ArgumentMap(arguments);
49+
}
50+
51+
/**
52+
* Get argument value by name.
53+
*
54+
* @param name argument name
55+
* @return argument value
56+
*/
57+
public Literal get(String name) {
58+
return map.get(name);
59+
}
60+
}
3561
}

core/src/main/java/org/opensearch/sql/ast/expression/WindowFrame.java

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import lombok.Getter;
1111
import lombok.RequiredArgsConstructor;
1212
import lombok.ToString;
13+
import org.opensearch.sql.ast.dsl.AstDSL;
1314

1415
@EqualsAndHashCode(callSuper = false)
1516
@Getter
@@ -25,12 +26,25 @@ public enum FrameType {
2526
ROWS
2627
}
2728

28-
public static WindowFrame defaultFrame() {
29-
return new WindowFrame(
30-
FrameType.ROWS, createBound("UNBOUNDED PRECEDING"), createBound("UNBOUNDED FOLLOWING"));
29+
public static WindowFrame rowsUnbounded() {
30+
return WindowFrame.of(
31+
FrameType.ROWS,
32+
AstDSL.stringLiteral("UNBOUNDED PRECEDING"),
33+
AstDSL.stringLiteral("UNBOUNDED FOLLOWING"));
3134
}
3235

33-
public static WindowFrame create(FrameType type, Literal lower, Literal upper) {
36+
public static WindowFrame toCurrentRow() {
37+
return WindowFrame.of(
38+
FrameType.ROWS,
39+
AstDSL.stringLiteral("UNBOUNDED PRECEDING"),
40+
AstDSL.stringLiteral("CURRENT ROW"));
41+
}
42+
43+
public static WindowFrame of(FrameType type, String lower, String upper) {
44+
return WindowFrame.of(type, AstDSL.stringLiteral(lower), AstDSL.stringLiteral(upper));
45+
}
46+
47+
public static WindowFrame of(FrameType type, Literal lower, Literal upper) {
3448
WindowBound lowerBound = null;
3549
WindowBound upperBound = null;
3650
if (lower != null) {

core/src/main/java/org/opensearch/sql/ast/expression/WindowFunction.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public class WindowFunction extends UnresolvedExpression {
2626
private final UnresolvedExpression function;
2727
@Setter private List<UnresolvedExpression> partitionByList = new ArrayList<>();
2828
@Setter private List<Pair<SortOption, UnresolvedExpression>> sortList = new ArrayList<>();
29-
@Setter private WindowFrame windowFrame = WindowFrame.defaultFrame();
29+
@Setter private WindowFrame windowFrame = WindowFrame.rowsUnbounded();
3030

3131
public WindowFunction(
3232
UnresolvedExpression function,

core/src/main/java/org/opensearch/sql/ast/tree/FillNull.java

Lines changed: 24 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -6,70 +6,53 @@
66
package org.opensearch.sql.ast.tree;
77

88
import java.util.List;
9-
import java.util.Objects;
10-
import lombok.AllArgsConstructor;
9+
import java.util.Optional;
10+
import lombok.EqualsAndHashCode;
1111
import lombok.Getter;
12-
import lombok.NonNull;
13-
import lombok.RequiredArgsConstructor;
12+
import lombok.ToString;
13+
import org.apache.commons.lang3.tuple.Pair;
1414
import org.opensearch.sql.ast.AbstractNodeVisitor;
1515
import org.opensearch.sql.ast.Node;
1616
import org.opensearch.sql.ast.expression.Field;
1717
import org.opensearch.sql.ast.expression.UnresolvedExpression;
1818

1919
/** AST node represent FillNull operation. */
20-
@RequiredArgsConstructor
21-
@AllArgsConstructor
20+
@Getter
21+
@EqualsAndHashCode(callSuper = false)
22+
@ToString
2223
public class FillNull extends UnresolvedPlan {
2324

24-
@Getter
25-
@RequiredArgsConstructor
26-
public static class NullableFieldFill {
27-
@NonNull private final Field nullableFieldReference;
28-
@NonNull private final UnresolvedExpression replaceNullWithMe;
25+
public static FillNull ofVariousValue(List<Pair<Field, UnresolvedExpression>> replacements) {
26+
return new FillNull(replacements);
2927
}
3028

31-
public interface ContainNullableFieldFill {
32-
List<NullableFieldFill> getNullFieldFill();
33-
34-
static ContainNullableFieldFill ofVariousValue(List<NullableFieldFill> replacements) {
35-
return new VariousValueNullFill(replacements);
36-
}
37-
38-
static ContainNullableFieldFill ofSameValue(
39-
UnresolvedExpression replaceNullWithMe, List<Field> nullableFieldReferences) {
40-
return new SameValueNullFill(replaceNullWithMe, nullableFieldReferences);
29+
public static FillNull ofSameValue(UnresolvedExpression replacement, List<Field> fieldList) {
30+
List<Pair<Field, UnresolvedExpression>> replacementPairs =
31+
fieldList.stream().map(f -> Pair.of(f, replacement)).toList();
32+
FillNull instance = new FillNull(replacementPairs);
33+
if (replacementPairs.isEmpty()) {
34+
// no field specified, the replacement value will be applied to all fields.
35+
instance.replacementForAll = Optional.of(replacement);
4136
}
37+
return instance;
4238
}
4339

44-
private static class SameValueNullFill implements ContainNullableFieldFill {
45-
@Getter private final List<NullableFieldFill> nullFieldFill;
40+
private Optional<UnresolvedExpression> replacementForAll = Optional.empty();
4641

47-
public SameValueNullFill(
48-
UnresolvedExpression replaceNullWithMe, List<Field> nullableFieldReferences) {
49-
Objects.requireNonNull(replaceNullWithMe, "Null replacement is required");
50-
this.nullFieldFill =
51-
Objects.requireNonNull(nullableFieldReferences, "Nullable field reference is required")
52-
.stream()
53-
.map(nullableReference -> new NullableFieldFill(nullableReference, replaceNullWithMe))
54-
.toList();
55-
}
56-
}
42+
private final List<Pair<Field, UnresolvedExpression>> replacementPairs;
5743

58-
@RequiredArgsConstructor
59-
private static class VariousValueNullFill implements ContainNullableFieldFill {
60-
@NonNull @Getter private final List<NullableFieldFill> nullFieldFill;
44+
FillNull(List<Pair<Field, UnresolvedExpression>> replacementPairs) {
45+
this.replacementPairs = replacementPairs;
6146
}
6247

6348
private UnresolvedPlan child;
6449

65-
@NonNull private final ContainNullableFieldFill containNullableFieldFill;
66-
67-
public List<NullableFieldFill> getNullableFieldFills() {
68-
return containNullableFieldFill.getNullFieldFill();
50+
public List<Field> getFields() {
51+
return getReplacementPairs().stream().map(Pair::getLeft).toList();
6952
}
7053

7154
@Override
72-
public UnresolvedPlan attach(UnresolvedPlan child) {
55+
public FillNull attach(UnresolvedPlan child) {
7356
this.child = child;
7457
return this;
7558
}

core/src/main/java/org/opensearch/sql/ast/tree/RareTopN.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ public class RareTopN extends UnresolvedPlan {
2929

3030
private UnresolvedPlan child;
3131
private final CommandType commandType;
32-
private final List<Argument> noOfResults;
32+
// arguments: noOfResults: Integer, countField: String, showCount: Boolean
33+
private final List<Argument> arguments;
3334
private final List<Field> fields;
3435
private final List<UnresolvedExpression> groupExprList;
3536

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ public AggCall visitAlias(Alias node, CalcitePlanContext context) {
3737

3838
@Override
3939
public AggCall visitAggregateFunction(AggregateFunction node, CalcitePlanContext context) {
40-
RexNode field = rexNodeVisitor.analyze(node.getField(), context);
40+
RexNode field =
41+
node.getField() == null ? null : rexNodeVisitor.analyze(node.getField(), context);
4142
List<RexNode> argList = new ArrayList<>();
4243
for (UnresolvedExpression arg : node.getArgList()) {
4344
argList.add(rexNodeVisitor.analyze(arg, context));

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public class CalcitePlanContext {
3131
public final ExtendedRexBuilder rexBuilder;
3232
public final FunctionProperties functionProperties;
3333
public final QueryType queryType;
34+
public final Integer querySizeLimit;
3435

3536
@Getter @Setter private boolean isResolvingJoinCondition = false;
3637
@Getter @Setter private boolean isResolvingSubquery = false;
@@ -46,8 +47,9 @@ public class CalcitePlanContext {
4647
private final Stack<RexCorrelVariable> correlVar = new Stack<>();
4748
private final Stack<List<RexNode>> windowPartitions = new Stack<>();
4849

49-
private CalcitePlanContext(FrameworkConfig config, QueryType queryType) {
50+
private CalcitePlanContext(FrameworkConfig config, Integer querySizeLimit, QueryType queryType) {
5051
this.config = config;
52+
this.querySizeLimit = querySizeLimit;
5153
this.queryType = queryType;
5254
this.connection = CalciteToolsHelper.connect(config, TYPE_FACTORY);
5355
this.relBuilder = CalciteToolsHelper.create(config, TYPE_FACTORY, connection);
@@ -84,7 +86,8 @@ public Optional<RexCorrelVariable> peekCorrelVar() {
8486
}
8587
}
8688

87-
public static CalcitePlanContext create(FrameworkConfig config, QueryType queryType) {
88-
return new CalcitePlanContext(config, queryType);
89+
public static CalcitePlanContext create(
90+
FrameworkConfig config, Integer querySizeLimit, QueryType queryType) {
91+
return new CalcitePlanContext(config, querySizeLimit, queryType);
8992
}
9093
}

0 commit comments

Comments
 (0)