[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 <jenkins@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Dmitry Lychagin <dmitry.lychagin@couchbase.com>
Reviewed-by: Ali Alsuliman <ali.al.solaiman@gmail.com>
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.2.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.2.query.sqlpp
new file mode 100644
index 0000000..d0d6c1a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.2.query.sqlpp
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * Description : Warning when a hint at GROUP BY is recognized,
+ * : but not applicable for GROUP BY
+ * Expected : SUCCESS (with ASX1107 warning)
+ */
+
+with ds as (
+ from range(1, 4) r
+ select r % 2 as x, r as y
+)
+
+from ds
+/*+ 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.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.3.query.sqlpp
new file mode 100644
index 0000000..daab311
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.3.query.sqlpp
@@ -0,0 +1,28 @@
+/*
+ * 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 : Warning when a hint at relational expression is recognized
+ * : but not applicable for relational expression
+ * Expected : SUCCESS (with ASX1107 warning)
+ */
+
+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.4.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.4.query.sqlpp
new file mode 100644
index 0000000..cc8c8df
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.4.query.sqlpp
@@ -0,0 +1,28 @@
+/*
+ * 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 : Warning when a hint at BETWEEN is recognized
+ * : but not applicable for BETWEEN
+ * Expected : SUCCESS (with ASX1107 warning)
+ */
+
+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.5.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.5.query.sqlpp
new file mode 100644
index 0000000..a19aeec
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.5.query.sqlpp
@@ -0,0 +1,28 @@
+/*
+ * 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 : Warning when a hint at function call is recognized
+ * : but not applicable for function call
+ * Expected : SUCCESS (with ASX1107 warning)
+ */
+
+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.6.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.6.query.sqlpp
new file mode 100644
index 0000000..b669569
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/inapplicable-hint-warning/inapplicable-hint-warning.6.query.sqlpp
@@ -0,0 +1,28 @@
+/*
+ * 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 : Warning when a hint is recognized
+ * : but no hints applicable at this location
+ * Expected : SUCCESS (with ASX1107 warning)
+ */
+
+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/unknown-hint-warning/unknown-hint-warning.5.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/unknown-hint-warning/unknown-hint-warning.5.query.sqlpp
new file mode 100644
index 0000000..517e39b
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/warnings/unknown-hint-warning/unknown-hint-warning.5.query.sqlpp
@@ -0,0 +1,27 @@
+/*
+ * 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 : Warning when a hint is not recognized elsewhere
+ * Expected : SUCCESS (with ASX1107 warning)
+ */
+
+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 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/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/parser/SqlppToken.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/parser/SqlppToken.java
new file mode 100644
index 0000000..13dca02
--- /dev/null
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/parser/SqlppToken.java
@@ -0,0 +1,45 @@
+/*
+ * 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.io.Serializable;
+
+import org.apache.hyracks.api.exceptions.SourceLocation;
+
+public abstract class SqlppToken implements Serializable {
+
+ public SourceLocation sourceLocation;
+
+ public SqlppHint hint;
+ public String hintParams;
+
+ 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.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.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 @@
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 @@
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 @@
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 @@
private <T> T parseImpl(ParseFunction<T> parseFunction) throws CompilationException {
warningCollector.clear();
+ hintCollector.clear();
try {
return parseFunction.parse();
} catch (Error e) {
@@ -371,6 +343,8 @@
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 @@
}
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 @@
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 @@
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 @@
}
}
-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 @@
<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 @@
<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 @@
{
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 @@
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 @@
(
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 @@
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 @@
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 @@
<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 @@
<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 @@
{
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 @@
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 @@
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();
+ }
}