You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@asterixdb.apache.org by bu...@apache.org on 2016/07/26 21:23:24 UTC
[4/4] asterixdb git commit: Support CASE expression in SQL++.
Support CASE expression in SQL++.
- support both simple CASE expression and searched CASE expression;
- support heterogenous return types of a CASE expression;
- remove IfElseExpression in SQL++;
- remove IfElseToSwitchCaseFunctionRule.java since the plan pattern it tries to identify is no longer right;
- unify CastRecordDescriptor and CastListDescriptor into CastTypeDescriptor;
- fix IS NULL for the case that the input is MISSING;
- let CastTypeDescriptor have a generated runtime so as to handle NULL/MISSING correctly.
Change-Id: Id9de7c3df70be43456e38a61ce767cc14f09e661
Reviewed-on: https://asterix-gerrit.ics.uci.edu/1015
Reviewed-by: Till Westmann <ti...@apache.org>
Tested-by: Jenkins <je...@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <je...@fulliautomatix.ics.uci.edu>
Project: http://git-wip-us.apache.org/repos/asf/asterixdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/asterixdb/commit/c8c067c5
Tree: http://git-wip-us.apache.org/repos/asf/asterixdb/tree/c8c067c5
Diff: http://git-wip-us.apache.org/repos/asf/asterixdb/diff/c8c067c5
Branch: refs/heads/master
Commit: c8c067c58cd19052fa9c108f08e42fdfd9ae6cec
Parents: f23d86e
Author: Yingyi Bu <yi...@couchbase.com>
Authored: Mon Jul 25 23:37:19 2016 -0700
Committer: Yingyi Bu <bu...@gmail.com>
Committed: Tue Jul 26 14:21:59 2016 -0700
----------------------------------------------------------------------
.../asterix/optimizer/base/RuleCollections.java | 4 +-
.../rules/AsterixInlineVariablesRule.java | 2 +-
.../optimizer/rules/ConstantFoldingRule.java | 19 +-
.../rules/IfElseToSwitchCaseFunctionRule.java | 130 --------
.../rules/InjectToAnyTypeCastRule.java | 145 +++++++++
...eDynamicTypeCastForExternalFunctionRule.java | 24 +-
.../rules/IntroduceDynamicTypeCastRule.java | 10 +-
...IntroduceSecondaryIndexInsertDeleteRule.java | 2 +-
.../rules/typecast/StaticTypeCastUtil.java | 14 +-
.../LangExpressionToPlanTranslator.java | 51 ++-
.../SqlppExpressionToPlanTranslator.java | 153 +++++++--
.../translator/util/FunctionCollection.java | 10 +-
.../file/SecondaryBTreeOperationsHelper.java | 54 ++--
.../file/SecondaryIndexOperationsHelper.java | 39 ++-
.../SecondaryInvertedIndexOperationsHelper.java | 46 +--
.../file/SecondaryRTreeOperationsHelper.java | 102 +++---
.../apache/asterix/runtime/NullMissingTest.java | 6 +-
.../optimizerts/queries/tpch/q12_shipping.sqlpp | 56 ++++
.../results/query-ASTERIXDB-1203.plan | 3 +-
.../results/query-ASTERIXDB-865.plan | 3 +-
.../optimizerts/results/tpch/q12_shipping.plan | 43 +++
.../parserts/queries_sqlpp/IfInFLOWGR.sqlpp | 5 +-
.../parserts/queries_sqlpp/IfThenElse.sqlpp | 8 +-
.../parserts/queries_sqlpp/functionDecl2.sqlpp | 4 +-
.../parserts/queries_sqlpp/nestedFLWOGR1.sqlpp | 7 +-
.../parserts/queries_sqlpp/nestedFLWOGR2.sqlpp | 8 +-
.../results_parser_sqlpp/IfInFLOWGR.ast | 16 +-
.../results_parser_sqlpp/IfThenElse.ast | 16 +-
.../results_parser_sqlpp/functionDecl2.ast | 16 +-
.../results_parser_sqlpp/nestedFLWOGR1.ast | 16 +-
.../results_parser_sqlpp/nestedFLWOGR2.ast | 16 +-
.../ifthenelse_02/ifthenelse_01.3.query.aql | 23 ++
.../query-ASTERIXDB-819-2.1.query.aql | 23 ++
.../query-ASTERIXDB-819.1.query.aql | 23 ++
.../misc/case_01/case_01.1.query.sqlpp | 28 ++
.../misc/case_02/case_02.1.query.sqlpp | 29 ++
.../misc/case_03/case_03.1.query.sqlpp | 28 ++
.../misc/case_04/case_04.1.query.sqlpp | 28 ++
.../misc/case_05/case_05.1.query.sqlpp | 30 ++
.../misc/case_06/case_06.1.query.sqlpp | 26 ++
.../misc/case_07/case_07.1.query.sqlpp | 30 ++
.../ifthenelse_01/ifthenelse_01.3.query.sqlpp | 12 +-
.../query-issue258.2.update.sqlpp | 14 +-
.../q08_national_market_share.3.query.sqlpp | 2 +-
.../q12_shipping/q12_shipping.3.query.sqlpp | 10 +-
.../q14_promotion_effect.3.query.sqlpp | 5 +-
.../q08_national_market_share.3.query.sqlpp | 3 +-
.../q12_shipping/q12_shipping.3.query.sqlpp | 6 +-
.../q14_promotion_effect.3.query.sqlpp | 6 +-
.../q08_national_market_share.3.query.sqlpp | 2 +-
.../q12_shipping/q12_shipping.3.query.sqlpp | 4 +-
.../q14_promotion_effect.3.query.sqlpp | 2 +-
.../q08_national_market_share.3.query.sqlpp | 2 +-
.../q12_shipping/q12_shipping.3.query.sqlpp | 10 +-
.../q14_promotion_effect.3.query.sqlpp | 5 +-
.../q08_national_market_share.3.query.sqlpp | 2 +-
.../q12_shipping/q12_shipping.3.query.sqlpp | 5 +-
.../q14_promotion_effect.3.query.sqlpp | 2 +-
.../query-issue218-2.1.ddl.sqlpp | 8 +-
.../query-issue218/query-issue218.1.ddl.sqlpp | 8 +-
.../results/misc/case_01/case_01.1.adm | 6 +
.../results/misc/case_02/case_02.1.adm | 6 +
.../results/misc/case_03/case_03.1.adm | 6 +
.../results/misc/case_04/case_04.1.adm | 6 +
.../results/misc/case_05/case_05.1.adm | 6 +
.../results/misc/case_06/case_06.1.adm | 6 +
.../misc/ifthenelse_02/ifthenelse_02.1.adm | 1 +
.../query-ASTERIXDB-819-2.1.adm | 1 +
.../query-ASTERIXDB-819.1.adm | 1 +
.../runtimets/results/null-missing/is/is.1.adm | 2 +-
.../misc/ifthenelse_01/ifthenelse_01.3.ast | 16 +-
.../q08_national_market_share.3.ast | 31 +-
.../q12_shipping/q12_shipping.3.ast | 96 +++---
.../q14_promotion_effect.3.ast | 50 +--
.../q08_national_market_share.3.ast | 34 +-
.../tpch/q12_shipping/q12_shipping.3.ast | 93 +++---
.../q14_promotion_effect.3.ast | 47 +--
.../src/test/resources/runtimets/testsuite.xml | 15 +
.../resources/runtimets/testsuite_sqlpp.xml | 35 ++
.../lang/aql/visitor/AQLInlineUdfsVisitor.java | 4 +-
.../asterix/lang/common/base/Expression.java | 3 +-
.../visitor/AbstractInlineUdfsVisitor.java | 93 +++---
.../visitor/SubstituteExpressionVisitor.java | 2 +-
.../lang/sqlpp/expression/CaseExpression.java | 129 ++++++++
.../lang/sqlpp/rewrites/SqlppQueryRewriter.java | 14 +
.../visitor/InlineColumnAliasVisitor.java | 14 +
.../SqlppBuiltinFunctionRewriteVisitor.java | 52 +++
.../visitor/SqlppInlineUdfsVisitor.java | 26 +-
.../lang/sqlpp/util/SqlppRewriteUtil.java | 10 +
.../visitor/CheckSql92AggregateVisitor.java | 9 +-
.../sqlpp/visitor/CheckSubqueryVisitor.java | 316 +++++++++++++++++++
.../lang/sqlpp/visitor/DeepCopyVisitor.java | 34 +-
.../lang/sqlpp/visitor/FreeVariableVisitor.java | 37 ++-
.../sqlpp/visitor/SqlppAstPrintVisitor.java | 27 +-
...SqlppCloneAndSubstituteVariablesVisitor.java | 15 +
.../sqlpp/visitor/SqlppFormatPrintVisitor.java | 22 ++
.../SqlppSubstituteExpressionsVisitor.java | 15 +
.../visitor/base/AbstractSqlppAstVisitor.java | 6 +
.../AbstractSqlppSimpleExpressionVisitor.java | 30 +-
.../lang/sqlpp/visitor/base/ISqlppVisitor.java | 3 +
.../src/main/javacc/SQLPP.html | 7 +-
.../asterix-lang-sqlpp/src/main/javacc/SQLPP.jj | 42 ++-
.../om/functions/AsterixBuiltinFunctions.java | 14 +-
.../impl/CastListResultTypeComputer.java | 46 ---
.../impl/CastRecordResultTypeComputer.java | 40 ---
.../om/typecomputer/impl/CastTypeComputer.java | 46 +++
.../typecomputer/impl/SwitchCaseComputer.java | 33 +-
.../common/AbstractTypeCheckEvaluator.java | 18 +-
.../functions/CastListDescriptor.java | 105 ------
.../functions/CastRecordDescriptor.java | 102 ------
.../functions/CastTypeDescriptor.java | 154 +++++++++
.../functions/IsMissingDescriptor.java | 4 +-
.../evaluators/functions/IsNullDescriptor.java | 7 +-
.../functions/IsUnknownDescriptor.java | 6 +-
.../functions/SwitchCaseDescriptor.java | 7 +-
.../runtime/formats/NonTaggedDataFormat.java | 68 ++--
116 files changed, 2336 insertions(+), 1086 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
index 683d722..0fba9da 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
@@ -36,7 +36,7 @@ import org.apache.asterix.optimizer.rules.ExtractDistinctByExpressionsRule;
import org.apache.asterix.optimizer.rules.ExtractOrderExpressionsRule;
import org.apache.asterix.optimizer.rules.FeedScanCollectionToUnnest;
import org.apache.asterix.optimizer.rules.FuzzyEqRule;
-import org.apache.asterix.optimizer.rules.IfElseToSwitchCaseFunctionRule;
+import org.apache.asterix.optimizer.rules.InjectToAnyTypeCastRule;
import org.apache.asterix.optimizer.rules.InlineUnnestFunctionRule;
import org.apache.asterix.optimizer.rules.IntroduceAutogenerateIDRule;
import org.apache.asterix.optimizer.rules.IntroduceDynamicTypeCastForExternalFunctionRule;
@@ -173,7 +173,6 @@ public final class RuleCollections {
normalization.add(new RemoveRedundantSelectRule());
normalization.add(new UnnestToDataScanRule());
normalization.add(new MetaFunctionToMetaVariableRule());
- normalization.add(new IfElseToSwitchCaseFunctionRule());
normalization.add(new FuzzyEqRule());
normalization.add(new SimilarityCheckRule());
return normalization;
@@ -282,6 +281,7 @@ public final class RuleCollections {
planCleanupRules.add(new IntroduceDynamicTypeCastForExternalFunctionRule());
planCleanupRules.add(new RemoveUnusedAssignAndAggregateRule());
planCleanupRules.add(new RemoveCartesianProductWithEmptyBranchRule());
+ planCleanupRules.add(new InjectToAnyTypeCastRule());
return planCleanupRules;
}
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/AsterixInlineVariablesRule.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/AsterixInlineVariablesRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/AsterixInlineVariablesRule.java
index 5486e64..74640a6 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/AsterixInlineVariablesRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/AsterixInlineVariablesRule.java
@@ -31,7 +31,7 @@ public class AsterixInlineVariablesRule extends InlineVariablesRule {
doNotInlineFuncs.add(AsterixBuiltinFunctions.FIELD_ACCESS_BY_INDEX);
doNotInlineFuncs.add(AsterixBuiltinFunctions.CLOSED_RECORD_CONSTRUCTOR);
doNotInlineFuncs.add(AsterixBuiltinFunctions.OPEN_RECORD_CONSTRUCTOR);
- doNotInlineFuncs.add(AsterixBuiltinFunctions.CAST_RECORD);
+ doNotInlineFuncs.add(AsterixBuiltinFunctions.CAST_TYPE);
doNotInlineFuncs.add(AsterixBuiltinFunctions.CREATE_CIRCLE);
doNotInlineFuncs.add(AsterixBuiltinFunctions.CREATE_LINE);
doNotInlineFuncs.add(AsterixBuiltinFunctions.CREATE_MBR);
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ConstantFoldingRule.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ConstantFoldingRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ConstantFoldingRule.java
index b29f110..9d9dda0 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ConstantFoldingRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ConstantFoldingRule.java
@@ -83,13 +83,13 @@ public class ConstantFoldingRule implements IAlgebraicRewriteRule {
// Function Identifier sets that the ConstantFolding rule should skip to apply.
// Most of them are record-related functions.
- private static final ImmutableSet<FunctionIdentifier> FUNC_ID_SET_THAT_SHOULD_NOT_BE_APPLIED = ImmutableSet.of(
- AsterixBuiltinFunctions.RECORD_MERGE, AsterixBuiltinFunctions.ADD_FIELDS,
- AsterixBuiltinFunctions.REMOVE_FIELDS, AsterixBuiltinFunctions.GET_RECORD_FIELDS,
- AsterixBuiltinFunctions.GET_RECORD_FIELD_VALUE, AsterixBuiltinFunctions.FIELD_ACCESS_NESTED,
- AsterixBuiltinFunctions.GET_ITEM, AsterixBuiltinFunctions.OPEN_RECORD_CONSTRUCTOR,
- AsterixBuiltinFunctions.FIELD_ACCESS_BY_INDEX, AsterixBuiltinFunctions.CAST_RECORD,
- AsterixBuiltinFunctions.CAST_LIST, AsterixBuiltinFunctions.META, AsterixBuiltinFunctions.META_KEY);
+ private static final ImmutableSet<FunctionIdentifier> FUNC_ID_SET_THAT_SHOULD_NOT_BE_APPLIED =
+ ImmutableSet.of(AsterixBuiltinFunctions.RECORD_MERGE, AsterixBuiltinFunctions.ADD_FIELDS,
+ AsterixBuiltinFunctions.REMOVE_FIELDS, AsterixBuiltinFunctions.GET_RECORD_FIELDS,
+ AsterixBuiltinFunctions.GET_RECORD_FIELD_VALUE, AsterixBuiltinFunctions.FIELD_ACCESS_NESTED,
+ AsterixBuiltinFunctions.GET_ITEM, AsterixBuiltinFunctions.OPEN_RECORD_CONSTRUCTOR,
+ AsterixBuiltinFunctions.FIELD_ACCESS_BY_INDEX, AsterixBuiltinFunctions.CAST_TYPE,
+ AsterixBuiltinFunctions.META, AsterixBuiltinFunctions.META_KEY);
/** Throws exceptions in substituiteProducedVariable, setVarType, and one getVarType method. */
private static final IVariableTypeEnvironment _emptyTypeEnv = new IVariableTypeEnvironment() {
@@ -204,8 +204,9 @@ public class ConstantFoldingRule implements IAlgebraicRewriteRule {
}
if (expr.getFunctionIdentifier().equals(AsterixBuiltinFunctions.FIELD_ACCESS_BY_NAME)) {
ARecordType rt = (ARecordType) _emptyTypeEnv.getType(expr.getArguments().get(0).getValue());
- String str = ((AString) ((AsterixConstantValue) ((ConstantExpression) expr.getArguments().get(1)
- .getValue()).getValue()).getObject()).getStringValue();
+ String str =
+ ((AString) ((AsterixConstantValue) ((ConstantExpression) expr.getArguments().get(1).getValue())
+ .getValue()).getObject()).getStringValue();
int k = rt.getFieldIndex(str);
if (k >= 0) {
// wait for the ByNameToByIndex rule to apply
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IfElseToSwitchCaseFunctionRule.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IfElseToSwitchCaseFunctionRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IfElseToSwitchCaseFunctionRule.java
deleted file mode 100644
index 76d4a47..0000000
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IfElseToSwitchCaseFunctionRule.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.asterix.optimizer.rules;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.asterix.lang.common.util.FunctionUtil;
-import org.apache.asterix.om.functions.AsterixBuiltinFunctions;
-import org.apache.commons.lang3.mutable.Mutable;
-import org.apache.commons.lang3.mutable.MutableObject;
-import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
-import org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
-import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
-import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
-import org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
-import org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
-import org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.AssignOperator;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.SubplanOperator;
-import org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
-
-public class IfElseToSwitchCaseFunctionRule implements IAlgebraicRewriteRule {
-
- @Override
- public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context)
- throws AlgebricksException {
- return false;
- }
-
- @Override
- public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context)
- throws AlgebricksException {
- AbstractLogicalOperator op1 = (AbstractLogicalOperator) opRef.getValue();
- if (op1.getOperatorTag() != LogicalOperatorTag.ASSIGN)
- return false;
-
- AssignOperator assignOp = (AssignOperator) op1;
- List<Mutable<ILogicalExpression>> assignExprs = assignOp.getExpressions();
- if (assignExprs.size() > 1)
- return false;
- ILogicalExpression expr = assignExprs.get(0).getValue();
- if (expr.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
- AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) expr;
- if (!funcExpr.getFunctionIdentifier().equals(AsterixBuiltinFunctions.CONCAT_NON_NULL))
- return false;
- }
-
- AbstractLogicalOperator op2 = (AbstractLogicalOperator) op1.getInputs().get(0).getValue();
- if (op2.getOperatorTag() != LogicalOperatorTag.SUBPLAN)
- return false;
-
- SubplanOperator subplan = (SubplanOperator) op2;
- List<ILogicalPlan> subPlans = subplan.getNestedPlans();
- List<Mutable<ILogicalExpression>> arguments = new ArrayList<Mutable<ILogicalExpression>>();
- for (ILogicalPlan plan : subPlans) {
- List<Mutable<ILogicalOperator>> roots = plan.getRoots();
-
- AbstractLogicalOperator nestedRoot = (AbstractLogicalOperator) roots.get(0).getValue();
- if (nestedRoot.getOperatorTag() != LogicalOperatorTag.SELECT)
- return false;
- SelectOperator selectOp = (SelectOperator) nestedRoot;
-
- AbstractLogicalOperator nestedNextOp = (AbstractLogicalOperator) nestedRoot.getInputs().get(0).getValue();
- if (nestedNextOp.getOperatorTag() != LogicalOperatorTag.ASSIGN)
- return false;
- AssignOperator assignRoot = (AssignOperator) nestedNextOp;
- Mutable<ILogicalExpression> actionExprRef = assignRoot.getExpressions().get(0);
-
- arguments.add(selectOp.getCondition());
- arguments.add(actionExprRef);
- AbstractLogicalOperator nestedBottomOp = (AbstractLogicalOperator) assignRoot.getInputs().get(0).getValue();
-
- if (nestedBottomOp.getOperatorTag() != LogicalOperatorTag.NESTEDTUPLESOURCE)
- return false;
- }
-
- AbstractLogicalOperator op3 = (AbstractLogicalOperator) op2.getInputs().get(0).getValue();
- if (op3.getOperatorTag() != LogicalOperatorTag.ASSIGN)
- return false;
-
- AssignOperator bottomAssign = (AssignOperator) op3;
- LogicalVariable conditionVar = bottomAssign.getVariables().get(0);
- Mutable<ILogicalExpression> switchCondition = new MutableObject<ILogicalExpression>(
- new VariableReferenceExpression(conditionVar));
- List<Mutable<ILogicalExpression>> argumentRefs = new ArrayList<Mutable<ILogicalExpression>>();
- argumentRefs.add(switchCondition);
- argumentRefs.addAll(arguments);
-
- /** replace the branch conditions */
- for (int i = 0; i < arguments.size(); i += 2) {
- if (arguments.get(i).getValue().equals(switchCondition.getValue())) {
- arguments.get(i).setValue(ConstantExpression.TRUE);
- } else {
- arguments.get(i).setValue(ConstantExpression.FALSE);
- }
- }
-
- ILogicalExpression callExpr = new ScalarFunctionCallExpression(
- FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.SWITCH_CASE), argumentRefs);
-
- assignOp.getInputs().get(0).setValue(op3);
- assignOp.getExpressions().get(0).setValue(callExpr);
- context.computeAndSetTypeEnvironmentForOperator(assignOp);
- return true;
- }
-}
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/InjectToAnyTypeCastRule.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/InjectToAnyTypeCastRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/InjectToAnyTypeCastRule.java
new file mode 100644
index 0000000..075c1f0
--- /dev/null
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/InjectToAnyTypeCastRule.java
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.asterix.optimizer.rules;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.asterix.lang.common.util.FunctionUtil;
+import org.apache.asterix.om.functions.AsterixBuiltinFunctions;
+import org.apache.asterix.om.typecomputer.base.TypeCastUtils;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.AUnionType;
+import org.apache.asterix.om.types.BuiltinType;
+import org.apache.asterix.om.types.IAType;
+import org.apache.commons.lang3.mutable.Mutable;
+import org.apache.commons.lang3.mutable.MutableObject;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
+import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
+import org.apache.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
+import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
+import org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
+import org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
+import org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
+
+/**
+ * This rule injects cast functions for "THEN" and "ELSE" branches of a switch-case function if
+ * different "THEN" and "ELSE" branches have heterogeneous return types.
+ */
+public class InjectToAnyTypeCastRule implements IAlgebraicRewriteRule {
+
+ @Override
+ public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context)
+ throws AlgebricksException {
+ ILogicalOperator op = opRef.getValue();
+ if (op.getInputs().isEmpty()) {
+ return false;
+ }
+ // Populates the latest type information.
+ context.computeAndSetTypeEnvironmentForOperator(op);
+ if (op.acceptExpressionTransform(exprRef -> injectToAnyTypeCast(op, exprRef, context))) {
+ // Generates the up-to-date type information.
+ context.computeAndSetTypeEnvironmentForOperator(op);
+ return true;
+ }
+ return false;
+ }
+
+ // Injects type casts to cast return expressions' return types to ANY.
+ private boolean injectToAnyTypeCast(ILogicalOperator op, Mutable<ILogicalExpression> exprRef,
+ IOptimizationContext context) throws AlgebricksException {
+ ILogicalExpression expr = exprRef.getValue();
+ if (expr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
+ return false;
+ }
+ boolean rewritten = false;
+ AbstractFunctionCallExpression func = (AbstractFunctionCallExpression) expr;
+ for (Mutable<ILogicalExpression> argRef : func.getArguments()) {
+ // Recursively rewrites arguments.
+ if (injectToAnyTypeCast(op, argRef, context)) {
+ context.computeAndSetTypeEnvironmentForOperator(op);
+ rewritten = true;
+ }
+ }
+ if (!func.getFunctionIdentifier().equals(AsterixBuiltinFunctions.SWITCH_CASE)) {
+ return rewritten;
+ }
+ return rewriteSwitchCase(op, func, context);
+ }
+
+ // Injects casts that cast types to ANY for different "THEN" and "ELSE" branches.
+ private boolean rewriteSwitchCase(ILogicalOperator op, AbstractFunctionCallExpression func,
+ IOptimizationContext context) throws AlgebricksException {
+ IVariableTypeEnvironment env = context.getOutputTypeEnvironment(op.getInputs().get(0).getValue());
+ if (!this.isHeterogenous(func, env)) {
+ return false;
+ }
+ List<Mutable<ILogicalExpression>> argRefs = func.getArguments();
+ int argSize = argRefs.size();
+ boolean rewritten = false;
+ for (int argIndex = 2; argIndex < argSize; argIndex += (argIndex + 2 == argSize) ? 1 : 2) {
+ Mutable<ILogicalExpression> argRef = argRefs.get(argIndex);
+ IAType type = (IAType) env.getType(argRefs.get(argIndex).getValue());
+ ATypeTag tag = type.getTypeTag();
+ // Casts are only needed when the original return type is a complex type.
+ // (In the runtime, there is already a type tag for scalar types.)
+ if (tag == ATypeTag.RECORD || tag == ATypeTag.UNORDEREDLIST || tag == ATypeTag.ORDEREDLIST) {
+ ILogicalExpression argExpr = argRef.getValue();
+ // Injects a cast call to cast the data type to ANY.
+ ScalarFunctionCallExpression castFunc = new ScalarFunctionCallExpression(
+ FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.CAST_TYPE),
+ new ArrayList<>(Collections.singletonList(new MutableObject<>(argExpr))));
+ TypeCastUtils.setRequiredAndInputTypes(castFunc, BuiltinType.ANY, type);
+ argRef.setValue(castFunc);
+ rewritten = true;
+ }
+ }
+ return rewritten;
+ }
+
+ // Checks whether "THEN" and "ELSE" branches return the heterogeneous types.
+ private boolean isHeterogenous(AbstractFunctionCallExpression func, IVariableTypeEnvironment env)
+ throws AlgebricksException {
+ List<Mutable<ILogicalExpression>> argRefs = func.getArguments();
+ int argSize = argRefs.size();
+ IAType currentType = null;
+ boolean heterogenous = false;
+ for (int argIndex = 2; argIndex < argSize; argIndex += (argIndex + 2 == argSize) ? 1 : 2) {
+ IAType type = (IAType) env.getType(argRefs.get(argIndex).getValue());
+ ATypeTag typeTag = type.getTypeTag();
+ // Null and missing are not considered as heterogeneous with other types.
+ if (typeTag != ATypeTag.NULL && typeTag != ATypeTag.MISSING) {
+ if (typeTag == ATypeTag.UNION) {
+ type = ((AUnionType) type).getActualType();
+ }
+ if (currentType != null && !type.equals(currentType)) {
+ heterogenous = true;
+ break;
+ }
+ currentType = type;
+ }
+ }
+ return heterogenous;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastForExternalFunctionRule.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastForExternalFunctionRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastForExternalFunctionRule.java
index 0fb5b0b..946ec39 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastForExternalFunctionRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastForExternalFunctionRule.java
@@ -22,14 +22,13 @@ package org.apache.asterix.optimizer.rules;
import java.util.ArrayList;
import java.util.List;
-import org.apache.commons.lang3.mutable.Mutable;
-
import org.apache.asterix.metadata.functions.AsterixExternalScalarFunctionInfo;
import org.apache.asterix.om.functions.AsterixBuiltinFunctions;
import org.apache.asterix.om.types.ARecordType;
import org.apache.asterix.om.types.AUnionType;
import org.apache.asterix.om.types.IAType;
import org.apache.asterix.om.util.NonTaggedFormatUtil;
+import org.apache.commons.lang3.mutable.Mutable;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
@@ -52,7 +51,8 @@ import org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
public class IntroduceDynamicTypeCastForExternalFunctionRule implements IAlgebraicRewriteRule {
@Override
- public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
+ public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context)
+ throws AlgebricksException {
return false;
}
@@ -64,17 +64,21 @@ public class IntroduceDynamicTypeCastForExternalFunctionRule implements IAlgebra
* resulting plan: distribute_result - project - assign (external function call) - assign (cast-record) - assign(open_record_constructor)
*/
AbstractLogicalOperator op1 = (AbstractLogicalOperator) opRef.getValue();
- if (op1.getOperatorTag() != LogicalOperatorTag.DISTRIBUTE_RESULT)
+ if (op1.getOperatorTag() != LogicalOperatorTag.DISTRIBUTE_RESULT) {
return false;
+ }
AbstractLogicalOperator op2 = (AbstractLogicalOperator) op1.getInputs().get(0).getValue();
- if (op2.getOperatorTag() != LogicalOperatorTag.PROJECT)
+ if (op2.getOperatorTag() != LogicalOperatorTag.PROJECT) {
return false;
+ }
AbstractLogicalOperator op3 = (AbstractLogicalOperator) op2.getInputs().get(0).getValue();
- if (op3.getOperatorTag() != LogicalOperatorTag.ASSIGN)
+ if (op3.getOperatorTag() != LogicalOperatorTag.ASSIGN) {
return false;
+ }
AbstractLogicalOperator op4 = (AbstractLogicalOperator) op3.getInputs().get(0).getValue();
- if (op4.getOperatorTag() != LogicalOperatorTag.ASSIGN)
+ if (op4.getOperatorTag() != LogicalOperatorTag.ASSIGN) {
return false;
+ }
// Op1 : assign (external function call), Op2 : assign (open_record_constructor)
AssignOperator assignOp1 = (AssignOperator) op3;
@@ -84,8 +88,8 @@ public class IntroduceDynamicTypeCastForExternalFunctionRule implements IAlgebra
FunctionIdentifier fid = null;
ILogicalExpression assignExpr = assignOp2.getExpressions().get(0).getValue();
if (assignExpr.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
- ScalarFunctionCallExpression funcExpr = (ScalarFunctionCallExpression) assignOp2.getExpressions().get(0)
- .getValue();
+ ScalarFunctionCallExpression funcExpr =
+ (ScalarFunctionCallExpression) assignOp2.getExpressions().get(0).getValue();
fid = funcExpr.getFunctionIdentifier();
if (fid != AsterixBuiltinFunctions.OPEN_RECORD_CONSTRUCTOR) {
@@ -137,7 +141,7 @@ public class IntroduceDynamicTypeCastForExternalFunctionRule implements IAlgebra
}
if (cast) {
IntroduceDynamicTypeCastRule.addWrapperFunction(requiredRecordType, recordVar.get(0), assignOp1, context,
- AsterixBuiltinFunctions.CAST_RECORD);
+ AsterixBuiltinFunctions.CAST_TYPE);
}
return cast || checkUnknown;
}
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastRule.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastRule.java
index e692678..f6cd015 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastRule.java
@@ -173,7 +173,7 @@ public class IntroduceDynamicTypeCastRule implements IAlgebraicRewriteRule {
AsterixBuiltinFunctions.CHECK_UNKNOWN);
}
if (cast) {
- addWrapperFunction(requiredRecordType, recordVar, op, context, AsterixBuiltinFunctions.CAST_RECORD);
+ addWrapperFunction(requiredRecordType, recordVar, op, context, AsterixBuiltinFunctions.CAST_TYPE);
}
return cast || checkUnknown;
}
@@ -210,15 +210,15 @@ public class IntroduceDynamicTypeCastRule implements IAlgebraicRewriteRule {
if (var.equals(recordVar)) {
/** insert an assign operator to call the function on-top-of the variable */
IAType actualType = (IAType) env.getVarType(var);
- AbstractFunctionCallExpression cast = new ScalarFunctionCallExpression(
- FunctionUtil.getFunctionInfo(fd));
+ AbstractFunctionCallExpression cast =
+ new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(fd));
cast.getArguments()
.add(new MutableObject<ILogicalExpression>(new VariableReferenceExpression(var)));
/** enforce the required record type */
TypeCastUtils.setRequiredAndInputTypes(cast, requiredRecordType, actualType);
LogicalVariable newAssignVar = context.newVar();
- AssignOperator newAssignOperator = new AssignOperator(newAssignVar,
- new MutableObject<ILogicalExpression>(cast));
+ AssignOperator newAssignOperator =
+ new AssignOperator(newAssignVar, new MutableObject<ILogicalExpression>(cast));
newAssignOperator.getInputs().add(new MutableObject<ILogicalOperator>(op));
opRef.setValue(newAssignOperator);
context.computeAndSetTypeEnvironmentForOperator(newAssignOperator);
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceSecondaryIndexInsertDeleteRule.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceSecondaryIndexInsertDeleteRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceSecondaryIndexInsertDeleteRule.java
index ae69093..c64258f 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceSecondaryIndexInsertDeleteRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceSecondaryIndexInsertDeleteRule.java
@@ -255,7 +255,7 @@ public class IntroduceSecondaryIndexInsertDeleteRule implements IAlgebraicRewrit
context.addNotToBeInlinedVar(castedRecVar);
//introduce casting to enforced type
AbstractFunctionCallExpression castFunc = new ScalarFunctionCallExpression(
- FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.CAST_RECORD));
+ FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.CAST_TYPE));
// The first argument is the record
castFunc.getArguments()
.add(new MutableObject<ILogicalExpression>(insertOp.getPayloadExpression().getValue()));
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/typecast/StaticTypeCastUtil.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/typecast/StaticTypeCastUtil.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/typecast/StaticTypeCastUtil.java
index eaf9484..eac35cd 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/typecast/StaticTypeCastUtil.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/typecast/StaticTypeCastUtil.java
@@ -49,7 +49,6 @@ import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCa
import org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
import org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
import org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
-import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
import org.apache.hyracks.algebricks.core.algebra.functions.IFunctionInfo;
/**
@@ -455,24 +454,25 @@ public class StaticTypeCastUtil {
if (argExpr.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL
|| argExpr.getExpressionTag() == LogicalExpressionTag.VARIABLE) {
IAType reqFieldType = inputFieldType;
- FunctionIdentifier fi = null;
// do not enforce nested type in the case of no-used variables
switch (inputFieldType.getTypeTag()) {
case RECORD:
reqFieldType = DefaultOpenFieldType.NESTED_OPEN_RECORD_TYPE;
- fi = AsterixBuiltinFunctions.CAST_RECORD;
break;
case ORDEREDLIST:
reqFieldType = DefaultOpenFieldType.NESTED_OPEN_AORDERED_LIST_TYPE;
- fi = AsterixBuiltinFunctions.CAST_LIST;
break;
case UNORDEREDLIST:
reqFieldType = DefaultOpenFieldType.NESTED_OPEN_AUNORDERED_LIST_TYPE;
- fi = AsterixBuiltinFunctions.CAST_LIST;
+ break;
+ default:
+ break;
}
- if (fi != null && !inputFieldType.equals(reqFieldType) && parameterVars.size() > 0) {
+ // do not enforce nested type in the case of no-used variables
+ if (!inputFieldType.equals(reqFieldType) && !parameterVars.isEmpty()) {
//inject dynamic type casting
- injectCastFunction(FunctionUtil.getFunctionInfo(fi), reqFieldType, inputFieldType, expRef, argExpr);
+ injectCastFunction(FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.CAST_TYPE), reqFieldType,
+ inputFieldType, expRef, argExpr);
castInjected = true;
}
//recursively rewrite function arguments
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
index 1894cc3..136dd5e 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
@@ -870,9 +870,9 @@ class LangExpressionToPlanTranslator
new MutableObject<>(new VariableReferenceExpression(varCond)), ifexpr.getThenExpr());
// Creates a subplan for the "else" branch.
- AbstractFunctionCallExpression notVarCond =
- new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(AlgebricksBuiltinFunctions.NOT),
- Collections.singletonList(new MutableObject<>(new VariableReferenceExpression(varCond))));
+ AbstractFunctionCallExpression notVarCond = new ScalarFunctionCallExpression(
+ FunctionUtil.getFunctionInfo(AlgebricksBuiltinFunctions.NOT),
+ Collections.singletonList(generateAndNotIsUnknownWrap(new VariableReferenceExpression(varCond))));
Pair<ILogicalOperator, LogicalVariable> opAndVarForElse = constructSubplanOperatorForBranch(
opAndVarForThen.first, new MutableObject<>(notVarCond), ifexpr.getElseExpr());
@@ -882,7 +882,6 @@ class LangExpressionToPlanTranslator
arguments.add(new MutableObject<>(new VariableReferenceExpression(varCond)));
arguments.add(new MutableObject<>(ConstantExpression.TRUE));
arguments.add(new MutableObject<>(new VariableReferenceExpression(opAndVarForThen.second)));
- arguments.add(new MutableObject<>(ConstantExpression.FALSE));
arguments.add(new MutableObject<>(new VariableReferenceExpression(opAndVarForElse.second)));
AbstractFunctionCallExpression swithCaseExpr = new ScalarFunctionCallExpression(
FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.SWITCH_CASE), arguments);
@@ -1364,10 +1363,14 @@ class LangExpressionToPlanTranslator
protected boolean expressionNeedsNoNesting(Expression expr) {
Kind k = expr.getKind();
- return k == Kind.LITERAL_EXPRESSION || k == Kind.LIST_CONSTRUCTOR_EXPRESSION
- || k == Kind.RECORD_CONSTRUCTOR_EXPRESSION || k == Kind.VARIABLE_EXPRESSION || k == Kind.CALL_EXPRESSION
- || k == Kind.OP_EXPRESSION || k == Kind.FIELD_ACCESSOR_EXPRESSION || k == Kind.INDEX_ACCESSOR_EXPRESSION
- || k == Kind.UNARY_EXPRESSION || k == Kind.IF_EXPRESSION || k == Kind.INDEPENDENT_SUBQUERY;
+ boolean noNesting = k == Kind.LITERAL_EXPRESSION || k == Kind.LIST_CONSTRUCTOR_EXPRESSION
+ || k == Kind.RECORD_CONSTRUCTOR_EXPRESSION || k == Kind.VARIABLE_EXPRESSION;
+ noNesting = noNesting || k == Kind.CALL_EXPRESSION || k == Kind.OP_EXPRESSION
+ || k == Kind.FIELD_ACCESSOR_EXPRESSION;
+ noNesting = noNesting || k == Kind.INDEX_ACCESSOR_EXPRESSION || k == Kind.UNARY_EXPRESSION
+ || k == Kind.IF_EXPRESSION;
+ return noNesting || k == Kind.INDEPENDENT_SUBQUERY || k == Kind.CASE_EXPRESSION;
+
}
protected <T> List<T> mkSingletonArrayList(T item) {
@@ -1519,7 +1522,7 @@ class LangExpressionToPlanTranslator
* @return a pair of the constructed subplan operator and the output variable for the branch.
* @throws AsterixException
*/
- private Pair<ILogicalOperator, LogicalVariable> constructSubplanOperatorForBranch(ILogicalOperator inputOp,
+ protected Pair<ILogicalOperator, LogicalVariable> constructSubplanOperatorForBranch(ILogicalOperator inputOp,
Mutable<ILogicalExpression> selectExpr, Expression branchExpression) throws AsterixException {
context.enterSubplan();
SubplanOperator subplanOp = new SubplanOperator();
@@ -1555,4 +1558,34 @@ class LangExpressionToPlanTranslator
.add(new MutableObject<>(new ConstantExpression(new AsterixConstantValue(new AInt64(0L)))));
return new AssignOperator(v1, new MutableObject<>(comparison));
}
+
+ // Generates the filter condition for whether a conditional branch should be executed.
+ protected Mutable<ILogicalExpression> generateNoMatchedPrecedingWhenBranchesFilter(
+ List<ILogicalExpression> inputBooleanExprs) {
+ List<Mutable<ILogicalExpression>> arguments = new ArrayList<>();
+ for (ILogicalExpression inputBooleanExpr : inputBooleanExprs) {
+ // A NULL/MISSING valued WHEN expression does not lead to the corresponding THEN execution.
+ // Therefore, we should check a previous WHEN boolean condition is not unknown.
+ arguments.add(generateAndNotIsUnknownWrap(inputBooleanExpr));
+ }
+ Mutable<ILogicalExpression> hasBeenExecutedExprRef = new MutableObject<>(
+ new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.OR), arguments));
+ return new MutableObject<>(
+ new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.NOT),
+ new ArrayList<>(Collections.singletonList(hasBeenExecutedExprRef))));
+ }
+
+ // For an input expression `expr`, return `expr AND expr IS NOT UNKOWN`.
+ protected Mutable<ILogicalExpression> generateAndNotIsUnknownWrap(ILogicalExpression logicalExpr) {
+ List<Mutable<ILogicalExpression>> arguments = new ArrayList<>();
+ arguments.add(new MutableObject<>(logicalExpr));
+ Mutable<ILogicalExpression> expr = new MutableObject<>(
+ new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.IS_UNKOWN),
+ new ArrayList<>(Collections.singletonList(new MutableObject<>(logicalExpr)))));
+ arguments.add(new MutableObject<>(
+ new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.NOT),
+ new ArrayList<>(Collections.singletonList(expr)))));
+ return new MutableObject<>(
+ new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.AND), arguments));
+ }
}
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
index b7ed988..e40de4b 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
@@ -20,6 +20,7 @@ package org.apache.asterix.translator;
import java.util.ArrayDeque;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Deque;
import java.util.List;
@@ -51,12 +52,14 @@ import org.apache.asterix.lang.sqlpp.clause.SelectElement;
import org.apache.asterix.lang.sqlpp.clause.SelectRegular;
import org.apache.asterix.lang.sqlpp.clause.SelectSetOperation;
import org.apache.asterix.lang.sqlpp.clause.UnnestClause;
+import org.apache.asterix.lang.sqlpp.expression.CaseExpression;
import org.apache.asterix.lang.sqlpp.expression.IndependentSubquery;
import org.apache.asterix.lang.sqlpp.expression.SelectExpression;
import org.apache.asterix.lang.sqlpp.optype.JoinType;
import org.apache.asterix.lang.sqlpp.util.SqlppVariableUtil;
import org.apache.asterix.lang.sqlpp.visitor.base.ISqlppVisitor;
import org.apache.asterix.metadata.declared.AqlMetadataProvider;
+import org.apache.asterix.om.base.ABoolean;
import org.apache.asterix.om.base.AInt32;
import org.apache.asterix.om.base.AString;
import org.apache.asterix.om.constants.AsterixConstantValue;
@@ -72,9 +75,11 @@ import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
import org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
+import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
import org.apache.hyracks.algebricks.core.algebra.expressions.AggregateFunctionCallExpression;
import org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
import org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
+import org.apache.hyracks.algebricks.core.algebra.expressions.UnnestingFunctionCallExpression;
import org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractUnnestNonMapOperator;
@@ -142,8 +147,8 @@ class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTranslator imp
currentOpRef = new MutableObject<>(letClause.accept(this, currentOpRef).first);
}
}
- Pair<ILogicalOperator, LogicalVariable> select = selectExpression.getSelectSetOperation().accept(this,
- currentOpRef);
+ Pair<ILogicalOperator, LogicalVariable> select =
+ selectExpression.getSelectSetOperation().accept(this, currentOpRef);
currentOpRef = new MutableObject<>(select.first);
if (selectExpression.hasOrderby()) {
currentOpRef = new MutableObject<>(selectExpression.getOrderbyClause().accept(this, currentOpRef).first);
@@ -151,8 +156,8 @@ class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTranslator imp
if (selectExpression.hasLimit()) {
currentOpRef = new MutableObject<>(selectExpression.getLimitClause().accept(this, currentOpRef).first);
}
- Pair<ILogicalOperator, LogicalVariable> result = produceSelectPlan(selectExpression.isSubquery(), currentOpRef,
- select.second);
+ Pair<ILogicalOperator, LogicalVariable> result =
+ produceSelectPlan(selectExpression.isSubquery(), currentOpRef, select.second);
if (selectExpression.isSubquery()) {
context.exitSubplan();
}
@@ -162,8 +167,8 @@ class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTranslator imp
@Override
public Pair<ILogicalOperator, LogicalVariable> visit(IndependentSubquery independentSubquery,
Mutable<ILogicalOperator> tupleSource) throws AsterixException {
- Pair<ILogicalExpression, Mutable<ILogicalOperator>> eo = langExprToAlgExpression(independentSubquery.getExpr(),
- tupleSource);
+ Pair<ILogicalExpression, Mutable<ILogicalOperator>> eo =
+ langExprToAlgExpression(independentSubquery.getExpr(), tupleSource);
// Replaces nested tuple source with empty tuple source so that the subquery can be independent
// from its input operators.
replaceNtsWithEts(eo.second.getValue());
@@ -177,8 +182,8 @@ class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTranslator imp
public Pair<ILogicalOperator, LogicalVariable> visit(SelectSetOperation selectSetOperation,
Mutable<ILogicalOperator> tupSource) throws AsterixException {
Mutable<ILogicalOperator> currentOpRef = tupSource;
- Pair<ILogicalOperator, LogicalVariable> currentResult = selectSetOperation.getLeftInput().accept(this,
- currentOpRef);
+ Pair<ILogicalOperator, LogicalVariable> currentResult =
+ selectSetOperation.getLeftInput().accept(this, currentOpRef);
if (selectSetOperation.hasRightInputs()) {
throw new NotImplementedException();
}
@@ -236,12 +241,12 @@ class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTranslator imp
if (fromTerm.hasPositionalVariable()) {
LogicalVariable pVar = context.newVar(fromTerm.getPositionalVariable());
// We set the positional variable type as INT64 type.
- unnestOp = new UnnestOperator(fromVar,
- new MutableObject<ILogicalExpression>(makeUnnestExpression(eo.first)), pVar, BuiltinType.AINT64,
- new AqlPositionWriter());
+ unnestOp =
+ new UnnestOperator(fromVar, new MutableObject<ILogicalExpression>(makeUnnestExpression(eo.first)),
+ pVar, BuiltinType.AINT64, new AqlPositionWriter());
} else {
- unnestOp = new UnnestOperator(fromVar,
- new MutableObject<ILogicalExpression>(makeUnnestExpression(eo.first)));
+ unnestOp =
+ new UnnestOperator(fromVar, new MutableObject<ILogicalExpression>(makeUnnestExpression(eo.first)));
}
unnestOp.getInputs().add(eo.second);
@@ -267,41 +272,41 @@ class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTranslator imp
throws AsterixException {
Mutable<ILogicalOperator> leftInputRef = uncorrelatedLeftBranchStack.pop();
if (joinClause.getJoinType() == JoinType.INNER) {
- Pair<ILogicalOperator, LogicalVariable> rightBranch = generateUnnestForBinaryCorrelateRightBranch(
- joinClause, inputRef, true);
+ Pair<ILogicalOperator, LogicalVariable> rightBranch =
+ generateUnnestForBinaryCorrelateRightBranch(joinClause, inputRef, true);
// A join operator with condition TRUE.
- AbstractBinaryJoinOperator joinOperator = new InnerJoinOperator(
- new MutableObject<ILogicalExpression>(ConstantExpression.TRUE), leftInputRef,
- new MutableObject<ILogicalOperator>(rightBranch.first));
+ AbstractBinaryJoinOperator joinOperator =
+ new InnerJoinOperator(new MutableObject<ILogicalExpression>(ConstantExpression.TRUE), leftInputRef,
+ new MutableObject<ILogicalOperator>(rightBranch.first));
Mutable<ILogicalOperator> joinOpRef = new MutableObject<>(joinOperator);
// Add an additional filter operator.
- Pair<ILogicalExpression, Mutable<ILogicalOperator>> conditionExprOpPair = langExprToAlgExpression(
- joinClause.getConditionExpression(), joinOpRef);
- SelectOperator filter = new SelectOperator(new MutableObject<ILogicalExpression>(conditionExprOpPair.first),
- false, null);
+ Pair<ILogicalExpression, Mutable<ILogicalOperator>> conditionExprOpPair =
+ langExprToAlgExpression(joinClause.getConditionExpression(), joinOpRef);
+ SelectOperator filter =
+ new SelectOperator(new MutableObject<ILogicalExpression>(conditionExprOpPair.first), false, null);
filter.getInputs().add(conditionExprOpPair.second);
return new Pair<>(filter, rightBranch.second);
} else {
// Creates a subplan operator.
SubplanOperator subplanOp = new SubplanOperator();
- Mutable<ILogicalOperator> ntsRef = new MutableObject<>(
- new NestedTupleSourceOperator(new MutableObject<ILogicalOperator>(subplanOp)));
+ Mutable<ILogicalOperator> ntsRef =
+ new MutableObject<>(new NestedTupleSourceOperator(new MutableObject<ILogicalOperator>(subplanOp)));
subplanOp.getInputs().add(leftInputRef);
// Enters the translation for a subplan.
context.enterSubplan();
// Adds an unnest operator to unnest to right expression.
- Pair<ILogicalOperator, LogicalVariable> rightBranch = generateUnnestForBinaryCorrelateRightBranch(
- joinClause, ntsRef, true);
+ Pair<ILogicalOperator, LogicalVariable> rightBranch =
+ generateUnnestForBinaryCorrelateRightBranch(joinClause, ntsRef, true);
AbstractUnnestNonMapOperator rightUnnestOp = (AbstractUnnestNonMapOperator) rightBranch.first;
// Adds an additional filter operator for the join condition.
Pair<ILogicalExpression, Mutable<ILogicalOperator>> conditionExprOpPair = langExprToAlgExpression(
joinClause.getConditionExpression(), new MutableObject<ILogicalOperator>(rightUnnestOp));
- SelectOperator filter = new SelectOperator(new MutableObject<ILogicalExpression>(conditionExprOpPair.first),
- false, null);
+ SelectOperator filter =
+ new SelectOperator(new MutableObject<ILogicalExpression>(conditionExprOpPair.first), false, null);
filter.getInputs().add(conditionExprOpPair.second);
ILogicalOperator currentTopOp = filter;
@@ -327,8 +332,8 @@ class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTranslator imp
// Assigns the record constructor function to a record variable.
LogicalVariable recordVar = context.newVar();
- AssignOperator assignOp = new AssignOperator(recordVar,
- new MutableObject<ILogicalExpression>(recordCreationFunc));
+ AssignOperator assignOp =
+ new AssignOperator(recordVar, new MutableObject<ILogicalExpression>(recordCreationFunc));
assignOp.getInputs().add(new MutableObject<ILogicalOperator>(currentTopOp));
// Sets currentTopOp and varToListify for later usages.
@@ -357,8 +362,8 @@ class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTranslator imp
// Outer unnest the aggregated var from the subplan.
LogicalVariable outerUnnestVar = context.newVar();
- LeftOuterUnnestOperator outerUnnestOp = new LeftOuterUnnestOperator(outerUnnestVar,
- new MutableObject<ILogicalExpression>(
+ LeftOuterUnnestOperator outerUnnestOp =
+ new LeftOuterUnnestOperator(outerUnnestVar, new MutableObject<ILogicalExpression>(
makeUnnestExpression(new VariableReferenceExpression(aggVar))));
outerUnnestOp.getInputs().add(new MutableObject<ILogicalOperator>(subplanOp));
currentTopOp = outerUnnestOp;
@@ -423,8 +428,8 @@ class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTranslator imp
@Override
public Pair<ILogicalOperator, LogicalVariable> visit(HavingClause havingClause, Mutable<ILogicalOperator> tupSource)
throws AsterixException {
- Pair<ILogicalExpression, Mutable<ILogicalOperator>> p = langExprToAlgExpression(
- havingClause.getFilterExpression(), tupSource);
+ Pair<ILogicalExpression, Mutable<ILogicalOperator>> p =
+ langExprToAlgExpression(havingClause.getFilterExpression(), tupSource);
SelectOperator s = new SelectOperator(new MutableObject<ILogicalExpression>(p.first), false, null);
s.getInputs().add(p.second);
return new Pair<>(s, null);
@@ -477,6 +482,86 @@ class SqlppExpressionToPlanTranslator extends LangExpressionToPlanTranslator imp
throw new UnsupportedOperationException(ERR_MSG);
}
+ @Override
+ public Pair<ILogicalOperator, LogicalVariable> visit(CaseExpression caseExpression,
+ Mutable<ILogicalOperator> tupSource) throws AsterixException {
+ //Creates a series of subplan operators, one for each branch.
+ Mutable<ILogicalOperator> currentOpRef = tupSource;
+ ILogicalOperator currentOperator = null;
+ List<Expression> whenExprList = caseExpression.getWhenExprs();
+ List<Expression> thenExprList = caseExpression.getThenExprs();
+ List<ILogicalExpression> branchCondVarReferences = new ArrayList<>();
+ List<ILogicalExpression> allVarReferences = new ArrayList<>();
+ for (int index = 0; index < whenExprList.size(); ++index) {
+ Pair<ILogicalOperator, LogicalVariable> whenExprResult = whenExprList.get(index).accept(this, currentOpRef);
+ currentOperator = whenExprResult.first;
+ // Variable whenConditionVar is corresponds to the current "WHEN" condition.
+ LogicalVariable whenConditionVar = whenExprResult.second;
+ Mutable<ILogicalExpression> branchEntraceConditionExprRef =
+ new MutableObject<>(new VariableReferenceExpression(whenConditionVar));
+
+ // Constructs an expression that filters data based on preceding "WHEN" conditions
+ // and the current "WHEN" condition. Note that only one "THEN" expression can be run
+ // even though multiple "WHEN" conditions can be satisfied.
+ if (!branchCondVarReferences.isEmpty()) {
+ // The additional filter generated here makes sure the the tuple has not
+ // entered other matched "WHEN...THEN" case.
+ List<Mutable<ILogicalExpression>> andArgs = new ArrayList<>();
+ andArgs.add(generateNoMatchedPrecedingWhenBranchesFilter(branchCondVarReferences));
+ andArgs.add(branchEntraceConditionExprRef);
+
+ // A "THEN" branch can be entered only when the tuple has not enter any other preceding
+ // branches and the current "WHEN" condition is TRUE.
+ branchEntraceConditionExprRef = new MutableObject<>(new ScalarFunctionCallExpression(
+ FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.AND), andArgs));
+ }
+
+ // Translates the corresponding "THEN" expression.
+ Pair<ILogicalOperator, LogicalVariable> opAndVarForThen = constructSubplanOperatorForBranch(currentOperator,
+ branchEntraceConditionExprRef, thenExprList.get(index));
+
+ branchCondVarReferences.add(new VariableReferenceExpression(whenConditionVar));
+ allVarReferences.add(new VariableReferenceExpression(whenConditionVar));
+ allVarReferences.add(new VariableReferenceExpression(opAndVarForThen.second));
+ currentOperator = opAndVarForThen.first;
+ currentOpRef = new MutableObject<>(currentOperator);
+ }
+
+ // Creates a subplan for the "ELSE" branch.
+ Mutable<ILogicalExpression> elseCondExprRef =
+ generateNoMatchedPrecedingWhenBranchesFilter(branchCondVarReferences);
+ Pair<ILogicalOperator, LogicalVariable> opAndVarForElse =
+ constructSubplanOperatorForBranch(currentOperator, elseCondExprRef, caseExpression.getElseExpr());
+
+ // Uses switch-case function to select the results of two branches.
+ LogicalVariable selectVar = context.newVar();
+ List<Mutable<ILogicalExpression>> arguments = new ArrayList<>();
+ arguments.add(new MutableObject<>(new ConstantExpression(new AsterixConstantValue(ABoolean.TRUE))));
+ for (ILogicalExpression argVar : allVarReferences) {
+ arguments.add(new MutableObject<>(argVar));
+ }
+ arguments.add(new MutableObject<>(new VariableReferenceExpression(opAndVarForElse.second)));
+ AbstractFunctionCallExpression swithCaseExpr = new ScalarFunctionCallExpression(
+ FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.SWITCH_CASE), arguments);
+ AssignOperator assignOp = new AssignOperator(selectVar, new MutableObject<>(swithCaseExpr));
+ assignOp.getInputs().add(new MutableObject<>(opAndVarForElse.first));
+
+ // Unnests the selected (a "THEN" or "ELSE" branch) result.
+ LogicalVariable unnestVar = context.newVar();
+ UnnestOperator unnestOp = new UnnestOperator(unnestVar,
+ new MutableObject<>(new UnnestingFunctionCallExpression(
+ FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.SCAN_COLLECTION), Collections
+ .singletonList(new MutableObject<>(new VariableReferenceExpression(selectVar))))));
+ unnestOp.getInputs().add(new MutableObject<>(assignOp));
+
+ // Produces the final assign operator.
+ LogicalVariable resultVar = context.newVar();
+ AssignOperator finalAssignOp =
+ new AssignOperator(resultVar, new MutableObject<>(new VariableReferenceExpression(unnestVar)));
+ finalAssignOp.getInputs().add(new MutableObject<>(unnestOp));
+ return new Pair<>(finalAssignOp, resultVar);
+ }
+
private Pair<ILogicalOperator, LogicalVariable> produceSelectPlan(boolean isSubquery,
Mutable<ILogicalOperator> returnOpRef, LogicalVariable resVar) {
if (isSubquery) {
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/util/FunctionCollection.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/util/FunctionCollection.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/util/FunctionCollection.java
index 24ddaf6..2c0aef4 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/util/FunctionCollection.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/util/FunctionCollection.java
@@ -131,8 +131,7 @@ import org.apache.asterix.runtime.evaluators.constructors.ClosedRecordConstructo
import org.apache.asterix.runtime.evaluators.constructors.OpenRecordConstructorDescriptor;
import org.apache.asterix.runtime.evaluators.functions.AndDescriptor;
import org.apache.asterix.runtime.evaluators.functions.AnyCollectionMemberDescriptor;
-import org.apache.asterix.runtime.evaluators.functions.CastListDescriptor;
-import org.apache.asterix.runtime.evaluators.functions.CastRecordDescriptor;
+import org.apache.asterix.runtime.evaluators.functions.CastTypeDescriptor;
import org.apache.asterix.runtime.evaluators.functions.CheckUnknownDescriptor;
import org.apache.asterix.runtime.evaluators.functions.CodePointToStringDescriptor;
import org.apache.asterix.runtime.evaluators.functions.CountHashedGramTokensDescriptor;
@@ -374,10 +373,8 @@ public class FunctionCollection {
temp.add(OrderedListConstructorDescriptor.FACTORY);
temp.add(UnorderedListConstructorDescriptor.FACTORY);
- // Cast functions
+ // Inject failure function
temp.add(InjectFailureDescriptor.FACTORY);
- temp.add(CastListDescriptor.FACTORY);
- temp.add(CastRecordDescriptor.FACTORY);
// Switch case
temp.add(SwitchCaseDescriptor.FACTORY);
@@ -612,6 +609,9 @@ public class FunctionCollection {
functionsToInjectUnkownHandling.add(GetOverlappingIntervalDescriptor.FACTORY);
functionsToInjectUnkownHandling.add(DurationFromIntervalDescriptor.FACTORY);
+ // Cast function
+ functionsToInjectUnkownHandling.add(CastTypeDescriptor.FACTORY);
+
List<IFunctionDescriptorFactory> generatedFactories = new ArrayList<>();
for (IFunctionDescriptorFactory factory : functionsToInjectUnkownHandling) {
generatedFactories
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/main/java/org/apache/asterix/file/SecondaryBTreeOperationsHelper.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/file/SecondaryBTreeOperationsHelper.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/file/SecondaryBTreeOperationsHelper.java
index 15ea2f8..9e2e0b0 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/file/SecondaryBTreeOperationsHelper.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/file/SecondaryBTreeOperationsHelper.java
@@ -95,8 +95,8 @@ public class SecondaryBTreeOperationsHelper extends SecondaryIndexOperationsHelp
secondaryComparatorFactories, secondaryBloomFilterKeyFields, false, dataset.getDatasetId(),
mergePolicyFactory, mergePolicyFactoryProperties, filterTypeTraits, filterCmpFactories,
secondaryBTreeFields, secondaryFilterFields);
- localResourceFactoryProvider = new PersistentLocalResourceFactoryProvider(localResourceMetadata,
- LocalResource.LSMBTreeResource);
+ localResourceFactoryProvider =
+ new PersistentLocalResourceFactoryProvider(localResourceMetadata, LocalResource.LSMBTreeResource);
indexDataflowHelperFactory = new LSMBTreeDataflowHelperFactory(
new AsterixVirtualBufferCacheProvider(dataset.getDatasetId()), mergePolicyFactory,
mergePolicyFactoryProperties, new SecondaryIndexOperationTrackerProvider(dataset.getDatasetId()),
@@ -146,12 +146,12 @@ public class SecondaryBTreeOperationsHelper extends SecondaryIndexOperationsHelp
// Assign op.
AbstractOperatorDescriptor sourceOp = primaryScanOp;
- if (isEnforcingKeyTypes) {
+ if (isEnforcingKeyTypes && !enforcedItemType.equals(itemType)) {
sourceOp = createCastOp(spec, dataset.getDatasetType());
spec.connect(new OneToOneConnectorDescriptor(spec), primaryScanOp, 0, sourceOp, 0);
}
- AlgebricksMetaOperatorDescriptor asterixAssignOp = createExternalAssignOp(spec, numSecondaryKeys,
- secondaryRecDesc);
+ AlgebricksMetaOperatorDescriptor asterixAssignOp =
+ createExternalAssignOp(spec, numSecondaryKeys, secondaryRecDesc);
// If any of the secondary fields are nullable, then add a select op that filters nulls.
AlgebricksMetaOperatorDescriptor selectOp = null;
@@ -165,13 +165,13 @@ public class SecondaryBTreeOperationsHelper extends SecondaryIndexOperationsHelp
AsterixStorageProperties storageProperties = propertiesProvider.getStorageProperties();
// Create secondary BTree bulk load op.
AbstractTreeIndexOperatorDescriptor secondaryBulkLoadOp;
- ExternalBTreeWithBuddyDataflowHelperFactory dataflowHelperFactory = new ExternalBTreeWithBuddyDataflowHelperFactory(
- mergePolicyFactory, mergePolicyFactoryProperties,
- new SecondaryIndexOperationTrackerProvider(dataset.getDatasetId()),
- AsterixRuntimeComponentsProvider.RUNTIME_PROVIDER,
- LSMBTreeWithBuddyIOOperationCallbackFactory.INSTANCE,
- storageProperties.getBloomFilterFalsePositiveRate(), new int[] { numSecondaryKeys },
- ExternalDatasetsRegistry.INSTANCE.getDatasetVersion(dataset), true);
+ ExternalBTreeWithBuddyDataflowHelperFactory dataflowHelperFactory =
+ new ExternalBTreeWithBuddyDataflowHelperFactory(mergePolicyFactory, mergePolicyFactoryProperties,
+ new SecondaryIndexOperationTrackerProvider(dataset.getDatasetId()),
+ AsterixRuntimeComponentsProvider.RUNTIME_PROVIDER,
+ LSMBTreeWithBuddyIOOperationCallbackFactory.INSTANCE,
+ storageProperties.getBloomFilterFalsePositiveRate(), new int[] { numSecondaryKeys },
+ ExternalDatasetsRegistry.INSTANCE.getDatasetVersion(dataset), true);
IOperatorDescriptor root;
if (externalFiles != null) {
// Transaction load
@@ -208,12 +208,12 @@ public class SecondaryBTreeOperationsHelper extends SecondaryIndexOperationsHelp
// Assign op.
AbstractOperatorDescriptor sourceOp = primaryScanOp;
- if (isEnforcingKeyTypes) {
+ if (isEnforcingKeyTypes && !enforcedItemType.equals(itemType)) {
sourceOp = createCastOp(spec, dataset.getDatasetType());
spec.connect(new OneToOneConnectorDescriptor(spec), primaryScanOp, 0, sourceOp, 0);
}
- AlgebricksMetaOperatorDescriptor asterixAssignOp = createAssignOp(spec, sourceOp, numSecondaryKeys,
- secondaryRecDesc);
+ AlgebricksMetaOperatorDescriptor asterixAssignOp =
+ createAssignOp(spec, sourceOp, numSecondaryKeys, secondaryRecDesc);
// If any of the secondary fields are nullable, then add a select op that filters nulls.
AlgebricksMetaOperatorDescriptor selectOp = null;
@@ -311,17 +311,17 @@ public class SecondaryBTreeOperationsHelper extends SecondaryIndexOperationsHelp
secondaryFieldAccessEvalFactories = new IScalarEvaluatorFactory[numSecondaryKeys + numFilterFields];
secondaryComparatorFactories = new IBinaryComparatorFactory[numSecondaryKeys + numPrimaryKeys];
secondaryBloomFilterKeyFields = new int[numSecondaryKeys];
- ISerializerDeserializer[] secondaryRecFields = new ISerializerDeserializer[numPrimaryKeys + numSecondaryKeys
- + numFilterFields];
- ISerializerDeserializer[] enforcedRecFields = new ISerializerDeserializer[1 + numPrimaryKeys
- + (dataset.hasMetaPart() ? 1 : 0) + numFilterFields];
- ITypeTraits[] enforcedTypeTraits = new ITypeTraits[1 + numPrimaryKeys + (dataset.hasMetaPart() ? 1 : 0)
- + numFilterFields];
+ ISerializerDeserializer[] secondaryRecFields =
+ new ISerializerDeserializer[numPrimaryKeys + numSecondaryKeys + numFilterFields];
+ ISerializerDeserializer[] enforcedRecFields =
+ new ISerializerDeserializer[1 + numPrimaryKeys + (dataset.hasMetaPart() ? 1 : 0) + numFilterFields];
+ ITypeTraits[] enforcedTypeTraits =
+ new ITypeTraits[1 + numPrimaryKeys + (dataset.hasMetaPart() ? 1 : 0) + numFilterFields];
secondaryTypeTraits = new ITypeTraits[numSecondaryKeys + numPrimaryKeys];
ISerializerDeserializerProvider serdeProvider = metadataProvider.getFormat().getSerdeProvider();
ITypeTraitProvider typeTraitProvider = metadataProvider.getFormat().getTypeTraitProvider();
- IBinaryComparatorFactoryProvider comparatorFactoryProvider = metadataProvider.getFormat()
- .getBinaryComparatorFactoryProvider();
+ IBinaryComparatorFactoryProvider comparatorFactoryProvider =
+ metadataProvider.getFormat().getBinaryComparatorFactoryProvider();
// Record column is 0 for external datasets, numPrimaryKeys for internal ones
int recordColumn = dataset.getDatasetType() == DatasetType.INTERNAL ? numPrimaryKeys : 0;
for (int i = 0; i < numSecondaryKeys; i++) {
@@ -336,8 +336,8 @@ public class SecondaryBTreeOperationsHelper extends SecondaryIndexOperationsHelp
}
secondaryFieldAccessEvalFactories[i] = metadataProvider.getFormat().getFieldAccessEvaluatorFactory(
isEnforcingKeyTypes ? enforcedItemType : sourceType, secondaryKeyFields.get(i), sourceColumn);
- Pair<IAType, Boolean> keyTypePair = Index.getNonNullableOpenFieldType(secondaryKeyTypes.get(i),
- secondaryKeyFields.get(i), sourceType);
+ Pair<IAType, Boolean> keyTypePair =
+ Index.getNonNullableOpenFieldType(secondaryKeyTypes.get(i), secondaryKeyFields.get(i), sourceType);
IAType keyType = keyTypePair.first;
anySecondaryKeyIsNullable = anySecondaryKeyIsNullable || keyTypePair.second;
ISerializerDeserializer keySerde = serdeProvider.getSerializerDeserializer(keyType);
@@ -380,8 +380,8 @@ public class SecondaryBTreeOperationsHelper extends SecondaryIndexOperationsHelp
ISerializerDeserializer serde = serdeProvider.getSerializerDeserializer(type);
secondaryRecFields[numPrimaryKeys + numSecondaryKeys] = serde;
enforcedRecFields[numPrimaryKeys + 1 + (dataset.hasMetaPart() ? 1 : 0)] = serde;
- enforcedTypeTraits[numPrimaryKeys + 1 + (dataset.hasMetaPart() ? 1 : 0)] = typeTraitProvider
- .getTypeTrait(type);
+ enforcedTypeTraits[numPrimaryKeys + 1 + (dataset.hasMetaPart() ? 1 : 0)] =
+ typeTraitProvider.getTypeTrait(type);
}
secondaryRecDesc = new RecordDescriptor(secondaryRecFields, secondaryTypeTraits);
enforcedRecDesc = new RecordDescriptor(enforcedRecFields, enforcedTypeTraits);
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/c8c067c5/asterixdb/asterix-app/src/main/java/org/apache/asterix/file/SecondaryIndexOperationsHelper.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/file/SecondaryIndexOperationsHelper.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/file/SecondaryIndexOperationsHelper.java
index e677f54..8ebe246 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/file/SecondaryIndexOperationsHelper.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/file/SecondaryIndexOperationsHelper.java
@@ -53,7 +53,7 @@ import org.apache.asterix.om.types.ARecordType;
import org.apache.asterix.om.types.IAType;
import org.apache.asterix.om.util.AsterixAppContextInfo;
import org.apache.asterix.runtime.evaluators.functions.AndDescriptor;
-import org.apache.asterix.runtime.evaluators.functions.CastRecordDescriptor;
+import org.apache.asterix.runtime.evaluators.functions.CastTypeDescriptor;
import org.apache.asterix.runtime.evaluators.functions.IsUnknownDescriptor;
import org.apache.asterix.runtime.evaluators.functions.NotDescriptor;
import org.apache.asterix.runtime.job.listener.JobEventListenerFactory;
@@ -173,8 +173,8 @@ public abstract class SecondaryIndexOperationsHelper {
case SINGLE_PARTITION_NGRAM_INVIX:
case LENGTH_PARTITIONED_WORD_INVIX:
case LENGTH_PARTITIONED_NGRAM_INVIX: {
- indexOperationsHelper = new SecondaryInvertedIndexOperationsHelper(physOptConf,
- asterixPropertiesProvider);
+ indexOperationsHelper =
+ new SecondaryInvertedIndexOperationsHelper(physOptConf, asterixPropertiesProvider);
break;
}
default: {
@@ -240,8 +240,8 @@ public abstract class SecondaryIndexOperationsHelper {
setSecondaryRecDescAndComparators(indexType, secondaryKeyFields, secondaryKeyTypes, gramLength,
metadataProvider);
numElementsHint = metadataProvider.getCardinalityPerPartitionHint(dataset);
- Pair<ILSMMergePolicyFactory, Map<String, String>> compactionInfo = DatasetUtils.getMergePolicyFactory(dataset,
- metadataProvider.getMetadataTxnContext());
+ Pair<ILSMMergePolicyFactory, Map<String, String>> compactionInfo =
+ DatasetUtils.getMergePolicyFactory(dataset, metadataProvider.getMetadataTxnContext());
mergePolicyFactory = compactionInfo.first;
mergePolicyFactoryProperties = compactionInfo.second;
@@ -276,8 +276,8 @@ public abstract class SecondaryIndexOperationsHelper {
protected void setPrimaryRecDescAndComparators() throws AlgebricksException {
List<List<String>> partitioningKeys = DatasetUtils.getPartitioningKeys(dataset);
int numPrimaryKeys = partitioningKeys.size();
- ISerializerDeserializer[] primaryRecFields = new ISerializerDeserializer[numPrimaryKeys + 1
- + (dataset.hasMetaPart() ? 1 : 0)];
+ ISerializerDeserializer[] primaryRecFields =
+ new ISerializerDeserializer[numPrimaryKeys + 1 + (dataset.hasMetaPart() ? 1 : 0)];
ITypeTraits[] primaryTypeTraits = new ITypeTraits[numPrimaryKeys + 1 + (dataset.hasMetaPart() ? 1 : 0)];
primaryComparatorFactories = new IBinaryComparatorFactory[numPrimaryKeys];
primaryBloomFilterKeyFields = new int[numPrimaryKeys];
@@ -287,12 +287,12 @@ public abstract class SecondaryIndexOperationsHelper {
indicators = ((InternalDatasetDetails) dataset.getDatasetDetails()).getKeySourceIndicator();
}
for (int i = 0; i < numPrimaryKeys; i++) {
- IAType keyType = (indicators == null || indicators.get(i) == 0)
- ? itemType.getSubFieldType(partitioningKeys.get(i))
- : metaType.getSubFieldType(partitioningKeys.get(i));
+ IAType keyType =
+ (indicators == null || indicators.get(i) == 0) ? itemType.getSubFieldType(partitioningKeys.get(i))
+ : metaType.getSubFieldType(partitioningKeys.get(i));
primaryRecFields[i] = serdeProvider.getSerializerDeserializer(keyType);
- primaryComparatorFactories[i] = AqlBinaryComparatorFactoryProvider.INSTANCE
- .getBinaryComparatorFactory(keyType, true);
+ primaryComparatorFactories[i] =
+ AqlBinaryComparatorFactoryProvider.INSTANCE.getBinaryComparatorFactory(keyType, true);
primaryTypeTraits[i] = AqlTypeTraitProvider.INSTANCE.getTypeTrait(keyType);
primaryBloomFilterKeyFields[i] = i;
}
@@ -398,8 +398,7 @@ public abstract class SecondaryIndexOperationsHelper {
}
protected AlgebricksMetaOperatorDescriptor createCastOp(JobSpecification spec, DatasetType dsType) {
- CastRecordDescriptor castFuncDesc = (CastRecordDescriptor) CastRecordDescriptor.FACTORY
- .createFunctionDescriptor();
+ CastTypeDescriptor castFuncDesc = (CastTypeDescriptor) CastTypeDescriptor.FACTORY.createFunctionDescriptor();
castFuncDesc.reset(enforcedItemType, itemType);
int[] outColumns = new int[1];
@@ -419,8 +418,8 @@ public abstract class SecondaryIndexOperationsHelper {
if (dataset.hasMetaPart()) {
projectionList[numPrimaryKeys + 1] = numPrimaryKeys + 1;
}
- IScalarEvaluatorFactory[] castEvalFact = new IScalarEvaluatorFactory[] {
- new ColumnAccessEvalFactory(recordIdx) };
+ IScalarEvaluatorFactory[] castEvalFact =
+ new IScalarEvaluatorFactory[] { new ColumnAccessEvalFactory(recordIdx) };
IScalarEvaluatorFactory[] sefs = new IScalarEvaluatorFactory[1];
sefs[0] = castFuncDesc.createEvaluatorFactory(castEvalFact);
AssignRuntimeFactory castAssign = new AssignRuntimeFactory(outColumns, sefs, projectionList);
@@ -463,10 +462,10 @@ public abstract class SecondaryIndexOperationsHelper {
for (int i = 0; i < numSecondaryKeyFields; i++) {
// Access column i, and apply 'is not null'.
ColumnAccessEvalFactory columnAccessEvalFactory = new ColumnAccessEvalFactory(i);
- IScalarEvaluatorFactory isUnknownEvalFactory = isUnknownDesc
- .createEvaluatorFactory(new IScalarEvaluatorFactory[] { columnAccessEvalFactory });
- IScalarEvaluatorFactory notEvalFactory = notDesc
- .createEvaluatorFactory(new IScalarEvaluatorFactory[] { isUnknownEvalFactory });
+ IScalarEvaluatorFactory isUnknownEvalFactory =
+ isUnknownDesc.createEvaluatorFactory(new IScalarEvaluatorFactory[] { columnAccessEvalFactory });
+ IScalarEvaluatorFactory notEvalFactory =
+ notDesc.createEvaluatorFactory(new IScalarEvaluatorFactory[] { isUnknownEvalFactory });
andArgsEvalFactories[i] = notEvalFactory;
}
IScalarEvaluatorFactory selectCond = null;