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 <[email protected]>
