Finished code for fixing this issue. Next: Add more tests.
git-svn-id: https://asterixdb.googlecode.com/svn/branches/asterix-fix-issue-9@276 eaa15691-b419-025a-1212-ee371bd00084
diff --git a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/IntroduceSecondaryIndexInsertDeleteRule.java b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/IntroduceSecondaryIndexInsertDeleteRule.java
index 8543edd..c9f9f93 100644
--- a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/IntroduceSecondaryIndexInsertDeleteRule.java
+++ b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/IntroduceSecondaryIndexInsertDeleteRule.java
@@ -21,6 +21,7 @@
import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
import edu.uci.ics.asterix.om.types.ARecordType;
import edu.uci.ics.asterix.om.types.ATypeTag;
+import edu.uci.ics.asterix.om.types.AUnionType;
import edu.uci.ics.asterix.om.types.IAType;
import edu.uci.ics.asterix.om.util.NonTaggedFormatUtil;
import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
@@ -32,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.IVariableTypeEnvironment;
import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
import edu.uci.ics.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
@@ -139,22 +141,23 @@
AssignOperator assign = new AssignOperator(secondaryKeyVars, expressions);
ProjectOperator project = new ProjectOperator(projectVars);
+ assign.getInputs().add(new MutableObject<ILogicalOperator>(project));
+ project.getInputs().add(new MutableObject<ILogicalOperator>(currentTop));
+ context.computeAndSetTypeEnvironmentForOperator(project);
+ context.computeAndSetTypeEnvironmentForOperator(assign);
if (index.getKind() == IndexKind.BTREE) {
for (LogicalVariable secondaryKeyVar : secondaryKeyVars) {
secondaryExpressions.add(new MutableObject<ILogicalExpression>(new VariableReferenceExpression(
secondaryKeyVar)));
}
- Mutable<ILogicalExpression> filterExpression = createFilterExpression(secondaryKeyVars);
+ Mutable<ILogicalExpression> filterExpression = createFilterExpression(secondaryKeyVars,
+ context.getOutputTypeEnvironment(assign));
AqlIndex dataSourceIndex = new AqlIndex(index, metadata, datasetName);
IndexInsertDeleteOperator indexUpdate = new IndexInsertDeleteOperator(dataSourceIndex,
insertOp.getPrimaryKeyExpressions(), secondaryExpressions, filterExpression,
insertOp.getOperation());
indexUpdate.getInputs().add(new MutableObject<ILogicalOperator>(assign));
- assign.getInputs().add(new MutableObject<ILogicalOperator>(project));
- project.getInputs().add(new MutableObject<ILogicalOperator>(currentTop));
currentTop = indexUpdate;
- context.computeAndSetTypeEnvironmentForOperator(project);
- context.computeAndSetTypeEnvironmentForOperator(assign);
context.computeAndSetTypeEnvironmentForOperator(indexUpdate);
} else if (index.getKind() == IndexKind.RTREE) {
IAType spatialType = null;
@@ -185,20 +188,17 @@
secondaryExpressions.add(new MutableObject<ILogicalExpression>(new VariableReferenceExpression(
secondaryKeyVar)));
}
- Mutable<ILogicalExpression> filterExpression = createFilterExpression(keyVarList);
+ AssignOperator assignCoordinates = new AssignOperator(keyVarList, keyExprList);
+ assignCoordinates.getInputs().add(new MutableObject<ILogicalOperator>(assign));
+ context.computeAndSetTypeEnvironmentForOperator(assignCoordinates);
+ Mutable<ILogicalExpression> filterExpression = createFilterExpression(keyVarList,
+ context.getOutputTypeEnvironment(assignCoordinates));
AqlIndex dataSourceIndex = new AqlIndex(index, metadata, datasetName);
IndexInsertDeleteOperator indexUpdate = new IndexInsertDeleteOperator(dataSourceIndex,
insertOp.getPrimaryKeyExpressions(), secondaryExpressions, filterExpression,
insertOp.getOperation());
- AssignOperator assignCoordinates = new AssignOperator(keyVarList, keyExprList);
- indexUpdate.getInputs().add(new MutableObject<ILogicalOperator>(assignCoordinates));
- assignCoordinates.getInputs().add(new MutableObject<ILogicalOperator>(assign));
- assign.getInputs().add(new MutableObject<ILogicalOperator>(project));
- project.getInputs().add(new MutableObject<ILogicalOperator>(currentTop));
- currentTop = indexUpdate;
- context.computeAndSetTypeEnvironmentForOperator(project);
- context.computeAndSetTypeEnvironmentForOperator(assign);
- context.computeAndSetTypeEnvironmentForOperator(assignCoordinates);
+ indexUpdate.getInputs().add(new MutableObject<ILogicalOperator>(assignCoordinates));
+ currentTop = indexUpdate;
context.computeAndSetTypeEnvironmentForOperator(indexUpdate);
}
@@ -208,21 +208,31 @@
return true;
}
- // TODO: Return null here for non-nullable fields.
- private Mutable<ILogicalExpression> createFilterExpression(List<LogicalVariable> secondaryKeyVars) {
+ @SuppressWarnings("unchecked")
+ private Mutable<ILogicalExpression> createFilterExpression(List<LogicalVariable> secondaryKeyVars,
+ IVariableTypeEnvironment typeEnv) throws AlgebricksException {
List<Mutable<ILogicalExpression>> filterExpressions = new ArrayList<Mutable<ILogicalExpression>>();
+ // Add 'is not null' to all nullable secondary index keys as a filtering condition.
for (LogicalVariable secondaryKeyVar : secondaryKeyVars) {
- // Add 'is not null' to all secondary index keys as a filtering condition.
+ IAType secondaryKeyType = (IAType) typeEnv.getVarType(secondaryKeyVar);
+ if (!isNullableType(secondaryKeyType)) {
+ continue;
+ }
ScalarFunctionCallExpression isNullFuncExpr = new ScalarFunctionCallExpression(
FunctionUtils.getFunctionInfo(AsterixBuiltinFunctions.IS_NULL),
new MutableObject<ILogicalExpression>(new VariableReferenceExpression(secondaryKeyVar)));
ScalarFunctionCallExpression notFuncExpr = new ScalarFunctionCallExpression(
- FunctionUtils.getFunctionInfo(AsterixBuiltinFunctions.NOT),
- new MutableObject<ILogicalExpression>(isNullFuncExpr));
+ FunctionUtils.getFunctionInfo(AsterixBuiltinFunctions.NOT), new MutableObject<ILogicalExpression>(
+ isNullFuncExpr));
filterExpressions.add(new MutableObject<ILogicalExpression>(notFuncExpr));
}
+ // No nullable secondary keys.
+ if (filterExpressions.isEmpty()) {
+ return null;
+ }
Mutable<ILogicalExpression> filterExpression = null;
if (filterExpressions.size() > 1) {
+ // Create a conjunctive condition.
filterExpression = new MutableObject<ILogicalExpression>(new ScalarFunctionCallExpression(
FunctionUtils.getFunctionInfo(AsterixBuiltinFunctions.AND), filterExpressions));
} else {
@@ -231,6 +241,13 @@
return filterExpression;
}
+ private boolean isNullableType(IAType type) {
+ if (type.getTypeTag() == ATypeTag.UNION) {
+ return ((AUnionType)type).isNullableType();
+ }
+ return false;
+ }
+
public static IAType keyFieldType(String expr, ARecordType recType) throws AlgebricksException {
String[] names = recType.getFieldNames();
int n = names.length;
diff --git a/asterix-app/src/main/java/edu/uci/ics/asterix/file/SecondaryIndexCreator.java b/asterix-app/src/main/java/edu/uci/ics/asterix/file/SecondaryIndexCreator.java
index b63e019..7da18fb 100644
--- a/asterix-app/src/main/java/edu/uci/ics/asterix/file/SecondaryIndexCreator.java
+++ b/asterix-app/src/main/java/edu/uci/ics/asterix/file/SecondaryIndexCreator.java
@@ -55,6 +55,8 @@
import edu.uci.ics.hyracks.storage.am.common.impls.NoOpOperationCallbackProvider;
@SuppressWarnings("rawtypes")
+// TODO: We should eventually have a hierarchy of classes that can create all possible index job specs,
+// not just for creation.
public abstract class SecondaryIndexCreator {
protected final PhysicalOptimizationConfig physOptConf;
diff --git a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/declared/AqlMetadataProvider.java b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/declared/AqlMetadataProvider.java
index a67d0c3..33d36bd 100644
--- a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/declared/AqlMetadataProvider.java
+++ b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/declared/AqlMetadataProvider.java
@@ -824,7 +824,6 @@
}
@Override
- // TODO: Use filterExpr.
public Pair<IOperatorDescriptor, AlgebricksPartitionConstraint> getIndexInsertRuntime(
IDataSourceIndex<String, AqlSourceId> dataSourceIndex,
IOperatorSchema propagatedSchema, IOperatorSchema[] inputSchemas,
@@ -857,7 +856,6 @@
}
@Override
- // TODO: Use filterExpr.
public Pair<IOperatorDescriptor, AlgebricksPartitionConstraint> getIndexDeleteRuntime(
IDataSourceIndex<String, AqlSourceId> dataSourceIndex,
IOperatorSchema propagatedSchema, IOperatorSchema[] inputSchemas,
@@ -893,6 +891,10 @@
IOperatorSchema[] inputSchemas, IVariableTypeEnvironment typeEnv,
ILogicalExpression filterExpr, JobGenContext context)
throws AlgebricksException {
+ // No filtering condition.
+ if (filterExpr == null) {
+ return null;
+ }
ILogicalExpressionJobGen exprJobGen = context.getExpressionJobGen();
IEvaluatorFactory filterEvalFactory = exprJobGen
.createEvaluatorFactory(filterExpr, typeEnv, inputSchemas,