Taewoo Kim has uploaded a new change for review.
https://asterix-gerrit.ics.uci.edu/1383
Change subject: Full-text implementation step 2
......................................................................
Full-text implementation step 2
- Parameter checking during the compilation is now applied.
Change-Id: Idec6b602ff7797846fd237a924005031c2395346
---
M
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/DefaultRuleSetFactory.java
M
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
A
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/FullTextContainsParameterCheckRule.java
M asterixdb/asterix-doc/src/site/site.xml
4 files changed, 249 insertions(+), 0 deletions(-)
git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb
refs/changes/83/1383/1
diff --git
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/DefaultRuleSetFactory.java
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/DefaultRuleSetFactory.java
index f6526c4..32d766b 100644
---
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/DefaultRuleSetFactory.java
+++
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/DefaultRuleSetFactory.java
@@ -64,6 +64,7 @@
defaultLogicalRewrites.add(new Pair<>(seqCtrlFullDfs,
RuleCollections.buildLoadFieldsRuleCollection()));
defaultLogicalRewrites.add(new Pair<>(seqOnceCtrl,
RuleCollections.buildDataExchangeRuleCollection()));
defaultLogicalRewrites.add(new Pair<>(seqCtrlNoDfs,
RuleCollections.buildConsolidationRuleCollection()));
+ defaultLogicalRewrites.add(new Pair<>(seqOnceCtrl,
RuleCollections.buildFulltextContainsRuleCollection()));
defaultLogicalRewrites.add(new Pair<>(seqCtrlNoDfs,
RuleCollections.buildAccessMethodRuleCollection()));
defaultLogicalRewrites.add(new Pair<>(seqCtrlNoDfs,
RuleCollections.buildPlanCleanupRuleCollection()));
diff --git
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
index 3efc4dc..8e318be 100644
---
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
+++
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
@@ -35,6 +35,7 @@
import org.apache.asterix.optimizer.rules.ExtractDistinctByExpressionsRule;
import org.apache.asterix.optimizer.rules.ExtractOrderExpressionsRule;
import org.apache.asterix.optimizer.rules.FeedScanCollectionToUnnest;
+import org.apache.asterix.optimizer.rules.FullTextContainsParameterCheckRule;
import org.apache.asterix.optimizer.rules.FuzzyEqRule;
import org.apache.asterix.optimizer.rules.InjectTypeCastForSwitchCaseRule;
import org.apache.asterix.optimizer.rules.InjectTypeCastForUnionRule;
@@ -154,6 +155,12 @@
return autogen;
}
+ public static final List<IAlgebraicRewriteRule>
buildFulltextContainsRuleCollection() {
+ List<IAlgebraicRewriteRule> ftRule = new LinkedList<>();
+ ftRule.add(new FullTextContainsParameterCheckRule());
+ return ftRule;
+ }
+
public static final List<IAlgebraicRewriteRule>
buildNormalizationRuleCollection() {
List<IAlgebraicRewriteRule> normalization = new LinkedList<>();
normalization.add(new ResolveVariableRule());
diff --git
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/FullTextContainsParameterCheckRule.java
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/FullTextContainsParameterCheckRule.java
new file mode 100644
index 0000000..c8aa3f1
--- /dev/null
+++
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/FullTextContainsParameterCheckRule.java
@@ -0,0 +1,240 @@
+/*
+ * 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.optimizer.rules;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.asterix.om.functions.AsterixBuiltinFunctions;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.util.ConstantExpressionUtil;
+import
org.apache.asterix.runtime.evaluators.functions.FullTextContainsDescriptor;
+import org.apache.commons.lang3.mutable.Mutable;
+import org.apache.commons.lang3.mutable.MutableObject;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
+import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
+import org.apache.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
+import org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
+import
org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import
org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator;
+import
org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator;
+import org.apache.hyracks.algebricks.core.algebra.util.OperatorPropertiesUtil;
+import org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
+
+/**
+ * Checks whether the given parameters of the ftcontains() function are
correct during the compilation.
+ */
+public class FullTextContainsParameterCheckRule implements
IAlgebraicRewriteRule {
+
+ // parameter name and its value
+ HashMap<MutableObject<ILogicalExpression>,
MutableObject<ILogicalExpression>> paramValueMap;
+
+ @Override
+ public boolean rewritePost(Mutable<ILogicalOperator> opRef,
IOptimizationContext context)
+ throws AlgebricksException {
+ AbstractLogicalOperator op = (AbstractLogicalOperator)
opRef.getValue();
+ SelectOperator selectOp;
+
+ Mutable<ILogicalExpression> expRef;
+ if (op.getOperatorTag() == LogicalOperatorTag.SELECT) {
+ selectOp = (SelectOperator) op;
+ expRef = selectOp.getCondition();
+ } else {
+ return false;
+ }
+
+ if (context.checkIfInDontApplySet(this, selectOp)) {
+ return false;
+ }
+
+ if (checkParamter(selectOp, expRef, context)) {
+ OperatorPropertiesUtil.typeOpRec(opRef, context);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Check the correctness of the parameters of the ftcontains(). Also
rearrange options as arguments.
+ */
+ private boolean checkParamter(SelectOperator selectOp,
Mutable<ILogicalExpression> expRef,
+ IOptimizationContext context)
+ throws AlgebricksException {
+ ILogicalExpression exp = expRef.getValue();
+
+ if (exp.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
+ return false;
+ }
+
+ AbstractFunctionCallExpression funcExp =
(AbstractFunctionCallExpression) exp;
+ FunctionIdentifier fi = funcExp.getFunctionIdentifier();
+
+ if (fi == AsterixBuiltinFunctions.FULLTEXT_CONTAINS) {
+ // Don't need to check this operator again.
+ context.addToDontApplySet(this, selectOp);
+
+ List<Mutable<ILogicalExpression>> oldExprs =
funcExp.getArguments();
+ List<Mutable<ILogicalExpression>> newExprs = new ArrayList<>();
+
+ for (int i = 0; i < oldExprs.size() - 1; i++) {
+ newExprs.add(new
MutableObject<ILogicalExpression>((ILogicalExpression)
oldExprs.get(i).getValue()));
+ }
+
+ // the number of parameters should be three: exp1, exp2, and the
option
+ if (oldExprs.size() != 3) {
+ throw new AlgebricksException(
+ AsterixBuiltinFunctions.FULLTEXT_CONTAINS.getName() +
" should have three parameters.");
+ }
+
+ checkFirstAndSecondParamter(oldExprs);
+
+ checkAndSetDefaultValueForThirdParameter(oldExprs.get(2),
newExprs);
+
+ // Reset the argument
+ funcExp.getArguments().clear();
+ funcExp.getArguments().addAll(newExprs);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Checks the correctness of the first and second argument. If the
argument is a constant, we can check
+ * it now. If the argument is not a constant, we will defer the checking
until run-time.
+ */
+ void checkFirstAndSecondParamter(List<Mutable<ILogicalExpression>> exprs)
throws AlgebricksException {
+ // Check the first parameter - Expression1. If it's a constant, then
we can check the type here.
+ ILogicalExpression firstExpr = exprs.get(0).getValue();
+ if (firstExpr.getExpressionTag() == LogicalExpressionTag.CONSTANT
+ && ConstantExpressionUtil.getConstantIaObjectType(firstExpr)
!= ATypeTag.STRING) {
+ throw new AlgebricksException("The first expression of "
+ + AsterixBuiltinFunctions.FULLTEXT_CONTAINS.getName() + "
should be a string.");
+ }
+
+ // Check the second parameter - Expression2. If it's a constant, then
we can check the type here.
+ ILogicalExpression secondExpr = exprs.get(1).getValue();
+ if (secondExpr.getExpressionTag() == LogicalExpressionTag.CONSTANT) {
+ ATypeTag exprTypeTag =
ConstantExpressionUtil.getConstantIaObjectType(secondExpr);
+ switch (exprTypeTag) {
+ case STRING:
+ case UNORDEREDLIST:
+ case ORDEREDLIST:
+ break;
+ default:
+ throw new AlgebricksException(
+ "The second expression of " +
AsterixBuiltinFunctions.FULLTEXT_CONTAINS.getName()
+ + "should be a string, an unordered list,
or an ordered list.");
+ }
+ }
+ }
+
+ /**
+ * Checks the option of the given ftcontains() function. Also, sets
default value.
+ *
+ * @param expr
+ * @throws AlgebricksException
+ */
+ void checkAndSetDefaultValueForThirdParameter(Mutable<ILogicalExpression>
expr,
+ List<Mutable<ILogicalExpression>> newArgs) throws
AlgebricksException {
+ // Get the last parameter - this should be a record-constructor.
+ AbstractFunctionCallExpression openRecConsExpr =
(AbstractFunctionCallExpression) expr.getValue();
+ FunctionIdentifier openRecConsFi =
openRecConsExpr.getFunctionIdentifier();
+ if (openRecConsFi != AsterixBuiltinFunctions.OPEN_RECORD_CONSTRUCTOR
+ && openRecConsFi !=
AsterixBuiltinFunctions.CLOSED_RECORD_CONSTRUCTOR) {
+ throw new AlgebricksException("ftcontains() option should be the
form of a record { }.");
+ }
+
+ // We multiply 2 because the layout of the arguments are: [expr, val,
expr1, val1, ...]
+ if (openRecConsExpr.getArguments().size() >
FullTextContainsDescriptor.getParamTypeMap().size() * 2) {
+ throw new AlgebricksException("Too many options were specified.");
+ }
+
+ for (int i = 0; i < openRecConsExpr.getArguments().size(); i = i + 2) {
+ ILogicalExpression optionExpr =
openRecConsExpr.getArguments().get(i).getValue();
+ ILogicalExpression optionExprVal =
openRecConsExpr.getArguments().get(i + 1).getValue();
+
+ if (optionExpr.getExpressionTag() !=
LogicalExpressionTag.CONSTANT) {
+ throw new AlgebricksException(
+ "Options must be in the form of constant strings.
Check that the option at " + (i % 2 + 1)
+ + " is indeed a constant string");
+ }
+
+ String option =
ConstantExpressionUtil.getStringArgument(openRecConsExpr, i).toLowerCase();
+ if
(!FullTextContainsDescriptor.getParamTypeMap().containsKey(option)) {
+ throw new AlgebricksException(
+ "The given option " + option + " is not a valid
argument to ftcontains()");
+ }
+
+ boolean typeError = false;
+ String optionTypeStringVal = null;
+
+ // If the option value is a constant, then we can check here.
+ if (optionExprVal.getExpressionTag() ==
LogicalExpressionTag.CONSTANT) {
+ switch
(FullTextContainsDescriptor.getParamTypeMap().get(option)) {
+ case STRING:
+ optionTypeStringVal =
ConstantExpressionUtil.getStringArgument(openRecConsExpr, i + 1)
+ .toLowerCase();
+ if (optionTypeStringVal == null) {
+ typeError = true;
+ }
+ break;
+ default:
+ // Currently, we only have a string parameter. So, the
flow doesn't reach here.
+ typeError = true;
+ break;
+ }
+ }
+
+ if (typeError) {
+ throw new AlgebricksException(
+ "The given value for option " + option + " was not of
the expected type");
+ }
+
+ // Check the validity of option value
+ switch (option) {
+ case FullTextContainsDescriptor.SEARCH_MODE_OPTION:
+ checkSearchModeOption(optionTypeStringVal);
+ break;
+ default:
+ break;
+ }
+
+ // Add this option as arguments to the ftcontains().
+ newArgs.add(new MutableObject<ILogicalExpression>(optionExpr));
+ newArgs.add(new MutableObject<ILogicalExpression>(optionExprVal));
+ }
+ }
+
+ void checkSearchModeOption(String optionVal) throws AlgebricksException {
+ if
(optionVal.equals(FullTextContainsDescriptor.CONJUNCTIVE_SEARCH_MODE_OPTION)
+ ||
optionVal.equals(FullTextContainsDescriptor.DISJUNCTIVE_SEARCH_MODE_OPTION)) {
+ return;
+ } else {
+ throw new AlgebricksException("The given value for the search mode
(" + optionVal
+ + ") is not valid. Valid modes are " +
FullTextContainsDescriptor.CONJUNCTIVE_SEARCH_MODE_OPTION
+ + " or " +
FullTextContainsDescriptor.DISJUNCTIVE_SEARCH_MODE_OPTION + ".");
+ }
+ }
+}
diff --git a/asterixdb/asterix-doc/src/site/site.xml
b/asterixdb/asterix-doc/src/site/site.xml
index 4c0ba6e..24d06c2 100644
--- a/asterixdb/asterix-doc/src/site/site.xml
+++ b/asterixdb/asterix-doc/src/site/site.xml
@@ -100,6 +100,7 @@
<menu name="Advanced Features">
<item name="Support of Similarity Queries" href="aql/similarity.html"/>
+ <item name="AQL Support of Full-text Queries" href="aql/fulltext.html"/>
<item name="Accessing External Data" href="aql/externaldata.html"/>
<item name="Support for Data Ingestion" href="feeds/tutorial.html"/>
<item name="User Defined Functions" href="udf.html"/>
--
To view, visit https://asterix-gerrit.ics.uci.edu/1383
To unsubscribe, visit https://asterix-gerrit.ics.uci.edu/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Idec6b602ff7797846fd237a924005031c2395346
Gerrit-PatchSet: 1
Gerrit-Project: asterixdb
Gerrit-Branch: master
Gerrit-Owner: Taewoo Kim <[email protected]>