Taewoo Kim has submitted this change and it was merged.

Change subject: [ASTERIXDB-2153][COMP][RT] Ensure the fulltext search option is 
properly handled
......................................................................


[ASTERIXDB-2153][COMP][RT] Ensure the fulltext search option is properly handled

- user model changes: no
- storage format changes: no
- interface changes: no

details:
When a fulltext search operation is combined with multiple
other predicates, the fulltext search option was not handled
properly. This patch set ensures that the fulltext search option
is correctly handled.

Change-Id: I240fbe08891d29532c6fcd60638a3b6bbe8da771
Reviewed-on: https://asterix-gerrit.ics.uci.edu/2116
Sonar-Qube: Jenkins <jenk...@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenk...@fulliautomatix.ics.uci.edu>
Contrib: Jenkins <jenk...@fulliautomatix.ics.uci.edu>
Reviewed-by: Taewoo Kim <wangs...@gmail.com>
Integration-Tests: Jenkins <jenk...@fulliautomatix.ics.uci.edu>
---
M 
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/FullTextContainsParameterCheckRule.java
M 
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/InvertedIndexAccessMethod.java
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.1.ddl.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.2.update.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.3.query.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.4.query.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.5.query.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.6.query.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.7.query.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.8.query.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.1.ddl.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.2.update.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.3.query.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.4.query.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.5.query.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.6.query.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.7.query.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.8.query.sqlpp
A 
asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-09/fulltext-09.3.adm
A 
asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-09/fulltext-09.4.adm
A 
asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-09/fulltext-09.5.adm
A 
asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-09/fulltext-09.6.adm
A 
asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-09/fulltext-09.7.adm
A 
asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-09/fulltext-09.8.adm
A 
asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-index-08/fulltext-index-02.8.adm
A 
asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-index-08/fulltext-index-08.3.adm
A 
asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-index-08/fulltext-index-08.4.adm
A 
asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-index-08/fulltext-index-08.5.adm
A 
asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-index-08/fulltext-index-08.6.adm
A 
asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-index-08/fulltext-index-08.7.adm
M asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
M 
asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
M asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
M 
asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/common/FullTextContainsEvaluator.java
34 files changed, 961 insertions(+), 205 deletions(-)

Approvals:
  Taewoo Kim: Looks good to me, approved
  Jenkins: Verified; No violations found; ; Verified



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
index 42cea34..8bd3d79 100644
--- 
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
@@ -19,9 +19,10 @@
 package org.apache.asterix.optimizer.rules;
 
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 
+import org.apache.asterix.common.exceptions.CompilationException;
+import org.apache.asterix.common.exceptions.ErrorCode;
 import org.apache.asterix.om.base.AString;
 import org.apache.asterix.om.constants.AsterixConstantValue;
 import org.apache.asterix.om.functions.BuiltinFunctions;
@@ -36,12 +37,12 @@
 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.expressions.AbstractFunctionCallExpression;
+import 
org.apache.hyracks.algebricks.core.algebra.expressions.AbstractLogicalExpression;
 import 
org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
 import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
-import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator;
 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.algebra.visitors.ILogicalExpressionReferenceTransform;
 import org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
 
 /**
@@ -49,38 +50,16 @@
  */
 public class FullTextContainsParameterCheckRule implements 
