You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@asterixdb.apache.org by dl...@apache.org on 2019/08/07 22:11:44 UTC
[asterixdb] branch master updated: [NO ISSUE][COMP] Improve
warnings for SQL++ hints
This is an automated email from the ASF dual-hosted git repository.
dlych pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/asterixdb.git
The following commit(s) were added to refs/heads/master by this push:
new e77cdac [NO ISSUE][COMP] Improve warnings for SQL++ hints
e77cdac is described below
commit e77cdacb5939b930db20620012dc91ed6392a1e1
Author: Dmitry Lychagin <dm...@couchbase.com>
AuthorDate: Mon Aug 5 11:37:47 2019 -0700
[NO ISSUE][COMP] Improve warnings for SQL++ hints
- user model changes: no
- storage format changes: no
- interface changes: no
Details:
- Issue warnings for all hints that were not processed
by the SQL++ parser. A hint is not processed because
it is either unknown or unexpected at given location
Change-Id: Iec46335a8db4360e5431b145cd9e98c7075c7fda
Reviewed-on: https://asterix-gerrit.ics.uci.edu/3517
Contrib: Jenkins <je...@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <je...@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <je...@fulliautomatix.ics.uci.edu>
Reviewed-by: Dmitry Lychagin <dm...@couchbase.com>
Reviewed-by: Ali Alsuliman <al...@gmail.com>
---
.../inapplicable-hint-warning.1.query.sqlpp | 6 +-
...lpp => inapplicable-hint-warning.2.query.sqlpp} | 9 +-
...lpp => inapplicable-hint-warning.3.query.sqlpp} | 17 +-
...lpp => inapplicable-hint-warning.4.query.sqlpp} | 17 +-
...lpp => inapplicable-hint-warning.5.query.sqlpp} | 17 +-
...lpp => inapplicable-hint-warning.6.query.sqlpp} | 17 +-
.../unknown-hint-warning.5.query.sqlpp} | 16 +-
.../inapplicable-hint-warning.2.adm | 2 +
.../inapplicable-hint-warning.3.adm | 1 +
.../inapplicable-hint-warning.4.adm | 1 +
.../inapplicable-hint-warning.5.adm | 1 +
.../inapplicable-hint-warning.6.adm | 1 +
.../unknown-hint-warning.5.adm | 1 +
.../test/resources/runtimets/testsuite_sqlpp.xml | 14 +-
.../asterix/common/exceptions/ErrorCode.java | 2 +-
.../src/main/resources/asx_errormsg/en.properties | 2 +-
.../asterix/lang/sqlpp/parser/SqlppHint.java | 93 +++++
.../asterix/lang/sqlpp/parser/SqlppToken.java | 34 +-
.../asterix-lang-sqlpp/src/main/javacc/SQLPP.jj | 374 +++++++++++----------
.../java/org/apache/hyracks/util/StringUtil.java | 14 +
20 files changed, 369 insertions(+), 270 deletions(-)
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.query.sqlpp
index 0c0e667..2b70df1 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.query.sqlpp
@@ -18,9 +18,9 @@
*/
/*
- * Description : Warning when a GROUP BY hint is recognized,
- * : but cannot be applied for given aggregate function
- * Expected : SUCCESS (with ASX1107 warning)
+ * Description : Warning when a GROUP BY hint is the expected one,
+ * : but cannot be applied for a given aggregate function
+ * Expected : SUCCESS (with HYR10006 warning)
*/
with ds as (
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.2.query.sqlpp
similarity index 82%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.2.query.sqlpp
index 0c0e667..d0d6c1a 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.2.query.sqlpp
@@ -18,8 +18,8 @@
*/
/*
- * Description : Warning when a GROUP BY hint is recognized,
- * : but cannot be applied for given aggregate function
+ * Description : Warning when a hint at GROUP BY is recognized,
+ * : but not applicable for GROUP BY
* Expected : SUCCESS (with ASX1107 warning)
*/
@@ -29,7 +29,6 @@ with ds as (
)
from ds
-where y < 3
-/*+ hash */ group by x
-select x, array_agg(y) as y
+/*+ indexnl */ group by x
+select x, sum(y) as y
order by x
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.3.query.sqlpp
similarity index 75%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.3.query.sqlpp
index 0c0e667..daab311 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.3.query.sqlpp
@@ -18,18 +18,11 @@
*/
/*
- * Description : Warning when a GROUP BY hint is recognized,
- * : but cannot be applied for given aggregate function
+ * Description : Warning when a hint at relational expression is recognized
+ * : but not applicable for relational expression
* Expected : SUCCESS (with ASX1107 warning)
*/
-with ds as (
- from range(1, 4) r
- select r % 2 as x, r as y
-)
-
-from ds
-where y < 3
-/*+ hash */ group by x
-select x, array_agg(y) as y
-order by x
\ No newline at end of file
+from range(1, 4) r
+where r /*+ hash */ < 2
+select value r
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.4.query.sqlpp
similarity index 75%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.4.query.sqlpp
index 0c0e667..cc8c8df 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.4.query.sqlpp
@@ -18,18 +18,11 @@
*/
/*
- * Description : Warning when a GROUP BY hint is recognized,
- * : but cannot be applied for given aggregate function
+ * Description : Warning when a hint at BETWEEN is recognized
+ * : but not applicable for BETWEEN
* Expected : SUCCESS (with ASX1107 warning)
*/
-with ds as (
- from range(1, 4) r
- select r % 2 as x, r as y
-)
-
-from ds
-where y < 3
-/*+ hash */ group by x
-select x, array_agg(y) as y
-order by x
\ No newline at end of file
+from range(1, 4) r
+where r /*+ auto */ between 0 and 1
+select value r
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.5.query.sqlpp
similarity index 75%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.5.query.sqlpp
index 0c0e667..a19aeec 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.5.query.sqlpp
@@ -18,18 +18,11 @@
*/
/*
- * Description : Warning when a GROUP BY hint is recognized,
- * : but cannot be applied for given aggregate function
+ * Description : Warning when a hint at function call is recognized
+ * : but not applicable for function call
* Expected : SUCCESS (with ASX1107 warning)
*/
-with ds as (
- from range(1, 4) r
- select r % 2 as x, r as y
-)
-
-from ds
-where y < 3
-/*+ hash */ group by x
-select x, array_agg(y) as y
-order by x
\ No newline at end of file
+from range(1, 4) r
+where /*+ hash */ tostring(r) < "2"
+select value r
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.6.query.sqlpp
similarity index 75%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.6.query.sqlpp
index 0c0e667..b669569 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.6.query.sqlpp
@@ -18,18 +18,11 @@
*/
/*
- * Description : Warning when a GROUP BY hint is recognized,
- * : but cannot be applied for given aggregate function
+ * Description : Warning when a hint is recognized
+ * : but no hints applicable at this location
* Expected : SUCCESS (with ASX1107 warning)
*/
-with ds as (
- from range(1, 4) r
- select r % 2 as x, r as y
-)
-
-from ds
-where y < 3
-/*+ hash */ group by x
-select x, array_agg(y) as y
-order by x
\ No newline at end of file
+from range(1, 4) r
+where r < 2
+select /*+ hash */ value r
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/unknown-hint-warning/unknown-hint-warning.5.query.sqlpp
similarity index 75%
copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.query.sqlpp
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/unknown-hint-warning/unknown-hint-warning.5.query.sqlpp
index 0c0e667..517e39b 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.1.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/unknown-hint-warning/unknown-hint-warning.5.query.sqlpp
@@ -18,18 +18,10 @@
*/
/*
- * Description : Warning when a GROUP BY hint is recognized,
- * : but cannot be applied for given aggregate function
+ * Description : Warning when a hint is not recognized elsewhere
* Expected : SUCCESS (with ASX1107 warning)
*/
-with ds as (
- from range(1, 4) r
- select r % 2 as x, r as y
-)
-
-from ds
-where y < 3
-/*+ hash */ group by x
-select x, array_agg(y) as y
-order by x
\ No newline at end of file
+from range(1, 4) r
+where r < 2
+select /*+ unknown_hint_elsewhere */ value r
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/inapplicable-hint-warning/inapplicable-hint-warning.2.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/inapplicable-hint-warning/inapplicable-hint-warning.2.adm
new file mode 100644
index 0000000..60bff22
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/inapplicable-hint-warning/inapplicable-hint-warning.2.adm
@@ -0,0 +1,2 @@
+{ "x": 0, "y": 6 }
+{ "x": 1, "y": 4 }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/inapplicable-hint-warning/inapplicable-hint-warning.3.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/inapplicable-hint-warning/inapplicable-hint-warning.3.adm
new file mode 100644
index 0000000..56a6051
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/inapplicable-hint-warning/inapplicable-hint-warning.3.adm
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/inapplicable-hint-warning/inapplicable-hint-warning.4.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/inapplicable-hint-warning/inapplicable-hint-warning.4.adm
new file mode 100644
index 0000000..56a6051
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/inapplicable-hint-warning/inapplicable-hint-warning.4.adm
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/inapplicable-hint-warning/inapplicable-hint-warning.5.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/inapplicable-hint-warning/inapplicable-hint-warning.5.adm
new file mode 100644
index 0000000..56a6051
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/inapplicable-hint-warning/inapplicable-hint-warning.5.adm
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/inapplicable-hint-warning/inapplicable-hint-warning.6.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/inapplicable-hint-warning/inapplicable-hint-warning.6.adm
new file mode 100644
index 0000000..56a6051
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/inapplicable-hint-warning/inapplicable-hint-warning.6.adm
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/unknown-hint-warning/unknown-hint-warning.5.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/unknown-hint-warning/unknown-hint-warning.5.adm
new file mode 100644
index 0000000..56a6051
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/warnings/unknown-hint-warning/unknown-hint-warning.5.adm
@@ -0,0 +1 @@
+1
\ 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 c2c3f4c..0724f45 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -12418,6 +12418,11 @@
<compilation-unit name="inapplicable-hint-warning">
<output-dir compare="Text">inapplicable-hint-warning</output-dir>
<expected-warn>HYR10006: Could not apply Group By hint: hash</expected-warn>
+ <expected-warn>ASX1107: Unexpected hint: indexnl. "hash" expected at this location</expected-warn>
+ <expected-warn>ASX1107: Unexpected hint: hash. "indexnl", "skip-index", "bcast" expected at this location</expected-warn>
+ <expected-warn>ASX1107: Unexpected hint: auto. "indexnl", "skip-index" expected at this location</expected-warn>
+ <expected-warn>ASX1107: Unexpected hint: hash. "indexnl", "skip-index" expected at this location</expected-warn>
+ <expected-warn>ASX1107: Unexpected hint: hash. None expected at this location</expected-warn>
</compilation-unit>
</test-case>
<test-case FilePath="warnings" check-warnings="true">
@@ -12436,10 +12441,11 @@
<test-case FilePath="warnings" check-warnings="true">
<compilation-unit name="unknown-hint-warning">
<output-dir compare="Text">unknown-hint-warning</output-dir>
- <expected-warn>ASX1107: Unknown hint: unknown_hint_groupby. Supported hints are: hash</expected-warn>
- <expected-warn>ASX1107: Unknown hint: unknown_hint_relexpr. Supported hints are: indexnl, skip-index, bcast</expected-warn>
- <expected-warn>ASX1107: Unknown hint: unknown_hint_between. Supported hints are: indexnl, skip-index</expected-warn>
- <expected-warn>ASX1107: Unknown hint: unknown_hint_funcall. Supported hints are: indexnl, skip-index</expected-warn>
+ <expected-warn>ASX1107: Unexpected hint: unknown_hint_groupby. "hash" expected at this location</expected-warn>
+ <expected-warn>ASX1107: Unexpected hint: unknown_hint_relexpr. "indexnl", "skip-index", "bcast" expected at this location</expected-warn>
+ <expected-warn>ASX1107: Unexpected hint: unknown_hint_between. "indexnl", "skip-index" expected at this location</expected-warn>
+ <expected-warn>ASX1107: Unexpected hint: unknown_hint_funcall. "indexnl", "skip-index" expected at this location</expected-warn>
+ <expected-warn>ASX1107: Unexpected hint: unknown_hint_elsewhere. None expected at this location</expected-warn>
</compilation-unit>
</test-case>
</test-group>
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
index 188ad94..ca8ee38 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
@@ -188,7 +188,7 @@ public class ErrorCode {
public static final int INVALID_FUNCTION_MODIFIER = 1104;
public static final int OPERATION_NOT_SUPPORTED_ON_PRIMARY_INDEX = 1105;
public static final int EXPECTED_CONSTANT_VALUE = 1106;
- public static final int UNKNOWN_HINT = 1107;
+ public static final int UNEXPECTED_HINT = 1107;
// Feed errors
public static final int DATAFLOW_ILLEGAL_STATE = 3001;
diff --git a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
index 0848f66..362e506 100644
--- a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
+++ b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
@@ -183,7 +183,7 @@
1104 = Invalid modifier %1$s for function %2$s
1105 = Operation not supported on primary index %1$s
1106 = Expected constant value
-1107 = Unknown hint: %1$s. Supported hints are: %2$s
+1107 = Unexpected hint: %1$s. %2$s expected at this location
# Feed Errors
3001 = Illegal state.
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/parser/SqlppHint.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/parser/SqlppHint.java
new file mode 100644
index 0000000..4770581
--- /dev/null
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/parser/SqlppHint.java
@@ -0,0 +1,93 @@
+/*
+ * 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.parser;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+public enum SqlppHint {
+
+ // optimizer hints
+ AUTO_HINT("auto"),
+ BROADCAST_JOIN_HINT("bcast"),
+ COMPOSE_VAL_FILES_HINT("compose-val-files"),
+ DATE_BETWEEN_YEARS_HINT("date-between-years"),
+ DATETIME_ADD_RAND_HOURS_HINT("datetime-add-rand-hours"),
+ DATETIME_BETWEEN_YEARS_HINT("datetime-between-years"),
+ HASH_GROUP_BY_HINT("hash"),
+ INDEXED_NESTED_LOOP_JOIN_HINT("indexnl"),
+ INMEMORY_HINT("inmem"),
+ INSERT_RAND_INT_HINT("insert-rand-int"),
+ INTERVAL_HINT("interval"),
+ LIST_HINT("list"),
+ LIST_VAL_FILE_HINT("list-val-file"),
+ RANGE_HINT("range"),
+ SKIP_SECONDARY_INDEX_SEARCH_HINT("skip-index"),
+ VAL_FILE_HINT("val-files"),
+ VAL_FILE_SAME_INDEX_HINT("val-file-same-idx"),
+ GEN_FIELDS_HINT("gen-fields"),
+
+ // data generator hints
+ DGEN_HINT("dgen");
+
+ private static final Map<String, SqlppHint> ID_MAP = createIdentifierMap(values());
+
+ private final String id;
+
+ SqlppHint(String id) {
+ Objects.requireNonNull(id);
+ this.id = id;
+ }
+
+ public String getIdentifier() {
+ return id;
+ }
+
+ @Override
+ public String toString() {
+ return getIdentifier();
+ }
+
+ public static SqlppHint findByIdentifier(String id) {
+ return ID_MAP.get(id);
+ }
+
+ private static Map<String, SqlppHint> createIdentifierMap(SqlppHint[] values) {
+ Map<String, SqlppHint> map = new HashMap<>();
+ for (SqlppHint hint : values) {
+ map.put(hint.getIdentifier(), hint);
+ }
+ return map;
+ }
+
+ public static int findParamStart(String str) {
+ for (int i = 0, ln = str.length(); i < ln; i++) {
+ if (!isIdentifierChar(str.charAt(i))) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public static boolean isIdentifierChar(char c) {
+ return Character.isJavaIdentifierStart(c) || c == '-';
+ }
+}
diff --git a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/StringUtil.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/parser/SqlppToken.java
similarity index 52%
copy from hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/StringUtil.java
copy to asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/parser/SqlppToken.java
index 11be0ba..13dca02 100644
--- a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/StringUtil.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/parser/SqlppToken.java
@@ -16,24 +16,30 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.hyracks.util;
-import java.util.Collections;
-import java.util.Map;
-import java.util.regex.Pattern;
+package org.apache.asterix.lang.sqlpp.parser;
-import org.apache.commons.collections4.map.LRUMap;
-import org.apache.commons.text.WordUtils;
+import java.io.Serializable;
-public class StringUtil {
- private static final Map<String, String> CAMEL_CACHE = Collections.synchronizedMap(new LRUMap<>(1024));
- private static final Pattern SEPARATORS_PATTERN = Pattern.compile("[_\\-\\s]");
+import org.apache.hyracks.api.exceptions.SourceLocation;
- private StringUtil() {
- }
+public abstract class SqlppToken implements Serializable {
+
+ public SourceLocation sourceLocation;
+
+ public SqlppHint hint;
+ public String hintParams;
- public static String toCamelCase(String input) {
- return CAMEL_CACHE.computeIfAbsent(input, s -> SEPARATORS_PATTERN
- .matcher(WordUtils.capitalize("z" + s.toLowerCase(), '_', '-', ' ').substring(1)).replaceAll(""));
+ public boolean parseHint(String text) {
+ int paramStart = SqlppHint.findParamStart(text);
+ String id = paramStart >= 0 ? text.substring(0, paramStart) : text;
+ hint = SqlppHint.findByIdentifier(id);
+ if (hint != null) {
+ hintParams = paramStart >= 0 ? text.substring(paramStart).trim() : null;
+ return true;
+ } else {
+ hintParams = text;
+ return false;
+ }
}
}
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
index ead92cf..0909fe0 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
+++ b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
@@ -17,13 +17,11 @@
// under the License.
//
options {
-
-
- STATIC = false;
-
+ COMMON_TOKEN_ACTION = true;
+ STATIC = false;
+ TOKEN_EXTENDS = "org.apache.asterix.lang.sqlpp.parser.SqlppToken";
}
-
PARSER_BEGIN(SQLPPParser)
package org.apache.asterix.lang.sqlpp.parser;
@@ -176,12 +174,14 @@ import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
import org.apache.asterix.lang.sqlpp.expression.WindowExpression;
import org.apache.asterix.lang.sqlpp.optype.JoinType;
import org.apache.asterix.lang.sqlpp.optype.SetOpType;
+import org.apache.asterix.lang.sqlpp.parser.SqlppHint;
import org.apache.asterix.lang.sqlpp.struct.SetOperationInput;
import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
import org.apache.asterix.lang.sqlpp.util.ExpressionToVariableUtil;
import org.apache.asterix.lang.sqlpp.util.FunctionMapUtil;
import org.apache.asterix.lang.sqlpp.util.SqlppVariableUtil;
import org.apache.asterix.om.functions.BuiltinFunctions;
+import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.hyracks.algebricks.common.utils.Pair;
import org.apache.hyracks.algebricks.common.utils.Triple;
@@ -192,6 +192,7 @@ import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
import org.apache.hyracks.api.exceptions.SourceLocation;
import org.apache.hyracks.api.exceptions.Warning;
import org.apache.hyracks.util.LogRedactionUtil;
+import org.apache.hyracks.util.StringUtil;
class SQLPPParser extends ScopeChecker implements IParser {
@@ -215,29 +216,6 @@ class SQLPPParser extends ScopeChecker implements IParser {
private static final String TIES = "TIES";
private static final String UNBOUNDED = "UNBOUNDED";
- // optimizer hints
- private static final String AUTO_HINT = "auto";
- private static final String BROADCAST_JOIN_HINT = "bcast";
- private static final String COMPOSE_VAL_FILES_HINT = "compose-val-files";
- private static final String DATE_BETWEEN_YEARS_HINT = "date-between-years";
- private static final String DATETIME_ADD_RAND_HOURS_HINT = "datetime-add-rand-hours";
- private static final String DATETIME_BETWEEN_YEARS_HINT = "datetime-between-years";
- private static final String HASH_GROUP_BY_HINT = "hash";
- private static final String INDEXED_NESTED_LOOP_JOIN_HINT = "indexnl";
- private static final String INMEMORY_HINT = "inmem";
- private static final String INSERT_RAND_INT_HINT = "insert-rand-int";
- private static final String INTERVAL_HINT = "interval";
- private static final String LIST_HINT = "list";
- private static final String LIST_VAL_FILE_HINT = "list-val-file";
- private static final String RANGE_HINT = "range";
- private static final String SKIP_SECONDARY_INDEX_SEARCH_HINT = "skip-index";
- private static final String VAL_FILE_HINT = "val-files";
- private static final String VAL_FILE_SAME_INDEX_HINT = "val-file-same-idx";
- private static final String GEN_FIELDS_HINT = "gen-fields";
-
- // data generator hints
- private static final String DGEN_HINT = "dgen";
-
// error configuration
protected static final boolean REPORT_EXPECTED_TOKENS = false;
@@ -245,6 +223,8 @@ class SQLPPParser extends ScopeChecker implements IParser {
private final WarningCollector warningCollector = new WarningCollector();
+ private final Map<SourceLocation, String> hintCollector = new HashMap<SourceLocation, String>();
+
private static class IndexParams {
public IndexType type;
public int gramLength;
@@ -259,73 +239,64 @@ class SQLPPParser extends ScopeChecker implements IParser {
public String dataverse;
public String library;
public String function;
- public String hint;
+ public SqlppHint hint;
public SourceLocation sourceLoc;
- public SourceLocation hintSourceLoc;
}
- private String getHint(Token t) {
- if (t.specialToken == null) {
- return null;
- }
- String s = t.specialToken.image;
- int n = s.length();
- if (n < 2) {
- return null;
- }
- return s.substring(1).trim();
- }
-
- private Token getHintToken(Token t) {
- return t.specialToken;
- }
-
- private IRecordFieldDataGen parseFieldDataGen(String hint, Token hintToken) throws ParseException {
- IRecordFieldDataGen rfdg = null;
- String splits[] = hint.split(" +");
- if (splits[0].equals(VAL_FILE_HINT)) {
- File[] valFiles = new File[splits.length - 1];
- for (int k=1; k<splits.length; k++) {
- valFiles[k-1] = new File(splits[k]);
- }
- rfdg = new FieldValFileDataGen(valFiles);
- } else if (splits[0].equals(VAL_FILE_SAME_INDEX_HINT)) {
- rfdg = new FieldValFileSameIndexDataGen(new File(splits[1]), splits[2]);
- } else if (splits[0].equals(LIST_VAL_FILE_HINT)) {
- rfdg = new ListValFileDataGen(new File(splits[1]), Integer.parseInt(splits[2]), Integer.parseInt(splits[3]));
- } else if (splits[0].equals(LIST_HINT)) {
- rfdg = new ListDataGen(Integer.parseInt(splits[1]), Integer.parseInt(splits[2]));
- } else if (splits[0].equals(INTERVAL_HINT)) {
- FieldIntervalDataGen.ValueType vt;
- if (splits[1].equals("int")) {
- vt = FieldIntervalDataGen.ValueType.INT;
- } else if (splits[1].equals("long")) {
- vt = FieldIntervalDataGen.ValueType.LONG;
- } else if (splits[1].equals("float")) {
- vt = FieldIntervalDataGen.ValueType.FLOAT;
- } else if (splits[1].equals("double")) {
- vt = FieldIntervalDataGen.ValueType.DOUBLE;
- } else {
- throw new SqlppParseException(getSourceLocation(hintToken), "Unknown type for interval data gen: " + splits[1]);
- }
- rfdg = new FieldIntervalDataGen(vt, splits[2], splits[3]);
- } else if (splits[0].equals(INSERT_RAND_INT_HINT)) {
- rfdg = new InsertRandIntDataGen(splits[1], splits[2]);
- } else if (splits[0].equals(DATE_BETWEEN_YEARS_HINT)) {
- rfdg = new DateBetweenYearsDataGen(Integer.parseInt(splits[1]), Integer.parseInt(splits[2]));
- } else if (splits[0].equals(DATETIME_BETWEEN_YEARS_HINT)) {
- rfdg = new DatetimeBetweenYearsDataGen(Integer.parseInt(splits[1]), Integer.parseInt(splits[2]));
- } else if (splits[0].equals(DATETIME_ADD_RAND_HOURS_HINT)) {
- rfdg = new DatetimeAddRandHoursDataGen(Integer.parseInt(splits[1]), Integer.parseInt(splits[2]), splits[3]);
- } else if (splits[0].equals(AUTO_HINT)) {
- rfdg = new AutoDataGen(splits[1]);
+ private IRecordFieldDataGen parseFieldDataGen(Token hintToken) throws ParseException {
+ String[] splits = hintToken.hintParams != null ? hintToken.hintParams.split("\\s+") : null;
+ switch (hintToken.hint) {
+ case VAL_FILE_HINT:
+ File[] valFiles = new File[splits.length];
+ for (int k=0; k<splits.length; k++) {
+ valFiles[k] = new File(splits[k]);
+ }
+ return new FieldValFileDataGen(valFiles);
+ case VAL_FILE_SAME_INDEX_HINT:
+ return new FieldValFileSameIndexDataGen(new File(splits[0]), splits[1]);
+ case LIST_VAL_FILE_HINT:
+ return new ListValFileDataGen(new File(splits[0]), Integer.parseInt(splits[1]), Integer.parseInt(splits[2]));
+ case LIST_HINT:
+ return new ListDataGen(Integer.parseInt(splits[0]), Integer.parseInt(splits[1]));
+ case INTERVAL_HINT:
+ FieldIntervalDataGen.ValueType vt;
+ switch (splits[0]) {
+ case "int":
+ vt = FieldIntervalDataGen.ValueType.INT;
+ break;
+ case "long":
+ vt = FieldIntervalDataGen.ValueType.LONG;
+ break;
+ case "float":
+ vt = FieldIntervalDataGen.ValueType.FLOAT;
+ break;
+ case "double":
+ vt = FieldIntervalDataGen.ValueType.DOUBLE;
+ break;
+ default:
+ throw new SqlppParseException(getSourceLocation(hintToken),
+ "Unknown type for interval data gen: " + splits[0]);
+ }
+ return new FieldIntervalDataGen(vt, splits[1], splits[2]);
+ case INSERT_RAND_INT_HINT:
+ return new InsertRandIntDataGen(splits[0], splits[1]);
+ case DATE_BETWEEN_YEARS_HINT:
+ return new DateBetweenYearsDataGen(Integer.parseInt(splits[0]), Integer.parseInt(splits[1]));
+ case DATETIME_BETWEEN_YEARS_HINT:
+ return new DatetimeBetweenYearsDataGen(Integer.parseInt(splits[0]), Integer.parseInt(splits[1]));
+ case DATETIME_ADD_RAND_HOURS_HINT:
+ return new DatetimeAddRandHoursDataGen(Integer.parseInt(splits[0]), Integer.parseInt(splits[1]), splits[2]);
+ case AUTO_HINT:
+ return new AutoDataGen(splits[0]);
+ default:
+ return null;
}
- return rfdg;
}
public SQLPPParser(String s) {
this(new StringReader(s));
super.setInput(s);
+ token_source.hintCollector = hintCollector;
}
public static void main(String args[]) throws ParseException, TokenMgrError, IOException, FileNotFoundException, CompilationException {
@@ -360,6 +331,7 @@ class SQLPPParser extends ScopeChecker implements IParser {
private <T> T parseImpl(ParseFunction<T> parseFunction) throws CompilationException {
warningCollector.clear();
+ hintCollector.clear();
try {
return parseFunction.parse();
} catch (Error e) {
@@ -371,6 +343,8 @@ class SQLPPParser extends ScopeChecker implements IParser {
throw new CompilationException(ErrorCode.PARSE_ERROR, e.getSourceLocation(), LogRedactionUtil.userData(getMessage(e)));
} catch (ParseException e) {
throw new CompilationException(ErrorCode.PARSE_ERROR, LogRedactionUtil.userData(getMessage(e)));
+ } finally {
+ reportUnclaimedHints();
}
}
@@ -426,7 +400,10 @@ class SQLPPParser extends ScopeChecker implements IParser {
}
protected static SourceLocation getSourceLocation(Token token) {
- return token != null ? new SourceLocation(token.beginLine, token.beginColumn) : null;
+ return
+ token == null ? null :
+ token.sourceLocation != null ? token.sourceLocation :
+ new SourceLocation(token.beginLine, token.beginColumn);
}
protected static <T extends AbstractLangExpression> T addSourceLocation(T expr, Token token) {
@@ -461,15 +438,41 @@ class SQLPPParser extends ScopeChecker implements IParser {
return laIdentifier(1, image);
}
- private void warnUnknownHint(String actualHint, SourceLocation sourceLoc, String... expectedHints) {
- warningCollector.warn(WarningUtil.forAsterix(sourceLoc, ErrorCode.UNKNOWN_HINT, actualHint,
- StringUtils.join(expectedHints, ", ")));
+ private Token fetchHint(Token token, SqlppHint... expectedHints) {
+ Token hintToken = token.specialToken;
+ if (hintToken == null) {
+ return null;
+ }
+ SourceLocation sourceLoc = getSourceLocation(hintToken);
+ hintCollector.remove(sourceLoc);
+ if (hintToken.hint == null) {
+ warnUnexpectedHint(hintToken.hintParams, sourceLoc, expectedHints);
+ return null;
+ } else if (!ArrayUtils.contains(expectedHints, hintToken.hint)) {
+ warnUnexpectedHint(hintToken.hint.getIdentifier(), sourceLoc, expectedHints);
+ return null;
+ } else {
+ return hintToken;
+ }
+ }
+
+ private void reportUnclaimedHints() {
+ for (Map.Entry<SourceLocation, String> me : hintCollector.entrySet()) {
+ warnUnexpectedHint(me.getValue(), me.getKey(), "None");
+ }
+ }
+
+ private void warnUnexpectedHint(String actualHint, SourceLocation sourceLoc, SqlppHint... expectedHints) {
+ warnUnexpectedHint(actualHint, sourceLoc, StringUtil.join(expectedHints, ", ", "\""));
+ }
+
+ private void warnUnexpectedHint(String actualHint, SourceLocation sourceLoc, String expectedHints) {
+ warningCollector.warn(WarningUtil.forAsterix(sourceLoc, ErrorCode.UNEXPECTED_HINT, actualHint, expectedHints));
}
}
PARSER_END(SQLPPParser)
-
List<Statement> Statement() throws ParseException:
{
scopeStack.push(RootScopeFactory.createRootScope(this));
@@ -556,22 +559,12 @@ DataverseDecl DataverseDeclaration() throws ParseException:
Statement CreateStatement() throws ParseException:
{
Token startToken = null;
- String hint = null;
- Token hintToken = null;
- boolean hintDGen = false;
Statement stmt = null;
}
{
<CREATE> { startToken = token; }
(
- {
- hint = getHint(token);
- if (hint != null) {
- hintToken = getHintToken(token);
- hintDGen = hint.startsWith(DGEN_HINT);
- }
- }
- stmt = TypeSpecification(startToken, hint, hintDGen, hintToken)
+ stmt = TypeSpecification(startToken)
| stmt = NodegroupSpecification(startToken)
| stmt = DatasetSpecification(startToken)
| stmt = IndexSpecification(startToken)
@@ -585,7 +578,7 @@ Statement CreateStatement() throws ParseException:
}
}
-TypeDecl TypeSpecification(Token startStmtToken, String hint, boolean dgen, Token hintToken) throws ParseException:
+TypeDecl TypeSpecification(Token startStmtToken) throws ParseException:
{
Pair<Identifier,Identifier> nameComponents = null;
boolean ifNotExists = false;
@@ -595,15 +588,20 @@ TypeDecl TypeSpecification(Token startStmtToken, String hint, boolean dgen, Toke
<TYPE> nameComponents = TypeName() ifNotExists = IfNotExists()
<AS> typeExpr = RecordTypeDef()
{
+ boolean dgen = false;
long numValues = -1;
String filename = null;
- if (dgen) {
- String splits[] = hint.split(" +");
- if (splits.length != 3) {
- throw new SqlppParseException(getSourceLocation(hintToken), "Expecting /*+ dgen <filename> <numberOfItems> */");
- }
- filename = splits[1];
- numValues = Long.parseLong(splits[2]);
+ Token hintToken = fetchHint(startStmtToken, SqlppHint.DGEN_HINT);
+ if (hintToken != null) {
+ String hintParams = hintToken.hintParams;
+ String[] splits = hintParams != null ? hintParams.split("\\s+") : null;
+ if (splits == null || splits.length != 2) {
+ throw new SqlppParseException(getSourceLocation(hintToken),
+ "Expecting /*+ dgen <filename> <numberOfItems> */");
+ }
+ dgen = true;
+ filename = splits[0];
+ numValues = Long.parseLong(splits[1]);
}
TypeDataGen tddg = new TypeDataGen(dgen, filename, numValues);
TypeDecl stmt = new TypeDecl(nameComponents.first, nameComponents.second, typeExpr, tddg, ifNotExists);
@@ -1581,29 +1579,27 @@ RecordTypeDefinition RecordTypeDef() throws ParseException:
<LEFTBRACE>
{
startToken = token;
- String hint = getHint(token);
- if (hint != null) {
- String splits[] = hint.split(" +");
- if (splits[0].equals(GEN_FIELDS_HINT)) {
- if (splits.length != 5) {
- throw new SqlppParseException(getSourceLocation(getHintToken(token)),
- "Expecting: /*+ gen-fields <type> <min> <max> <prefix>*/");
- }
- if (!splits[1].equals("int")) {
- throw new SqlppParseException(getSourceLocation(getHintToken(token)),
- "The only supported type for gen-fields is int.");
- }
- UndeclaredFieldsDataGen ufdg = new UndeclaredFieldsDataGen(UndeclaredFieldsDataGen.Type.INT,
- Integer.parseInt(splits[2]), Integer.parseInt(splits[3]), splits[4]);
- recType.setUndeclaredFieldsDataGen(ufdg);
+ Token hintToken = fetchHint(token, SqlppHint.GEN_FIELDS_HINT);
+ if (hintToken != null) {
+ String hintParams = hintToken.hintParams;
+ String[] splits = hintParams != null ? hintParams.split("\\s+") : null;
+ if (splits == null || splits.length != 4) {
+ throw new SqlppParseException(getSourceLocation(hintToken),
+ "Expecting: /*+ gen-fields <type> <min> <max> <prefix>*/");
+ }
+ if (!splits[0].equals("int")) {
+ throw new SqlppParseException(getSourceLocation(hintToken),
+ "The only supported type for gen-fields is int.");
}
+ UndeclaredFieldsDataGen ufdg = new UndeclaredFieldsDataGen(UndeclaredFieldsDataGen.Type.INT,
+ Integer.parseInt(splits[1]), Integer.parseInt(splits[2]), splits[3]);
+ recType.setUndeclaredFieldsDataGen(ufdg);
}
-
}
- (
- RecordField(recType)
- ( <COMMA> RecordField(recType) )*
- )?
+ (
+ RecordField(recType)
+ ( <COMMA> RecordField(recType) )*
+ )?
<RIGHTBRACE>
{
if (recordKind == null) {
@@ -1623,8 +1619,10 @@ void RecordField(RecordTypeDefinition recType) throws ParseException:
{
fieldName = Identifier()
{
- String hint = getHint(token);
- IRecordFieldDataGen rfdg = hint != null ? parseFieldDataGen(hint, token.specialToken) : null;
+ Token hintToken = fetchHint(token, SqlppHint.VAL_FILE_HINT, SqlppHint.VAL_FILE_SAME_INDEX_HINT,
+ SqlppHint.LIST_VAL_FILE_HINT, SqlppHint.LIST_HINT, SqlppHint.INTERVAL_HINT, SqlppHint.INSERT_RAND_INT_HINT,
+ SqlppHint.DATE_BETWEEN_YEARS_HINT, SqlppHint.DATETIME_ADD_RAND_HOURS_HINT, SqlppHint.AUTO_HINT);
+ IRecordFieldDataGen rfdg = hintToken != null ? parseFieldDataGen(hintToken) : null;
}
<COLON> type = TypeExpr() (<QUES> { nullable = true; } )?
{
@@ -1689,9 +1687,12 @@ FunctionName FunctionName() throws ParseException:
first = Identifier()
{
FunctionName result = new FunctionName();
- result.hint = getHint(token);
result.sourceLoc = getSourceLocation(token);
- result.hintSourceLoc = getSourceLocation(getHintToken(token));
+ Token hintToken = fetchHint(token, SqlppHint.INDEXED_NESTED_LOOP_JOIN_HINT,
+ SqlppHint.SKIP_SECONDARY_INDEX_SEARCH_HINT);
+ if (hintToken != null) {
+ result.hint = hintToken.hint;
+ }
}
( <DOT> second = Identifier()
{
@@ -2055,18 +2056,19 @@ Expression RelExpr() throws ParseException:
(
LOOKAHEAD(2)( <LT> | <GT> | <LE> | <GE> | <EQ> | <NE> | <LG> |<SIMILAR> | (<NOT> { not = true; })? <IN>)
{
- String mhint = getHint(token);
- if (mhint != null) {
- if (mhint.equals(INDEXED_NESTED_LOOP_JOIN_HINT)) {
+ Token hintToken = fetchHint(token, SqlppHint.INDEXED_NESTED_LOOP_JOIN_HINT,
+ SqlppHint.SKIP_SECONDARY_INDEX_SEARCH_HINT, SqlppHint.BROADCAST_JOIN_HINT);
+ if (hintToken != null) {
+ switch (hintToken.hint) {
+ case INDEXED_NESTED_LOOP_JOIN_HINT:
annotation = IndexedNLJoinExpressionAnnotation.INSTANCE;
- } else if (mhint.equals(SKIP_SECONDARY_INDEX_SEARCH_HINT)) {
+ break;
+ case SKIP_SECONDARY_INDEX_SEARCH_HINT:
annotation = SkipSecondaryIndexSearchExpressionAnnotation.INSTANCE;
- } else if (mhint.equals(BROADCAST_JOIN_HINT)) {
+ break;
+ case BROADCAST_JOIN_HINT:
broadcast = true;
- } else {
- warnUnknownHint(mhint, getSourceLocation(getHintToken(token)),
- INDEXED_NESTED_LOOP_JOIN_HINT, SKIP_SECONDARY_INDEX_SEARCH_HINT, BROADCAST_JOIN_HINT
- );
+ break;
}
}
@@ -2117,16 +2119,16 @@ Expression BetweenExpr() throws ParseException:
LOOKAHEAD(2)
(<NOT> { not = true; })? <BETWEEN>
{
- String mhint = getHint(token);
- if (mhint != null) {
- if (mhint.equals(INDEXED_NESTED_LOOP_JOIN_HINT)) {
+ Token hintToken = fetchHint(token, SqlppHint.INDEXED_NESTED_LOOP_JOIN_HINT,
+ SqlppHint.SKIP_SECONDARY_INDEX_SEARCH_HINT);
+ if (hintToken != null) {
+ switch (hintToken.hint) {
+ case INDEXED_NESTED_LOOP_JOIN_HINT:
annotation = IndexedNLJoinExpressionAnnotation.INSTANCE;
- } else if (mhint.equals(SKIP_SECONDARY_INDEX_SEARCH_HINT)) {
+ break;
+ case SKIP_SECONDARY_INDEX_SEARCH_HINT:
annotation = SkipSecondaryIndexSearchExpressionAnnotation.INSTANCE;
- } else {
- warnUnknownHint(mhint, getSourceLocation(getHintToken(token)),
- INDEXED_NESTED_LOOP_JOIN_HINT, SKIP_SECONDARY_INDEX_SEARCH_HINT
- );
+ break;
}
}
String operator = token.image.toLowerCase();
@@ -2807,16 +2809,14 @@ Expression FunctionCallExpr() throws ParseException:
signature = new FunctionSignature(funcName.dataverse, fqFunctionName, arity);
}
callExpr = FunctionMapUtil.normalizedListInputFunctions(new CallExpr(signature,argList));
- String hint = funcName.hint;
- if (hint != null) {
- if (hint.startsWith(INDEXED_NESTED_LOOP_JOIN_HINT)) {
- callExpr.addHint(IndexedNLJoinExpressionAnnotation.INSTANCE);
- } else if (hint.startsWith(SKIP_SECONDARY_INDEX_SEARCH_HINT)) {
- callExpr.addHint(SkipSecondaryIndexSearchExpressionAnnotation.INSTANCE);
- } else {
- warnUnknownHint(hint, funcName.hintSourceLoc,
- INDEXED_NESTED_LOOP_JOIN_HINT, SKIP_SECONDARY_INDEX_SEARCH_HINT
- );
+ if (funcName.hint != null) {
+ switch (funcName.hint) {
+ case INDEXED_NESTED_LOOP_JOIN_HINT:
+ callExpr.addHint(IndexedNLJoinExpressionAnnotation.INSTANCE);
+ break;
+ case SKIP_SECONDARY_INDEX_SEARCH_HINT:
+ callExpr.addHint(SkipSecondaryIndexSearchExpressionAnnotation.INSTANCE);
+ break;
}
}
callExpr.setSourceLocation(funcName.sourceLoc);
@@ -3475,20 +3475,23 @@ OrderbyClause OrderbyClause() throws ParseException :
<ORDER>
{
startToken = token;
- String hint = getHint(token);
- if (hint != null) {
- if (hint.startsWith(INMEMORY_HINT)) {
- String splits[] = hint.split(" +");
- int numFrames = Integer.parseInt(splits[1]);
- int numTuples = Integer.parseInt(splits[2]);
- oc.setNumFrames(numFrames);
- oc.setNumTuples(numTuples);
- } else if (hint.startsWith(RANGE_HINT)) {
- try {
- oc.setRangeMap(RangeMapBuilder.parseHint(parseExpression(hint.substring(RANGE_HINT.length()))));
- } catch (CompilationException e) {
- throw new SqlppParseException(getSourceLocation(getHintToken(token)), e.getMessage());
- }
+ Token hintToken = fetchHint(token, SqlppHint.INMEMORY_HINT, SqlppHint.RANGE_HINT);
+ if (hintToken != null) {
+ switch (hintToken.hint) {
+ case INMEMORY_HINT:
+ String[] splits = hintToken.hintParams.split("\\s+");
+ int numFrames = Integer.parseInt(splits[0]);
+ int numTuples = Integer.parseInt(splits[1]);
+ oc.setNumFrames(numFrames);
+ oc.setNumTuples(numTuples);
+ break;
+ case RANGE_HINT:
+ try {
+ oc.setRangeMap(RangeMapBuilder.parseHint(parseExpression(hintToken.hintParams)));
+ } catch (CompilationException e) {
+ throw new SqlppParseException(getSourceLocation(hintToken), e.getMessage());
+ }
+ break;
}
}
}
@@ -3543,13 +3546,9 @@ GroupbyClause GroupbyClause()throws ParseException :
<GROUP>
{
startToken = token;
- String hint = getHint(token);
- if (hint != null) {
- if (hint.equals(HASH_GROUP_BY_HINT)) {
- gbc.setHashGroupByHint(true);
- } else {
- warnUnknownHint(hint, getSourceLocation(getHintToken(token)), HASH_GROUP_BY_HINT);
- }
+ Token hintToken = fetchHint(token, SqlppHint.HASH_GROUP_BY_HINT);
+ if (hintToken != null) {
+ gbc.setHashGroupByHint(true);
}
}
<BY> (
@@ -3694,6 +3693,7 @@ TOKEN_MGR_DECLS:
{
public int commentDepth = 0;
public ArrayDeque<Integer> lexerStateStack = new ArrayDeque<Integer>();
+ public Map<SourceLocation, String> hintCollector;
public void pushState() {
lexerStateStack.push( curLexState );
@@ -3710,6 +3710,16 @@ TOKEN_MGR_DECLS:
throw new TokenMgrError(msg, -1);
}
}
+
+ void CommonTokenAction(Token token) {
+ Token hintToken = token.specialToken;
+ if (hintToken != null) {
+ hintToken.sourceLocation = new SourceLocation(hintToken.beginLine, hintToken.beginColumn);
+ String text = hintToken.image.substring(1).trim();
+ boolean hintFound = hintToken.parseHint(text);
+ hintCollector.put(hintToken.sourceLocation, hintFound ? hintToken.hint.getIdentifier() : hintToken.hintParams);
+ }
+ }
}
<DEFAULT,IN_DBL_BRACE>
diff --git a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/StringUtil.java b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/StringUtil.java
index 11be0ba..78155c9 100644
--- a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/StringUtil.java
+++ b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/StringUtil.java
@@ -36,4 +36,18 @@ public class StringUtil {
return CAMEL_CACHE.computeIfAbsent(input, s -> SEPARATORS_PATTERN
.matcher(WordUtils.capitalize("z" + s.toLowerCase(), '_', '-', ' ').substring(1)).replaceAll(""));
}
+
+ public static String join(Object[] objects, String separator, String quote) {
+ if (objects == null || objects.length == 0) {
+ return "";
+ }
+ int length = objects.length;
+ String str0 = String.valueOf(objects[0]);
+ StringBuilder sb = new StringBuilder((str0.length() + 3) * length);
+ sb.append(quote).append(str0).append(quote);
+ for (int i = 1; i < length; i++) {
+ sb.append(separator).append(quote).append(objects[i]).append(quote);
+ }
+ return sb.toString();
+ }
}