1. Fix the SetClosedRecordConstructorRule
2. Add Khurram's test case for that.

git-svn-id: https://asterixdb.googlecode.com/svn/branches/asterix_stabilization@166 eaa15691-b419-025a-1212-ee371bd00084
diff --git a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/SetClosedRecordConstructorsRule.java b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/SetClosedRecordConstructorsRule.java
index 33377e1..f3d1d12 100644
--- a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/SetClosedRecordConstructorsRule.java
+++ b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/SetClosedRecordConstructorsRule.java
@@ -5,6 +5,7 @@
 import edu.uci.ics.asterix.aql.util.FunctionUtils;
 import edu.uci.ics.asterix.common.config.GlobalConfig;
 import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
+import edu.uci.ics.asterix.om.typecomputer.base.TypeComputerUtilities;
 import edu.uci.ics.asterix.om.types.AOrderedListType;
 import edu.uci.ics.asterix.om.types.ARecordType;
 import edu.uci.ics.asterix.om.types.AUnionType;
@@ -32,65 +33,78 @@
 
 public class SetClosedRecordConstructorsRule implements IAlgebraicRewriteRule {
 
-    private SettingClosedRecordVisitor recordVisitor;
+	private SettingClosedRecordVisitor recordVisitor;
 
-    public SetClosedRecordConstructorsRule() {
-        this.recordVisitor = new SettingClosedRecordVisitor();
-    }
+	public SetClosedRecordConstructorsRule() {
+		this.recordVisitor = new SettingClosedRecordVisitor();
+	}
 
-    @Override
-    public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context) {
-        return false;
-    }
+	@Override
+	public boolean rewritePre(Mutable<ILogicalOperator> opRef,
+			IOptimizationContext context) {
+		return false;
+	}
 
-    @Override
-    public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext ctx) throws AlgebricksException {
-        AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
-        if (ctx.checkIfInDontApplySet(this, op)) {
-            return false;
-        }
-        ctx.addToDontApplySet(this, op);
-        this.recordVisitor.setOptimizationContext(ctx, op.computeInputTypeEnvironment(ctx));
-        boolean res = op.acceptExpressionTransform(recordVisitor);
-        if (res) {
-            ctx.computeAndSetTypeEnvironmentForOperator(op);
-        }
-        return res;
-    }
+	@Override
+	public boolean rewritePost(Mutable<ILogicalOperator> opRef,
+			IOptimizationContext ctx) throws AlgebricksException {
+		AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
+		if (ctx.checkIfInDontApplySet(this, op)) {
+			return false;
+		}
+		ctx.addToDontApplySet(this, op);
+		this.recordVisitor.setOptimizationContext(ctx,
+				op.computeInputTypeEnvironment(ctx));
+		boolean res = op.acceptExpressionTransform(recordVisitor);
+		if (res) {
+			ctx.computeAndSetTypeEnvironmentForOperator(op);
+		}
+		return res;
+	}
 
