[NO ISSUE][COMP] Support * index accessor
- user model changes: yes
- storage format changes: no
- interface changes: no
Details:
- Support [*] index accessor that is equivalent to ARRAY_STAR()
x[*] = ARRAY_STAR(x)
- Add testcases
Change-Id: I35462b02d5ac2960be1bdbc552536f3cf9392ab5
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/7744
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Ali Alsuliman <ali.al.solaiman@gmail.com>
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
index d38a263..039b8db 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
@@ -736,31 +736,48 @@
// Expression pair
Pair<ILogicalExpression, Mutable<ILogicalOperator>> expressionPair =
langExprToAlgExpression(ia.getExpr(), tupSource);
+
LogicalVariable v = context.newVar();
- AbstractFunctionCallExpression f;
- // Index expression
- Pair<ILogicalExpression, Mutable<ILogicalOperator>> indexPair = null;
-
- if (ia.isAny()) {
- f = new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.ANY_COLLECTION_MEMBER));
- f.getArguments().add(new MutableObject<>(expressionPair.first));
- } else {
- indexPair = langExprToAlgExpression(ia.getIndexExpr(), expressionPair.second);
- f = new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.GET_ITEM));
- f.getArguments().add(new MutableObject<>(expressionPair.first));
- f.getArguments().add(new MutableObject<>(indexPair.first));
+ FunctionIdentifier fid;
+ ILogicalExpression farg0, farg1 = null;
+ Mutable<ILogicalOperator> assignInput;
+ switch (ia.getIndexKind()) {
+ case ANY:
+ fid = BuiltinFunctions.ANY_COLLECTION_MEMBER;
+ farg0 = expressionPair.first;
+ assignInput = expressionPair.second;
+ break;
+ case STAR:
+ fid = BuiltinFunctions.ARRAY_STAR;
+ farg0 = expressionPair.first;
+ assignInput = expressionPair.second;
+ break;
+ case ELEMENT:
+ Pair<ILogicalExpression, Mutable<ILogicalOperator>> indexPair =
+ langExprToAlgExpression(ia.getIndexExpr(), expressionPair.second);
+ fid = BuiltinFunctions.GET_ITEM;
+ farg0 = expressionPair.first;
+ farg1 = indexPair.first;
+ assignInput = indexPair.second;
+ break;
+ default:
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, ia.getSourceLocation(),
+ ia.getIndexKind());
}
+ AbstractFunctionCallExpression f =
+ new ScalarFunctionCallExpression(BuiltinFunctions.getBuiltinFunctionInfo(fid));
f.setSourceLocation(sourceLoc);
- AssignOperator a = new AssignOperator(v, new MutableObject<>(f));
-
- if (ia.isAny()) {
- a.getInputs().add(expressionPair.second);
- } else {
- a.getInputs().add(indexPair.second); // NOSONAR: Called only if value exists
+ f.getArguments().add(new MutableObject<>(farg0));
+ if (farg1 != null) {
+ f.getArguments().add(new MutableObject<>(farg1));
}
+
+ AssignOperator a = new AssignOperator(v, new MutableObject<>(f));
a.setSourceLocation(sourceLoc);
+ a.getInputs().add(assignInput);
+
return new Pair<>(a, v);
}
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/list/list-star_01/list-star_01.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/list/list-star_01/list-star_01.1.ddl.sqlpp
new file mode 100644
index 0000000..ad018d3
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/list/list-star_01/list-star_01.1.ddl.sqlpp
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+drop dataverse TinySocial if exists;
+create dataverse TinySocial;
+
+use TinySocial;
+
+create type t1 AS {
+
+};
+
+create type t2 AS {
+id: int,
+compType: t1
+};
+
+create dataset d1(t2) primary key id;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/list/list-star_01/list-star_01.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/list/list-star_01/list-star_01.2.update.sqlpp
new file mode 100644
index 0000000..2c88183
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/list/list-star_01/list-star_01.2.update.sqlpp
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use TinySocial;
+
+insert into d1([
+{"id":1, "compType":{"sth":33}},
+{"id":2, "compType":{"sth":44}, "followers":[{"a":"a_val1", "b": "b_val1"}, {"a":"a_val2", "b":"b_val2"}, {"a":"a_val3", "b":"b_val3"}]}
+]);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/list/list-star_01/list-star_01.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/list/list-star_01/list-star_01.3.query.sqlpp
new file mode 100644
index 0000000..f26c332
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/list/list-star_01/list-star_01.3.query.sqlpp
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use TinySocial;
+
+{
+ "t1": [{"a":"a_val1", "b": "b_val1"}, {"a":"a_val2", "b":"b_val2"}, {"a":"a_val3", "b":"b_val3"}][*],
+ "t2": (select value v from d1 v)[*],
+ "t3": [{"b": "b_val1", "a":"a_val1"}, {"a":"a_val2", "b":"b_val2"}, {"a":"a_val3", "b":"b_val3"}][*],
+ "t4": [{"b": "b_val1", "a":"a_val1"}, {"b":"b_val2"}, {"a":"a_val3", "b":"b_val3"}][*],
+ "t5": [{"b": "b_val1", "a":"a_val1"}, {"a": null, "b":"b_val2"}, {"a":"a_val3", "b":"b_val3"}][*],
+ "t6": [{"b": "b_val1", "a":"a_val1"}, {"a": null, "b":"b_val2"}, {"a":"a_val3", "b":"b_val3", "c":"c_val3"}][*],
+ "t7": [{"b": "b_val1", "a":5}, {"a": 3.2, "b":"b_val2"}, {"a":"a_val3", "b":"b_val3", "c":"c_val3"}][*],
+ "t8": [{"b": "b_val1", "a":"a_val1"}, {}, {"a":"a_val3", "b":"b_val3"}][*],
+ "t9": [{"b": "b_val1", "a":"a_val1"}, 5, {"a":"a_val3", "b":"b_val3"}][*],
+ "t10": [{"b": "b_val1", "a":"a_val1"}, null, {"a":"a_val3", "b":"b_val3"}][*],
+ "t11": [{"b": "b_val1", "a":"a_val1"}, missing, {"a":"a_val3", "b":"b_val3"}][*],
+ "t12": [{"b": "b_val1", "a":"a_val1"}, 5, [3] ][*],
+ "t13": [{}, {}, {}][*],
+ "t14": [1, 2, 3][*],
+ "t15": [1][*],
+ "t16": [][*],
+ "t17": "non_array"[*],
+ "t18": missing[*],
+ "t19": null[*],
+ "t20": (select d.followers[*] from d1 d)
+};
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/list/list-star_01/list-star_01.3.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/list/list-star_01/list-star_01.3.adm
new file mode 100644
index 0000000..7c99ec3
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/list/list-star_01/list-star_01.3.adm
@@ -0,0 +1 @@
+{ "t1": { "a": [ "a_val1", "a_val2", "a_val3" ], "b": [ "b_val1", "b_val2", "b_val3" ] }, "t2": { "compType": [ { "sth": 33 }, { "sth": 44 } ], "followers": [ null, [ { "a": "a_val1", "b": "b_val1" }, { "a": "a_val2", "b": "b_val2" }, { "a": "a_val3", "b": "b_val3" } ] ], "id": [ 1, 2 ] }, "t3": { "a": [ "a_val1", "a_val2", "a_val3" ], "b": [ "b_val1", "b_val2", "b_val3" ] }, "t4": { "a": [ "a_val1", null, "a_val3" ], "b": [ "b_val1", "b_val2", "b_val3" ] }, "t5": { "a": [ "a_val1", null, "a_val3" ], "b": [ "b_val1", "b_val2", "b_val3" ] }, "t6": { "a": [ "a_val1", null, "a_val3" ], "b": [ "b_val1", "b_val2", "b_val3" ], "c": [ null, null, "c_val3" ] }, "t7": { "a": [ 5, 3.2, "a_val3" ], "b": [ "b_val1", "b_val2", "b_val3" ], "c": [ null, null, "c_val3" ] }, "t8": { "a": [ "a_val1", null, "a_val3" ], "b": [ "b_val1", null, "b_val3" ] }, "t9": { "a": [ "a_val1", null, "a_val3" ], "b": [ "b_val1", null, "b_val3" ] }, "t10": { "a": [ "a_val1", null, "a_val3" ], "b": [ "b_val1", null, "b_val3" ] }, "t11": { "a": [ "a_val1", null, "a_val3" ], "b": [ "b_val1", null, "b_val3" ] }, "t12": { "a": [ "a_val1", null, null ], "b": [ "b_val1", null, null ] }, "t17": null, "t19": null, "t20": [ { }, { "$1": { "a": [ "a_val1", "a_val2", "a_val3" ], "b": [ "b_val1", "b_val2", "b_val3" ] } } ] }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/list/list-star_01/list-star_01.1.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/list/list-star_01/list-star_01.1.ast
new file mode 100644
index 0000000..736d1cc
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/list/list-star_01/list-star_01.1.ast
@@ -0,0 +1,13 @@
+DataverseUse TinySocial
+TypeDecl t1 [
+ open RecordType {
+
+ }
+]
+TypeDecl t2 [
+ open RecordType {
+ id : int64,
+ compType : t1
+ }
+]
+DatasetDecl d1(t2) partitioned by [[id]]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/list/list-star_01/list-star_01.2.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/list/list-star_01/list-star_01.2.ast
new file mode 100644
index 0000000..f36d0ea
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/list/list-star_01/list-star_01.2.ast
@@ -0,0 +1 @@
+DataverseUse TinySocial
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/list/list-star_01/list-star_01.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/list/list-star_01/list-star_01.3.ast
new file mode 100644
index 0000000..85b966e
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/list/list-star_01/list-star_01.3.ast
@@ -0,0 +1,549 @@
+DataverseUse TinySocial
+Query:
+RecordConstructor [
+ (
+ LiteralExpr [STRING] [t1]
+ :
+ IndexAccessor [
+ OrderedListConstructor [
+ RecordConstructor [
+ (
+ LiteralExpr [STRING] [a]
+ :
+ LiteralExpr [STRING] [a_val1]
+ )
+ (
+ LiteralExpr [STRING] [b]
+ :
+ LiteralExpr [STRING] [b_val1]
+ )
+ ]
+ RecordConstructor [
+ (
+ LiteralExpr [STRING] [a]
+ :
+ LiteralExpr [STRING] [a_val2]
+ )
+ (
+ LiteralExpr [STRING] [b]
+ :
+ LiteralExpr [STRING] [b_val2]
+ )
+ ]
+ RecordConstructor [
+ (
+ LiteralExpr [STRING] [a]
+ :
+ LiteralExpr [STRING] [a_val3]
+ )
+ (
+ LiteralExpr [STRING] [b]
+ :
+ LiteralExpr [STRING] [b_val3]
+ )
+ ]
+ ]
+ Index: STAR
+ ]
+ )
+ (
+ LiteralExpr [STRING] [t2]
+ :
+ IndexAccessor [
+ (
+ SELECT ELEMENT [
+ Variable [ Name=$v ]
+ ]
+ FROM [ FunctionCall asterix.dataset@1[
+ LiteralExpr [STRING] [TinySocial.d1]
+ ]
+ AS Variable [ Name=$v ]
+ ]
+ )
+ Index: STAR
+ ]
+ )
+ (
+ LiteralExpr [STRING] [t3]
+ :
+ IndexAccessor [
+ OrderedListConstructor [
+ RecordConstructor [
+ (
+ LiteralExpr [STRING] [b]
+ :
+ LiteralExpr [STRING] [b_val1]
+ )
+ (
+ LiteralExpr [STRING] [a]
+ :
+ LiteralExpr [STRING] [a_val1]
+ )
+ ]
+ RecordConstructor [
+ (
+ LiteralExpr [STRING] [a]
+ :
+ LiteralExpr [STRING] [a_val2]
+ )
+ (
+ LiteralExpr [STRING] [b]
+ :
+ LiteralExpr [STRING] [b_val2]
+ )
+ ]
+ RecordConstructor [
+ (
+ LiteralExpr [STRING] [a]
+ :
+ LiteralExpr [STRING] [a_val3]
+ )
+ (
+ LiteralExpr [STRING] [b]
+ :
+ LiteralExpr [STRING] [b_val3]
+ )
+ ]
+ ]
+ Index: STAR
+ ]
+ )
+ (
+ LiteralExpr [STRING] [t4]
+ :
+ IndexAccessor [
+ OrderedListConstructor [
+ RecordConstructor [
+ (
+ LiteralExpr [STRING] [b]
+ :
+ LiteralExpr [STRING] [b_val1]
+ )
+ (
+ LiteralExpr [STRING] [a]
+ :
+ LiteralExpr [STRING] [a_val1]
+ )
+ ]
+ RecordConstructor [
+ (
+ LiteralExpr [STRING] [b]
+ :
+ LiteralExpr [STRING] [b_val2]
+ )
+ ]
+ RecordConstructor [
+ (
+ LiteralExpr [STRING] [a]
+ :
+ LiteralExpr [STRING] [a_val3]
+ )
+ (
+ LiteralExpr [STRING] [b]
+ :
+ LiteralExpr [STRING] [b_val3]
+ )
+ ]
+ ]
+ Index: STAR
+ ]
+ )
+ (
+ LiteralExpr [STRING] [t5]
+ :
+ IndexAccessor [
+ OrderedListConstructor [
+ RecordConstructor [
+ (
+ LiteralExpr [STRING] [b]
+ :
+ LiteralExpr [STRING] [b_val1]
+ )
+ (
+ LiteralExpr [STRING] [a]
+ :
+ LiteralExpr [STRING] [a_val1]
+ )
+ ]
+ RecordConstructor [
+ (
+ LiteralExpr [STRING] [a]
+ :
+ LiteralExpr [NULL]
+ )
+ (
+ LiteralExpr [STRING] [b]
+ :
+ LiteralExpr [STRING] [b_val2]
+ )
+ ]
+ RecordConstructor [
+ (
+ LiteralExpr [STRING] [a]
+ :
+ LiteralExpr [STRING] [a_val3]
+ )
+ (
+ LiteralExpr [STRING] [b]
+ :
+ LiteralExpr [STRING] [b_val3]
+ )
+ ]
+ ]
+ Index: STAR
+ ]
+ )
+ (
+ LiteralExpr [STRING] [t6]
+ :
+ IndexAccessor [
+ OrderedListConstructor [
+ RecordConstructor [
+ (
+ LiteralExpr [STRING] [b]
+ :
+ LiteralExpr [STRING] [b_val1]
+ )
+ (
+ LiteralExpr [STRING] [a]
+ :
+ LiteralExpr [STRING] [a_val1]
+ )
+ ]
+ RecordConstructor [
+ (
+ LiteralExpr [STRING] [a]
+ :
+ LiteralExpr [NULL]
+ )
+ (
+ LiteralExpr [STRING] [b]
+ :
+ LiteralExpr [STRING] [b_val2]
+ )
+ ]
+ RecordConstructor [
+ (
+ LiteralExpr [STRING] [a]
+ :
+ LiteralExpr [STRING] [a_val3]
+ )
+ (
+ LiteralExpr [STRING] [b]
+ :
+ LiteralExpr [STRING] [b_val3]
+ )
+ (
+ LiteralExpr [STRING] [c]
+ :
+ LiteralExpr [STRING] [c_val3]
+ )
+ ]
+ ]
+ Index: STAR
+ ]
+ )
+ (
+ LiteralExpr [STRING] [t7]
+ :
+ IndexAccessor [
+ OrderedListConstructor [
+ RecordConstructor [
+ (
+ LiteralExpr [STRING] [b]
+ :
+ LiteralExpr [STRING] [b_val1]
+ )
+ (
+ LiteralExpr [STRING] [a]
+ :
+ LiteralExpr [LONG] [5]
+ )
+ ]
+ RecordConstructor [
+ (
+ LiteralExpr [STRING] [a]
+ :
+ LiteralExpr [DOUBLE] [3.2]
+ )
+ (
+ LiteralExpr [STRING] [b]
+ :
+ LiteralExpr [STRING] [b_val2]
+ )
+ ]
+ RecordConstructor [
+ (
+ LiteralExpr [STRING] [a]
+ :
+ LiteralExpr [STRING] [a_val3]
+ )
+ (
+ LiteralExpr [STRING] [b]
+ :
+ LiteralExpr [STRING] [b_val3]
+ )
+ (
+ LiteralExpr [STRING] [c]
+ :
+ LiteralExpr [STRING] [c_val3]
+ )
+ ]
+ ]
+ Index: STAR
+ ]
+ )
+ (
+ LiteralExpr [STRING] [t8]
+ :
+ IndexAccessor [
+ OrderedListConstructor [
+ RecordConstructor [
+ (
+ LiteralExpr [STRING] [b]
+ :
+ LiteralExpr [STRING] [b_val1]
+ )
+ (
+ LiteralExpr [STRING] [a]
+ :
+ LiteralExpr [STRING] [a_val1]
+ )
+ ]
+ RecordConstructor [
+ ]
+ RecordConstructor [
+ (
+ LiteralExpr [STRING] [a]
+ :
+ LiteralExpr [STRING] [a_val3]
+ )
+ (
+ LiteralExpr [STRING] [b]
+ :
+ LiteralExpr [STRING] [b_val3]
+ )
+ ]
+ ]
+ Index: STAR
+ ]
+ )
+ (
+ LiteralExpr [STRING] [t9]
+ :
+ IndexAccessor [
+ OrderedListConstructor [
+ RecordConstructor [
+ (
+ LiteralExpr [STRING] [b]
+ :
+ LiteralExpr [STRING] [b_val1]
+ )
+ (
+ LiteralExpr [STRING] [a]
+ :
+ LiteralExpr [STRING] [a_val1]
+ )
+ ]
+ LiteralExpr [LONG] [5]
+ RecordConstructor [
+ (
+ LiteralExpr [STRING] [a]
+ :
+ LiteralExpr [STRING] [a_val3]
+ )
+ (
+ LiteralExpr [STRING] [b]
+ :
+ LiteralExpr [STRING] [b_val3]
+ )
+ ]
+ ]
+ Index: STAR
+ ]
+ )
+ (
+ LiteralExpr [STRING] [t10]
+ :
+ IndexAccessor [
+ OrderedListConstructor [
+ RecordConstructor [
+ (
+ LiteralExpr [STRING] [b]
+ :
+ LiteralExpr [STRING] [b_val1]
+ )
+ (
+ LiteralExpr [STRING] [a]
+ :
+ LiteralExpr [STRING] [a_val1]
+ )
+ ]
+ LiteralExpr [NULL]
+ RecordConstructor [
+ (
+ LiteralExpr [STRING] [a]
+ :
+ LiteralExpr [STRING] [a_val3]
+ )
+ (
+ LiteralExpr [STRING] [b]
+ :
+ LiteralExpr [STRING] [b_val3]
+ )
+ ]
+ ]
+ Index: STAR
+ ]
+ )
+ (
+ LiteralExpr [STRING] [t11]
+ :
+ IndexAccessor [
+ OrderedListConstructor [
+ RecordConstructor [
+ (
+ LiteralExpr [STRING] [b]
+ :
+ LiteralExpr [STRING] [b_val1]
+ )
+ (
+ LiteralExpr [STRING] [a]
+ :
+ LiteralExpr [STRING] [a_val1]
+ )
+ ]
+ LiteralExpr [MISSING]
+ RecordConstructor [
+ (
+ LiteralExpr [STRING] [a]
+ :
+ LiteralExpr [STRING] [a_val3]
+ )
+ (
+ LiteralExpr [STRING] [b]
+ :
+ LiteralExpr [STRING] [b_val3]
+ )
+ ]
+ ]
+ Index: STAR
+ ]
+ )
+ (
+ LiteralExpr [STRING] [t12]
+ :
+ IndexAccessor [
+ OrderedListConstructor [
+ RecordConstructor [
+ (
+ LiteralExpr [STRING] [b]
+ :
+ LiteralExpr [STRING] [b_val1]
+ )
+ (
+ LiteralExpr [STRING] [a]
+ :
+ LiteralExpr [STRING] [a_val1]
+ )
+ ]
+ LiteralExpr [LONG] [5]
+ OrderedListConstructor [
+ LiteralExpr [LONG] [3]
+ ]
+ ]
+ Index: STAR
+ ]
+ )
+ (
+ LiteralExpr [STRING] [t13]
+ :
+ IndexAccessor [
+ OrderedListConstructor [
+ RecordConstructor [
+ ]
+ RecordConstructor [
+ ]
+ RecordConstructor [
+ ]
+ ]
+ Index: STAR
+ ]
+ )
+ (
+ LiteralExpr [STRING] [t14]
+ :
+ IndexAccessor [
+ OrderedListConstructor [
+ LiteralExpr [LONG] [1]
+ LiteralExpr [LONG] [2]
+ LiteralExpr [LONG] [3]
+ ]
+ Index: STAR
+ ]
+ )
+ (
+ LiteralExpr [STRING] [t15]
+ :
+ IndexAccessor [
+ OrderedListConstructor [
+ LiteralExpr [LONG] [1]
+ ]
+ Index: STAR
+ ]
+ )
+ (
+ LiteralExpr [STRING] [t16]
+ :
+ IndexAccessor [
+ OrderedListConstructor [
+ ]
+ Index: STAR
+ ]
+ )
+ (
+ LiteralExpr [STRING] [t17]
+ :
+ IndexAccessor [
+ LiteralExpr [STRING] [non_array]
+ Index: STAR
+ ]
+ )
+ (
+ LiteralExpr [STRING] [t18]
+ :
+ IndexAccessor [
+ LiteralExpr [MISSING]
+ Index: STAR
+ ]
+ )
+ (
+ LiteralExpr [STRING] [t19]
+ :
+ IndexAccessor [
+ LiteralExpr [NULL]
+ Index: STAR
+ ]
+ )
+ (
+ LiteralExpr [STRING] [t20]
+ :
+ (
+ SELECT [
+ IndexAccessor [
+ FieldAccessor [
+ Variable [ Name=$d ]
+ Field=followers
+ ]
+ Index: STAR
+ ]
+ $1
+ ]
+ FROM [ FunctionCall asterix.dataset@1[
+ LiteralExpr [STRING] [TinySocial.d1]
+ ]
+ AS Variable [ Name=$d ]
+ ]
+ )
+ )
+]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
index 95b2bb9..a390875 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -6256,6 +6256,11 @@
</compilation-unit>
</test-case>
<test-case FilePath="list">
+ <compilation-unit name="list-star_01">
+ <output-dir compare="Text">list-star_01</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="list">
<compilation-unit name="listify_01">
<output-dir compare="Text">listify_01</output-dir>
</compilation-unit>
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp_parser.xml b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp_parser.xml
index 9c4bb41..7177797 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp_parser.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp_parser.xml
@@ -6732,4 +6732,11 @@
</compilation-unit>
</test-case>
</test-group>
+ <test-group name="list">
+ <test-case FilePath="list">
+ <compilation-unit name="list-star_01">
+ <output-dir compare="AST">list-star_01</output-dir>
+ </compilation-unit>
+ </test-case>
+ </test-group>
</test-suite>
diff --git a/asterixdb/asterix-lang-aql/src/main/javacc/AQL.jj b/asterixdb/asterix-lang-aql/src/main/javacc/AQL.jj
index 35a7a92..00d183f 100644
--- a/asterixdb/asterix-lang-aql/src/main/javacc/AQL.jj
+++ b/asterixdb/asterix-lang-aql/src/main/javacc/AQL.jj
@@ -1990,7 +1990,7 @@
Expression expr = null;
Identifier ident = null;
AbstractAccessor fa = null;
- Expression indexExpr = null;
+ Pair<IndexAccessor.IndexKind, Expression> index = null;
}
{
expr = PrimaryExpr() ( ident = Field()
@@ -1998,10 +1998,10 @@
fa = (fa == null ? new FieldAccessor(expr, ident)
: new FieldAccessor(fa, ident));
}
- | indexExpr = Index()
+ | index = Index()
{
- fa = (fa == null ? new IndexAccessor(expr, indexExpr)
- : new IndexAccessor(fa, indexExpr));
+ fa = (fa == null ? new IndexAccessor(expr, index.first, index.second)
+ : new IndexAccessor(fa, index.first, index.second));
}
)*
{
@@ -2020,8 +2020,9 @@
}
}
-Expression Index() throws ParseException:
+Pair<IndexAccessor.IndexKind, Expression> Index() throws ParseException:
{
+ IndexAccessor.IndexKind kind = null;
Expression expr = null;
}
{
@@ -2035,15 +2036,18 @@
throw new ParseException("Index should be an INTEGER");
}
}
+ kind = IndexAccessor.IndexKind.ELEMENT;
}
| <QUES> // ANY
-
+ {
+ kind = IndexAccessor.IndexKind.ANY;
+ }
)
<RIGHTBRACKET>
{
- return expr;
+ return new Pair<IndexAccessor.IndexKind, Expression>(kind, expr);
}
}
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/expression/IndexAccessor.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/expression/IndexAccessor.java
index 102c133..73deecd 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/expression/IndexAccessor.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/expression/IndexAccessor.java
@@ -25,23 +25,32 @@
import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
public class IndexAccessor extends AbstractAccessor {
- private boolean isAny;
+
+ public enum IndexKind {
+ ELEMENT,
+ ANY,
+ STAR
+ }
+
+ private IndexKind indexKind;
+
private Expression indexExpr;
- public IndexAccessor(Expression expr, Expression indexExpr) {
+ public IndexAccessor(Expression expr, IndexKind indexKind, Expression indexExpr) {
super(expr);
- if (indexExpr == null) {
- this.isAny = true;
+ if (indexKind != IndexKind.ELEMENT && indexExpr != null) {
+ throw new IllegalArgumentException(indexExpr.toString());
}
+ this.indexKind = Objects.requireNonNull(indexKind);
this.indexExpr = indexExpr;
}
- public boolean isAny() {
- return isAny;
+ public IndexKind getIndexKind() {
+ return indexKind;
}
- public void setAny(boolean any) {
- this.isAny = any;
+ public void setIndexKind(IndexKind indexKind) {
+ this.indexKind = indexKind;
}
public Expression getIndexExpr() {
@@ -64,7 +73,7 @@
@Override
public int hashCode() {
- return 31 * super.hashCode() + Objects.hash(indexExpr, isAny);
+ return 31 * super.hashCode() + Objects.hash(indexKind, indexExpr);
}
@Override
@@ -76,11 +85,11 @@
return false;
}
IndexAccessor target = (IndexAccessor) object;
- return super.equals(target) && isAny == target.isAny && Objects.equals(indexExpr, target.indexExpr);
+ return super.equals(target) && indexKind == target.indexKind && Objects.equals(indexExpr, target.indexExpr);
}
@Override
public String toString() {
- return expr + "[" + (isAny ? "?" : indexExpr) + "]";
+ return expr + "[" + indexKind + '(' + indexExpr + ")]";
}
}
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/CloneAndSubstituteVariablesVisitor.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/CloneAndSubstituteVariablesVisitor.java
index 567dd4a..97701e4 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/CloneAndSubstituteVariablesVisitor.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/CloneAndSubstituteVariablesVisitor.java
@@ -298,12 +298,11 @@
VariableSubstitutionEnvironment env) throws CompilationException {
Pair<ILangExpression, VariableSubstitutionEnvironment> p1 = ia.getExpr().accept(this, env);
Expression indexExpr = null;
- if (!ia.isAny()) {
+ if (ia.getIndexExpr() != null) {
Pair<ILangExpression, VariableSubstitutionEnvironment> p2 = ia.getIndexExpr().accept(this, env);
indexExpr = (Expression) p2.first;
}
- IndexAccessor i = new IndexAccessor((Expression) p1.first, indexExpr);
- i.setAny(ia.isAny());
+ IndexAccessor i = new IndexAccessor((Expression) p1.first, ia.getIndexKind(), indexExpr);
i.setSourceLocation(ia.getSourceLocation());
i.addHints(ia.getHints());
return new Pair<>(i, env);
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/FormatPrintVisitor.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/FormatPrintVisitor.java
index 325f9b0..f5caccf 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/FormatPrintVisitor.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/FormatPrintVisitor.java
@@ -31,6 +31,7 @@
import org.apache.asterix.common.config.DatasetConfig.DatasetType;
import org.apache.asterix.common.config.DatasetConfig.IndexType;
import org.apache.asterix.common.exceptions.CompilationException;
+import org.apache.asterix.common.exceptions.ErrorCode;
import org.apache.asterix.common.functions.FunctionSignature;
import org.apache.asterix.common.metadata.DataverseName;
import org.apache.asterix.lang.common.base.Expression;
@@ -355,13 +356,22 @@
}
@Override
- public Void visit(IndexAccessor fa, Integer step) throws CompilationException {
- fa.getExpr().accept(this, step + 1);
+ public Void visit(IndexAccessor ia, Integer step) throws CompilationException {
+ ia.getExpr().accept(this, step + 1);
out.print("[");
- if (fa.isAny()) {
- out.print("?");
- } else {
- fa.getIndexExpr().accept(this, step + 1);
+ switch (ia.getIndexKind()) {
+ case ANY:
+ out.print("?");
+ break;
+ case STAR:
+ out.print("*");
+ break;
+ case ELEMENT:
+ ia.getIndexExpr().accept(this, step + 1);
+ break;
+ default:
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, ia.getSourceLocation(),
+ ia.getIndexKind());
}
out.print("]");
return null;
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/GatherFunctionCallsVisitor.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/GatherFunctionCallsVisitor.java
index 3d7b467..858729c 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/GatherFunctionCallsVisitor.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/GatherFunctionCallsVisitor.java
@@ -113,11 +113,9 @@
@Override
public Void visit(IndexAccessor ia, Void arg) throws CompilationException {
ia.getExpr().accept(this, arg);
-
- if (!ia.isAny()) {
+ if (ia.getIndexExpr() != null) {
ia.getIndexExpr().accept(this, arg);
}
-
return null;
}
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/QueryPrintVisitor.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/QueryPrintVisitor.java
index 90fb9c1..64d97f3 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/QueryPrintVisitor.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/QueryPrintVisitor.java
@@ -24,6 +24,7 @@
import org.apache.asterix.common.config.DatasetConfig.DatasetType;
import org.apache.asterix.common.exceptions.CompilationException;
+import org.apache.asterix.common.exceptions.ErrorCode;
import org.apache.asterix.common.functions.FunctionSignature;
import org.apache.asterix.lang.common.base.Expression;
import org.apache.asterix.lang.common.base.Literal;
@@ -291,14 +292,23 @@
}
@Override
- public Void visit(IndexAccessor fa, Integer step) throws CompilationException {
+ public Void visit(IndexAccessor ia, Integer step) throws CompilationException {
out.println(skip(step) + "IndexAccessor [");
- fa.getExpr().accept(this, step + 1);
+ ia.getExpr().accept(this, step + 1);
out.print(skip(step + 1) + "Index: ");
- if (fa.isAny()) {
- out.println("ANY");
- } else {
- fa.getIndexExpr().accept(this, step + 1);
+ switch (ia.getIndexKind()) {
+ case ANY:
+ out.println("ANY");
+ break;
+ case STAR:
+ out.println("STAR");
+ break;
+ case ELEMENT:
+ ia.getIndexExpr().accept(this, step + 1);
+ break;
+ default:
+ throw new CompilationException(ErrorCode.COMPILATION_ILLEGAL_STATE, ia.getSourceLocation(),
+ ia.getIndexKind());
}
out.println(skip(step) + "]");
return null;
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSql92AggregateVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSql92AggregateVisitor.java
index a2dafbd..027560c 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSql92AggregateVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/CheckSql92AggregateVisitor.java
@@ -128,7 +128,7 @@
return true;
}
- if (!ia.isAny() && ia.getIndexExpr().accept(this, parentSelectBlock)) {
+ if (ia.getIndexExpr() != null && ia.getIndexExpr().accept(this, parentSelectBlock)) {
return true;
}
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/DeepCopyVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/DeepCopyVisitor.java
index 70ebcfc..684a738 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/DeepCopyVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/DeepCopyVisitor.java
@@ -481,7 +481,7 @@
if (ia.getIndexExpr() != null) {
indexExpr = (Expression) ia.getIndexExpr().accept(this, arg);
}
- IndexAccessor copy = new IndexAccessor(expr, indexExpr);
+ IndexAccessor copy = new IndexAccessor(expr, ia.getIndexKind(), indexExpr);
copy.setSourceLocation(ia.getSourceLocation());
copy.addHints(ia.getHints());
return copy;
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
index 525c15e..201ff7d 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
+++ b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
@@ -566,6 +566,13 @@
"Unexpected return type declaration for function " + fnName);
}
}
+
+ private void ensureIntegerLiteral(LiteralExpr expr, String errorPrefix) throws SqlppParseException {
+ Literal lit = expr.getValue();
+ if (lit.getLiteralType() != Literal.Type.INTEGER && lit.getLiteralType() != Literal.Type.LONG) {
+ throw new SqlppParseException(expr.getSourceLocation(), errorPrefix + " should be an INTEGER");
+ }
+ }
}
PARSER_END(SQLPPParser)
@@ -3088,49 +3095,33 @@
AbstractAccessor IndexAccessor(Expression inputExpr) throws ParseException:
{
Token startToken = null;
- boolean isListSliceExpression = false;
- AbstractAccessor resultExpression = null;
- Expression argumentExpression1 = null;
- Expression argumentExpression2 = null;
+ boolean star = false, slice = false;
+ Expression expr1 = null, expr2 = null;
}
{
<LEFTBRACKET> { startToken = token; }
- ( argumentExpression1 = Expression()
- {
- if (argumentExpression1.getKind() == Expression.Kind.LITERAL_EXPRESSION)
- {
- Literal lit = ((LiteralExpr)argumentExpression1).getValue();
- if (lit.getLiteralType() != Literal.Type.INTEGER &&
- lit.getLiteralType() != Literal.Type.LONG) {
- throw new SqlppParseException(argumentExpression1.getSourceLocation(), "Index should be an INTEGER");
- }
- }
- }
+ (
+ <MUL> { star = true; }
+ |
+ ( expr1 = Expression() ( <COLON> { slice = true; } ( expr2 = Expression() )? )? )
)
- (<COLON>
- {
- isListSliceExpression = true;
- }
- ( argumentExpression2 = Expression()
- {
- if (argumentExpression2.getKind() == Expression.Kind.LITERAL_EXPRESSION) {
- Literal lit = ((LiteralExpr)argumentExpression2).getValue();
- if (lit.getLiteralType() != Literal.Type.INTEGER &&
- lit.getLiteralType() != Literal.Type.LONG) {
- throw new SqlppParseException(argumentExpression2.getSourceLocation(), "Index should be an INTEGER");
- }
- }
- })?
- )?
<RIGHTBRACKET>
{
- if (!isListSliceExpression) {
- resultExpression = new IndexAccessor(inputExpr, argumentExpression1);
- } else {
- resultExpression = new ListSliceExpression(inputExpr, argumentExpression1, argumentExpression2);
+ if (expr1 != null && expr1.getKind() == Expression.Kind.LITERAL_EXPRESSION) {
+ ensureIntegerLiteral( (LiteralExpr) expr1, "Index");
}
-
- return addSourceLocation(resultExpression, startToken);
+ if (expr2 != null && expr2.getKind() == Expression.Kind.LITERAL_EXPRESSION) {
+ ensureIntegerLiteral( (LiteralExpr) expr2, "Index");
+ }
+ AbstractAccessor resultAccessor;
+ if (slice) {
+ resultAccessor = new ListSliceExpression(inputExpr, expr1, expr2);
+ } else if (star) {
+ resultAccessor = new IndexAccessor(inputExpr, IndexAccessor.IndexKind.STAR, null);
+ } else {
+ resultAccessor = new IndexAccessor(inputExpr, IndexAccessor.IndexKind.ELEMENT, expr1);
+ }
+ return addSourceLocation(resultAccessor, startToken);
}
}