IAlgebraicRewriteRule {
 
-    // parameter name and its value
-    HashMap<MutableObject<ILogicalExpression>, 
MutableObject<ILogicalExpression>> paramValueMap;
-
-    // the last expression position before the option argument in the 
arguments array
-    private static final int LAST_EXPRESSION_POS_BEFORE_OPTION = 1;
-    // The number of anticipated arguments for a full-text query when a user 
doesn't provide any option.
-    private static final int FULLTEXT_QUERY_WITHOUT_OPTION_NO_OF_ARGUMENTS = 2;
-    // The number of anticipated arguments for a full-text query when a user 
provide option(s) as a record.
-    private static final int FULLTEXT_QUERY_WITH_OPTION_NO_OF_ARGUMENTS = 3;
+    // Visitor for checking and transforming ftcontains() expression
+    protected FullTextContainsExpressionVisitor ftcontainsExprVisitor = new 
FullTextContainsExpressionVisitor();
 
     @Override
-    public boolean rewritePost(Mutable<ILogicalOperator> opRef, 
IOptimizationContext context)
+    public boolean rewritePre(Mutable<ILogicalOperator> opRef, 
IOptimizationContext context)
             throws AlgebricksException {
-        AbstractLogicalOperator op = (AbstractLogicalOperator) 
opRef.getValue();
-        Mutable<ILogicalExpression> exprRef;
-        switch (op.getOperatorTag()) {
-            case SELECT:
-                exprRef = ((SelectOperator) op).getCondition();
-                break;
-            case INNERJOIN:
-            case LEFTOUTERJOIN:
-                exprRef = ((AbstractBinaryJoinOperator) op).getCondition();
-                break;
-            default:
-                return false;
-        }
-
-        if (context.checkIfInDontApplySet(this, op)) {
+        if (context.checkIfInDontApplySet(this, opRef.getValue())) {
             return false;
         }
-
-        if (checkParamter(op, exprRef, context)) {
+        if (checkParameter(opRef, context)) {
             OperatorPropertiesUtil.typeOpRec(opRef, context);
             return true;
         }
@@ -91,199 +70,234 @@
      * Check the correctness of the parameters of the ftcontains(). Also 
rearrange options as arguments.
      * The expected form of ftcontains() is ftcontains(expression1, 
expression2, parameters as a record).
      */
-    private boolean checkParamter(ILogicalOperator op, 
Mutable<ILogicalExpression> exprRef,
-            IOptimizationContext context) throws AlgebricksException {
-        ILogicalExpression expr = exprRef.getValue();
+    private boolean checkParameter(Mutable<ILogicalOperator> opRef, 
IOptimizationContext context)
+            throws AlgebricksException {
+        AbstractLogicalOperator op = (AbstractLogicalOperator) 
opRef.getValue();
+        boolean modified = op.acceptExpressionTransform(ftcontainsExprVisitor);
+        if (modified) {
+            context.addToDontApplySet(this, op);
+        }
+        return modified;
+    }
 
-        if (expr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
+
+    /**
+     * This visitor class handles actual checking and transformation.
+     */
+    protected class FullTextContainsExpressionVisitor implements 
ILogicalExpressionReferenceTransform {
+
+        // the last expression position before the option argument in the 
arguments array
+        private static final int LAST_EXPRESSION_POS_BEFORE_OPTION = 1;
+        // The number of anticipated arguments for a full-text query when a 
user doesn't provide any option.
+        private static final int FULLTEXT_QUERY_WITHOUT_OPTION_NO_OF_ARGUMENTS 
= 2;
+        // The number of anticipated arguments for a full-text query when a 
user provide option(s) as a record.
+        private static final int FULLTEXT_QUERY_WITH_OPTION_NO_OF_ARGUMENTS = 
3;
+
+        public FullTextContainsExpressionVisitor() {
+            // no parameter is needed.
+        }
+
+        @Override
+        public boolean transform(Mutable<ILogicalExpression> exprRef) throws 
AlgebricksException {
+            ILogicalExpression e = exprRef.getValue();
+            switch (((AbstractLogicalExpression) e).getExpressionTag()) {
+                case FUNCTION_CALL:
+                    return 
transformFunctionCallExpression((AbstractFunctionCallExpression) e);
+                default:
+                    return false;
+            }
+        }
+
+        private boolean 
transformFunctionCallExpression(AbstractFunctionCallExpression fce) throws 
AlgebricksException {
+            boolean modified = false;
+            FunctionIdentifier fi = fce.getFunctionIdentifier();
+            if (fi != BuiltinFunctions.FULLTEXT_CONTAINS && fi != 
BuiltinFunctions.FULLTEXT_CONTAINS_WO_OPTION) {
+                for (Mutable<ILogicalExpression> arg : fce.getArguments()) {
+                    if (transform(arg)) {
+                        modified = true;
+                    }
+                }
+            } else {
+                modified = checkParameterForFuncExpr(fce, fi);
+            }
+
+            return modified;
+        }
+
+        private boolean 
checkParameterForFuncExpr(AbstractFunctionCallExpression funcExpr, 
FunctionIdentifier fi)
+                throws AlgebricksException {
+            // Collects the correct number of arguments - it can be 2 if a 
user doesn't provide any option.
+            int numberOfCorrectArguments = 0;
+            String functionName = "";
+            if (fi == BuiltinFunctions.FULLTEXT_CONTAINS) {
+                numberOfCorrectArguments = 
FULLTEXT_QUERY_WITH_OPTION_NO_OF_ARGUMENTS;
+                functionName = BuiltinFunctions.FULLTEXT_CONTAINS.getName();
+            } else if (fi == BuiltinFunctions.FULLTEXT_CONTAINS_WO_OPTION) {
+                numberOfCorrectArguments = 
FULLTEXT_QUERY_WITHOUT_OPTION_NO_OF_ARGUMENTS;
+                functionName = 
BuiltinFunctions.FULLTEXT_CONTAINS_WO_OPTION.getName();
+            }
+
+            // If numberOfCorrectArguments is greater than zero, then this is 
a full-text search query.
+            if (numberOfCorrectArguments > 0) {
+
+                List<Mutable<ILogicalExpression>> oldExprs = 
funcExpr.getArguments();
+                List<Mutable<ILogicalExpression>> newExprs = new ArrayList<>();
+
+                // The number of parameters should be three: exp1, exp2, and 
the option
+                if (oldExprs.size() != numberOfCorrectArguments) {
+                    throw 
CompilationException.create(ErrorCode.COMPILATION_INVALID_PARAMETER_NUMBER, fi,
+                            oldExprs.size());
+                }
+
+                // The last expression before the option needs to be copied 
first.
+                for (int i = 0; i <= LAST_EXPRESSION_POS_BEFORE_OPTION; i++) {
+                    newExprs.add(new 
MutableObject<ILogicalExpression>(oldExprs.get(i).getValue()));
+                }
+
+                // Sanity check for the types of the first two parameters
+                checkFirstAndSecondParamter(oldExprs, functionName);
+
+                // Checks and transforms the actual full-text parameters.
+                if (numberOfCorrectArguments == 
FULLTEXT_QUERY_WITH_OPTION_NO_OF_ARGUMENTS) {
+                    checkValueForThirdParameter(oldExprs.get(2), newExprs, 
functionName);
+                } else {
+                    // no option provided case: sets the default option here.
+                    setDefaultValueForThirdParameter(newExprs);
+                }
+
+                // Resets the last argument.
+                funcExpr.getArguments().clear();
+                funcExpr.getArguments().addAll(newExprs);
+
+                return true;
+            }
+
             return false;
         }
 
-        AbstractFunctionCallExpression funcExpr = 
(AbstractFunctionCallExpression) expr;
-        FunctionIdentifier fi = funcExpr.getFunctionIdentifier();
-
-        // Collects the correct number of arguments - it can be 2 if a user 
doesn't provide any option.
-        int numberOfCorrectArguments = 0;
-        String functionName = "";
-        if (fi == BuiltinFunctions.FULLTEXT_CONTAINS) {
-            numberOfCorrectArguments = 
FULLTEXT_QUERY_WITH_OPTION_NO_OF_ARGUMENTS;
-            functionName = BuiltinFunctions.FULLTEXT_CONTAINS.getName();
-        } else if (fi == BuiltinFunctions.FULLTEXT_CONTAINS_WO_OPTION) {
-            numberOfCorrectArguments = 
FULLTEXT_QUERY_WITHOUT_OPTION_NO_OF_ARGUMENTS;
-            functionName = 
BuiltinFunctions.FULLTEXT_CONTAINS_WO_OPTION.getName();
-        }
-
-        // If numberOfCorrectArguments is greater than zero, then this is a 
full-text search query.
-        if (numberOfCorrectArguments > 0) {
-            // Don't need to check this operator again.
-            context.addToDontApplySet(this, op);
-
-            List<Mutable<ILogicalExpression>> oldExprs = 
funcExpr.getArguments();
-            List<Mutable<ILogicalExpression>> newExprs = new ArrayList<>();
-
-            // The number of parameters should be three: exp1, exp2, and the 
option
-            if (oldExprs.size() != numberOfCorrectArguments) {
-                throw new AlgebricksException(
-                        functionName + " should have " + 
numberOfCorrectArguments + " parameters.");
+        /**
+         * 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.
+         */
+        private void 
checkFirstAndSecondParamter(List<Mutable<ILogicalExpression>> exprs, String 
functionName)
+                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 CompilationException.create(ErrorCode.TYPE_UNSUPPORTED, 
functionName,
+                        
ConstantExpressionUtil.getConstantIaObjectType(firstExpr));
             }
 
-            // The last expression before the option needs to be copied first.
-            for (int i = 0; i <= LAST_EXPRESSION_POS_BEFORE_OPTION; i++) {
-                newExprs.add(new 
MutableObject<ILogicalExpression>((ILogicalExpression) 
oldExprs.get(i).getValue()));
-            }
-
-            // Sanity check for the types of the first two parameters
-            checkFirstAndSecondParamter(oldExprs, functionName);
-
-            // Checks and transforms the actual full-text parameters.
-            if (numberOfCorrectArguments == 
FULLTEXT_QUERY_WITH_OPTION_NO_OF_ARGUMENTS) {
-                checkValueForThirdParameter(oldExprs.get(2), newExprs);
-            } else {
-                // no option provided case: sets the default option here.
-                setDefaultValueForThirdParameter(newExprs);
-            }
-
-            // Resets the last argument.
-            funcExpr.getArguments().clear();
-            funcExpr.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, 
String functionName)
-            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 " + 
functionName + " 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 MULTISET:
-                case ARRAY:
-                    break;
-                default:
-                    throw new AlgebricksException("The second expression of " 
+ functionName
-                            + "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 checkValueForThirdParameter(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 != BuiltinFunctions.OPEN_RECORD_CONSTRUCTOR
-                && openRecConsFi != 
BuiltinFunctions.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)) {
+            // 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:
-                        optionTypeStringVal = 
ConstantExpressionUtil.getStringArgument(openRecConsExpr, i + 1)
-                                .toLowerCase();
-                        if (optionTypeStringVal == null) {
-                            typeError = true;
-                        }
+                    case MULTISET:
+                    case ARRAY:
                         break;
                     default:
-                        // Currently, we only have a string parameter. So, the 
flow doesn't reach here.
-                        typeError = true;
-                        break;
+                        throw 
CompilationException.create(ErrorCode.TYPE_UNSUPPORTED, functionName, 
exprTypeTag);
                 }
             }
+        }
 
-            if (typeError) {
-                throw new AlgebricksException(
-                        "The given value for option " + option + " was not of 
the expected type");
+        /**
+         * Checks the option of the given ftcontains() function. Also, sets 
default value.
+         *
+         * @param expr
+         * @throws AlgebricksException
+         */
+        private void checkValueForThirdParameter(Mutable<ILogicalExpression> 
expr,
+                List<Mutable<ILogicalExpression>> newArgs, String 
functionName) throws AlgebricksException {
+            // Get the last parameter - this should be a record-constructor.
+            AbstractFunctionCallExpression openRecConsExpr = 
(AbstractFunctionCallExpression) expr.getValue();
+            FunctionIdentifier openRecConsFi = 
openRecConsExpr.getFunctionIdentifier();
+            if (openRecConsFi != BuiltinFunctions.OPEN_RECORD_CONSTRUCTOR
+                    && openRecConsFi != 
BuiltinFunctions.CLOSED_RECORD_CONSTRUCTOR) {
+                throw CompilationException.create(ErrorCode.TYPE_UNSUPPORTED, 
functionName, openRecConsFi);
             }
 
-            // Check the validity of option value
-            switch (option) {
-                case FullTextContainsDescriptor.SEARCH_MODE_OPTION:
-                    checkSearchModeOption(optionTypeStringVal);
-                    break;
-                default:
-                    break;
+            // We multiply 2 because the layout of the arguments are: [expr, 
val, expr1, val1, ...]
+            if (openRecConsExpr.getArguments().size() > 
FullTextContainsDescriptor.getParamTypeMap().size() * 2) {
+                throw 
CompilationException.create(ErrorCode.TOO_MANY_OPTIONS_FOR_FUNCTION, 
functionName);
             }
+
+            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();
+
+                String option = 
ConstantExpressionUtil.getStringConstant(optionExpr);
+
+                if (optionExpr.getExpressionTag() != 
LogicalExpressionTag.CONSTANT || option == null) {
+                    throw 
CompilationException.create(ErrorCode.TYPE_UNSUPPORTED, functionName,
+                            optionExpr.getExpressionTag());
+                }
+
+                option = option.toLowerCase();
+                if 
(!FullTextContainsDescriptor.getParamTypeMap().containsKey(option)) {
+                    throw 
CompilationException.create(ErrorCode.TYPE_UNSUPPORTED, functionName, option);
+                }
+
+                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.getStringConstant(optionExprVal);
+                            if (optionTypeStringVal == null) {
+                                throw 
CompilationException.create(ErrorCode.TYPE_UNSUPPORTED, functionName, option);
+                            }
+                            optionTypeStringVal = 
optionTypeStringVal.toLowerCase();
+                            break;
+                        default:
+                            // Currently, we only have a string parameter. So, 
the flow doesn't reach here.
+                            throw 
CompilationException.create(ErrorCode.TYPE_UNSUPPORTED, functionName, option);
+                    }
+
+                    // Check the validity of option value
+                    switch (option) {
+                        case FullTextContainsDescriptor.SEARCH_MODE_OPTION:
+                            checkSearchModeOption(optionTypeStringVal, 
functionName);
+                            break;
+                        default:
+                            throw 
CompilationException.create(ErrorCode.TYPE_UNSUPPORTED, functionName, option);
+                    }
+                }
+
+                // Add this option as arguments to the ftcontains().
+                newArgs.add(new MutableObject<ILogicalExpression>(optionExpr));
+                newArgs.add(new 
MutableObject<ILogicalExpression>(optionExprVal));
+            }
+        }
+
+        private void checkSearchModeOption(String optionVal, String 
functionName) throws AlgebricksException {
+            if 
(optionVal.equals(FullTextContainsDescriptor.CONJUNCTIVE_SEARCH_MODE_OPTION)
+                    || 
optionVal.equals(FullTextContainsDescriptor.DISJUNCTIVE_SEARCH_MODE_OPTION)) {
+                return;
+            } else {
+                throw CompilationException.create(ErrorCode.TYPE_UNSUPPORTED, 
functionName, optionVal);
+            }
+        }
+
+        /**
+         * Sets the default option value(s) when a user doesn't provide any 
option.
+         */
+        void 
setDefaultValueForThirdParameter(List<Mutable<ILogicalExpression>> newArgs) 
throws AlgebricksException {
+            // Sets the search mode option: the default option is conjunctive 
search.
+            ILogicalExpression searchModeOptionExpr = new ConstantExpression(
+                    new AsterixConstantValue(new 
AString(FullTextContainsDescriptor.SEARCH_MODE_OPTION)));
+            ILogicalExpression searchModeValExpr = new ConstantExpression(
+                    new AsterixConstantValue(new 
AString(FullTextContainsDescriptor.CONJUNCTIVE_SEARCH_MODE_OPTION)));
 
             // Add this option as arguments to the ftcontains().
-            newArgs.add(new MutableObject<ILogicalExpression>(optionExpr));
-            newArgs.add(new MutableObject<ILogicalExpression>(optionExprVal));
+            newArgs.add(new 
MutableObject<ILogicalExpression>(searchModeOptionExpr));
+            newArgs.add(new 
MutableObject<ILogicalExpression>(searchModeValExpr));
         }
-    }
 
-    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 + ".");
-        }
-    }
-
-    /**
-     * Sets the default option value(s) when a user doesn't provide any option.
-     */
-    void setDefaultValueForThirdParameter(List<Mutable<ILogicalExpression>> 
newArgs)
-            throws AlgebricksException {
-        // Sets the search mode option: the default option is conjunctive 
search.
-        ILogicalExpression searchModeOptionExpr = new ConstantExpression(
-                new AsterixConstantValue(new 
AString(FullTextContainsDescriptor.SEARCH_MODE_OPTION)));
-        ILogicalExpression searchModeValExpr = new ConstantExpression(
-                new AsterixConstantValue(new 
AString(FullTextContainsDescriptor.CONJUNCTIVE_SEARCH_MODE_OPTION)));
-
-        // Add this option as arguments to the ftcontains().
-        newArgs.add(new 
MutableObject<ILogicalExpression>(searchModeOptionExpr));
-        newArgs.add(new MutableObject<ILogicalExpression>(searchModeValExpr));
     }
 
 }
