Steven Jacobs has uploaded a new change for review. https://asterix-gerrit.ics.uci.edu/2735
Change subject: [ASTERIXDB-2402][COMP] Allow AND for IsMissing in Groupby ...................................................................... [ASTERIXDB-2402][COMP] Allow AND for IsMissing in Groupby AccessMethodUtils.findLOJIsMissingFuncInGroupBy() looks for the not(is-missing($VAR)) pattern in a group by, but failed to detect it if it is part of an and, e.g. and(not(is-missing($VAR1)),not(is-missing($VAR2))) This changes fixes this and adds a test case Change-Id: I9547fba5e4ba02226b5b2c2504080b091d3b8d5e --- M asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AccessMethodUtils.java A asterixdb/asterix-app/src/test/resources/optimizerts/queries/ASTERIXDB-2402.sqlpp A asterixdb/asterix-app/src/test/resources/optimizerts/results/ASTERIXDB-2402.plan 3 files changed, 348 insertions(+), 11 deletions(-) git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb refs/changes/35/2735/1 diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AccessMethodUtils.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AccessMethodUtils.java index 6368058..13c09cd 100644 --- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AccessMethodUtils.java +++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AccessMethodUtils.java @@ -1483,6 +1483,23 @@ return createRectangleExpr; } + private static ScalarFunctionCallExpression getNestedIsMissingCall(AbstractFunctionCallExpression call) { + ScalarFunctionCallExpression isMissingFuncExpr = null; + if (call.getFunctionIdentifier().equals(AlgebricksBuiltinFunctions.NOT)) { + if (call.getArguments().get(0).getValue().getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) { + if (((AbstractFunctionCallExpression) call.getArguments().get(0).getValue()).getFunctionIdentifier() + .equals(AlgebricksBuiltinFunctions.IS_MISSING)) { + isMissingFuncExpr = (ScalarFunctionCallExpression) call.getArguments().get(0).getValue(); + if (isMissingFuncExpr.getArguments().get(0).getValue() + .getExpressionTag() == LogicalExpressionTag.VARIABLE) { + return isMissingFuncExpr; + } + } + } + } + return null; + } + public static ScalarFunctionCallExpression findLOJIsMissingFuncInGroupBy(GroupByOperator lojGroupbyOp) throws AlgebricksException { //find IS_MISSING function of which argument has the nullPlaceholder variable in the nested plan of groupby. @@ -1496,24 +1513,28 @@ if (inputOp.getOperatorTag() == LogicalOperatorTag.SELECT) { SelectOperator selectOp = (SelectOperator) inputOp; if (selectOp.getCondition().getValue().getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) { - if (((AbstractFunctionCallExpression) selectOp.getCondition().getValue()).getFunctionIdentifier() - .equals(AlgebricksBuiltinFunctions.NOT)) { - ScalarFunctionCallExpression notFuncExpr = - (ScalarFunctionCallExpression) selectOp.getCondition().getValue(); - if (notFuncExpr.getArguments().get(0).getValue() - .getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) { - if (((AbstractFunctionCallExpression) notFuncExpr.getArguments().get(0).getValue()) - .getFunctionIdentifier().equals(AlgebricksBuiltinFunctions.IS_MISSING)) { + AbstractFunctionCallExpression call = + (AbstractFunctionCallExpression) (selectOp).getCondition().getValue(); + if (call.getFunctionIdentifier().equals(AlgebricksBuiltinFunctions.AND)) { + for (Mutable<ILogicalExpression> mexpr : call.getArguments()) { + if (mexpr.getValue().getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) { isMissingFuncExpr = - (ScalarFunctionCallExpression) notFuncExpr.getArguments().get(0).getValue(); - if (isMissingFuncExpr.getArguments().get(0).getValue() - .getExpressionTag() == LogicalExpressionTag.VARIABLE) { + getNestedIsMissingCall((AbstractFunctionCallExpression) mexpr.getValue()); + if (isMissingFuncExpr != null) { foundSelectNonMissing = true; break; } } } } + if (foundSelectNonMissing) { + break; + } + isMissingFuncExpr = getNestedIsMissingCall(call); + if (isMissingFuncExpr != null) { + foundSelectNonMissing = true; + break; + } } } inputOp = inputOp.getInputs().size() > 0 ? (AbstractLogicalOperator) inputOp.getInputs().get(0).getValue() diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/ASTERIXDB-2402.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/ASTERIXDB-2402.sqlpp new file mode 100644 index 0000000..3f59239 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/ASTERIXDB-2402.sqlpp @@ -0,0 +1,119 @@ +/* + * 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 channels if exists; +create dataverse channels; +use channels; + +create type UserLocation as { + location: circle, + userName: string, + timeStamp: datetime +}; + + +create type UserLocationFeedType as { + location: circle, + userName: string +}; + +create type EmergencyReport as { + reportId: uuid, + Etype: string, + location: circle, + timeStamp: datetime +}; + +create type EmergencyReportFeedType as { + Etype: string, + location: circle +}; + + +create type EmergencyShelter as { + shelterName: string, + location: point +}; + +create dataset UserLocations(UserLocation) +primary key userName; +create dataset Shelters(EmergencyShelter) +primary key shelterName; +create dataset Reports(EmergencyReport) +primary key reportId autogenerated; + +create index location_time on UserLocations(timeStamp); +create index u_location on UserLocations(location) type RTREE; +create index s_location on Shelters(location) type RTREE; +create index report_time on Reports(timeStamp); + +create function EmergenciesNearMe(userName) { + ( + select report, shelters from + ( select value r from Reports r where r.timeStamp > + current_datetime() - day_time_duration("PT10S"))report, + UserLocations u + let shelters = (select s.location from Shelters s where spatial_intersect(s.location,u.location)) + where u.userName = userName + and spatial_intersect(report.location,u.location) + ) +}; + +create type result as { + resultId:uuid +}; +create type channelSub as { + channelSubId:uuid +}; +create type brokerSub as { + channelSubId:uuid, + brokerSubId:uuid +}; +create type broke as { + DataverseName: string, + BrokerName: string, + BrokerEndpoint: string +}; + +create dataset EmergenciesNearMeChannelResults(result) primary key resultId autogenerated; +create dataset EmergenciesNearMeChannelChannelSubscriptions(channelSub) primary key channelSubId; +create dataset EmergenciesNearMeChannelBrokerSubscriptions(brokerSub) primary key channelSubId,brokerSubId; +create dataset Broker(broke) primary key DataverseName,BrokerName; + + + +SET inline_with "false"; +insert into channels.EmergenciesNearMeChannelResults as a ( +with channelExecutionTime as current_datetime() +select result, channelExecutionTime, sub.channelSubId as channelSubId,current_datetime() as deliveryTime, +(select b.BrokerEndPoint, bs.brokerSubId from +channels.EmergenciesNearMeChannelBrokerSubscriptions bs, +channels.Broker b +where bs.BrokerName = b.BrokerName +and bs.DataverseName = b.DataverseName +and bs.channelSubId = sub.channelSubId +) as brokerSubIds +from channels.EmergenciesNearMeChannelChannelSubscriptions sub, +channels.EmergenciesNearMe(sub.param0) result +) returning +(select +a.channelExecutionTime, a.result, sub.BrokerEndpoint +from (select sub from a.brokerSubIds sub) sub +group by sub.BrokerEndpoint +); \ No newline at end of file diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/ASTERIXDB-2402.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/ASTERIXDB-2402.plan new file mode 100644 index 0000000..3abf291 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/ASTERIXDB-2402.plan @@ -0,0 +1,197 @@ +-- DISTRIBUTE_RESULT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- SUBPLAN |PARTITIONED| + { + -- AGGREGATE |LOCAL| + -- ASSIGN |LOCAL| + -- MICRO_PRE_CLUSTERED_GROUP_BY[$$183] |LOCAL| + { + -- AGGREGATE |LOCAL| + -- NESTED_TUPLE_SOURCE |LOCAL| + } + -- IN_MEMORY_STABLE_SORT [$$183(ASC)] |LOCAL| + -- ASSIGN |LOCAL| + -- UNNEST |LOCAL| + -- SUBPLAN |LOCAL| + { + -- AGGREGATE |LOCAL| + -- ASSIGN |LOCAL| + -- UNNEST |LOCAL| + -- NESTED_TUPLE_SOURCE |LOCAL| + } + -- NESTED_TUPLE_SOURCE |LOCAL| + } + -- STREAM_PROJECT |PARTITIONED| + -- COMMIT |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- INSERT_DELETE |PARTITIONED| + -- HASH_PARTITION_EXCHANGE [$$167] |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- PRE_CLUSTERED_GROUP_BY[$$221] |PARTITIONED| + { + -- AGGREGATE |LOCAL| + -- STREAM_SELECT |LOCAL| + -- NESTED_TUPLE_SOURCE |LOCAL| + } + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STABLE_SORT [$$221(ASC)] |PARTITIONED| + -- HASH_PARTITION_EXCHANGE [$$221] |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- HYBRID_HASH_JOIN [$$267][$$190] |PARTITIONED| + -- HASH_PARTITION_EXCHANGE [$$267] |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- UNNEST |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- PRE_CLUSTERED_GROUP_BY[$$275] |PARTITIONED| + { + -- AGGREGATE |LOCAL| + -- MICRO_PRE_CLUSTERED_GROUP_BY[$$277, $$279] |LOCAL| + { + -- AGGREGATE |LOCAL| + -- STREAM_SELECT |LOCAL| + -- NESTED_TUPLE_SOURCE |LOCAL| + } + -- STREAM_SELECT |LOCAL| + -- NESTED_TUPLE_SOURCE |LOCAL| + } + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STABLE_SORT [$$275(ASC), $$277(ASC), $$279(ASC)] |PARTITIONED| + -- HASH_PARTITION_EXCHANGE [$$275] |PARTITIONED| + -- UNION_ALL |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- STREAM_SELECT |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- BTREE_SEARCH |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- SPLIT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- RTREE_SEARCH |PARTITIONED| + -- BROADCAST_EXCHANGE |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- STREAM_SELECT |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- BTREE_SEARCH |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STABLE_SORT [$$289(ASC)] |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- RTREE_SEARCH |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- NESTED_LOOP |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- DATASOURCE_SCAN |PARTITIONED| + -- BROADCAST_EXCHANGE |PARTITIONED| + -- ASSIGN |UNPARTITIONED| + -- EMPTY_TUPLE_SOURCE |UNPARTITIONED| + -- BROADCAST_EXCHANGE |PARTITIONED| + -- STREAM_SELECT |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- BTREE_SEARCH |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STABLE_SORT [$$228(ASC)] |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- BTREE_SEARCH |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- EMPTY_TUPLE_SOURCE |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- STREAM_SELECT |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- SPLIT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- RTREE_SEARCH |PARTITIONED| + -- BROADCAST_EXCHANGE |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- STREAM_SELECT |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- BTREE_SEARCH |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STABLE_SORT [$$289(ASC)] |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- RTREE_SEARCH |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- NESTED_LOOP |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- DATASOURCE_SCAN |PARTITIONED| + -- BROADCAST_EXCHANGE |PARTITIONED| + -- ASSIGN |UNPARTITIONED| + -- EMPTY_TUPLE_SOURCE |UNPARTITIONED| + -- BROADCAST_EXCHANGE |PARTITIONED| + -- STREAM_SELECT |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- BTREE_SEARCH |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STABLE_SORT [$$228(ASC)] |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- BTREE_SEARCH |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- EMPTY_TUPLE_SOURCE |PARTITIONED| + -- HASH_PARTITION_EXCHANGE [$$190] |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- HYBRID_HASH_JOIN [$$198, $$200][$$192, $$193] |PARTITIONED| + -- HASH_PARTITION_EXCHANGE [$$198, $$200] |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- DATASOURCE_SCAN |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- EMPTY_TUPLE_SOURCE |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- DATASOURCE_SCAN |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- EMPTY_TUPLE_SOURCE |PARTITIONED| \ No newline at end of file -- To view, visit https://asterix-gerrit.ics.uci.edu/2735 To unsubscribe, visit https://asterix-gerrit.ics.uci.edu/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I9547fba5e4ba02226b5b2c2504080b091d3b8d5e Gerrit-PatchSet: 1 Gerrit-Project: asterixdb Gerrit-Branch: master Gerrit-Owner: Steven Jacobs <sjaco...@ucr.edu>