[ASTERIXDB-2797][COMP] Fix casting elements of a list constructor
- user model changes: no
- storage format changes: no
- interface changes: no
Details:
Currently, variable elements in a list constructor are always wrapped
in cast() which would cast the variable to open type (when the variable
type is a complex type, e.g. record). The required target type should
be taken into account to decide whether to cast or not.
Change-Id: If18467115e7e497af1b3bc1b76d8ff64adf14c4a
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/11743
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>
Reviewed-by: Dmitry Lychagin <dmitry.lychagin@couchbase.com>
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceEnforcedListTypeRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceEnforcedListTypeRule.java
index 72f24b0..723fff2 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceEnforcedListTypeRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceEnforcedListTypeRule.java
@@ -64,6 +64,7 @@
* rewrite list constructor types for list constructor functions
*/
List<Mutable<ILogicalExpression>> expressions;
+ // TODO(ali): what about other operators that could have list expressions?
switch (op.getOperatorTag()) {
case ASSIGN:
AbstractAssignOperator assignOp = (AbstractAssignOperator) op;
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/typecast/StaticTypeCastUtil.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/typecast/StaticTypeCastUtil.java
index ac2460e..e96a192 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/typecast/StaticTypeCastUtil.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/typecast/StaticTypeCastUtil.java
@@ -69,7 +69,7 @@
*
* @author yingyib
*/
-public class StaticTypeCastUtil {
+public final class StaticTypeCastUtil {
private StaticTypeCastUtil() {
}
@@ -82,10 +82,11 @@
* rule: @ IntroduceEnforcedListTypeRule.
*
* @param funcExpr
- * record constructor function expression
+ * a function expression
* @param reqType
- * required record type
+ * required (list) type (for when the funcExpr is a list constructor)
* @param inputType
+ * inferred (list) type (for when the funcExpr is a list constructor)
* @param env
* type environment
* @throws AlgebricksException
@@ -136,7 +137,7 @@
* @param reqType
* the required type inferred from parent operators/expressions
* @param inputType
- * the current inferred
+ * the current inferred type
* @param env
* the type environment
* @return true if the type is casted; otherwise, false.
@@ -162,6 +163,7 @@
return rewriteListFuncExpr(funcExpr, (AbstractCollectionType) reqType, (AbstractCollectionType) inputType,
env);
} else if (inputType.getTypeTag().equals(ATypeTag.OBJECT)) {
+ // TODO(ali): inputType? shouldn't we check against the funcExpr whether it's a record constructor?
if (reqType.equals(BuiltinType.ANY)) {
reqType = DefaultOpenFieldType.NESTED_OPEN_RECORD_TYPE;
}
@@ -186,13 +188,14 @@
}
/**
- * only called when funcExpr is record constructor
+ * Only called when funcExpr's inferred type (the inputRecordType) is a record.
*
* @param funcExpr
- * record constructor function expression
+ * a function expression that produces a record
* @param requiredRecordType
* required record type
* @param inputRecordType
+ * inferred record type of funcExpr
* @param env
* type environment
* @throws AlgebricksException
@@ -213,13 +216,14 @@
}
/**
- * only called when funcExpr is list constructor
+ * Only called when funcExpr is list constructor.
*
* @param funcExpr
* list constructor function expression
* @param requiredListType
* required list type
* @param inputListType
+ * inferred list type
* @param env
* type environment
* @throws AlgebricksException
@@ -247,19 +251,22 @@
case FUNCTION_CALL:
ScalarFunctionCallExpression argFunc = (ScalarFunctionCallExpression) arg;
changed |= rewriteFuncExpr(argFunc, requiredItemType, currentItemType, env);
- changed |= castItem(argRef, argFunc, requiredItemType, env);
+ changed |= castItem(argRef, requiredItemType, env);
break;
case VARIABLE:
- // TODO(ali): why are we always casting to an open type without considering "requiredItemType"?
- changed |= injectCastToRelaxType(argRef, currentItemType, env);
+ changed |= castItem(argRef, requiredItemType, env);
+ break;
+ case CONSTANT:
+ // TODO(ali): should the constant be handled (i.e. constant array or record)?
break;
}
}
return changed;
}
- private static boolean castItem(Mutable<ILogicalExpression> itemExprRef, ScalarFunctionCallExpression itemExpr,
- IAType requiredItemType, IVariableTypeEnvironment env) throws AlgebricksException {
+ private static boolean castItem(Mutable<ILogicalExpression> itemExprRef, IAType requiredItemType,
+ IVariableTypeEnvironment env) throws AlgebricksException {
+ ILogicalExpression itemExpr = itemExprRef.getValue();
IAType itemType = (IAType) env.getType(itemExpr);
if (TypeResolverUtil.needsCast(requiredItemType, itemType) && !satisfied(requiredItemType, itemType)) {
injectCastFunction(FunctionUtil.getFunctionInfo(BuiltinFunctions.CAST_TYPE), requiredItemType, itemType,
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/list/var-in-list/var-in-list.01.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/list/var-in-list/var-in-list.01.ddl.sqlpp
new file mode 100644
index 0000000..5b2b740
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/list/var-in-list/var-in-list.01.ddl.sqlpp
@@ -0,0 +1,30 @@
+/*
+ * 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 test IF EXISTS;
+CREATE DATAVERSE test;
+
+USE test;
+
+CREATE TYPE t1 AS {id: int};
+CREATE DATASET ds1(t1) primary key id;
+
+CREATE FUNCTION fun1(r) {
+ (SELECT VALUE x FROM [r] AS x)[0]
+};
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/list/var-in-list/var-in-list.02.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/list/var-in-list/var-in-list.02.update.sqlpp
new file mode 100644
index 0000000..7535183
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/list/var-in-list/var-in-list.02.update.sqlpp
@@ -0,0 +1,23 @@
+/*
+ * 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 test;
+
+INSERT INTO ds1 {"id": 1, "f1": "foo"};
+INSERT INTO ds1 {"id": 2, "f1": "bar"};
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/list/var-in-list/var-in-list.03.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/list/var-in-list/var-in-list.03.query.sqlpp
new file mode 100644
index 0000000..b9a79b6
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/list/var-in-list/var-in-list.03.query.sqlpp
@@ -0,0 +1,22 @@
+/*
+ * 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 test;
+
+FROM ds1 AS v SELECT [v] AS list ORDER BY list;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/list/var-in-list/var-in-list.04.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/list/var-in-list/var-in-list.04.query.sqlpp
new file mode 100644
index 0000000..d61e5be
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/list/var-in-list/var-in-list.04.query.sqlpp
@@ -0,0 +1,22 @@
+/*
+ * 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 test;
+
+FROM ds1 AS s SELECT fun1(s) AS list ORDER BY list;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/list/var-in-list/var-in-list.05.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/list/var-in-list/var-in-list.05.query.sqlpp
new file mode 100644
index 0000000..42c7031
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/list/var-in-list/var-in-list.05.query.sqlpp
@@ -0,0 +1,22 @@
+/*
+ * 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 test;
+
+FROM [{'a':5}, {'a':7}] AS s SELECT fun1(s) AS list ORDER BY list;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/list/var-in-list/var-in-list.06.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/list/var-in-list/var-in-list.06.query.sqlpp
new file mode 100644
index 0000000..924b4b8
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/list/var-in-list/var-in-list.06.query.sqlpp
@@ -0,0 +1,22 @@
+/*
+ * 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 test;
+
+FROM [{'a':5}, {'b':7}] AS s SELECT fun1(s) AS list ORDER BY list;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/list/var-in-list/var-in-list.03.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/list/var-in-list/var-in-list.03.adm
new file mode 100644
index 0000000..17ad9c9
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/list/var-in-list/var-in-list.03.adm
@@ -0,0 +1,2 @@
+{ "list": [ { "id": 2, "f1": "bar" } ] }
+{ "list": [ { "id": 1, "f1": "foo" } ] }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/list/var-in-list/var-in-list.04.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/list/var-in-list/var-in-list.04.adm
new file mode 100644
index 0000000..b875625
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/list/var-in-list/var-in-list.04.adm
@@ -0,0 +1,2 @@
+{ "list": { "id": 2, "f1": "bar" } }
+{ "list": { "id": 1, "f1": "foo" } }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/list/var-in-list/var-in-list.05.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/list/var-in-list/var-in-list.05.adm
new file mode 100644
index 0000000..4721f1c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/list/var-in-list/var-in-list.05.adm
@@ -0,0 +1,2 @@
+{ "list": { "a": 5 } }
+{ "list": { "a": 7 } }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/list/var-in-list/var-in-list.06.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/list/var-in-list/var-in-list.06.adm
new file mode 100644
index 0000000..ff72349
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/list/var-in-list/var-in-list.06.adm
@@ -0,0 +1,2 @@
+{ "list": { "a": 5 } }
+{ "list": { "b": 7 } }
\ No newline at end of file
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 ce1303b..af6ca78 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -6140,6 +6140,11 @@
<output-dir compare="Text">query-ASTERIXDB-159-3</output-dir>
</compilation-unit>
</test-case>
+ <test-case FilePath="list">
+ <compilation-unit name="var-in-list">
+ <output-dir compare="Text">var-in-list</output-dir>
+ </compilation-unit>
+ </test-case>
</test-group>
<test-group name="misc">
<test-case FilePath="misc">