-    private static class SettingClosedRecordVisitor extends AbstractConstVarFunVisitor<ClosedDataInfo, Void> implements
-            ILogicalExpressionReferenceTransform {
+	private static class SettingClosedRecordVisitor extends
+			AbstractConstVarFunVisitor<ClosedDataInfo, Void> implements
+			ILogicalExpressionReferenceTransform {
 
-        private IOptimizationContext context;
-        private IVariableTypeEnvironment env;
+		private IOptimizationContext context;
+		private IVariableTypeEnvironment env;
 
-        public void setOptimizationContext(IOptimizationContext context, IVariableTypeEnvironment env) {
-            this.context = context;
-            this.env = env;
-        }
+		public void setOptimizationContext(IOptimizationContext context,
+				IVariableTypeEnvironment env) {
+			this.context = context;
+			this.env = env;
+		}
 
-        @Override
-        public boolean transform(Mutable<ILogicalExpression> exprRef) throws AlgebricksException {
-            AbstractLogicalExpression expr = (AbstractLogicalExpression) exprRef.getValue();
-            ClosedDataInfo cdi = expr.accept(this, null);
-            if (cdi.expressionChanged) {
-                exprRef.setValue(cdi.expression);
-            }
-            return cdi.expressionChanged;
-        }
+		@Override
+		public boolean transform(Mutable<ILogicalExpression> exprRef)
+				throws AlgebricksException {
+			AbstractLogicalExpression expr = (AbstractLogicalExpression) exprRef
+					.getValue();
+			ClosedDataInfo cdi = expr.accept(this, null);
+			if (cdi.expressionChanged) {
+				exprRef.setValue(cdi.expression);
+			}
+			return cdi.expressionChanged;
+		}
 
-        @Override
-        public ClosedDataInfo visitConstantExpression(ConstantExpression expr, Void arg) throws AlgebricksException {
-            return new ClosedDataInfo(false, hasClosedType(expr), expr);
-        }
+		@Override
+		public ClosedDataInfo visitConstantExpression(ConstantExpression expr,
+				Void arg) throws AlgebricksException {
+			return new ClosedDataInfo(false, hasClosedType(expr), expr);
+		}
 
-        @Override
+		@Override
         public ClosedDataInfo visitFunctionCallExpression(AbstractFunctionCallExpression expr, Void arg)
                 throws AlgebricksException {
             boolean allClosed = true;
             boolean changed = false;
             if (expr.getFunctionIdentifier().equals(AsterixBuiltinFunctions.OPEN_RECORD_CONSTRUCTOR)) {
-                int n = expr.getArguments().size();
+                ARecordType reqType = (ARecordType) TypeComputerUtilities.getRequiredType(expr);
+                if(reqType!=null){
+                	if(reqType.isOpen())
+                		allClosed = false;
+                }
+            	int n = expr.getArguments().size();
                 if (n % 2 > 0) {
                     throw new AlgebricksException("Record constructor expected to have an even number of arguments: "
                             + expr);
@@ -133,82 +147,88 @@
             return new ClosedDataInfo(changed, hasClosedType(expr), expr);
         }
 
-        @Override
-        public ClosedDataInfo visitVariableReferenceExpression(VariableReferenceExpression expr, Void arg)
-                throws AlgebricksException {
-            boolean dataIsClosed = isClosedRec((IAType) env.getVarType(expr.getVariableReference()));
-            return new ClosedDataInfo(false, dataIsClosed, expr);
-        }
+		@Override
+		public ClosedDataInfo visitVariableReferenceExpression(
+				VariableReferenceExpression expr, Void arg)
+				throws AlgebricksException {
+			boolean dataIsClosed = isClosedRec((IAType) env.getVarType(expr
+					.getVariableReference()));
+			return new ClosedDataInfo(false, dataIsClosed, expr);
+		}
 
-        private boolean hasClosedType(ILogicalExpression expr) throws AlgebricksException {
-            IAType t = (IAType) context.getExpressionTypeComputer().getType(expr, context.getMetadataProvider(), env);
-            return isClosedRec(t);
-        }
+		private boolean hasClosedType(ILogicalExpression expr)
+				throws AlgebricksException {
+			IAType t = (IAType) context.getExpressionTypeComputer().getType(
+					expr, context.getMetadataProvider(), env);
+			return isClosedRec(t);
+		}
 
-        private static boolean isClosedRec(IAType t) throws AlgebricksException {
-            switch (t.getTypeTag()) {
-                case ANY: {
-                    return false;
-                }
-                case CIRCLE:
-                case INT8:
-                case INT16:
-                case INT32:
-                case INT64:
-                case BINARY:
-                case BITARRAY:
-                case FLOAT:
-                case DOUBLE:
-                case STRING:
-                case LINE:
-                case NULL:
-                case BOOLEAN:
-                case DATETIME:
-                case DATE:
-                case TIME:
-                case DURATION:
-                case POINT:
-                case POINT3D:
-                case POLYGON:
-                case RECTANGLE: {
-                    return true;
-                }
-                case RECORD: {
-                    return !((ARecordType) t).isOpen();
-                }
-                case UNION: {
-                    AUnionType ut = (AUnionType) t;
-                    for (IAType t2 : ut.getUnionList()) {
-                        if (!isClosedRec(t2)) {
-                            return false;
-                        }
-                    }
-                    return true;
-                }
-                case ORDEREDLIST: {
-                    AOrderedListType ol = (AOrderedListType) t;
-                    return isClosedRec(ol.getItemType());
-                }
-                case UNORDEREDLIST: {
-                    AUnorderedListType ul = (AUnorderedListType) t;
-                    return isClosedRec(ul.getItemType());
-                }
-                default: {
-                    throw new IllegalStateException("Closed type analysis not implemented for type " + t);
-                }
-            }
-        }
-    }
+		private static boolean isClosedRec(IAType t) throws AlgebricksException {
+			switch (t.getTypeTag()) {
+			case ANY: {
+				return false;
+			}
+			case CIRCLE:
+			case INT8:
+			case INT16:
+			case INT32:
+			case INT64:
+			case BINARY:
+			case BITARRAY:
+			case FLOAT:
+			case DOUBLE:
+			case STRING:
+			case LINE:
+			case NULL:
+			case BOOLEAN:
+			case DATETIME:
+			case DATE:
+			case TIME:
+			case DURATION:
+			case POINT:
+			case POINT3D:
+			case POLYGON:
+			case RECTANGLE: {
+				return true;
+			}
+			case RECORD: {
+				return !((ARecordType) t).isOpen();
+			}
+			case UNION: {
+				AUnionType ut = (AUnionType) t;
+				for (IAType t2 : ut.getUnionList()) {
+					if (!isClosedRec(t2)) {
+						return false;
+					}
+				}
+				return true;
+			}
+			case ORDEREDLIST: {
+				AOrderedListType ol = (AOrderedListType) t;
+				return isClosedRec(ol.getItemType());
+			}
+			case UNORDEREDLIST: {
+				AUnorderedListType ul = (AUnorderedListType) t;
+				return isClosedRec(ul.getItemType());
+			}
+			default: {
+				throw new IllegalStateException(
+						"Closed type analysis not implemented for type " + t);
+			}
+			}
+		}
+	}
 
-    private static class ClosedDataInfo {
-        boolean expressionChanged;
-        boolean dataIsClosed;
-        ILogicalExpression expression;
+	private static class ClosedDataInfo {
+		boolean expressionChanged;
+		boolean dataIsClosed;
+		ILogicalExpression expression;
 
-        public ClosedDataInfo(boolean expressionChanged, boolean dataIsClosed, ILogicalExpression expression) {
-            this.expressionChanged = expressionChanged;
-            this.dataIsClosed = dataIsClosed;
-            this.expression = expression;
-        }
-    }
+		public ClosedDataInfo(boolean expressionChanged, boolean dataIsClosed,
+				ILogicalExpression expression) {
+			this.expressionChanged = expressionChanged;
+			this.dataIsClosed = dataIsClosed;
+			this.expression = expression;
+		}
+	}
 }
diff --git a/asterix-app/src/test/resources/runtimets/queries/dml/opentype-insert2.aql b/asterix-app/src/test/resources/runtimets/queries/dml/opentype-insert2.aql
new file mode 100644
index 0000000..8339bc2
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/dml/opentype-insert2.aql
@@ -0,0 +1,20 @@
+//Test the case where SetClosedRecordRule should not rewrite
+//the plan to use closed-record-descriptor;
+
+drop dataverse test if exists;
+create dataverse test;
+use dataverse test;
+
+create type TestType as open {
+id:int32
+}
+
+create dataset testds(TestType) partitioned by key id;
+
+insert into dataset testds( for $i in range(1,10) return { "id":$i,"name":"John Doe" });
+
+
+write output to nc1:"rttest/dml_opentype-insert2.adm";
+for $l in dataset('testds')
+order by $l.id
+return $l
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/runtimets/results/dml/opentype-insert2.adm b/asterix-app/src/test/resources/runtimets/results/dml/opentype-insert2.adm
new file mode 100644
index 0000000..45d112e
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/dml/opentype-insert2.adm
@@ -0,0 +1,10 @@
+{ "id": 1, "name": "John Doe" }
+{ "id": 2, "name": "John Doe" }
+{ "id": 3, "name": "John Doe" }
+{ "id": 4, "name": "John Doe" }
+{ "id": 5, "name": "John Doe" }
+{ "id": 6, "name": "John Doe" }
+{ "id": 7, "name": "John Doe" }
+{ "id": 8, "name": "John Doe" }
+{ "id": 9, "name": "John Doe" }
+{ "id": 10, "name": "John Doe" }