Skip to content

Commit f87787b

Browse files
committed
merge from main
Signed-off-by: xinyual <xinyual@amazon.com>
2 parents 794df29 + 23407cb commit f87787b

272 files changed

Lines changed: 27986 additions & 5448 deletions

File tree

Some content is hidden

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

.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)

build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66

77
buildscript {
88
ext {
9-
opensearch_version = System.getProperty("opensearch.version", "3.0.0-beta1-SNAPSHOT")
9+
opensearch_version = System.getProperty("opensearch.version", "3.1.0-SNAPSHOT")
1010
isSnapshot = "true" == System.getProperty("build.snapshot", "true")
11-
buildVersionQualifier = System.getProperty("build.version_qualifier", "beta1")
11+
buildVersionQualifier = System.getProperty("build.version_qualifier", "")
1212
version_tokens = opensearch_version.tokenize('-')
1313
opensearch_build = version_tokens[0] + '.0'
1414
prometheus_binary_version = "2.37.2"

common/src/main/java/org/opensearch/sql/common/setting/Settings.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ public enum Key {
3131
CALCITE_ENGINE_ENABLED("plugins.calcite.enabled"),
3232
CALCITE_FALLBACK_ALLOWED("plugins.calcite.fallback.allowed"),
3333
CALCITE_PUSHDOWN_ENABLED("plugins.calcite.pushdown.enabled"),
34+
CALCITE_PUSHDOWN_ROWCOUNT_ESTIMATION_FACTOR(
35+
"plugins.calcite.pushdown.rowcount.estimation.factor"),
3436

3537
/** Query Settings. */
3638
FIELD_TYPE_TOLERANCE("plugins.query.field_type_tolerance"),

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

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
import org.opensearch.sql.ast.tree.ML;
6262
import org.opensearch.sql.ast.tree.Paginate;
6363
import org.opensearch.sql.ast.tree.Parse;
64+
import org.opensearch.sql.ast.tree.Patterns;
6465
import org.opensearch.sql.ast.tree.Project;
6566
import org.opensearch.sql.ast.tree.RareTopN;
6667
import org.opensearch.sql.ast.tree.Relation;
@@ -73,7 +74,6 @@
7374
import org.opensearch.sql.ast.tree.Trendline;
7475
import org.opensearch.sql.ast.tree.UnresolvedPlan;
7576
import org.opensearch.sql.ast.tree.Values;
76-
import org.opensearch.sql.ast.tree.Window;
7777
import org.opensearch.sql.common.antlr.SyntaxCheckException;
7878
import org.opensearch.sql.data.model.ExprMissingValue;
7979
import org.opensearch.sql.data.type.ExprCoreType;
@@ -493,7 +493,7 @@ public LogicalPlan visitParse(Parse node, AnalysisContext context) {
493493
}
494494

495495
@Override
496-
public LogicalPlan visitWindow(Window node, AnalysisContext context) {
496+
public LogicalPlan visitPatterns(Patterns node, AnalysisContext context) {
497497
LogicalPlan child = node.getChild().get(0).accept(this, context);
498498
WindowExpressionAnalyzer windowAnalyzer =
499499
new WindowExpressionAnalyzer(expressionAnalyzer, child);
@@ -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/AbstractNodeVisitor.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
import org.opensearch.sql.ast.tree.ML;
6161
import org.opensearch.sql.ast.tree.Paginate;
6262
import org.opensearch.sql.ast.tree.Parse;
63+
import org.opensearch.sql.ast.tree.Patterns;
6364
import org.opensearch.sql.ast.tree.Project;
6465
import org.opensearch.sql.ast.tree.RareTopN;
6566
import org.opensearch.sql.ast.tree.Relation;
@@ -348,6 +349,10 @@ public T visitFillNull(FillNull fillNull, C context) {
348349
return visitChildren(fillNull, context);
349350
}
350351

352+
public T visitPatterns(Patterns patterns, C context) {
353+
return visitChildren(patterns, context);
354+
}
355+
351356
public T visitWindow(Window window, C context) {
352357
return visitChildren(window, context);
353358
}

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

Lines changed: 16 additions & 15 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;
@@ -58,6 +57,7 @@
5857
import org.opensearch.sql.ast.tree.Head;
5958
import org.opensearch.sql.ast.tree.Limit;
6059
import org.opensearch.sql.ast.tree.Parse;
60+
import org.opensearch.sql.ast.tree.Patterns;
6161
import org.opensearch.sql.ast.tree.Project;
6262
import org.opensearch.sql.ast.tree.RareTopN;
6363
import org.opensearch.sql.ast.tree.RareTopN.CommandType;
@@ -71,7 +71,6 @@
7171
import org.opensearch.sql.ast.tree.Trendline;
7272
import org.opensearch.sql.ast.tree.UnresolvedPlan;
7373
import org.opensearch.sql.ast.tree.Values;
74-
import org.opensearch.sql.ast.tree.Window;
7574

7675
/** Class of static methods to create specific node instances. */
7776
@UtilityClass
@@ -504,7 +503,7 @@ public static Parse parse(
504503
return new Parse(parseMethod, sourceField, pattern, arguments, input);
505504
}
506505

507-
public static Window window(
506+
public static Patterns patterns(
508507
UnresolvedPlan input,
509508
PatternMethod patternMethod,
510509
UnresolvedExpression sourceField,
@@ -513,7 +512,7 @@ public static Window window(
513512
List<UnresolvedExpression> funArgs = new ArrayList<>();
514513
funArgs.add(sourceField);
515514
funArgs.addAll(arguments);
516-
return new Window(
515+
return new Patterns(
517516
new Alias(
518517
alias,
519518
new WindowFunction(
@@ -524,21 +523,23 @@ public static Window window(
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/ParseMethod.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
@RequiredArgsConstructor
1212
public enum ParseMethod {
1313
REGEX("regex"),
14-
GROK("grok");
14+
GROK("grok"),
15+
PATTERNS("patterns");
1516

1617
@Getter private final String name;
1718
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package org.opensearch.sql.ast.expression;
7+
8+
import lombok.Getter;
9+
10+
public abstract class WindowBound {
11+
private WindowBound() {}
12+
13+
@Getter
14+
public static class OffSetWindowBound extends WindowBound {
15+
private final long offset;
16+
private final boolean isPreceding;
17+
18+
OffSetWindowBound(long offset, boolean isPreceding) {
19+
this.offset = offset;
20+
this.isPreceding = isPreceding;
21+
}
22+
23+
public boolean isPreceding() {
24+
return isPreceding;
25+
}
26+
}
27+
28+
public static class CurrentRowWindowBound extends WindowBound {
29+
CurrentRowWindowBound() {}
30+
31+
@Override
32+
public String toString() {
33+
return "CURRENT ROW";
34+
}
35+
}
36+
37+
public static class UnboundedWindowBound extends WindowBound {
38+
private final boolean isPreceding;
39+
40+
UnboundedWindowBound(boolean isPreceding) {
41+
this.isPreceding = isPreceding;
42+
}
43+
44+
public boolean isPreceding() {
45+
return isPreceding;
46+
}
47+
48+
@Override
49+
public boolean equals(Object o) {
50+
return this == o
51+
|| o instanceof UnboundedWindowBound
52+
&& isPreceding == ((UnboundedWindowBound) o).isPreceding;
53+
}
54+
55+
@Override
56+
public String toString() {
57+
return isPreceding ? "UNBOUNDED PRECEDING" : "UNBOUNDED FOLLOWING";
58+
}
59+
}
60+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package org.opensearch.sql.ast.expression;
7+
8+
import java.util.Locale;
9+
import lombok.EqualsAndHashCode;
10+
import lombok.Getter;
11+
import lombok.RequiredArgsConstructor;
12+
import lombok.ToString;
13+
14+
@EqualsAndHashCode(callSuper = false)
15+
@Getter
16+
@RequiredArgsConstructor
17+
@ToString
18+
public class WindowFrame extends UnresolvedExpression {
19+
private final FrameType type;
20+
private final WindowBound lower;
21+
private final WindowBound upper;
22+
23+
public enum FrameType {
24+
RANGE,
25+
ROWS
26+
}
27+
28+
public static WindowFrame defaultFrame() {
29+
return new WindowFrame(
30+
FrameType.ROWS, createBound("UNBOUNDED PRECEDING"), createBound("UNBOUNDED FOLLOWING"));
31+
}
32+
33+
public static WindowFrame create(FrameType type, Literal lower, Literal upper) {
34+
WindowBound lowerBound = null;
35+
WindowBound upperBound = null;
36+
if (lower != null) {
37+
if (lower.getType() == DataType.STRING) {
38+
lowerBound = createBound(lower.getValue().toString());
39+
} else {
40+
throw new IllegalArgumentException(
41+
String.format("Unsupported bound type: %s", lower.getType()));
42+
}
43+
}
44+
if (upper != null) {
45+
if (upper.getType() == DataType.STRING) {
46+
upperBound = createBound(upper.getValue().toString());
47+
} else {
48+
throw new IllegalArgumentException(
49+
String.format("Unsupported bound type: %s", upper.getType()));
50+
}
51+
}
52+
return new WindowFrame(type, lowerBound, upperBound);
53+
}
54+
55+
private static WindowBound createBound(String boundType) {
56+
boundType = boundType.trim().toUpperCase(Locale.ROOT);
57+
if ("CURRENT ROW".equals(boundType)) {
58+
return new WindowBound.CurrentRowWindowBound();
59+
} else if ("UNBOUNDED PRECEDING".equals(boundType)) {
60+
return new WindowBound.UnboundedWindowBound(true);
61+
} else if ("UNBOUNDED FOLLOWING".equals(boundType)) {
62+
return new WindowBound.UnboundedWindowBound(false);
63+
} else if (boundType.endsWith(" PRECEDING")) {
64+
long number = Long.parseLong(boundType.split(" PRECEDING")[0]);
65+
return new WindowBound.OffSetWindowBound(number, true);
66+
} else if (boundType.endsWith(" FOLLOWING")) {
67+
long number = Long.parseLong(boundType.split(" FOLLOWING")[0]);
68+
return new WindowBound.OffSetWindowBound(number, false);
69+
} else {
70+
throw new IllegalArgumentException(String.format("Unsupported bound type: %s", boundType));
71+
}
72+
}
73+
}

0 commit comments

Comments
 (0)