Merge "Merge branch 'gerrit/goldfish' into 'master'"
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
index be36225..c5fc395 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
@@ -114,6 +114,8 @@
import org.apache.hyracks.api.job.JobSpecification;
import org.apache.hyracks.api.job.resource.IClusterCapacity;
import org.apache.hyracks.control.common.config.OptionTypes;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
@@ -125,6 +127,8 @@
*/
public class APIFramework {
+ private static final Logger LOGGER = LogManager.getLogger();
+
private static final ObjectWriter OBJECT_WRITER = new ObjectMapper().writerWithDefaultPrettyPrinter();
public static final String PREFIX_INTERNAL_PARAMETERS = "_internal";
@@ -192,16 +196,21 @@
public Pair<IReturningStatement, Integer> reWriteQuery(LangRewritingContext langRewritingContext,
IReturningStatement q, SessionOutput output, boolean allowNonStoredUdfCalls, boolean inlineUdfsAndViews,
Collection<VarIdentifier> externalVars) throws CompilationException {
- if (q == null) {
- return null;
+ try {
+ if (q == null) {
+ return null;
+ }
+ SessionConfig conf = output.config();
+ if (!conf.is(SessionConfig.FORMAT_ONLY_PHYSICAL_OPS) && conf.is(SessionConfig.OOB_EXPR_TREE)) {
+ generateExpressionTree(q);
+ }
+ IQueryRewriter rw = rewriterFactory.createQueryRewriter();
+ rw.rewrite(langRewritingContext, q, allowNonStoredUdfCalls, inlineUdfsAndViews, externalVars);
+ return new Pair<>(q, q.getVarCounter());
+ } catch (StackOverflowError error) {
+ LOGGER.info("Stack Overflow", error);
+ throw new CompilationException(ErrorCode.COMPILATION_ERROR, "internal error");
}
- SessionConfig conf = output.config();
- if (!conf.is(SessionConfig.FORMAT_ONLY_PHYSICAL_OPS) && conf.is(SessionConfig.OOB_EXPR_TREE)) {
- generateExpressionTree(q);
- }
- IQueryRewriter rw = rewriterFactory.createQueryRewriter();
- rw.rewrite(langRewritingContext, q, allowNonStoredUdfCalls, inlineUdfsAndViews, externalVars);
- return new Pair<>(q, q.getVarCounter());
}
public JobSpecification compileQuery(IClusterInfoCollector clusterInfoCollector, MetadataProvider metadataProvider,
@@ -210,172 +219,183 @@
IRequestParameters requestParameters, EnumSet<JobFlag> runtimeFlags)
throws AlgebricksException, ACIDException {
- // establish facts
- final boolean isQuery = query != null;
- final boolean isLoad = statement != null && statement.getKind() == Statement.Kind.LOAD;
- final boolean isCopy = statement != null && statement.getKind() == Statement.Kind.COPY_FROM;
- final SourceLocation sourceLoc =
- query != null ? query.getSourceLocation() : statement != null ? statement.getSourceLocation() : null;
- final boolean isExplainOnly = isQuery && query.isExplain();
+ try {
+ // establish facts
+ final boolean isQuery = query != null;
+ final boolean isLoad = statement != null && statement.getKind() == Statement.Kind.LOAD;
+ final boolean isCopy = statement != null && statement.getKind() == Statement.Kind.COPY_FROM;
+ final SourceLocation sourceLoc = query != null ? query.getSourceLocation()
+ : statement != null ? statement.getSourceLocation() : null;
+ final boolean isExplainOnly = isQuery && query.isExplain();
- SessionConfig conf = output.config();
- if (isQuery && !conf.is(SessionConfig.FORMAT_ONLY_PHYSICAL_OPS)
- && conf.is(SessionConfig.OOB_REWRITTEN_EXPR_TREE)) {
- generateRewrittenExpressionTree(query);
- }
+ SessionConfig conf = output.config();
+ if (isQuery && !conf.is(SessionConfig.FORMAT_ONLY_PHYSICAL_OPS)
+ && conf.is(SessionConfig.OOB_REWRITTEN_EXPR_TREE)) {
+ generateRewrittenExpressionTree(query);
+ }
- final TxnId txnId = metadataProvider.getTxnIdFactory().create();
- metadataProvider.setTxnId(txnId);
- ILangExpressionToPlanTranslator t =
- translatorFactory.createExpressionToPlanTranslator(metadataProvider, varCounter, externalVars);
- ResultMetadata resultMetadata = new ResultMetadata(output.config().fmt());
- ILogicalPlan plan = isLoad || isCopy ? t.translateCopyOrLoad((ICompiledDmlStatement) statement)
- : t.translate(query, outputDatasetName, statement, resultMetadata);
+ final TxnId txnId = metadataProvider.getTxnIdFactory().create();
+ metadataProvider.setTxnId(txnId);
+ ILangExpressionToPlanTranslator t =
+ translatorFactory.createExpressionToPlanTranslator(metadataProvider, varCounter, externalVars);
+ ResultMetadata resultMetadata = new ResultMetadata(output.config().fmt());
+ ILogicalPlan plan = isLoad || isCopy ? t.translateCopyOrLoad((ICompiledDmlStatement) statement)
+ : t.translate(query, outputDatasetName, statement, resultMetadata);
- ICcApplicationContext ccAppContext = metadataProvider.getApplicationContext();
- CompilerProperties compilerProperties = ccAppContext.getCompilerProperties();
- Map<String, Object> config = metadataProvider.getConfig();
- Map<String, Object> querySpecificConfig = validateConfig(config, sourceLoc);
- final PhysicalOptimizationConfig physOptConf = OptimizationConfUtil.createPhysicalOptimizationConf(
- compilerProperties, querySpecificConfig, configurableParameterNames, sourceLoc);
- if (!config.containsKey(CompilerProperties.COMPILER_ORDERED_FIELDS_KEY)) {
- config.put(CompilerProperties.COMPILER_ORDERED_FIELDS_KEY, Boolean.toString(physOptConf.isOrderField()));
- }
+ ICcApplicationContext ccAppContext = metadataProvider.getApplicationContext();
+ CompilerProperties compilerProperties = ccAppContext.getCompilerProperties();
+ Map<String, Object> config = metadataProvider.getConfig();
+ Map<String, Object> querySpecificConfig = validateConfig(config, sourceLoc);
+ final PhysicalOptimizationConfig physOptConf = OptimizationConfUtil.createPhysicalOptimizationConf(
+ compilerProperties, querySpecificConfig, configurableParameterNames, sourceLoc);
+ if (!config.containsKey(CompilerProperties.COMPILER_ORDERED_FIELDS_KEY)) {
+ config.put(CompilerProperties.COMPILER_ORDERED_FIELDS_KEY,
+ Boolean.toString(physOptConf.isOrderField()));
+ }
- boolean cboMode = physOptConf.getCBOMode() || physOptConf.getCBOTestMode();
- HeuristicCompilerFactoryBuilder builder =
- new HeuristicCompilerFactoryBuilder(OptimizationContextFactory.INSTANCE);
- builder.setPhysicalOptimizationConfig(physOptConf);
- builder.setLogicalRewrites(() -> ruleSetFactory.getLogicalRewrites(ccAppContext));
- builder.setLogicalRewritesByKind(kind -> ruleSetFactory.getLogicalRewrites(kind, ccAppContext));
- builder.setPhysicalRewrites(() -> ruleSetFactory.getPhysicalRewrites(ccAppContext));
- IDataFormat format = metadataProvider.getDataFormat();
- ICompilerFactory compilerFactory = builder.create();
- builder.setExpressionEvalSizeComputer(format.getExpressionEvalSizeComputer());
- builder.setIMergeAggregationExpressionFactory(new MergeAggregationExpressionFactory());
- builder.setPartialAggregationTypeComputer(new PartialAggregationTypeComputer());
- builder.setExpressionTypeComputer(ExpressionTypeComputer.INSTANCE);
- builder.setMissableTypeComputer(MissableTypeComputer.INSTANCE);
- builder.setConflictingTypeResolver(ConflictingTypeResolver.INSTANCE);
- builder.setWarningCollector(warningCollector);
- builder.setMaxWarnings(conf.getMaxWarnings());
+ boolean cboMode = physOptConf.getCBOMode() || physOptConf.getCBOTestMode();
+ HeuristicCompilerFactoryBuilder builder =
+ new HeuristicCompilerFactoryBuilder(OptimizationContextFactory.INSTANCE);
+ builder.setPhysicalOptimizationConfig(physOptConf);
+ builder.setLogicalRewrites(() -> ruleSetFactory.getLogicalRewrites(ccAppContext));
+ builder.setLogicalRewritesByKind(kind -> ruleSetFactory.getLogicalRewrites(kind, ccAppContext));
+ builder.setPhysicalRewrites(() -> ruleSetFactory.getPhysicalRewrites(ccAppContext));
+ IDataFormat format = metadataProvider.getDataFormat();
+ ICompilerFactory compilerFactory = builder.create();
+ builder.setExpressionEvalSizeComputer(format.getExpressionEvalSizeComputer());
+ builder.setIMergeAggregationExpressionFactory(new MergeAggregationExpressionFactory());
+ builder.setPartialAggregationTypeComputer(new PartialAggregationTypeComputer());
+ builder.setExpressionTypeComputer(ExpressionTypeComputer.INSTANCE);
+ builder.setMissableTypeComputer(MissableTypeComputer.INSTANCE);
+ builder.setConflictingTypeResolver(ConflictingTypeResolver.INSTANCE);
+ builder.setWarningCollector(warningCollector);
+ builder.setMaxWarnings(conf.getMaxWarnings());
- if ((isQuery || isLoad || isCopy) && !conf.is(SessionConfig.FORMAT_ONLY_PHYSICAL_OPS)
- && conf.is(SessionConfig.OOB_LOGICAL_PLAN)) {
- generateLogicalPlan(plan, output.config().getPlanFormat(), cboMode);
- }
+ if ((isQuery || isLoad || isCopy) && !conf.is(SessionConfig.FORMAT_ONLY_PHYSICAL_OPS)
+ && conf.is(SessionConfig.OOB_LOGICAL_PLAN)) {
+ generateLogicalPlan(plan, output.config().getPlanFormat(), cboMode);
+ }
- int parallelism = getParallelism((String) querySpecificConfig.get(CompilerProperties.COMPILER_PARALLELISM_KEY),
- compilerProperties.getParallelism());
- AlgebricksAbsolutePartitionConstraint computationLocations =
- chooseLocations(clusterInfoCollector, parallelism, metadataProvider.getClusterLocations());
- builder.setClusterLocations(computationLocations);
+ int parallelism =
+ getParallelism((String) querySpecificConfig.get(CompilerProperties.COMPILER_PARALLELISM_KEY),
+ compilerProperties.getParallelism());
+ AlgebricksAbsolutePartitionConstraint computationLocations =
+ chooseLocations(clusterInfoCollector, parallelism, metadataProvider.getClusterLocations());
+ builder.setClusterLocations(computationLocations);
- builder.setBinaryBooleanInspectorFactory(format.getBinaryBooleanInspectorFactory());
- builder.setBinaryIntegerInspectorFactory(format.getBinaryIntegerInspectorFactory());
- builder.setComparatorFactoryProvider(format.getBinaryComparatorFactoryProvider());
- builder.setExpressionRuntimeProvider(
- new ExpressionRuntimeProvider(new QueryLogicalExpressionJobGen(metadataProvider.getFunctionManager())));
- builder.setHashFunctionFactoryProvider(format.getBinaryHashFunctionFactoryProvider());
- builder.setHashFunctionFamilyProvider(format.getBinaryHashFunctionFamilyProvider());
- builder.setMissingWriterFactory(format.getMissingWriterFactory());
- builder.setNullWriterFactory(format.getNullWriterFactory());
- builder.setUnnestingPositionWriterFactory(format.getUnnestingPositionWriterFactory());
- builder.setPredicateEvaluatorFactoryProvider(format.getPredicateEvaluatorFactoryProvider());
- builder.setPrinterProvider(getPrinterFactoryProvider(format, conf.fmt()));
- builder.setWriterFactory(PrinterBasedWriterFactory.INSTANCE);
- builder.setResultSerializerFactoryProvider(ResultSerializerFactoryProvider.INSTANCE);
- builder.setSerializerDeserializerProvider(format.getSerdeProvider());
- builder.setTypeTraitProvider(format.getTypeTraitProvider());
- builder.setNormalizedKeyComputerFactoryProvider(format.getNormalizedKeyComputerFactoryProvider());
+ builder.setBinaryBooleanInspectorFactory(format.getBinaryBooleanInspectorFactory());
+ builder.setBinaryIntegerInspectorFactory(format.getBinaryIntegerInspectorFactory());
+ builder.setComparatorFactoryProvider(format.getBinaryComparatorFactoryProvider());
+ builder.setExpressionRuntimeProvider(new ExpressionRuntimeProvider(
+ new QueryLogicalExpressionJobGen(metadataProvider.getFunctionManager())));
+ builder.setHashFunctionFactoryProvider(format.getBinaryHashFunctionFactoryProvider());
+ builder.setHashFunctionFamilyProvider(format.getBinaryHashFunctionFamilyProvider());
+ builder.setMissingWriterFactory(format.getMissingWriterFactory());
+ builder.setNullWriterFactory(format.getNullWriterFactory());
+ builder.setUnnestingPositionWriterFactory(format.getUnnestingPositionWriterFactory());
+ builder.setPredicateEvaluatorFactoryProvider(format.getPredicateEvaluatorFactoryProvider());
+ builder.setPrinterProvider(getPrinterFactoryProvider(format, conf.fmt()));
+ builder.setWriterFactory(PrinterBasedWriterFactory.INSTANCE);
+ builder.setResultSerializerFactoryProvider(ResultSerializerFactoryProvider.INSTANCE);
+ builder.setSerializerDeserializerProvider(format.getSerdeProvider());
+ builder.setTypeTraitProvider(format.getTypeTraitProvider());
+ builder.setNormalizedKeyComputerFactoryProvider(format.getNormalizedKeyComputerFactoryProvider());
- ICompiler compiler = compilerFactory.createCompiler(plan, metadataProvider, t.getVarCounter());
- if (conf.isOptimize()) {
- compiler.optimize();
- if (conf.is(SessionConfig.OOB_OPTIMIZED_LOGICAL_PLAN) || isExplainOnly) {
- if (conf.is(SessionConfig.FORMAT_ONLY_PHYSICAL_OPS)) {
- // For Optimizer tests. Print physical operators in verbose mode.
- AlgebricksStringBuilderWriter buf = new AlgebricksStringBuilderWriter(PlanPrettyPrinter.INIT_SIZE);
- PlanPrettyPrinter.printPhysicalOps(plan, buf, 0, true);
- output.out().write(buf.toString());
- } else {
- if (isQuery || isLoad || isCopy) {
- generateOptimizedLogicalPlan(plan, output.config().getPlanFormat(), cboMode);
+ ICompiler compiler = compilerFactory.createCompiler(plan, metadataProvider, t.getVarCounter());
+ if (conf.isOptimize()) {
+ compiler.optimize();
+ if (conf.is(SessionConfig.OOB_OPTIMIZED_LOGICAL_PLAN) || isExplainOnly) {
+ if (conf.is(SessionConfig.FORMAT_ONLY_PHYSICAL_OPS)) {
+ // For Optimizer tests. Print physical operators in verbose mode.
+ AlgebricksStringBuilderWriter buf =
+ new AlgebricksStringBuilderWriter(PlanPrettyPrinter.INIT_SIZE);
+ PlanPrettyPrinter.printPhysicalOps(plan, buf, 0, true);
+ output.out().write(buf.toString());
+ } else {
+ if (isQuery || isLoad || isCopy) {
+ generateOptimizedLogicalPlan(plan, output.config().getPlanFormat(), cboMode);
+ }
}
}
}
- }
- if (conf.getClientType() == SessionConfig.ClientType.JDBC) {
- executionPlans.setStatementCategory(Statement.Category.toString(getStatementCategory(query, statement)));
- if (!conf.isExecuteQuery()) {
- String stmtParams = ResultUtil.ParseOnlyResult.printStatementParameters(externalVars.keySet(), v -> v);
- executionPlans.setStatementParameters(stmtParams);
+ if (conf.getClientType() == SessionConfig.ClientType.JDBC) {
+ executionPlans
+ .setStatementCategory(Statement.Category.toString(getStatementCategory(query, statement)));
+ if (!conf.isExecuteQuery()) {
+ String stmtParams =
+ ResultUtil.ParseOnlyResult.printStatementParameters(externalVars.keySet(), v -> v);
+ executionPlans.setStatementParameters(stmtParams);
+ }
+ if (isExplainOnly) {
+ executionPlans.setExplainOnly(true);
+ } else if (isQuery) {
+ executionPlans.setSignature(SignaturePrinter.generateFlatSignature(resultMetadata));
+ }
}
+
+ boolean printSignature = isQuery && requestParameters != null && requestParameters.isPrintSignature();
+
+ if (printSignature && !isExplainOnly) { //explainOnly adds the signature later
+ printer.addResultPrinter(SignaturePrinter.newInstance(executionPlans));
+ }
+
+ if (!conf.isGenerateJobSpec()) {
+ if (isQuery || isLoad || isCopy) {
+ generateOptimizedLogicalPlan(plan, output.config().getPlanFormat(), cboMode);
+ }
+ return null;
+ }
+
+ JobEventListenerFactory jobEventListenerFactory =
+ new JobEventListenerFactory(txnId, metadataProvider.isWriteTransaction());
+ JobSpecification spec = compiler.createJob(ccAppContext, jobEventListenerFactory, runtimeFlags);
+
+ if (isQuery || isCopy) {
+ if (!compiler.skipJobCapacityAssignment()) {
+ if (requestParameters == null || !requestParameters.isSkipAdmissionPolicy()) {
+ // Sets a required capacity, only for read-only queries.
+ // DDLs and DMLs are considered not that frequent.
+ // limit the computation locations to the locations that will be used in the query
+ final INodeJobTracker nodeJobTracker = ccAppContext.getNodeJobTracker();
+ final AlgebricksAbsolutePartitionConstraint jobLocations =
+ getJobLocations(spec, nodeJobTracker, computationLocations);
+ final IClusterCapacity jobRequiredCapacity =
+ ResourceUtils.getRequiredCapacity(plan, jobLocations, physOptConf, compilerProperties);
+ addRuntimeMemoryOverhead(jobRequiredCapacity, compilerProperties);
+ spec.setRequiredClusterCapacity(jobRequiredCapacity);
+ }
+ }
+ }
+
+ if (conf.is(SessionConfig.OOB_OPTIMIZED_LOGICAL_PLAN) || isExplainOnly) {
+ if (isQuery || isLoad || isCopy) {
+ generateOptimizedLogicalPlan(plan, spec.getLogical2PhysicalMap(), output.config().getPlanFormat(),
+ cboMode);
+ if (runtimeFlags.contains(JobFlag.PROFILE_RUNTIME)) {
+ lastPlan = new PlanInfo(plan, spec.getLogical2PhysicalMap(), cboMode,
+ output.config().getPlanFormat());
+ }
+ }
+ }
+
if (isExplainOnly) {
- executionPlans.setExplainOnly(true);
- } else if (isQuery) {
- executionPlans.setSignature(SignaturePrinter.generateFlatSignature(resultMetadata));
- }
- }
-
- boolean printSignature = isQuery && requestParameters != null && requestParameters.isPrintSignature();
-
- if (printSignature && !isExplainOnly) { //explainOnly adds the signature later
- printer.addResultPrinter(SignaturePrinter.newInstance(executionPlans));
- }
-
- if (!conf.isGenerateJobSpec()) {
- if (isQuery || isLoad || isCopy) {
- generateOptimizedLogicalPlan(plan, output.config().getPlanFormat(), cboMode);
- }
- return null;
- }
-
- JobEventListenerFactory jobEventListenerFactory =
- new JobEventListenerFactory(txnId, metadataProvider.isWriteTransaction());
- JobSpecification spec = compiler.createJob(ccAppContext, jobEventListenerFactory, runtimeFlags);
-
- if (isQuery || isCopy) {
- if (!compiler.skipJobCapacityAssignment()) {
- if (requestParameters == null || !requestParameters.isSkipAdmissionPolicy()) {
- // Sets a required capacity, only for read-only queries.
- // DDLs and DMLs are considered not that frequent.
- // limit the computation locations to the locations that will be used in the query
- final INodeJobTracker nodeJobTracker = ccAppContext.getNodeJobTracker();
- final AlgebricksAbsolutePartitionConstraint jobLocations =
- getJobLocations(spec, nodeJobTracker, computationLocations);
- final IClusterCapacity jobRequiredCapacity =
- ResourceUtils.getRequiredCapacity(plan, jobLocations, physOptConf, compilerProperties);
- addRuntimeMemoryOverhead(jobRequiredCapacity, compilerProperties);
- spec.setRequiredClusterCapacity(jobRequiredCapacity);
+ printPlanAsResult(metadataProvider, output, printer, printSignature);
+ if (!conf.is(SessionConfig.OOB_OPTIMIZED_LOGICAL_PLAN)) {
+ executionPlans.setOptimizedLogicalPlan(null);
}
+ return null;
}
- }
- if (conf.is(SessionConfig.OOB_OPTIMIZED_LOGICAL_PLAN) || isExplainOnly) {
- if (isQuery || isLoad || isCopy) {
- generateOptimizedLogicalPlan(plan, spec.getLogical2PhysicalMap(), output.config().getPlanFormat(),
- cboMode);
- if (runtimeFlags.contains(JobFlag.PROFILE_RUNTIME)) {
- lastPlan =
- new PlanInfo(plan, spec.getLogical2PhysicalMap(), cboMode, output.config().getPlanFormat());
- }
+ if (isQuery && conf.is(SessionConfig.OOB_HYRACKS_JOB)) {
+ generateJob(spec);
}
- }
+ return spec;
- if (isExplainOnly) {
- printPlanAsResult(metadataProvider, output, printer, printSignature);
- if (!conf.is(SessionConfig.OOB_OPTIMIZED_LOGICAL_PLAN)) {
- executionPlans.setOptimizedLogicalPlan(null);
- }
- return null;
+ } catch (StackOverflowError error) {
+ LOGGER.info("Stack Overflow", error);
+ throw new CompilationException(ErrorCode.COMPILATION_ERROR, "internal error");
}
-
- if (isQuery && conf.is(SessionConfig.OOB_HYRACKS_JOB)) {
- generateJob(spec);
- }
- return spec;
}
private void printPlanAsResult(MetadataProvider metadataProvider, SessionOutput output, IResponsePrinter printer,
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/skip-index/skip-secondary-btree-index-4.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/skip-index/skip-secondary-btree-index-4.sqlpp
new file mode 100644
index 0000000..35ca9f9
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/skip-index/skip-secondary-btree-index-4.sqlpp
@@ -0,0 +1,31 @@
+/*
+ * 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 : Skip secondary index for LIKE operator
+ * Expected Res : Success
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
+use test;
+
+create collection c primary key (id: int);
+create index idx1 on c(f:string);
+select * from c where f /*+skip-index*/ like "abc%";
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/skip-index/skip-secondary-btree-index-4.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/skip-index/skip-secondary-btree-index-4.plan
new file mode 100644
index 0000000..1435e63
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/skip-index/skip-secondary-btree-index-4.plan
@@ -0,0 +1,10 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- DATASOURCE_SCAN (test.c) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
\ No newline at end of file
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
index e65568e..6b3aa54 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
+++ b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
@@ -4184,6 +4184,7 @@
OperatorExpr op = null;
Expression operand = null;
IExpressionAnnotation annotation = null;
+ List<IExpressionAnnotation> annotationList = null;
}
{
operand = ConcatExpr()
@@ -4191,9 +4192,17 @@
LOOKAHEAD(2)
(<NOT> { not = true; })? <LIKE>
{
- Token hintToken = fetchHint(token, SqlppHint.SINGLE_DATASET_PREDICATE_SELECTIVITY_HINT);
- if (hintToken != null) {
- annotation = parseExpressionAnnotation(hintToken);
+ List<Token> hintTokens = fetchHints(token, SqlppHint.SINGLE_DATASET_PREDICATE_SELECTIVITY_HINT,
+ SqlppHint.SKIP_SECONDARY_INDEX_SEARCH_HINT, SqlppHint.USE_SECONDARY_INDEX_SEARCH_HINT);
+ if (hintTokens != null && !hintTokens.isEmpty()) {
+ annotationList = new ArrayList<IExpressionAnnotation>();
+ }
+ for (Token hintToken : hintTokens) {
+ annotation = parseExpressionAnnotation(hintToken);
+ if (annotation != null) {
+ // annotation may be null if hints are malformed
+ annotationList.add(annotation);
+ }
}
op = new OperatorExpr();
op.addOperand(operand);
@@ -4209,8 +4218,8 @@
} catch (CompilationException e){
throw new SqlppParseException(getSourceLocation(token), e.getMessage());
}
- if (annotation != null) {
- op.addHint(annotation);
+ if (annotationList != null && !annotationList.isEmpty()) {
+ op.addHints(annotationList);
}
}