Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 5E5C5200B5A for ; Thu, 4 Aug 2016 16:29:02 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 5CAA5160A6A; Thu, 4 Aug 2016 14:29:02 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id E661F160AAB for ; Thu, 4 Aug 2016 16:28:59 +0200 (CEST) Received: (qmail 20722 invoked by uid 500); 4 Aug 2016 14:28:59 -0000 Mailing-List: contact commits-help@asterixdb.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@asterixdb.apache.org Delivered-To: mailing list commits@asterixdb.apache.org Received: (qmail 20711 invoked by uid 99); 4 Aug 2016 14:28:59 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 04 Aug 2016 14:28:59 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id B61DEE08E8; Thu, 4 Aug 2016 14:28:58 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: buyingyi@apache.org To: commits@asterixdb.apache.org Date: Thu, 04 Aug 2016 14:28:59 -0000 Message-Id: <818f27193ec04e83a233986d99e77c2c@git.apache.org> In-Reply-To: <9a962848985d47b1accc7ab9131afaad@git.apache.org> References: <9a962848985d47b1accc7ab9131afaad@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [2/3] asterixdb git commit: Support UNION ALL. archived-at: Thu, 04 Aug 2016 14:29:02 -0000 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 @@ query-ASTERIXDB-1047 + + + query-ASTERIXDB-1354 + + 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 @@ - let33 @@ -7629,4 +7620,53 @@ + + + + union + + + + + union_heterogeneous_scalar + + + + + union + Cannot find dataset t in dataverse TinySocial nor an alias with name t + + + + + union + Undefined alias (variable) reference for identifier t + + + + + union_orderby + + + + + union_orderby_2 + + + + + union_orderby_3 + + + + + union_orderby_3 + + + + + query-ASTERIXDB-1354-2 + + + 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 allVisableVars = SqlppVariableUtil - .getLiveUserDefinedVariables(scopeChecker.getCurrentScope()); + .getLiveVariables(scopeChecker.getCurrentScope()); if (selectBlock.hasLetClausesAfterGroupby()) { List 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 liveVars = SqlppVariableUtil.getLiveUserDefinedVariables(scopeChecker.getCurrentScope()); + Set 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 getLiveUserDefinedVariables(Scope scope) { + public static Set getLiveVariables(Scope scope) { Set results = new HashSet<>(); Set liveVars = scope.getLiveVariables(); Iterator 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 getBindingVariables(FromClause fromClause) { - Set bindingVars = new HashSet<>(); if (fromClause == null) { - return bindingVars; + return Collections.emptyList(); } + List bindingVars = new ArrayList<>(); for (FromTerm fromTerm : fromClause.getFromTerms()) { bindingVars.addAll(getBindingVariables(fromTerm)); } @@ -119,7 +114,7 @@ public class SqlppVariableUtil { } public static Collection getBindingVariables(FromTerm fromTerm) { - Set bindingVars = new HashSet<>(); + List bindingVars = new ArrayList<>(); if (fromTerm == null) { return bindingVars; } @@ -137,7 +132,7 @@ public class SqlppVariableUtil { } public static Collection getBindingVariables(GroupbyClause gbyClause) { - Set bindingVars = new HashSet<>(); + List bindingVars = new ArrayList<>(); if (gbyClause == null) { return bindingVars; } @@ -159,7 +154,7 @@ public class SqlppVariableUtil { } public static Collection getBindingVariables(List letClauses) { - Set bindingVars = new HashSet<>(); + List 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 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 ConflictingTypeResolver and SwitchCaseComputer. + */ +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 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 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 fieldNames = new ArrayList<>(); + List 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 allPossibleAdditionalFieldNames, List fieldNames, List fieldTypes) { + boolean allMatched = true; + Set 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 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 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 inputTypes = new ArrayList<>(); + inputTypes.add(leftRecordType); + inputTypes.add(rightRecordType); + ARecordType resolvedType = (ARecordType) TypeResolverUtil.resolve(inputTypes); + + // Constructs the expected type. + Set 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 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 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 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 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 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 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 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 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 vars) { - // if (!vars.contains(variable)) { vars.add(variable); - // } } @Override