Merge branch 'gerrit/cheshire-cat'
Change-Id: Ie6a4c591cf0581775f57979c62f69801c21edb9b
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/InlineAllNtsInSubplanVisitor.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/InlineAllNtsInSubplanVisitor.java
index 1b7b7d2..4ac44b4 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/InlineAllNtsInSubplanVisitor.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/subplan/InlineAllNtsInSubplanVisitor.java
@@ -743,7 +743,7 @@
gbyOp.getNestedPlans().add(nestedPlan);
OperatorManipulationUtil.computeTypeEnvironmentBottomUp(gbyOp, context);
- return op;
+ return gbyOp;
}
private ILogicalOperator visitMultiInputOperator(ILogicalOperator op) throws AlgebricksException {
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/quantifiers/query-ASTERIXDB-2947/query-ASTERIXDB-2947.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/quantifiers/query-ASTERIXDB-2947/query-ASTERIXDB-2947.1.ddl.sqlpp
new file mode 100644
index 0000000..0ab290f
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/quantifiers/query-ASTERIXDB-2947/query-ASTERIXDB-2947.1.ddl.sqlpp
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+/*
+ * Description: This test case is to verify the fix for ASTERIXDB-2947
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
+use test;
+
+create dataset t1(id uuid not unknown) open type primary key id autogenerated;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/quantifiers/query-ASTERIXDB-2947/query-ASTERIXDB-2947.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/quantifiers/query-ASTERIXDB-2947/query-ASTERIXDB-2947.2.update.sqlpp
new file mode 100644
index 0000000..5dcf4b9
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/quantifiers/query-ASTERIXDB-2947/query-ASTERIXDB-2947.2.update.sqlpp
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use test;
+
+insert into t1
+([
+ {"x":1, "y":"A" },
+ {"x":1, "y":"B" },
+ {"x":1, "y":"C" },
+
+ {"x":2, "y":"D" },
+ {"x":2, "y":"E" },
+ {"x":2, "y":"F" },
+
+ {"x":3, "y":"G" },
+ {"x":3, "y":"H" },
+ {"x":3, "y":"I" }
+]);
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/quantifiers/query-ASTERIXDB-2947/query-ASTERIXDB-2947.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/quantifiers/query-ASTERIXDB-2947/query-ASTERIXDB-2947.3.query.sqlpp
new file mode 100644
index 0000000..712b8d1
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/quantifiers/query-ASTERIXDB-2947/query-ASTERIXDB-2947.3.query.sqlpp
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * Description: This test case is to verify the fix for ASTERIXDB-2947
+ */
+
+use test;
+
+select x, array_sort(array_agg({y})) yy
+from t1
+group by x
+having some r in array_agg({y}) satisfies r.y in ["B", "H"]
+order by x;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/quantifiers/query-ASTERIXDB-2947/query-ASTERIXDB-2947.3.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/quantifiers/query-ASTERIXDB-2947/query-ASTERIXDB-2947.3.adm
new file mode 100644
index 0000000..4f412c8
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/quantifiers/query-ASTERIXDB-2947/query-ASTERIXDB-2947.3.adm
@@ -0,0 +1,2 @@
+{ "yy": [ { "y": "A" }, { "y": "B" }, { "y": "C" } ], "x": 1 }
+{ "yy": [ { "y": "G" }, { "y": "H" }, { "y": "I" } ], "x": 3 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
index 2586447..4c821a8 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -9440,6 +9440,11 @@
<output-dir compare="Text">query-ASTERIXDB-2696</output-dir>
</compilation-unit>
</test-case>
+ <test-case FilePath="quantifiers">
+ <compilation-unit name="query-ASTERIXDB-2947">
+ <output-dir compare="Text">query-ASTERIXDB-2947</output-dir>
+ </compilation-unit>
+ </test-case>
<!--
<test-case FilePath="quantifiers">
<compilation-unit name="everysat_02">
diff --git a/asterixdb/asterix-doc/src/main/markdown/sqlpp/3_query.md b/asterixdb/asterix-doc/src/main/markdown/sqlpp/3_query.md
index fe9a3ad..04a65d1 100644
--- a/asterixdb/asterix-doc/src/main/markdown/sqlpp/3_query.md
+++ b/asterixdb/asterix-doc/src/main/markdown/sqlpp/3_query.md
@@ -742,7 +742,7 @@
WHERE get_year(date(o.order_date)) = 2020
GROUP BY get_month(date(o.order_date)) AS month
SELECT month, COUNT(*) AS order_count
- ORDER BY order_count desc
+ ORDER BY order_count DESC, month DESC
LIMIT 3;
Result:
@@ -794,6 +794,327 @@
}
]
+#### <a id="Rollup">ROLLUP</a>
+
+The `ROLLUP` subclause is an aggregation feature that extends the functionality of the `GROUP BY` clause.
+It returns extra _super-aggregate_ items in the query results, giving subtotals and a grand total for the aggregate
+functions in the query.
+To illustrate, first consider the following query.
+
+##### Example
+
+(Q3.R1) List the number of orders, grouped by customer region and city.
+
+ SELECT customer_region AS Region,
+ customer_city AS City,
+ COUNT(o.orderno) AS `Order Count`
+ FROM customers AS c LEFT OUTER JOIN orders AS o ON c.custid = o.custid
+ LET address_line = SPLIT(c.address.city, ","),
+ customer_city = TRIM(address_line[0]),
+ customer_region = TRIM(address_line[1])
+ GROUP BY customer_region, customer_city
+ ORDER BY customer_region ASC, customer_city ASC, `Order Count` DESC;
+
+Result:
+
+ [
+ {
+ "Region": "Italy",
+ "City": "Rome",
+ "Order Count": 0
+ },
+ {
+ "Region": "MA",
+ "City": "Boston",
+ "Order Count": 2
+ },
+ {
+ "Region": "MA",
+ "City": "Hanover",
+ "Order Count": 0
+ },
+ {
+ "Region": "MO",
+ "City": "St. Louis",
+ "Order Count": 7
+ }
+ ]
+
+This query uses string functions to split each customer's address into city and region.
+The query then counts the total number of orders placed by each customer, and groups the results first by customer
+region, then by customer city.
+The aggregate results (labeled `Order Count`) are only shown by city, and there are no subtotals or grand total.
+We can add these using the `ROLLUP` subclause, as in the following example.
+
+##### Example
+
+(Q3.R2) List the number of orders by customer region and city, including subtotals and a grand total.
+
+ SELECT customer_region AS Region,
+ customer_city AS City,
+ COUNT(o.orderno) AS `Order Count`
+ FROM customers AS c LEFT OUTER JOIN orders AS o ON c.custid = o.custid
+ LET address_line = SPLIT(c.address.city, ","),
+ customer_city = TRIM(address_line[0]),
+ customer_region = TRIM(address_line[1])
+ GROUP BY ROLLUP(customer_region, customer_city)
+ ORDER BY customer_region ASC, customer_city ASC, `Order Count` DESC;
+
+Result:
+
+ [
+ {
+ "Region": null,
+ "City": null,
+ "Order Count": 9
+ },
+ {
+ "Region": "Italy",
+ "City": null,
+ "Order Count": 0
+ },
+ {
+ "Region": "Italy",
+ "City": "Rome",
+ "Order Count": 0
+ },
+ {
+ "Region": "MA",
+ "City": null,
+ "Order Count": 2
+ },
+ {
+ "Region": "MA",
+ "City": "Boston",
+ "Order Count": 2
+ },
+ {
+ "Region": "MA",
+ "City": "Hanover",
+ "Order Count": 0
+ },
+ {
+ "Region": "MO",
+ "City": null,
+ "Order Count": 7
+ },
+ {
+ "Region": "MO",
+ "City": "St. Louis",
+ "Order Count": 7
+ }
+ ]
+
+With the addition of the `ROLLUP` subclause, the results now include an extra item at the start of each region,
+giving the subtotal for that region.
+There is also another extra item at the very start of the results, giving the grand total for all regions.
+
+The order of the fields specified by the `ROLLUP` subclause determines the hierarchy of the super-aggregate items.
+The customer region is specified first, followed by the customer city; so the results are aggregated by region first,
+and then by city within each region.
+
+The grand total returns `null` as a value for the city and the region, and the subtotals return `null` as the
+value for the city, which may make the results hard to understand at first glance.
+A workaround for this is given in the next example.
+
+##### Example
+
+(Q3.R3) List the number of orders by customer region and city, with meaningful subtotals and grand total.
+
+ SELECT IFNULL(customer_region, "All regions") AS Region,
+ IFNULL(customer_city, "All cities") AS City,
+ COUNT(o.orderno) AS `Order Count`
+ FROM customers AS c LEFT OUTER JOIN orders AS o ON c.custid = o.custid
+ LET address_line = SPLIT(c.address.city, ","),
+ customer_city = TRIM(address_line[0]),
+ customer_region = TRIM(address_line[1])
+ GROUP BY ROLLUP(customer_region, customer_city)
+ ORDER BY customer_region ASC, customer_city ASC, `Order Count` DESC;
+
+Result:
+
+ [
+ {
+ "Region": "All regions",
+ "City": "All cities",
+ "Order Count": 9
+ },
+ {
+ "Region": "Italy",
+ "City": "All cities",
+ "Order Count": 0
+ },
+ {
+ "Region": "Italy",
+ "City": "Rome",
+ "Order Count": 0
+ },
+ {
+ "Region": "MA",
+ "City": "All cities",
+ "Order Count": 2
+ },
+ {
+ "Region": "MA",
+ "City": "Boston",
+ "Order Count": 2
+ },
+ {
+ "Region": "MA",
+ "City": "Hanover",
+ "Order Count": 0
+ },
+ {
+ "Region": "MO",
+ "City": "All cities",
+ "Order Count": 7
+ },
+ {
+ "Region": "MO",
+ "City": "St. Louis",
+ "Order Count": 7
+ }
+ ]
+
+This query uses the `IFNULL` function to populate the region and city fields with meaningful values for the
+super-aggregate items.
+This makes the results clearer and more readable.
+
+#### <a id="Cube">CUBE</a>
+
+The `CUBE` subclause is similar to the `ROLLUP` subclause, in that it returns extra super-aggregate items in the query
+results, giving subtotals and a grand total for the aggregate functions.
+Whereas `ROLLUP` returns a grand total and a hierarchy of subtotals based on the specified fields,
+the `CUBE` subclause returns a grand total and subtotals for every possible combination of the specified fields.
+
+The following example is a modification of Q3.R3 which illustrates the `CUBE` subclause.
+
+##### Example
+
+(Q3.C) List the number of orders by customer region and order date, with all possible subtotals and a grand total.
+
+ SELECT IFNULL(customer_region, "All regions") AS Region,
+ IFNULL(order_month, "All months") AS Month,
+ COUNT(o.orderno) AS `Order Count`
+ FROM customers AS c INNER JOIN orders AS o ON c.custid = o.custid
+ LET address_line = SPLIT(c.address.city, ","),
+ customer_region = TRIM(address_line[1]),
+ order_month = get_month(date(o.order_date))
+ GROUP BY CUBE(customer_region, order_month)
+ ORDER BY customer_region ASC, order_month ASC;
+
+Result:
+
+ [
+ {
+ "Region": "All regions",
+ "Order Count": 9,
+ "Month": "All months"
+ },
+ {
+ "Region": "All regions",
+ "Order Count": 1,
+ "Month": 4
+ },
+ {
+ "Region": "All regions",
+ "Order Count": 1,
+ "Month": 5
+ },
+ {
+ "Region": "All regions",
+ "Order Count": 1,
+ "Month": 6
+ },
+ {
+ "Region": "All regions",
+ "Order Count": 1,
+ "Month": 7
+ },
+ {
+ "Region": "All regions",
+ "Order Count": 1,
+ "Month": 8
+ },
+ {
+ "Region": "All regions",
+ "Order Count": 2,
+ "Month": 9
+ },
+ {
+ "Region": "All regions",
+ "Order Count": 2,
+ "Month": 10
+ },
+ {
+ "Region": "MA",
+ "Order Count": 2,
+ "Month": "All months"
+ },
+ {
+ "Region": "MA",
+ "Order Count": 1,
+ "Month": 7
+ },
+ {
+ "Region": "MA",
+ "Order Count": 1,
+ "Month": 8
+ },
+ {
+ "Region": "MO",
+ "Order Count": 7,
+ "Month": "All months"
+ },
+ {
+ "Region": "MO",
+ "Order Count": 1,
+ "Month": 4
+ },
+ {
+ "Region": "MO",
+ "Order Count": 1,
+ "Month": 5
+ },
+ {
+ "Region": "MO",
+ "Order Count": 1,
+ "Month": 6
+ },
+ {
+ "Region": "MO",
+ "Order Count": 2,
+ "Month": 9
+ },
+ {
+ "Region": "MO",
+ "Order Count": 2,
+ "Month": 10
+ }
+ ]
+
+To simplify the results, this query uses an inner join, so that customers who have not placed an order are not included
+in the totals.
+The query uses string functions to extract the region from each customer's address,
+and a temporal function to extract the year from the order date.
+
+The query uses the `CUBE` subclause with customer region and order month.
+This means that there are four possible aggregates to calculate:
+
+* All regions, all months
+* All regions, each month
+* Each region, all months
+* Each region, each month
+
+The results start with the grand total, showing the total number of orders across all regions for all months.
+This is followed by date subtotals, showing the number of orders across all regions for each month.
+Following that are the regional subtotals, showing the total number of orders for all months in each region;
+and the result items, giving the number of orders for each month in each region.
+
+The query also uses the `IFNULL` function to populate the region and date fields with meaningful values for the
+super-aggregate items.
+This makes the results clearer and more readable.
+
### <a id="Having_clauses">HAVING Clause</a>
##### HavingClause
diff --git a/asterixdb/asterix-server/pom.xml b/asterixdb/asterix-server/pom.xml
index 98e3e59..afaad49 100644
--- a/asterixdb/asterix-server/pom.xml
+++ b/asterixdb/asterix-server/pom.xml
@@ -343,6 +343,7 @@
<aliasUrl>http://www.apache.org/licenses/LICENSE-2.0</aliasUrl>
<aliasUrl>https://www.apache.org/licenses/LICENSE-2.0.txt</aliasUrl>
<aliasUrl>http://www.apache.org/licenses/LICENSE-2.0.html</aliasUrl>
+ <aliasUrl>https://www.apache.org/licenses/LICENSE-2.0.html</aliasUrl>
<aliasUrl>https://aws.amazon.com/apache2.0</aliasUrl>
<aliasUrl>https://raw.githubusercontent.com/jorabin/KeePassJava2/KeePassJava2-2.1.4/LICENSE</aliasUrl>
<aliasUrl>https://raw.githubusercontent.com/reactor/reactor-netty/v1.0.7/LICENSE</aliasUrl>
diff --git a/asterixdb/src/main/appended-resources/supplemental-models.xml b/asterixdb/src/main/appended-resources/supplemental-models.xml
index 9624ae5..5ed7c32 100644
--- a/asterixdb/src/main/appended-resources/supplemental-models.xml
+++ b/asterixdb/src/main/appended-resources/supplemental-models.xml
@@ -290,9 +290,10 @@
<properties>
<!-- snappy-java is ALv2, and does not contain any embedded LICENSE or NOTICE file -->
<!-- license override not needed, ALv2 is specified in its pom.xml -->
- <!-- see https://github.com/xerial/snappy-java/blob/1.1.7.1/LICENSE -->
- <license.ignoreMissingEmbeddedLicense>1.1.7.1</license.ignoreMissingEmbeddedLicense>
- <license.ignoreMissingEmbeddedNotice>1.1.7.1</license.ignoreMissingEmbeddedNotice>
+ <!-- see https://github.com/xerial/snappy-java/blob/1.1.8.4/LICENSE -->
+ <license.ignoreMissingEmbeddedLicense>1.1.7.1,1.1.8.4</license.ignoreMissingEmbeddedLicense>
+ <license.ignoreMissingEmbeddedNotice>1.1.7.1,1.1.8.4</license.ignoreMissingEmbeddedNotice>
+ <license.ignoreLicenseOverride>1.1.7.1</license.ignoreLicenseOverride>
</properties>
</project>
</supplement>
diff --git a/hyracks-fullstack/hyracks/hyracks-storage-common/pom.xml b/hyracks-fullstack/hyracks/hyracks-storage-common/pom.xml
index 2e0ac6c..99056a4 100644
--- a/hyracks-fullstack/hyracks/hyracks-storage-common/pom.xml
+++ b/hyracks-fullstack/hyracks/hyracks-storage-common/pom.xml
@@ -69,7 +69,6 @@
<dependency>
<groupId>org.xerial.snappy</groupId>
<artifactId>snappy-java</artifactId>
- <version>1.1.7.1</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
diff --git a/hyracks-fullstack/pom.xml b/hyracks-fullstack/pom.xml
index 051d4f5..15c1c15 100644
--- a/hyracks-fullstack/pom.xml
+++ b/hyracks-fullstack/pom.xml
@@ -73,6 +73,7 @@
<hadoop.version>2.8.5</hadoop.version>
<jacoco.version>0.7.6.201602180812</jacoco.version>
<log4j.version>2.14.1</log4j.version>
+ <snappy.version>1.1.8.4</snappy.version>
<implementation.title>Apache Hyracks and Algebricks - ${project.name}</implementation.title>
<implementation.url>https://asterixdb.apache.org/</implementation.url>
@@ -331,6 +332,11 @@
<artifactId>powermock-core</artifactId>
<version>2.0.9</version>
</dependency>
+ <dependency>
+ <groupId>org.xerial.snappy</groupId>
+ <artifactId>snappy-java</artifactId>
+ <version>${snappy.version}</version>
+ </dependency>
</dependencies>
</dependencyManagement>
<build>