address Vinayak and Alex's coments and ready for 2nd round review

git-svn-id: https://asterixdb.googlecode.com/svn/branches/asterix_opentype_mergeback_staging@303 eaa15691-b419-025a-1212-ee371bd00084
diff --git a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/base/RuleCollections.java b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/base/RuleCollections.java
index fc9e789..e45eeea 100644
--- a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/base/RuleCollections.java
+++ b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/base/RuleCollections.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.optimizer.base;
 
 import java.util.LinkedList;
@@ -18,6 +33,7 @@
 import edu.uci.ics.asterix.optimizer.rules.IntroduceDynamicTypeCastRule;
 import edu.uci.ics.asterix.optimizer.rules.IntroduceRTreeIndexSearchRule;
 import edu.uci.ics.asterix.optimizer.rules.IntroduceSecondaryIndexInsertDeleteRule;
+import edu.uci.ics.asterix.optimizer.rules.IntroduceStaticTypeCastRule;
 import edu.uci.ics.asterix.optimizer.rules.LoadRecordFieldsRule;
 import edu.uci.ics.asterix.optimizer.rules.NestGroupByRule;
 import edu.uci.ics.asterix.optimizer.rules.PullPositionalVariableFromUnnestRule;
@@ -28,7 +44,6 @@
 import edu.uci.ics.asterix.optimizer.rules.RemoveRedundantListifyRule;
 import edu.uci.ics.asterix.optimizer.rules.SetAsterixPhysicalOperatorsRule;
 import edu.uci.ics.asterix.optimizer.rules.SetClosedRecordConstructorsRule;
-import edu.uci.ics.asterix.optimizer.rules.IntroduceStaticTypeCastRule;
 import edu.uci.ics.asterix.optimizer.rules.UnnestToDataScanRule;
 import edu.uci.ics.hyracks.algebricks.core.rewriter.base.HeuristicOptimizer;
 import edu.uci.ics.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
@@ -83,8 +98,9 @@
         normalization.add(new ExtractDistinctByExpressionsRule());
         normalization.add(new ExtractOrderExpressionsRule());
 
-        // TopdownTypeInferenceRule should go before IntroduceCastRecordRule to
-        // avoid unnecessary casting
+        // IntroduceStaticTypeCastRule should go before
+        // IntroduceDynamicTypeCastRule to
+        // avoid unnecessary dynamic casting
         normalization.add(new IntroduceStaticTypeCastRule());
         normalization.add(new IntroduceDynamicTypeCastRule());
         normalization.add(new ConstantFoldingRule());
diff --git a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/ByNameToByIndexFieldAccessRule.java b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/ByNameToByIndexFieldAccessRule.java
index 25412d8..704ccb5 100644
--- a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/ByNameToByIndexFieldAccessRule.java
+++ b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/ByNameToByIndexFieldAccessRule.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.optimizer.rules;
 
 import java.util.ArrayList;
@@ -49,11 +64,6 @@
             return false;
         }
         AssignOperator assign = (AssignOperator) op;
-        // if
-        // (assign.getAnnotations().get(AsterixOperatorAnnotations.PUSHED_FIELD_ACCESS)
-        // == null) {
-        // return false;
-        // }
         if (assign.getExpressions().get(0).getValue().getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
             return false;
         }
@@ -123,6 +133,7 @@
         return changed;
     }
 
