asterixdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From buyin...@apache.org
Subject [2/3] asterixdb git commit: Support UNION ALL.
Date Thu, 04 Aug 2016 14:28:59 GMT
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_2/union_orderby_2.1.ddl.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_2/union_orderby_2.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_2/union_orderby_2.1.ddl.sqlpp
new file mode 100644
index 0000000..bdfed09
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_2/union_orderby_2.1.ddl.sqlpp
@@ -0,0 +1,41 @@
+/*
+ * 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 TinySocial.FacebookUserType as
+{
+  id : int64
+}
+
+create type TinySocial.FacebookMessageType as
+{
+  `message-id` : int64
+}
+
+create  dataset FacebookUsers(FacebookUserType) primary key id;
+
+create  dataset FacebookUsers2(FacebookUserType) primary key id;
+
+create  dataset FacebookMessages(FacebookMessageType) primary key `message-id`;
+

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_2/union_orderby_2.2.update.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_2/union_orderby_2.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_2/union_orderby_2.2.update.sqlpp
new file mode 100644
index 0000000..ccd33a5
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_2/union_orderby_2.2.update.sqlpp
@@ -0,0 +1,26 @@
+/*
+ * 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;
+
+
+load  dataset FacebookUsers using localfs ((`path`=`asterix_nc1://data/tinysocial/fbu.adm`),(`format`=`adm`));
+
+load  dataset FacebookMessages using localfs ((`path`=`asterix_nc1://data/tinysocial/fbm.adm`),(`format`=`adm`));
+

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_2/union_orderby_2.3.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_2/union_orderby_2.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_2/union_orderby_2.3.query.sqlpp
new file mode 100644
index 0000000..4936ba0
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_2/union_orderby_2.3.query.sqlpp
@@ -0,0 +1,32 @@
+/*
+ * 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;
+
+SELECT t.id id
+FROM FacebookUsers AS t
+UNION ALL
+SELECT s.`message-id` id
+FROM FacebookMessages AS s
+UNION ALL
+(
+  SELECT t.name id
+  FROM FacebookUsers AS t
+)
+ORDER BY id;

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_3/union_orderby_3.1.ddl.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_3/union_orderby_3.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_3/union_orderby_3.1.ddl.sqlpp
new file mode 100644
index 0000000..bdfed09
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_3/union_orderby_3.1.ddl.sqlpp
@@ -0,0 +1,41 @@
+/*
+ * 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 TinySocial.FacebookUserType as
+{
+  id : int64
+}
+
+create type TinySocial.FacebookMessageType as
+{
+  `message-id` : int64
+}
+
+create  dataset FacebookUsers(FacebookUserType) primary key id;
+
+create  dataset FacebookUsers2(FacebookUserType) primary key id;
+
+create  dataset FacebookMessages(FacebookMessageType) primary key `message-id`;
+

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_3/union_orderby_3.2.update.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_3/union_orderby_3.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_3/union_orderby_3.2.update.sqlpp
new file mode 100644
index 0000000..ccd33a5
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_3/union_orderby_3.2.update.sqlpp
@@ -0,0 +1,26 @@
+/*
+ * 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;
+
+
+load  dataset FacebookUsers using localfs ((`path`=`asterix_nc1://data/tinysocial/fbu.adm`),(`format`=`adm`));
+
+load  dataset FacebookMessages using localfs ((`path`=`asterix_nc1://data/tinysocial/fbm.adm`),(`format`=`adm`));
+

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_3/union_orderby_3.3.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_3/union_orderby_3.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_3/union_orderby_3.3.query.sqlpp
new file mode 100644
index 0000000..e65327c
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_3/union_orderby_3.3.query.sqlpp
@@ -0,0 +1,33 @@
+/*
+ * 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;
+
+SELECT t.id id
+FROM FacebookUsers AS t
+UNION ALL
+SELECT s.`message-id` id
+FROM FacebookMessages AS s
+UNION ALL
+SELECT t.name id
+FROM FacebookUsers AS t
+UNION ALL
+SELECT foo id
+FROM [{"first-name":"a", "last-name":"b"}, ["c", "d"], [1234]] AS foo
+ORDER BY id;

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_4/union_orderby_4.1.ddl.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_4/union_orderby_4.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_4/union_orderby_4.1.ddl.sqlpp
new file mode 100644
index 0000000..bdfed09
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_4/union_orderby_4.1.ddl.sqlpp
@@ -0,0 +1,41 @@
+/*
+ * 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 TinySocial.FacebookUserType as
+{
+  id : int64
+}
+
+create type TinySocial.FacebookMessageType as
+{
+  `message-id` : int64
+}
+
+create  dataset FacebookUsers(FacebookUserType) primary key id;
+
+create  dataset FacebookUsers2(FacebookUserType) primary key id;
+
+create  dataset FacebookMessages(FacebookMessageType) primary key `message-id`;
+

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_4/union_orderby_4.2.update.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_4/union_orderby_4.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_4/union_orderby_4.2.update.sqlpp
new file mode 100644
index 0000000..ccd33a5
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_4/union_orderby_4.2.update.sqlpp
@@ -0,0 +1,26 @@
+/*
+ * 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;
+
+
+load  dataset FacebookUsers using localfs ((`path`=`asterix_nc1://data/tinysocial/fbu.adm`),(`format`=`adm`));
+
+load  dataset FacebookMessages using localfs ((`path`=`asterix_nc1://data/tinysocial/fbm.adm`),(`format`=`adm`));
+

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_4/union_orderby_4.3.query.sqlpp
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_4/union_orderby_4.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_4/union_orderby_4.3.query.sqlpp
new file mode 100644
index 0000000..c975fa4
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/union/union_orderby_4/union_orderby_4.3.query.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.
+ */
+
+USE TinySocial;
+
+
+SELECT foo id
+FROM [{"first-name":"a", "last-name":"b"}, ["c", "d"], [1234]] AS foo
+UNION ALL
+SELECT t.id id
+FROM FacebookUsers AS t
+UNION ALL
+SELECT s.`message-id` id
+FROM FacebookMessages AS s
+UNION ALL
+SELECT t.name id
+FROM FacebookUsers AS t
+ORDER BY id;

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-app/src/test/resources/runtimets/results/union/query-ASTERIXDB-1354-2/query-ASTERIXDB-1354-2.1.adm
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/union/query-ASTERIXDB-1354-2/query-ASTERIXDB-1354-2.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/union/query-ASTERIXDB-1354-2/query-ASTERIXDB-1354-2.1.adm
new file mode 100644
index 0000000..3d494b8
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/union/query-ASTERIXDB-1354-2/query-ASTERIXDB-1354-2.1.adm
@@ -0,0 +1,2 @@
+{ "o": { "o_orderkey": 2, "o_custkey": 79, "o_orderstatus": "O", "o_totalprice": 40183.29, "o_orderdate": "1996-12-01", "o_orderpriority": "1-URGENT", "o_clerk": "Clerk#000000880", "o_shippriority": 0, "o_comment": " foxes. pending accounts at the pending, silent asymptot" } }
+{ "l": { "l_orderkey": 2, "l_partkey": 107, "l_suppkey": 2, "l_linenumber": 1, "l_quantity": 38, "l_extendedprice": 38269.8, "l_discount": 0.0, "l_tax": 0.05, "l_returnflag": "N", "l_linestatus": "O", "l_shipdate": "1997-01-28", "l_commitdate": "1997-01-14", "l_receiptdate": "1997-02-02", "l_shipinstruct": "TAKE BACK RETURN", "l_shipmode": "RAIL", "l_comment": "ven requests. deposits breach a" } }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-app/src/test/resources/runtimets/results/union/query-ASTERIXDB-1354/query-ASTERIXDB-1354.1.adm
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/union/query-ASTERIXDB-1354/query-ASTERIXDB-1354.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/union/query-ASTERIXDB-1354/query-ASTERIXDB-1354.1.adm
new file mode 100644
index 0000000..9f5fa37
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/union/query-ASTERIXDB-1354/query-ASTERIXDB-1354.1.adm
@@ -0,0 +1,2 @@
+1
+79

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-app/src/test/resources/runtimets/results/union/union_heterogeneous_scalar/union_heterogeneous_scalar.1.adm
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/union/union_heterogeneous_scalar/union_heterogeneous_scalar.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/union/union_heterogeneous_scalar/union_heterogeneous_scalar.1.adm
new file mode 100644
index 0000000..2d5e9f6
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/union/union_heterogeneous_scalar/union_heterogeneous_scalar.1.adm
@@ -0,0 +1,25 @@
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+"BramHatch"
+"EmoryUnk"
+"IsbelDull"
+"MargaritaStoddard"
+"NicholasStroh"
+"NilaMilliron"
+"SuzannaTillson"
+"VonKemble"
+"WillisWynne"
+"WoodrowNehling"

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-app/src/test/resources/runtimets/results/union/union_orderby/union_orderby.1.adm
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/union/union_orderby/union_orderby.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/union/union_orderby/union_orderby.1.adm
new file mode 100644
index 0000000..58385a9
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/union/union_orderby/union_orderby.1.adm
@@ -0,0 +1,25 @@
+{ "id": 1 }
+{ "id": 1 }
+{ "id": 2 }
+{ "id": 2 }
+{ "id": 3 }
+{ "id": 3 }
+{ "id": 4 }
+{ "id": 4 }
+{ "id": 5 }
+{ "id": 5 }
+{ "id": 6 }
+{ "id": 6 }
+{ "id": 7 }
+{ "id": 7 }
+{ "id": 8 }
+{ "id": 8 }
+{ "id": 9 }
+{ "id": 9 }
+{ "id": 10 }
+{ "id": 10 }
+{ "id": 11 }
+{ "id": 12 }
+{ "id": 13 }
+{ "id": 14 }
+{ "id": 15 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-app/src/test/resources/runtimets/results/union/union_orderby_2/union_orderby_2.1.adm
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/union/union_orderby_2/union_orderby_2.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/union/union_orderby_2/union_orderby_2.1.adm
new file mode 100644
index 0000000..6286610
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/union/union_orderby_2/union_orderby_2.1.adm
@@ -0,0 +1,35 @@
+{ "id": 1 }
+{ "id": 1 }
+{ "id": 2 }
+{ "id": 2 }
+{ "id": 3 }
+{ "id": 3 }
+{ "id": 4 }
+{ "id": 4 }
+{ "id": 5 }
+{ "id": 5 }
+{ "id": 6 }
+{ "id": 6 }
+{ "id": 7 }
+{ "id": 7 }
+{ "id": 8 }
+{ "id": 8 }
+{ "id": 9 }
+{ "id": 9 }
+{ "id": 10 }
+{ "id": 10 }
+{ "id": 11 }
+{ "id": 12 }
+{ "id": 13 }
+{ "id": 14 }
+{ "id": 15 }
+{ "id": "BramHatch" }
+{ "id": "EmoryUnk" }
+{ "id": "IsbelDull" }
+{ "id": "MargaritaStoddard" }
+{ "id": "NicholasStroh" }
+{ "id": "NilaMilliron" }
+{ "id": "SuzannaTillson" }
+{ "id": "VonKemble" }
+{ "id": "WillisWynne" }
+{ "id": "WoodrowNehling" }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-app/src/test/resources/runtimets/results/union/union_orderby_3/union_orderby_3.1.adm
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/union/union_orderby_3/union_orderby_3.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/union/union_orderby_3/union_orderby_3.1.adm
new file mode 100644
index 0000000..f3e8db2
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/union/union_orderby_3/union_orderby_3.1.adm
@@ -0,0 +1,38 @@
+{ "id": 1 }
+{ "id": 1 }
+{ "id": 2 }
+{ "id": 2 }
+{ "id": 3 }
+{ "id": 3 }
+{ "id": 4 }
+{ "id": 4 }
+{ "id": 5 }
+{ "id": 5 }
+{ "id": 6 }
+{ "id": 6 }
+{ "id": 7 }
+{ "id": 7 }
+{ "id": 8 }
+{ "id": 8 }
+{ "id": 9 }
+{ "id": 9 }
+{ "id": 10 }
+{ "id": 10 }
+{ "id": 11 }
+{ "id": 12 }
+{ "id": 13 }
+{ "id": 14 }
+{ "id": 15 }
+{ "id": "BramHatch" }
+{ "id": "EmoryUnk" }
+{ "id": "IsbelDull" }
+{ "id": "MargaritaStoddard" }
+{ "id": "NicholasStroh" }
+{ "id": "NilaMilliron" }
+{ "id": "SuzannaTillson" }
+{ "id": "VonKemble" }
+{ "id": "WillisWynne" }
+{ "id": "WoodrowNehling" }
+{ "id": [ 1234 ] }
+{ "id": [ "c", "d" ] }
+{ "id": { "first-name": "a", "last-name": "b" } }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-app/src/test/resources/runtimets/testsuite.xml
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite.xml b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite.xml
index 9f98434..82f5071 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite.xml
@@ -380,6 +380,11 @@
         <output-dir compare="Text">query-ASTERIXDB-1047</output-dir>
       </compilation-unit>
     </test-case>
+    <test-case FilePath="union">
+      <compilation-unit name="query-ASTERIXDB-1354">
+        <output-dir compare="Text">query-ASTERIXDB-1354</output-dir>
+      </compilation-unit>
+    </test-case>
   </test-group>
   <test-group name="aggregate">
     <test-case FilePath="aggregate">

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
----------------------------------------------------------------------
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 9021994..ff00ea5 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -75,15 +75,6 @@
       </compilation-unit>
     </test-case>
   </test-group>
-  <!--
-    <test-group name="union">
-        <test-case FilePath="union">
-            <compilation-unit name="union">
-                <output-dir compare="Text">union</output-dir>
-            </compilation-unit>
-        </test-case>
-    </test-group>
-    -->
   <test-case FilePath="flwor">
     <compilation-unit name="let33">
       <output-dir compare="Text">let33</output-dir>
@@ -7629,4 +7620,53 @@
       </compilation-unit>
     </test-case>
   </test-group>
+  <test-group name="union">
+    <test-case FilePath="union">
+      <compilation-unit name="union">
+        <output-dir compare="Text">union</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="union">
+      <compilation-unit name="union_heterogeneous_scalar">
+        <output-dir compare="Text">union_heterogeneous_scalar</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="union">
+      <compilation-unit name="union_negative">
+        <output-dir compare="Text">union</output-dir>
+        <expected-error>Cannot find dataset t in dataverse TinySocial nor an alias with name t</expected-error>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="union">
+      <compilation-unit name="union_negative_2">
+        <output-dir compare="Text">union</output-dir>
+        <expected-error>Undefined alias (variable) reference for identifier t</expected-error>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="union">
+      <compilation-unit name="union_orderby">
+        <output-dir compare="Text">union_orderby</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="union">
+      <compilation-unit name="union_orderby_2">
+        <output-dir compare="Text">union_orderby_2</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="union">
+      <compilation-unit name="union_orderby_3">
+        <output-dir compare="Text">union_orderby_3</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="union">
+      <compilation-unit name="union_orderby_4">
+        <output-dir compare="Text">union_orderby_3</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="union">
+      <compilation-unit name="query-ASTERIXDB-1354-2">
+        <output-dir compare="Text">query-ASTERIXDB-1354-2</output-dir>
+      </compilation-unit>
+    </test-case>
+  </test-group>
 </test-suite>

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppFunctionBodyRewriter.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppFunctionBodyRewriter.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppFunctionBodyRewriter.java
index 6ddfa40..43fa4a2 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppFunctionBodyRewriter.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppFunctionBodyRewriter.java
@@ -52,6 +52,9 @@ class SqlppFunctionBodyRewriter extends SqlppQueryRewriter {
         // Group-by core/sugar rewrites.
         rewriteGroupBys();
 
+        // Rewrites set operations.
+        rewriteSetOperations();
+
         // Rewrites like/not-like expressions.
         rewriteOperatorExpression();
 

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
index c85097d..3f7cb31 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
@@ -54,6 +54,7 @@ import org.apache.asterix.lang.sqlpp.rewrites.visitor.GenerateColumnNameVisitor;
 import org.apache.asterix.lang.sqlpp.rewrites.visitor.InlineColumnAliasVisitor;
 import org.apache.asterix.lang.sqlpp.rewrites.visitor.InlineWithExpressionVisitor;
 import org.apache.asterix.lang.sqlpp.rewrites.visitor.OperatorExpressionVisitor;
+import org.apache.asterix.lang.sqlpp.rewrites.visitor.SetOperationVisitor;
 import org.apache.asterix.lang.sqlpp.rewrites.visitor.SqlppBuiltinFunctionRewriteVisitor;
 import org.apache.asterix.lang.sqlpp.rewrites.visitor.SqlppGlobalAggregationSugarVisitor;
 import org.apache.asterix.lang.sqlpp.rewrites.visitor.SqlppGroupByVisitor;
@@ -115,6 +116,9 @@ class SqlppQueryRewriter implements IQueryRewriter {
         // Group-by core/sugar rewrites.
         rewriteGroupBys();
 
+        // Rewrites set operations.
+        rewriteSetOperations();
+
         // Rewrites like/not-like expressions.
         rewriteOperatorExpression();
 
@@ -189,6 +193,15 @@ class SqlppQueryRewriter implements IQueryRewriter {
         substituteGbyExprVisitor.visit(topExpr, null);
     }
 
+    protected void rewriteSetOperations() throws AsterixException {
+        if (topExpr == null) {
+            return;
+        }
+        // Rewrites set operation queries that contain order-by and limit clauses.
+        SetOperationVisitor setOperationVisitor = new SetOperationVisitor(context);
+        setOperationVisitor.visit(topExpr, null);
+    }
+
     protected void rewriteOperatorExpression() throws AsterixException {
         if (topExpr == null) {
             return;

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/InlineColumnAliasVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/InlineColumnAliasVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/InlineColumnAliasVisitor.java
index 4aa25d7..ea0aa86 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/InlineColumnAliasVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/InlineColumnAliasVisitor.java
@@ -274,17 +274,20 @@ public class InlineColumnAliasVisitor extends AbstractSqlppQueryExpressionVisito
             }
         }
 
-        // Visits selectSetOperation.
-        selectExpression.getSelectSetOperation().accept(this, overwriteWithGbyKeyVarRefs);
-
-        // Visits order by.
-        if (selectExpression.hasOrderby()) {
-            selectExpression.getOrderbyClause().accept(this, overwriteWithGbyKeyVarRefs);
-        }
-
-        // Visits limit.
-        if (selectExpression.hasLimit()) {
-            selectExpression.getLimitClause().accept(this, overwriteWithGbyKeyVarRefs);
+        // Visits selectSetOperation
+        SelectSetOperation selectSetOperation = selectExpression.getSelectSetOperation();
+        selectSetOperation.accept(this, overwriteWithGbyKeyVarRefs);
+
+        // If there is a UNION in the selectSetOperation, we cannot overwrite order by or limit.
+        if (!selectSetOperation.hasRightInputs()) {
+            // Visits order by.
+            if (selectExpression.hasOrderby()) {
+                selectExpression.getOrderbyClause().accept(this, overwriteWithGbyKeyVarRefs);
+            }
+            // Visits limit.
+            if (selectExpression.hasLimit()) {
+                selectExpression.getLimitClause().accept(this, overwriteWithGbyKeyVarRefs);
+            }
         }
 
         // Exits the scope that were entered within this select expression

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SetOperationVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SetOperationVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SetOperationVisitor.java
new file mode 100644
index 0000000..66bfecd
--- /dev/null
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SetOperationVisitor.java
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+
+package org.apache.asterix.lang.sqlpp.rewrites.visitor;
+
+import java.util.ArrayList;
+import java.util.Collections;
+
+import org.apache.asterix.common.exceptions.AsterixException;
+import org.apache.asterix.lang.common.base.Expression;
+import org.apache.asterix.lang.common.base.ILangExpression;
+import org.apache.asterix.lang.common.clause.LimitClause;
+import org.apache.asterix.lang.common.clause.OrderbyClause;
+import org.apache.asterix.lang.common.expression.VariableExpr;
+import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
+import org.apache.asterix.lang.sqlpp.clause.FromClause;
+import org.apache.asterix.lang.sqlpp.clause.FromTerm;
+import org.apache.asterix.lang.sqlpp.clause.SelectBlock;
+import org.apache.asterix.lang.sqlpp.clause.SelectClause;
+import org.apache.asterix.lang.sqlpp.clause.SelectElement;
+import org.apache.asterix.lang.sqlpp.clause.SelectSetOperation;
+import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
+import org.apache.asterix.lang.sqlpp.struct.SetOperationInput;
+import org.apache.asterix.lang.sqlpp.visitor.base.AbstractSqlppExpressionScopingVisitor;
+
+/**
+ * This visitor rewrites set operation queries with order by and limit into
+ * a nested query where the set operation part is a subquery in the from clause.
+ * In this way, there is no special variable scoping mechanism that is needed
+ * for order by and limit clauses after the set operation.
+ */
+/*
+For example, the following query
+
+SELECT ... FROM ...
+UNION ALL
+SELECT ... FROM ...
+ORDER BY foo
+Limit 5;
+
+is rewritten into the following form:
+
+SELECT VALUE v
+FROM (
+   SELECT ... FROM ...
+   UNION ALL
+   SELECT ... FROM ...
+ ) AS v
+ORDER BY foo
+LIMIT 5;
+*/
+public class SetOperationVisitor extends AbstractSqlppExpressionScopingVisitor {
+
+    public SetOperationVisitor(LangRewritingContext context) {
+        super(context);
+    }
+
+    @Override
+    public Expression visit(SelectExpression selectExpression, ILangExpression arg) throws AsterixException {
+        // Recursively visit nested select expressions.
+        SelectSetOperation selectSetOperation = selectExpression.getSelectSetOperation();
+        if (!selectSetOperation.hasRightInputs() || !(selectExpression.hasOrderby() || selectExpression.hasLimit())) {
+            return super.visit(selectExpression, arg);
+        }
+        OrderbyClause orderBy = selectExpression.getOrderbyClause();
+        LimitClause limit = selectExpression.getLimitClause();
+
+        // Wraps the set operation part with a subquery.
+        SelectExpression nestedSelectExpression = new SelectExpression(null, selectSetOperation, null, null, true);
+        VariableExpr newBindingVar = new VariableExpr(context.newVariable()); // Binding variable for the subquery.
+        FromTerm newFromTerm = new FromTerm(nestedSelectExpression, newBindingVar, null, null);
+        FromClause newFromClause = new FromClause(new ArrayList<>(Collections.singletonList(newFromTerm)));
+        SelectClause selectClause = new SelectClause(new SelectElement(newBindingVar), null, false);
+        SelectBlock selectBlock = new SelectBlock(selectClause, newFromClause, null, null, null, null, null);
+        SelectSetOperation newSelectSetOperation =
+                new SelectSetOperation(new SetOperationInput(selectBlock, null), null);
+
+        // Puts together the generated select-from-where query and order by/limit.
+        SelectExpression newSelectExpression = new SelectExpression(selectExpression.getLetList(),
+                newSelectSetOperation, orderBy, limit, selectExpression.isSubquery());
+        return super.visit(newSelectExpression, arg);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGroupByVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGroupByVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGroupByVisitor.java
index 36463cb..6575752 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGroupByVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppGroupByVisitor.java
@@ -106,7 +106,7 @@ public class SqlppGroupByVisitor extends AbstractSqlppExpressionScopingVisitor {
             withVarSet.remove(selectBlock.getGroupbyClause().getGroupVar());
 
             Set<VariableExpr> allVisableVars = SqlppVariableUtil
-                    .getLiveUserDefinedVariables(scopeChecker.getCurrentScope());
+                    .getLiveVariables(scopeChecker.getCurrentScope());
             if (selectBlock.hasLetClausesAfterGroupby()) {
                 List<LetClause> letListAfterGby = selectBlock.getLetListAfterGroupby();
                 for (LetClause letClauseAfterGby : letListAfterGby) {

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/VariableCheckAndRewriteVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/VariableCheckAndRewriteVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/VariableCheckAndRewriteVisitor.java
index d250e08..79c99b8 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/VariableCheckAndRewriteVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/VariableCheckAndRewriteVisitor.java
@@ -102,7 +102,7 @@ public class VariableCheckAndRewriteVisitor extends AbstractSqlppExpressionScopi
         if (!rewriteNeeded(varExpr)) {
             return varExpr;
         }
-        Set<VariableExpr> liveVars = SqlppVariableUtil.getLiveUserDefinedVariables(scopeChecker.getCurrentScope());
+        Set<VariableExpr> liveVars = SqlppVariableUtil.getLiveVariables(scopeChecker.getCurrentScope());
         boolean resolveAsDataset = resolveDatasetFirst(arg) && datasetExists(dataverseName, datasetName);
         if (resolveAsDataset) {
             return wrapWithDatasetFunction(dataverseName, datasetName);

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppVariableUtil.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppVariableUtil.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppVariableUtil.java
index a3e8447..b2a07e1 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppVariableUtil.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppVariableUtil.java
@@ -18,7 +18,9 @@
  */
 package org.apache.asterix.lang.sqlpp.util;
 
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
@@ -75,23 +77,16 @@ public class SqlppVariableUtil {
         return varName;
     }
 
-    public static Set<VariableExpr> getLiveUserDefinedVariables(Scope scope) {
+    public static Set<VariableExpr> getLiveVariables(Scope scope) {
         Set<VariableExpr> results = new HashSet<>();
         Set<VariableExpr> liveVars = scope.getLiveVariables();
         Iterator<VariableExpr> liveVarIter = liveVars.iterator();
         while (liveVarIter.hasNext()) {
-            VariableExpr var = liveVarIter.next();
-            if (SqlppVariableUtil.isUserDefinedVariable(var)) {
-                results.add(var);
-            }
+            results.add(liveVarIter.next());
         }
         return results;
     }
 
-    private static boolean isUserDefinedVariable(VariableExpr varExpr) {
-        return varExpr.getVar().getValue().startsWith(USER_VAR_PREFIX);
-    }
-
     public static String toInternalVariableName(String varName) {
         return USER_VAR_PREFIX + varName;
     }
@@ -108,10 +103,10 @@ public class SqlppVariableUtil {
     }
 
     public static Collection<VariableExpr> getBindingVariables(FromClause fromClause) {
-        Set<VariableExpr> bindingVars = new HashSet<>();
         if (fromClause == null) {
-            return bindingVars;
+            return Collections.emptyList();
         }
+        List<VariableExpr> bindingVars = new ArrayList<>();
         for (FromTerm fromTerm : fromClause.getFromTerms()) {
             bindingVars.addAll(getBindingVariables(fromTerm));
         }
@@ -119,7 +114,7 @@ public class SqlppVariableUtil {
     }
 
     public static Collection<VariableExpr> getBindingVariables(FromTerm fromTerm) {
-        Set<VariableExpr> bindingVars = new HashSet<>();
+        List<VariableExpr> bindingVars = new ArrayList<>();
         if (fromTerm == null) {
             return bindingVars;
         }
@@ -137,7 +132,7 @@ public class SqlppVariableUtil {
     }
 
     public static Collection<VariableExpr> getBindingVariables(GroupbyClause gbyClause) {
-        Set<VariableExpr> bindingVars = new HashSet<>();
+        List<VariableExpr> bindingVars = new ArrayList<>();
         if (gbyClause == null) {
             return bindingVars;
         }
@@ -159,7 +154,7 @@ public class SqlppVariableUtil {
     }
 
     public static Collection<VariableExpr> getBindingVariables(List<LetClause> letClauses) {
-        Set<VariableExpr> bindingVars = new HashSet<>();
+        List<VariableExpr> bindingVars = new ArrayList<>();
         if (letClauses == null || letClauses.isEmpty()) {
             return bindingVars;
         }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppExpressionScopingVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppExpressionScopingVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppExpressionScopingVisitor.java
index 4fbb697..13ec855 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppExpressionScopingVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/base/AbstractSqlppExpressionScopingVisitor.java
@@ -177,10 +177,22 @@ public class AbstractSqlppExpressionScopingVisitor extends AbstractSqlppSimpleEx
 
     @Override
     public Expression visit(SelectSetOperation selectSetOperation, ILangExpression arg) throws AsterixException {
+        Scope scopeBeforeCurrentBranch = scopeChecker.getCurrentScope();
+        scopeChecker.createNewScope();
         selectSetOperation.getLeftInput().accept(this, arg);
-        for (SetOperationRight right : selectSetOperation.getRightInputs()) {
-            scopeChecker.createNewScope();
-            right.getSetOperationRightInput().accept(this, arg);
+        if (selectSetOperation.hasRightInputs()) {
+            for (SetOperationRight right : selectSetOperation.getRightInputs()) {
+                // Exit scopes that were entered within a previous select expression
+                while (scopeChecker.getCurrentScope() != scopeBeforeCurrentBranch) {
+                    scopeChecker.removeCurrentScope();
+                }
+                scopeChecker.createNewScope();
+                right.getSetOperationRightInput().accept(this, arg);
+            }
+            // Exit scopes that were entered within the last branch of the set operation.
+            while (scopeChecker.getCurrentScope() != scopeBeforeCurrentBranch) {
+                scopeChecker.removeCurrentScope();
+            }
         }
         return null;
     }
@@ -274,7 +286,7 @@ public class AbstractSqlppExpressionScopingVisitor extends AbstractSqlppSimpleEx
         // variables defined in the parent scope.
         Scope scope = new Scope(scopeChecker, scopeChecker.getCurrentScope(), true);
         scopeChecker.pushExistingScope(scope);
-        independentSubquery.setExpr(independentSubquery.getExpr().accept(this, arg));
+        independentSubquery.setExpr(independentSubquery.getExpr().accept(this, independentSubquery));
         scopeChecker.removeCurrentScope();
         return independentSubquery;
     }
@@ -283,8 +295,8 @@ public class AbstractSqlppExpressionScopingVisitor extends AbstractSqlppSimpleEx
     public Expression visit(QuantifiedExpression qe, ILangExpression arg) throws AsterixException {
         scopeChecker.createNewScope();
         for (QuantifiedPair pair : qe.getQuantifiedList()) {
-            scopeChecker.getCurrentScope().addNewVarSymbolToScope(pair.getVarExpr().getVar());
             pair.setExpr(pair.getExpr().accept(this, qe));
+            scopeChecker.getCurrentScope().addNewVarSymbolToScope(pair.getVarExpr().getVar());
         }
         qe.setSatisfiesExpr(qe.getSatisfiesExpr().accept(this, qe));
         scopeChecker.removeCurrentScope();

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/common/ConflictingTypeResolver.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/common/ConflictingTypeResolver.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/common/ConflictingTypeResolver.java
new file mode 100644
index 0000000..fda032c
--- /dev/null
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/common/ConflictingTypeResolver.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+package org.apache.asterix.dataflow.data.common;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.asterix.om.types.IAType;
+import org.apache.hyracks.algebricks.core.algebra.expressions.IConflictingTypeResolver;
+
+/**
+ * The AsterixDB implementation for IConflictingTypeResolver.
+ */
+public class ConflictingTypeResolver implements IConflictingTypeResolver {
+
+    public static final ConflictingTypeResolver INSTANCE = new ConflictingTypeResolver();
+
+    private ConflictingTypeResolver() {
+    }
+
+    @Override
+    public Object resolve(Object... inputTypes) {
+        List<IAType> types = new ArrayList<>();
+        for (Object object : inputTypes) {
+            types.add((IAType) object);
+        }
+        return TypeResolverUtil.resolve(types);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/common/TypeResolverUtil.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/common/TypeResolverUtil.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/common/TypeResolverUtil.java
new file mode 100644
index 0000000..6d66073
--- /dev/null
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/common/TypeResolverUtil.java
@@ -0,0 +1,202 @@
+/*
+ * 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.
+ */
+
+package org.apache.asterix.dataflow.data.common;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.asterix.om.typecomputer.impl.TypeComputeUtils;
+import org.apache.asterix.om.types.AOrderedListType;
+import org.apache.asterix.om.types.ARecordType;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.AUnionType;
+import org.apache.asterix.om.types.AUnorderedListType;
+import org.apache.asterix.om.types.BuiltinType;
+import org.apache.asterix.om.types.IAType;
+
+/**
+ * A common facility for resolving conflicting types.
+ * It is shared between the <code>ConflictingTypeResolver</code> and <code>SwitchCaseComputer</code>.
+ */
+public class TypeResolverUtil {
+
+    private TypeResolverUtil() {
+    }
+
+    /**
+     * Returns a minimally generalized type that conforms to all input types.
+     *
+     * @param inputTypes,
+     *            a list of input types
+     * @return a generalized type that conforms to all input types.
+     */
+    public static IAType resolve(List<IAType> inputTypes) {
+        IAType currentType = null;
+        for (IAType type : inputTypes) {
+            currentType = currentType == null ? type : generalizeTypes(currentType, type);
+        }
+        return currentType;
+    }
+
+    /**
+     * Decides whether a type cast is needed to covert data instances from the input type to the required type.
+     *
+     * @param reqType,
+     *            the required type.
+     * @param inputType,
+     *            the input type.
+     * @return true of a type cast is needed, false otherwise.
+     */
+    public static boolean needsCast(IAType reqType, IAType inputType) {
+        ATypeTag tag = inputType.getTypeTag();
+        // Gets the actual input type regardless of MISSING and NULL.
+        if (tag == ATypeTag.UNION) {
+            tag = ((AUnionType) inputType).getActualType().getTypeTag();
+        }
+        // Casts are only needed when the original return type is a complex type.
+        // (In the runtime, there is already a type tag for scalar types.)
+        if (tag != ATypeTag.RECORD && tag != ATypeTag.UNORDEREDLIST && tag != ATypeTag.ORDEREDLIST) {
+            return false;
+        }
+        return !TypeComputeUtils.getActualType(reqType).equals(TypeComputeUtils.getActualType(inputType));
+    }
+
+    // Generalizes two input types.
+    private static IAType generalizeTypes(IAType inputLeftType, IAType inputRightType) {
+        IAType leftType = inputLeftType;
+        IAType rightType = inputRightType;
+        ATypeTag leftTypeTag = leftType.getTypeTag();
+        ATypeTag rightTypeTag = rightType.getTypeTag();
+        boolean unknownable = false;
+
+        // Gets the actual types for UNIONs and mark unknownable to be true.
+        if (leftTypeTag == ATypeTag.UNION || rightTypeTag == ATypeTag.UNION) {
+            leftType = TypeComputeUtils.getActualType(leftType);
+            rightType = TypeComputeUtils.getActualType(leftType);
+            leftTypeTag = leftType.getTypeTag();
+            rightTypeTag = rightType.getTypeTag();
+            unknownable = true;
+        }
+        if (leftType.equals(rightType)) {
+            return unknownable ? AUnionType.createUnknownableType(leftType) : leftType;
+        }
+
+        // Deals with the case one input type is null or missing.
+        if (leftTypeTag == ATypeTag.MISSING || leftTypeTag == ATypeTag.NULL) {
+            return AUnionType.createUnknownableType(leftType);
+        }
+        if (rightTypeTag == ATypeTag.MISSING || rightTypeTag == ATypeTag.NULL) {
+            return AUnionType.createUnknownableType(leftType);
+        }
+
+        // If two input types have different type tags (UNION/NULL/MISSING have been excluded), we return ANY here.
+        if (leftTypeTag != rightTypeTag) {
+            return BuiltinType.ANY;
+        }
+
+        // If two input types have the same type tag but are not equal, they can only be complex types.
+        IAType generalizedComplexType = generalizeComplexTypes(leftTypeTag, leftType, rightType);
+        return unknownable ? AUnionType.createUnknownableType(generalizedComplexType) : generalizedComplexType;
+    }
+
+    // Generalizes two complex types, e.g., record, ordered list and unordered list.
+    private static IAType generalizeComplexTypes(ATypeTag typeTag, IAType leftType, IAType rightType) {
+        switch (typeTag) {
+            case RECORD:
+                return generalizeRecordTypes((ARecordType) leftType, (ARecordType) rightType);
+            case ORDEREDLIST:
+                return generalizeOrderedListTypes((AOrderedListType) leftType, (AOrderedListType) rightType);
+            case UNORDEREDLIST:
+                return generalizeUnorderedListTypes((AUnorderedListType) leftType, (AUnorderedListType) rightType);
+            default:
+                return BuiltinType.ANY;
+        }
+    }
+
+    // Generalizes two record types.
+    private static ARecordType generalizeRecordTypes(ARecordType leftType, ARecordType rightType) {
+        boolean knowsAdditonalFieldNames = true;
+        Set<String> allPossibleAdditionalFieldNames = new HashSet<>();
+        if (leftType.isOpen() && !leftType.knowsAllPossibleAdditonalFieldNames()) {
+            knowsAdditonalFieldNames = false;
+        } else if (leftType.isOpen()) {
+            allPossibleAdditionalFieldNames.addAll(leftType.getAllPossibleAdditonalFieldNames());
+        }
+        if (rightType.isOpen() && !rightType.knowsAllPossibleAdditonalFieldNames()) {
+            knowsAdditonalFieldNames = false;
+        } else if (rightType.isOpen()) {
+            allPossibleAdditionalFieldNames.addAll(rightType.getAllPossibleAdditonalFieldNames());
+        }
+        boolean canBeClosed = !leftType.isOpen() && !rightType.isOpen();
+        List<String> fieldNames = new ArrayList<>();
+        List<IAType> fieldTypes = new ArrayList<>();
+        boolean leftAllMatched =
+                generalizeRecordFields(leftType, rightType, allPossibleAdditionalFieldNames, fieldNames, fieldTypes);
+        boolean rightAllMatched =
+                generalizeRecordFields(rightType, leftType, allPossibleAdditionalFieldNames, fieldNames, fieldTypes);
+        return new ARecordType("generalized-record-type", fieldNames.toArray(new String[fieldNames.size()]),
+                fieldTypes.toArray(new IAType[fieldTypes.size()]), !(canBeClosed && leftAllMatched && rightAllMatched),
+                knowsAdditonalFieldNames ? allPossibleAdditionalFieldNames : null);
+    }
+
+    // Generates closed fields and possible additional fields of a generalized type of two record types.
+    private static boolean generalizeRecordFields(ARecordType leftType, ARecordType rightType,
+            Set<String> allPossibleAdditionalFieldNames, List<String> fieldNames, List<IAType> fieldTypes) {
+        boolean allMatched = true;
+        Set<String> existingFieldNames = new HashSet<>(fieldNames);
+        for (String fieldName : leftType.getFieldNames()) {
+            IAType leftFieldType = leftType.getFieldType(fieldName);
+            IAType rightFieldType = rightType.getFieldType(fieldName);
+            IAType generalizedFieldType =
+                    rightFieldType == null ? null : generalizeTypes(leftFieldType, rightFieldType);
+            if (generalizedFieldType == null || generalizedFieldType.equals(BuiltinType.ANY)) {
+                allPossibleAdditionalFieldNames.add(fieldName);
+                allMatched = false;
+            } else if (!existingFieldNames.contains(fieldName)) {
+                fieldNames.add(fieldName);
+                fieldTypes.add(generalizedFieldType);
+            }
+        }
+        return allMatched;
+    }
+
+    // Generalizes two ordered list types.
+    private static AOrderedListType generalizeOrderedListTypes(AOrderedListType leftType, AOrderedListType rightType) {
+        return new AOrderedListType(processItemType(generalizeTypes(leftType.getItemType(), rightType.getItemType())),
+                "generalized-ordered-list");
+    }
+
+    // Generalizes two unordered list types.
+    private static AUnorderedListType generalizeUnorderedListTypes(AUnorderedListType leftType,
+            AUnorderedListType rightType) {
+        return new AUnorderedListType(processItemType(generalizeTypes(leftType.getItemType(), rightType.getItemType())),
+                "generalized-unordered-list");
+    }
+
+    // A special processing for generalized item types in collections:
+    // a collection cannot maintain an item type of UNION. In this case, the item type has to be ANY.
+    private static IAType processItemType(IAType type) {
+        ATypeTag tag = type.getTypeTag();
+        return tag == ATypeTag.UNION ? BuiltinType.ANY : type;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/cast/ACastVisitor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/cast/ACastVisitor.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/cast/ACastVisitor.java
index b551c88..00c4075 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/cast/ACastVisitor.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/cast/ACastVisitor.java
@@ -105,8 +105,13 @@ public class ACastVisitor implements IVisitablePointableVisitor<Void, Triple<IVi
         }
         // set the pointer for result
         ATypeTag reqTypeTag = (arg.second).getTypeTag();
-        ATypeTag inputTypeTag = EnumDeserializer.ATYPETAGDESERIALIZER
-                .deserialize(accessor.getByteArray()[accessor.getStartOffset()]);
+        if (reqTypeTag == ATypeTag.ANY) {
+            // for open type case
+            arg.first.set(accessor);
+            return null;
+        }
+        ATypeTag inputTypeTag =
+                EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(accessor.getByteArray()[accessor.getStartOffset()]);
         if (!needPromote(inputTypeTag, reqTypeTag)) {
             arg.first.set(accessor);
         } else {

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/SwitchCaseComputer.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/SwitchCaseComputer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/SwitchCaseComputer.java
index 0eb60cb..22fe89f 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/SwitchCaseComputer.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/typecomputer/impl/SwitchCaseComputer.java
@@ -18,10 +18,11 @@
  */
 package org.apache.asterix.om.typecomputer.impl;
 
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.asterix.dataflow.data.common.TypeResolverUtil;
 import org.apache.asterix.om.typecomputer.base.IResultTypeComputer;
-import org.apache.asterix.om.types.ATypeTag;
-import org.apache.asterix.om.types.AUnionType;
-import org.apache.asterix.om.types.BuiltinType;
 import org.apache.asterix.om.types.IAType;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
@@ -45,31 +46,14 @@ public class SwitchCaseComputer implements IResultTypeComputer {
         if (fce.getArguments().size() < 3) {
             throw new AlgebricksException(ERR_MSG);
         }
-
-        IAType currentType = null;
-        boolean any = false;
-        boolean unknownable = false;
         int argSize = fce.getArguments().size();
-        // Checks return types of different branches' return types.
+        List<IAType> types = new ArrayList<>();
+        // Collects different branches' return types.
         // The last return expression is from the ELSE branch and it is optional.
         for (int argIndex = 2; argIndex < argSize; argIndex += (argIndex + 2 == argSize) ? 1 : 2) {
             IAType type = (IAType) env.getType(fce.getArguments().get(argIndex).getValue());
-            ATypeTag typeTag = type.getTypeTag();
-            if (typeTag == ATypeTag.NULL || typeTag == ATypeTag.MISSING) {
-                unknownable = true;
-            } else {
-                if (typeTag == ATypeTag.UNION) {
-                    type = ((AUnionType) type).getActualType();
-                    unknownable = true;
-                }
-                if (currentType != null && !type.equals(currentType)) {
-                    any = true;
-                    break;
-                }
-                currentType = type;
-            }
+            types.add(type);
         }
-        currentType = currentType == null ? BuiltinType.ANULL : currentType;
-        return any ? BuiltinType.ANY : unknownable ? AUnionType.createUnknownableType(currentType) : currentType;
+        return TypeResolverUtil.resolve(types);
     }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/ARecordType.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/ARecordType.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/ARecordType.java
index f2379ef..248ec3a 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/ARecordType.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/ARecordType.java
@@ -44,8 +44,8 @@ import org.json.JSONObject;
  */
 public class ARecordType extends AbstractComplexType {
 
-    public static final ARecordType FULLY_OPEN_RECORD_TYPE = new ARecordType("OpenRecord", new String[0], new IAType[0],
-            true);
+    public static final ARecordType FULLY_OPEN_RECORD_TYPE =
+            new ARecordType("OpenRecord", new String[0], new IAType[0], true);
 
     private static final long serialVersionUID = 1L;
     private final String[] fieldNames;
@@ -116,6 +116,14 @@ public class ARecordType extends AbstractComplexType {
         }
     }
 
+    public boolean knowsAllPossibleAdditonalFieldNames() {
+        return allPossibleAdditionalFieldNames != null;
+    }
+
+    public Set<String> getAllPossibleAdditonalFieldNames() {
+        return allPossibleAdditionalFieldNames;
+    }
+
     public String[] getFieldNames() {
         return fieldNames;
     }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-om/src/test/java/org/apache/asterix/dataflow/data/common/TypeResolverUtilTest.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-om/src/test/java/org/apache/asterix/dataflow/data/common/TypeResolverUtilTest.java b/asterixdb/asterix-om/src/test/java/org/apache/asterix/dataflow/data/common/TypeResolverUtilTest.java
new file mode 100644
index 0000000..5303870
--- /dev/null
+++ b/asterixdb/asterix-om/src/test/java/org/apache/asterix/dataflow/data/common/TypeResolverUtilTest.java
@@ -0,0 +1,199 @@
+/*
+ * 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.
+ */
+
+package org.apache.asterix.dataflow.data.common;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.asterix.om.types.AOrderedListType;
+import org.apache.asterix.om.types.ARecordType;
+import org.apache.asterix.om.types.AUnionType;
+import org.apache.asterix.om.types.AUnorderedListType;
+import org.apache.asterix.om.types.AbstractCollectionType;
+import org.apache.asterix.om.types.BuiltinType;
+import org.apache.asterix.om.types.IAType;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Tests for TypeResolverUtil.
+ */
+public class TypeResolverUtilTest {
+
+    @Test
+    public void testRecordType() {
+        // Constructs input types.
+        ARecordType leftRecordType = new ARecordType(null, new String[] { "a", "b" },
+                new IAType[] { BuiltinType.ASTRING, BuiltinType.AINT32 }, false, null);
+        ARecordType rightRecordType = new ARecordType(null, new String[] { "b", "c" },
+                new IAType[] { BuiltinType.AINT32, BuiltinType.ABINARY }, false, null);
+
+        // Resolves input types to a generalized type.
+        List<IAType> inputTypes = new ArrayList<>();
+        inputTypes.add(leftRecordType);
+        inputTypes.add(rightRecordType);
+        ARecordType resolvedType = (ARecordType) TypeResolverUtil.resolve(inputTypes);
+
+        // Constructs the expected type.
+        Set<String> possibleAdditionalFields = new HashSet<>();
+        possibleAdditionalFields.add("a");
+        possibleAdditionalFields.add("c");
+        ARecordType expectedType = new ARecordType(null, new String[] { "b" }, new IAType[] { BuiltinType.AINT32 },
+                true, possibleAdditionalFields);
+
+        // Compares the resolved type with the expected type.
+        Assert.assertEquals(resolvedType, expectedType);
+        Assert.assertEquals(resolvedType.getAllPossibleAdditonalFieldNames(),
+                expectedType.getAllPossibleAdditonalFieldNames());
+    }
+
+    @Test
+    public void testIsmophicRecordType() {
+        // Constructs input types.
+        ARecordType leftRecordType = new ARecordType(null, new String[] { "a", "b" },
+                new IAType[] { BuiltinType.ASTRING, BuiltinType.AINT32 }, false, null);
+        ARecordType rightRecordType = new ARecordType(null, new String[] { "b", "a" },
+                new IAType[] { BuiltinType.AINT32, BuiltinType.ASTRING }, false, null);
+
+        // Resolves input types to a generalized type.
+        List<IAType> inputTypes = new ArrayList<>();
+        inputTypes.add(leftRecordType);
+        inputTypes.add(rightRecordType);
+        ARecordType resolvedType = (ARecordType) TypeResolverUtil.resolve(inputTypes);
+
+        // Compares the resolved type with the expected type.
+        Assert.assertEquals(resolvedType, leftRecordType);
+    }
+
+    @Test
+    public void testNestedRecordType() {
+        // Constructs input types.
+        ARecordType leftRecordType =
+                new ARecordType("null", new String[] { "a", "b" },
+                        new IAType[] { BuiltinType.ASTRING,
+                                new ARecordType(null, new String[] { "c", "d" },
+                                        new IAType[] { BuiltinType.ASTRING, BuiltinType.AINT32 }, false, null) },
+                        false, null);
+        ARecordType rightRecordType =
+                new ARecordType("null", new String[] { "a", "b" },
+                        new IAType[] { BuiltinType.ASTRING,
+                                new ARecordType(null, new String[] { "d", "e" },
+                                        new IAType[] { BuiltinType.AINT32, BuiltinType.AINT32 }, false, null) },
+                        false, null);
+
+        // Resolves input types to a generalized type.
+        List<IAType> inputTypes = new ArrayList<>();
+        inputTypes.add(leftRecordType);
+        inputTypes.add(rightRecordType);
+        ARecordType resolvedType = (ARecordType) TypeResolverUtil.resolve(inputTypes);
+        ARecordType nestedRecordType = (ARecordType) resolvedType.getFieldType("b");
+
+        // Constructs the expected type.
+        Set<String> nestedPossibleAdditionalFields = new HashSet<>();
+        nestedPossibleAdditionalFields.add("c");
+        nestedPossibleAdditionalFields.add("e");
+        ARecordType expectedType =
+                new ARecordType(null, new String[] { "a", "b" },
+                        new IAType[] { BuiltinType.ASTRING, new ARecordType(null, new String[] { "d" },
+                                new IAType[] { BuiltinType.AINT32 }, true, nestedPossibleAdditionalFields) },
+                        false, null);
+
+        // Compares the resolved type with the expected type.
+        Assert.assertEquals(expectedType, resolvedType);
+        Assert.assertEquals(nestedRecordType.getAllPossibleAdditonalFieldNames(), nestedPossibleAdditionalFields);
+    }
+
+    @Test
+    public void testOrderedListType() {
+        // Constructs input types.
+        ARecordType leftRecordType = new ARecordType("null", new String[] { "a", "b" },
+                new IAType[] { BuiltinType.ASTRING, BuiltinType.AINT32 }, true, Collections.singleton("d"));
+        AOrderedListType leftListType = new AOrderedListType(leftRecordType, "null");
+        ARecordType rightRecordType = new ARecordType("null", new String[] { "b", "c" },
+                new IAType[] { BuiltinType.AINT32, BuiltinType.ABINARY }, true, Collections.singleton("e"));
+        AOrderedListType rightListType = new AOrderedListType(rightRecordType, "null");
+
+        // Gets the actual resolved type.
+        List<IAType> inputTypes = new ArrayList<>();
+        inputTypes.add(leftListType);
+        inputTypes.add(rightListType);
+        AbstractCollectionType resolvedType = (AbstractCollectionType) TypeResolverUtil.resolve(inputTypes);
+        ARecordType resolvedRecordType = (ARecordType) resolvedType.getItemType();
+
+        // Gets the expected generalized type.
+        Set<String> possibleAdditionalFields = new HashSet<>();
+        possibleAdditionalFields.add("a");
+        possibleAdditionalFields.add("c");
+        possibleAdditionalFields.add("d");
+        possibleAdditionalFields.add("e");
+        ARecordType expectedRecordType = new ARecordType(null, new String[] { "b" },
+                new IAType[] { BuiltinType.AINT32 }, true, possibleAdditionalFields);
+        AOrderedListType expectedListType = new AOrderedListType(expectedRecordType, null);
+
+        // Compares the resolved type and the expected type.
+        Assert.assertEquals(resolvedType, expectedListType);
+        Assert.assertEquals(resolvedRecordType.getAllPossibleAdditonalFieldNames(),
+                expectedRecordType.getAllPossibleAdditonalFieldNames());
+    }
+
+    @Test
+    public void testUnorderedListType() {
+        // Constructs input types.
+        ARecordType leftRecordType = new ARecordType(null, new String[] { "a", "b" },
+                new IAType[] { BuiltinType.ASTRING, BuiltinType.AINT32 }, true, Collections.singleton("d"));
+        AUnorderedListType leftListType = new AUnorderedListType(leftRecordType, null);
+        AUnorderedListType rightListType = new AUnorderedListType(BuiltinType.ASTRING, null);
+
+        // Gets the actual resolved type.
+        List<IAType> inputTypes = new ArrayList<>();
+        inputTypes.add(leftListType);
+        inputTypes.add(rightListType);
+        AbstractCollectionType resolvedType = (AbstractCollectionType) TypeResolverUtil.resolve(inputTypes);
+
+        // Compares the resolved type and the expected type.
+        Assert.assertEquals(resolvedType, new AUnorderedListType(BuiltinType.ANY, null));
+    }
+
+    @Test
+    public void testNullType() {
+        ARecordType leftRecordType = new ARecordType(null, new String[] { "a", "b" },
+                new IAType[] { BuiltinType.ASTRING, BuiltinType.AINT32 }, false, null);
+        List<IAType> inputTypes = new ArrayList<>();
+        inputTypes.add(leftRecordType);
+        inputTypes.add(BuiltinType.ANULL);
+        IAType resolvedType = TypeResolverUtil.resolve(inputTypes);
+        Assert.assertEquals(resolvedType, AUnionType.createUnknownableType(leftRecordType));
+    }
+
+    @Test
+    public void testMissingType() {
+        ARecordType leftRecordType = new ARecordType(null, new String[] { "a", "b" },
+                new IAType[] { BuiltinType.ASTRING, BuiltinType.AINT32 }, false, null);
+        List<IAType> inputTypes = new ArrayList<>();
+        inputTypes.add(leftRecordType);
+        inputTypes.add(BuiltinType.AMISSING);
+        IAType resolvedType = TypeResolverUtil.resolve(inputTypes);
+        Assert.assertEquals(resolvedType, AUnionType.createUnknownableType(leftRecordType));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CastTypeDescriptor.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CastTypeDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CastTypeDescriptor.java
index 5c754cf..51b10dc 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CastTypeDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CastTypeDescriptor.java
@@ -26,6 +26,7 @@ import org.apache.asterix.om.pointables.PointableAllocator;
 import org.apache.asterix.om.pointables.base.DefaultOpenFieldType;
 import org.apache.asterix.om.pointables.base.IVisitablePointable;
 import org.apache.asterix.om.pointables.cast.ACastVisitor;
+import org.apache.asterix.om.typecomputer.impl.TypeComputeUtils;
 import org.apache.asterix.om.types.ATypeTag;
 import org.apache.asterix.om.types.BuiltinType;
 import org.apache.asterix.om.types.IAType;
@@ -67,8 +68,9 @@ public class CastTypeDescriptor extends AbstractScalarFunctionDynamicDescriptor
             throw new IllegalStateException(
                     "Invalid types for casting, required type " + reqType + ", input type " + inputType);
         }
-        this.reqType = reqType;
-        this.inputType = inputType;
+        // NULLs and MISSINGs are handled by the generated code, therefore we only need to handle actual types here.
+        this.reqType = TypeComputeUtils.getActualType(reqType);
+        this.inputType = TypeComputeUtils.getActualType(inputType);
     }
 
     @Override
@@ -107,8 +109,8 @@ class CastTypeEvaluator implements IScalarEvaluator {
             throws AlgebricksException {
         try {
             this.argEvaluator = argEvaluator;
-            this.inputPointable = allocateResultPointable(inputType, reqType);
-            this.resultPointable = allocateResultPointable(reqType, inputType);
+            this.inputPointable = allocatePointable(inputType, reqType);
+            this.resultPointable = allocatePointable(reqType, inputType);
             this.arg = new Triple<>(resultPointable, reqType, Boolean.FALSE);
         } catch (AsterixException e) {
             throw new AlgebricksException(e);
@@ -128,7 +130,7 @@ class CastTypeEvaluator implements IScalarEvaluator {
     }
 
     // Allocates the result pointable.
-    private final IVisitablePointable allocateResultPointable(IAType typeForPointable, IAType typeForOtherSide)
+    private final IVisitablePointable allocatePointable(IAType typeForPointable, IAType typeForOtherSide)
             throws AsterixException {
         if (!typeForPointable.equals(BuiltinType.ANY)) {
             return allocator.allocateFieldValue(typeForPointable);

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/AbstractCompilerFactoryBuilder.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/AbstractCompilerFactoryBuilder.java b/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/AbstractCompilerFactoryBuilder.java
index 6f28df3..deed53d 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/AbstractCompilerFactoryBuilder.java
+++ b/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/AbstractCompilerFactoryBuilder.java
@@ -23,6 +23,7 @@ import java.util.List;
 import org.apache.hyracks.algebricks.common.constraints.AlgebricksAbsolutePartitionConstraint;
 import org.apache.hyracks.algebricks.common.constraints.AlgebricksPartitionConstraint;
 import org.apache.hyracks.algebricks.common.utils.Pair;
+import org.apache.hyracks.algebricks.core.algebra.expressions.IConflictingTypeResolver;
 import org.apache.hyracks.algebricks.core.algebra.expressions.IExpressionEvalSizeComputer;
 import org.apache.hyracks.algebricks.core.algebra.expressions.IExpressionRuntimeProvider;
 import org.apache.hyracks.algebricks.core.algebra.expressions.IExpressionTypeComputer;
@@ -60,6 +61,7 @@ public abstract class AbstractCompilerFactoryBuilder {
     protected IExpressionRuntimeProvider expressionRuntimeProvider;
     protected IExpressionTypeComputer expressionTypeComputer;
     protected IMissableTypeComputer missableTypeComputer;
+    protected IConflictingTypeResolver conflictingTypeResolver;
     protected IExpressionEvalSizeComputer expressionEvalSizeComputer;
     protected IMissingWriterFactory missingWriterFactory;
     protected INormalizedKeyComputerFactoryProvider normalizedKeyComputerFactoryProvider;
@@ -232,4 +234,12 @@ public abstract class AbstractCompilerFactoryBuilder {
         return missableTypeComputer;
     }
 
+    public void setConflictingTypeResolver(IConflictingTypeResolver conflictingTypeResolver) {
+        this.conflictingTypeResolver = conflictingTypeResolver;
+    }
+
+    public IConflictingTypeResolver getConflictingTypeResolver() {
+        return conflictingTypeResolver;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/HeuristicCompilerFactoryBuilder.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/HeuristicCompilerFactoryBuilder.java b/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/HeuristicCompilerFactoryBuilder.java
index 09982a0..311aa43 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/HeuristicCompilerFactoryBuilder.java
+++ b/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/HeuristicCompilerFactoryBuilder.java
@@ -22,6 +22,7 @@ import org.apache.hyracks.algebricks.common.constraints.AlgebricksPartitionConst
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
 import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
+import org.apache.hyracks.algebricks.core.algebra.expressions.IConflictingTypeResolver;
 import org.apache.hyracks.algebricks.core.algebra.expressions.IExpressionEvalSizeComputer;
 import org.apache.hyracks.algebricks.core.algebra.expressions.IExpressionTypeComputer;
 import org.apache.hyracks.algebricks.core.algebra.expressions.IMergeAggregationExpressionFactory;
@@ -52,11 +53,12 @@ public class HeuristicCompilerFactoryBuilder extends AbstractCompilerFactoryBuil
                 IExpressionEvalSizeComputer expressionEvalSizeComputer,
                 IMergeAggregationExpressionFactory mergeAggregationExpressionFactory,
                 IExpressionTypeComputer expressionTypeComputer, IMissableTypeComputer missableTypeComputer,
-                PhysicalOptimizationConfig physicalOptimizationConfig, AlgebricksPartitionConstraint clusterLocations) {
+                IConflictingTypeResolver conflictingTypeResolver, PhysicalOptimizationConfig physicalOptimizationConfig,
+                AlgebricksPartitionConstraint clusterLocations) {
             LogicalOperatorPrettyPrintVisitor prettyPrintVisitor = new LogicalOperatorPrettyPrintVisitor();
             return new AlgebricksOptimizationContext(varCounter, expressionEvalSizeComputer,
                     mergeAggregationExpressionFactory, expressionTypeComputer, missableTypeComputer,
-                    physicalOptimizationConfig, clusterLocations, prettyPrintVisitor);
+                    conflictingTypeResolver, physicalOptimizationConfig, clusterLocations, prettyPrintVisitor);
         }
     }
 
@@ -78,7 +80,7 @@ public class HeuristicCompilerFactoryBuilder extends AbstractCompilerFactoryBuil
                     int varCounter) {
                 final IOptimizationContext oc = optCtxFactory.createOptimizationContext(varCounter,
                         expressionEvalSizeComputer, mergeAggregationExpressionFactory, expressionTypeComputer,
-                        missableTypeComputer, physicalOptimizationConfig, clusterLocations);
+                        missableTypeComputer, conflictingTypeResolver, physicalOptimizationConfig, clusterLocations);
                 oc.setMetadataDeclarations(metadata);
                 final HeuristicOptimizer opt = new HeuristicOptimizer(plan, logicalRewrites, physicalRewrites, oc);
                 return new ICompiler() {

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/expressions/IConflictingTypeResolver.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/expressions/IConflictingTypeResolver.java b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/expressions/IConflictingTypeResolver.java
new file mode 100644
index 0000000..a6b5701
--- /dev/null
+++ b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/expressions/IConflictingTypeResolver.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+package org.apache.hyracks.algebricks.core.algebra.expressions;
+
+/**
+ * This interface is in charge of resolving conflicting types and returning
+ * a resolved type that conform to all input types in the case there are conflicting
+ * types during type inference. For example, a UNION ALL operator can union a sequence
+ * of integers with a sequence of records, where the two input sequences have
+ * conflicting types.
+ */
+@FunctionalInterface
+public interface IConflictingTypeResolver {
+
+    /**
+     * Resolves conflicting input types and return a type that conforms to every input type.
+     *
+     * @param inputTypes,
+     *            conflicting types that need to be resolved.
+     * @return a (potentially relaxed) type that conform to all input types.
+     */
+    public Object resolve(Object... inputTypes);
+
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/b7624575/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/expressions/VariableReferenceExpression.java
----------------------------------------------------------------------
diff --git a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/expressions/VariableReferenceExpression.java b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/expressions/VariableReferenceExpression.java
index 865e781..c02eec3 100644
--- a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/expressions/VariableReferenceExpression.java
+++ b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/expressions/VariableReferenceExpression.java
@@ -22,7 +22,6 @@ import java.util.Collection;
 import java.util.List;
 
 import org.apache.commons.lang3.mutable.Mutable;
-
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
 import org.apache.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
@@ -70,9 +69,7 @@ public class VariableReferenceExpression extends AbstractLogicalExpression {
 
     @Override
     public void getUsedVariables(Collection<LogicalVariable> vars) {
-        // if (!vars.contains(variable)) {
         vars.add(variable);
-        // }
     }
 
     @Override


Mime
View raw message