Merged asterix_stabilization r585:r605.
git-svn-id: https://asterixdb.googlecode.com/svn/branches/asterix_fix_agg@606 eaa15691-b419-025a-1212-ee371bd00084
diff --git a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/FuzzyEqRule.java b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/FuzzyEqRule.java
index c770e9f..1a2cd2a 100644
--- a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/FuzzyEqRule.java
+++ b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/FuzzyEqRule.java
@@ -140,6 +140,8 @@
FunctionIdentifier simFunctionIdentifier = FuzzyUtils.getFunctionIdentifier(simFuncName);
ScalarFunctionCallExpression similarityExp = new ScalarFunctionCallExpression(
FunctionUtils.getFunctionInfo(simFunctionIdentifier), similarityArgs);
+ // Add annotations from the original fuzzy-eq function.
+ similarityExp.getAnnotations().putAll(funcExp.getAnnotations());
ArrayList<Mutable<ILogicalExpression>> cmpArgs = new ArrayList<Mutable<ILogicalExpression>>();
cmpArgs.add(new MutableObject<ILogicalExpression>(similarityExp));
IAObject simThreshold = FuzzyUtils.getSimThreshold(aqlMetadata, simFuncName);
diff --git a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/FuzzyJoinRule.java b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/FuzzyJoinRule.java
index d5131a9..e700971 100644
--- a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/FuzzyJoinRule.java
+++ b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/FuzzyJoinRule.java
@@ -33,6 +33,7 @@
import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalVariable;
import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
+import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.IndexedNLJoinExpressionAnnotation;
import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
import edu.uci.ics.hyracks.algebricks.core.algebra.functions.AlgebricksBuiltinFunctions;
import edu.uci.ics.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
@@ -46,6 +47,11 @@
public class FuzzyJoinRule implements IAlgebraicRewriteRule {
+ private static HashSet<FunctionIdentifier> simFuncs = new HashSet<FunctionIdentifier>();
+ static {
+ simFuncs.add(AsterixBuiltinFunctions.SIMILARITY_JACCARD_CHECK);
+ }
+
private static final String AQLPLUS = ""
//
// -- - Stage 3 - --
@@ -133,20 +139,30 @@
return false;
}
- // find fuzzy join condition
+ // Find GET_ITEM function.
AbstractBinaryJoinOperator joinOp = (AbstractBinaryJoinOperator) op;
Mutable<ILogicalExpression> expRef = joinOp.getCondition();
- Mutable<ILogicalExpression> fuzzyExpRef = getSimilarityExpression(expRef);
- if (fuzzyExpRef == null) {
+ Mutable<ILogicalExpression> getItemExprRef = getSimilarityExpression(expRef);
+ if (getItemExprRef == null) {
return false;
}
-
- AbstractFunctionCallExpression funcExp = (AbstractFunctionCallExpression) fuzzyExpRef.getValue();
+ // Check if the GET_ITEM function is on one of the supported similarity-check functions.
+ AbstractFunctionCallExpression getItemFuncExpr = (AbstractFunctionCallExpression) getItemExprRef.getValue();
+ Mutable<ILogicalExpression> argRef = getItemFuncExpr.getArguments().get(0);
+ AbstractFunctionCallExpression simFuncExpr = (AbstractFunctionCallExpression) argRef.getValue();
+ if (!simFuncs.contains(simFuncExpr.getFunctionIdentifier())) {
+ return false;
+ }
+ // Skip this rule based on annotations.
+ if (simFuncExpr.getAnnotations().containsKey(IndexedNLJoinExpressionAnnotation.INSTANCE)) {
+ return false;
+ }
+
List<Mutable<ILogicalOperator>> inputOps = joinOp.getInputs();
ILogicalOperator leftInputOp = inputOps.get(0).getValue();
ILogicalOperator rightInputOp = inputOps.get(1).getValue();
- List<Mutable<ILogicalExpression>> inputExps = funcExp.getArguments();
+ List<Mutable<ILogicalExpression>> inputExps = simFuncExpr.getArguments();
ILogicalExpression inputExp0 = inputExps.get(0).getValue();
ILogicalExpression inputExp1 = inputExps.get(1).getValue();
@@ -315,9 +331,9 @@
ILogicalOperator outputOp = plan.getRoots().get(0).getValue();
SelectOperator extraSelect = null;
- if (fuzzyExpRef != expRef) {
+ if (getItemExprRef != expRef) {
// more than one join condition
- fuzzyExpRef.setValue(ConstantExpression.TRUE);
+ getItemExprRef.setValue(ConstantExpression.TRUE);
switch (joinOp.getJoinKind()) {
case INNER: {
extraSelect = new SelectOperator(expRef);
@@ -343,19 +359,19 @@
return true;
}
- /*
- * look for FUZZY_EQ function call
+ /**
+ * Look for GET_ITEM function call.
*/
private Mutable<ILogicalExpression> getSimilarityExpression(Mutable<ILogicalExpression> expRef) {
ILogicalExpression exp = expRef.getValue();
if (exp.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
- AbstractFunctionCallExpression funcExp = (AbstractFunctionCallExpression) exp;
- if (funcExp.getFunctionIdentifier().equals(AsterixBuiltinFunctions.FUZZY_EQ)) {
- return expRef;
- } else if (funcExp.getFunctionIdentifier().equals(AlgebricksBuiltinFunctions.AND)
- || funcExp.getFunctionIdentifier().equals(AlgebricksBuiltinFunctions.OR)) {
+ AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) exp;
+ if (funcExpr.getFunctionIdentifier().equals(AsterixBuiltinFunctions.GET_ITEM)) {
+ return expRef;
+ }
+ if (funcExpr.getFunctionIdentifier().equals(AlgebricksBuiltinFunctions.AND)) {
for (int i = 0; i < 2; i++) {
- Mutable<ILogicalExpression> expRefRet = getSimilarityExpression(funcExp.getArguments().get(i));
+ Mutable<ILogicalExpression> expRefRet = getSimilarityExpression(funcExpr.getArguments().get(i));
if (expRefRet != null) {
return expRefRet;
}
diff --git a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/SimilarityCheckRule.java b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/SimilarityCheckRule.java
index 60e5a3e..5726ce3 100644
--- a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/SimilarityCheckRule.java
+++ b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/SimilarityCheckRule.java
@@ -7,8 +7,10 @@
import org.apache.commons.lang3.mutable.MutableObject;
import edu.uci.ics.asterix.aql.util.FunctionUtils;
+import edu.uci.ics.asterix.om.base.ADouble;
import edu.uci.ics.asterix.om.base.AFloat;
import edu.uci.ics.asterix.om.base.AInt32;
+import edu.uci.ics.asterix.om.base.IAObject;
import edu.uci.ics.asterix.om.constants.AsterixConstantValue;
import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
@@ -127,7 +129,7 @@
Mutable<ILogicalExpression> simFuncExprRef = null;
ScalarFunctionCallExpression simCheckFuncExpr = null;
AssignOperator matchingAssign = null;
- for (int i = 0; i < assigns.size(); i++) {
+ for (int i = 0; i < assigns.size(); i++) {
AssignOperator assign = assigns.get(i);
for (int j = 0; j < assign.getVariables().size(); j++) {
// Check if variables match.
@@ -216,12 +218,21 @@
ScalarFunctionCallExpression simCheckFuncExpr = null;
// Look for jaccard function call, and GE or GT.
if (funcExpr.getFunctionIdentifier() == AsterixBuiltinFunctions.SIMILARITY_JACCARD) {
- AFloat aFloat = (AFloat) constVal.getObject();
- AFloat jaccThresh;
- if (normFuncIdent == AlgebricksBuiltinFunctions.GE) {
- jaccThresh = aFloat;
+ IAObject jaccThresh;
+ if (normFuncIdent == AlgebricksBuiltinFunctions.GE) {
+ if (constVal.getObject() instanceof AFloat) {
+ jaccThresh = constVal.getObject();
+ } else {
+ jaccThresh = new AFloat((float)((ADouble) constVal.getObject()).getDoubleValue());
+ }
} else if (normFuncIdent == AlgebricksBuiltinFunctions.GT) {
- float f = aFloat.getFloatValue() + Float.MIN_VALUE;
+ float threshVal = 0.0f;
+ if (constVal.getObject() instanceof AFloat) {
+ threshVal = ((AFloat) constVal.getObject()).getFloatValue();
+ } else {
+ threshVal = (float)((ADouble) constVal.getObject()).getDoubleValue();
+ }
+ float f = threshVal + Float.MIN_VALUE;
if (f > 1.0f) f = 1.0f;
jaccThresh = new AFloat(f);
} else {
@@ -253,6 +264,10 @@
simCheckFuncExpr = new ScalarFunctionCallExpression(
FunctionUtils.getFunctionInfo(AsterixBuiltinFunctions.EDIT_DISTANCE_CHECK), similarityArgs);
}
+ // Preserve all annotations.
+ if (simCheckFuncExpr != null) {
+ simCheckFuncExpr.getAnnotations().putAll(funcExpr.getAnnotations());
+ }
return simCheckFuncExpr;
}
diff --git a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/BTreeAccessMethod.java b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/BTreeAccessMethod.java
index 414dca3..6baf1b5 100644
--- a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/BTreeAccessMethod.java
+++ b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/am/BTreeAccessMethod.java
@@ -1,6 +1,7 @@
package edu.uci.ics.asterix.optimizer.rules.am;
import java.util.ArrayList;
+import java.util.BitSet;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -116,6 +117,9 @@
// If we can't figure out how to integrate a certain funcExpr into the current predicate, we just bail by setting this flag.
boolean couldntFigureOut = false;
boolean doneWithExprs = false;
+ // TODO: For now don't consider prefix searches.
+ BitSet setLowKeys = new BitSet(numSecondaryKeys);
+ BitSet setHighKeys = new BitSet(numSecondaryKeys);
// Go through the func exprs listed as optimizable by the chosen index,
// and formulate a range predicate on the secondary-index keys.
for (Integer exprIndex : exprList) {
@@ -132,11 +136,17 @@
lowKeyLimits[keyPos] = highKeyLimits[keyPos] = limit;
lowKeyInclusive[keyPos] = highKeyInclusive[keyPos] = true;
lowKeyConstants[keyPos] = highKeyConstants[keyPos] = optFuncExpr.getConstantVal(0);
+ setLowKeys.set(keyPos);
+ setHighKeys.set(keyPos);
} else {
couldntFigureOut = true;
}
- // Mmmm, we would need an inference system here.
- doneWithExprs = true;
+ // TODO: For now don't consider prefix searches.
+ // If high and low keys are set, we exit for now.
+ if (setLowKeys.cardinality() == numSecondaryKeys
+ && setHighKeys.cardinality() == numSecondaryKeys) {
+ doneWithExprs = true;
+ }
break;
}
case HIGH_EXCLUSIVE: {
diff --git a/asterix-algebra/src/main/java/edu/uci/ics/asterix/translator/AqlExpressionToPlanTranslator.java b/asterix-algebra/src/main/java/edu/uci/ics/asterix/translator/AqlExpressionToPlanTranslator.java
index 35fb3ae..e5712df 100644
--- a/asterix-algebra/src/main/java/edu/uci/ics/asterix/translator/AqlExpressionToPlanTranslator.java
+++ b/asterix-algebra/src/main/java/edu/uci/ics/asterix/translator/AqlExpressionToPlanTranslator.java
@@ -115,6 +115,7 @@
import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.BroadcastExpressionAnnotation;
import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.BroadcastExpressionAnnotation.BroadcastSide;
import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
+import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.IExpressionAnnotation;
import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.UnnestingFunctionCallExpression;
import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
@@ -577,6 +578,12 @@
f = new ScalarFunctionCallExpression(
FunctionUtils.getFunctionInfo(fi), args);
}
+ // Put hints into function call expr.
+ if (fcall.hasHints()) {
+ for (IExpressionAnnotation hint : fcall.getHints()) {
+ f.getAnnotations().put(hint, hint);
+ }
+ }
AssignOperator op = new AssignOperator(v,
new MutableObject<ILogicalExpression>(f));
if (topOp != null) {
@@ -828,6 +835,14 @@
}
}
+ // Add hints as annotations.
+ if (op.hasHints() && currExpr instanceof AbstractFunctionCallExpression) {
+ AbstractFunctionCallExpression currFuncExpr = (AbstractFunctionCallExpression) currExpr;
+ for (IExpressionAnnotation hint : op.getHints()) {
+ currFuncExpr.getAnnotations().put(hint, hint);
+ }
+ }
+
LogicalVariable assignedVar = context.newVar();
AssignOperator a = new AssignOperator(assignedVar,
new MutableObject<ILogicalExpression>(currExpr));
diff --git a/asterix-app/src/main/java/edu/uci/ics/asterix/api/common/APIFramework.java b/asterix-app/src/main/java/edu/uci/ics/asterix/api/common/APIFramework.java
index eae4c46..57b2ff0 100644
--- a/asterix-app/src/main/java/edu/uci/ics/asterix/api/common/APIFramework.java
+++ b/asterix-app/src/main/java/edu/uci/ics/asterix/api/common/APIFramework.java
@@ -469,36 +469,38 @@
ICompiler compiler = compilerFactory.createCompiler(planAndMetadata.getPlan(),
planAndMetadata.getMetadataProvider(), t.getVarCounter());
if (pc.isOptimize()) {
- compiler.optimize();
- if (true) {
- StringBuilder buffer = new StringBuilder();
- PlanPrettyPrinter.printPhysicalOps(planAndMetadata.getPlan(), buffer, 0);
- out.print(buffer);
- } else if (pc.isPrintOptimizedLogicalPlanParam()) {
- switch (pdf) {
- case HTML: {
- out.println("<H1>Optimized logical plan:</H1>");
- out.println("<PRE>");
- break;
- }
- case TEXT: {
- out.println("----------Optimized plan ");
- break;
- }
- }
-
- if (q != null) {
- StringBuilder buffer = new StringBuilder();
- PlanPrettyPrinter.printPlan(planAndMetadata.getPlan(), buffer, pvisitor, 0);
- out.print(buffer);
- }
- switch (pdf) {
- case HTML: {
- out.println("</PRE>");
- break;
- }
- }
- }
+ compiler.optimize();
+ if (pc.isPrintOptimizedLogicalPlanParam()) {
+ if (pc.isPrintPhysicalOpsOnly()) {
+ // For Optimizer tests.
+ StringBuilder buffer = new StringBuilder();
+ PlanPrettyPrinter.printPhysicalOps(planAndMetadata.getPlan(), buffer, 0);
+ out.print(buffer);
+ } else {
+ switch (pdf) {
+ case HTML: {
+ out.println("<H1>Optimized logical plan:</H1>");
+ out.println("<PRE>");
+ break;
+ }
+ case TEXT: {
+ out.println("----------Optimized plan ");
+ break;
+ }
+ }
+ if (q != null) {
+ StringBuilder buffer = new StringBuilder();
+ PlanPrettyPrinter.printPlan(planAndMetadata.getPlan(), buffer, pvisitor, 0);
+ out.print(buffer);
+ }
+ switch (pdf) {
+ case HTML: {
+ out.println("</PRE>");
+ break;
+ }
+ }
+ }
+ }
}
if (!pc.isGenerateJobSpec()) {
diff --git a/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/APIServlet.java b/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/APIServlet.java
index 15b959e..cf2b54c 100644
--- a/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/APIServlet.java
+++ b/asterix-app/src/main/java/edu/uci/ics/asterix/api/http/servlet/APIServlet.java
@@ -98,16 +98,17 @@
out.println("</PRE>");
}
} catch (ParseException pe) {
- String message = pe.getMessage();
- message = message.replace("<", "<");
- message = message.replace(">", ">");
- int pos = message.indexOf("line");
- int columnPos = message.indexOf(",", pos + 1 + "line".length());
- int lineNo = Integer.parseInt(message.substring(pos + "line".length() + 1, columnPos));
- String line = query.split("\n")[lineNo - 1];
- out.println("SyntaxError:" + message);
- out.println("==> " + line);
-
+ String message = pe.getMessage();
+ message = message.replace("<", "<");
+ message = message.replace(">", ">");
+ out.println("SyntaxError:" + message);
+ int pos = message.indexOf("line");
+ if (pos > 0) {
+ int columnPos = message.indexOf(",", pos + 1 + "line".length());
+ int lineNo = Integer.parseInt(message.substring(pos + "line".length() + 1, columnPos));
+ String line = query.split("\n")[lineNo - 1];
+ out.println("==> " + line);
+ }
} catch (Exception e) {
out.println(e.getMessage());
}
diff --git a/asterix-app/src/test/java/edu/uci/ics/asterix/test/optimizer/OptimizerTest.java b/asterix-app/src/test/java/edu/uci/ics/asterix/test/optimizer/OptimizerTest.java
index d60971b..b31fa92 100644
--- a/asterix-app/src/test/java/edu/uci/ics/asterix/test/optimizer/OptimizerTest.java
+++ b/asterix-app/src/test/java/edu/uci/ics/asterix/test/optimizer/OptimizerTest.java
@@ -126,7 +126,7 @@
AsterixJavaClient asterix = new AsterixJavaClient(
AsterixHyracksIntegrationUtil.getHyracksClientConnection(), query, plan);
try {
- asterix.compile(true, false, false, false, true, true, false);
+ asterix.compile(true, false, false, true, true, true, false);
} catch (AsterixException e) {
plan.close();
query.close();
diff --git a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-fuzzyeq-jaccard_01.aql b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-fuzzyeq-jaccard_01.aql
index f6f2f84..ffb9b8a 100644
--- a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-fuzzyeq-jaccard_01.aql
+++ b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-fuzzyeq-jaccard_01.aql
@@ -44,5 +44,5 @@
for $a in dataset('Customers')
for $b in dataset('Customers2')
-where $a.interests ~= $b.interests and $a.cid < $b.cid
+where $a.interests /*+ indexnl */ ~= $b.interests and $a.cid < $b.cid
return {"arec": $a, "brec": $b }
diff --git a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-fuzzyeq-jaccard_02.aql b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-fuzzyeq-jaccard_02.aql
index 1951e6f..f94fb85 100644
--- a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-fuzzyeq-jaccard_02.aql
+++ b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-fuzzyeq-jaccard_02.aql
@@ -44,5 +44,5 @@
for $a in dataset('Customers')
for $b in dataset('Customers2')
-where $a.interests ~= $b.interests and $a.cid < $b.cid
+where $a.interests /*+ indexnl */ ~= $b.interests and $a.cid < $b.cid
return {"arec": $a, "brec": $b }
diff --git a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-fuzzyeq-jaccard_03.aql b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-fuzzyeq-jaccard_03.aql
index d791b85..669c336 100644
--- a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-fuzzyeq-jaccard_03.aql
+++ b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-fuzzyeq-jaccard_03.aql
@@ -38,5 +38,5 @@
for $a in dataset('Customers')
for $b in dataset('Customers')
-where $a.interests ~= $b.interests and $a.cid < $b.cid
+where $a.interests /*+ indexnl */ ~= $b.interests and $a.cid < $b.cid
return {"arec": $a, "brec": $b }
diff --git a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-jaccard-check_01.aql b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-jaccard-check_01.aql
index 5f6f59b..63ff85c 100644
--- a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-jaccard-check_01.aql
+++ b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-jaccard-check_01.aql
@@ -41,5 +41,5 @@
for $a in dataset('Customers')
for $b in dataset('Customers2')
-where similarity-jaccard-check($a.interests, $b.interests, 0.7f)[0] and $a.cid < $b.cid
+where /*+ indexnl */ similarity-jaccard-check($a.interests, $b.interests, 0.7f)[0] and $a.cid < $b.cid
return {"arec": $a, "brec": $b }
diff --git a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-jaccard-check_02.aql b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-jaccard-check_02.aql
index 0754282..b708069 100644
--- a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-jaccard-check_02.aql
+++ b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-jaccard-check_02.aql
@@ -41,5 +41,5 @@
for $a in dataset('Customers')
for $b in dataset('Customers2')
-where similarity-jaccard-check($a.interests, $b.interests, 0.7f)[0] and $a.cid < $b.cid
+where /*+ indexnl */ similarity-jaccard-check($a.interests, $b.interests, 0.7f)[0] and $a.cid < $b.cid
return {"arec": $a, "brec": $b }
diff --git a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-jaccard-check_03.aql b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-jaccard-check_03.aql
index 4dbc4d5..21932ef 100644
--- a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-jaccard-check_03.aql
+++ b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-jaccard-check_03.aql
@@ -35,5 +35,5 @@
for $a in dataset('Customers')
for $b in dataset('Customers')
-where similarity-jaccard-check($a.interests, $b.interests, 0.7f)[0] and $a.cid < $b.cid
+where /*+ indexnl */ similarity-jaccard-check($a.interests, $b.interests, 0.7f)[0] and $a.cid < $b.cid
return {"arec": $a, "brec": $b }
diff --git a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-jaccard_01.aql b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-jaccard_01.aql
index ddf386e..c519be9 100644
--- a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-jaccard_01.aql
+++ b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-jaccard_01.aql
@@ -41,5 +41,5 @@
for $a in dataset('Customers')
for $b in dataset('Customers2')
-where similarity-jaccard($a.interests, $b.interests) >= 0.7f and $a.cid < $b.cid
+where /*+ indexnl */ similarity-jaccard($a.interests, $b.interests) >= 0.7f and $a.cid < $b.cid
return {"arec": $a, "brec": $b }
diff --git a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-jaccard_02.aql b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-jaccard_02.aql
index 50c3db6..7cd595a 100644
--- a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-jaccard_02.aql
+++ b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-jaccard_02.aql
@@ -41,5 +41,5 @@
for $a in dataset('Customers')
for $b in dataset('Customers2')
-where similarity-jaccard($a.interests, $b.interests) >= 0.7f and $a.cid < $b.cid
+where /*+ indexnl */ similarity-jaccard($a.interests, $b.interests) >= 0.7f and $a.cid < $b.cid
return {"arec": $a, "brec": $b }
diff --git a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-jaccard_03.aql b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-jaccard_03.aql
index 50729ba..c7ad4c4 100644
--- a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-jaccard_03.aql
+++ b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/olist-jaccard_03.aql
@@ -35,5 +35,5 @@
for $a in dataset('Customers')
for $b in dataset('Customers')
-where similarity-jaccard($a.interests, $b.interests) >= 0.7f and $a.cid < $b.cid
+where /*+ indexnl */ similarity-jaccard($a.interests, $b.interests) >= 0.7f and $a.cid < $b.cid
return {"arec": $a, "brec": $b }
diff --git a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-fuzzyeq-jaccard_01.aql b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-fuzzyeq-jaccard_01.aql
index 1fa479d..74d043e 100644
--- a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-fuzzyeq-jaccard_01.aql
+++ b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-fuzzyeq-jaccard_01.aql
@@ -44,5 +44,5 @@
for $a in dataset('Customers')
for $b in dataset('Customers2')
-where $a.interests ~= $b.interests and $a.cid < $b.cid
+where $a.interests /*+ indexnl */ ~= $b.interests and $a.cid < $b.cid
return {"arec": $a, "brec": $b }
diff --git a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-fuzzyeq-jaccard_02.aql b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-fuzzyeq-jaccard_02.aql
index e5b532f..da1ebe9 100644
--- a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-fuzzyeq-jaccard_02.aql
+++ b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-fuzzyeq-jaccard_02.aql
@@ -44,5 +44,5 @@
for $a in dataset('Customers')
for $b in dataset('Customers2')
-where $a.interests ~= $b.interests and $a.cid < $b.cid
+where $a.interests /*+ indexnl */ ~= $b.interests and $a.cid < $b.cid
return {"arec": $a, "brec": $b }
diff --git a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-fuzzyeq-jaccard_03.aql b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-fuzzyeq-jaccard_03.aql
index a881c89..283d80a 100644
--- a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-fuzzyeq-jaccard_03.aql
+++ b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-fuzzyeq-jaccard_03.aql
@@ -38,5 +38,5 @@
for $a in dataset('Customers')
for $b in dataset('Customers')
-where $a.interests ~= $b.interests and $a.cid < $b.cid
+where $a.interests /*+ indexnl */ ~= $b.interests and $a.cid < $b.cid
return {"arec": $a, "brec": $b }
diff --git a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-jaccard-check_01.aql b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-jaccard-check_01.aql
index 5d95894..7f5e92d 100644
--- a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-jaccard-check_01.aql
+++ b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-jaccard-check_01.aql
@@ -41,5 +41,5 @@
for $a in dataset('Customers')
for $b in dataset('Customers2')
-where similarity-jaccard-check($a.interests, $b.interests, 0.7f)[0] and $a.cid < $b.cid
+where /*+ indexnl */ similarity-jaccard-check($a.interests, $b.interests, 0.7f)[0] and $a.cid < $b.cid
return {"arec": $a, "brec": $b }
diff --git a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-jaccard-check_02.aql b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-jaccard-check_02.aql
index 561e15f..d367bb8 100644
--- a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-jaccard-check_02.aql
+++ b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-jaccard-check_02.aql
@@ -41,5 +41,5 @@
for $a in dataset('Customers')
for $b in dataset('Customers2')
-where similarity-jaccard-check($a.interests, $b.interests, 0.7f)[0] and $a.cid < $b.cid
+where /*+ indexnl */ similarity-jaccard-check($a.interests, $b.interests, 0.7f)[0] and $a.cid < $b.cid
return {"arec": $a, "brec": $b }
diff --git a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-jaccard-check_03.aql b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-jaccard-check_03.aql
index 87d78e5..0bdd09e 100644
--- a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-jaccard-check_03.aql
+++ b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-jaccard-check_03.aql
@@ -35,5 +35,5 @@
for $a in dataset('Customers')
for $b in dataset('Customers')
-where similarity-jaccard-check($a.interests, $b.interests, 0.7f)[0] and $a.cid < $b.cid
+where /*+ indexnl */ similarity-jaccard-check($a.interests, $b.interests, 0.7f)[0] and $a.cid < $b.cid
return {"arec": $a, "brec": $b }
diff --git a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-jaccard_01.aql b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-jaccard_01.aql
index 864ede7..8188e07 100644
--- a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-jaccard_01.aql
+++ b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-jaccard_01.aql
@@ -41,5 +41,5 @@
for $a in dataset('Customers')
for $b in dataset('Customers2')
-where similarity-jaccard($a.interests, $b.interests) >= 0.7f and $a.cid < $b.cid
+where /*+ indexnl */ similarity-jaccard($a.interests, $b.interests) >= 0.7f and $a.cid < $b.cid
return {"arec": $a, "brec": $b }
diff --git a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-jaccard_02.aql b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-jaccard_02.aql
index 4d9f89e..ba64230 100644
--- a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-jaccard_02.aql
+++ b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-jaccard_02.aql
@@ -41,5 +41,5 @@
for $a in dataset('Customers')
for $b in dataset('Customers2')
-where similarity-jaccard($a.interests, $b.interests) >= 0.7f and $a.cid < $b.cid
+where /*+ indexnl */ similarity-jaccard($a.interests, $b.interests) >= 0.7f and $a.cid < $b.cid
return {"arec": $a, "brec": $b }
diff --git a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-jaccard_03.aql b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-jaccard_03.aql
index 5eae45b..5007579 100644
--- a/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-jaccard_03.aql
+++ b/asterix-app/src/test/resources/optimizerts/queries/inverted-index-join/ulist-jaccard_03.aql
@@ -35,5 +35,5 @@
for $a in dataset('Customers')
for $b in dataset('Customers')
-where similarity-jaccard($a.interests, $b.interests) >= 0.7f and $a.cid < $b.cid
+where /*+ indexnl */ similarity-jaccard($a.interests, $b.interests) >= 0.7f and $a.cid < $b.cid
return {"arec": $a, "brec": $b }
diff --git a/asterix-app/src/test/resources/optimizerts/queries/orders-composite-index-search.aql b/asterix-app/src/test/resources/optimizerts/queries/orders-composite-index-search.aql
new file mode 100644
index 0000000..d82be3c
--- /dev/null
+++ b/asterix-app/src/test/resources/optimizerts/queries/orders-composite-index-search.aql
@@ -0,0 +1,30 @@
+drop dataverse index_search if exists;
+create dataverse index_search;
+use dataverse index_search;
+
+create type OrderType as closed {
+ o_orderkey: int32,
+ o_custkey: int32,
+ o_orderstatus: string,
+ o_totalprice: double,
+ o_orderdate: string,
+ o_orderpriority: string,
+ o_clerk: string,
+ o_shippriority: int32,
+ o_comment: string
+}
+
+create dataset Orders(OrderType) partitioned by key o_orderkey;
+
+create index idx_Custkey_Orderstatus on Orders(o_custkey, o_orderstatus);
+
+write output to nc1:"/tmp/index_search.adm";
+
+for $o in dataset('Orders')
+where
+ $o.o_custkey = 40 and $o.o_orderstatus = "P"
+return {
+ "o_orderkey": $o.o_orderkey,
+ "o_custkey": $o.o_custkey,
+ "o_orderstatus": $o.o_orderstatus
+}
diff --git a/asterix-app/src/test/resources/optimizerts/results/orders-composite-index-search.plan b/asterix-app/src/test/resources/optimizerts/results/orders-composite-index-search.plan
new file mode 100644
index 0000000..2b19a64
--- /dev/null
+++ b/asterix-app/src/test/resources/optimizerts/results/orders-composite-index-search.plan
@@ -0,0 +1,16 @@
+-- SINK_WRITE |PARTITIONED|
+ -- RANDOM_MERGE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |LOCAL|
+ -- STABLE_SORT [$$23(ASC)] |LOCAL|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterix-app/src/test/resources/runtimets/ignore.txt b/asterix-app/src/test/resources/runtimets/ignore.txt
index 4467bc2..172d920 100644
--- a/asterix-app/src/test/resources/runtimets/ignore.txt
+++ b/asterix-app/src/test/resources/runtimets/ignore.txt
@@ -2,13 +2,7 @@
scan/spatial_types_02.aql
scan/temp_types_02.aql
fuzzyjoin/dblp-splits-3_1.aql
-fuzzyjoin/dblp-csx-aqlplus_1.aql
-fuzzyjoin/dblp-csx-aqlplus_2.aql
-fuzzyjoin/dblp-csx-aqlplus_3.aql
fuzzyjoin/events-users-aqlplus_1.aql
-fuzzyjoin/dblp-aqlplus_1.aql
-fuzzyjoin/dblp-csx-dblp-aqlplus_1.aql
-fuzzyjoin/user-vis-int-vis-user-lot-aqlplus_1.aql
subset-collection/04.aql
custord/freq-clerk.aql
custord/denorm-cust-order_01.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/index-join/inverted-index-olist-jaccard.aql b/asterix-app/src/test/resources/runtimets/queries/index-join/inverted-index-olist-jaccard.aql
index 91fcd80..ddccd2e 100644
--- a/asterix-app/src/test/resources/runtimets/queries/index-join/inverted-index-olist-jaccard.aql
+++ b/asterix-app/src/test/resources/runtimets/queries/index-join/inverted-index-olist-jaccard.aql
@@ -41,7 +41,7 @@
for $a in dataset('Customers')
for $b in dataset('Customers2')
-where similarity-jaccard($a.interests, $b.interests) >= 0.9f
+where /*+ indexnl */ similarity-jaccard($a.interests, $b.interests) >= 0.9f
and $a.cid < $b.cid
order by $a.cid, $b.cid
return { "a": $a.interests, "b": $b.interests }
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/runtimets/queries/index-join/inverted-index-ulist-jaccard.aql b/asterix-app/src/test/resources/runtimets/queries/index-join/inverted-index-ulist-jaccard.aql
index 2b2d52c..e0dba06 100644
--- a/asterix-app/src/test/resources/runtimets/queries/index-join/inverted-index-ulist-jaccard.aql
+++ b/asterix-app/src/test/resources/runtimets/queries/index-join/inverted-index-ulist-jaccard.aql
@@ -41,7 +41,7 @@
for $a in dataset('Customers')
for $b in dataset('Customers2')
-where similarity-jaccard($a.interests, $b.interests) >= 0.9f
+where /*+ indexnl */ similarity-jaccard($a.interests, $b.interests) >= 0.9f
and $a.cid < $b.cid
order by $a.cid, $b.cid
return { "a": $a.interests, "b": $b.interests }
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/runtimets/queries/string/concat1.aql b/asterix-app/src/test/resources/runtimets/queries/string/concat_01.aql
similarity index 81%
rename from asterix-app/src/test/resources/runtimets/queries/string/concat1.aql
rename to asterix-app/src/test/resources/runtimets/queries/string/concat_01.aql
index a6ce63b..2a0b1ab 100644
--- a/asterix-app/src/test/resources/runtimets/queries/string/concat1.aql
+++ b/asterix-app/src/test/resources/runtimets/queries/string/concat_01.aql
@@ -2,7 +2,7 @@
create dataverse test;
use dataverse test;
-write output to nc1:"rttest/string_concat1.adm";
+write output to nc1:"rttest/string_concat_01.adm";
let $x := ["aa", "25991", "bb", "31526"]
let $c := string-concat($x)
diff --git a/asterix-app/src/test/resources/runtimets/queries/string/concat_02.aql b/asterix-app/src/test/resources/runtimets/queries/string/concat_02.aql
new file mode 100644
index 0000000..c716fcb
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/string/concat_02.aql
@@ -0,0 +1,15 @@
+/*
+ * Description : Test concat-string function with nulls in the list which is passed as an argument.
+ * Success : Yes
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+use dataverse test;
+
+write output to nc1:"rttest/string_concat_02.adm";
+
+let $a := string-concat([null])
+let $b := string-concat([null, "foo"])
+let $c := string-concat(["foo", null])
+return {"a": $a, "b": $b, "c": $c}
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/runtimets/queries/string/length.aql b/asterix-app/src/test/resources/runtimets/queries/string/length_01.aql
similarity index 81%
rename from asterix-app/src/test/resources/runtimets/queries/string/length.aql
rename to asterix-app/src/test/resources/runtimets/queries/string/length_01.aql
index d78d986..8186f6b 100644
--- a/asterix-app/src/test/resources/runtimets/queries/string/length.aql
+++ b/asterix-app/src/test/resources/runtimets/queries/string/length_01.aql
@@ -2,7 +2,7 @@
create dataverse test;
use dataverse test;
-write output to nc1:"rttest/string_length.adm";
+write output to nc1:"rttest/string_length_01.adm";
let $c1 := string-length("hellow")
let $c2 := string-length("")
diff --git a/asterix-app/src/test/resources/runtimets/queries/string/length_02.aql b/asterix-app/src/test/resources/runtimets/queries/string/length_02.aql
new file mode 100644
index 0000000..3cc33e7
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/string/length_02.aql
@@ -0,0 +1,8 @@
+drop dataverse test if exists;
+create dataverse test;
+use dataverse test;
+
+write output to nc1:"rttest/string_length_02.adm";
+
+for $x in ["ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "ninety"]
+return string-length($x)
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/runtimets/results/string/concat1.adm b/asterix-app/src/test/resources/runtimets/results/string/concat_01.adm
similarity index 100%
rename from asterix-app/src/test/resources/runtimets/results/string/concat1.adm
rename to asterix-app/src/test/resources/runtimets/results/string/concat_01.adm
diff --git a/asterix-app/src/test/resources/runtimets/results/string/concat_02.adm b/asterix-app/src/test/resources/runtimets/results/string/concat_02.adm
new file mode 100644
index 0000000..ba4be9f
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/string/concat_02.adm
@@ -0,0 +1 @@
+{ "a": null, "b": null, "c": null }
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/runtimets/results/string/length.adm b/asterix-app/src/test/resources/runtimets/results/string/length_01.adm
similarity index 100%
rename from asterix-app/src/test/resources/runtimets/results/string/length.adm
rename to asterix-app/src/test/resources/runtimets/results/string/length_01.adm
diff --git a/asterix-app/src/test/resources/runtimets/results/string/length_02.adm b/asterix-app/src/test/resources/runtimets/results/string/length_02.adm
new file mode 100644
index 0000000..930236d
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/string/length_02.adm
@@ -0,0 +1,8 @@
+3
+6
+6
+5
+5
+5
+7
+6
diff --git a/asterix-app/src/test/resources/runtimets/results/writers/serialized_01.adm b/asterix-app/src/test/resources/runtimets/results/writers/serialized_01.adm
index f2aee15..c503a33 100644
--- a/asterix-app/src/test/resources/runtimets/results/writers/serialized_01.adm
+++ b/asterix-app/src/test/resources/runtimets/results/writers/serialized_01.adm
Binary files differ
diff --git a/asterix-aql/src/main/java/edu/uci/ics/asterix/aql/base/AbstractExpression.java b/asterix-aql/src/main/java/edu/uci/ics/asterix/aql/base/AbstractExpression.java
new file mode 100644
index 0000000..e83a1ed
--- /dev/null
+++ b/asterix-aql/src/main/java/edu/uci/ics/asterix/aql/base/AbstractExpression.java
@@ -0,0 +1,25 @@
+package edu.uci.ics.asterix.aql.base;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.IExpressionAnnotation;
+
+public abstract class AbstractExpression implements Expression {
+ protected List<IExpressionAnnotation> hints;
+
+ public void addHint(IExpressionAnnotation hint) {
+ if (hints == null) {
+ hints = new ArrayList<IExpressionAnnotation>();
+ }
+ hints.add(hint);
+ }
+
+ public boolean hasHints() {
+ return hints != null;
+ }
+
+ public List<IExpressionAnnotation> getHints() {
+ return hints;
+ }
+}
diff --git a/asterix-aql/src/main/java/edu/uci/ics/asterix/aql/expression/CallExpr.java b/asterix-aql/src/main/java/edu/uci/ics/asterix/aql/expression/CallExpr.java
index cda7e69..d1f83b0 100644
--- a/asterix-aql/src/main/java/edu/uci/ics/asterix/aql/expression/CallExpr.java
+++ b/asterix-aql/src/main/java/edu/uci/ics/asterix/aql/expression/CallExpr.java
@@ -2,17 +2,18 @@
import java.util.List;
+import edu.uci.ics.asterix.aql.base.AbstractExpression;
import edu.uci.ics.asterix.aql.base.Expression;
import edu.uci.ics.asterix.aql.expression.visitor.IAqlExpressionVisitor;
import edu.uci.ics.asterix.aql.expression.visitor.IAqlVisitorWithVoidReturn;
import edu.uci.ics.asterix.common.exceptions.AsterixException;
import edu.uci.ics.asterix.om.functions.AsterixFunction;
-public class CallExpr implements Expression {
+public class CallExpr extends AbstractExpression {
private AsterixFunction ident;
private List<Expression> exprList;
- private boolean isBuiltin;
-
+ private boolean isBuiltin;
+
public CallExpr() {
}
@@ -32,7 +33,7 @@
public List<Expression> getExprList() {
return exprList;
}
-
+
public void setExprList(List<Expression> exprList) {
this.exprList = exprList;
}
diff --git a/asterix-aql/src/main/java/edu/uci/ics/asterix/aql/expression/OperatorExpr.java b/asterix-aql/src/main/java/edu/uci/ics/asterix/aql/expression/OperatorExpr.java
index b6bb55b..23d2179 100644
--- a/asterix-aql/src/main/java/edu/uci/ics/asterix/aql/expression/OperatorExpr.java
+++ b/asterix-aql/src/main/java/edu/uci/ics/asterix/aql/expression/OperatorExpr.java
@@ -2,12 +2,13 @@
import java.util.ArrayList;
+import edu.uci.ics.asterix.aql.base.AbstractExpression;
import edu.uci.ics.asterix.aql.base.Expression;
import edu.uci.ics.asterix.aql.expression.visitor.IAqlExpressionVisitor;
import edu.uci.ics.asterix.aql.expression.visitor.IAqlVisitorWithVoidReturn;
import edu.uci.ics.asterix.common.exceptions.AsterixException;
-public class OperatorExpr implements Expression {
+public class OperatorExpr extends AbstractExpression {
private ArrayList<Expression> exprList;
private ArrayList<OperatorType> opList;
private ArrayList<Integer> exprBroadcastIdx;
diff --git a/asterix-aql/src/main/javacc/AQL.jj b/asterix-aql/src/main/javacc/AQL.jj
index 3e63b35..9a47c77 100644
--- a/asterix-aql/src/main/javacc/AQL.jj
+++ b/asterix-aql/src/main/javacc/AQL.jj
@@ -39,6 +39,8 @@
import edu.uci.ics.asterix.common.annotations.*;
import edu.uci.ics.asterix.common.exceptions.AsterixException;
import edu.uci.ics.asterix.om.functions.AsterixFunction;
+import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.IExpressionAnnotation;
+import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.IndexedNLJoinExpressionAnnotation;
public class AQLParser extends ScopeChecker {
@@ -59,6 +61,7 @@
// optimizer hints
private static final String HASH_GROUP_BY_HINT = "hash";
private static final String BROADCAST_JOIN_HINT = "bcast";
+ private static final String INDEXED_NESTED_LOOP_JOIN_HINT = "indexnl";
private static final String INMEMORY_HINT = "inmem";
private static final String VAL_FILE_HINT = "val-files";
private static final String VAL_FILE_SAME_INDEX_HINT = "val-file-same-idx";
@@ -1248,14 +1251,15 @@
OperatorExpr op = null;
Expression operand = null;
boolean broadcast = false;
+ IExpressionAnnotation annotation = null;
}
{
operand = AddExpr()
- {
- if (operand instanceof VariableExpr) {
- String hint = getHint(token);
+ {
+ if (operand instanceof VariableExpr) {
+ String hint = getHint(token);
if (hint != null && hint.equals(BROADCAST_JOIN_HINT)) {
- broadcast = true;
+ broadcast = true;
}
}
}
@@ -1263,6 +1267,10 @@
(
LOOKAHEAD(2)( "<" | ">" | "<=" | ">=" | "=" | "!=" |"~=")
{
+ String mhint = getHint(token);
+ if (mhint != null && mhint.equals(INDEXED_NESTED_LOOP_JOIN_HINT)) {
+ annotation = IndexedNLJoinExpressionAnnotation.INSTANCE;
+ }
if (op == null) {
op = new OperatorExpr();
op.addOperand(operand, broadcast);
@@ -1275,18 +1283,21 @@
operand = AddExpr()
{
- broadcast = false;
- if (operand instanceof VariableExpr) {
- String hint = getHint(token);
+ broadcast = false;
+ if (operand instanceof VariableExpr) {
+ String hint = getHint(token);
if (hint != null && hint.equals(BROADCAST_JOIN_HINT)) {
broadcast = true;
}
- }
+ }
op.addOperand(operand, broadcast);
}
)?
{
+ if (annotation != null) {
+ op.addHint(annotation);
+ }
return op==null? operand: op;
}
}
@@ -1730,14 +1741,18 @@
Expression FunctionCallExpr() throws ParseException:
{
CallExpr pf = new CallExpr();
- List<Expression > argList = new ArrayList<Expression >();
+ List<Expression> argList = new ArrayList<Expression>();
Expression tmp;
int arity = 0;
Token funcName;
}
-{
+{
( <IDENTIFIER> | <DATASET> )
{
+ String hint = getHint(token);
+ if (hint != null && hint.startsWith(INDEXED_NESTED_LOOP_JOIN_HINT)) {
+ pf.addHint(IndexedNLJoinExpressionAnnotation.INSTANCE);
+ }
funcName = getToken(0);
}
<LEFTPAREN> (tmp = Expression()
@@ -1746,7 +1761,7 @@
arity ++;
} ("," tmp = Expression() { argList.add(tmp); arity++; })*)? <RIGHTPAREN>
- {
+ {
AsterixFunction fd = lookupFunctionSignature(funcName.toString(), arity);
if(fd == null)
{
diff --git a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/entities/Index.java b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/entities/Index.java
index 7c6d9ed..2aade27 100644
--- a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/entities/Index.java
+++ b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/entities/Index.java
@@ -123,4 +123,27 @@
}
throw new AlgebricksException("Could not find field " + expr + " in the schema.");
}
+
+ @Override
+ public int hashCode() {
+ return indexName.hashCode() ^ datasetName.hashCode() ^ dataverseName.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof Index)) {
+ return false;
+ }
+ Index otherIndex = (Index) other;
+ if (!indexName.equals(otherIndex.getIndexName())) {
+ return false;
+ }
+ if (!datasetName.equals(otherIndex.getDatasetName())) {
+ return false;
+ }
+ if (!dataverseName.equals(otherIndex.getDataverseName())) {
+ return false;
+ }
+ return true;
+ }
}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/formats/nontagged/AqlBinaryComparatorFactoryProvider.java b/asterix-om/src/main/java/edu/uci/ics/asterix/formats/nontagged/AqlBinaryComparatorFactoryProvider.java
index ede7b99..93167cf 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/formats/nontagged/AqlBinaryComparatorFactoryProvider.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/formats/nontagged/AqlBinaryComparatorFactoryProvider.java
@@ -2,6 +2,7 @@
import java.io.Serializable;
+import edu.uci.ics.asterix.dataflow.data.nontagged.comparators.ADateTimeAscBinaryComparatorFactory;
import edu.uci.ics.asterix.dataflow.data.nontagged.comparators.AObjectAscBinaryComparatorFactory;
import edu.uci.ics.asterix.dataflow.data.nontagged.comparators.AObjectDescBinaryComparatorFactory;
import edu.uci.ics.asterix.dataflow.data.nontagged.comparators.BooleanBinaryComparatorFactory;
@@ -55,7 +56,7 @@
public IBinaryComparatorFactory getBinaryComparatorFactory(Object type, boolean ascending) {
if (type == null) {
return anyBinaryComparatorFactory(ascending);
- }
+ }
IAType aqlType = (IAType) type;
switch (aqlType.getTypeTag()) {
case ANY:
@@ -100,6 +101,9 @@
case RECTANGLE: {
return addOffset(RectangleBinaryComparatorFactory.INSTANCE, ascending);
}
+ case DATETIME: {
+ return addOffset(ADateTimeAscBinaryComparatorFactory.INSTANCE, ascending);
+ }
default: {
throw new NotImplementedException("No binary comparator factory implemented for type "
+ aqlType.getTypeTag() + " .");
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/AsterixBuiltinFunctions.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/AsterixBuiltinFunctions.java
index c27be6e..a624cf9 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/AsterixBuiltinFunctions.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/AsterixBuiltinFunctions.java
@@ -434,7 +434,7 @@
// and then, Asterix builtin functions
add(ANY_COLLECTION_MEMBER, NonTaggedCollectionMemberResultType.INSTANCE);
- add(AVG, OptionalADoubleTypeComputer.INSTANCE);
+ addPrivateFunction(AVG, OptionalADoubleTypeComputer.INSTANCE);
add(BOOLEAN_CONSTRUCTOR, UnaryBooleanOrNullFunctionTypeComputer.INSTANCE);
add(CARET, NonTaggedNumericAddSubMulDivTypeComputer.INSTANCE);
add(CIRCLE_CONSTRUCTOR, OptionalACircleTypeComputer.INSTANCE);
@@ -456,7 +456,7 @@
}
});
add(CONTAINS, ABooleanTypeComputer.INSTANCE);
- add(COUNT, AInt32TypeComputer.INSTANCE);
+ addPrivateFunction(COUNT, AInt32TypeComputer.INSTANCE);
add(COUNTHASHED_GRAM_TOKENS, OrderedListOfAInt32TypeComputer.INSTANCE);
add(COUNTHASHED_WORD_TOKENS, OrderedListOfAInt32TypeComputer.INSTANCE);
add(CREATE_CIRCLE, ACircleTypeComputer.INSTANCE);
@@ -491,7 +491,7 @@
add(GET_HANDLE, null); // TODO
add(GET_ITEM, NonTaggedGetItemResultType.INSTANCE);
add(GET_DATA, null); // TODO
- add(GLOBAL_AVG, OptionalADoubleTypeComputer.INSTANCE);
+ addPrivateFunction(GLOBAL_AVG, OptionalADoubleTypeComputer.INSTANCE);
add(GRAM_TOKENS, OrderedListOfAStringTypeComputer.INSTANCE);
add(GLOBAL_AVG, OptionalADoubleTypeComputer.INSTANCE);
add(HASHED_GRAM_TOKENS, OrderedListOfAInt32TypeComputer.INSTANCE);
@@ -512,7 +512,7 @@
add(LIKE, BinaryBooleanOrNullFunctionTypeComputer.INSTANCE);
add(LINE_CONSTRUCTOR, OptionalALineTypeComputer.INSTANCE);
add(LISTIFY, OrderedListConstructorResultType.INSTANCE);
- add(LOCAL_AVG, NonTaggedLocalAvgTypeComputer.INSTANCE);
+ addPrivateFunction(LOCAL_AVG, NonTaggedLocalAvgTypeComputer.INSTANCE);
add(MAKE_FIELD_INDEX_HANDLE, null); // TODO
add(MAKE_FIELD_NAME_HANDLE, null); // TODO
add(MAX, NonTaggedSumTypeComputer.INSTANCE);
@@ -537,7 +537,7 @@
add(STRING_TO_CODEPOINT, OrderedListOfAInt32TypeComputer.INSTANCE);
add(CODEPOINT_TO_STRING, AStringTypeComputer.INSTANCE);
- add(STRING_CONCAT, AStringTypeComputer.INSTANCE);
+ add(STRING_CONCAT, OptionalAStringTypeComputer.INSTANCE);
add(SUBSTRING2, Substring2TypeComputer.INSTANCE);
add(STRING_LENGTH, UnaryStringInt32OrNullTypeComputer.INSTANCE);
add(STRING_LOWERCASE, UnaryStringOrNullTypeComputer.INSTANCE);
@@ -625,7 +625,7 @@
}
});
add(SUBSTRING, SubstringTypeComputer.INSTANCE);
- add(SUM, NonTaggedSumTypeComputer.INSTANCE);
+ addPrivateFunction(SUM, NonTaggedSumTypeComputer.INSTANCE);
add(LOCAL_SUM, NonTaggedSumTypeComputer.INSTANCE);
add(SWITCH_CASE, NonTaggedSwitchCaseComputer.INSTANCE);
add(REG_EXP, ABooleanTypeComputer.INSTANCE);
@@ -829,6 +829,13 @@
asterixFunctionIdToInfo.put(fi, functionInfo);
}
+ private static IFunctionInfo addPrivateFunction(FunctionIdentifier fi, IResultTypeComputer typeComputer) {
+ IFunctionInfo functionInfo = getAsterixFunctionInfo(fi);
+ builtinFunctionsSet.put(functionInfo, functionInfo);
+ funTypeComputer.put(functionInfo, typeComputer);
+ return functionInfo;
+ }
+
private static void addAgg(FunctionIdentifier fi) {
builtinAggregateFunctions.add(getAsterixFunctionInfo(fi));
}
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/typecomputer/impl/NonTaggedCollectionMemberResultType.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/typecomputer/impl/NonTaggedCollectionMemberResultType.java
index 7caf99b..2a39d83 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/om/typecomputer/impl/NonTaggedCollectionMemberResultType.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/typecomputer/impl/NonTaggedCollectionMemberResultType.java
@@ -1,8 +1,5 @@
package edu.uci.ics.asterix.om.typecomputer.impl;
-import java.util.ArrayList;
-import java.util.List;
-
import edu.uci.ics.asterix.om.typecomputer.base.IResultTypeComputer;
import edu.uci.ics.asterix.om.types.ATypeTag;
import edu.uci.ics.asterix.om.types.AUnionType;
@@ -28,18 +25,13 @@
IMetadataProvider<?, ?> metadataProvider) throws AlgebricksException {
AbstractFunctionCallExpression f = (AbstractFunctionCallExpression) expression;
IAType type = (IAType) env.getType(f.getArguments().get(0).getValue());
- if (type.getTypeTag() == ATypeTag.UNION && NonTaggedFormatUtil.isOptionalField((AUnionType) type))
+ if (type.getTypeTag() == ATypeTag.UNION && NonTaggedFormatUtil.isOptionalField((AUnionType) type)) {
type = ((AUnionType) type).getUnionList().get(NonTaggedFormatUtil.OPTIONAL_TYPE_INDEX_IN_UNION_LIST);
- if (type.getTypeTag() == ATypeTag.ANY)
- return BuiltinType.ANY;
- else {
- if (((AbstractCollectionType) type).getItemType().getTypeTag() == ATypeTag.NULL)
- return BuiltinType.ANULL;
- List<IAType> unionList = new ArrayList<IAType>();
- unionList.add(BuiltinType.ANULL);
- unionList.add(((AbstractCollectionType) type).getItemType());
- return new AUnionType(unionList, "CollectionMemberResult");
}
+ if (type.getTypeTag() == ATypeTag.ANY) {
+ return BuiltinType.ANY;
+ }
+ return ((AbstractCollectionType) type).getItemType();
}
}
\ No newline at end of file
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/GlobalAvgAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/GlobalAvgAggregateDescriptor.java
index fe2242c..7d49228 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/GlobalAvgAggregateDescriptor.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/GlobalAvgAggregateDescriptor.java
@@ -133,12 +133,19 @@
+ EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(serBytes[0]));
}
}
- int offset1 = ARecordSerializerDeserializer.getFieldOffsetById(serBytes, 0, 1, false);
+
+ // The record length helps us determine whether the input record fields are nullable.
+ int recordLength = ARecordSerializerDeserializer.getRecordLength(serBytes, 1);
+ int nullBitmapSize = 1;
+ if (recordLength == 29) {
+ nullBitmapSize = 0;
+ }
+ int offset1 = ARecordSerializerDeserializer.getFieldOffsetById(serBytes, 0, nullBitmapSize, false);
if (offset1 == 0) // the sum is null
metNull = true;
else
globalSum += ADoubleSerializerDeserializer.getDouble(serBytes, offset1);
- int offset2 = ARecordSerializerDeserializer.getFieldOffsetById(serBytes, 1, 1, false);
+ int offset2 = ARecordSerializerDeserializer.getFieldOffsetById(serBytes, 1, nullBitmapSize, false);
if (offset2 != 0) // the count is not null
globalCount += AInt32SerializerDeserializer.getInt(serBytes, offset2);
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/common/AsterixListAccessor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/common/AsterixListAccessor.java
new file mode 100644
index 0000000..fd6b691
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/common/AsterixListAccessor.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2009-2010 by The Regents of the University of California
+ * Licensed 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 from
+ *
+ * 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 edu.uci.ics.asterix.runtime.evaluators.common;
+
+import java.io.DataOutput;
+import java.io.IOException;
+
+import edu.uci.ics.asterix.common.exceptions.AsterixException;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AOrderedListSerializerDeserializer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AUnorderedListSerializerDeserializer;
+import edu.uci.ics.asterix.om.types.ATypeTag;
+import edu.uci.ics.asterix.om.types.EnumDeserializer;
+import edu.uci.ics.asterix.om.util.NonTaggedFormatUtil;
+
+/**
+ * Utility class for accessing serialized unordered and ordered lists.
+ */
+public class AsterixListAccessor {
+
+ protected byte[] listBytes;
+ protected int start;
+ protected ATypeTag listType;
+ protected ATypeTag itemType;
+ protected int size;
+
+ public ATypeTag getListType() {
+ return listType;
+ }
+
+ public ATypeTag getItemType() {
+ return itemType;
+ }
+
+ public boolean itemsAreSelfDescribing() {
+ return itemType == ATypeTag.ANY;
+ }
+
+ public void reset(byte[] listBytes, int start) throws AsterixException {
+ this.listBytes = listBytes;
+ this.start = start;
+ listType = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(listBytes[start]);
+ if (listType != ATypeTag.UNORDEREDLIST && listType != ATypeTag.ORDEREDLIST) {
+ throw new AsterixException("Unsupported type: " + listType);
+ }
+ itemType = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(listBytes[start + 1]);
+ if (listType == ATypeTag.UNORDEREDLIST) {
+ size = AUnorderedListSerializerDeserializer.getNumberOfItems(listBytes, start);
+ } else {
+ size = AOrderedListSerializerDeserializer.getNumberOfItems(listBytes, start);
+ }
+ }
+
+ public int size() {
+ return size;
+ }
+
+ public int getItemOffset(int itemIndex) throws AsterixException {
+ if (listType == ATypeTag.UNORDEREDLIST) {
+ return AUnorderedListSerializerDeserializer.getItemOffset(listBytes, start, itemIndex);
+ } else {
+ return AOrderedListSerializerDeserializer.getItemOffset(listBytes, start, itemIndex);
+ }
+ }
+
+ public int getItemLength(int itemOffset) throws AsterixException {
+ ATypeTag itemType = getItemType(itemOffset);
+ return NonTaggedFormatUtil.getFieldValueLength(listBytes, itemOffset, itemType, itemsAreSelfDescribing());
+ }
+
+ public ATypeTag getItemType(int itemOffset) throws AsterixException {
+ if (itemType == ATypeTag.ANY) {
+ return EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(listBytes[itemOffset]);
+ } else {
+ return itemType;
+ }
+ }
+
+ public void writeItem(int itemIndex, DataOutput dos) throws AsterixException, IOException {
+ int itemOffset = getItemOffset(itemIndex);
+ int itemLength = getItemLength(itemOffset);
+ if (itemsAreSelfDescribing()) {
+ ++itemLength;
+ } else {
+ dos.writeByte(itemType.serialize());
+ }
+ dos.write(listBytes, itemOffset, itemLength);
+ }
+
+ public byte[] getByteArray() {
+ return listBytes;
+ }
+
+ public int getStart() {
+ return start;
+ }
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/functions/StringConcatDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/functions/StringConcatDescriptor.java
index 1c2cee7..2b53f35 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/functions/StringConcatDescriptor.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/functions/StringConcatDescriptor.java
@@ -1,18 +1,20 @@
package edu.uci.ics.asterix.runtime.evaluators.functions;
+import java.io.DataOutput;
+import java.io.IOException;
+
import edu.uci.ics.asterix.common.exceptions.AsterixException;
import edu.uci.ics.asterix.common.functions.FunctionConstants;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AOrderedListSerializerDeserializer;
import edu.uci.ics.asterix.formats.nontagged.AqlSerializerDeserializerProvider;
import edu.uci.ics.asterix.om.base.ANull;
import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
import edu.uci.ics.asterix.om.types.ATypeTag;
import edu.uci.ics.asterix.om.types.BuiltinType;
-import edu.uci.ics.asterix.om.types.EnumDeserializer;
import edu.uci.ics.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
-import edu.uci.ics.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import edu.uci.ics.asterix.runtime.evaluators.common.AsterixListAccessor;
import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluator;
import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
@@ -21,8 +23,6 @@
import edu.uci.ics.hyracks.data.std.util.ArrayBackedValueStorage;
import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
import edu.uci.ics.hyracks.dataflow.common.data.util.StringUtils;
-import java.io.DataOutput;
-import java.io.IOException;
/**
* @author Xiaoyu Ma
@@ -37,24 +37,22 @@
return new StringConcatDescriptor();
}
};
- private final static byte SER_NULL_TYPE_TAG = ATypeTag.NULL.serialize();
- private final static byte SER_ORDEREDLIST_TYPE_TAG = ATypeTag.ORDEREDLIST.serialize();
- private final byte stringTypeTag = ATypeTag.STRING.serialize();
-
+
@Override
public ICopyEvaluatorFactory createEvaluatorFactory(final ICopyEvaluatorFactory[] args) {
return new ICopyEvaluatorFactory() {
-
+
private static final long serialVersionUID = 1L;
@Override
public ICopyEvaluator createEvaluator(final IDataOutputProvider output) throws AlgebricksException {
return new ICopyEvaluator() {
- private DataOutput out = output.getDataOutput();
- private ICopyEvaluatorFactory listEvalFactory = args[0];
- private ArrayBackedValueStorage outInputList = new ArrayBackedValueStorage();
- private ICopyEvaluator evalList = listEvalFactory.createEvaluator(outInputList);
+ private final AsterixListAccessor listAccessor = new AsterixListAccessor();
+ private final DataOutput out = output.getDataOutput();
+ private final ICopyEvaluatorFactory listEvalFactory = args[0];
+ private final ArrayBackedValueStorage outInputList = new ArrayBackedValueStorage();
+ private final ICopyEvaluator evalList = listEvalFactory.createEvaluator(outInputList);
@SuppressWarnings("unchecked")
private ISerializerDeserializer<ANull> nullSerde = AqlSerializerDeserializerProvider.INSTANCE
.getSerializerDeserializer(BuiltinType.ANULL);
@@ -64,32 +62,39 @@
try {
outInputList.reset();
evalList.evaluate(tuple);
- byte[] serOrderedList = outInputList.getByteArray();
- if (serOrderedList[0] == SER_NULL_TYPE_TAG) {
+ byte[] listBytes = outInputList.getByteArray();
+ try {
+ listAccessor.reset(listBytes, 0);
+ } catch (AsterixException e) {
+ throw new AlgebricksException(e);
+ }
+ if (listAccessor.getItemType() == ATypeTag.NULL) {
nullSerde.serialize(ANull.NULL, out);
return;
}
- if (serOrderedList[0] != SER_ORDEREDLIST_TYPE_TAG) {
- throw new AlgebricksException("Expects String List."
- + EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(serOrderedList[0]));
- }
- int size = AOrderedListSerializerDeserializer.getNumberOfItems(serOrderedList);
try {
// calculate length first
- int utf_8_len = 0;
- for (int i = 0; i < size; i++) {
- int itemOffset = AOrderedListSerializerDeserializer
- .getItemOffset(serOrderedList, i);
- utf_8_len += UTF8StringPointable.getUTFLength(serOrderedList, itemOffset);
+ int utf8Len = 0;
+ for (int i = 0; i < listAccessor.size(); i++) {
+ int itemOffset = listAccessor.getItemOffset(i);
+ ATypeTag itemType = listAccessor.getItemType(itemOffset);
+ if (itemType != ATypeTag.STRING) {
+ if (itemType == ATypeTag.NULL) {
+ nullSerde.serialize(ANull.NULL, out);
+ return;
+ }
+ throw new AlgebricksException("Unsupported type " + itemType
+ + " in list passed to string-concat function.");
+ }
+ utf8Len += UTF8StringPointable.getUTFLength(listBytes, itemOffset);
}
- out.writeByte(stringTypeTag);
- StringUtils.writeUTF8Len(utf_8_len, out);
- for (int i = 0; i < size; i++) {
- int itemOffset = AOrderedListSerializerDeserializer
- .getItemOffset(serOrderedList, i);
- utf_8_len = UTF8StringPointable.getUTFLength(serOrderedList, itemOffset);
- for (int j = 0; j < utf_8_len; j++) {
- out.writeByte(serOrderedList[2 + itemOffset + j]);
+ out.writeByte(ATypeTag.STRING.serialize());
+ StringUtils.writeUTF8Len(utf8Len, out);
+ for (int i = 0; i < listAccessor.size(); i++) {
+ int itemOffset = listAccessor.getItemOffset(i);
+ utf8Len = UTF8StringPointable.getUTFLength(listBytes, itemOffset);
+ for (int j = 0; j < utf8Len; j++) {
+ out.writeByte(listBytes[2 + itemOffset + j]);
}
}
} catch (AsterixException ex) {
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/unnestingfunctions/std/ScanCollectionDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/unnestingfunctions/std/ScanCollectionDescriptor.java
index cf39008..ef89e9f 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/unnestingfunctions/std/ScanCollectionDescriptor.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/unnestingfunctions/std/ScanCollectionDescriptor.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2009-2010 by The Regents of the University of California
+ * Licensed 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 from
+ *
+ * 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 edu.uci.ics.asterix.runtime.unnestingfunctions.std;
import java.io.DataOutput;
@@ -5,16 +20,9 @@
import edu.uci.ics.asterix.common.exceptions.AsterixException;
import edu.uci.ics.asterix.common.functions.FunctionConstants;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AOrderedListSerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AUnorderedListSerializerDeserializer;
-import edu.uci.ics.asterix.formats.nontagged.AqlSerializerDeserializerProvider;
-import edu.uci.ics.asterix.om.base.ANull;
import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
-import edu.uci.ics.asterix.om.types.ATypeTag;
-import edu.uci.ics.asterix.om.types.BuiltinType;
-import edu.uci.ics.asterix.om.types.EnumDeserializer;
-import edu.uci.ics.asterix.om.util.NonTaggedFormatUtil;
+import edu.uci.ics.asterix.runtime.evaluators.common.AsterixListAccessor;
import edu.uci.ics.asterix.runtime.unnestingfunctions.base.AbstractUnnestingFunctionDynamicDescriptor;
import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
import edu.uci.ics.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
@@ -22,7 +30,6 @@
import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyUnnestingFunction;
import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyUnnestingFunctionFactory;
-import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
import edu.uci.ics.hyracks.data.std.api.IDataOutputProvider;
import edu.uci.ics.hyracks.data.std.util.ArrayBackedValueStorage;
import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
@@ -51,14 +58,7 @@
public static class ScanCollectionUnnestingFunctionFactory implements ICopyUnnestingFunctionFactory {
private static final long serialVersionUID = 1L;
-
private ICopyEvaluatorFactory listEvalFactory;
- private final static byte SER_ORDEREDLIST_TYPE_TAG = ATypeTag.ORDEREDLIST.serialize();
- private final static byte SER_UNORDEREDLIST_TYPE_TAG = ATypeTag.UNORDEREDLIST.serialize();
- private final static byte SER_NULL_TYPE_TAG = ATypeTag.NULL.serialize();
- private ATypeTag itemTag;
- private byte serItemTypeTag;
- private boolean selfDescList = false;
public ScanCollectionUnnestingFunctionFactory(ICopyEvaluatorFactory arg) {
this.listEvalFactory = arg;
@@ -71,84 +71,37 @@
return new ICopyUnnestingFunction() {
+ private final AsterixListAccessor listAccessor = new AsterixListAccessor();
private ArrayBackedValueStorage inputVal = new ArrayBackedValueStorage();
private ICopyEvaluator argEval = listEvalFactory.createEvaluator(inputVal);
- @SuppressWarnings("unchecked")
- private ISerializerDeserializer<ANull> nullSerde = AqlSerializerDeserializerProvider.INSTANCE
- .getSerializerDeserializer(BuiltinType.ANULL);
- private int numItems;
- private int pos;
- private int itemOffset;
- private int itemLength;
- private byte serListTag;
+ private int itemIndex;
@Override
public void init(IFrameTupleReference tuple) throws AlgebricksException {
try {
inputVal.reset();
argEval.evaluate(tuple);
- byte[] serList = inputVal.getByteArray();
-
- if (serList[0] == SER_NULL_TYPE_TAG) {
- nullSerde.serialize(ANull.NULL, out);
- return;
- }
-
- if (serList[0] != SER_ORDEREDLIST_TYPE_TAG && serList[0] != SER_UNORDEREDLIST_TYPE_TAG) {
- throw new AlgebricksException("Scan collection is not defined for values of type"
- + EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(serList[0]));
- }
-
- serListTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(inputVal.getByteArray()[0])
- .serialize();
- if (serListTag == SER_ORDEREDLIST_TYPE_TAG)
- numItems = AOrderedListSerializerDeserializer.getNumberOfItems(inputVal.getByteArray());
- else
- numItems = AUnorderedListSerializerDeserializer.getNumberOfItems(inputVal.getByteArray());
-
- itemTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(serList[1]);
- if (itemTag == ATypeTag.ANY)
- selfDescList = true;
- else
- serItemTypeTag = serList[1];
-
- pos = 0;
- } catch (IOException e) {
- throw new AlgebricksException(e);
+ listAccessor.reset(inputVal.getByteArray(), 0);
+ itemIndex = 0;
+ } catch (AsterixException e) {
+ throw new AlgebricksException(e);
}
}
@Override
public boolean step() throws AlgebricksException {
-
try {
- if (pos < numItems) {
- byte[] serList = inputVal.getByteArray();
-
- try {
- if (serListTag == SER_ORDEREDLIST_TYPE_TAG) {
- itemOffset = AOrderedListSerializerDeserializer.getItemOffset(serList, pos);
- } else {
- itemOffset = AUnorderedListSerializerDeserializer.getItemOffset(serList, pos);
- }
- if (selfDescList)
- itemTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(serList[itemOffset]);
- itemLength = NonTaggedFormatUtil.getFieldValueLength(serList, itemOffset, itemTag,
- selfDescList);
- if (!selfDescList)
- out.writeByte(serItemTypeTag);
- out.write(serList, itemOffset, itemLength + (!selfDescList ? 0 : 1));
- } catch (AsterixException e) {
- throw new AlgebricksException(e);
- }
- ++pos;
+ if (itemIndex < listAccessor.size()) {
+ listAccessor.writeItem(itemIndex, out);
+ ++itemIndex;
return true;
- } else
- return false;
-
+ }
} catch (IOException e) {
throw new AlgebricksException(e);
+ } catch (AsterixException e) {
+ throw new AlgebricksException(e);
}
+ return false;
}
};