+    @SuppressWarnings("unchecked")
     private static ILogicalExpression createFieldAccessByIndex(ARecordType recType, AbstractFunctionCallExpression fce) {
         String s = getStringSecondArgument(fce);
         if (s == null) {
diff --git a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/ConstantFoldingRule.java b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/ConstantFoldingRule.java
index 36783ce..a8e6961 100644
--- a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/ConstantFoldingRule.java
+++ b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/ConstantFoldingRule.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.optimizer.rules;
 
 import java.io.DataInputStream;
@@ -106,7 +121,6 @@
         if (context.checkIfInDontApplySet(this, op)) {
             return false;
         }
-        // context.addToDontApplySet(this, op);
         return op.acceptExpressionTransform(cfv);
     }
 
@@ -167,6 +181,8 @@
             resStore.reset();
             eval.evaluate(null);
             Object t = _emptyTypeEnv.getType(expr);
+            
+            @SuppressWarnings("rawtypes")
             ISerializerDeserializer serde = _jobGenCtx.getSerializerDeserializerProvider().getSerializerDeserializer(t);
             bbis.setByteBuffer(ByteBuffer.wrap(resStore.getBytes(), resStore.getStartIndex(), resStore.getLength()), 0);
             IAObject o;
diff --git a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/IntroduceDynamicTypeCastRule.java b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/IntroduceDynamicTypeCastRule.java
index 1bd4127..35a5966 100644
--- a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/IntroduceDynamicTypeCastRule.java
+++ b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/IntroduceDynamicTypeCastRule.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.optimizer.rules;
 
 import java.util.ArrayList;
@@ -73,50 +88,39 @@
         IVariableTypeEnvironment env = oldAssignOperator.computeInputTypeEnvironment(context);
         ARecordType inputRecordType = (ARecordType) env.getVarType(inputRecordVar);
 
-        boolean needCast = needCast(requiredRecordType, inputRecordType);
-        if (needCast) {
-            // insert
-            // project
-            // assign
-            // assign
-            AbstractFunctionCallExpression cast = new ScalarFunctionCallExpression(
-                    FunctionUtils.getFunctionInfo(AsterixBuiltinFunctions.CAST_RECORD));
-            ARecordType[] types = new ARecordType[2];
-            types[0] = requiredRecordType;
-            types[1] = inputRecordType;
-            cast.getArguments().add(
-                    new MutableObject<ILogicalExpression>(new VariableReferenceExpression(inputRecordVar)));
-            cast.setOpaqueParameters(types);
-            LogicalVariable newAssignVar = context.newVar();
-            AssignOperator newAssignOperator = new AssignOperator(newAssignVar, new MutableObject<ILogicalExpression>(
-                    cast));
-            newAssignOperator.getInputs().add(new MutableObject<ILogicalOperator>(op3));
-
-            List<LogicalVariable> projectVariables = new ArrayList<LogicalVariable>();
-            VariableUtilities.getProducedVariables(oldAssignOperator, projectVariables);
-            projectVariables.add(newAssignVar);
-            ProjectOperator projectOperator = new ProjectOperator(projectVariables);
-            projectOperator.getInputs().add(new MutableObject<ILogicalOperator>(newAssignOperator));
-
-            ILogicalExpression payloadExpr = new VariableReferenceExpression(newAssignVar);
-            MutableObject<ILogicalExpression> payloadRef = new MutableObject<ILogicalExpression>(payloadExpr);
-            InsertDeleteOperator newInserDeleteOperator = new InsertDeleteOperator(
-                    insertDeleteOperator.getDataSource(), payloadRef, insertDeleteOperator.getPrimaryKeyExpressions(),
-                    insertDeleteOperator.getOperation());
-            newInserDeleteOperator.getInputs().add(new MutableObject<ILogicalOperator>(projectOperator));
-            insertDeleteOperator.getInputs().clear();
-            op1.getInputs().get(0).setValue(newInserDeleteOperator);
-            return true;
-        }
-        return false;
-
-    }
-
-    private boolean needCast(ARecordType reqType, ARecordType inputType) {
-        if (!reqType.equals(inputType))
-            return true;
-        else
+        boolean needCast = !requiredRecordType.equals(inputRecordType);
+        if (!needCast)
             return false;
+
+        // insert
+        // project
+        // assign
+        // assign
+        AbstractFunctionCallExpression cast = new ScalarFunctionCallExpression(
+                FunctionUtils.getFunctionInfo(AsterixBuiltinFunctions.CAST_RECORD));
+        ARecordType[] types = new ARecordType[2];
+        types[0] = requiredRecordType;
+        types[1] = inputRecordType;
+        cast.getArguments().add(new MutableObject<ILogicalExpression>(new VariableReferenceExpression(inputRecordVar)));
+        cast.setOpaqueParameters(types);
+        LogicalVariable newAssignVar = context.newVar();
+        AssignOperator newAssignOperator = new AssignOperator(newAssignVar, new MutableObject<ILogicalExpression>(cast));
+        newAssignOperator.getInputs().add(new MutableObject<ILogicalOperator>(op3));
+
+        List<LogicalVariable> projectVariables = new ArrayList<LogicalVariable>();
+        VariableUtilities.getProducedVariables(oldAssignOperator, projectVariables);
+        projectVariables.add(newAssignVar);
+        ProjectOperator projectOperator = new ProjectOperator(projectVariables);
+        projectOperator.getInputs().add(new MutableObject<ILogicalOperator>(newAssignOperator));
+
+        ILogicalExpression payloadExpr = new VariableReferenceExpression(newAssignVar);
+        MutableObject<ILogicalExpression> payloadRef = new MutableObject<ILogicalExpression>(payloadExpr);
+        InsertDeleteOperator newInserDeleteOperator = new InsertDeleteOperator(insertDeleteOperator.getDataSource(),
+                payloadRef, insertDeleteOperator.getPrimaryKeyExpressions(), insertDeleteOperator.getOperation());
+        newInserDeleteOperator.getInputs().add(new MutableObject<ILogicalOperator>(projectOperator));
+        insertDeleteOperator.getInputs().clear();
+        op1.getInputs().get(0).setValue(newInserDeleteOperator);
+        return true;
     }
 
 }
