Skip to content

Commit d4cc259

Browse files
committed
Merge remote-tracking branch 'origin/main' into issues/4201
Signed-off-by: Yuanchun Shen <[email protected]>
2 parents 91aaee8 + 0257aa5 commit d4cc259

File tree

61 files changed

+2464
-131
lines changed

Some content is hidden

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

61 files changed

+2464
-131
lines changed

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
@@ -50,6 +50,8 @@ public enum Key {
5050
/** Common Settings for SQL and PPL. */
5151
QUERY_MEMORY_LIMIT("plugins.query.memory_limit"),
5252
QUERY_SIZE_LIMIT("plugins.query.size_limit"),
53+
QUERY_BUCKET_SIZE("plugins.query.buckets"),
54+
SEARCH_MAX_BUCKETS("search.max_buckets"),
5355
ENCYRPTION_MASTER_KEY("plugins.query.datasources.encryption.masterkey"),
5456
DATASOURCES_URI_HOSTS_DENY_LIST("plugins.query.datasources.uri.hosts.denylist"),
5557
DATASOURCES_LIMIT("plugins.query.datasources.limit"),

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@
8585
import org.opensearch.sql.ast.tree.Relation;
8686
import org.opensearch.sql.ast.tree.RelationSubquery;
8787
import org.opensearch.sql.ast.tree.Rename;
88+
import org.opensearch.sql.ast.tree.Replace;
8889
import org.opensearch.sql.ast.tree.Reverse;
8990
import org.opensearch.sql.ast.tree.Rex;
9091
import org.opensearch.sql.ast.tree.SPath;
@@ -801,6 +802,11 @@ public LogicalPlan visitCloseCursor(CloseCursor closeCursor, AnalysisContext con
801802
return new LogicalCloseCursor(closeCursor.getChild().get(0).accept(this, context));
802803
}
803804

805+
@Override
806+
public LogicalPlan visitReplace(Replace node, AnalysisContext context) {
807+
throw getOnlyForCalciteException("Replace");
808+
}
809+
804810
@Override
805811
public LogicalPlan visitJoin(Join node, AnalysisContext context) {
806812
throw getOnlyForCalciteException("Join");

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
import org.opensearch.sql.ast.tree.Relation;
7474
import org.opensearch.sql.ast.tree.RelationSubquery;
7575
import org.opensearch.sql.ast.tree.Rename;
76+
import org.opensearch.sql.ast.tree.Replace;
7677
import org.opensearch.sql.ast.tree.Reverse;
7778
import org.opensearch.sql.ast.tree.Rex;
7879
import org.opensearch.sql.ast.tree.SPath;
@@ -245,6 +246,10 @@ public T visitRename(Rename node, C context) {
245246
return visitChildren(node, context);
246247
}
247248

249+
public T visitReplace(Replace node, C context) {
250+
return visitChildren(node, context);
251+
}
252+
248253
public T visitEval(Eval node, C context) {
249254
return visitChildren(node, context);
250255
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package org.opensearch.sql.ast.tree;
7+
8+
import com.google.common.collect.ImmutableList;
9+
import java.util.List;
10+
import java.util.Set;
11+
import lombok.EqualsAndHashCode;
12+
import lombok.Getter;
13+
import lombok.Setter;
14+
import lombok.ToString;
15+
import org.jetbrains.annotations.Nullable;
16+
import org.opensearch.sql.ast.AbstractNodeVisitor;
17+
import org.opensearch.sql.ast.expression.Field;
18+
19+
@Getter
20+
@Setter
21+
@ToString
22+
@EqualsAndHashCode(callSuper = false)
23+
public class Replace extends UnresolvedPlan {
24+
private final List<ReplacePair> replacePairs;
25+
private final Set<Field> fieldList;
26+
@Nullable private UnresolvedPlan child;
27+
28+
/**
29+
* Constructor with multiple pattern/replacement pairs.
30+
*
31+
* @param replacePairs List of pattern/replacement pairs
32+
* @param fieldList Set of fields to apply replacements to
33+
*/
34+
public Replace(List<ReplacePair> replacePairs, Set<Field> fieldList) {
35+
this.replacePairs = replacePairs;
36+
this.fieldList = fieldList;
37+
}
38+
39+
@Override
40+
public Replace attach(UnresolvedPlan child) {
41+
if (null == this.child) {
42+
this.child = child;
43+
} else {
44+
this.child.attach(child);
45+
}
46+
return this;
47+
}
48+
49+
@Override
50+
public List<UnresolvedPlan> getChild() {
51+
return this.child == null ? ImmutableList.of() : ImmutableList.of(this.child);
52+
}
53+
54+
@Override
55+
public <T, C> T accept(AbstractNodeVisitor<T, C> nodeVisitor, C context) {
56+
return nodeVisitor.visitReplace(this, context);
57+
}
58+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package org.opensearch.sql.ast.tree;
7+
8+
import lombok.AllArgsConstructor;
9+
import lombok.EqualsAndHashCode;
10+
import lombok.Getter;
11+
import lombok.ToString;
12+
import org.opensearch.sql.ast.expression.Literal;
13+
14+
/** A pair of pattern and replacement literals for the Replace command. */
15+
@Getter
16+
@AllArgsConstructor
17+
@EqualsAndHashCode
18+
@ToString
19+
public class ReplacePair {
20+
private final Literal pattern;
21+
private final Literal replacement;
22+
}

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

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@
121121
import org.opensearch.sql.ast.tree.Regex;
122122
import org.opensearch.sql.ast.tree.Relation;
123123
import org.opensearch.sql.ast.tree.Rename;
124+
import org.opensearch.sql.ast.tree.Replace;
125+
import org.opensearch.sql.ast.tree.ReplacePair;
124126
import org.opensearch.sql.ast.tree.Rex;
125127
import org.opensearch.sql.ast.tree.SPath;
126128
import org.opensearch.sql.ast.tree.Search;
@@ -2411,6 +2413,51 @@ public RelNode visitValues(Values values, CalcitePlanContext context) {
24112413
}
24122414
}
24132415

2416+
@Override
2417+
public RelNode visitReplace(Replace node, CalcitePlanContext context) {
2418+
visitChildren(node, context);
2419+
2420+
List<String> fieldNames = context.relBuilder.peek().getRowType().getFieldNames();
2421+
2422+
// Create a set of field names to replace for quick lookup
2423+
Set<String> fieldsToReplace =
2424+
node.getFieldList().stream().map(f -> f.getField().toString()).collect(Collectors.toSet());
2425+
2426+
// Validate that all fields to replace exist by calling field() on each
2427+
// This leverages relBuilder.field()'s built-in validation which throws
2428+
// IllegalArgumentException if any field doesn't exist
2429+
for (String fieldToReplace : fieldsToReplace) {
2430+
context.relBuilder.field(fieldToReplace);
2431+
}
2432+
2433+
List<RexNode> projectList = new ArrayList<>();
2434+
2435+
// Project all fields, replacing specified ones in-place
2436+
for (String fieldName : fieldNames) {
2437+
if (fieldsToReplace.contains(fieldName)) {
2438+
// Replace this field in-place with all pattern/replacement pairs applied sequentially
2439+
RexNode fieldRef = context.relBuilder.field(fieldName);
2440+
2441+
// Apply all replacement pairs sequentially (nested REPLACE calls)
2442+
for (ReplacePair pair : node.getReplacePairs()) {
2443+
RexNode patternNode = rexVisitor.analyze(pair.getPattern(), context);
2444+
RexNode replacementNode = rexVisitor.analyze(pair.getReplacement(), context);
2445+
fieldRef =
2446+
context.relBuilder.call(
2447+
SqlStdOperatorTable.REPLACE, fieldRef, patternNode, replacementNode);
2448+
}
2449+
2450+
projectList.add(fieldRef);
2451+
} else {
2452+
// Keep original field unchanged
2453+
projectList.add(context.relBuilder.field(fieldName));
2454+
}
2455+
}
2456+
2457+
context.relBuilder.project(projectList, fieldNames);
2458+
return context.relBuilder.peek();
2459+
}
2460+
24142461
private void buildParseRelNode(Parse node, CalcitePlanContext context) {
24152462
RexNode sourceField = rexVisitor.analyze(node.getSourceField(), context);
24162463
ParseMethod parseMethod = node.getParseMethod();

core/src/main/java/org/opensearch/sql/expression/function/BuiltinFunctionName.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,9 @@ public enum BuiltinFunctionName {
6262
/** Collection functions */
6363
ARRAY(FunctionName.of("array")),
6464
ARRAY_LENGTH(FunctionName.of("array_length")),
65+
MAP_APPEND(FunctionName.of("map_append"), true),
6566
MAP_CONCAT(FunctionName.of("map_concat"), true),
67+
MAP_REMOVE(FunctionName.of("map_remove"), true),
6668
MVAPPEND(FunctionName.of("mvappend")),
6769
MVJOIN(FunctionName.of("mvjoin")),
6870
FORALL(FunctionName.of("forall")),
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package org.opensearch.sql.expression.function.CollectionUDF;
7+
8+
import java.util.ArrayList;
9+
import java.util.List;
10+
11+
/** Core logic for `mvappend` command to collect elements from list of args */
12+
public class MVAppendCore {
13+
14+
/**
15+
* Collect non-null elements from `args`. If an item is a list, it will collect non-null elements
16+
* of the list. See {@ref MVAppendFunctionImplTest} for detailed behavior.
17+
*/
18+
public static List<Object> collectElements(Object... args) {
19+
List<Object> elements = new ArrayList<>();
20+
21+
for (Object arg : args) {
22+
if (arg == null) {
23+
continue;
24+
} else if (arg instanceof List) {
25+
addListElements((List<?>) arg, elements);
26+
} else {
27+
elements.add(arg);
28+
}
29+
}
30+
31+
return elements.isEmpty() ? null : elements;
32+
}
33+
34+
private static void addListElements(List<?> list, List<Object> elements) {
35+
for (Object item : list) {
36+
if (item != null) {
37+
elements.add(item);
38+
}
39+
}
40+
}
41+
}

core/src/main/java/org/opensearch/sql/expression/function/CollectionUDF/MVAppendFunctionImpl.java

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
import static org.apache.calcite.sql.type.SqlTypeUtil.createArrayType;
99

10-
import java.util.ArrayList;
1110
import java.util.List;
1211
import org.apache.calcite.adapter.enumerable.NotNullImplementor;
1312
import org.apache.calcite.adapter.enumerable.NullPolicy;
@@ -98,33 +97,6 @@ public Expression implement(
9897
}
9998

10099
public static Object mvappend(Object... args) {
101-
List<Object> elements = collectElements(args);
102-
return elements.isEmpty() ? null : elements;
103-
}
104-
105-
private static List<Object> collectElements(Object... args) {
106-
List<Object> elements = new ArrayList<>();
107-
108-
for (Object arg : args) {
109-
if (arg == null) {
110-
continue;
111-
}
112-
113-
if (arg instanceof List) {
114-
addListElements((List<?>) arg, elements);
115-
} else {
116-
elements.add(arg);
117-
}
118-
}
119-
120-
return elements;
121-
}
122-
123-
private static void addListElements(List<?> list, List<Object> elements) {
124-
for (Object item : list) {
125-
if (item != null) {
126-
elements.add(item);
127-
}
128-
}
100+
return MVAppendCore.collectElements(args);
129101
}
130102
}

0 commit comments

Comments
 (0)