Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id DEA5A200D35 for ; Tue, 7 Nov 2017 23:58:51 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id DD1E7160BED; Tue, 7 Nov 2017 22:58:51 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id AC147160BEB for ; Tue, 7 Nov 2017 23:58:49 +0100 (CET) Received: (qmail 40852 invoked by uid 500); 7 Nov 2017 22:58:48 -0000 Mailing-List: contact notifications-help@asterixdb.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@asterixdb.apache.org Delivered-To: mailing list notifications@asterixdb.apache.org Received: (qmail 40843 invoked by uid 99); 7 Nov 2017 22:58:48 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd1-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 07 Nov 2017 22:58:48 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd1-us-west.apache.org (ASF Mail Server at spamd1-us-west.apache.org) with ESMTP id AA97CCDA77 for ; Tue, 7 Nov 2017 22:58:47 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd1-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: 0.919 X-Spam-Level: X-Spam-Status: No, score=0.919 tagged_above=-999 required=6.31 tests=[SPF_FAIL=0.919] autolearn=disabled Received: from mx1-lw-eu.apache.org ([10.40.0.8]) by localhost (spamd1-us-west.apache.org [10.40.0.7]) (amavisd-new, port 10024) with ESMTP id 2BXjyOgzELvs for ; Tue, 7 Nov 2017 22:58:26 +0000 (UTC) Received: from vitalstatistix.ics.uci.edu (vitalstatistix.ics.uci.edu [128.195.52.38]) by mx1-lw-eu.apache.org (ASF Mail Server at mx1-lw-eu.apache.org) with ESMTP id AA64E62C89 for ; Tue, 7 Nov 2017 22:48:45 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by vitalstatistix.ics.uci.edu (Postfix) with ESMTP id E4689100ADD; Tue, 7 Nov 2017 14:48:44 -0800 (PST) Date: Tue, 7 Nov 2017 14:48:44 -0800 From: "Taewoo Kim (Code Review)" To: Taewoo Kim CC: Jenkins , Dmitry Lychagin , Ian2 Maxon Reply-To: wangsaeu@gmail.com X-Gerrit-MessageType: merged Subject: Change in asterixdb[master]: [ASTERIXDB-2153][COMP][RT] Ensure the fulltext search option... X-Gerrit-Change-Id: I240fbe08891d29532c6fcd60638a3b6bbe8da771 X-Gerrit-ChangeURL: X-Gerrit-Commit: 63645130f5e590dae2e117235a37b35d30044943 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Content-Disposition: inline User-Agent: Gerrit/2.12.7 Message-Id: <20171107224844.E4689100ADD@vitalstatistix.ics.uci.edu> archived-at: Tue, 07 Nov 2017 22:58:52 -0000 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 Tested-by: Jenkins Contrib: Jenkins Reviewed-by: Taewoo Kim Integration-Tests: Jenkins --- 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> 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 opRef, IOptimizationContext context) + public boolean rewritePre(Mutable opRef, IOptimizationContext context) throws AlgebricksException { - AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue(); - Mutable 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 exprRef, - IOptimizationContext context) throws AlgebricksException { - ILogicalExpression expr = exprRef.getValue(); + private boolean checkParameter(Mutable 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 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 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> oldExprs = funcExpr.getArguments(); + List> 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(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> oldExprs = funcExpr.getArguments(); - List> 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> 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) 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> 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 expr, - List> 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 expr, + List> 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(optionExpr)); + newArgs.add(new MutableObject(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> 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(optionExpr)); - newArgs.add(new MutableObject(optionExprVal)); + newArgs.add(new MutableObject(searchModeOptionExpr)); + newArgs.add(new MutableObject(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> 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(searchModeOptionExpr)); - newArgs.add(new MutableObject(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 @@ + + fulltext-09 + + + fulltext-index-01 @@ -2746,6 +2751,11 @@ fulltext-index-02 + + + fulltext-index-08 + + 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 Gerrit-Reviewer: Anon. E. Moose #1000171 Gerrit-Reviewer: Dmitry Lychagin Gerrit-Reviewer: Ian2 Maxon Gerrit-Reviewer: Jenkins Gerrit-Reviewer: Taewoo Kim