diff --git a/asterix-app/src/test/resources/runtimets/queries/dml/opentype-c2o.aql b/asterix-app/src/test/resources/runtimets/queries/dml/opentype-c2o.aql
index ef6cd3a..e29ccdc 100644
--- a/asterix-app/src/test/resources/runtimets/queries/dml/opentype-c2o.aql
+++ b/asterix-app/src/test/resources/runtimets/queries/dml/opentype-c2o.aql
@@ -1,3 +1,10 @@
+/* 
+ * Test case Name  : opentype-c2o.aql
+ * Description     : read data from a closed type dataset into a open type dataset and verify if
+ *					records can be casted to the target open type 
+ * Expected Result : Success
+ */
+
 drop dataverse testdv2 if exists;
 create dataverse testdv2;
 use dataverse testdv2;
@@ -8,6 +15,10 @@
   hobby: string?
 }
 
+/*
+* name and hobby from the closed dataset will
+* become open fields, and hobby can be null
+*/
 create type testtype2 as open {
   id: string
 }
@@ -17,15 +28,15 @@
 create dataset testds2(testtype2) partitioned by key id;
  
 insert into dataset testds (
-{ "id": "001", "name": "Person Three", "hobby": "music"}
+{ "hobby": "music", "id": "001", "name": "Person Three"}
 );
 
 insert into dataset testds (
-{ "id": "002", "name": "Person One", "hobby": "sports"}
+{ "name": "Person One", "id": "002", "hobby": "sports"}
 );
 
 insert into dataset testds (
-{ "id": "003", "name": "Person Two", "hobby": "movie"}
+{ "id": "003", "hobby": "movie", "name": "Person Two"}
 );
 
 insert into dataset testds (
@@ -33,7 +44,7 @@
 );
  
 insert into dataset testds (
-{ "id": "005", "name": "Person Five"}
+{ "name": "Person Five", "id": "005"}
 ); 
  
 insert into dataset testds2 (
diff --git a/asterix-app/src/test/resources/runtimets/queries/dml/opentype-closed-optional.aql b/asterix-app/src/test/resources/runtimets/queries/dml/opentype-closed-optional.aql
index cc3b622..94991be 100644
--- a/asterix-app/src/test/resources/runtimets/queries/dml/opentype-closed-optional.aql
+++ b/asterix-app/src/test/resources/runtimets/queries/dml/opentype-closed-optional.aql
@@ -1,9 +1,15 @@
+/* 
+ * Test case Name  : opentype-closed-optional.aql
+ * Description     : verify that closed type can have optional fields
+ * Expected Result : Success
+ */
+
 drop dataverse testdv2 if exists;
 create dataverse testdv2;
 use dataverse testdv2;
 
 create type testtype as closed {
-  name: string ?,
+  name: string?,
   id: string
 }
 
diff --git a/asterix-app/src/test/resources/runtimets/queries/dml/opentype-insert.aql b/asterix-app/src/test/resources/runtimets/queries/dml/opentype-insert.aql
index 19dd1d6..12248dd 100644
--- a/asterix-app/src/test/resources/runtimets/queries/dml/opentype-insert.aql
+++ b/asterix-app/src/test/resources/runtimets/queries/dml/opentype-insert.aql
@@ -1,3 +1,9 @@
+/* 
+ * Test case Name  : opentype-insert.aql
+ * Description     : verify static type casting
+ * Expected Result : Success
+ */
+
 drop dataverse testdv2 if exists;
 create dataverse testdv2;
 use dataverse testdv2;
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
index db5ee2e..1903bf2 100644
--- a/asterix-app/src/test/resources/runtimets/queries/dml/opentype-insert2.aql
+++ b/asterix-app/src/test/resources/runtimets/queries/dml/opentype-insert2.aql
@@ -1,12 +1,16 @@
-//Test the case where SetClosedRecordRule should not rewrite
-//the plan to use closed-record-descriptor;
+/* 
+ * Test case Name  : opentype-insert2.aql
+ * Description     : verify that the case where SetClosedRecordRule should not rewrite
+ *					the plan to use closed-record-descriptor
+ * Expected Result : Success
+ */
 
 drop dataverse test if exists;
 create dataverse test;
 use dataverse test;
 
 create type TestType as open {
-id:int32
+	id:int32
 }
 
 create dataset testds(TestType) partitioned by key id;
diff --git a/asterix-app/src/test/resources/runtimets/queries/dml/opentype-noexpand.aql b/asterix-app/src/test/resources/runtimets/queries/dml/opentype-noexpand.aql
index f8b4880..c6ff1cd 100644
--- a/asterix-app/src/test/resources/runtimets/queries/dml/opentype-noexpand.aql
+++ b/asterix-app/src/test/resources/runtimets/queries/dml/opentype-noexpand.aql
@@ -1,9 +1,16 @@
+/* 
+ * Test case Name  : opentype-noexpand.aql
+ * Description     : verify that open type dataset can have records without open fields
+ *					 verify the bag-based fields
+ * Expected Result : Success
+ */
+ 
 drop dataverse testdv2 if exists;
 create dataverse testdv2;
 use dataverse testdv2;
 
 create type testtype as open {
-  name: string ?,
+  name: string?,
   id: string
 }
 
diff --git a/asterix-app/src/test/resources/runtimets/queries/dml/opentype-o2c.aql b/asterix-app/src/test/resources/runtimets/queries/dml/opentype-o2c.aql
index d160f40..a6ed9cc 100644
--- a/asterix-app/src/test/resources/runtimets/queries/dml/opentype-o2c.aql
+++ b/asterix-app/src/test/resources/runtimets/queries/dml/opentype-o2c.aql
@@ -1,3 +1,11 @@
+/* 
+ * Test case Name  : opentype-o2c.aql
+ * Description     : verify that open records can be inserted into a closed dataset
+ *					 verify missing optional fields in the closed part of the target closed dataset are allowed
+ * Expected Result : Success
+ */
+
+
 drop dataverse testdv2 if exists;
 create dataverse testdv2;
 use dataverse testdv2;
@@ -8,9 +16,9 @@
 }
 
 create type testtype2 as closed {
+  hobby: string?,
   id: string,
-  name: string,
-  hobby: string?
+  name: string
 }
 
 create dataset testds(testtype) partitioned by key id;