diff --git 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/InvertedIndexAccessMethod.java
 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/InvertedIndexAccessMethod.java
index 8e09164..d1506f7 100644
--- 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/InvertedIndexAccessMethod.java
+++ 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/InvertedIndexAccessMethod.java
@@ -877,7 +877,7 @@
     private static SearchModifierType 
getFullTextOption(AbstractFunctionCallExpression funcExpr) {
         if (funcExpr.getArguments().size() < 3 || 
funcExpr.getArguments().size() % 2 != 0) {
             // If no parameters or incorrect number of parameters are given, 
the default search type is returned.
-            return SearchModifierType.DISJUNCTIVE;
+            return SearchModifierType.CONJUNCTIVE;
         }
         // From the third argument, it contains full-text search options.
         for (int i = 2; i < funcExpr.getArguments().size(); i = i + 2) {
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.1.ddl.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.1.ddl.sqlpp
new file mode 100644
index 0000000..c201040
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.1.ddl.sqlpp
@@ -0,0 +1,58 @@
+/*
+ * 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     : Full-text search non-index test
+ *                  : This test is intended to verify that the full-text 
search works as expected
+ *                  : with multiple conditions.
+ *                  : query #3 - two string values in [an ordered list] query 
with "any" option
+ *                  :            in this case, "any" option that enforces a 
disjunctive search will be applied.
+ *                  : query #4 - the same as query #3, but with a different 
option - "all"
+ *                  :            in this case, we explicitly specify "all" 
option that enforces a conjunctive search.
+ *                  : query #5 - two string values in {{an unordered list}} 
query with "any" option
+ *                  :            in this case, "any" option that enforces a 
disjunctive search will be applied.
+ *                  : query #6 - the same as query #6, but with a different 
option - "all"
+ *                  :            in this case, we explicitly specify "all" 
option that enforces a conjunctive search.
+ *                  : query #7 - the same as query #4, but without any option 
that is equivalent to "all".
+ *                  : query #8 - the same as query #6, but without any option 
that is equivalent to "all".
+ *  Expected Result : Success
+ *
+*/
+
+drop dataverse test if exists;
+create dataverse test;
+use test;
+
+create type MyRecord as closed {
+  id: int64,
+  docid: int64,
+  val1: int64,
+  title: string,
+  point: point,
+  kwds: string,
+  line1: line,
+  line2: line,
+  poly1: polygon,
+  poly2: polygon,
+  rec: rectangle,
+  circle: circle
+};
+
+create dataset MyData(MyRecord)
+  primary key id;
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.2.update.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.2.update.sqlpp
new file mode 100644
index 0000000..9b7c1f6
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.2.update.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use test;
+
+load dataset MyData
+using localfs
+(("path"="asterix_nc1://data/spatial/spatialData2.json"),("format"="adm"));
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.3.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.3.query.sqlpp
new file mode 100644
index 0000000..02d27ab
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.3.query.sqlpp
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use test;
+
+select element {"id":ftval.id}
+from MyData as ftval
+where test.ftcontains(ftval.title, ["object","database"], {"mode":"any"}) and 
ftval.val1 > 0 and ftval.val1 < 200
+order by ftval.id;
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.4.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.4.query.sqlpp
new file mode 100644
index 0000000..f495022
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.4.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+use test;
+
+select element {"id":ftval.id}
+from MyData as ftval
+where test.ftcontains(ftval.title, ["object","database"], {"mode":"all"}) and 
ftval.val1 > 0 and ftval.val1 < 200
+order by ftval.id;
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.5.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.5.query.sqlpp
new file mode 100644
index 0000000..8bf8eba
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.5.query.sqlpp
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use test;
+
+select element {"id":ftval.id}
+from MyData as ftval
+where test.ftcontains(ftval.title, {{"object","database"}}, {"mode":"any"}) 
and ftval.val1 > 0 and ftval.val1 < 200
+order by ftval.id;
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.6.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.6.query.sqlpp
new file mode 100644
index 0000000..6a2c2ba
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.6.query.sqlpp
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use test;
+
+select element {"id":ftval.id}
+from MyData as ftval
+where test.ftcontains(ftval.title, {{"object","database"}}, {"mode":"all"}) 
and ftval.val1 > 0 and ftval.val1 < 200
+order by ftval.id;
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.7.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.7.query.sqlpp
new file mode 100644
index 0000000..14ec94f
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.7.query.sqlpp
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use test;
+
+select element {"id":ftval.id}
+from MyData as ftval
+where test.ftcontains(ftval.title, ["object","database"]) and ftval.val1 > 0 
and ftval.val1 < 200
+order by ftval.id;
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.8.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.8.query.sqlpp
new file mode 100644
index 0000000..c770842
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-09/fulltext-09.8.query.sqlpp
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use test;
+
+select element {"id":ftval.id}
+from MyData as ftval
+where test.ftcontains(ftval.title, {{"object","database"}}) and ftval.val1 > 0 
and ftval.val1 < 200
+order by ftval.id;
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.1.ddl.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.1.ddl.sqlpp
new file mode 100644
index 0000000..5848e28
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.1.ddl.sqlpp
@@ -0,0 +1,60 @@
+/*
+ * 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     : Full-text search index test
+ *                  : This test is intended to verify that the full-text 
search works as expected
+ *                  : with multiple conditions.
+ *                  : query #3 - two string values in [an ordered list] query 
with "any" option
+ *                  :            in this case, "any" option that enforces a 
disjunctive search will be applied.
+ *                  : query #4 - the same as query #3, but with a different 
option - "all"
+ *                  :            in this case, we explicitly specify "all" 
option that enforces a conjunctive search.
+ *                  : query #5 - two string values in {{an unordered list}} 
query with "any" option
+ *                  :            in this case, "any" option that enforces a 
disjunctive search will be applied.
+ *                  : query #6 - the same as query #6, but with a different 
option - "all"
+ *                  :            in this case, we explicitly specify "all" 
option that enforces a conjunctive search.
+ *                  : query #7 - the same as query #4, but without any option 
that is equivalent to "all".
+ *                  : query #8 - the same as query #6, but without any option 
that is equivalent to "all".
+ *  Expected Result : Success
+ *
+*/
+
+drop dataverse test if exists;
+create dataverse test;
+use test;
+
+create type MyRecord as closed {
+  id: int64,
+  docid: int64,
+  val1: int64,
+  title: string,
+  point: point,
+  kwds: string,
+  line1: line,
+  line2: line,
+  poly1: polygon,
+  poly2: polygon,
+  rec: rectangle,
+  circle: circle
+};
+
+create dataset MyData(MyRecord)
+  primary key id;
+
+create index fulltext_index_title on MyData(title) type fulltext;
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.2.update.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.2.update.sqlpp
new file mode 100644
index 0000000..9b7c1f6
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.2.update.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use test;
+
+load dataset MyData
+using localfs
+(("path"="asterix_nc1://data/spatial/spatialData2.json"),("format"="adm"));
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.3.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.3.query.sqlpp
new file mode 100644
index 0000000..02d27ab
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.3.query.sqlpp
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use test;
+
+select element {"id":ftval.id}
+from MyData as ftval
+where test.ftcontains(ftval.title, ["object","database"], {"mode":"any"}) and 
ftval.val1 > 0 and ftval.val1 < 200
+order by ftval.id;
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.4.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.4.query.sqlpp
new file mode 100644
index 0000000..f495022
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.4.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+use test;
+
+select element {"id":ftval.id}
+from MyData as ftval
+where test.ftcontains(ftval.title, ["object","database"], {"mode":"all"}) and 
ftval.val1 > 0 and ftval.val1 < 200
+order by ftval.id;
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.5.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.5.query.sqlpp
new file mode 100644
index 0000000..8bf8eba
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.5.query.sqlpp
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use test;
+
+select element {"id":ftval.id}
+from MyData as ftval
+where test.ftcontains(ftval.title, {{"object","database"}}, {"mode":"any"}) 
and ftval.val1 > 0 and ftval.val1 < 200
+order by ftval.id;
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.6.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.6.query.sqlpp
new file mode 100644
index 0000000..6a2c2ba
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.6.query.sqlpp
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use test;
+
+select element {"id":ftval.id}
+from MyData as ftval
+where test.ftcontains(ftval.title, {{"object","database"}}, {"mode":"all"}) 
and ftval.val1 > 0 and ftval.val1 < 200
+order by ftval.id;
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.7.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.7.query.sqlpp
new file mode 100644
index 0000000..14ec94f
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.7.query.sqlpp
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use test;
+
+select element {"id":ftval.id}
+from MyData as ftval
+where test.ftcontains(ftval.title, ["object","database"]) and ftval.val1 > 0 
and ftval.val1 < 200
+order by ftval.id;
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.8.query.sqlpp
 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.8.query.sqlpp
new file mode 100644
index 0000000..c770842
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/fulltext/fulltext-index-08/fulltext-index-08.8.query.sqlpp
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+use test;
+
+select element {"id":ftval.id}
+from MyData as ftval
+where test.ftcontains(ftval.title, {{"object","database"}}) and ftval.val1 > 0 
and ftval.val1 < 200
+order by ftval.id;
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-09/fulltext-09.3.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-09/fulltext-09.3.adm
new file mode 100644
index 0000000..9b34c44
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-09/fulltext-09.3.adm
@@ -0,0 +1,38 @@
+{ "id": 1 }
+{ "id": 2 }
+{ "id": 5 }
+{ "id": 6 }
+{ "id": 8 }
+{ "id": 11 }
+{ "id": 12 }
+{ "id": 13 }
+{ "id": 16 }
+{ "id": 17 }
+{ "id": 19 }
+{ "id": 20 }
+{ "id": 21 }
+{ "id": 22 }
+{ "id": 23 }
+{ "id": 26 }
+{ "id": 27 }
+{ "id": 29 }
+{ "id": 30 }
+{ "id": 31 }
+{ "id": 32 }
+{ "id": 35 }
+{ "id": 36 }
+{ "id": 38 }
+{ "id": 41 }
+{ "id": 42 }
+{ "id": 43 }
+{ "id": 46 }
+{ "id": 47 }
+{ "id": 49 }
+{ "id": 50 }
+{ "id": 51 }
+{ "id": 52 }
+{ "id": 53 }
+{ "id": 56 }
+{ "id": 57 }
+{ "id": 59 }
+{ "id": 60 }
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-09/fulltext-09.4.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-09/fulltext-09.4.adm
new file mode 100644
index 0000000..acde73f
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-09/fulltext-09.4.adm
@@ -0,0 +1,14 @@
+{ "id": 8 }
+{ "id": 13 }
+{ "id": 16 }
+{ "id": 19 }
+{ "id": 23 }
+{ "id": 26 }
+{ "id": 29 }
+{ "id": 38 }
+{ "id": 43 }
+{ "id": 46 }
+{ "id": 49 }
+{ "id": 53 }
+{ "id": 56 }
+{ "id": 59 }
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-09/fulltext-09.5.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-09/fulltext-09.5.adm
new file mode 100644
index 0000000..9b34c44
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-09/fulltext-09.5.adm
@@ -0,0 +1,38 @@
+{ "id": 1 }
+{ "id": 2 }
+{ "id": 5 }
+{ "id": 6 }
+{ "id": 8 }
+{ "id": 11 }
+{ "id": 12 }
+{ "id": 13 }
+{ "id": 16 }
+{ "id": 17 }
+{ "id": 19 }
+{ "id": 20 }
+{ "id": 21 }
+{ "id": 22 }
+{ "id": 23 }
+{ "id": 26 }
+{ "id": 27 }
+{ "id": 29 }
+{ "id": 30 }
+{ "id": 31 }
+{ "id": 32 }
+{ "id": 35 }
+{ "id": 36 }
+{ "id": 38 }
+{ "id": 41 }
+{ "id": 42 }
+{ "id": 43 }
+{ "id": 46 }
+{ "id": 47 }
+{ "id": 49 }
+{ "id": 50 }
+{ "id": 51 }
+{ "id": 52 }
+{ "id": 53 }
+{ "id": 56 }
+{ "id": 57 }
+{ "id": 59 }
+{ "id": 60 }
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-09/fulltext-09.6.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-09/fulltext-09.6.adm
new file mode 100644
index 0000000..acde73f
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-09/fulltext-09.6.adm
@@ -0,0 +1,14 @@
+{ "id": 8 }
+{ "id": 13 }
+{ "id": 16 }
+{ "id": 19 }
+{ "id": 23 }
+{ "id": 26 }
+{ "id": 29 }
+{ "id": 38 }
+{ "id": 43 }
+{ "id": 46 }
+{ "id": 49 }
+{ "id": 53 }
+{ "id": 56 }
+{ "id": 59 }
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-09/fulltext-09.7.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-09/fulltext-09.7.adm
new file mode 100644
index 0000000..acde73f
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-09/fulltext-09.7.adm
@@ -0,0 +1,14 @@
+{ "id": 8 }
+{ "id": 13 }
+{ "id": 16 }
+{ "id": 19 }
+{ "id": 23 }
+{ "id": 26 }
+{ "id": 29 }
+{ "id": 38 }
+{ "id": 43 }
+{ "id": 46 }
+{ "id": 49 }
+{ "id": 53 }
+{ "id": 56 }
+{ "id": 59 }
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-09/fulltext-09.8.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-09/fulltext-09.8.adm
new file mode 100644
index 0000000..acde73f
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-09/fulltext-09.8.adm
@@ -0,0 +1,14 @@
+{ "id": 8 }
+{ "id": 13 }
+{ "id": 16 }
+{ "id": 19 }
+{ "id": 23 }
+{ "id": 26 }
+{ "id": 29 }
+{ "id": 38 }
+{ "id": 43 }
+{ "id": 46 }
+{ "id": 49 }
+{ "id": 53 }
+{ "id": 56 }
+{ "id": 59 }
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-index-08/fulltext-index-02.8.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-index-08/fulltext-index-02.8.adm
new file mode 100644
index 0000000..acde73f
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-index-08/fulltext-index-02.8.adm
@@ -0,0 +1,14 @@
+{ "id": 8 }
+{ "id": 13 }
+{ "id": 16 }
+{ "id": 19 }
+{ "id": 23 }
+{ "id": 26 }
+{ "id": 29 }
+{ "id": 38 }
+{ "id": 43 }
+{ "id": 46 }
+{ "id": 49 }
+{ "id": 53 }
+{ "id": 56 }
+{ "id": 59 }
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-index-08/fulltext-index-08.3.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-index-08/fulltext-index-08.3.adm
new file mode 100644
index 0000000..9b34c44
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-index-08/fulltext-index-08.3.adm
@@ -0,0 +1,38 @@
+{ "id": 1 }
+{ "id": 2 }
+{ "id": 5 }
+{ "id": 6 }
+{ "id": 8 }
+{ "id": 11 }
+{ "id": 12 }
+{ "id": 13 }
+{ "id": 16 }
+{ "id": 17 }
+{ "id": 19 }
+{ "id": 20 }
+{ "id": 21 }
+{ "id": 22 }
+{ "id": 23 }
+{ "id": 26 }
+{ "id": 27 }
+{ "id": 29 }
+{ "id": 30 }
+{ "id": 31 }
+{ "id": 32 }
+{ "id": 35 }
+{ "id": 36 }
+{ "id": 38 }
+{ "id": 41 }
+{ "id": 42 }
+{ "id": 43 }
+{ "id": 46 }
+{ "id": 47 }
+{ "id": 49 }
+{ "id": 50 }
+{ "id": 51 }
+{ "id": 52 }
+{ "id": 53 }
+{ "id": 56 }
+{ "id": 57 }
+{ "id": 59 }
+{ "id": 60 }
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-index-08/fulltext-index-08.4.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-index-08/fulltext-index-08.4.adm
new file mode 100644
index 0000000..acde73f
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-index-08/fulltext-index-08.4.adm
@@ -0,0 +1,14 @@
+{ "id": 8 }
+{ "id": 13 }
+{ "id": 16 }
+{ "id": 19 }
+{ "id": 23 }
+{ "id": 26 }
+{ "id": 29 }
+{ "id": 38 }
+{ "id": 43 }
+{ "id": 46 }
+{ "id": 49 }
+{ "id": 53 }
+{ "id": 56 }
+{ "id": 59 }
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-index-08/fulltext-index-08.5.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-index-08/fulltext-index-08.5.adm
new file mode 100644
index 0000000..9b34c44
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-index-08/fulltext-index-08.5.adm
@@ -0,0 +1,38 @@
+{ "id": 1 }
+{ "id": 2 }
+{ "id": 5 }
+{ "id": 6 }
+{ "id": 8 }
+{ "id": 11 }
+{ "id": 12 }
+{ "id": 13 }
+{ "id": 16 }
+{ "id": 17 }
+{ "id": 19 }
+{ "id": 20 }
+{ "id": 21 }
+{ "id": 22 }
+{ "id": 23 }
+{ "id": 26 }
+{ "id": 27 }
+{ "id": 29 }
+{ "id": 30 }
+{ "id": 31 }
+{ "id": 32 }
+{ "id": 35 }
+{ "id": 36 }
+{ "id": 38 }
+{ "id": 41 }
+{ "id": 42 }
+{ "id": 43 }
+{ "id": 46 }
+{ "id": 47 }
+{ "id": 49 }
+{ "id": 50 }
+{ "id": 51 }
+{ "id": 52 }
+{ "id": 53 }
+{ "id": 56 }
+{ "id": 57 }
+{ "id": 59 }
+{ "id": 60 }
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-index-08/fulltext-index-08.6.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-index-08/fulltext-index-08.6.adm
new file mode 100644
index 0000000..acde73f
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-index-08/fulltext-index-08.6.adm
@@ -0,0 +1,14 @@
+{ "id": 8 }
+{ "id": 13 }
+{ "id": 16 }
+{ "id": 19 }
+{ "id": 23 }
+{ "id": 26 }
+{ "id": 29 }
+{ "id": 38 }
+{ "id": 43 }
+{ "id": 46 }
+{ "id": 49 }
+{ "id": 53 }
+{ "id": 56 }
+{ "id": 59 }
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-index-08/fulltext-index-08.7.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-index-08/fulltext-index-08.7.adm
new file mode 100644
index 0000000..acde73f
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/fulltext/fulltext-index-08/fulltext-index-08.7.adm
@@ -0,0 +1,14 @@
+{ "id": 8 }
+{ "id": 13 }
+{ "id": 16 }
+{ "id": 19 }
+{ "id": 23 }
+{ "id": 26 }
+{ "id": 29 }
+{ "id": 38 }
+{ "id": 43 }
+{ "id": 46 }
+{ "id": 49 }
+{ "id": 53 }
+{ "id": 56 }
+{ "id": 59 }
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 a55d435..f0ad1a4 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -2737,6 +2737,11 @@
       </compilation-unit>
     </test-case>
     <test-case FilePath="fulltext">
+      <compilation-unit name="fulltext-09">
+        <output-dir compare="Text">fulltext-09</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="fulltext">
       <compilation-unit name="fulltext-index-01">
         <output-dir compare="Text">fulltext-index-01</output-dir>
       </compilation-unit>
@@ -2746,6 +2751,11 @@
         <output-dir compare="Text">fulltext-index-02</output-dir>
       </compilation-unit>
     </test-case>
+    <test-case FilePath="fulltext">
+      <compilation-unit name="fulltext-index-08">
+        <output-dir compare="Text">fulltext-index-08</output-dir>
+      </compilation-unit>
+    </test-case>
   </test-group>
   <test-group name="global-aggregate">
     <test-case FilePath="global-aggregate">
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 6d3b6c2..a4cf64a 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
@@ -132,6 +132,7 @@
     public static final int CANNOT_CREATE_SEC_PRIMARY_IDX_ON_EXT_DATASET = 
1053;
     public static final int COMPILATION_FAILED_DUE_TO_REPLICATE_OP = 1054;
     public static final int COMPILATION_INCOMPATIBLE_FUNCTION_LANGUAGE = 1055;
+    public static final int TOO_MANY_OPTIONS_FOR_FUNCTION = 1056;
 
     // 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 e428721..39a74ff 100644
--- a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
+++ b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
@@ -118,6 +118,7 @@
 1053 = Cannot create primary index on external dataset.
 1054 = Compilation failed due to some problem in the query plan.
 1055 = Incompatible function language. Expect %1$s, but %2$s found.
+1056 = Too many options were specified for %1$s
 
 # Feed Errors
 3001 = Illegal state.
diff --git 
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/common/FullTextContainsEvaluator.java
 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/common/FullTextContainsEvaluator.java
index a7160ac..b93d613 100644
--- 
a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/common/FullTextContainsEvaluator.java
+++ 
b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/common/FullTextContainsEvaluator.java
@@ -335,6 +335,8 @@
      * for that option. (e.g., argOptions[0] = "mode", argOptions[1] = "all")
      */
     private void setFullTextOption(IPointable[] argOptions, int 
uniqueQueryTokenCount) throws HyracksDataException {
+        // By default, we conduct a conjunctive search.
+        occurrenceThreshold = uniqueQueryTokenCount;
         for (int i = 0; i < optionArgsLength; i = i + 2) {
             // mode option
             if 
(compareStrInByteArrayAndPointable(FullTextContainsDescriptor.getSearchModeOptionArray(),
 argOptions[i],

-- 
To view, visit https://asterix-gerrit.ics.uci.edu/2116
To unsubscribe, visit https://asterix-gerrit.ics.uci.edu/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I240fbe08891d29532c6fcd60638a3b6bbe8da771
Gerrit-PatchSet: 10
Gerrit-Project: asterixdb
Gerrit-Branch: master
Gerrit-Owner: Taewoo Kim <wangs...@gmail.com>
Gerrit-Reviewer: Anon. E. Moose #1000171
Gerrit-Reviewer: Dmitry Lychagin <dmitry.lycha...@couchbase.com>
Gerrit-Reviewer: Ian2 Maxon <ima...@uci.edu>
Gerrit-Reviewer: Jenkins <jenk...@fulliautomatix.ics.uci.edu>
Gerrit-Reviewer: Taewoo Kim <wangs...@gmail.com>

Reply via email to