@@ -18,7 +26,7 @@
 create dataset testds2(testtype2) partitioned by key id; 
  
 insert into dataset testds (
-{ "id": "001", "name": "Person Three", "hobby": "music"}
+{ "id": "001",  "hobby": "music", "name": "Person Three"}
 );
 
 insert into dataset testds (
@@ -30,7 +38,7 @@
 );
 
 insert into dataset testds (
-{ "id": "004", "name": "Person Three", "hobby": "swimming"}
+{ "name": "Person Three", "hobby": "swimming", "id": "004"}
 );
 
 insert into dataset testds (
diff --git a/asterix-app/src/test/resources/runtimets/queries/dml/opentype-o2o.aql b/asterix-app/src/test/resources/runtimets/queries/dml/opentype-o2o.aql
index 6793180..545790b 100644
--- a/asterix-app/src/test/resources/runtimets/queries/dml/opentype-o2o.aql
+++ b/asterix-app/src/test/resources/runtimets/queries/dml/opentype-o2o.aql
@@ -1,3 +1,11 @@
+/* 
+ * Test case Name  : opentype-o2o.aql
+ * Description     : verify that the dynamic type cast from one open type to another compatible open type
+ *					 verify the bag-based fields
+ * Expected Result : Success
+ */
+
+
 drop dataverse testdv2 if exists;
 create dataverse testdv2;
 use dataverse testdv2;
@@ -22,7 +30,7 @@
 );
 
 insert into dataset testds (
-{ "name": "Person Two", "id": "002",  "hobby": "football", "city":"irvine"}
+{ "hobby": "football", "city":"irvine", "name": "Person Two", "id": "002"}
 );
 
 insert into dataset testds (
@@ -30,7 +38,7 @@
 );
 
 insert into dataset testds (
-{ "name": "Person Four", "id": "004",  "hobby": "swimming", "phone":"102-304-506"}
+{ "hobby": "swimming", "name": "Person Four", "id": "004", "phone":"102-304-506"}
 );
 
 insert into dataset testds2 (
diff --git a/asterix-app/src/test/resources/runtimets/queries/open-closed/open-closed-02.aql b/asterix-app/src/test/resources/runtimets/queries/open-closed/open-closed-02.aql
index c037cc8..e15577b 100644
--- a/asterix-app/src/test/resources/runtimets/queries/open-closed/open-closed-02.aql
+++ b/asterix-app/src/test/resources/runtimets/queries/open-closed/open-closed-02.aql
@@ -19,7 +19,7 @@
 
 create dataset testds(testType) partitioned by key id;
 
-insert into dataset testds({"id": 123);
+insert into dataset testds({"id": 123});
 
 write output to nc1:"rttest/open-closed_open-closed-02.adm";
 for $l in dataset("testds") return $l
diff --git a/asterix-app/src/test/resources/runtimets/results/dml/opentype-o2c.adm b/asterix-app/src/test/resources/runtimets/results/dml/opentype-o2c.adm
index 34023cd..d9c778b 100644
--- a/asterix-app/src/test/resources/runtimets/results/dml/opentype-o2c.adm
+++ b/asterix-app/src/test/resources/runtimets/results/dml/opentype-o2c.adm
@@ -1,5 +1,5 @@
-{ "id": "001", "name": "Person Three", "hobby": "music" }
-{ "id": "002", "name": "Person Three", "hobby": "football" }
-{ "id": "003", "name": "Person Three", "hobby": "movie" }
-{ "id": "004", "name": "Person Three", "hobby": "swimming" }
-{ "id": "005", "name": "Person Five", "hobby": null }
+{ "hobby": "music", "id": "001", "name": "Person Three" }
+{ "hobby": "football", "id": "002", "name": "Person Three" }
+{ "hobby": "movie", "id": "003", "name": "Person Three" }
+{ "hobby": "swimming", "id": "004", "name": "Person Three" }
+{ "hobby": null, "id": "005", "name": "Person Five" }
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 9aeac2b..a996683 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
@@ -737,8 +737,6 @@
         builtinFunctionsSet.put(functionInfo, functionInfo);
         funTypeComputer.put(functionInfo, typeComputer);
         asterixFunctionIdToInfo.put(fi, functionInfo);
-        // AsterixFunction asterixFunction = new AsterixFunction(fi.getName(),
-        // fi.getArity());
     }
 
     private static void addAgg(FunctionIdentifier fi) {
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/IFunctionDescriptorFactory.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/IFunctionDescriptorFactory.java
index dd77193..516bf51 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/IFunctionDescriptorFactory.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/IFunctionDescriptorFactory.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.om.functions;
 
 public interface IFunctionDescriptorFactory {
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/common/FunctionManagerImpl.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/common/FunctionManagerImpl.java
index 72a2b70..b5b6f29 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/common/FunctionManagerImpl.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/common/FunctionManagerImpl.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.evaluators.common;
 
 import java.util.ArrayList;
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/ARecordAccessor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/ARecordAccessor.java
index 9a048f5..d45b4ac 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/ARecordAccessor.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/ARecordAccessor.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.util;
 
 import java.io.DataOutputStream;
@@ -23,11 +38,11 @@
     private List<SimpleValueReference> fieldValues = new ArrayList<SimpleValueReference>();
 
     private byte[] typeBuffer = new byte[32768];
-    private ResetableByteArrayOutputStream typeBos = new ResetableByteArrayOutputStream();
+    private ResettableByteArrayOutputStream typeBos = new ResettableByteArrayOutputStream();
     private DataOutputStream typeDos = new DataOutputStream(typeBos);
 
     private byte[] dataBuffer = new byte[32768];
-    private ResetableByteArrayOutputStream dataBos = new ResetableByteArrayOutputStream();
+    private ResettableByteArrayOutputStream dataBos = new ResettableByteArrayOutputStream();
     private DataOutputStream dataDos = new DataOutputStream(dataBos);
 
     private int closedPartTypeInfoSize = 0;
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/ARecordCaster.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/ARecordCaster.java
index 5ba7a31..505e769 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/ARecordCaster.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/ARecordCaster.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.util;
 
 import java.io.DataOutput;
@@ -13,23 +28,29 @@
 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.api.dataflow.value.IBinaryComparator;
 import edu.uci.ics.hyracks.api.dataflow.value.INullWriter;
+import edu.uci.ics.hyracks.data.std.accessors.PointableBinaryComparatorFactory;
+import edu.uci.ics.hyracks.data.std.primitive.UTF8StringPointable;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.IValueReference;
 
 public class ARecordCaster {
 
     // describe closed fields in the required type
     private int[] fieldPermutation;
+    private boolean[] optionalFields;
 
     // describe fields (open or not) in the input records
     private boolean[] openFields;
-    private boolean[] optionalFields;
+    private int[] fieldNamesSortedIndex;
 
     private List<SimpleValueReference> reqFieldNames = new ArrayList<SimpleValueReference>();
+    private int[] reqFieldNamesSortedIndex;
     private List<SimpleValueReference> reqFieldTypeTags = new ArrayList<SimpleValueReference>();
     private ARecordType cachedReqType = null;
 
     private byte[] buffer = new byte[32768];
-    private ResetableByteArrayOutputStream bos = new ResetableByteArrayOutputStream();
+    private ResettableByteArrayOutputStream bos = new ResettableByteArrayOutputStream();
     private DataOutputStream dos = new DataOutputStream(bos);
 
     private RecordBuilder recBuilder = new RecordBuilder();
@@ -37,6 +58,8 @@
     private SimpleValueReference nullTypeTag = new SimpleValueReference();
 
     private int numInputFields = 0;
+    private IBinaryComparator fieldNameComparator = PointableBinaryComparatorFactory.of(UTF8StringPointable.FACTORY)
+            .createBinaryComparator();
 
     public ARecordCaster() {
         try {
@@ -63,6 +86,7 @@
 
         if (openFields == null || numInputFields > openFields.length) {
             openFields = new boolean[numInputFields];
+            fieldNamesSortedIndex = new int[numInputFields];
         }
         if (cachedReqType == null || !reqType.equals(cachedReqType)) {
             loadRequiredType(reqType);
@@ -79,6 +103,8 @@
             openFields[i] = true;
         for (int i = 0; i < fieldPermutation.length; i++)
             fieldPermutation[i] = -1;
+        for (int i = 0; i < numInputFields; i++)
+            fieldNamesSortedIndex[i] = i;
     }
 
     private void loadRequiredType(ARecordType reqType) throws IOException {
@@ -123,62 +149,57 @@
             typeNamePointable.reset(buffer, nameStart, nameEnd - nameStart);
             reqFieldNames.add(typeNamePointable);
         }
+
+        reqFieldNamesSortedIndex = new int[reqFieldNames.size()];
+        for (int i = 0; i < reqFieldNamesSortedIndex.length; i++)
+            reqFieldNamesSortedIndex[i] = i;
+        // sort the field name index
+        quickSort(reqFieldNamesSortedIndex, reqFieldNames, 0, reqFieldNamesSortedIndex.length - 1);
     }
 
     private void matchClosedPart(List<SimpleValueReference> fieldNames, List<SimpleValueReference> fieldTypeTags,
             List<SimpleValueReference> fieldValues) {
-        // forward match: match from actual to required
-        boolean matched = false;
-        for (int i = 0; i < numInputFields; i++) {
-            SimpleValueReference fieldName = fieldNames.get(i);
-            SimpleValueReference fieldTypeTag = fieldTypeTags.get(i);
-            matched = false;
-            for (int j = 0; j < reqFieldNames.size(); j++) {
-                SimpleValueReference reqFieldName = reqFieldNames.get(j);
-                SimpleValueReference reqFieldTypeTag = reqFieldTypeTags.get(j);
-                if (fieldName.equals(reqFieldName) && fieldTypeTag.equals(reqFieldTypeTag)) {
-                    fieldPermutation[j] = i;
-                    openFields[i] = false;
-                    matched = true;
-                    break;
+        // sort-merge based match
+        quickSort(fieldNamesSortedIndex, fieldNames, 0, numInputFields - 1);
+        int fnStart = 0;
+        int reqFnStart = 0;
+        while (fnStart < numInputFields && reqFnStart < reqFieldNames.size()) {
+            int fnPos = fieldNamesSortedIndex[fnStart];
+            int reqFnPos = reqFieldNamesSortedIndex[reqFnStart];
+            int c = compare(fieldNames.get(fnPos), reqFieldNames.get(reqFnPos));
+            if (c == 0) {
+                SimpleValueReference fieldTypeTag = fieldTypeTags.get(fnPos);
+                SimpleValueReference reqFieldTypeTag = reqFieldTypeTags.get(reqFnPos);
+                if (fieldTypeTag.equals(reqFieldTypeTag) || (
+                // match the null type of optional field
+                        optionalFields[reqFnPos] && fieldTypeTag.equals(nullTypeTag))) {
+                    fieldPermutation[reqFnPos] = fnPos;
+                    openFields[fnPos] = false;
                 }
+                fnStart++;
+                reqFnStart++;
             }
-            if (matched)
-                continue;
-            // the input has extra fields
-            if (!cachedReqType.isOpen())
+            if (c > 0)
+                reqFnStart++;
+            if (c < 0)
+                fnStart++;
+        }
+
+        // check unmatched fields in the input type
+        for (int i = 0; i < openFields.length; i++) {
+            if (openFields[i] == true && !cachedReqType.isOpen())
                 throw new IllegalStateException("type mismatch: including extra closed fields");
         }
 
-        // backward match: match from required to actual
-        for (int i = 0; i < reqFieldNames.size(); i++) {
-            SimpleValueReference reqFieldName = reqFieldNames.get(i);
-            SimpleValueReference reqFieldTypeTag = reqFieldTypeTags.get(i);
-            matched = false;
-            for (int j = 0; j < numInputFields; j++) {
-                SimpleValueReference fieldName = fieldNames.get(j);
-                SimpleValueReference fieldTypeTag = fieldTypeTags.get(j);
-                if (fieldName.equals(reqFieldName)) {
-                    if (fieldTypeTag.equals(reqFieldTypeTag)) {
-                        matched = true;
-                        break;
-                    }
-
-                    // match the null type of optional field
-                    if (optionalFields[i] && fieldTypeTag.equals(nullTypeTag)) {
-                        matched = true;
-                        break;
-                    }
+        // check unmatched fields in the required type
+        for (int i = 0; i < fieldPermutation.length; i++) {
+            if (fieldPermutation[i] < 0) {
+                IAType t = cachedReqType.getFieldTypes()[i];
+                if (!(t.getTypeTag() == ATypeTag.UNION && NonTaggedFormatUtil.isOptionalField((AUnionType) t))) {
+                    // no matched field in the input for a required closed field
+                    throw new IllegalStateException("type mismatch: miss a required closed field");
                 }
             }
-            if (matched)
-                continue;
-
-            IAType t = cachedReqType.getFieldTypes()[i];
-            if (!(t.getTypeTag() == ATypeTag.UNION && NonTaggedFormatUtil.isOptionalField((AUnionType) t))) {
-                // no matched field in the input for a required closed field
-                throw new IllegalStateException("type mismatch: miss a required closed field");
-            }
         }
     }
 
@@ -210,4 +231,45 @@
         }
         recBuilder.write(output, true);
     }
+
+    private void quickSort(int[] index, List<SimpleValueReference> names, int start, int end) {
+        if (end <= start)
+            return;
+        int i = partition(index, names, start, end);
+        quickSort(index, names, start, i - 1);
+        quickSort(index, names, i + 1, end);
+    }
+
+    private int partition(int[] index, List<SimpleValueReference> names, int left, int right) {
+        int i = left - 1;
+        int j = right;
+        while (true) {
+            // grow from the left
+            while (compare(names.get(index[++i]), names.get(index[right])) < 0)
+                ;
+            // lower from the right
+            while (compare(names.get(index[right]), names.get(index[--j])) < 0)
+                if (j == left)
+                    break;
+            if (i >= j)
+                break;
+            // swap i and j
+            swap(index, i, j);
+        }
+        // swap i and right
+        swap(index, i, right); // swap with partition element
+        return i;
+    }
+
+    private void swap(int[] array, int i, int j) {
+        int temp = array[i];
+        array[i] = array[j];
+        array[j] = temp;
+    }
+
+    private int compare(IValueReference a, IValueReference b) {
+        // start+1 and len-1 due to the type tag
+        return fieldNameComparator.compare(a.getBytes(), a.getStartIndex() + 1, a.getLength() - 1, b.getBytes(),
+                b.getStartIndex() + 1, b.getLength() - 1);
+    }
 }
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/ResetableByteArrayInputStream.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/ResettableByteArrayInputStream.java
similarity index 88%
rename from asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/ResetableByteArrayInputStream.java
rename to asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/ResettableByteArrayInputStream.java
index 7f8f0e9..af18133 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/ResetableByteArrayInputStream.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/ResettableByteArrayInputStream.java
@@ -18,13 +18,13 @@
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-public class ResetableByteArrayInputStream extends ByteArrayInputStream {
-    private static final Logger LOGGER = Logger.getLogger(ResetableByteArrayInputStream.class.getName());
+public class ResettableByteArrayInputStream extends ByteArrayInputStream {
+    private static final Logger LOGGER = Logger.getLogger(ResettableByteArrayInputStream.class.getName());
 
     private byte[] data;
     private int position;
 
-    public ResetableByteArrayInputStream(byte[] data) {
+    public ResettableByteArrayInputStream(byte[] data) {
         super(data);
     }
 
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/ResetableByteArrayOutputStream.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/ResettableByteArrayOutputStream.java
similarity index 89%
rename from asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/ResetableByteArrayOutputStream.java
rename to asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/ResettableByteArrayOutputStream.java
index 2958314..62db3a9 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/ResetableByteArrayOutputStream.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/ResettableByteArrayOutputStream.java
@@ -18,13 +18,13 @@
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-public class ResetableByteArrayOutputStream extends ByteArrayOutputStream {
-    private static final Logger LOGGER = Logger.getLogger(ResetableByteArrayOutputStream.class.getName());
+public class ResettableByteArrayOutputStream extends ByteArrayOutputStream {
+    private static final Logger LOGGER = Logger.getLogger(ResettableByteArrayOutputStream.class.getName());
 
     private byte[] data;
     private int position;
 
-    public ResetableByteArrayOutputStream() {
+    public ResettableByteArrayOutputStream() {
     }
 
     public void setByteArray(byte[] data, int position) {
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/SimpleValueReference.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/SimpleValueReference.java
index bb54624..e49218a 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/SimpleValueReference.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/util/SimpleValueReference.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.util;
 
 import edu.uci.ics.hyracks.dataflow.common.data.accessors.IValueReference;