Merge branch 'master' into ecarm002/aggregate_sql_functions

* master:
  added test case for inverted index + minor change to the c'tor (putting indexName as the last arg)
  added test case
  fix for issue 711
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_null/agg_null.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_null/agg_null.1.ddl.aql
new file mode 100644
index 0000000..aae98cc
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_null/agg_null.1.ddl.aql
@@ -0,0 +1,5 @@
+/*
+* Description  : Run aggregates over both ordered list and unordered list with only null items.
+* Expected Res : Success
+* Date         : Jun 2nd 2013
+*/
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_null/agg_null.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_null/agg_null.2.update.aql
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_null/agg_null.2.update.aql
@@ -0,0 +1 @@
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_null/agg_null.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_null/agg_null.3.query.aql
new file mode 100644
index 0000000..f4fb020
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_null/agg_null.3.query.aql
@@ -0,0 +1,9 @@
+/*
+* Description  : Run aggregates over both ordered list and unordered list with only null items.
+* Expected Res : Success
+* Date         : Jun 2nd 2013
+*/
+
+let $l1 := [null]
+let $l2 := {{null, null}}
+return { "sql-count1": sql-count($l1), "average1": sql-avg($l1), "sql-sum1": sql-sum($l1), "sql-min1": sql-min($l1), "sql-max1": sql-max($l1), "sql-count2": sql-count($l2), "average2": sql-avg($l2), "sql-sum2": sql-sum($l2), "sql-min2": sql-min($l2), "sql-max2": sql-max($l2) } 
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_null_rec/agg_null_rec.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_null_rec/agg_null_rec.1.ddl.aql
new file mode 100644
index 0000000..3546456
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_null_rec/agg_null_rec.1.ddl.aql
@@ -0,0 +1,16 @@
+/*
+* Description  : Run aggregates over records, with only null items for the aggregating fields.
+* Expected Res : Success
+* Date         : Jun 2nd 2013
+*/
+
+drop dataverse test if exists;
+create dataverse test;
+use dataverse test;
+
+create type TestType as open {
+  id: int32,
+  val: double
+}
+
+create dataset Test(TestType) primary key id;
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_null_rec/agg_null_rec.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_null_rec/agg_null_rec.2.update.aql
new file mode 100644
index 0000000..75bc00e
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_null_rec/agg_null_rec.2.update.aql
@@ -0,0 +1,11 @@
+/*
+* Description  : Run aggregates over records, with only null items for the aggregating fields.
+* Expected Res : Success
+* Date         : Jun 2nd 2013
+*/
+
+use dataverse test;
+
+insert into dataset Test ({"id": 0, "val": 4.32, "valplus": 21});
+insert into dataset Test ({"id": 1, "val": 5.32});
+insert into dataset Test ({"id": 2, "val": 6.32, "valplus": 31});
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_null_rec/agg_null_rec.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_null_rec/agg_null_rec.3.query.aql
new file mode 100644
index 0000000..19463da
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_null_rec/agg_null_rec.3.query.aql
@@ -0,0 +1,10 @@
+/*
+* Description  : Run aggregates over records, with only null items for the aggregating fields.
+* Expected Res : Success
+* Date         : Jun 2nd 2013
+*/
+
+use dataverse test;
+
+let $l := for $t in dataset Test return $t.valplus
+return { "sql-count": sql-count($l), "average": sql-avg($l), "sql-sum": sql-sum($l), "sql-min": sql-min($l), "sql-max": sql-max($l) }  
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_null_rec_1/agg_null_rec_1.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_null_rec_1/agg_null_rec_1.1.ddl.aql
new file mode 100644
index 0000000..3546456
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_null_rec_1/agg_null_rec_1.1.ddl.aql
@@ -0,0 +1,16 @@
+/*
+* Description  : Run aggregates over records, with only null items for the aggregating fields.
+* Expected Res : Success
+* Date         : Jun 2nd 2013
+*/
+
+drop dataverse test if exists;
+create dataverse test;
+use dataverse test;
+
+create type TestType as open {
+  id: int32,
+  val: double
+}
+
+create dataset Test(TestType) primary key id;
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_null_rec_1/agg_null_rec_1.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_null_rec_1/agg_null_rec_1.2.update.aql
new file mode 100644
index 0000000..4e0db2b
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_null_rec_1/agg_null_rec_1.2.update.aql
@@ -0,0 +1,11 @@
+/*
+* Description  : Run aggregates over records, with only null items for the aggregating fields.
+* Expected Res : Success
+* Date         : Jun 2nd 2013
+*/
+
+use dataverse test;
+
+insert into dataset Test ({"id": 0, "val": 4.32, "valplus": 473847});
+insert into dataset Test ({"id": 1, "val": 5.32});
+insert into dataset Test ({"id": 2, "val": 6.32, "valplus": 38473827484738239});
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_null_rec_1/agg_null_rec_1.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_null_rec_1/agg_null_rec_1.3.query.aql
new file mode 100644
index 0000000..14ed81d
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_null_rec_1/agg_null_rec_1.3.query.aql
@@ -0,0 +1,12 @@
+/*
+* Description  : Run aggregates over records, with only null items for the aggregating fields.
+* Expected Res : Success
+* Date         : Jun 2nd 2013
+*/
+
+use dataverse test;
+
+let $l := for $t in dataset Test return $t
+return { "sql-count": sql-count($l), "average": sql-avg(for $i in $l return $i.val), "sql-sum":
+sql-sum(for $i in $l return $i.val), "sql-min": sql-min(for $i in $l return $i.valplus),
+"sql-max": sql-max(for $i in $l return $i.valplus) }
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_number/agg_number.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_number/agg_number.1.ddl.aql
new file mode 100644
index 0000000..343be89
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_number/agg_number.1.ddl.aql
@@ -0,0 +1,6 @@
+/*
+* Description  : Run aggregates over an ordered list with numbers of different types
+* Expected Res : Success
+* Date         : Jun 2nd 2013
+*/
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_number/agg_number.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_number/agg_number.2.update.aql
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_number/agg_number.2.update.aql
@@ -0,0 +1 @@
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_number/agg_number.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_number/agg_number.3.query.aql
new file mode 100644
index 0000000..33e8b03
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_number/agg_number.3.query.aql
@@ -0,0 +1,15 @@
+/*
+* Description  : Run aggregates over an ordered list with numbers of different types
+* Expected Res : Success
+* Date         : Jun 2nd 2013
+*/
+
+let $l1 := [float("2.0"), double("3.0"), 93847382783847382, 1]
+let $l2 := {{float("2.0"), double("3.0"), 93847382783847382, 1}}
+let $a1 := sql-count($l2)
+let $a2 := sql-avg($l2)
+let $a3 := sql-sum($l2)
+let $a4 := sql-min($l2)
+let $a5 := sql-max($l2)
+return { "sql-count1": sql-count($l1), "average1": sql-avg($l1), "sql-sum1": sql-sum($l1), "sql-min1": sql-min($l1), "sql-max1": sql-max($l1), "sql-count2": $a1, "average2": $a2, "sql-sum2": $a3, "sql-min2": $a4, "sql-max2": $a5 }
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_number_rec/agg_number_rec.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_number_rec/agg_number_rec.1.ddl.aql
new file mode 100644
index 0000000..53a50fb
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_number_rec/agg_number_rec.1.ddl.aql
@@ -0,0 +1,16 @@
+/*
+* Description  : Run aggregates over records, with different numeric typed items for the aggregating fields.
+* Expected Res : Success
+* Date         : Jun 2nd 2013
+*/
+
+drop dataverse test if exists;
+create dataverse test;
+use dataverse test;
+
+create type TestType as open {
+  id: int32,
+  val: double
+}
+
+create dataset Test(TestType) primary key id;
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_number_rec/agg_number_rec.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_number_rec/agg_number_rec.2.update.aql
new file mode 100644
index 0000000..86aeb85
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_number_rec/agg_number_rec.2.update.aql
@@ -0,0 +1,11 @@
+/*
+* Description  : Run aggregates over records, with different numeric typed items for the aggregating fields.
+* Expected Res : Success
+* Date         : Jun 2nd 2013
+*/
+
+use dataverse test;
+
+insert into dataset Test ({"id": 0, "val": 4.32, "valplus": 2});
+insert into dataset Test ({"id": 1, "val": 5.32, "valplus": 32.98});
+insert into dataset Test ({"id": 2, "val": 6.32, "valplus": 38473827484738239});
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_number_rec/agg_number_rec.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_number_rec/agg_number_rec.3.query.aql
new file mode 100644
index 0000000..9588561
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/agg_number_rec/agg_number_rec.3.query.aql
@@ -0,0 +1,10 @@
+/*
+* Description  : Run aggregates over records, with different numeric typed items for the aggregating fields.
+* Expected Res : Success
+* Date         : Jun 2nd 2013
+*/
+
+use dataverse test;
+
+let $l := for $t in dataset Test return $t.valplus
+return { "sql-count": sql-count($l), "average": sql-avg($l), "sql-sum": sql-sum($l), "sql-min": sql-min($l), "sql-max": sql-max($l) }  
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_double/avg_double.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_double/avg_double.1.ddl.aql
new file mode 100644
index 0000000..55ab0f7
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_double/avg_double.1.ddl.aql
@@ -0,0 +1,6 @@
+drop dataverse test if exists;
+
+create dataverse test;
+
+use dataverse test;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_double/avg_double.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_double/avg_double.2.update.aql
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_double/avg_double.2.update.aql
@@ -0,0 +1 @@
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_double/avg_double.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_double/avg_double.3.query.aql
new file mode 100644
index 0000000..b4cb727
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_double/avg_double.3.query.aql
@@ -0,0 +1,5 @@
+sql-avg(
+ for $x in [1.0, 2.0, double("3.0")]
+ return $x
+)
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_double_null/avg_double_null.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_double_null/avg_double_null.1.ddl.aql
new file mode 100644
index 0000000..7cdcbea
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_double_null/avg_double_null.1.ddl.aql
@@ -0,0 +1,20 @@
+drop dataverse test if exists;
+
+create dataverse test;
+
+use dataverse test;
+
+create type NumericType as open {
+  id: int32,
+  int8Field: int8?,
+  int16Field: int16?,
+  int32Field: int32?,
+  int64Field: int64?,
+  floatField: float?,
+  doubleField: double?
+}
+
+create external dataset Numeric(NumericType)
+using "edu.uci.ics.asterix.external.dataset.adapter.NCFileSystemAdapter"
+(("path"="nc1://data/nontagged/numericData.json"),("format"="adm"));
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_double_null/avg_double_null.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_double_null/avg_double_null.2.update.aql
new file mode 100644
index 0000000..1ecf3aa
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_double_null/avg_double_null.2.update.aql
@@ -0,0 +1 @@
+// no inserts, deletes
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_double_null/avg_double_null.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_double_null/avg_double_null.3.query.aql
new file mode 100644
index 0000000..2b9e5ce
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_double_null/avg_double_null.3.query.aql
@@ -0,0 +1,7 @@
+use dataverse test;
+
+let $a := sql-avg( 
+ for $x in dataset('Numeric') 
+ return $x.doubleField
+)
+return {"average": $a}
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_empty_01/avg_empty_01.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_empty_01/avg_empty_01.1.ddl.aql
new file mode 100644
index 0000000..0970752
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_empty_01/avg_empty_01.1.ddl.aql
@@ -0,0 +1,9 @@
+/*
+ * Description    : Tests that sql-avg aggregation correctly returns null for an empty stream,
+ *                  without an aggregate combiner.
+ * Success        : Yes
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_empty_01/avg_empty_01.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_empty_01/avg_empty_01.2.update.aql
new file mode 100644
index 0000000..e078b9a
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_empty_01/avg_empty_01.2.update.aql
@@ -0,0 +1,7 @@
+/*
+ * Description    : Tests that sql-avg aggregation correctly returns null for an empty stream,
+ *                  without an aggregate combiner.
+ * Success        : Yes
+ */
+
+// no inserts, deletes
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_empty_01/avg_empty_01.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_empty_01/avg_empty_01.3.query.aql
new file mode 100644
index 0000000..f659fcf
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_empty_01/avg_empty_01.3.query.aql
@@ -0,0 +1,13 @@
+/*
+ * Description    : Tests that sql-avg aggregation correctly returns null for an empty stream,
+ *                  without an aggregate combiner.
+ * Success        : Yes
+ */
+
+use dataverse test;
+
+sql-avg(
+ for $x in [1, 2, 3]
+ where $x > 10
+ return $x
+)
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_empty_02/avg_empty_02.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_empty_02/avg_empty_02.1.ddl.aql
new file mode 100644
index 0000000..1c7ee1c
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_empty_02/avg_empty_02.1.ddl.aql
@@ -0,0 +1,18 @@
+/*
+ * Description    : Tests that sql-avg aggregation correctly returns null for an empty stream,
+ *                  with an aggregate combiner.
+ * Success        : Yes
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
+use dataverse test;
+
+create type TestType as closed {
+  id: int32,
+  val: double
+}
+
+create dataset Test(TestType) primary key id;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_empty_02/avg_empty_02.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_empty_02/avg_empty_02.2.update.aql
new file mode 100644
index 0000000..7b6bb9c
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_empty_02/avg_empty_02.2.update.aql
@@ -0,0 +1,7 @@
+/*
+ * Description    : Tests that sql-avg aggregation correctly returns null for an empty stream,
+ *                  with an aggregate combiner.
+ * Success        : Yes
+ */
+
+// no inserts, deletes
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_empty_02/avg_empty_02.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_empty_02/avg_empty_02.3.query.aql
new file mode 100644
index 0000000..7f7489c
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_empty_02/avg_empty_02.3.query.aql
@@ -0,0 +1,12 @@
+/*
+ * Description    : Tests that sql-avg aggregation correctly returns null for an empty stream,
+ *                  with an aggregate combiner.
+ * Success        : Yes
+ */
+
+use dataverse test;
+
+sql-avg(
+ for $x in dataset('Test')
+ return $x.val
+)
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_float/avg_float.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_float/avg_float.1.ddl.aql
new file mode 100644
index 0000000..97b4670
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_float/avg_float.1.ddl.aql
@@ -0,0 +1,4 @@
+drop dataverse test if exists;
+
+create dataverse test;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_float/avg_float.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_float/avg_float.2.update.aql
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_float/avg_float.2.update.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_float/avg_float.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_float/avg_float.3.query.aql
new file mode 100644
index 0000000..a106705
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_float/avg_float.3.query.aql
@@ -0,0 +1,6 @@
+use dataverse test;
+
+sql-avg( 
+ for $x in [float("1"), float("2"), float("3")] 
+ return $x
+)
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_float_null/avg_float_nu.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_float_null/avg_float_nu.1.ddl.aql
new file mode 100644
index 0000000..7cdcbea
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_float_null/avg_float_nu.1.ddl.aql
@@ -0,0 +1,20 @@
+drop dataverse test if exists;
+
+create dataverse test;
+
+use dataverse test;
+
+create type NumericType as open {
+  id: int32,
+  int8Field: int8?,
+  int16Field: int16?,
+  int32Field: int32?,
+  int64Field: int64?,
+  floatField: float?,
+  doubleField: double?
+}
+
+create external dataset Numeric(NumericType)
+using "edu.uci.ics.asterix.external.dataset.adapter.NCFileSystemAdapter"
+(("path"="nc1://data/nontagged/numericData.json"),("format"="adm"));
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_float_null/avg_float_nu.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_float_null/avg_float_nu.2.update.aql
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_float_null/avg_float_nu.2.update.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_float_null/avg_float_nu.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_float_null/avg_float_nu.3.query.aql
new file mode 100644
index 0000000..fdadd1d
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_float_null/avg_float_nu.3.query.aql
@@ -0,0 +1,7 @@
+use dataverse test;
+
+let $a := sql-avg( 
+ for $x in dataset('Numeric') 
+ return $x.floatField
+)
+return {"average": $a}
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int16/avg_int16.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int16/avg_int16.1.ddl.aql
new file mode 100644
index 0000000..97b4670
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int16/avg_int16.1.ddl.aql
@@ -0,0 +1,4 @@
+drop dataverse test if exists;
+
+create dataverse test;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int16/avg_int16.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int16/avg_int16.2.update.aql
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int16/avg_int16.2.update.aql
@@ -0,0 +1 @@
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int16/avg_int16.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int16/avg_int16.3.query.aql
new file mode 100644
index 0000000..c204756
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int16/avg_int16.3.query.aql
@@ -0,0 +1,6 @@
+use dataverse test;
+
+sql-avg( 
+ for $x in [int16("1"), int16("2"), int16("3")] 
+ return $x
+)
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int16_null/avg_int16_null.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int16_null/avg_int16_null.1.ddl.aql
new file mode 100644
index 0000000..7cdcbea
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int16_null/avg_int16_null.1.ddl.aql
@@ -0,0 +1,20 @@
+drop dataverse test if exists;
+
+create dataverse test;
+
+use dataverse test;
+
+create type NumericType as open {
+  id: int32,
+  int8Field: int8?,
+  int16Field: int16?,
+  int32Field: int32?,
+  int64Field: int64?,
+  floatField: float?,
+  doubleField: double?
+}
+
+create external dataset Numeric(NumericType)
+using "edu.uci.ics.asterix.external.dataset.adapter.NCFileSystemAdapter"
+(("path"="nc1://data/nontagged/numericData.json"),("format"="adm"));
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int16_null/avg_int16_null.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int16_null/avg_int16_null.2.update.aql
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int16_null/avg_int16_null.2.update.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int16_null/avg_int16_null.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int16_null/avg_int16_null.3.query.aql
new file mode 100644
index 0000000..738cc6d
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int16_null/avg_int16_null.3.query.aql
@@ -0,0 +1,7 @@
+use dataverse test;
+
+let $a := sql-avg( 
+ for $x in dataset('Numeric') 
+ return $x.int16Field
+)
+return {"average": $a}
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int32/avg_int32.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int32/avg_int32.1.ddl.aql
new file mode 100644
index 0000000..97b4670
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int32/avg_int32.1.ddl.aql
@@ -0,0 +1,4 @@
+drop dataverse test if exists;
+
+create dataverse test;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int32/avg_int32.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int32/avg_int32.2.update.aql
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int32/avg_int32.2.update.aql
@@ -0,0 +1 @@
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int32/avg_int32.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int32/avg_int32.3.query.aql
new file mode 100644
index 0000000..52d5e9b
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int32/avg_int32.3.query.aql
@@ -0,0 +1,7 @@
+use dataverse test;
+
+sql-avg( 
+ for $x in [1, 2, 3] 
+ return $x
+)
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int32_null/avg_int32_null.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int32_null/avg_int32_null.1.ddl.aql
new file mode 100644
index 0000000..7cdcbea
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int32_null/avg_int32_null.1.ddl.aql
@@ -0,0 +1,20 @@
+drop dataverse test if exists;
+
+create dataverse test;
+
+use dataverse test;
+
+create type NumericType as open {
+  id: int32,
+  int8Field: int8?,
+  int16Field: int16?,
+  int32Field: int32?,
+  int64Field: int64?,
+  floatField: float?,
+  doubleField: double?
+}
+
+create external dataset Numeric(NumericType)
+using "edu.uci.ics.asterix.external.dataset.adapter.NCFileSystemAdapter"
+(("path"="nc1://data/nontagged/numericData.json"),("format"="adm"));
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int32_null/avg_int32_null.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int32_null/avg_int32_null.2.update.aql
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int32_null/avg_int32_null.2.update.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int32_null/avg_int32_null.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int32_null/avg_int32_null.3.query.aql
new file mode 100644
index 0000000..a2f16e0
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int32_null/avg_int32_null.3.query.aql
@@ -0,0 +1,7 @@
+use dataverse test;
+
+let $a := sql-avg( 
+ for $x in dataset('Numeric') 
+ return $x.int32Field
+)
+return {"average": $a}
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int64/avg_int64.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int64/avg_int64.1.ddl.aql
new file mode 100644
index 0000000..d330bc0
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int64/avg_int64.1.ddl.aql
@@ -0,0 +1,3 @@
+drop dataverse test if exists;
+
+create dataverse test;
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int64/avg_int64.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int64/avg_int64.2.update.aql
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int64/avg_int64.2.update.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int64/avg_int64.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int64/avg_int64.3.query.aql
new file mode 100644
index 0000000..fa668c1
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int64/avg_int64.3.query.aql
@@ -0,0 +1,6 @@
+use dataverse test;
+
+sql-avg( 
+ for $x in [int64("1"), int64("2"), int64("3")] 
+ return $x
+)
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int64_null/avg_int64_null.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int64_null/avg_int64_null.1.ddl.aql
new file mode 100644
index 0000000..7cdcbea
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int64_null/avg_int64_null.1.ddl.aql
@@ -0,0 +1,20 @@
+drop dataverse test if exists;
+
+create dataverse test;
+
+use dataverse test;
+
+create type NumericType as open {
+  id: int32,
+  int8Field: int8?,
+  int16Field: int16?,
+  int32Field: int32?,
+  int64Field: int64?,
+  floatField: float?,
+  doubleField: double?
+}
+
+create external dataset Numeric(NumericType)
+using "edu.uci.ics.asterix.external.dataset.adapter.NCFileSystemAdapter"
+(("path"="nc1://data/nontagged/numericData.json"),("format"="adm"));
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int64_null/avg_int64_null.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int64_null/avg_int64_null.2.update.aql
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int64_null/avg_int64_null.2.update.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int64_null/avg_int64_null.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int64_null/avg_int64_null.3.query.aql
new file mode 100644
index 0000000..9534dc6
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int64_null/avg_int64_null.3.query.aql
@@ -0,0 +1,7 @@
+use dataverse test;
+
+let $a := sql-avg( 
+ for $x in dataset('Numeric') 
+ return $x.int64Field
+)
+return {"average": $a}
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int8/avg_int8.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int8/avg_int8.1.ddl.aql
new file mode 100644
index 0000000..d330bc0
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int8/avg_int8.1.ddl.aql
@@ -0,0 +1,3 @@
+drop dataverse test if exists;
+
+create dataverse test;
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int8/avg_int8.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int8/avg_int8.2.update.aql
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int8/avg_int8.2.update.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int8/avg_int8.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int8/avg_int8.3.query.aql
new file mode 100644
index 0000000..fc77503
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int8/avg_int8.3.query.aql
@@ -0,0 +1,6 @@
+use dataverse test;
+
+sql-avg( 
+ for $x in [int8("1"),int8("2"), int8("3")] 
+ return $x
+)
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int8_null/avg_int8_null.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int8_null/avg_int8_null.1.ddl.aql
new file mode 100644
index 0000000..5cf8ddf
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int8_null/avg_int8_null.1.ddl.aql
@@ -0,0 +1,19 @@
+drop dataverse test if exists;
+
+create dataverse test;
+
+use dataverse test;
+
+create type NumericType as open {
+  id: int32,
+  int8Field: int8?,
+  int16Field: int16?,
+  int32Field: int32?,
+  int64Field: int64?,
+  floatField: float?,
+  doubleField: double?
+}
+
+create external dataset Numeric(NumericType)
+using "edu.uci.ics.asterix.external.dataset.adapter.NCFileSystemAdapter"
+(("path"="nc1://data/nontagged/numericData.json"),("format"="adm"));
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int8_null/avg_int8_null.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int8_null/avg_int8_null.2.update.aql
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int8_null/avg_int8_null.2.update.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int8_null/avg_int8_null.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int8_null/avg_int8_null.3.query.aql
new file mode 100644
index 0000000..f5d91bf
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_int8_null/avg_int8_null.3.query.aql
@@ -0,0 +1,7 @@
+use dataverse test;
+
+let $a := sql-avg( 
+ for $x in dataset('Numeric') 
+ return $x.int8Field
+)
+return {"average": $a}
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_mixed/avg_mixed.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_mixed/avg_mixed.1.ddl.aql
new file mode 100644
index 0000000..174f7c9
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_mixed/avg_mixed.1.ddl.aql
@@ -0,0 +1,5 @@
+/*
+* Description  : Run sql-avg over an ordered list with mixed types
+* Expected Res : Failure
+* Date         : Jun 2nd 2013
+*/
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_mixed/avg_mixed.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_mixed/avg_mixed.2.update.aql
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_mixed/avg_mixed.2.update.aql
@@ -0,0 +1 @@
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_mixed/avg_mixed.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_mixed/avg_mixed.3.query.aql
new file mode 100644
index 0000000..fbcc3a6
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/avg_mixed/avg_mixed.3.query.aql
@@ -0,0 +1,11 @@
+/*
+* Description  : Run sql-avg over an ordered list with mixed types
+* Expected Res : Failure
+* Date         : Jun 2nd 2013
+*/
+
+sql-avg(
+ for $x in [float("2.0"), "hello world", 93847382783847382, date("2013-01-01")]
+ return $x
+)
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_01/count_01.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_01/count_01.1.ddl.aql
new file mode 100644
index 0000000..55ab0f7
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_01/count_01.1.ddl.aql
@@ -0,0 +1,6 @@
+drop dataverse test if exists;
+
+create dataverse test;
+
+use dataverse test;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_01/count_01.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_01/count_01.2.update.aql
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_01/count_01.2.update.aql
@@ -0,0 +1 @@
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_01/count_01.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_01/count_01.3.query.aql
new file mode 100644
index 0000000..0d87f51
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_01/count_01.3.query.aql
@@ -0,0 +1,12 @@
+use dataverse test;
+
+sql-count( 
+ for $x in [1, 2, 3] 
+ return $x
+)
+
+
+
+
+
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_empty_01/count_empty_01.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_empty_01/count_empty_01.1.ddl.aql
new file mode 100644
index 0000000..22b6585
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_empty_01/count_empty_01.1.ddl.aql
@@ -0,0 +1,10 @@
+/*
+ * Description    : Tests that sql-count aggregation correctly returns 0 for an empty stream,
+ *                  without an aggregate combiner.
+ * Success        : Yes
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+use dataverse test;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_empty_01/count_empty_01.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_empty_01/count_empty_01.2.update.aql
new file mode 100644
index 0000000..6d86705
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_empty_01/count_empty_01.2.update.aql
@@ -0,0 +1,6 @@
+/*
+ * Description    : Tests that sql-count aggregation correctly returns 0 for an empty stream,
+ *                  without an aggregate combiner.
+ * Success        : Yes
+ */
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_empty_01/count_empty_01.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_empty_01/count_empty_01.3.query.aql
new file mode 100644
index 0000000..27a7aa7
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_empty_01/count_empty_01.3.query.aql
@@ -0,0 +1,11 @@
+/*
+ * Description    : Tests that sql-count aggregation correctly returns 0 for an empty stream,
+ *                  without an aggregate combiner.
+ * Success        : Yes
+ */
+
+sql-count(
+ for $x in [1, 2, 3]
+ where $x > 10
+ return $x
+)
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_empty_02/count_empty_02.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_empty_02/count_empty_02.1.ddl.aql
new file mode 100644
index 0000000..0770bfb
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_empty_02/count_empty_02.1.ddl.aql
@@ -0,0 +1,17 @@
+/*
+ * Description    : Tests that sql-count aggregation correctly returns 0 for an empty stream,
+ *                  with an aggregate combiner.
+ * Success        : Yes
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+use dataverse test;
+
+create type TestType as closed {
+  id: int32,
+  val: double
+}
+
+create dataset Test(TestType) primary key id;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_empty_02/count_empty_02.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_empty_02/count_empty_02.2.update.aql
new file mode 100644
index 0000000..774e6ca
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_empty_02/count_empty_02.2.update.aql
@@ -0,0 +1,6 @@
+/*
+ * Description    : Tests that sql-count aggregation correctly returns 0 for an empty stream,
+ *                  with an aggregate combiner.
+ * Success        : Yes
+ */
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_empty_02/count_empty_02.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_empty_02/count_empty_02.3.query.aql
new file mode 100644
index 0000000..33c080a
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_empty_02/count_empty_02.3.query.aql
@@ -0,0 +1,11 @@
+/*
+ * Description    : Tests that sql-count aggregation correctly returns 0 for an empty stream,
+ *                  with an aggregate combiner.
+ * Success        : Yes
+ */
+use dataverse test;
+
+sql-count(
+ for $x in dataset('Test')
+ return $x.val
+)
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_null/count_null.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_null/count_null.1.ddl.aql
new file mode 100644
index 0000000..7cdcbea
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_null/count_null.1.ddl.aql
@@ -0,0 +1,20 @@
+drop dataverse test if exists;
+
+create dataverse test;
+
+use dataverse test;
+
+create type NumericType as open {
+  id: int32,
+  int8Field: int8?,
+  int16Field: int16?,
+  int32Field: int32?,
+  int64Field: int64?,
+  floatField: float?,
+  doubleField: double?
+}
+
+create external dataset Numeric(NumericType)
+using "edu.uci.ics.asterix.external.dataset.adapter.NCFileSystemAdapter"
+(("path"="nc1://data/nontagged/numericData.json"),("format"="adm"));
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_null/count_null.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_null/count_null.2.update.aql
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_null/count_null.2.update.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_null/count_null.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_null/count_null.3.query.aql
new file mode 100644
index 0000000..2e15415
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/count_null/count_null.3.query.aql
@@ -0,0 +1,7 @@
+use dataverse test;
+
+let $c := sql-count( 
+ for $x in dataset('Numeric') 
+ return $x.doubleField
+)
+return {"sql-count": $c}
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue395/issue395.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue395/issue395.1.ddl.aql
new file mode 100644
index 0000000..7c6368c
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue395/issue395.1.ddl.aql
@@ -0,0 +1,10 @@
+drop dataverse test if exists;
+create dataverse test;
+use dataverse test;
+
+create type Emp as open {
+id:int32,
+name:string ?
+}
+
+create dataset Employee(Emp) primary key id;
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue395/issue395.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue395/issue395.2.update.aql
new file mode 100644
index 0000000..d92b582
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue395/issue395.2.update.aql
@@ -0,0 +1,6 @@
+use dataverse test;
+
+insert into dataset Employee({"id":12,"name":"John Doe"});
+insert into dataset Employee({"id":42});
+insert into dataset Employee({"id":22,"name":"John Smith"});
+insert into dataset Employee({"id":19});
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue395/issue395.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue395/issue395.3.query.aql
new file mode 100644
index 0000000..809f0e2
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue395/issue395.3.query.aql
@@ -0,0 +1,4 @@
+use dataverse test;
+
+sql-count(for $l in dataset Employee
+return $l.name)
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue412_0/issue412_0.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue412_0/issue412_0.1.ddl.aql
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue412_0/issue412_0.1.ddl.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue412_0/issue412_0.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue412_0/issue412_0.2.update.aql
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue412_0/issue412_0.2.update.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue412_0/issue412_0.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue412_0/issue412_0.3.query.aql
new file mode 100644
index 0000000..0bced9f
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue412_0/issue412_0.3.query.aql
@@ -0,0 +1,2 @@
+let $l := ["ASTERIX", "Hyracks", null]
+return sql-count($l)
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue412_1/issue412_1.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue412_1/issue412_1.1.ddl.aql
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue412_1/issue412_1.1.ddl.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue412_1/issue412_1.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue412_1/issue412_1.2.update.aql
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue412_1/issue412_1.2.update.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue412_1/issue412_1.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue412_1/issue412_1.3.query.aql
new file mode 100644
index 0000000..de6ab96
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue412_1/issue412_1.3.query.aql
@@ -0,0 +1,2 @@
+let $l := [1, 60, null]
+return { "sql-count": sql-count($l), "average": sql-avg($l), "sql-sum": sql-sum($l), "sql-min": sql-min($l), "sql-max": sql-max($l) } 
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_min_hetero_list/issue425_min_hetero_list.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_min_hetero_list/issue425_min_hetero_list.1.ddl.aql
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_min_hetero_list/issue425_min_hetero_list.1.ddl.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_min_hetero_list/issue425_min_hetero_list.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_min_hetero_list/issue425_min_hetero_list.2.update.aql
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_min_hetero_list/issue425_min_hetero_list.2.update.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_min_hetero_list/issue425_min_hetero_list.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_min_hetero_list/issue425_min_hetero_list.3.query.aql
new file mode 100644
index 0000000..5a0e3b2
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_min_hetero_list/issue425_min_hetero_list.3.query.aql
@@ -0,0 +1,2 @@
+let $l := [23, 748374857483]
+return sql-min($l)
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_min_hetero_list_1/issue425_min_hetero_list_1.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_min_hetero_list_1/issue425_min_hetero_list_1.1.ddl.aql
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_min_hetero_list_1/issue425_min_hetero_list_1.1.ddl.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_min_hetero_list_1/issue425_min_hetero_list_1.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_min_hetero_list_1/issue425_min_hetero_list_1.2.update.aql
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_min_hetero_list_1/issue425_min_hetero_list_1.2.update.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_min_hetero_list_1/issue425_min_hetero_list_1.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_min_hetero_list_1/issue425_min_hetero_list_1.3.query.aql
new file mode 100644
index 0000000..9f436a5
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_min_hetero_list_1/issue425_min_hetero_list_1.3.query.aql
@@ -0,0 +1,2 @@
+let $l := [748374857483, 23, 0.5]
+return sql-min($l)
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_sum_hetero_list/issue425_sum_hetero_list.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_sum_hetero_list/issue425_sum_hetero_list.1.ddl.aql
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_sum_hetero_list/issue425_sum_hetero_list.1.ddl.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_sum_hetero_list/issue425_sum_hetero_list.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_sum_hetero_list/issue425_sum_hetero_list.2.update.aql
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_sum_hetero_list/issue425_sum_hetero_list.2.update.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_sum_hetero_list/issue425_sum_hetero_list.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_sum_hetero_list/issue425_sum_hetero_list.3.query.aql
new file mode 100644
index 0000000..f8fd365
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_sum_hetero_list/issue425_sum_hetero_list.3.query.aql
@@ -0,0 +1,2 @@
+let $l := [23, 748374857483]
+return sql-sum($l)
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_sum_hetero_list_1/issue425_sum_hetero_list_1.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_sum_hetero_list_1/issue425_sum_hetero_list_1.1.ddl.aql
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_sum_hetero_list_1/issue425_sum_hetero_list_1.1.ddl.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_sum_hetero_list_1/issue425_sum_hetero_list_1.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_sum_hetero_list_1/issue425_sum_hetero_list_1.2.update.aql
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_sum_hetero_list_1/issue425_sum_hetero_list_1.2.update.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_sum_hetero_list_1/issue425_sum_hetero_list_1.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_sum_hetero_list_1/issue425_sum_hetero_list_1.3.query.aql
new file mode 100644
index 0000000..0512478
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue425_sum_hetero_list_1/issue425_sum_hetero_list_1.3.query.aql
@@ -0,0 +1,2 @@
+let $l := [748374857483, 23, 0.5]
+return sql-sum($l)
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue531_string_min_max/issue531_string_min_max.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue531_string_min_max/issue531_string_min_max.1.ddl.aql
new file mode 100644
index 0000000..5f9957f
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue531_string_min_max/issue531_string_min_max.1.ddl.aql
@@ -0,0 +1,18 @@
+/**
+ * issue531_string_sql-min_sql-max
+ * 
+ * Purpose: test the support of string values for sql-min and sql-max aggregation function
+ * Result: success
+ * 
+ */
+ 
+drop dataverse test if exists;
+create dataverse test;
+use dataverse test;
+
+create type TestType as open{
+id:int32,
+name:string
+}
+
+create dataset t1(TestType) primary key id;
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue531_string_min_max/issue531_string_min_max.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue531_string_min_max/issue531_string_min_max.2.update.aql
new file mode 100644
index 0000000..59572b5
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue531_string_min_max/issue531_string_min_max.2.update.aql
@@ -0,0 +1,18 @@
+/**
+ * issue531_string_sql-min_sql-max
+ * 
+ * Purpose: test the support of string values for sql-min and sql-max aggregation function
+ * Result: success
+ * 
+ */
+
+use dataverse test;
+
+insert into dataset t1({"id":5,"name":"Smith"});
+insert into dataset t1({"id":12,"name":"Roger"});
+insert into dataset t1({"id":67,"name":"Kevin"});
+insert into dataset t1({"id":32,"name":"Bob"});
+insert into dataset t1({"id":89,"name":"John"});
+insert into dataset t1({"id":10,"name":"Alex"});
+insert into dataset t1({"id":37,"name":"Calvin"});
+insert into dataset t1({"id":98,"name":"Susan"});
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue531_string_min_max/issue531_string_min_max.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue531_string_min_max/issue531_string_min_max.3.query.aql
new file mode 100644
index 0000000..1eca77a
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/issue531_string_min_max/issue531_string_min_max.3.query.aql
@@ -0,0 +1,13 @@
+/**
+ * issue531_string_sql-min_sql-max
+ * 
+ * Purpose: test the support of string values for sql-min and sql-max aggregation function
+ * Result: success
+ * 
+ */
+
+use dataverse test;
+
+{"sql-min": sql-min(for $l in dataset t1
+return $l.name), "sql-max": sql-max(for $l in dataset t1
+return $l.name)}
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/max_empty_01/max_empty_01.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/max_empty_01/max_empty_01.1.ddl.aql
new file mode 100644
index 0000000..6a3be49
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/max_empty_01/max_empty_01.1.ddl.aql
@@ -0,0 +1,9 @@
+/*
+ * Description    : Tests that sql-max aggregation correctly returns null for an empty stream,
+ *                  without an aggregate combiner.
+ * Success        : Yes
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/max_empty_01/max_empty_01.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/max_empty_01/max_empty_01.2.update.aql
new file mode 100644
index 0000000..53df1c8
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/max_empty_01/max_empty_01.2.update.aql
@@ -0,0 +1,7 @@
+/*
+ * Description    : Tests that sql-max aggregation correctly returns null for an empty stream,
+ *                  without an aggregate combiner.
+ * Success        : Yes
+ */
+
+// no inserts/deletes here
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/max_empty_01/max_empty_01.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/max_empty_01/max_empty_01.3.query.aql
new file mode 100644
index 0000000..e7bccb0
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/max_empty_01/max_empty_01.3.query.aql
@@ -0,0 +1,13 @@
+/*
+ * Description    : Tests that sql-max aggregation correctly returns null for an empty stream,
+ *                  without an aggregate combiner.
+ * Success        : Yes
+ */
+
+use dataverse test;
+
+sql-max(
+ for $x in [1, 2, 3]
+ where $x > 10
+ return $x
+)
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/max_empty_02/max_empty_02.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/max_empty_02/max_empty_02.1.ddl.aql
new file mode 100644
index 0000000..6f6b50a
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/max_empty_02/max_empty_02.1.ddl.aql
@@ -0,0 +1,18 @@
+/*
+ * Description    : Tests that sql-max aggregation correctly returns null for an empty stream,
+ *                  with an aggregate combiner.
+ * Success        : Yes
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
+use dataverse test;
+
+create type TestType as closed {
+  id: int32,
+  val: double
+}
+
+create dataset Test(TestType) primary key id;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/max_empty_02/max_empty_02.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/max_empty_02/max_empty_02.2.update.aql
new file mode 100644
index 0000000..421ae94
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/max_empty_02/max_empty_02.2.update.aql
@@ -0,0 +1,6 @@
+/*
+ * Description    : Tests that sql-max aggregation correctly returns null for an empty stream,
+ *                  with an aggregate combiner.
+ * Success        : Yes
+ */
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/max_empty_02/max_empty_02.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/max_empty_02/max_empty_02.3.query.aql
new file mode 100644
index 0000000..02bfcf2
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/max_empty_02/max_empty_02.3.query.aql
@@ -0,0 +1,12 @@
+/*
+ * Description    : Tests that sql-max aggregation correctly returns null for an empty stream,
+ *                  with an aggregate combiner.
+ * Success        : Yes
+ */
+
+use dataverse test;
+
+sql-max(
+ for $x in dataset('Test')
+ return $x.val
+)
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/min_empty_01/min_empty_01.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/min_empty_01/min_empty_01.1.ddl.aql
new file mode 100644
index 0000000..ead6e0d
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/min_empty_01/min_empty_01.1.ddl.aql
@@ -0,0 +1,8 @@
+/*
+ * Description    : Tests that sql-min aggregation correctly returns null for an empty stream,
+ *                  without an aggregate combiner.
+ * Success        : Yes
+ */
+
+drop dataverse test if exists;
+create dataverse test;
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/min_empty_01/min_empty_01.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/min_empty_01/min_empty_01.2.update.aql
new file mode 100644
index 0000000..a5d2f81
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/min_empty_01/min_empty_01.2.update.aql
@@ -0,0 +1,7 @@
+/*
+ * Description    : Tests that sql-min aggregation correctly returns null for an empty stream,
+ *                  without an aggregate combiner.
+ * Success        : Yes
+ */
+
+// no inserts/deletes here
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/min_empty_01/min_empty_01.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/min_empty_01/min_empty_01.3.query.aql
new file mode 100644
index 0000000..fba638c
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/min_empty_01/min_empty_01.3.query.aql
@@ -0,0 +1,13 @@
+/*
+ * Description    : Tests that sql-min aggregation correctly returns null for an empty stream,
+ *                  without an aggregate combiner.
+ * Success        : Yes
+ */
+
+use dataverse test;
+
+sql-min(
+ for $x in [1, 2, 3]
+ where $x > 10
+ return $x
+)
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/min_empty_02/min_empty_02.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/min_empty_02/min_empty_02.1.ddl.aql
new file mode 100644
index 0000000..4888947
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/min_empty_02/min_empty_02.1.ddl.aql
@@ -0,0 +1,18 @@
+/*
+ * Description    : Tests that sql-min aggregation correctly returns null for an empty stream,
+ *                  with an aggregate combiner.
+ * Success        : Yes
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
+use dataverse test;
+
+create type TestType as closed {
+  id: int32,
+  val: double
+}
+
+create dataset Test(TestType) primary key id;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/min_empty_02/min_empty_02.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/min_empty_02/min_empty_02.2.update.aql
new file mode 100644
index 0000000..e88343a
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/min_empty_02/min_empty_02.2.update.aql
@@ -0,0 +1,7 @@
+/*
+ * Description    : Tests that sql-min aggregation correctly returns null for an empty stream,
+ *                  with an aggregate combiner.
+ * Success        : Yes
+ */
+
+// no inserts and deletes here
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/min_empty_02/min_empty_02.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/min_empty_02/min_empty_02.3.query.aql
new file mode 100644
index 0000000..140759a
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/min_empty_02/min_empty_02.3.query.aql
@@ -0,0 +1,12 @@
+/*
+ * Description    : Tests that sql-min aggregation correctly returns null for an empty stream,
+ *                  with an aggregate combiner.
+ * Success        : Yes
+ */
+
+use dataverse test;
+
+sql-min(
+ for $x in dataset('Test')
+ return $x.val
+)
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/min_mixed/min_mixed.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/min_mixed/min_mixed.1.ddl.aql
new file mode 100644
index 0000000..5ca35e0
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/min_mixed/min_mixed.1.ddl.aql
@@ -0,0 +1,5 @@
+/*
+* Description  : Run sql-min over an ordered list with mixed types
+* Expected Res : Failure
+* Date         : Jun 2nd 2013
+*/
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/min_mixed/min_mixed.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/min_mixed/min_mixed.2.update.aql
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/min_mixed/min_mixed.2.update.aql
@@ -0,0 +1 @@
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/min_mixed/min_mixed.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/min_mixed/min_mixed.3.query.aql
new file mode 100644
index 0000000..5912d48
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/min_mixed/min_mixed.3.query.aql
@@ -0,0 +1,11 @@
+/*
+* Description  : Run sql-min over an ordered list with mixed types
+* Expected Res : Failure
+* Date         : Jun 2nd 2013
+*/
+
+sql-min(
+ for $x in [float("2.0"), "hello world", 93847382783847382, date("2013-01-01")]
+ return $x
+)
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/query-issue400/query-issue400.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/query-issue400/query-issue400.1.ddl.aql
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/query-issue400/query-issue400.1.ddl.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/query-issue400/query-issue400.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/query-issue400/query-issue400.2.update.aql
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/query-issue400/query-issue400.2.update.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/query-issue400/query-issue400.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/query-issue400/query-issue400.3.query.aql
new file mode 100644
index 0000000..a36e018
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/query-issue400/query-issue400.3.query.aql
@@ -0,0 +1,9 @@
+/*
+ * Description  : This test case is to verify the fix for issue400
+ 				: https://code.google.com/p/asterixdb/issues/detail?id=400
+ * Expected Res : Success
+ * Date         : 8th May 2013
+ */
+ 
+let $l := [[1,2,3,4,5],[6,7,8,9]]
+return sql-count(for $i in $l return $i)
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_avg/scalar_avg.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_avg/scalar_avg.1.ddl.aql
new file mode 100644
index 0000000..5d15119
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_avg/scalar_avg.1.ddl.aql
@@ -0,0 +1,8 @@
+/*
+ * Description    : Tests the scalar version of sql-avg without nulls.
+ * Success        : Yes
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_avg/scalar_avg.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_avg/scalar_avg.2.update.aql
new file mode 100644
index 0000000..e22fbfc
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_avg/scalar_avg.2.update.aql
@@ -0,0 +1,6 @@
+/*
+ * Description    : Tests the scalar version of sql-avg without nulls.
+ * Success        : Yes
+ */
+
+// no insert delete here
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_avg/scalar_avg.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_avg/scalar_avg.3.query.aql
new file mode 100644
index 0000000..919767a
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_avg/scalar_avg.3.query.aql
@@ -0,0 +1,15 @@
+/*
+ * Description    : Tests the scalar version of sql-avg without nulls.
+ * Success        : Yes
+ */
+
+use dataverse test;
+
+let $i8 := sql-avg([int8("1"), int8("2"), int8("3")])
+let $i16 := sql-avg([int16("1"), int16("2"), int16("3")])
+let $i32 := sql-avg([int32("1"), int32("2"), int32("3")])
+let $i64 := sql-avg([int64("1"), int64("2"), int64("3")])
+let $f := sql-avg([float("1"), float("2"), float("3")])
+let $d := sql-avg([double("1"), double("2"), double("3")])
+for $i in [$i8, $i16, $i32, $i64, $f, $d]
+return $i
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_avg_empty/scalar_avg_empty.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_avg_empty/scalar_avg_empty.1.ddl.aql
new file mode 100644
index 0000000..f219e4e
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_avg_empty/scalar_avg_empty.1.ddl.aql
@@ -0,0 +1,8 @@
+/*
+ * Description    : Tests the scalar version of sql-avg with an empty list.
+ * Success        : Yes
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_avg_empty/scalar_avg_empty.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_avg_empty/scalar_avg_empty.2.update.aql
new file mode 100644
index 0000000..122b595
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_avg_empty/scalar_avg_empty.2.update.aql
@@ -0,0 +1,6 @@
+/*
+ * Description    : Tests the scalar version of sql-avg with an empty list.
+ * Success        : Yes
+ */
+
+// no insert delete here
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_avg_empty/scalar_avg_empty.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_avg_empty/scalar_avg_empty.3.query.aql
new file mode 100644
index 0000000..e99927e
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_avg_empty/scalar_avg_empty.3.query.aql
@@ -0,0 +1,6 @@
+/*
+ * Description    : Tests the scalar version of sql-avg with an empty list.
+ * Success        : Yes
+ */
+
+sql-avg([ ])
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_avg_null/scalar_avg_null.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_avg_null/scalar_avg_null.1.ddl.aql
new file mode 100644
index 0000000..52f73bb
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_avg_null/scalar_avg_null.1.ddl.aql
@@ -0,0 +1,8 @@
+/*
+ * Description    : Tests the scalar version of sql-avg with nulls.
+ * Success        : Yes
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_avg_null/scalar_avg_null.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_avg_null/scalar_avg_null.2.update.aql
new file mode 100644
index 0000000..5871aba
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_avg_null/scalar_avg_null.2.update.aql
@@ -0,0 +1,6 @@
+/*
+ * Description    : Tests the scalar version of sql-avg with nulls.
+ * Success        : Yes
+ */
+
+// no inserts deletes here
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_avg_null/scalar_avg_null.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_avg_null/scalar_avg_null.3.query.aql
new file mode 100644
index 0000000..d44216d
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_avg_null/scalar_avg_null.3.query.aql
@@ -0,0 +1,15 @@
+/*
+ * Description    : Tests the scalar version of sql-avg with nulls.
+ * Success        : Yes
+ */
+
+use dataverse test;
+
+let $i8 := sql-avg([int8("1"), int8("2"), int8("3"), null])
+let $i16 := sql-avg([int16("1"), int16("2"), int16("3"), null])
+let $i32 := sql-avg([int32("1"), int32("2"), int32("3"), null])
+let $i64 := sql-avg([int64("1"), int64("2"), int64("3"), null])
+let $f := sql-avg([float("1"), float("2"), float("3"), null])
+let $d := sql-avg([double("1"), double("2"), double("3"), null])
+for $i in [$i8, $i16, $i32, $i64, $f, $d]
+return $i
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_count/scalar_count.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_count/scalar_count.1.ddl.aql
new file mode 100644
index 0000000..6c7f633
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_count/scalar_count.1.ddl.aql
@@ -0,0 +1,8 @@
+/*
+ * Description    : Tests the scalar version of sql-count without nulls.
+ * Success        : Yes
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_count/scalar_count.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_count/scalar_count.2.update.aql
new file mode 100644
index 0000000..2b20144
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_count/scalar_count.2.update.aql
@@ -0,0 +1,6 @@
+/*
+ * Description    : Tests the scalar version of sql-count without nulls.
+ * Success        : Yes
+ */
+
+// no inserts, deletes here
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_count/scalar_count.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_count/scalar_count.3.query.aql
new file mode 100644
index 0000000..43fe3be
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_count/scalar_count.3.query.aql
@@ -0,0 +1,16 @@
+/*
+ * Description    : Tests the scalar version of sql-count without nulls.
+ * Success        : Yes
+ */
+
+use dataverse test;
+
+let $i8 := sql-count([int8("1"), int8("2"), int8("3")])
+let $i16 := sql-count([int16("1"), int16("2"), int16("3")])
+let $i32 := sql-count([int32("1"), int32("2"), int32("3")])
+let $i64 := sql-count([int64("1"), int64("2"), int64("3")])
+let $f := sql-count([float("1"), float("2"), float("3")])
+let $d := sql-count([double("1"), double("2"), double("3")])
+let $s := sql-count(["a", "b", "c"])
+for $i in [$i8, $i16, $i32, $i64, $f, $d, $s]
+return $i
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_count_empty/scalar_count_empty.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_count_empty/scalar_count_empty.1.ddl.aql
new file mode 100644
index 0000000..3073723
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_count_empty/scalar_count_empty.1.ddl.aql
@@ -0,0 +1,8 @@
+/*
+ * Description    : Tests the scalar version of sql-count with an empty list.
+ * Success        : Yes
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_count_empty/scalar_count_empty.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_count_empty/scalar_count_empty.2.update.aql
new file mode 100644
index 0000000..4905d59
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_count_empty/scalar_count_empty.2.update.aql
@@ -0,0 +1,6 @@
+/*
+ * Description    : Tests the scalar version of sql-count with an empty list.
+ * Success        : Yes
+ */
+
+// no inserts, deletes here
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_count_empty/scalar_count_empty.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_count_empty/scalar_count_empty.3.query.aql
new file mode 100644
index 0000000..17f55b2
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_count_empty/scalar_count_empty.3.query.aql
@@ -0,0 +1,8 @@
+/*
+ * Description    : Tests the scalar version of sql-count with an empty list.
+ * Success        : Yes
+ */
+
+use dataverse test;
+
+sql-count([ ])
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_count_null/scalar_count_null.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_count_null/scalar_count_null.1.ddl.aql
new file mode 100644
index 0000000..b5f9603
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_count_null/scalar_count_null.1.ddl.aql
@@ -0,0 +1,8 @@
+/*
+ * Description    : Tests the scalar version of sql-count with nulls.
+ * Success        : Yes
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_count_null/scalar_count_null.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_count_null/scalar_count_null.2.update.aql
new file mode 100644
index 0000000..e1216d3
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_count_null/scalar_count_null.2.update.aql
@@ -0,0 +1,6 @@
+/*
+ * Description    : Tests the scalar version of sql-count with nulls.
+ * Success        : Yes
+ */
+
+// no inserts, deletes here
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_count_null/scalar_count_null.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_count_null/scalar_count_null.3.query.aql
new file mode 100644
index 0000000..3bfa354
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_count_null/scalar_count_null.3.query.aql
@@ -0,0 +1,16 @@
+/*
+ * Description    : Tests the scalar version of sql-count with nulls.
+ * Success        : Yes
+ */
+
+use dataverse test;
+
+let $i8 := sql-count([int8("1"), int8("2"), int8("3"), null])
+let $i16 := sql-count([int16("1"), int16("2"), int16("3"), null])
+let $i32 := sql-count([int32("1"), int32("2"), int32("3"), null])
+let $i64 := sql-count([int64("1"), int64("2"), int64("3"), null])
+let $f := sql-count([float("1"), float("2"), float("3"), null])
+let $d := sql-count([double("1"), double("2"), double("3"), null])
+let $s := sql-count(["a", "b", "c", null])
+for $i in [$i8, $i16, $i32, $i64, $f, $d, $s]
+return $i
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_max/scalar_max.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_max/scalar_max.1.ddl.aql
new file mode 100644
index 0000000..5c72f61
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_max/scalar_max.1.ddl.aql
@@ -0,0 +1,8 @@
+/*
+ * Description    : Tests the scalar version of sql-max without nulls.
+ * Success        : Yes
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_max/scalar_max.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_max/scalar_max.2.update.aql
new file mode 100644
index 0000000..be12602
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_max/scalar_max.2.update.aql
@@ -0,0 +1,6 @@
+/*
+ * Description    : Tests the scalar version of sql-max without nulls.
+ * Success        : Yes
+ */
+
+// no inserts, deletes here
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_max/scalar_max.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_max/scalar_max.3.query.aql
new file mode 100644
index 0000000..dd55d7e
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_max/scalar_max.3.query.aql
@@ -0,0 +1,17 @@
+/*
+ * Description    : Tests the scalar version of sql-max without nulls.
+ * Success        : Yes
+ */
+
+use dataverse test;
+
+let $i8 := sql-max([int8("1"), int8("2"), int8("3")])
+let $i16 := sql-max([int16("1"), int16("2"), int16("3")])
+let $i32 := sql-max([int32("1"), int32("2"), int32("3")])
+let $i64 := sql-max([int64("1"), int64("2"), int64("3")])
+let $f := sql-max([float("1"), float("2"), float("3")])
+let $d := sql-max([double("1"), double("2"), double("3")])
+let $s := sql-max(["foo", "bar", "world"])
+let $dt := sql-max([datetime("2012-03-01T00:00:00Z"), datetime("2012-01-01T00:00:00Z"), datetime("2012-02-01T00:00:00Z")])
+for $i in [$i8, $i16, $i32, $i64, $f, $d, $s, $dt]
+return $i
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_max_empty/scalar_max_empty.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_max_empty/scalar_max_empty.1.ddl.aql
new file mode 100644
index 0000000..c593eb4
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_max_empty/scalar_max_empty.1.ddl.aql
@@ -0,0 +1,8 @@
+/*
+ * Description    : Tests the scalar version of sql-max with an empty list.
+ * Success        : Yes
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_max_empty/scalar_max_empty.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_max_empty/scalar_max_empty.2.update.aql
new file mode 100644
index 0000000..c5c7707
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_max_empty/scalar_max_empty.2.update.aql
@@ -0,0 +1,6 @@
+/*
+ * Description    : Tests the scalar version of sql-max with an empty list.
+ * Success        : Yes
+ */
+
+// no inserts, deletes here
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_max_empty/scalar_max_empty.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_max_empty/scalar_max_empty.3.query.aql
new file mode 100644
index 0000000..4fb68a7
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_max_empty/scalar_max_empty.3.query.aql
@@ -0,0 +1,8 @@
+/*
+ * Description    : Tests the scalar version of sql-max with an empty list.
+ * Success        : Yes
+ */
+
+use dataverse test;
+
+sql-max([ ])
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_max_null/scalar_max_null.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_max_null/scalar_max_null.1.ddl.aql
new file mode 100644
index 0000000..79f8bd3
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_max_null/scalar_max_null.1.ddl.aql
@@ -0,0 +1,8 @@
+/*
+ * Description    : Tests the scalar version of sql-max with nulls.
+ * Success        : Yes
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_max_null/scalar_max_null.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_max_null/scalar_max_null.2.update.aql
new file mode 100644
index 0000000..9fb5537
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_max_null/scalar_max_null.2.update.aql
@@ -0,0 +1,6 @@
+/*
+ * Description    : Tests the scalar version of sql-max with nulls.
+ * Success        : Yes
+ */
+
+// no inserts, deletes here
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_max_null/scalar_max_null.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_max_null/scalar_max_null.3.query.aql
new file mode 100644
index 0000000..2ef1361
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_max_null/scalar_max_null.3.query.aql
@@ -0,0 +1,17 @@
+/*
+ * Description    : Tests the scalar version of sql-max with nulls.
+ * Success        : Yes
+ */
+
+use dataverse test;
+
+let $i8 := sql-max([int8("1"), int8("2"), int8("3"), null])
+let $i16 := sql-max([int16("1"), int16("2"), int16("3"), null])
+let $i32 := sql-max([int32("1"), int32("2"), int32("3"), null])
+let $i64 := sql-max([int64("1"), int64("2"), int64("3"), null])
+let $f := sql-max([float("1"), float("2"), float("3"), null])
+let $d := sql-max([double("1"), double("2"), double("3"), null])
+let $s := sql-max(["foo", "bar", "world", null])
+let $dt := sql-max([datetime("2012-03-01T00:00:00Z"), datetime("2012-01-01T00:00:00Z"), datetime("2012-02-01T00:00:00Z"), null])
+for $i in [$i8, $i16, $i32, $i64, $f, $d, $s, $dt]
+return $i
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_min/scalar_min.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_min/scalar_min.1.ddl.aql
new file mode 100644
index 0000000..2a64ea03a
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_min/scalar_min.1.ddl.aql
@@ -0,0 +1,8 @@
+/*
+ * Description    : Tests the scalar version of sql-min without nulls.
+ * Success        : Yes
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_min/scalar_min.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_min/scalar_min.2.update.aql
new file mode 100644
index 0000000..e6f3c83
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_min/scalar_min.2.update.aql
@@ -0,0 +1,6 @@
+/*
+ * Description    : Tests the scalar version of sql-min without nulls.
+ * Success        : Yes
+ */
+
+// no inserts, deletes here
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_min/scalar_min.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_min/scalar_min.3.query.aql
new file mode 100644
index 0000000..3758080
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_min/scalar_min.3.query.aql
@@ -0,0 +1,17 @@
+/*
+ * Description    : Tests the scalar version of sql-min without nulls.
+ * Success        : Yes
+ */
+
+use dataverse test;
+
+let $i8 := sql-min([int8("1"), int8("2"), int8("3")])
+let $i16 := sql-min([int16("1"), int16("2"), int16("3")])
+let $i32 := sql-min([int32("1"), int32("2"), int32("3")])
+let $i64 := sql-min([int64("1"), int64("2"), int64("3")])
+let $f := sql-min([float("1"), float("2"), float("3")])
+let $d := sql-min([double("1"), double("2"), double("3")])
+let $s := sql-min(["foo", "bar", "world"])
+let $dt := sql-min([datetime("2012-03-01T00:00:00Z"), datetime("2012-01-01T00:00:00Z"), datetime("2012-02-01T00:00:00Z")])
+for $i in [$i8, $i16, $i32, $i64, $f, $d, $s, $dt]
+return $i
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_min_empty/scalar_min_empty.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_min_empty/scalar_min_empty.1.ddl.aql
new file mode 100644
index 0000000..57e61b7
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_min_empty/scalar_min_empty.1.ddl.aql
@@ -0,0 +1,8 @@
+/*
+ * Description    : Tests the scalar version of sql-min with an empty list.
+ * Success        : Yes
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_min_empty/scalar_min_empty.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_min_empty/scalar_min_empty.2.update.aql
new file mode 100644
index 0000000..ab4b309
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_min_empty/scalar_min_empty.2.update.aql
@@ -0,0 +1,6 @@
+/*
+ * Description    : Tests the scalar version of sql-min with an empty list.
+ * Success        : Yes
+ */
+
+// no inserts, deletes here
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_min_empty/scalar_min_empty.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_min_empty/scalar_min_empty.3.query.aql
new file mode 100644
index 0000000..f3aafa1
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_min_empty/scalar_min_empty.3.query.aql
@@ -0,0 +1,8 @@
+/*
+ * Description    : Tests the scalar version of sql-min with an empty list.
+ * Success        : Yes
+ */
+
+use dataverse test;
+
+sql-min([ ])
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_min_null/scalar_min_null.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_min_null/scalar_min_null.1.ddl.aql
new file mode 100644
index 0000000..bb1e400
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_min_null/scalar_min_null.1.ddl.aql
@@ -0,0 +1,8 @@
+/*
+ * Description    : Tests the scalar version of sql-min with nulls.
+ * Success        : Yes
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_min_null/scalar_min_null.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_min_null/scalar_min_null.2.update.aql
new file mode 100644
index 0000000..26c9a6b
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_min_null/scalar_min_null.2.update.aql
@@ -0,0 +1,6 @@
+/*
+ * Description    : Tests the scalar version of sql-min with nulls.
+ * Success        : Yes
+ */
+
+// no inserts, deletes here
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_min_null/scalar_min_null.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_min_null/scalar_min_null.3.query.aql
new file mode 100644
index 0000000..032f125
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_min_null/scalar_min_null.3.query.aql
@@ -0,0 +1,17 @@
+/*
+ * Description    : Tests the scalar version of sql-min with nulls.
+ * Success        : Yes
+ */
+
+use dataverse test;
+
+let $i8 := sql-min([int8("1"), int8("2"), int8("3"), null])
+let $i16 := sql-min([int16("1"), int16("2"), int16("3"), null])
+let $i32 := sql-min([int32("1"), int32("2"), int32("3"), null])
+let $i64 := sql-min([int64("1"), int64("2"), int64("3"), null])
+let $f := sql-min([float("1"), float("2"), float("3"), null])
+let $d := sql-min([double("1"), double("2"), double("3"), null])
+let $s := sql-min(["foo", "bar", "world", null])
+let $dt := sql-min([datetime("2012-03-01T00:00:00Z"), datetime("2012-01-01T00:00:00Z"), datetime("2012-02-01T00:00:00Z"), null])
+for $i in [$i8, $i16, $i32, $i64, $f, $d, $s, $dt]
+return $i
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_sum/scalar_sum.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_sum/scalar_sum.1.ddl.aql
new file mode 100644
index 0000000..6734cc6
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_sum/scalar_sum.1.ddl.aql
@@ -0,0 +1,8 @@
+/*
+ * Description    : Tests the scalar version of sql-sum without nulls.
+ * Success        : Yes
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_sum/scalar_sum.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_sum/scalar_sum.2.update.aql
new file mode 100644
index 0000000..cacdd99
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_sum/scalar_sum.2.update.aql
@@ -0,0 +1,6 @@
+/*
+ * Description    : Tests the scalar version of sql-sum without nulls.
+ * Success        : Yes
+ */
+
+// no inserts, deletes here
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_sum/scalar_sum.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_sum/scalar_sum.3.query.aql
new file mode 100644
index 0000000..adc94d3
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_sum/scalar_sum.3.query.aql
@@ -0,0 +1,15 @@
+/*
+ * Description    : Tests the scalar version of sql-sum without nulls.
+ * Success        : Yes
+ */
+
+use dataverse test;
+
+let $i8 := sql-sum([int8("1"), int8("2"), int8("3")])
+let $i16 := sql-sum([int16("1"), int16("2"), int16("3")])
+let $i32 := sql-sum([int32("1"), int32("2"), int32("3")])
+let $i64 := sql-sum([int64("1"), int64("2"), int64("3")])
+let $f := sql-sum([float("1"), float("2"), float("3")])
+let $d := sql-sum([double("1"), double("2"), double("3")])
+for $i in [$i8, $i16, $i32, $i64, $f, $d]
+return $i
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_sum_empty/scalar_sum_empty.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_sum_empty/scalar_sum_empty.1.ddl.aql
new file mode 100644
index 0000000..f292f68
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_sum_empty/scalar_sum_empty.1.ddl.aql
@@ -0,0 +1,8 @@
+/*
+ * Description    : Tests the scalar version of sql-sum with an empty list.
+ * Success        : Yes
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_sum_empty/scalar_sum_empty.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_sum_empty/scalar_sum_empty.2.update.aql
new file mode 100644
index 0000000..36453e6
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_sum_empty/scalar_sum_empty.2.update.aql
@@ -0,0 +1,6 @@
+/*
+ * Description    : Tests the scalar version of sql-sum with an empty list.
+ * Success        : Yes
+ */
+
+// no inserts, deletes here
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_sum_empty/scalar_sum_empty.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_sum_empty/scalar_sum_empty.3.query.aql
new file mode 100644
index 0000000..5ef7bfa
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_sum_empty/scalar_sum_empty.3.query.aql
@@ -0,0 +1,8 @@
+/*
+ * Description    : Tests the scalar version of sql-sum with an empty list.
+ * Success        : Yes
+ */
+
+use dataverse test;
+
+sql-sum([ ])
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_sum_null/scalar_sum_null.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_sum_null/scalar_sum_null.1.ddl.aql
new file mode 100644
index 0000000..e3b6154
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_sum_null/scalar_sum_null.1.ddl.aql
@@ -0,0 +1,7 @@
+/*
+ * Description    : Tests the scalar version of sql-sum with nulls.
+ * Success        : Yes
+ */
+
+drop dataverse test if exists;
+create dataverse test;
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_sum_null/scalar_sum_null.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_sum_null/scalar_sum_null.2.update.aql
new file mode 100644
index 0000000..f35e671
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_sum_null/scalar_sum_null.2.update.aql
@@ -0,0 +1,6 @@
+/*
+ * Description    : Tests the scalar version of sql-sum with nulls.
+ * Success        : Yes
+ */
+
+// no inserts, deletes here
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_sum_null/scalar_sum_null.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_sum_null/scalar_sum_null.3.query.aql
new file mode 100644
index 0000000..2d0e120
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/scalar_sum_null/scalar_sum_null.3.query.aql
@@ -0,0 +1,15 @@
+/*
+ * Description    : Tests the scalar version of sql-sum with nulls.
+ * Success        : Yes
+ */
+
+use dataverse test;
+
+let $i8 := sql-sum([int8("1"), int8("2"), int8("3"), null])
+let $i16 := sql-sum([int16("1"), int16("2"), int16("3"), null])
+let $i32 := sql-sum([int32("1"), int32("2"), int32("3"), null])
+let $i64 := sql-sum([int64("1"), int64("2"), int64("3"), null])
+let $f := sql-sum([float("1"), float("2"), float("3"), null])
+let $d := sql-sum([double("1"), double("2"), double("3"), null])
+for $i in [$i8, $i16, $i32, $i64, $f, $d]
+return $i
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_double/sum_double.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_double/sum_double.1.ddl.aql
new file mode 100644
index 0000000..97b4670
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_double/sum_double.1.ddl.aql
@@ -0,0 +1,4 @@
+drop dataverse test if exists;
+
+create dataverse test;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_double/sum_double.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_double/sum_double.2.update.aql
new file mode 100644
index 0000000..d93253f
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_double/sum_double.2.update.aql
@@ -0,0 +1 @@
+// no inserts, deletes here
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_double/sum_double.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_double/sum_double.3.query.aql
new file mode 100644
index 0000000..ddf3598
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_double/sum_double.3.query.aql
@@ -0,0 +1,7 @@
+use dataverse test;
+
+sql-sum( 
+ for $x in [1.0, 2.0, 3.0] 
+ return $x
+)
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_double_null/sum_double_null.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_double_null/sum_double_null.1.ddl.aql
new file mode 100644
index 0000000..7cdcbea
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_double_null/sum_double_null.1.ddl.aql
@@ -0,0 +1,20 @@
+drop dataverse test if exists;
+
+create dataverse test;
+
+use dataverse test;
+
+create type NumericType as open {
+  id: int32,
+  int8Field: int8?,
+  int16Field: int16?,
+  int32Field: int32?,
+  int64Field: int64?,
+  floatField: float?,
+  doubleField: double?
+}
+
+create external dataset Numeric(NumericType)
+using "edu.uci.ics.asterix.external.dataset.adapter.NCFileSystemAdapter"
+(("path"="nc1://data/nontagged/numericData.json"),("format"="adm"));
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_double_null/sum_double_null.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_double_null/sum_double_null.2.update.aql
new file mode 100644
index 0000000..d93253f
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_double_null/sum_double_null.2.update.aql
@@ -0,0 +1 @@
+// no inserts, deletes here
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_double_null/sum_double_null.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_double_null/sum_double_null.3.query.aql
new file mode 100644
index 0000000..80692dd
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_double_null/sum_double_null.3.query.aql
@@ -0,0 +1,6 @@
+use dataverse test;
+
+sql-sum( 
+ for $x in dataset('Numeric') 
+ return $x.doubleField
+)
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_empty_01/sum_empty_01.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_empty_01/sum_empty_01.1.ddl.aql
new file mode 100644
index 0000000..d7a0f6b
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_empty_01/sum_empty_01.1.ddl.aql
@@ -0,0 +1,8 @@
+/*
+ * Description    : Tests that sql-sum aggregation correctly returns null for an empty stream,
+ *                  without an aggregate combiner.
+ * Success        : Yes
+ */
+
+drop dataverse test if exists;
+create dataverse test;
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_empty_01/sum_empty_01.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_empty_01/sum_empty_01.2.update.aql
new file mode 100644
index 0000000..1feb209
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_empty_01/sum_empty_01.2.update.aql
@@ -0,0 +1,7 @@
+/*
+ * Description    : Tests that sql-sum aggregation correctly returns null for an empty stream,
+ *                  without an aggregate combiner.
+ * Success        : Yes
+ */
+
+// no inserts, deletes here
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_empty_01/sum_empty_01.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_empty_01/sum_empty_01.3.query.aql
new file mode 100644
index 0000000..eb5fe35
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_empty_01/sum_empty_01.3.query.aql
@@ -0,0 +1,13 @@
+/*
+ * Description    : Tests that sql-sum aggregation correctly returns null for an empty stream,
+ *                  without an aggregate combiner.
+ * Success        : Yes
+ */
+
+use dataverse test;
+
+sql-sum(
+ for $x in [1, 2, 3]
+ where $x > 10
+ return $x
+)
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_empty_02/sum_empty_02.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_empty_02/sum_empty_02.1.ddl.aql
new file mode 100644
index 0000000..d43610e
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_empty_02/sum_empty_02.1.ddl.aql
@@ -0,0 +1,18 @@
+/*
+ * Description    : Tests that sql-sum aggregation correctly returns null for an empty stream,
+ *                  with an aggregate combiner.
+ * Success        : Yes
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
+use dataverse test;
+
+create type TestType as closed {
+  id: int32,
+  val: double
+}
+
+create dataset Test(TestType) primary key id;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_empty_02/sum_empty_02.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_empty_02/sum_empty_02.2.update.aql
new file mode 100644
index 0000000..c1670f9
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_empty_02/sum_empty_02.2.update.aql
@@ -0,0 +1,7 @@
+/*
+ * Description    : Tests that sql-sum aggregation correctly returns null for an empty stream,
+ *                  with an aggregate combiner.
+ * Success        : Yes
+ */
+
+// no inserts, deletes here
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_empty_02/sum_empty_02.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_empty_02/sum_empty_02.3.query.aql
new file mode 100644
index 0000000..f46bfc1
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_empty_02/sum_empty_02.3.query.aql
@@ -0,0 +1,12 @@
+/*
+ * Description    : Tests that sql-sum aggregation correctly returns null for an empty stream,
+ *                  with an aggregate combiner.
+ * Success        : Yes
+ */
+
+use dataverse test;
+
+sql-sum(
+ for $x in dataset('Test')
+ return $x.val
+)
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_float/sum_float.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_float/sum_float.1.ddl.aql
new file mode 100644
index 0000000..97b4670
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_float/sum_float.1.ddl.aql
@@ -0,0 +1,4 @@
+drop dataverse test if exists;
+
+create dataverse test;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_float/sum_float.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_float/sum_float.2.update.aql
new file mode 100644
index 0000000..d93253f
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_float/sum_float.2.update.aql
@@ -0,0 +1 @@
+// no inserts, deletes here
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_float/sum_float.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_float/sum_float.3.query.aql
new file mode 100644
index 0000000..9fcd5e0
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_float/sum_float.3.query.aql
@@ -0,0 +1,7 @@
+use dataverse test;
+
+sql-sum( 
+ for $x in [float("1"), float("2"), float("3")] 
+ return $x
+)
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_float_null/sum_float_null.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_float_null/sum_float_null.1.ddl.aql
new file mode 100644
index 0000000..7cdcbea
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_float_null/sum_float_null.1.ddl.aql
@@ -0,0 +1,20 @@
+drop dataverse test if exists;
+
+create dataverse test;
+
+use dataverse test;
+
+create type NumericType as open {
+  id: int32,
+  int8Field: int8?,
+  int16Field: int16?,
+  int32Field: int32?,
+  int64Field: int64?,
+  floatField: float?,
+  doubleField: double?
+}
+
+create external dataset Numeric(NumericType)
+using "edu.uci.ics.asterix.external.dataset.adapter.NCFileSystemAdapter"
+(("path"="nc1://data/nontagged/numericData.json"),("format"="adm"));
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_float_null/sum_float_null.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_float_null/sum_float_null.2.update.aql
new file mode 100644
index 0000000..d93253f
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_float_null/sum_float_null.2.update.aql
@@ -0,0 +1 @@
+// no inserts, deletes here
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_float_null/sum_float_null.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_float_null/sum_float_null.3.query.aql
new file mode 100644
index 0000000..7e6a126
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_float_null/sum_float_null.3.query.aql
@@ -0,0 +1,6 @@
+use dataverse test;
+
+sql-sum( 
+ for $x in dataset('Numeric') 
+ return $x.floatField
+)
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int16/sum_int16.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int16/sum_int16.1.ddl.aql
new file mode 100644
index 0000000..d330bc0
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int16/sum_int16.1.ddl.aql
@@ -0,0 +1,3 @@
+drop dataverse test if exists;
+
+create dataverse test;
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int16/sum_int16.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int16/sum_int16.2.update.aql
new file mode 100644
index 0000000..d93253f
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int16/sum_int16.2.update.aql
@@ -0,0 +1 @@
+// no inserts, deletes here
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int16/sum_int16.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int16/sum_int16.3.query.aql
new file mode 100644
index 0000000..d11671a
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int16/sum_int16.3.query.aql
@@ -0,0 +1,7 @@
+use dataverse test;
+
+sql-sum( 
+ for $x in [int16("1"), int16("2"), int16("3")] 
+ return $x
+)
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int16_null/sum_int16_null.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int16_null/sum_int16_null.1.ddl.aql
new file mode 100644
index 0000000..7cdcbea
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int16_null/sum_int16_null.1.ddl.aql
@@ -0,0 +1,20 @@
+drop dataverse test if exists;
+
+create dataverse test;
+
+use dataverse test;
+
+create type NumericType as open {
+  id: int32,
+  int8Field: int8?,
+  int16Field: int16?,
+  int32Field: int32?,
+  int64Field: int64?,
+  floatField: float?,
+  doubleField: double?
+}
+
+create external dataset Numeric(NumericType)
+using "edu.uci.ics.asterix.external.dataset.adapter.NCFileSystemAdapter"
+(("path"="nc1://data/nontagged/numericData.json"),("format"="adm"));
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int16_null/sum_int16_null.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int16_null/sum_int16_null.2.update.aql
new file mode 100644
index 0000000..d93253f
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int16_null/sum_int16_null.2.update.aql
@@ -0,0 +1 @@
+// no inserts, deletes here
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int16_null/sum_int16_null.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int16_null/sum_int16_null.3.query.aql
new file mode 100644
index 0000000..89f6773
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int16_null/sum_int16_null.3.query.aql
@@ -0,0 +1,6 @@
+use dataverse test;
+
+sql-sum( 
+ for $x in dataset('Numeric') 
+ return $x.int16Field
+)
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int32/sum_int32.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int32/sum_int32.1.ddl.aql
new file mode 100644
index 0000000..d330bc0
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int32/sum_int32.1.ddl.aql
@@ -0,0 +1,3 @@
+drop dataverse test if exists;
+
+create dataverse test;
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int32/sum_int32.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int32/sum_int32.2.update.aql
new file mode 100644
index 0000000..d93253f
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int32/sum_int32.2.update.aql
@@ -0,0 +1 @@
+// no inserts, deletes here
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int32/sum_int32.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int32/sum_int32.3.query.aql
new file mode 100644
index 0000000..e5f47cb
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int32/sum_int32.3.query.aql
@@ -0,0 +1,7 @@
+use dataverse test;
+
+sql-sum( 
+ for $x in [1, 2, int32("3")] 
+ return $x
+)
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int32_null/sum_int32_null.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int32_null/sum_int32_null.1.ddl.aql
new file mode 100644
index 0000000..7cdcbea
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int32_null/sum_int32_null.1.ddl.aql
@@ -0,0 +1,20 @@
+drop dataverse test if exists;
+
+create dataverse test;
+
+use dataverse test;
+
+create type NumericType as open {
+  id: int32,
+  int8Field: int8?,
+  int16Field: int16?,
+  int32Field: int32?,
+  int64Field: int64?,
+  floatField: float?,
+  doubleField: double?
+}
+
+create external dataset Numeric(NumericType)
+using "edu.uci.ics.asterix.external.dataset.adapter.NCFileSystemAdapter"
+(("path"="nc1://data/nontagged/numericData.json"),("format"="adm"));
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int32_null/sum_int32_null.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int32_null/sum_int32_null.2.update.aql
new file mode 100644
index 0000000..d93253f
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int32_null/sum_int32_null.2.update.aql
@@ -0,0 +1 @@
+// no inserts, deletes here
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int32_null/sum_int32_null.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int32_null/sum_int32_null.3.query.aql
new file mode 100644
index 0000000..521d291
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int32_null/sum_int32_null.3.query.aql
@@ -0,0 +1,6 @@
+use dataverse test;
+
+sql-sum( 
+ for $x in dataset('Numeric') 
+ return $x.int32Field
+)
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int64/sum_int64.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int64/sum_int64.1.ddl.aql
new file mode 100644
index 0000000..97b4670
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int64/sum_int64.1.ddl.aql
@@ -0,0 +1,4 @@
+drop dataverse test if exists;
+
+create dataverse test;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int64/sum_int64.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int64/sum_int64.2.update.aql
new file mode 100644
index 0000000..d93253f
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int64/sum_int64.2.update.aql
@@ -0,0 +1 @@
+// no inserts, deletes here
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int64/sum_int64.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int64/sum_int64.3.query.aql
new file mode 100644
index 0000000..03bda35
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int64/sum_int64.3.query.aql
@@ -0,0 +1,6 @@
+use dataverse test;
+
+sql-sum( 
+ for $x in [int64("1"), int64("2"), int64("3")] 
+ return $x
+)
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int64_null/sum_int64_null.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int64_null/sum_int64_null.1.ddl.aql
new file mode 100644
index 0000000..7cdcbea
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int64_null/sum_int64_null.1.ddl.aql
@@ -0,0 +1,20 @@
+drop dataverse test if exists;
+
+create dataverse test;
+
+use dataverse test;
+
+create type NumericType as open {
+  id: int32,
+  int8Field: int8?,
+  int16Field: int16?,
+  int32Field: int32?,
+  int64Field: int64?,
+  floatField: float?,
+  doubleField: double?
+}
+
+create external dataset Numeric(NumericType)
+using "edu.uci.ics.asterix.external.dataset.adapter.NCFileSystemAdapter"
+(("path"="nc1://data/nontagged/numericData.json"),("format"="adm"));
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int64_null/sum_int64_null.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int64_null/sum_int64_null.2.update.aql
new file mode 100644
index 0000000..d93253f
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int64_null/sum_int64_null.2.update.aql
@@ -0,0 +1 @@
+// no inserts, deletes here
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int64_null/sum_int64_null.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int64_null/sum_int64_null.3.query.aql
new file mode 100644
index 0000000..c266a22
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int64_null/sum_int64_null.3.query.aql
@@ -0,0 +1,6 @@
+use dataverse test;
+
+sql-sum( 
+ for $x in dataset('Numeric') 
+ return $x.int64Field
+)
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int8/sum_int8.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int8/sum_int8.1.ddl.aql
new file mode 100644
index 0000000..d330bc0
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int8/sum_int8.1.ddl.aql
@@ -0,0 +1,3 @@
+drop dataverse test if exists;
+
+create dataverse test;
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int8/sum_int8.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int8/sum_int8.2.update.aql
new file mode 100644
index 0000000..1ecf3aa
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int8/sum_int8.2.update.aql
@@ -0,0 +1 @@
+// no inserts, deletes
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int8/sum_int8.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int8/sum_int8.3.query.aql
new file mode 100644
index 0000000..a21c80c
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int8/sum_int8.3.query.aql
@@ -0,0 +1,7 @@
+use dataverse test;
+
+sql-sum( 
+ for $x in [int8("1"), int8("2"), int8("3")] 
+ return $x
+)
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int8_null/sum_int8_null.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int8_null/sum_int8_null.1.ddl.aql
new file mode 100644
index 0000000..7cdcbea
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int8_null/sum_int8_null.1.ddl.aql
@@ -0,0 +1,20 @@
+drop dataverse test if exists;
+
+create dataverse test;
+
+use dataverse test;
+
+create type NumericType as open {
+  id: int32,
+  int8Field: int8?,
+  int16Field: int16?,
+  int32Field: int32?,
+  int64Field: int64?,
+  floatField: float?,
+  doubleField: double?
+}
+
+create external dataset Numeric(NumericType)
+using "edu.uci.ics.asterix.external.dataset.adapter.NCFileSystemAdapter"
+(("path"="nc1://data/nontagged/numericData.json"),("format"="adm"));
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int8_null/sum_int8_null.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int8_null/sum_int8_null.2.update.aql
new file mode 100644
index 0000000..1ecf3aa
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int8_null/sum_int8_null.2.update.aql
@@ -0,0 +1 @@
+// no inserts, deletes
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int8_null/sum_int8_null.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int8_null/sum_int8_null.3.query.aql
new file mode 100644
index 0000000..bc962c3
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_int8_null/sum_int8_null.3.query.aql
@@ -0,0 +1,6 @@
+use dataverse test;
+
+sql-sum( 
+ for $x in dataset('Numeric') 
+ return $x.int8Field
+)
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_mixed/sum_mixed.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_mixed/sum_mixed.1.ddl.aql
new file mode 100644
index 0000000..c2325f0
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_mixed/sum_mixed.1.ddl.aql
@@ -0,0 +1,5 @@
+/*
+* Description  : Run sql-sum over an ordered list with mixed types
+* Expected Res : Failure
+* Date         : Jun 2nd 2013
+*/
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_mixed/sum_mixed.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_mixed/sum_mixed.2.update.aql
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_mixed/sum_mixed.2.update.aql
@@ -0,0 +1 @@
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_mixed/sum_mixed.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_mixed/sum_mixed.3.query.aql
new file mode 100644
index 0000000..73dd8f0
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_mixed/sum_mixed.3.query.aql
@@ -0,0 +1,11 @@
+/*
+* Description  : Run sql-sum over an ordered list with mixed types
+* Expected Res : Failure
+* Date         : Jun 2nd 2013
+*/
+
+sql-sum(
+ for $x in [float("2.0"), "hello world", 93847382783847382, date("2013-01-01")]
+ return $x
+)
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_null-with-pred/sum_null-with-pred.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_null-with-pred/sum_null-with-pred.1.ddl.aql
new file mode 100644
index 0000000..02237c9
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_null-with-pred/sum_null-with-pred.1.ddl.aql
@@ -0,0 +1,19 @@
+/*
+ * Description      :   sql-sum() aggregate function must return the numeric sql-sum, when non null values are given as input to sql-sum().
+ *                  :   Get the sql-sum for those tuples which are non null for salary fields.
+ * Expected result  :   Success
+ * Date             :   July 20th 2012
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
+use dataverse test;
+
+create type TestType as open {
+id:int32,
+sal:int32?
+}
+
+create dataset tdst(TestType) primary key id;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_null-with-pred/sum_null-with-pred.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_null-with-pred/sum_null-with-pred.2.update.aql
new file mode 100644
index 0000000..5fc1af1
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_null-with-pred/sum_null-with-pred.2.update.aql
@@ -0,0 +1,16 @@
+/*
+ * Description      :   sql-sum() aggregate function must return the numeric sql-sum, when non null values are given as input to sql-sum().
+ *                  :   Get the sql-sum for those tuples which are non null for salary fields.
+ * Expected result  :   Success
+ * Date             :   July 20th 2012
+ */
+
+use dataverse test;
+
+insert into dataset tdst({"id":123,"sal":1000});
+insert into dataset tdst({"id":113,"sal":2000});
+insert into dataset tdst({"id":163,"sal":3000});
+insert into dataset tdst({"id":161,"sal":4000});
+insert into dataset tdst({"id":173,"sal":5000});
+insert into dataset tdst({"id":183,"sal":null});
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_null-with-pred/sum_null-with-pred.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_null-with-pred/sum_null-with-pred.3.query.aql
new file mode 100644
index 0000000..8f15be1
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_null-with-pred/sum_null-with-pred.3.query.aql
@@ -0,0 +1,13 @@
+/*
+ * Description      :   sql-sum() aggregate function must return the numeric sql-sum, when non null values are given as input to sql-sum().
+ *                  :   Get the sql-sum for those tuples which are non null for salary fields.
+ * Expected result  :   Success
+ * Date             :   July 20th 2012
+ */
+
+use dataverse test;
+set import-private-functions 'true';
+
+sql-sum(for $l in dataset('tdst')
+where not(is-null($l.sal))
+return $l.sal)
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_numeric_null/sum_numeric_null.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_numeric_null/sum_numeric_null.1.ddl.aql
new file mode 100644
index 0000000..b54f6ab
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_numeric_null/sum_numeric_null.1.ddl.aql
@@ -0,0 +1,18 @@
+/*
+ * Description      :   Add numeric values with a null value, sql-sum() aggregate function must return null.
+ * Expected result  :   Success
+ * Date             :   July 20th 2012
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
+use dataverse test;
+
+create type TestType as open {
+id:int32,
+sal:int32?
+}
+
+create dataset tdst(TestType) primary key id;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_numeric_null/sum_numeric_null.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_numeric_null/sum_numeric_null.2.update.aql
new file mode 100644
index 0000000..1d47c20
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_numeric_null/sum_numeric_null.2.update.aql
@@ -0,0 +1,15 @@
+/*
+ * Description      :   Add numeric values with a null value, sql-sum() aggregate function must return null.
+ * Expected result  :   Success
+ * Date             :   July 20th 2012
+ */
+
+use dataverse test;
+
+insert into dataset tdst({"id":123,"sal":1000});
+insert into dataset tdst({"id":113,"sal":2000});
+insert into dataset tdst({"id":163,"sal":3000});
+insert into dataset tdst({"id":161,"sal":4000});
+insert into dataset tdst({"id":173,"sal":5000});
+insert into dataset tdst({"id":183,"sal":null});
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_numeric_null/sum_numeric_null.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_numeric_null/sum_numeric_null.3.query.aql
new file mode 100644
index 0000000..a632b16
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate-sql/sum_numeric_null/sum_numeric_null.3.query.aql
@@ -0,0 +1,13 @@
+/*
+ * Description      :   Add numeric values with a null value, sql-sum() aggregate function must return null.
+ * Expected result  :   Success
+ * Date             :   July 20th 2012
+ */
+
+use dataverse test;
+
+// In AQL
+// sql-sum(numeric + null) => null
+
+sql-sum(for $l in dataset('tdst')
+return $l.sal)
diff --git a/asterix-app/src/test/resources/runtimets/queries/aggregate/scalar_max_null/scalar_max_null.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/aggregate/scalar_max_null/scalar_max_null.3.query.aql
index b5708c9..c0d548f 100644
--- a/asterix-app/src/test/resources/runtimets/queries/aggregate/scalar_max_null/scalar_max_null.3.query.aql
+++ b/asterix-app/src/test/resources/runtimets/queries/aggregate/scalar_max_null/scalar_max_null.3.query.aql
@@ -12,6 +12,6 @@
 let $f := max([float("1"), float("2"), float("3"), null])
 let $d := max([double("1"), double("2"), double("3"), null])
 let $s := max(["foo", "bar", "world", null])
-let $dt := min([datetime("2012-03-01T00:00:00Z"), datetime("2012-01-01T00:00:00Z"), datetime("2012-02-01T00:00:00Z"), null])
+let $dt := max([datetime("2012-03-01T00:00:00Z"), datetime("2012-01-01T00:00:00Z"), datetime("2012-02-01T00:00:00Z"), null])
 for $i in [$i8, $i16, $i32, $i64, $f, $d, $s, $dt]
 return $i
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/agg_null/agg_null.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/agg_null/agg_null.1.adm
new file mode 100644
index 0000000..3ca4bc7
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/agg_null/agg_null.1.adm
@@ -0,0 +1 @@
+{ "sql-count1": 0i64, "average1": null, "sql-sum1": null, "sql-min1": null, "sql-max1": null, "sql-count2": 0i64, "average2": null, "sql-sum2": null, "sql-min2": null, "sql-max2": null }
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/agg_null_rec/agg_null_rec.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/agg_null_rec/agg_null_rec.1.adm
new file mode 100644
index 0000000..0f82337
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/agg_null_rec/agg_null_rec.1.adm
@@ -0,0 +1 @@
+{ "sql-count": 2i64, "average": 26.0d, "sql-sum": 52, "sql-min": 21, "sql-max": 31 }
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/agg_null_rec_1/agg_null_rec.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/agg_null_rec_1/agg_null_rec.1.adm
new file mode 100644
index 0000000..5897df3
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/agg_null_rec_1/agg_null_rec.1.adm
@@ -0,0 +1 @@
+{ "sql-count": 3i64, "average": 5.32d, "sql-sum": 15.96d, "sql-min": 473847i64, "sql-max": 38473827484738239i64 }
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/agg_number/agg_number.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/agg_number/agg_number.1.adm
new file mode 100644
index 0000000..b4a93b6
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/agg_number/agg_number.1.adm
@@ -0,0 +1 @@
+{ "sql-count1": 4i64, "sql-count2": 4i64, "average1": 2.3461845695961844E16d, "sql-sum1": 9.3847382783847376E16, "sql-min1": 1.0d, "sql-max1": 9.3847382783847376E16, "average2": 2.3461845695961844E16d, "sql-sum2": 9.3847382783847376E16, "sql-min2": 1.0d, "sql-max2": 9.3847382783847376E16 }
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/agg_number_rec/agg_number_rec.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/agg_number_rec/agg_number_rec.1.adm
new file mode 100644
index 0000000..5953969
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/agg_number_rec/agg_number_rec.1.adm
@@ -0,0 +1 @@
+{ "sql-count": 3i64, "average": 1.2824609161579424E16d, "sql-sum": 3.8473827484738272E16d, "sql-min": 2.0d, "sql-max": 3.847382748473824E16d }
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_double/avg_double.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_double/avg_double.1.adm
new file mode 100644
index 0000000..e64425e
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_double/avg_double.1.adm
@@ -0,0 +1 @@
+2.0d
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_double_null/avg_double_null.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_double_null/avg_double_null.1.adm
new file mode 100644
index 0000000..52032db
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_double_null/avg_double_null.1.adm
@@ -0,0 +1 @@
+{ "average": 64.0d }
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_empty_01/avg_empty_01.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_empty_01/avg_empty_01.1.adm
new file mode 100644
index 0000000..19765bd
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_empty_01/avg_empty_01.1.adm
@@ -0,0 +1 @@
+null
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_empty_02/avg_empty_02.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_empty_02/avg_empty_02.1.adm
new file mode 100644
index 0000000..19765bd
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_empty_02/avg_empty_02.1.adm
@@ -0,0 +1 @@
+null
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_float/avg_float.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_float/avg_float.1.adm
new file mode 100644
index 0000000..e64425e
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_float/avg_float.1.adm
@@ -0,0 +1 @@
+2.0d
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_float_null/avg_float_null.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_float_null/avg_float_null.1.adm
new file mode 100644
index 0000000..52032db
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_float_null/avg_float_null.1.adm
@@ -0,0 +1 @@
+{ "average": 64.0d }
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_int16/avg_int16.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_int16/avg_int16.1.adm
new file mode 100644
index 0000000..e64425e
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_int16/avg_int16.1.adm
@@ -0,0 +1 @@
+2.0d
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_int16_null/avg_int16_null.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_int16_null/avg_int16_null.1.adm
new file mode 100644
index 0000000..6d462be
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_int16_null/avg_int16_null.1.adm
@@ -0,0 +1 @@
+{ "average": -16.0d }
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_int32/avg_int32.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_int32/avg_int32.1.adm
new file mode 100644
index 0000000..e64425e
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_int32/avg_int32.1.adm
@@ -0,0 +1 @@
+2.0d
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_int32_null/avg_int32_null.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_int32_null/avg_int32_null.1.adm
new file mode 100644
index 0000000..584fc0c
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_int32_null/avg_int32_null.1.adm
@@ -0,0 +1 @@
+{ "average": -32.0d }
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_int64/avg_int64.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_int64/avg_int64.1.adm
new file mode 100644
index 0000000..e64425e
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_int64/avg_int64.1.adm
@@ -0,0 +1 @@
+2.0d
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_int64_null/avg_int64_null.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_int64_null/avg_int64_null.1.adm
new file mode 100644
index 0000000..3b54c9a
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_int64_null/avg_int64_null.1.adm
@@ -0,0 +1 @@
+{ "average": -64.0d }
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_int8/avg_int8.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_int8/avg_int8.1.adm
new file mode 100644
index 0000000..e64425e
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_int8/avg_int8.1.adm
@@ -0,0 +1 @@
+2.0d
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_int8_null/avg_int8_null.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_int8_null/avg_int8_null.1.adm
new file mode 100644
index 0000000..7d08439
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_int8_null/avg_int8_null.1.adm
@@ -0,0 +1 @@
+{ "average": 48.0d }
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_mixed/avg_mixed.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_mixed/avg_mixed.1.adm
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/avg_mixed/avg_mixed.1.adm
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/count_01/count_01.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/count_01/count_01.1.adm
new file mode 100644
index 0000000..deb6a26
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/count_01/count_01.1.adm
@@ -0,0 +1 @@
+3i64
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/count_empty_01/count_empty_01.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/count_empty_01/count_empty_01.1.adm
new file mode 100644
index 0000000..2dd16db
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/count_empty_01/count_empty_01.1.adm
@@ -0,0 +1 @@
+0i64
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/count_empty_02/count_empty_02.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/count_empty_02/count_empty_02.1.adm
new file mode 100644
index 0000000..2dd16db
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/count_empty_02/count_empty_02.1.adm
@@ -0,0 +1 @@
+0i64
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/count_null/count_null.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/count_null/count_null.1.adm
new file mode 100644
index 0000000..5b8b1d0
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/count_null/count_null.1.adm
@@ -0,0 +1 @@
+{ "sql-count": 1i64 }
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/issue395/issue395.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/issue395/issue395.1.adm
new file mode 100644
index 0000000..06e4a82
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/issue395/issue395.1.adm
@@ -0,0 +1 @@
+2i64
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/issue412_0/issue412_0.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/issue412_0/issue412_0.1.adm
new file mode 100644
index 0000000..06e4a82
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/issue412_0/issue412_0.1.adm
@@ -0,0 +1 @@
+2i64
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/issue412_1/issue412_1.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/issue412_1/issue412_1.1.adm
new file mode 100644
index 0000000..cd1dae2
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/issue412_1/issue412_1.1.adm
@@ -0,0 +1 @@
+{ "sql-count": 2i64, "average": 30.5d, "sql-sum": 61, "sql-min": 1, "sql-max": 60 }
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/issue425_min_hetero_list/issue425_min_hetero_list.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/issue425_min_hetero_list/issue425_min_hetero_list.1.adm
new file mode 100644
index 0000000..c874983
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/issue425_min_hetero_list/issue425_min_hetero_list.1.adm
@@ -0,0 +1 @@
+23i64
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/issue425_min_hetero_list_1/issue425_min_hetero_list_1.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/issue425_min_hetero_list_1/issue425_min_hetero_list_1.1.adm
new file mode 100644
index 0000000..697ccbb
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/issue425_min_hetero_list_1/issue425_min_hetero_list_1.1.adm
@@ -0,0 +1 @@
+0.5d
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/issue425_sum_hetero_list/issue425_sum_hetero_list.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/issue425_sum_hetero_list/issue425_sum_hetero_list.1.adm
new file mode 100644
index 0000000..9c65934
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/issue425_sum_hetero_list/issue425_sum_hetero_list.1.adm
@@ -0,0 +1 @@
+748374857506i64
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/issue425_sum_hetero_list_1/issue425_sum_hetero_list_1.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/issue425_sum_hetero_list_1/issue425_sum_hetero_list_1.1.adm
new file mode 100644
index 0000000..e26a893
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/issue425_sum_hetero_list_1/issue425_sum_hetero_list_1.1.adm
@@ -0,0 +1 @@
+748374857506.5d
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/issue531_string_min_max/issue531_string_min_max.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/issue531_string_min_max/issue531_string_min_max.1.adm
new file mode 100644
index 0000000..a01d30e
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/issue531_string_min_max/issue531_string_min_max.1.adm
@@ -0,0 +1 @@
+{ "sql-min": "Alex", "sql-max": "Susan" }
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/max_empty_01/max_empty_01.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/max_empty_01/max_empty_01.1.adm
new file mode 100644
index 0000000..19765bd
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/max_empty_01/max_empty_01.1.adm
@@ -0,0 +1 @@
+null
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/max_empty_02/max_empty_02.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/max_empty_02/max_empty_02.1.adm
new file mode 100644
index 0000000..19765bd
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/max_empty_02/max_empty_02.1.adm
@@ -0,0 +1 @@
+null
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/min_empty_01/min_empty_01.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/min_empty_01/min_empty_01.1.adm
new file mode 100644
index 0000000..19765bd
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/min_empty_01/min_empty_01.1.adm
@@ -0,0 +1 @@
+null
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/min_empty_02/min_empty_02.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/min_empty_02/min_empty_02.1.adm
new file mode 100644
index 0000000..19765bd
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/min_empty_02/min_empty_02.1.adm
@@ -0,0 +1 @@
+null
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/min_mixed/min_mixed.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/min_mixed/min_mixed.1.adm
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/min_mixed/min_mixed.1.adm
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/query-issue400/query-issue400.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/query-issue400/query-issue400.1.adm
new file mode 100644
index 0000000..06e4a82
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/query-issue400/query-issue400.1.adm
@@ -0,0 +1 @@
+2i64
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_avg/scalar_avg.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_avg/scalar_avg.1.adm
new file mode 100644
index 0000000..4d13c57
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_avg/scalar_avg.1.adm
@@ -0,0 +1,6 @@
+2.0
+2.0
+2.0
+2.0
+2.0
+2.0
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_avg_empty/scalar_avg_empty.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_avg_empty/scalar_avg_empty.1.adm
new file mode 100644
index 0000000..19765bd
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_avg_empty/scalar_avg_empty.1.adm
@@ -0,0 +1 @@
+null
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_avg_null/scalar_avg_null.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_avg_null/scalar_avg_null.1.adm
new file mode 100644
index 0000000..4d13c57
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_avg_null/scalar_avg_null.1.adm
@@ -0,0 +1,6 @@
+2.0
+2.0
+2.0
+2.0
+2.0
+2.0
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_count/scalar_count.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_count/scalar_count.1.adm
new file mode 100644
index 0000000..4378df9
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_count/scalar_count.1.adm
@@ -0,0 +1,7 @@
+3i64
+3i64
+3i64
+3i64
+3i64
+3i64
+3i64
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_count_empty/scalar_count_empty.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_count_empty/scalar_count_empty.1.adm
new file mode 100644
index 0000000..2dd16db
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_count_empty/scalar_count_empty.1.adm
@@ -0,0 +1 @@
+0i64
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_count_null/scalar_count_null.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_count_null/scalar_count_null.1.adm
new file mode 100644
index 0000000..4378df9
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_count_null/scalar_count_null.1.adm
@@ -0,0 +1,7 @@
+3i64
+3i64
+3i64
+3i64
+3i64
+3i64
+3i64
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_max/scalar_max.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_max/scalar_max.1.adm
new file mode 100644
index 0000000..3a0f763
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_max/scalar_max.1.adm
@@ -0,0 +1,8 @@
+3i8
+3i16
+3
+3i64
+3.0f
+3.0d
+"world"
+datetime("2012-03-01T00:00:00.000Z")
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_max_empty/scalar_max_empty.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_max_empty/scalar_max_empty.1.adm
new file mode 100644
index 0000000..19765bd
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_max_empty/scalar_max_empty.1.adm
@@ -0,0 +1 @@
+null
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_max_null/scalar_max_null.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_max_null/scalar_max_null.1.adm
new file mode 100644
index 0000000..3a0f763
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_max_null/scalar_max_null.1.adm
@@ -0,0 +1,8 @@
+3i8
+3i16
+3
+3i64
+3.0f
+3.0d
+"world"
+datetime("2012-03-01T00:00:00.000Z")
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_min/scalar_min.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_min/scalar_min.1.adm
new file mode 100644
index 0000000..e5749ff
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_min/scalar_min.1.adm
@@ -0,0 +1,8 @@
+1i8
+1i16
+1
+1i64
+1.0f
+1.0d
+"bar"
+datetime("2012-01-01T00:00:00.000Z")
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_min_empty/scalar_min_empty.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_min_empty/scalar_min_empty.1.adm
new file mode 100644
index 0000000..19765bd
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_min_empty/scalar_min_empty.1.adm
@@ -0,0 +1 @@
+null
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_min_null/scalar_min_null.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_min_null/scalar_min_null.1.adm
new file mode 100644
index 0000000..e5749ff
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_min_null/scalar_min_null.1.adm
@@ -0,0 +1,8 @@
+1i8
+1i16
+1
+1i64
+1.0f
+1.0d
+"bar"
+datetime("2012-01-01T00:00:00.000Z")
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_sum/scalar_sum.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_sum/scalar_sum.1.adm
new file mode 100644
index 0000000..819c752
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_sum/scalar_sum.1.adm
@@ -0,0 +1,6 @@
+6i8
+6i16
+6
+6i64
+6.0f
+6.0d
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_sum_empty/scalar_sum_empty.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_sum_empty/scalar_sum_empty.1.adm
new file mode 100644
index 0000000..19765bd
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_sum_empty/scalar_sum_empty.1.adm
@@ -0,0 +1 @@
+null
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_sum_null/scalar_sum_null.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_sum_null/scalar_sum_null.1.adm
new file mode 100644
index 0000000..819c752
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/scalar_sum_null/scalar_sum_null.1.adm
@@ -0,0 +1,6 @@
+6i8
+6i16
+6
+6i64
+6.0f
+6.0d
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_double/sum_double.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_double/sum_double.1.adm
new file mode 100644
index 0000000..617fd08
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_double/sum_double.1.adm
@@ -0,0 +1 @@
+6.0d
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_double_null/sum_double_null.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_double_null/sum_double_null.1.adm
new file mode 100644
index 0000000..35dcd47
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_double_null/sum_double_null.1.adm
@@ -0,0 +1 @@
+64.0d
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_empty_01/sum_empty_01.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_empty_01/sum_empty_01.1.adm
new file mode 100644
index 0000000..19765bd
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_empty_01/sum_empty_01.1.adm
@@ -0,0 +1 @@
+null
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_empty_02/sum_empty_02.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_empty_02/sum_empty_02.1.adm
new file mode 100644
index 0000000..19765bd
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_empty_02/sum_empty_02.1.adm
@@ -0,0 +1 @@
+null
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_float/sum_float.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_float/sum_float.1.adm
new file mode 100644
index 0000000..d840134
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_float/sum_float.1.adm
@@ -0,0 +1 @@
+6.0f
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_float_null/sum_float_null.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_float_null/sum_float_null.1.adm
new file mode 100644
index 0000000..29e6891
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_float_null/sum_float_null.1.adm
@@ -0,0 +1 @@
+64.0f
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_int16/sum_int16.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_int16/sum_int16.1.adm
new file mode 100644
index 0000000..fa2ec89
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_int16/sum_int16.1.adm
@@ -0,0 +1 @@
+6i16
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_int16_null/sum_int16_null.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_int16_null/sum_int16_null.1.adm
new file mode 100644
index 0000000..1f13ece
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_int16_null/sum_int16_null.1.adm
@@ -0,0 +1 @@
+-16i16
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_int32/sum_int32.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_int32/sum_int32.1.adm
new file mode 100644
index 0000000..1e8b314
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_int32/sum_int32.1.adm
@@ -0,0 +1 @@
+6
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_int32_null/sum_int32_null.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_int32_null/sum_int32_null.1.adm
new file mode 100644
index 0000000..5ee602a
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_int32_null/sum_int32_null.1.adm
@@ -0,0 +1 @@
+-32
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_int64/sum_int64.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_int64/sum_int64.1.adm
new file mode 100644
index 0000000..1d21ae2
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_int64/sum_int64.1.adm
@@ -0,0 +1 @@
+6i64
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_int64_null/sum_int64_null.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_int64_null/sum_int64_null.1.adm
new file mode 100644
index 0000000..df81d5e
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_int64_null/sum_int64_null.1.adm
@@ -0,0 +1 @@
+-64i64
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_int8/sum_int8.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_int8/sum_int8.1.adm
new file mode 100644
index 0000000..7f3e31c
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_int8/sum_int8.1.adm
@@ -0,0 +1 @@
+6i8
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_int8_null/sum_int8_null.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_int8_null/sum_int8_null.1.adm
new file mode 100644
index 0000000..a0b5709
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_int8_null/sum_int8_null.1.adm
@@ -0,0 +1 @@
+48i8
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_mixed/sum_mixed.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_mixed/sum_mixed.1.adm
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_mixed/sum_mixed.1.adm
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_null-with-pred/sum_null-with-pred.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_null-with-pred/sum_null-with-pred.1.adm
new file mode 100644
index 0000000..9e70369
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_null-with-pred/sum_null-with-pred.1.adm
@@ -0,0 +1 @@
+15000
diff --git a/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_numeric_null/sum_numeric_null.1.adm b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_numeric_null/sum_numeric_null.1.adm
new file mode 100644
index 0000000..f0cc45c
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/aggregate-sql/sum_numeric_null/sum_numeric_null.1.adm
@@ -0,0 +1 @@
+15000
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/runtimets/testsuite.xml b/asterix-app/src/test/resources/runtimets/testsuite.xml
index 615ae17..9cdc3df 100644
--- a/asterix-app/src/test/resources/runtimets/testsuite.xml
+++ b/asterix-app/src/test/resources/runtimets/testsuite.xml
@@ -491,6 +491,361 @@
       </compilation-unit>
     </test-case>
   </test-group>
+  <test-group name="aggregate-sql">
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="issue531_string_min_max">
+        <output-dir compare="Text">issue531_string_min_max</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="agg_null">
+        <output-dir compare="Text">agg_null</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="agg_null_rec">
+        <output-dir compare="Text">agg_null_rec</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="agg_null_rec_1">
+        <output-dir compare="Text">agg_null_rec_1</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="agg_number_rec">
+        <output-dir compare="Text">agg_number_rec</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="avg_mixed">
+        <output-dir compare="Text">avg_mixed</output-dir>
+        <expected-error>edu.uci.ics.asterix.common.exceptions.AsterixException</expected-error>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="sum_mixed">
+        <output-dir compare="Text">sum_mixed</output-dir>
+        <expected-error>edu.uci.ics.asterix.common.exceptions.AsterixException</expected-error>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="min_mixed">
+        <output-dir compare="Text">min_mixed</output-dir>
+        <expected-error>edu.uci.ics.asterix.common.exceptions.AsterixException</expected-error>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="agg_number">
+        <output-dir compare="Text">agg_number</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="issue425_min_hetero_list_1">
+        <output-dir compare="Text">issue425_min_hetero_list_1</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="issue425_min_hetero_list">
+        <output-dir compare="Text">issue425_min_hetero_list</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="issue425_sum_hetero_list_1">
+        <output-dir compare="Text">issue425_sum_hetero_list_1</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="issue425_sum_hetero_list">
+        <output-dir compare="Text">issue425_sum_hetero_list</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="query-issue400">
+        <output-dir compare="Text">query-issue400</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="issue395">
+        <output-dir compare="Text">issue395</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="issue412_0">
+        <output-dir compare="Text">issue412_0</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="issue412_1">
+        <output-dir compare="Text">issue412_1</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="avg_double">
+        <output-dir compare="Text">avg_double</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="avg_double_null">
+        <output-dir compare="Text">avg_double_null</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="avg_empty_01">
+        <output-dir compare="Text">avg_empty_01</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="avg_empty_02">
+        <output-dir compare="Text">avg_empty_02</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="avg_float">
+        <output-dir compare="Text">avg_float</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="avg_float_null">
+        <output-dir compare="Text">avg_float_null</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="avg_int16">
+        <output-dir compare="Text">avg_int16</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="avg_int16_null">
+        <output-dir compare="Text">avg_int16_null</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="avg_int32">
+        <output-dir compare="Text">avg_int32</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="avg_int32_null">
+        <output-dir compare="Text">avg_int32_null</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="avg_int64">
+        <output-dir compare="Text">avg_int64</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="avg_int64_null">
+        <output-dir compare="Text">avg_int64_null</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="avg_int8">
+        <output-dir compare="Text">avg_int8</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="avg_int8_null">
+        <output-dir compare="Text">avg_int8_null</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="count_01">
+        <output-dir compare="Text">count_01</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="count_empty_01">
+        <output-dir compare="Text">count_empty_01</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="count_empty_02">
+        <output-dir compare="Text">count_empty_02</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="count_null">
+        <output-dir compare="Text">count_null</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="max_empty_01">
+        <output-dir compare="Text">max_empty_01</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="max_empty_02">
+        <output-dir compare="Text">max_empty_02</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="min_empty_01">
+        <output-dir compare="Text">min_empty_01</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="min_empty_02">
+        <output-dir compare="Text">min_empty_02</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="scalar_avg">
+        <output-dir compare="Text">scalar_avg</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="scalar_avg_empty">
+        <output-dir compare="Text">scalar_avg_empty</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="scalar_avg_null">
+        <output-dir compare="Text">scalar_avg_null</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="scalar_count">
+        <output-dir compare="Text">scalar_count</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="scalar_count_empty">
+        <output-dir compare="Text">scalar_count_empty</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="scalar_count_null">
+        <output-dir compare="Text">scalar_count_null</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="scalar_max">
+        <output-dir compare="Text">scalar_max</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="scalar_max_empty">
+        <output-dir compare="Text">scalar_max_empty</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="scalar_max_null">
+        <output-dir compare="Text">scalar_max_null</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="scalar_min">
+        <output-dir compare="Text">scalar_min</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="scalar_min_empty">
+        <output-dir compare="Text">scalar_min_empty</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="scalar_min_null">
+        <output-dir compare="Text">scalar_min_null</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="scalar_sum">
+        <output-dir compare="Text">scalar_sum</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="scalar_sum_empty">
+        <output-dir compare="Text">scalar_sum_empty</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="scalar_sum_null">
+        <output-dir compare="Text">scalar_sum_null</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="sum_double">
+        <output-dir compare="Text">sum_double</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="sum_double_null">
+        <output-dir compare="Text">sum_double_null</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="sum_empty_01">
+        <output-dir compare="Text">sum_empty_01</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="sum_empty_02">
+        <output-dir compare="Text">sum_empty_02</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="sum_float">
+        <output-dir compare="Text">sum_float</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="sum_float_null">
+        <output-dir compare="Text">sum_float_null</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="sum_int16">
+        <output-dir compare="Text">sum_int16</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="sum_int16_null">
+        <output-dir compare="Text">sum_int16_null</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="sum_int32">
+        <output-dir compare="Text">sum_int32</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="sum_int32_null">
+        <output-dir compare="Text">sum_int32_null</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="sum_int64">
+        <output-dir compare="Text">sum_int64</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="sum_int64_null">
+        <output-dir compare="Text">sum_int64_null</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="sum_int8">
+        <output-dir compare="Text">sum_int8</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="sum_int8_null">
+        <output-dir compare="Text">sum_int8_null</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="sum_null-with-pred">
+        <output-dir compare="Text">sum_null-with-pred</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="aggregate-sql">
+      <compilation-unit name="sum_numeric_null">
+        <output-dir compare="Text">sum_numeric_null</output-dir>
+      </compilation-unit>
+    </test-case>
+  </test-group>
   <test-group name="boolean">
     <test-case FilePath="boolean">
       <compilation-unit name="and_01">
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 299bbfb..8f0bab3 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
@@ -304,6 +304,57 @@
     public final static FunctionIdentifier SERIAL_LOCAL_AVG = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
             "local-avg-serial", 1);
 
+    // sql aggregate functions
+    public final static FunctionIdentifier SQL_AVG = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "agg-sql-avg", 1);
+    public final static FunctionIdentifier SQL_COUNT = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "agg-sql-count", 1);
+    public final static FunctionIdentifier SQL_SUM = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "agg-sql-sum", 1);
+    public final static FunctionIdentifier LOCAL_SQL_SUM = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "agg-local-sql-sum", 1);
+    public final static FunctionIdentifier SQL_MAX = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "agg-sql-max", 1);
+    public final static FunctionIdentifier LOCAL_SQL_MAX = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "agg-local-sql-max", 1);
+    public final static FunctionIdentifier SQL_MIN = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "agg-sql-min", 1);
+    public final static FunctionIdentifier LOCAL_SQL_MIN = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "agg-local-sql-min", 1);
+    public final static FunctionIdentifier GLOBAL_SQL_AVG = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "agg-global-sql-avg", 1);
+    public final static FunctionIdentifier LOCAL_SQL_AVG = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "agg-local-sql-avg", 1);
+
+    public final static FunctionIdentifier SCALAR_SQL_AVG = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "sql-avg", 1);
+    public final static FunctionIdentifier SCALAR_SQL_COUNT = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "sql-count", 1);
+    public final static FunctionIdentifier SCALAR_SQL_SUM = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "sql-sum", 1);
+    public final static FunctionIdentifier SCALAR_SQL_MAX = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "sql-max", 1);
+    public final static FunctionIdentifier SCALAR_SQL_MIN = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "sql-min", 1);
+    public final static FunctionIdentifier SCALAR_GLOBAL_SQL_AVG = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "global-sql-avg", 1);
+    public final static FunctionIdentifier SCALAR_LOCAL_SQL_AVG = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "local-sql-avg", 1);
+
+    // serializable sql aggregate functions
+    public final static FunctionIdentifier SERIAL_SQL_AVG = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "sql-avg-serial", 1);
+    public final static FunctionIdentifier SERIAL_SQL_COUNT = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "sql-count-serial", 1);
+    public final static FunctionIdentifier SERIAL_SQL_SUM = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "sql-sum-serial", 1);
+    public final static FunctionIdentifier SERIAL_LOCAL_SQL_SUM = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "local-sql-sum-serial", 1);
+    public final static FunctionIdentifier SERIAL_GLOBAL_SQL_AVG = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "global-sql-avg-serial", 1);
+    public final static FunctionIdentifier SERIAL_LOCAL_SQL_AVG = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "local-sql-avg-serial", 1);
+
     public final static FunctionIdentifier SCAN_COLLECTION = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
             "scan-collection", 1);
     public final static FunctionIdentifier SUBSET_COLLECTION = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
@@ -739,6 +790,29 @@
         addFunction(RANGE, AInt32TypeComputer.INSTANCE, true);
         addFunction(RECTANGLE_CONSTRUCTOR, OptionalARectangleTypeComputer.INSTANCE, true);
 
+        // SQL Aggregate Functions
+        addFunction(SQL_AVG, OptionalADoubleTypeComputer.INSTANCE, true);
+        addFunction(SQL_COUNT, AInt64TypeComputer.INSTANCE, true);
+        addFunction(SQL_MAX, NonTaggedMinMaxAggTypeComputer.INSTANCE, true);
+        addPrivateFunction(LOCAL_SQL_MAX, NonTaggedMinMaxAggTypeComputer.INSTANCE, true);
+        addFunction(SQL_MIN, NonTaggedMinMaxAggTypeComputer.INSTANCE, true);
+        addPrivateFunction(LOCAL_SQL_MIN, NonTaggedMinMaxAggTypeComputer.INSTANCE, true);
+        addFunction(SQL_SUM, NonTaggedNumericAggTypeComputer.INSTANCE, true);
+        addPrivateFunction(LOCAL_SQL_SUM, NonTaggedNumericAggTypeComputer.INSTANCE, true);
+        addFunction(SCALAR_SQL_AVG, ScalarVersionOfAggregateResultType.INSTANCE, true);
+        addFunction(SCALAR_SQL_COUNT, AInt64TypeComputer.INSTANCE, true);
+        addPrivateFunction(SCALAR_GLOBAL_SQL_AVG, ScalarVersionOfAggregateResultType.INSTANCE, true);
+        addPrivateFunction(SCALAR_LOCAL_SQL_AVG, ScalarVersionOfAggregateResultType.INSTANCE, true);
+        addFunction(SCALAR_SQL_MAX, ScalarVersionOfAggregateResultType.INSTANCE, true);
+        addFunction(SCALAR_SQL_MIN, ScalarVersionOfAggregateResultType.INSTANCE, true);
+        addFunction(SCALAR_SQL_SUM, ScalarVersionOfAggregateResultType.INSTANCE, true);
+        addPrivateFunction(SERIAL_SQL_AVG, OptionalADoubleTypeComputer.INSTANCE, true);
+        addPrivateFunction(SERIAL_SQL_COUNT, AInt64TypeComputer.INSTANCE, true);
+        addPrivateFunction(SERIAL_GLOBAL_SQL_AVG, OptionalADoubleTypeComputer.INSTANCE, true);
+        addPrivateFunction(SERIAL_LOCAL_SQL_AVG, NonTaggedLocalAvgTypeComputer.INSTANCE, true);
+        addPrivateFunction(SERIAL_SQL_SUM, NonTaggedNumericAggTypeComputer.INSTANCE, true);
+        addPrivateFunction(SERIAL_LOCAL_SQL_SUM, NonTaggedNumericAggTypeComputer.INSTANCE, true);
+
         addFunction(SCALAR_AVG, ScalarVersionOfAggregateResultType.INSTANCE, true);
         addFunction(SCALAR_COUNT, AInt64TypeComputer.INSTANCE, true);
         addPrivateFunction(SCALAR_GLOBAL_AVG, ScalarVersionOfAggregateResultType.INSTANCE, true);
@@ -913,6 +987,16 @@
         scalarToAggregateFunctionMap.put(getAsterixFunctionInfo(SCALAR_MAX), getAsterixFunctionInfo(MAX));
         scalarToAggregateFunctionMap.put(getAsterixFunctionInfo(SCALAR_MIN), getAsterixFunctionInfo(MIN));
         scalarToAggregateFunctionMap.put(getAsterixFunctionInfo(SCALAR_SUM), getAsterixFunctionInfo(SUM));
+        // SQL Aggregate Functions
+        scalarToAggregateFunctionMap.put(getAsterixFunctionInfo(SCALAR_SQL_AVG), getAsterixFunctionInfo(SQL_AVG));
+        scalarToAggregateFunctionMap.put(getAsterixFunctionInfo(SCALAR_SQL_COUNT), getAsterixFunctionInfo(SQL_COUNT));
+        scalarToAggregateFunctionMap.put(getAsterixFunctionInfo(SCALAR_GLOBAL_SQL_AVG),
+                getAsterixFunctionInfo(GLOBAL_SQL_AVG));
+        scalarToAggregateFunctionMap.put(getAsterixFunctionInfo(SCALAR_LOCAL_SQL_AVG),
+                getAsterixFunctionInfo(LOCAL_SQL_AVG));
+        scalarToAggregateFunctionMap.put(getAsterixFunctionInfo(SCALAR_SQL_MAX), getAsterixFunctionInfo(SQL_MAX));
+        scalarToAggregateFunctionMap.put(getAsterixFunctionInfo(SCALAR_SQL_MIN), getAsterixFunctionInfo(SQL_MIN));
+        scalarToAggregateFunctionMap.put(getAsterixFunctionInfo(SCALAR_SQL_SUM), getAsterixFunctionInfo(SQL_SUM));
     }
 
     static {
@@ -964,6 +1048,55 @@
         addAgg(SERIAL_LOCAL_SUM);
         addLocalAgg(SERIAL_SUM, SERIAL_LOCAL_SUM);
         addGlobalAgg(SERIAL_SUM, SERIAL_SUM);
+
+        // SQL Aggregate Functions
+        addAgg(SQL_AVG);
+        addAgg(LOCAL_SQL_AVG);
+        addAgg(GLOBAL_SQL_AVG);
+        addLocalAgg(SQL_AVG, LOCAL_SQL_AVG);
+        addGlobalAgg(SQL_AVG, GLOBAL_SQL_AVG);
+
+        addAgg(SQL_COUNT);
+        addLocalAgg(SQL_COUNT, SQL_COUNT);
+        addGlobalAgg(SQL_COUNT, SQL_SUM);
+
+        addAgg(SQL_MAX);
+        addAgg(LOCAL_SQL_MAX);
+        addLocalAgg(SQL_MAX, LOCAL_SQL_MAX);
+        addGlobalAgg(SQL_MAX, SQL_MAX);
+
+        addAgg(SQL_MIN);
+        addLocalAgg(SQL_MIN, LOCAL_SQL_MIN);
+        addGlobalAgg(SQL_MIN, SQL_MIN);
+
+        addAgg(SQL_SUM);
+        addAgg(LOCAL_SQL_SUM);
+        addLocalAgg(SQL_SUM, LOCAL_SQL_SUM);
+        addGlobalAgg(SQL_SUM, SQL_SUM);
+
+        // SQL serializable aggregate functions
+        addSerialAgg(SQL_AVG, SERIAL_SQL_AVG);
+        addSerialAgg(SQL_COUNT, SERIAL_SQL_COUNT);
+        addSerialAgg(SQL_SUM, SERIAL_SQL_SUM);
+        addSerialAgg(LOCAL_SQL_SUM, SERIAL_LOCAL_SQL_SUM);
+        addSerialAgg(LOCAL_SQL_AVG, SERIAL_LOCAL_SQL_AVG);
+        addSerialAgg(GLOBAL_SQL_AVG, SERIAL_GLOBAL_SQL_AVG);
+
+        addAgg(SERIAL_SQL_COUNT);
+        addLocalAgg(SERIAL_SQL_COUNT, SERIAL_SQL_COUNT);
+        addGlobalAgg(SERIAL_SQL_COUNT, SERIAL_SQL_SUM);
+
+        addAgg(SERIAL_SQL_AVG);
+        addAgg(SERIAL_LOCAL_SQL_AVG);
+        addAgg(SERIAL_GLOBAL_SQL_AVG);
+        addLocalAgg(SERIAL_SQL_AVG, SERIAL_LOCAL_SQL_AVG);
+        addGlobalAgg(SERIAL_SQL_AVG, SERIAL_GLOBAL_SQL_AVG);
+
+        addAgg(SERIAL_SQL_SUM);
+        addAgg(SERIAL_LOCAL_SQL_SUM);
+        addLocalAgg(SERIAL_SQL_SUM, SERIAL_LOCAL_SQL_SUM);
+        addGlobalAgg(SERIAL_SQL_SUM, SERIAL_SQL_SUM);
+
     }
 
     static {
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/scalar/ScalarSqlAvgAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/scalar/ScalarSqlAvgAggregateDescriptor.java
new file mode 100644
index 0000000..241ee46
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/scalar/ScalarSqlAvgAggregateDescriptor.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2009-2013 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.aggregates.scalar;
+
+import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
+import edu.uci.ics.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+
+public class ScalarSqlAvgAggregateDescriptor extends AbstractScalarAggregateDescriptor {
+
+    private static final long serialVersionUID = 1L;
+    public final static FunctionIdentifier FID = AsterixBuiltinFunctions.SCALAR_SQL_AVG;
+    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new ScalarSqlAvgAggregateDescriptor();
+        }
+    };
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return FID;
+    }
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/scalar/ScalarSqlCountAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/scalar/ScalarSqlCountAggregateDescriptor.java
new file mode 100644
index 0000000..1b581e4
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/scalar/ScalarSqlCountAggregateDescriptor.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2009-2013 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.aggregates.scalar;
+
+import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
+import edu.uci.ics.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+
+public class ScalarSqlCountAggregateDescriptor extends AbstractScalarAggregateDescriptor {
+
+    private static final long serialVersionUID = 1L;
+    public final static FunctionIdentifier FID = AsterixBuiltinFunctions.SCALAR_SQL_COUNT;
+    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new ScalarSqlCountAggregateDescriptor();
+        }
+    };
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return FID;
+    }
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/scalar/ScalarSqlMaxAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/scalar/ScalarSqlMaxAggregateDescriptor.java
new file mode 100644
index 0000000..f58d578
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/scalar/ScalarSqlMaxAggregateDescriptor.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2009-2013 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.aggregates.scalar;
+
+import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
+import edu.uci.ics.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+
+public class ScalarSqlMaxAggregateDescriptor extends AbstractScalarAggregateDescriptor {
+
+    private static final long serialVersionUID = 1L;
+    public final static FunctionIdentifier FID = AsterixBuiltinFunctions.SCALAR_SQL_MAX;
+    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new ScalarSqlMaxAggregateDescriptor();
+        }
+    };
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return FID;
+    }
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/scalar/ScalarSqlMinAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/scalar/ScalarSqlMinAggregateDescriptor.java
new file mode 100644
index 0000000..da6e38d
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/scalar/ScalarSqlMinAggregateDescriptor.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2009-2013 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.aggregates.scalar;
+
+import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
+import edu.uci.ics.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+
+public class ScalarSqlMinAggregateDescriptor extends AbstractScalarAggregateDescriptor {
+
+    private static final long serialVersionUID = 1L;
+    public final static FunctionIdentifier FID = AsterixBuiltinFunctions.SCALAR_SQL_MIN;
+    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new ScalarSqlMinAggregateDescriptor();
+        }
+    };
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return FID;
+    }
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/scalar/ScalarSqlSumAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/scalar/ScalarSqlSumAggregateDescriptor.java
new file mode 100644
index 0000000..14aa6b7
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/scalar/ScalarSqlSumAggregateDescriptor.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2009-2013 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.aggregates.scalar;
+
+import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
+import edu.uci.ics.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+
+public class ScalarSqlSumAggregateDescriptor extends AbstractScalarAggregateDescriptor {
+
+    private static final long serialVersionUID = 1L;
+    public final static FunctionIdentifier FID = AsterixBuiltinFunctions.SCALAR_SQL_SUM;
+    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new ScalarSqlSumAggregateDescriptor();
+        }
+    };
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return FID;
+    }
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/AbstractSerializableAvgAggregateFunction.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/AbstractSerializableAvgAggregateFunction.java
new file mode 100644
index 0000000..4d804ee
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/AbstractSerializableAvgAggregateFunction.java
@@ -0,0 +1,276 @@
+/*
+ * Copyright 2009-2013 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.aggregates.serializable.std;
+
+import java.io.DataOutput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import edu.uci.ics.asterix.common.config.GlobalConfig;
+import edu.uci.ics.asterix.common.exceptions.AsterixException;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.ADoubleSerializerDeserializer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AFloatSerializerDeserializer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt16SerializerDeserializer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt32SerializerDeserializer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt64SerializerDeserializer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt8SerializerDeserializer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.ARecordSerializerDeserializer;
+import edu.uci.ics.asterix.formats.nontagged.AqlSerializerDeserializerProvider;
+import edu.uci.ics.asterix.om.base.ADouble;
+import edu.uci.ics.asterix.om.base.AInt64;
+import edu.uci.ics.asterix.om.base.AMutableDouble;
+import edu.uci.ics.asterix.om.base.AMutableInt64;
+import edu.uci.ics.asterix.om.base.ANull;
+import edu.uci.ics.asterix.om.types.ARecordType;
+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.types.IAType;
+import edu.uci.ics.asterix.om.types.hierachy.ATypeHierarchy;
+import edu.uci.ics.asterix.runtime.evaluators.common.AccessibleByteArrayEval;
+import edu.uci.ics.asterix.runtime.evaluators.common.ClosedRecordConstructorEvalFactory.ClosedRecordConstructorEval;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.NotImplementedException;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluator;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopySerializableAggregateFunction;
+import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
+import edu.uci.ics.hyracks.data.std.util.ArrayBackedValueStorage;
+import edu.uci.ics.hyracks.data.std.util.ByteArrayAccessibleOutputStream;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+
+public abstract class AbstractSerializableAvgAggregateFunction implements ICopySerializableAggregateFunction {
+    private static final int SUM_FIELD_ID = 0;
+    private static final int COUNT_FIELD_ID = 1;
+
+    private static final int SUM_OFFSET = 0;
+    private static final int COUNT_OFFSET = 8;
+    protected static final int AGG_TYPE_OFFSET = 16;
+
+    private ArrayBackedValueStorage inputVal = new ArrayBackedValueStorage();
+    private ICopyEvaluator eval;
+    private AMutableDouble aDouble = new AMutableDouble(0);
+    private AMutableInt64 aInt64 = new AMutableInt64(0);
+
+    private ArrayBackedValueStorage avgBytes = new ArrayBackedValueStorage();
+    private ByteArrayAccessibleOutputStream sumBytes = new ByteArrayAccessibleOutputStream();
+    private DataOutput sumBytesOutput = new DataOutputStream(sumBytes);
+    private ByteArrayAccessibleOutputStream countBytes = new ByteArrayAccessibleOutputStream();
+    private DataOutput countBytesOutput = new DataOutputStream(countBytes);
+    private ICopyEvaluator evalSum = new AccessibleByteArrayEval(avgBytes.getDataOutput(), sumBytes);
+    private ICopyEvaluator evalCount = new AccessibleByteArrayEval(avgBytes.getDataOutput(), countBytes);
+    private ClosedRecordConstructorEval recordEval;
+
+    @SuppressWarnings("unchecked")
+    private ISerializerDeserializer<ADouble> doubleSerde = AqlSerializerDeserializerProvider.INSTANCE
+            .getSerializerDeserializer(BuiltinType.ADOUBLE);
+    @SuppressWarnings("unchecked")
+    private ISerializerDeserializer<AInt64> longSerde = AqlSerializerDeserializerProvider.INSTANCE
+            .getSerializerDeserializer(BuiltinType.AINT64);
+    @SuppressWarnings("unchecked")
+    private ISerializerDeserializer<ANull> nullSerde = AqlSerializerDeserializerProvider.INSTANCE
+            .getSerializerDeserializer(BuiltinType.ANULL);
+
+    public AbstractSerializableAvgAggregateFunction(ICopyEvaluatorFactory[] args) throws AlgebricksException {
+        eval = args[0].createEvaluator(inputVal);
+    }
+
+    @Override
+    public void init(DataOutput state) throws AlgebricksException {
+        try {
+            state.writeDouble(0.0);
+            state.writeLong(0);
+            state.writeByte(ATypeTag.SYSTEM_NULL.serialize());
+        } catch (IOException e) {
+            throw new AlgebricksException(e);
+        }
+    }
+
+    public abstract void step(IFrameTupleReference tuple, byte[] state, int start, int len) throws AlgebricksException;
+
+    public abstract void finish(byte[] state, int start, int len, DataOutput result) throws AlgebricksException;
+
+    public abstract void finishPartial(byte[] state, int start, int len, DataOutput result) throws AlgebricksException;
+
+    protected abstract void processNull(byte[] state, int start);
+
+    protected void processDataValues(IFrameTupleReference tuple, byte[] state, int start, int len)
+            throws AlgebricksException {
+        if (skipStep(state, start)) {
+            return;
+        }
+        inputVal.reset();
+        eval.evaluate(tuple);
+        double sum = BufferSerDeUtil.getDouble(state, start + SUM_OFFSET);
+        long count = BufferSerDeUtil.getLong(state, start + COUNT_OFFSET);
+        ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(inputVal.getByteArray()[0]);
+        ATypeTag aggType = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(state[start + AGG_TYPE_OFFSET]);
+        if (typeTag == ATypeTag.NULL) {
+            processNull(state, start);
+            return;
+        } else if (aggType == ATypeTag.SYSTEM_NULL) {
+            aggType = typeTag;
+        } else if (typeTag != ATypeTag.SYSTEM_NULL && !ATypeHierarchy.isCompatible(typeTag, aggType)) {
+            throw new AlgebricksException("Unexpected type " + typeTag + " in aggregation input stream. Expected type "
+                    + aggType + ".");
+        } else if (ATypeHierarchy.canPromote(aggType, typeTag)) {
+            aggType = typeTag;
+        }
+        ++count;
+        switch (typeTag) {
+            case INT8: {
+                byte val = AInt8SerializerDeserializer.getByte(inputVal.getByteArray(), 1);
+                sum += val;
+                break;
+            }
+            case INT16: {
+                short val = AInt16SerializerDeserializer.getShort(inputVal.getByteArray(), 1);
+                sum += val;
+                break;
+            }
+            case INT32: {
+                int val = AInt32SerializerDeserializer.getInt(inputVal.getByteArray(), 1);
+                sum += val;
+                break;
+            }
+            case INT64: {
+                long val = AInt64SerializerDeserializer.getLong(inputVal.getByteArray(), 1);
+                sum += val;
+                break;
+            }
+            case FLOAT: {
+                float val = AFloatSerializerDeserializer.getFloat(inputVal.getByteArray(), 1);
+                sum += val;
+                break;
+            }
+            case DOUBLE: {
+                double val = ADoubleSerializerDeserializer.getDouble(inputVal.getByteArray(), 1);
+                sum += val;
+                break;
+            }
+            default: {
+                throw new NotImplementedException("Cannot compute AVG for values of type " + typeTag);
+            }
+        }
+        inputVal.reset();
+        BufferSerDeUtil.writeDouble(sum, state, start + SUM_OFFSET);
+        BufferSerDeUtil.writeLong(count, state, start + COUNT_OFFSET);
+        state[start + AGG_TYPE_OFFSET] = aggType.serialize();
+    }
+
+    protected void finishPartialResults(byte[] state, int start, int len, DataOutput result) throws AlgebricksException {
+        double sum = BufferSerDeUtil.getDouble(state, start + SUM_OFFSET);
+        long count = BufferSerDeUtil.getLong(state, start + COUNT_OFFSET);
+        ATypeTag aggType = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(state[start + AGG_TYPE_OFFSET]);
+        if (recordEval == null) {
+            ARecordType recType;
+            try {
+                recType = new ARecordType(null, new String[] { "sum", "count" }, new IAType[] { BuiltinType.ADOUBLE,
+                        BuiltinType.AINT64 }, false);
+            } catch (AsterixException e) {
+                throw new AlgebricksException(e);
+            }
+            recordEval = new ClosedRecordConstructorEval(recType, new ICopyEvaluator[] { evalSum, evalCount },
+                    avgBytes, result);
+        }
+
+        try {
+            if (aggType == ATypeTag.SYSTEM_NULL) {
+                if (GlobalConfig.DEBUG) {
+                    GlobalConfig.ASTERIX_LOGGER.finest("AVG aggregate ran over empty input.");
+                }
+                result.writeByte(ATypeTag.SYSTEM_NULL.serialize());
+            } else if (aggType == ATypeTag.NULL) {
+                result.writeByte(ATypeTag.NULL.serialize());
+            } else {
+                sumBytes.reset();
+                aDouble.setValue(sum);
+                doubleSerde.serialize(aDouble, sumBytesOutput);
+                countBytes.reset();
+                aInt64.setValue(count);
+                longSerde.serialize(aInt64, countBytesOutput);
+                recordEval.evaluate(null);
+            }
+        } catch (IOException e) {
+            throw new AlgebricksException(e);
+        }
+    }
+
+    protected void processPartialResults(IFrameTupleReference tuple, byte[] state, int start, int len)
+            throws AlgebricksException {
+        if (skipStep(state, start)) {
+            return;
+        }
+        double sum = BufferSerDeUtil.getDouble(state, start + SUM_OFFSET);
+        long count = BufferSerDeUtil.getLong(state, start + COUNT_OFFSET);
+        ATypeTag aggType = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(state[start + AGG_TYPE_OFFSET]);
+
+        inputVal.reset();
+        eval.evaluate(tuple);
+        byte[] serBytes = inputVal.getByteArray();
+        ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(serBytes[0]);
+        switch (typeTag) {
+            case NULL: {
+                processNull(state, start);
+                break;
+            }
+            case SYSTEM_NULL: {
+                // Ignore and return.
+                break;
+            }
+            case RECORD: {
+                // Expected.
+                int nullBitmapSize = 0;
+                int offset1 = ARecordSerializerDeserializer.getFieldOffsetById(serBytes, SUM_FIELD_ID, nullBitmapSize,
+                        false);
+                sum += ADoubleSerializerDeserializer.getDouble(serBytes, offset1);
+                int offset2 = ARecordSerializerDeserializer.getFieldOffsetById(serBytes, COUNT_FIELD_ID,
+                        nullBitmapSize, false);
+                count += AInt64SerializerDeserializer.getLong(serBytes, offset2);
+
+                BufferSerDeUtil.writeDouble(sum, state, start + SUM_OFFSET);
+                BufferSerDeUtil.writeLong(count, state, start + COUNT_OFFSET);
+                state[start + AGG_TYPE_OFFSET] = aggType.serialize();
+                break;
+            }
+            default: {
+                throw new AlgebricksException("Global-Avg is not defined for values of type "
+                        + EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(serBytes[0]));
+            }
+        }
+    }
+
+    protected void finishFinalResults(byte[] state, int start, int len, DataOutput result) throws AlgebricksException {
+        double sum = BufferSerDeUtil.getDouble(state, start + SUM_OFFSET);
+        long count = BufferSerDeUtil.getLong(state, start + COUNT_OFFSET);
+        ATypeTag aggType = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(state[start + AGG_TYPE_OFFSET]);
+
+        try {
+            if (count == 0 || aggType == ATypeTag.NULL)
+                nullSerde.serialize(ANull.NULL, result);
+            else {
+                aDouble.setValue(sum / count);
+                doubleSerde.serialize(aDouble, result);
+            }
+        } catch (IOException e) {
+            throw new AlgebricksException(e);
+        }
+    }
+
+    protected boolean skipStep(byte[] state, int start) {
+        return false;
+    }
+
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/AbstractSerializableCountAggregateFunction.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/AbstractSerializableCountAggregateFunction.java
new file mode 100644
index 0000000..71f709f
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/AbstractSerializableCountAggregateFunction.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2009-2013 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.aggregates.serializable.std;
+
+import java.io.DataOutput;
+import java.io.IOException;
+
+import edu.uci.ics.asterix.formats.nontagged.AqlSerializerDeserializerProvider;
+import edu.uci.ics.asterix.om.base.AInt64;
+import edu.uci.ics.asterix.om.base.AMutableInt64;
+import edu.uci.ics.asterix.om.base.ANull;
+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.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluator;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopySerializableAggregateFunction;
+import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
+import edu.uci.ics.hyracks.data.std.util.ArrayBackedValueStorage;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+
+/**
+ * count(NULL) returns NULL.
+ */
+public abstract class AbstractSerializableCountAggregateFunction implements ICopySerializableAggregateFunction {
+    private static final int MET_NULL_OFFSET = 0;
+    private static final int COUNT_OFFSET = 1;
+
+    private AMutableInt64 result = new AMutableInt64(-1);
+    @SuppressWarnings("unchecked")
+    private ISerializerDeserializer<AInt64> int64Serde = AqlSerializerDeserializerProvider.INSTANCE
+            .getSerializerDeserializer(BuiltinType.AINT64);
+    @SuppressWarnings("unchecked")
+    private ISerializerDeserializer<ANull> nullSerde = AqlSerializerDeserializerProvider.INSTANCE
+            .getSerializerDeserializer(BuiltinType.ANULL);
+    private ArrayBackedValueStorage inputVal = new ArrayBackedValueStorage();
+    private ICopyEvaluator eval;
+
+    public AbstractSerializableCountAggregateFunction(ICopyEvaluatorFactory[] args) throws AlgebricksException {
+        eval = args[0].createEvaluator(inputVal);
+    }
+
+    @Override
+    public void init(DataOutput state) throws AlgebricksException {
+        try {
+            state.writeBoolean(false);
+            state.writeLong(0);
+        } catch (IOException e) {
+            throw new AlgebricksException(e);
+        }
+    }
+
+    @Override
+    public void step(IFrameTupleReference tuple, byte[] state, int start, int len) throws AlgebricksException {
+        boolean metNull = BufferSerDeUtil.getBoolean(state, start);
+        long cnt = BufferSerDeUtil.getLong(state, start + 1);
+        inputVal.reset();
+        eval.evaluate(tuple);
+        ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(inputVal.getByteArray()[0]);
+        if (typeTag == ATypeTag.NULL) {
+            processNull(state, start);
+        } else {
+            cnt++;
+        }
+        BufferSerDeUtil.writeBoolean(metNull, state, start + MET_NULL_OFFSET);
+        BufferSerDeUtil.writeLong(cnt, state, start + COUNT_OFFSET);
+    }
+
+    @Override
+    public void finish(byte[] state, int start, int len, DataOutput out) throws AlgebricksException {
+        boolean metNull = BufferSerDeUtil.getBoolean(state, start);
+        long cnt = BufferSerDeUtil.getLong(state, start + 1);
+        try {
+            if (metNull) {
+                nullSerde.serialize(ANull.NULL, out);
+            } else {
+                result.setValue(cnt);
+                int64Serde.serialize(result, out);
+            }
+        } catch (IOException e) {
+            throw new AlgebricksException(e);
+        }
+    }
+
+    @Override
+    public void finishPartial(byte[] state, int start, int len, DataOutput out) throws AlgebricksException {
+        finish(state, start, len, out);
+    }
+
+    protected void processNull(byte[] state, int start) {
+        BufferSerDeUtil.writeBoolean(true, state, start + MET_NULL_OFFSET);
+    }
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/AbstractSerializableSumAggregateFunction.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/AbstractSerializableSumAggregateFunction.java
new file mode 100644
index 0000000..68c5b43
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/AbstractSerializableSumAggregateFunction.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2009-2013 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.aggregates.serializable.std;
+
+import java.io.DataOutput;
+import java.io.IOException;
+
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.ADoubleSerializerDeserializer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AFloatSerializerDeserializer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt16SerializerDeserializer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt32SerializerDeserializer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt64SerializerDeserializer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt8SerializerDeserializer;
+import edu.uci.ics.asterix.formats.nontagged.AqlSerializerDeserializerProvider;
+import edu.uci.ics.asterix.om.base.AMutableDouble;
+import edu.uci.ics.asterix.om.base.AMutableFloat;
+import edu.uci.ics.asterix.om.base.AMutableInt16;
+import edu.uci.ics.asterix.om.base.AMutableInt32;
+import edu.uci.ics.asterix.om.base.AMutableInt64;
+import edu.uci.ics.asterix.om.base.AMutableInt8;
+import edu.uci.ics.asterix.om.base.ANull;
+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.types.hierachy.ATypeHierarchy;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.NotImplementedException;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluator;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopySerializableAggregateFunction;
+import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
+import edu.uci.ics.hyracks.data.std.util.ArrayBackedValueStorage;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+
+public abstract class AbstractSerializableSumAggregateFunction implements ICopySerializableAggregateFunction {
+    protected static final int AGG_TYPE_OFFSET = 0;
+    private static final int SUM_OFFSET = 1;
+
+    private ArrayBackedValueStorage inputVal = new ArrayBackedValueStorage();
+    private ICopyEvaluator eval;
+    private AMutableDouble aDouble = new AMutableDouble(0);
+    private AMutableFloat aFloat = new AMutableFloat(0);
+    private AMutableInt64 aInt64 = new AMutableInt64(0);
+    private AMutableInt32 aInt32 = new AMutableInt32(0);
+    private AMutableInt16 aInt16 = new AMutableInt16((short) 0);
+    private AMutableInt8 aInt8 = new AMutableInt8((byte) 0);
+    @SuppressWarnings("rawtypes")
+    public ISerializerDeserializer serde;
+
+    public AbstractSerializableSumAggregateFunction(ICopyEvaluatorFactory[] args)
+            throws AlgebricksException {
+        eval = args[0].createEvaluator(inputVal);
+    }
+
+    @Override
+    public void init(DataOutput state) throws AlgebricksException {
+        try {
+            state.writeByte(ATypeTag.SYSTEM_NULL.serialize());
+            state.writeDouble(0.0);
+        } catch (IOException e) {
+            throw new AlgebricksException(e);
+        }
+    }
+
+    @Override
+    public void step(IFrameTupleReference tuple, byte[] state, int start, int len) throws AlgebricksException {
+        if (skipStep(state, start)) {
+            return;
+        }
+        ATypeTag aggType = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(state[start + AGG_TYPE_OFFSET]);
+        double sum = BufferSerDeUtil.getDouble(state, start + SUM_OFFSET);
+        inputVal.reset();
+        eval.evaluate(tuple);
+        ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(inputVal.getByteArray()[0]);
+        if (typeTag == ATypeTag.NULL) {
+            processNull(state, start);
+            return;
+        } else if (aggType == ATypeTag.SYSTEM_NULL) {
+            aggType = typeTag;
+        } else if (typeTag != ATypeTag.SYSTEM_NULL && !ATypeHierarchy.isCompatible(typeTag, aggType)) {
+            throw new AlgebricksException("Unexpected type " + typeTag
+                    + " in aggregation input stream. Expected type (or a promotable type to)" + aggType + ".");
+        }
+
+        if (ATypeHierarchy.canPromote(aggType, typeTag)) {
+            aggType = typeTag;
+        }
+
+        switch (typeTag) {
+            case INT8: {
+                byte val = AInt8SerializerDeserializer.getByte(inputVal.getByteArray(), 1);
+                sum += val;
+                break;
+            }
+            case INT16: {
+                short val = AInt16SerializerDeserializer.getShort(inputVal.getByteArray(), 1);
+                sum += val;
+                break;
+            }
+            case INT32: {
+                int val = AInt32SerializerDeserializer.getInt(inputVal.getByteArray(), 1);
+                sum += val;
+                break;
+            }
+            case INT64: {
+                long val = AInt64SerializerDeserializer.getLong(inputVal.getByteArray(), 1);
+                sum += val;
+                break;
+            }
+            case FLOAT: {
+                float val = AFloatSerializerDeserializer.getFloat(inputVal.getByteArray(), 1);
+                sum += val;
+                break;
+            }
+            case DOUBLE: {
+                double val = ADoubleSerializerDeserializer.getDouble(inputVal.getByteArray(), 1);
+                sum += val;
+                break;
+            }
+            case NULL: {
+                aggType = typeTag;
+                break;
+            }
+            case SYSTEM_NULL: {
+                processSystemNull();
+                break;
+            }
+            default: {
+                throw new NotImplementedException("Cannot compute SUM for values of type " + typeTag + ".");
+            }
+        }
+        state[start + AGG_TYPE_OFFSET] = aggType.serialize();
+        BufferSerDeUtil.writeDouble(sum, state, start + SUM_OFFSET);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public void finish(byte[] state, int start, int len, DataOutput out) throws AlgebricksException {
+        ATypeTag aggType = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(state[start + AGG_TYPE_OFFSET]);
+        double sum = BufferSerDeUtil.getDouble(state, start + SUM_OFFSET);
+        try {
+            switch (aggType) {
+                case INT8: {
+                    serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AINT8);
+                    aInt8.setValue((byte) sum);
+                    serde.serialize(aInt8, out);
+                    break;
+                }
+                case INT16: {
+                    serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AINT16);
+                    aInt16.setValue((short) sum);
+                    serde.serialize(aInt16, out);
+                    break;
+                }
+                case INT32: {
+                    serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AINT32);
+                    aInt32.setValue((int) sum);
+                    serde.serialize(aInt32, out);
+                    break;
+                }
+                case INT64: {
+                    serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AINT64);
+                    aInt64.setValue((long) sum);
+                    serde.serialize(aInt64, out);
+                    break;
+                }
+                case FLOAT: {
+                    serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AFLOAT);
+                    aFloat.setValue((float) sum);
+                    serde.serialize(aFloat, out);
+                    break;
+                }
+                case DOUBLE: {
+                    serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ADOUBLE);
+                    aDouble.setValue(sum);
+                    serde.serialize(aDouble, out);
+                    break;
+                }
+                case NULL: {
+                    serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ANULL);
+                    serde.serialize(ANull.NULL, out);
+                    break;
+                }
+                case SYSTEM_NULL: {
+                    finishSystemNull(out);
+                    break;
+                }
+                default:
+                    throw new AlgebricksException("SumAggregationFunction: incompatible type for the result ("
+                            + aggType + "). ");
+            }
+        } catch (IOException e) {
+            throw new AlgebricksException(e);
+        }
+    }
+
+    @Override
+    public void finishPartial(byte[] state, int start, int len, DataOutput out) throws AlgebricksException {
+        finish(state, start, len, out);
+    }
+
+    protected boolean skipStep(byte[] state, int start) {
+        return false;
+    }
+    protected abstract void processNull(byte[] state, int start);
+    protected abstract void processSystemNull() throws AlgebricksException;
+    protected abstract void finishSystemNull(DataOutput out) throws IOException;
+
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableAvgAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableAvgAggregateDescriptor.java
index 72e0045..a215a07 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableAvgAggregateDescriptor.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableAvgAggregateDescriptor.java
@@ -14,37 +14,15 @@
  */
 package edu.uci.ics.asterix.runtime.aggregates.serializable.std;
 
-import java.io.DataOutput;
-import java.io.IOException;
-
-import edu.uci.ics.asterix.common.config.GlobalConfig;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.ADoubleSerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AFloatSerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt16SerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt32SerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt64SerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt8SerializerDeserializer;
-import edu.uci.ics.asterix.formats.nontagged.AqlSerializerDeserializerProvider;
-import edu.uci.ics.asterix.om.base.ADouble;
-import edu.uci.ics.asterix.om.base.AMutableDouble;
-import edu.uci.ics.asterix.om.base.ANull;
 import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
 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.aggregates.base.AbstractSerializableAggregateFunctionDynamicDescriptor;
 import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
-import edu.uci.ics.hyracks.algebricks.common.exceptions.NotImplementedException;
 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.algebricks.runtime.base.ICopySerializableAggregateFunction;
 import edu.uci.ics.hyracks.algebricks.runtime.base.ICopySerializableAggregateFunctionFactory;
-import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
-import edu.uci.ics.hyracks.data.std.util.ArrayBackedValueStorage;
-import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
 
 public class SerializableAvgAggregateDescriptor extends AbstractSerializableAggregateFunctionDynamicDescriptor {
 
@@ -62,129 +40,15 @@
 
     @Override
     public ICopySerializableAggregateFunctionFactory createSerializableAggregateFunctionFactory(
-            ICopyEvaluatorFactory[] args) throws AlgebricksException {
-        final ICopyEvaluatorFactory[] evals = args;
-
+            final ICopyEvaluatorFactory[] args) throws AlgebricksException {
         return new ICopySerializableAggregateFunctionFactory() {
             private static final long serialVersionUID = 1L;
 
+            @Override
             public ICopySerializableAggregateFunction createAggregateFunction() throws AlgebricksException {
-                return new ICopySerializableAggregateFunction() {
-                    private ArrayBackedValueStorage inputVal = new ArrayBackedValueStorage();
-                    private ICopyEvaluator eval = evals[0].createEvaluator(inputVal);
-
-                    private AMutableDouble aDouble = new AMutableDouble(0);
-                    @SuppressWarnings("unchecked")
-                    private ISerializerDeserializer<ADouble> doubleSerde = AqlSerializerDeserializerProvider.INSTANCE
-                            .getSerializerDeserializer(BuiltinType.ADOUBLE);
-                    @SuppressWarnings("unchecked")
-                    private ISerializerDeserializer<ANull> nullSerde = AqlSerializerDeserializerProvider.INSTANCE
-                            .getSerializerDeserializer(BuiltinType.ANULL);
-
-                    @Override
-                    public void init(DataOutput state) throws AlgebricksException {
-                        try {
-                            state.writeDouble(0.0);
-                            state.writeLong(0);
-                            state.writeBoolean(false);
-                        } catch (IOException e) {
-                            throw new AlgebricksException(e);
-                        }
-                    }
-
-                    @Override
-                    public void step(IFrameTupleReference tuple, byte[] state, int start, int len)
-                            throws AlgebricksException {
-                        inputVal.reset();
-                        eval.evaluate(tuple);
-                        double sum = BufferSerDeUtil.getDouble(state, start);
-                        long count = BufferSerDeUtil.getLong(state, start + 8);
-                        boolean metNull = BufferSerDeUtil.getBoolean(state, start + 16);
-                        if (inputVal.getLength() > 0) {
-                            ++count;
-                            ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(inputVal
-                                    .getByteArray()[0]);
-                            switch (typeTag) {
-                                case INT8: {
-                                    byte val = AInt8SerializerDeserializer.getByte(inputVal.getByteArray(), 1);
-                                    sum += val;
-                                    break;
-                                }
-                                case INT16: {
-                                    short val = AInt16SerializerDeserializer.getShort(inputVal.getByteArray(), 1);
-                                    sum += val;
-                                    break;
-                                }
-                                case INT32: {
-                                    int val = AInt32SerializerDeserializer.getInt(inputVal.getByteArray(), 1);
-                                    sum += val;
-                                    break;
-                                }
-                                case INT64: {
-                                    long val = AInt64SerializerDeserializer.getLong(inputVal.getByteArray(), 1);
-                                    sum += val;
-                                    break;
-                                }
-                                case FLOAT: {
-                                    float val = AFloatSerializerDeserializer.getFloat(inputVal.getByteArray(), 1);
-                                    sum += val;
-                                    break;
-                                }
-                                case DOUBLE: {
-                                    double val = ADoubleSerializerDeserializer.getDouble(inputVal.getByteArray(), 1);
-                                    sum += val;
-                                    break;
-                                }
-                                case NULL: {
-                                    metNull = true;
-                                    break;
-                                }
-                                default: {
-                                    throw new NotImplementedException("Cannot compute AVG for values of type "
-                                            + typeTag);
-                                }
-                            }
-                            inputVal.reset();
-                        }
-                        BufferSerDeUtil.writeDouble(sum, state, start);
-                        BufferSerDeUtil.writeLong(count, state, start + 8);
-                        BufferSerDeUtil.writeBoolean(metNull, state, start + 16);
-                    }
-
-                    @Override
-                    public void finish(byte[] state, int start, int len, DataOutput result) throws AlgebricksException {
-                        double sum = BufferSerDeUtil.getDouble(state, start);
-                        long count = BufferSerDeUtil.getLong(state, start + 8);
-                        boolean metNull = BufferSerDeUtil.getBoolean(state, start + 16);
-
-                        if (count == 0) {
-                            GlobalConfig.ASTERIX_LOGGER.fine("AVG aggregate ran over empty input.");
-                        } else {
-                            try {
-                                if (metNull)
-                                    nullSerde.serialize(ANull.NULL, result);
-                                else {
-                                    aDouble.setValue(sum / count);
-                                    doubleSerde.serialize(aDouble, result);
-                                }
-                            } catch (IOException e) {
-                                throw new AlgebricksException(e);
-                            }
-                        }
-                    }
-
-                    @Override
-                    public void finishPartial(byte[] data, int start, int len, DataOutput partialResult)
-                            throws AlgebricksException {
-                        try {
-                            partialResult.write(data, start, len);
-                        } catch (IOException e) {
-                            throw new AlgebricksException(e);
-                        }
-                    }
-
-                };
+                return new SerializableAvgAggregateFunction(args);
             }
         };
     }
+
 }
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableAvgAggregateFunction.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableAvgAggregateFunction.java
new file mode 100644
index 0000000..202933d
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableAvgAggregateFunction.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2009-2013 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.aggregates.serializable.std;
+
+import java.io.DataOutput;
+
+import edu.uci.ics.asterix.om.types.ATypeTag;
+import edu.uci.ics.asterix.om.types.EnumDeserializer;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+
+public class SerializableAvgAggregateFunction extends AbstractSerializableAvgAggregateFunction {
+
+    public SerializableAvgAggregateFunction(ICopyEvaluatorFactory[] args) throws AlgebricksException {
+        super(args);
+    }
+
+    @Override
+    public void step(IFrameTupleReference tuple, byte[] state, int start, int len) throws AlgebricksException {
+        processDataValues(tuple, state, start, len);
+    }
+
+    @Override
+    public void finish(byte[] state, int start, int len, DataOutput result) throws AlgebricksException {
+        finishFinalResults(state, start, len, result);
+    }
+
+    @Override
+    public void finishPartial(byte[] state, int start, int len, DataOutput result) throws AlgebricksException {
+        finish(state, start, len, result);
+    }
+
+    protected void processNull(byte[] state, int start) {
+        state[start + AGG_TYPE_OFFSET] = ATypeTag.NULL.serialize();
+    }
+
+    @Override
+    protected boolean skipStep(byte[] state, int start) {
+        ATypeTag aggType = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(state[start + AGG_TYPE_OFFSET]);
+        return (aggType == ATypeTag.NULL);
+    }
+
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableCountAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableCountAggregateDescriptor.java
index a9b264c..0c9ce06 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableCountAggregateDescriptor.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableCountAggregateDescriptor.java
@@ -14,29 +14,15 @@
  */
 package edu.uci.ics.asterix.runtime.aggregates.serializable.std;
 
-import java.io.DataOutput;
-import java.io.IOException;
-
-import edu.uci.ics.asterix.formats.nontagged.AqlSerializerDeserializerProvider;
-import edu.uci.ics.asterix.om.base.AInt64;
-import edu.uci.ics.asterix.om.base.AMutableInt64;
-import edu.uci.ics.asterix.om.base.ANull;
 import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
 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.aggregates.base.AbstractSerializableAggregateFunctionDynamicDescriptor;
 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.algebricks.runtime.base.ICopySerializableAggregateFunction;
 import edu.uci.ics.hyracks.algebricks.runtime.base.ICopySerializableAggregateFunctionFactory;
-import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
-import edu.uci.ics.hyracks.data.std.util.ArrayBackedValueStorage;
-import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
 
 /**
  * count(NULL) returns NULL.
@@ -63,68 +49,7 @@
 
             @Override
             public ICopySerializableAggregateFunction createAggregateFunction() throws AlgebricksException {
-
-                return new ICopySerializableAggregateFunction() {
-                    private AMutableInt64 result = new AMutableInt64(-1);
-                    @SuppressWarnings("unchecked")
-                    private ISerializerDeserializer<AInt64> int64Serde = AqlSerializerDeserializerProvider.INSTANCE
-                            .getSerializerDeserializer(BuiltinType.AINT64);
-                    @SuppressWarnings("unchecked")
-                    private ISerializerDeserializer<ANull> nullSerde = AqlSerializerDeserializerProvider.INSTANCE
-                            .getSerializerDeserializer(BuiltinType.ANULL);
-                    private ArrayBackedValueStorage inputVal = new ArrayBackedValueStorage();
-                    private ICopyEvaluator eval = args[0].createEvaluator(inputVal);
-
-                    @Override
-                    public void init(DataOutput state) throws AlgebricksException {
-                        try {
-                            state.writeBoolean(false);
-                            state.writeLong(0);
-                        } catch (IOException e) {
-                            throw new AlgebricksException(e);
-                        }
-                    }
-
-                    @Override
-                    public void step(IFrameTupleReference tuple, byte[] state, int start, int len)
-                            throws AlgebricksException {
-                        boolean metNull = BufferSerDeUtil.getBoolean(state, start);
-                        long cnt = BufferSerDeUtil.getLong(state, start + 1);
-                        inputVal.reset();
-                        eval.evaluate(tuple);
-                        ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER
-                                .deserialize(inputVal.getByteArray()[0]);
-                        if (typeTag == ATypeTag.NULL) {
-                            metNull = true;
-                        } else {
-                            cnt++;
-                        }
-                        BufferSerDeUtil.writeBoolean(metNull, state, start);
-                        BufferSerDeUtil.writeLong(cnt, state, start + 1);
-                    }
-
-                    @Override
-                    public void finish(byte[] state, int start, int len, DataOutput out) throws AlgebricksException {
-                        boolean metNull = BufferSerDeUtil.getBoolean(state, start);
-                        long cnt = BufferSerDeUtil.getLong(state, start + 1);
-                        try {
-                            if (metNull) {
-                                nullSerde.serialize(ANull.NULL, out);
-                            } else {
-                                result.setValue(cnt);
-                                int64Serde.serialize(result, out);
-                            }
-                        } catch (IOException e) {
-                            throw new AlgebricksException(e);
-                        }
-                    }
-
-                    @Override
-                    public void finishPartial(byte[] state, int start, int len, DataOutput out)
-                            throws AlgebricksException {
-                        finish(state, start, len, out);
-                    }
-                };
+                return new SerializableCountAggregateFunction(args);
             }
         };
     }
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableCountAggregateFunction.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableCountAggregateFunction.java
new file mode 100644
index 0000000..7a6aacd
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableCountAggregateFunction.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2009-2013 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.aggregates.serializable.std;
+
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+
+/**
+ * count(NULL) returns NULL.
+ */
+public class SerializableCountAggregateFunction extends AbstractSerializableCountAggregateFunction {
+    public SerializableCountAggregateFunction(ICopyEvaluatorFactory[] args) throws AlgebricksException {
+        super(args);
+    }
+}
\ No newline at end of file
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableGlobalAvgAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableGlobalAvgAggregateDescriptor.java
index f720434..ccfeb43 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableGlobalAvgAggregateDescriptor.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableGlobalAvgAggregateDescriptor.java
@@ -15,44 +15,15 @@
 
 package edu.uci.ics.asterix.runtime.aggregates.serializable.std;
 
-import java.io.DataOutput;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import edu.uci.ics.asterix.common.exceptions.AsterixException;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.ADoubleSerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt64SerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.ARecordSerializerDeserializer;
-import edu.uci.ics.asterix.formats.nontagged.AqlSerializerDeserializerProvider;
-import edu.uci.ics.asterix.om.base.ADouble;
-import edu.uci.ics.asterix.om.base.AInt64;
-import edu.uci.ics.asterix.om.base.AMutableDouble;
-import edu.uci.ics.asterix.om.base.AMutableInt64;
-import edu.uci.ics.asterix.om.base.ANull;
 import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
 import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
 import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
-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.BuiltinType;
-import edu.uci.ics.asterix.om.types.EnumDeserializer;
-import edu.uci.ics.asterix.om.types.IAType;
 import edu.uci.ics.asterix.runtime.aggregates.base.AbstractSerializableAggregateFunctionDynamicDescriptor;
-import edu.uci.ics.asterix.runtime.evaluators.common.AccessibleByteArrayEval;
-import edu.uci.ics.asterix.runtime.evaluators.common.ClosedRecordConstructorEvalFactory.ClosedRecordConstructorEval;
 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.algebricks.runtime.base.ICopySerializableAggregateFunction;
 import edu.uci.ics.hyracks.algebricks.runtime.base.ICopySerializableAggregateFunctionFactory;
-import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
-import edu.uci.ics.hyracks.data.std.util.ArrayBackedValueStorage;
-import edu.uci.ics.hyracks.data.std.util.ByteArrayAccessibleOutputStream;
-import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
 
 public class SerializableGlobalAvgAggregateDescriptor extends AbstractSerializableAggregateFunctionDynamicDescriptor {
 
@@ -70,154 +41,13 @@
 
     @Override
     public ICopySerializableAggregateFunctionFactory createSerializableAggregateFunctionFactory(
-            ICopyEvaluatorFactory[] args) throws AlgebricksException {
-        final ICopyEvaluatorFactory[] evals = args;
-        List<IAType> unionList = new ArrayList<IAType>();
-        unionList.add(BuiltinType.ANULL);
-        unionList.add(BuiltinType.ADOUBLE);
-        ARecordType _recType;
-        try {
-            _recType = new ARecordType(null, new String[] { "sum", "count" }, new IAType[] {
-                    new AUnionType(unionList, "OptionalDouble"), BuiltinType.AINT64 }, true);
-        } catch (AsterixException e) {
-            throw new AlgebricksException(e);
-        }
-
-        final ARecordType recType = _recType;
-
+            final ICopyEvaluatorFactory[] args) throws AlgebricksException {
         return new ICopySerializableAggregateFunctionFactory() {
             private static final long serialVersionUID = 1L;
 
             @Override
             public ICopySerializableAggregateFunction createAggregateFunction() throws AlgebricksException {
-
-                return new ICopySerializableAggregateFunction() {
-                    private ArrayBackedValueStorage inputVal = new ArrayBackedValueStorage();
-                    private ICopyEvaluator eval = evals[0].createEvaluator(inputVal);
-                    private AMutableDouble aDouble = new AMutableDouble(0);
-                    private AMutableInt64 aInt64 = new AMutableInt64(0);
-
-                    private ArrayBackedValueStorage avgBytes = new ArrayBackedValueStorage();
-                    private ByteArrayAccessibleOutputStream sumBytes = new ByteArrayAccessibleOutputStream();
-                    private DataOutput sumBytesOutput = new DataOutputStream(sumBytes);
-                    private ByteArrayAccessibleOutputStream countBytes = new ByteArrayAccessibleOutputStream();
-                    private DataOutput countBytesOutput = new DataOutputStream(countBytes);
-                    private ICopyEvaluator evalSum = new AccessibleByteArrayEval(avgBytes.getDataOutput(), sumBytes);
-                    private ICopyEvaluator evalCount = new AccessibleByteArrayEval(avgBytes.getDataOutput(), countBytes);
-                    private ClosedRecordConstructorEval recordEval;
-
-                    @SuppressWarnings("unchecked")
-                    private ISerializerDeserializer<AInt64> longSerde = AqlSerializerDeserializerProvider.INSTANCE
-                            .getSerializerDeserializer(BuiltinType.AINT64);
-                    @SuppressWarnings("unchecked")
-                    private ISerializerDeserializer<ADouble> doubleSerde = AqlSerializerDeserializerProvider.INSTANCE
-                            .getSerializerDeserializer(BuiltinType.ADOUBLE);
-                    @SuppressWarnings("unchecked")
-                    private ISerializerDeserializer<ANull> nullSerde = AqlSerializerDeserializerProvider.INSTANCE
-                            .getSerializerDeserializer(BuiltinType.ANULL);
-
-                    @Override
-                    public void init(DataOutput state) throws AlgebricksException {
-                        try {
-                            state.writeDouble(0.0);
-                            state.writeLong(0);
-                            state.writeBoolean(false);
-                        } catch (IOException e) {
-                            throw new AlgebricksException(e);
-                        }
-                    }
-
-                    @Override
-                    public void step(IFrameTupleReference tuple, byte[] state, int start, int len)
-                            throws AlgebricksException {
-                        double globalSum = BufferSerDeUtil.getDouble(state, start);
-                        long globalCount = BufferSerDeUtil.getLong(state, start + 8);
-                        boolean metNull = BufferSerDeUtil.getBoolean(state, start + 16);
-
-                        inputVal.reset();
-                        eval.evaluate(tuple);
-                        byte[] serBytes = inputVal.getByteArray();
-                        ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(serBytes[0]);
-                        switch (typeTag) {
-                            case NULL: {
-                                metNull = true;
-                                break;
-                            }
-                            case SYSTEM_NULL: {
-                                // Ignore and return.
-                                return;
-                            }
-                            case RECORD: {
-                                // Expected.
-                                break;
-                            }
-                            default: {
-                                throw new AlgebricksException("Global-Avg is not defined for values of type "
-                                        + EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(serBytes[0]));
-                            }
-                        }
-                        int offset1 = ARecordSerializerDeserializer.getFieldOffsetById(serBytes, 0, 1, true);
-                        if (offset1 == 0) // the sum is null
-                            metNull = true;
-                        else
-                            globalSum += ADoubleSerializerDeserializer.getDouble(serBytes, offset1);
-                        int offset2 = ARecordSerializerDeserializer.getFieldOffsetById(serBytes, 1, 1, true);
-                        if (offset2 != 0) // the count is not null
-                            globalCount += AInt64SerializerDeserializer.getLong(serBytes, offset2);
-
-                        BufferSerDeUtil.writeDouble(globalSum, state, start);
-                        BufferSerDeUtil.writeLong(globalCount, state, start + 8);
-                        BufferSerDeUtil.writeBoolean(metNull, state, start + 16);
-
-                    }
-
-                    @Override
-                    public void finish(byte[] state, int start, int len, DataOutput result) throws AlgebricksException {
-                        double globalSum = BufferSerDeUtil.getDouble(state, start);
-                        long globalCount = BufferSerDeUtil.getLong(state, start + 8);
-                        boolean metNull = BufferSerDeUtil.getBoolean(state, start + 16);
-
-                        try {
-                            if (globalCount == 0 || metNull)
-                                nullSerde.serialize(ANull.NULL, result);
-                            else {
-                                aDouble.setValue(globalSum / globalCount);
-                                doubleSerde.serialize(aDouble, result);
-                            }
-                        } catch (IOException e) {
-                            throw new AlgebricksException(e);
-                        }
-                    }
-
-                    @Override
-                    public void finishPartial(byte[] state, int start, int len, DataOutput result)
-                            throws AlgebricksException {
-                        double globalSum = BufferSerDeUtil.getDouble(state, start);
-                        long globalCount = BufferSerDeUtil.getLong(state, start + 8);
-                        boolean metNull = BufferSerDeUtil.getBoolean(state, start + 16);
-
-                        if (recordEval == null)
-                            recordEval = new ClosedRecordConstructorEval(recType, new ICopyEvaluator[] { evalSum,
-                                    evalCount }, avgBytes, result);
-
-                        try {
-                            if (globalCount == 0 || metNull) {
-                                sumBytes.reset();
-                                nullSerde.serialize(ANull.NULL, sumBytesOutput);
-                            } else {
-                                sumBytes.reset();
-                                aDouble.setValue(globalSum);
-                                doubleSerde.serialize(aDouble, sumBytesOutput);
-                            }
-                            countBytes.reset();
-                            aInt64.setValue(globalCount);
-                            longSerde.serialize(aInt64, countBytesOutput);
-                            recordEval.evaluate(null);
-                        } catch (IOException e) {
-                            throw new AlgebricksException(e);
-                        }
-                    }
-                };
+                return new SerializableGlobalAvgAggregateFunction(args);
             }
         };
     }
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableGlobalAvgAggregateFunction.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableGlobalAvgAggregateFunction.java
new file mode 100644
index 0000000..c6d4b5a
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableGlobalAvgAggregateFunction.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2009-2013 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.aggregates.serializable.std;
+
+import java.io.DataOutput;
+
+import edu.uci.ics.asterix.om.types.ATypeTag;
+import edu.uci.ics.asterix.om.types.EnumDeserializer;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+
+public class SerializableGlobalAvgAggregateFunction extends AbstractSerializableAvgAggregateFunction {
+
+    public SerializableGlobalAvgAggregateFunction(ICopyEvaluatorFactory[] args) throws AlgebricksException {
+        super(args);
+    }
+
+    @Override
+    public void step(IFrameTupleReference tuple, byte[] state, int start, int len) throws AlgebricksException {
+        processPartialResults(tuple, state, start, len);
+    }
+
+    @Override
+    public void finish(byte[] state, int start, int len, DataOutput result) throws AlgebricksException {
+        finishFinalResults(state, start, len, result);
+    }
+
+    @Override
+    public void finishPartial(byte[] state, int start, int len, DataOutput result) throws AlgebricksException {
+        finishPartialResults(state, start, len, result);
+    }
+
+    protected void processNull(byte[] state, int start) {
+        state[start + AGG_TYPE_OFFSET] = ATypeTag.NULL.serialize();
+    }
+
+    @Override
+    protected boolean skipStep(byte[] state, int start) {
+        ATypeTag aggType = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(state[start + AGG_TYPE_OFFSET]);
+        return (aggType == ATypeTag.NULL);
+    }
+
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableGlobalSqlAvgAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableGlobalSqlAvgAggregateDescriptor.java
new file mode 100644
index 0000000..7fa6b9c
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableGlobalSqlAvgAggregateDescriptor.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2009-2013 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.aggregates.serializable.std;
+
+import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
+import edu.uci.ics.asterix.runtime.aggregates.base.AbstractSerializableAggregateFunctionDynamicDescriptor;
+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.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopySerializableAggregateFunction;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopySerializableAggregateFunctionFactory;
+
+public class SerializableGlobalSqlAvgAggregateDescriptor extends AbstractSerializableAggregateFunctionDynamicDescriptor {
+
+    private static final long serialVersionUID = 1L;
+    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new SerializableGlobalSqlAvgAggregateDescriptor();
+        }
+    };
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return AsterixBuiltinFunctions.SERIAL_GLOBAL_SQL_AVG;
+    }
+
+    @Override
+    public ICopySerializableAggregateFunctionFactory createSerializableAggregateFunctionFactory(
+            final ICopyEvaluatorFactory[] args) throws AlgebricksException {
+        return new ICopySerializableAggregateFunctionFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public ICopySerializableAggregateFunction createAggregateFunction() throws AlgebricksException {
+                return new SerializableGlobalSqlAvgAggregateFunction(args);
+            }
+        };
+    }
+
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableGlobalSqlAvgAggregateFunction.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableGlobalSqlAvgAggregateFunction.java
new file mode 100644
index 0000000..cc5043f
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableGlobalSqlAvgAggregateFunction.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2009-2013 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.aggregates.serializable.std;
+
+import java.io.DataOutput;
+
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+
+public class SerializableGlobalSqlAvgAggregateFunction extends AbstractSerializableAvgAggregateFunction {
+
+    public SerializableGlobalSqlAvgAggregateFunction(ICopyEvaluatorFactory[] args) throws AlgebricksException {
+        super(args);
+    }
+
+    @Override
+    public void step(IFrameTupleReference tuple, byte[] state, int start, int len) throws AlgebricksException {
+        processPartialResults(tuple, state, start, len);
+    }
+
+    @Override
+    public void finish(byte[] state, int start, int len, DataOutput result) throws AlgebricksException {
+        finishFinalResults(state, start, len, result);
+    }
+
+    @Override
+    public void finishPartial(byte[] state, int start, int len, DataOutput result) throws AlgebricksException {
+        finishPartialResults(state, start, len, result);
+    }
+
+    @Override
+    protected void processNull(byte[] state, int start) {
+    }
+
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableLocalAvgAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableLocalAvgAggregateDescriptor.java
index 219204b..c015682 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableLocalAvgAggregateDescriptor.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableLocalAvgAggregateDescriptor.java
@@ -15,48 +15,15 @@
 
 package edu.uci.ics.asterix.runtime.aggregates.serializable.std;
 
-import java.io.DataOutput;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import edu.uci.ics.asterix.common.exceptions.AsterixException;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.ADoubleSerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AFloatSerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt16SerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt32SerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt64SerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt8SerializerDeserializer;
-import edu.uci.ics.asterix.formats.nontagged.AqlSerializerDeserializerProvider;
-import edu.uci.ics.asterix.om.base.ADouble;
-import edu.uci.ics.asterix.om.base.AInt64;
-import edu.uci.ics.asterix.om.base.AMutableDouble;
-import edu.uci.ics.asterix.om.base.AMutableInt64;
-import edu.uci.ics.asterix.om.base.ANull;
 import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
 import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
 import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
-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.BuiltinType;
-import edu.uci.ics.asterix.om.types.EnumDeserializer;
-import edu.uci.ics.asterix.om.types.IAType;
 import edu.uci.ics.asterix.runtime.aggregates.base.AbstractSerializableAggregateFunctionDynamicDescriptor;
-import edu.uci.ics.asterix.runtime.evaluators.common.AccessibleByteArrayEval;
-import edu.uci.ics.asterix.runtime.evaluators.common.ClosedRecordConstructorEvalFactory.ClosedRecordConstructorEval;
 import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
-import edu.uci.ics.hyracks.algebricks.common.exceptions.NotImplementedException;
 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.algebricks.runtime.base.ICopySerializableAggregateFunction;
 import edu.uci.ics.hyracks.algebricks.runtime.base.ICopySerializableAggregateFunctionFactory;
-import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
-import edu.uci.ics.hyracks.data.std.util.ArrayBackedValueStorage;
-import edu.uci.ics.hyracks.data.std.util.ByteArrayAccessibleOutputStream;
-import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
 
 public class SerializableLocalAvgAggregateDescriptor extends AbstractSerializableAggregateFunctionDynamicDescriptor {
 
@@ -74,163 +41,12 @@
 
     @Override
     public ICopySerializableAggregateFunctionFactory createSerializableAggregateFunctionFactory(
-            ICopyEvaluatorFactory[] args) throws AlgebricksException {
-        final ICopyEvaluatorFactory[] evals = args;
-        List<IAType> unionList = new ArrayList<IAType>();
-        unionList.add(BuiltinType.ANULL);
-        unionList.add(BuiltinType.ADOUBLE);
-        ARecordType tmpRecType;
-        try {
-            tmpRecType = new ARecordType(null, new String[] { "sum", "count" }, new IAType[] {
-                    new AUnionType(unionList, "OptionalDouble"), BuiltinType.AINT64 }, true);
-        } catch (AsterixException e) {
-            throw new AlgebricksException(e);
-        }
-
-        final ARecordType recType = tmpRecType;
-
+            final ICopyEvaluatorFactory[] args) throws AlgebricksException {
         return new ICopySerializableAggregateFunctionFactory() {
             private static final long serialVersionUID = 1L;
 
             public ICopySerializableAggregateFunction createAggregateFunction() throws AlgebricksException {
-                return new ICopySerializableAggregateFunction() {
-                    private ArrayBackedValueStorage inputVal = new ArrayBackedValueStorage();
-                    private ICopyEvaluator eval = evals[0].createEvaluator(inputVal);
-                    private ClosedRecordConstructorEval recordEval;
-
-                    private AMutableDouble aDouble = new AMutableDouble(0);
-                    private AMutableInt64 aInt64 = new AMutableInt64(0);
-
-                    @SuppressWarnings("unchecked")
-                    private ISerializerDeserializer<ADouble> doubleSerde = AqlSerializerDeserializerProvider.INSTANCE
-                            .getSerializerDeserializer(BuiltinType.ADOUBLE);
-                    @SuppressWarnings("unchecked")
-                    private ISerializerDeserializer<AInt64> int64Serde = AqlSerializerDeserializerProvider.INSTANCE
-                            .getSerializerDeserializer(BuiltinType.AINT64);
-                    @SuppressWarnings("unchecked")
-                    private ISerializerDeserializer<ANull> nullSerde = AqlSerializerDeserializerProvider.INSTANCE
-                            .getSerializerDeserializer(BuiltinType.ANULL);
-
-                    private ArrayBackedValueStorage avgBytes = new ArrayBackedValueStorage();
-                    private ByteArrayAccessibleOutputStream sumBytes = new ByteArrayAccessibleOutputStream();
-                    private DataOutput sumBytesOutput = new DataOutputStream(sumBytes);
-                    private ByteArrayAccessibleOutputStream countBytes = new ByteArrayAccessibleOutputStream();
-                    private DataOutput countBytesOutput = new DataOutputStream(countBytes);
-                    private ICopyEvaluator evalSum = new AccessibleByteArrayEval(avgBytes.getDataOutput(), sumBytes);
-                    private ICopyEvaluator evalCount = new AccessibleByteArrayEval(avgBytes.getDataOutput(), countBytes);
-
-                    @Override
-                    public void init(DataOutput state) throws AlgebricksException {
-                        try {
-                            state.writeDouble(0.0);
-                            state.writeLong(0);
-                            state.writeByte(ATypeTag.SYSTEM_NULL.serialize());
-                        } catch (IOException e) {
-                            throw new AlgebricksException(e);
-                        }
-                    }
-
-                    @Override
-                    public void step(IFrameTupleReference tuple, byte[] state, int start, int len)
-                            throws AlgebricksException {
-                        inputVal.reset();
-                        eval.evaluate(tuple);
-                        double sum = BufferSerDeUtil.getDouble(state, start);
-                        long count = BufferSerDeUtil.getLong(state, start + 8);
-                        ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER
-                                .deserialize(inputVal.getByteArray()[0]);
-                        ATypeTag aggType = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(state[start + 16]);
-                        if (typeTag == ATypeTag.NULL || aggType == ATypeTag.NULL) {
-                            aggType = ATypeTag.NULL;
-                            return;
-                        } else if (aggType == ATypeTag.SYSTEM_NULL) {
-                            aggType = typeTag;
-                        } else if (typeTag != ATypeTag.SYSTEM_NULL && typeTag != aggType) {
-                            throw new AlgebricksException("Unexpected type " + typeTag
-                                    + " in aggregation input stream. Expected type " + aggType + ".");
-                        }
-                        ++count;
-                        switch (typeTag) {
-                            case INT8: {
-                                byte val = AInt8SerializerDeserializer.getByte(inputVal.getByteArray(), 1);
-                                sum += val;
-                                break;
-                            }
-                            case INT16: {
-                                short val = AInt16SerializerDeserializer.getShort(inputVal.getByteArray(), 1);
-                                sum += val;
-                                break;
-                            }
-                            case INT32: {
-                                int val = AInt32SerializerDeserializer.getInt(inputVal.getByteArray(), 1);
-                                sum += val;
-                                break;
-                            }
-                            case INT64: {
-                                long val = AInt64SerializerDeserializer.getLong(inputVal.getByteArray(), 1);
-                                sum += val;
-                                break;
-                            }
-                            case FLOAT: {
-                                float val = AFloatSerializerDeserializer.getFloat(inputVal.getByteArray(), 1);
-                                sum += val;
-                                break;
-                            }
-                            case DOUBLE: {
-                                double val = ADoubleSerializerDeserializer.getDouble(inputVal.getByteArray(), 1);
-                                sum += val;
-                                break;
-                            }
-                            case NULL: {
-                                break;
-                            }
-                            default: {
-                                throw new NotImplementedException("Cannot compute AVG for values of type " + typeTag);
-                            }
-                        }
-                        BufferSerDeUtil.writeDouble(sum, state, start);
-                        BufferSerDeUtil.writeLong(count, state, start + 8);
-                        state[start + 16] = aggType.serialize();
-                    }
-
-                    @Override
-                    public void finish(byte[] state, int start, int len, DataOutput result) throws AlgebricksException {
-                        double sum = BufferSerDeUtil.getDouble(state, start);
-                        long count = BufferSerDeUtil.getLong(state, start + 8);
-                        ATypeTag aggType = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(state[start + 16]);
-                        if (recordEval == null) {
-                            recordEval = new ClosedRecordConstructorEval(recType, new ICopyEvaluator[] { evalSum,
-                                    evalCount }, avgBytes, result);
-                        }
-                        try {
-                            if (count == 0) {
-                                result.writeByte(ATypeTag.SYSTEM_NULL.serialize());
-                                return;
-                            }
-                            if (aggType == ATypeTag.NULL) {
-                                sumBytes.reset();
-                                nullSerde.serialize(ANull.NULL, sumBytesOutput);
-                            } else {
-                                sumBytes.reset();
-                                aDouble.setValue(sum);
-                                doubleSerde.serialize(aDouble, sumBytesOutput);
-                            }
-                            countBytes.reset();
-                            aInt64.setValue(count);
-                            int64Serde.serialize(aInt64, countBytesOutput);
-                            recordEval.evaluate(null);
-                        } catch (IOException e) {
-                            throw new AlgebricksException(e);
-                        }
-                    }
-
-                    @Override
-                    public void finishPartial(byte[] state, int start, int len, DataOutput partialResult)
-                            throws AlgebricksException {
-                        finish(state, start, len, partialResult);
-                    }
-
-                };
+                return new SerializableLocalAvgAggregateFunction(args);
             }
         };
     }
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableLocalAvgAggregateFunction.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableLocalAvgAggregateFunction.java
new file mode 100644
index 0000000..c51787b
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableLocalAvgAggregateFunction.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2009-2013 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.aggregates.serializable.std;
+
+import java.io.DataOutput;
+
+import edu.uci.ics.asterix.om.types.ATypeTag;
+import edu.uci.ics.asterix.om.types.EnumDeserializer;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+
+public class SerializableLocalAvgAggregateFunction extends AbstractSerializableAvgAggregateFunction {
+
+    public SerializableLocalAvgAggregateFunction(ICopyEvaluatorFactory[] args) throws AlgebricksException {
+        super(args);
+    }
+
+    @Override
+    public void step(IFrameTupleReference tuple, byte[] state, int start, int len) throws AlgebricksException {
+    	processDataValues(tuple, state, start, len);
+    }
+
+    @Override
+    public void finish(byte[] state, int start, int len, DataOutput result) throws AlgebricksException {
+        finishPartialResults(state, start, len, result);
+    }
+
+    @Override
+    public void finishPartial(byte[] state, int start, int len, DataOutput result) throws AlgebricksException {
+        finish(state, start, len, result);
+    }
+
+    protected void processNull(byte[] state, int start) {
+        state[start + AGG_TYPE_OFFSET] = ATypeTag.NULL.serialize();
+    }
+
+    @Override
+    protected boolean skipStep(byte[] state, int start) {
+        ATypeTag aggType = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(state[start + AGG_TYPE_OFFSET]);
+        return (aggType == ATypeTag.NULL);
+    }
+
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableLocalSqlAvgAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableLocalSqlAvgAggregateDescriptor.java
new file mode 100644
index 0000000..58415d3
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableLocalSqlAvgAggregateDescriptor.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2009-2013 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.aggregates.serializable.std;
+
+import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
+import edu.uci.ics.asterix.runtime.aggregates.base.AbstractSerializableAggregateFunctionDynamicDescriptor;
+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.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopySerializableAggregateFunction;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopySerializableAggregateFunctionFactory;
+
+public class SerializableLocalSqlAvgAggregateDescriptor extends AbstractSerializableAggregateFunctionDynamicDescriptor {
+
+    private static final long serialVersionUID = 1L;
+    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new SerializableLocalSqlAvgAggregateDescriptor();
+        }
+    };
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return AsterixBuiltinFunctions.SERIAL_LOCAL_SQL_AVG;
+    }
+
+    @Override
+    public ICopySerializableAggregateFunctionFactory createSerializableAggregateFunctionFactory(
+            final ICopyEvaluatorFactory[] args) throws AlgebricksException {
+        return new ICopySerializableAggregateFunctionFactory() {
+            private static final long serialVersionUID = 1L;
+
+            public ICopySerializableAggregateFunction createAggregateFunction() throws AlgebricksException {
+                return new SerializableLocalSqlAvgAggregateFunction(args);
+            }
+        };
+    }
+
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableLocalSqlAvgAggregateFunction.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableLocalSqlAvgAggregateFunction.java
new file mode 100644
index 0000000..a472285
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableLocalSqlAvgAggregateFunction.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2009-2013 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.aggregates.serializable.std;
+
+import java.io.DataOutput;
+
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+
+public class SerializableLocalSqlAvgAggregateFunction extends AbstractSerializableAvgAggregateFunction {
+
+    public SerializableLocalSqlAvgAggregateFunction(ICopyEvaluatorFactory[] args) throws AlgebricksException {
+        super(args);
+    }
+
+    @Override
+    public void step(IFrameTupleReference tuple, byte[] state, int start, int len) throws AlgebricksException {
+    	processDataValues(tuple, state, start, len);
+    }
+
+    @Override
+    public void finish(byte[] state, int start, int len, DataOutput result) throws AlgebricksException {
+        finishPartialResults(state, start, len, result);
+    }
+
+    @Override
+    public void finishPartial(byte[] state, int start, int len, DataOutput result) throws AlgebricksException {
+        finish(state, start, len, result);
+    }
+
+    @Override
+    protected void processNull(byte[] state, int start) {
+    }
+
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableLocalSqlSumAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableLocalSqlSumAggregateDescriptor.java
new file mode 100644
index 0000000..2ce85c6
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableLocalSqlSumAggregateDescriptor.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2009-2013 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.aggregates.serializable.std;
+
+import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
+import edu.uci.ics.asterix.runtime.aggregates.base.AbstractSerializableAggregateFunctionDynamicDescriptor;
+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.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopySerializableAggregateFunction;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopySerializableAggregateFunctionFactory;
+
+public class SerializableLocalSqlSumAggregateDescriptor extends AbstractSerializableAggregateFunctionDynamicDescriptor {
+
+    private static final long serialVersionUID = 1L;
+    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new SerializableLocalSqlSumAggregateDescriptor();
+        }
+    };
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return AsterixBuiltinFunctions.SERIAL_LOCAL_SQL_SUM;
+    }
+
+    @Override
+    public ICopySerializableAggregateFunctionFactory createSerializableAggregateFunctionFactory(
+            final ICopyEvaluatorFactory[] args) throws AlgebricksException {
+        return new ICopySerializableAggregateFunctionFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public ICopySerializableAggregateFunction createAggregateFunction() throws AlgebricksException {
+                return new SerializableSqlSumAggregateFunction(args, true);
+            }
+        };
+    }
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableLocalSumAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableLocalSumAggregateDescriptor.java
index 3f3aaff..bd6ead8 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableLocalSumAggregateDescriptor.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableLocalSumAggregateDescriptor.java
@@ -27,7 +27,6 @@
 public class SerializableLocalSumAggregateDescriptor extends AbstractSerializableAggregateFunctionDynamicDescriptor {
 
     private static final long serialVersionUID = 1L;
-    private final static FunctionIdentifier FID = AsterixBuiltinFunctions.SERIAL_LOCAL_SUM;
     public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
         public IFunctionDescriptor createFunctionDescriptor() {
             return new SerializableLocalSumAggregateDescriptor();
@@ -36,7 +35,7 @@
 
     @Override
     public FunctionIdentifier getIdentifier() {
-        return FID;
+        return AsterixBuiltinFunctions.SERIAL_LOCAL_SUM;
     }
 
     @Override
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableSqlAvgAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableSqlAvgAggregateDescriptor.java
new file mode 100644
index 0000000..786510b
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableSqlAvgAggregateDescriptor.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2009-2013 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.aggregates.serializable.std;
+
+import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
+import edu.uci.ics.asterix.runtime.aggregates.base.AbstractSerializableAggregateFunctionDynamicDescriptor;
+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.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopySerializableAggregateFunction;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopySerializableAggregateFunctionFactory;
+
+public class SerializableSqlAvgAggregateDescriptor extends AbstractSerializableAggregateFunctionDynamicDescriptor {
+
+    private static final long serialVersionUID = 1L;
+    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new SerializableSqlAvgAggregateDescriptor();
+        }
+    };
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return AsterixBuiltinFunctions.SERIAL_SQL_AVG;
+    }
+
+    @Override
+    public ICopySerializableAggregateFunctionFactory createSerializableAggregateFunctionFactory(
+            final ICopyEvaluatorFactory[] args) throws AlgebricksException {
+        return new ICopySerializableAggregateFunctionFactory() {
+            private static final long serialVersionUID = 1L;
+
+            public ICopySerializableAggregateFunction createAggregateFunction() throws AlgebricksException {
+                return new SerializableSqlAvgAggregateFunction(args);
+            }
+        };
+    }
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableSqlAvgAggregateFunction.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableSqlAvgAggregateFunction.java
new file mode 100644
index 0000000..c1f77a3
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableSqlAvgAggregateFunction.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2009-2013 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.aggregates.serializable.std;
+
+import java.io.DataOutput;
+
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+
+public class SerializableSqlAvgAggregateFunction extends AbstractSerializableAvgAggregateFunction {
+
+    public SerializableSqlAvgAggregateFunction(ICopyEvaluatorFactory[] args) throws AlgebricksException {
+        super(args);
+    }
+
+    @Override
+    public void step(IFrameTupleReference tuple, byte[] state, int start, int len) throws AlgebricksException {
+        processDataValues(tuple, state, start, len);
+    }
+
+    @Override
+    public void finish(byte[] state, int start, int len, DataOutput result) throws AlgebricksException {
+        finishFinalResults(state, start, len, result);
+    }
+
+    @Override
+    public void finishPartial(byte[] state, int start, int len, DataOutput result) throws AlgebricksException {
+        finish(state, start, len, result);
+    }
+
+    @Override
+    protected void processNull(byte[] state, int start) {
+    }
+
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableSqlCountAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableSqlCountAggregateDescriptor.java
new file mode 100644
index 0000000..5bfd6f2
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableSqlCountAggregateDescriptor.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2009-2013 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.aggregates.serializable.std;
+
+import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
+import edu.uci.ics.asterix.runtime.aggregates.base.AbstractSerializableAggregateFunctionDynamicDescriptor;
+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.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopySerializableAggregateFunction;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopySerializableAggregateFunctionFactory;
+
+/**
+ * count(NULL) returns NULL.
+ */
+public class SerializableSqlCountAggregateDescriptor extends AbstractSerializableAggregateFunctionDynamicDescriptor {
+
+    private static final long serialVersionUID = 1L;
+    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new SerializableSqlCountAggregateDescriptor();
+        }
+    };
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return AsterixBuiltinFunctions.SERIAL_SQL_COUNT;
+    }
+
+    @Override
+    public ICopySerializableAggregateFunctionFactory createSerializableAggregateFunctionFactory(
+            final ICopyEvaluatorFactory[] args) throws AlgebricksException {
+        return new ICopySerializableAggregateFunctionFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public ICopySerializableAggregateFunction createAggregateFunction() throws AlgebricksException {
+                return new SerializableSqlCountAggregateFunction(args);
+            }
+        };
+    }
+
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableSqlCountAggregateFunction.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableSqlCountAggregateFunction.java
new file mode 100644
index 0000000..525b643
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableSqlCountAggregateFunction.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2009-2013 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.aggregates.serializable.std;
+
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+
+/**
+ * count(NULL) returns NULL.
+ */
+public class SerializableSqlCountAggregateFunction extends AbstractSerializableCountAggregateFunction {
+    public SerializableSqlCountAggregateFunction(ICopyEvaluatorFactory[] args) throws AlgebricksException {
+        super(args);
+    }
+
+    @Override
+    protected void processNull(byte[] state, int start) {
+    }
+}
\ No newline at end of file
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableSqlSumAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableSqlSumAggregateDescriptor.java
new file mode 100644
index 0000000..c68b3b3
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableSqlSumAggregateDescriptor.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2009-2013 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.aggregates.serializable.std;
+
+import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
+import edu.uci.ics.asterix.runtime.aggregates.base.AbstractSerializableAggregateFunctionDynamicDescriptor;
+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.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopySerializableAggregateFunction;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopySerializableAggregateFunctionFactory;
+
+public class SerializableSqlSumAggregateDescriptor extends AbstractSerializableAggregateFunctionDynamicDescriptor {
+
+    private static final long serialVersionUID = 1L;
+    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new SerializableSqlSumAggregateDescriptor();
+        }
+    };
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return AsterixBuiltinFunctions.SERIAL_SQL_SUM;
+    }
+
+    @Override
+    public ICopySerializableAggregateFunctionFactory createSerializableAggregateFunctionFactory(
+            final ICopyEvaluatorFactory[] args) throws AlgebricksException {
+        return new ICopySerializableAggregateFunctionFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public ICopySerializableAggregateFunction createAggregateFunction() throws AlgebricksException {
+                return new SerializableSqlSumAggregateFunction(args, false);
+            }
+        };
+    }
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableSqlSumAggregateFunction.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableSqlSumAggregateFunction.java
new file mode 100644
index 0000000..f80ade3
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableSqlSumAggregateFunction.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2009-2013 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.aggregates.serializable.std;
+
+import java.io.DataOutput;
+import java.io.IOException;
+
+import edu.uci.ics.asterix.formats.nontagged.AqlSerializerDeserializerProvider;
+import edu.uci.ics.asterix.om.base.ANull;
+import edu.uci.ics.asterix.om.types.ATypeTag;
+import edu.uci.ics.asterix.om.types.BuiltinType;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+
+public class SerializableSqlSumAggregateFunction extends AbstractSerializableSumAggregateFunction {
+    private final boolean isLocalAgg;
+
+    public SerializableSqlSumAggregateFunction(ICopyEvaluatorFactory[] args, boolean isLocalAgg)
+            throws AlgebricksException {
+        super(args);
+        this.isLocalAgg = isLocalAgg;
+    }
+
+    @Override
+    protected void processNull(byte[] state, int start) {
+    }
+
+    @Override
+    protected void processSystemNull() throws AlgebricksException {
+        // For global aggregates simply ignore system null here,
+        // but if all input value are system null, then we should return
+        // null in finish().
+        if (isLocalAgg) {
+            throw new AlgebricksException("Type SYSTEM_NULL encountered in local aggregate.");
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    protected void finishSystemNull(DataOutput out) throws IOException {
+        // Empty stream. For local agg return system null. For global agg return null.
+        if (isLocalAgg) {
+            out.writeByte(ATypeTag.SYSTEM_NULL.serialize());
+        } else {
+            serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ANULL);
+            serde.serialize(ANull.NULL, out);
+        }
+    }
+
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableSumAggregateFunction.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableSumAggregateFunction.java
index bea6ab8..15e546a 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableSumAggregateFunction.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/serializable/std/SerializableSumAggregateFunction.java
@@ -17,196 +17,54 @@
 import java.io.DataOutput;
 import java.io.IOException;
 
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.ADoubleSerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AFloatSerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt16SerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt32SerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt64SerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt8SerializerDeserializer;
 import edu.uci.ics.asterix.formats.nontagged.AqlSerializerDeserializerProvider;
-import edu.uci.ics.asterix.om.base.AMutableDouble;
-import edu.uci.ics.asterix.om.base.AMutableFloat;
-import edu.uci.ics.asterix.om.base.AMutableInt16;
-import edu.uci.ics.asterix.om.base.AMutableInt32;
-import edu.uci.ics.asterix.om.base.AMutableInt64;
-import edu.uci.ics.asterix.om.base.AMutableInt8;
 import edu.uci.ics.asterix.om.base.ANull;
 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.hyracks.algebricks.common.exceptions.AlgebricksException;
-import edu.uci.ics.hyracks.algebricks.common.exceptions.NotImplementedException;
-import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluator;
 import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
-import edu.uci.ics.hyracks.algebricks.runtime.base.ICopySerializableAggregateFunction;
-import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
-import edu.uci.ics.hyracks.data.std.util.ArrayBackedValueStorage;
-import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
 
-public class SerializableSumAggregateFunction implements ICopySerializableAggregateFunction {
-    private ArrayBackedValueStorage inputVal = new ArrayBackedValueStorage();
-    private ICopyEvaluator eval;
-    private AMutableDouble aDouble = new AMutableDouble(0);
-    private AMutableFloat aFloat = new AMutableFloat(0);
-    private AMutableInt64 aInt64 = new AMutableInt64(0);
-    private AMutableInt32 aInt32 = new AMutableInt32(0);
-    private AMutableInt16 aInt16 = new AMutableInt16((short) 0);
-    private AMutableInt8 aInt8 = new AMutableInt8((byte) 0);
-    @SuppressWarnings("rawtypes")
-    private ISerializerDeserializer serde;
+public class SerializableSumAggregateFunction extends AbstractSerializableSumAggregateFunction {
     private final boolean isLocalAgg;
 
     public SerializableSumAggregateFunction(ICopyEvaluatorFactory[] args, boolean isLocalAgg)
             throws AlgebricksException {
-        eval = args[0].createEvaluator(inputVal);
+        super(args);
         this.isLocalAgg = isLocalAgg;
     }
 
-    @Override
-    public void init(DataOutput state) throws AlgebricksException {
-        try {
-            state.writeByte(ATypeTag.SYSTEM_NULL.serialize());
-            state.writeDouble(0.0);
-        } catch (IOException e) {
-            throw new AlgebricksException(e);
-        }
+    protected void processNull(byte[] state, int start) {
+        ATypeTag aggType = ATypeTag.NULL;
+        state[start + AGG_TYPE_OFFSET] = aggType.serialize();
     }
 
     @Override
-    public void step(IFrameTupleReference tuple, byte[] state, int start, int len) throws AlgebricksException {
-        ATypeTag aggType = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(state[start]);
-        double sum = BufferSerDeUtil.getDouble(state, start + 1);
-        inputVal.reset();
-        eval.evaluate(tuple);
-        ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(inputVal.getByteArray()[0]);
-        if (typeTag == ATypeTag.NULL || aggType == ATypeTag.NULL) {
-            aggType = ATypeTag.NULL;
-            return;
-        } else if (aggType == ATypeTag.SYSTEM_NULL) {
-            aggType = typeTag;
-        } else if (typeTag != ATypeTag.SYSTEM_NULL && typeTag != aggType) {
-            throw new AlgebricksException("Unexpected type " + typeTag + " in aggregation input stream. Expected type "
-                    + aggType + ".");
+    protected boolean skipStep(byte[] state, int start) {
+        ATypeTag aggType = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(state[start + AGG_TYPE_OFFSET]);
+        return (aggType == ATypeTag.NULL);
+    }
+
+    @Override
+    protected void processSystemNull() throws AlgebricksException {
+        // For global aggregates simply ignore system null here,
+        // but if all input value are system null, then we should return
+        // null in finish().
+        if (isLocalAgg) {
+            throw new AlgebricksException("Type SYSTEM_NULL encountered in local aggregate.");
         }
-        switch (typeTag) {
-            case INT8: {
-                byte val = AInt8SerializerDeserializer.getByte(inputVal.getByteArray(), 1);
-                sum += val;
-                break;
-            }
-            case INT16: {
-                short val = AInt16SerializerDeserializer.getShort(inputVal.getByteArray(), 1);
-                sum += val;
-                break;
-            }
-            case INT32: {
-                int val = AInt32SerializerDeserializer.getInt(inputVal.getByteArray(), 1);
-                sum += val;
-                break;
-            }
-            case INT64: {
-                long val = AInt64SerializerDeserializer.getLong(inputVal.getByteArray(), 1);
-                sum += val;
-                break;
-            }
-            case FLOAT: {
-                float val = AFloatSerializerDeserializer.getFloat(inputVal.getByteArray(), 1);
-                sum += val;
-                break;
-            }
-            case DOUBLE: {
-                double val = ADoubleSerializerDeserializer.getDouble(inputVal.getByteArray(), 1);
-                sum += val;
-                break;
-            }
-            case NULL: {
-                aggType = typeTag;
-                break;
-            }
-            case SYSTEM_NULL: {
-                // For global aggregates simply ignore system null here,
-                // but if all input value are system null, then we should return
-                // null in finish().
-                if (isLocalAgg) {
-                    throw new AlgebricksException("Type SYSTEM_NULL encountered in local aggregate.");
-                }
-                break;
-            }
-            default: {
-                throw new NotImplementedException("Cannot compute SUM for values of type " + typeTag + ".");
-            }
-        }
-        state[start] = aggType.serialize();
-        BufferSerDeUtil.writeDouble(sum, state, start + 1);
     }
 
     @SuppressWarnings("unchecked")
     @Override
-    public void finish(byte[] state, int start, int len, DataOutput out) throws AlgebricksException {
-        ATypeTag aggType = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(state[start]);
-        double sum = BufferSerDeUtil.getDouble(state, start + 1);
-        try {
-            switch (aggType) {
-                case INT8: {
-                    serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AINT8);
-                    aInt8.setValue((byte) sum);
-                    serde.serialize(aInt8, out);
-                    break;
-                }
-                case INT16: {
-                    serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AINT16);
-                    aInt16.setValue((short) sum);
-                    serde.serialize(aInt16, out);
-                    break;
-                }
-                case INT32: {
-                    serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AINT32);
-                    aInt32.setValue((int) sum);
-                    serde.serialize(aInt32, out);
-                    break;
-                }
-                case INT64: {
-                    serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AINT64);
-                    aInt64.setValue((long) sum);
-                    serde.serialize(aInt64, out);
-                    break;
-                }
-                case FLOAT: {
-                    serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AFLOAT);
-                    aFloat.setValue((float) sum);
-                    serde.serialize(aFloat, out);
-                    break;
-                }
-                case DOUBLE: {
-                    serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ADOUBLE);
-                    aDouble.setValue(sum);
-                    serde.serialize(aDouble, out);
-                    break;
-                }
-                case NULL: {
-                    serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ANULL);
-                    serde.serialize(ANull.NULL, out);
-                    break;
-                }
-                case SYSTEM_NULL: {
-                    // Empty stream. For local agg return system null. For global agg return null.
-                    if (isLocalAgg) {
-                        out.writeByte(ATypeTag.SYSTEM_NULL.serialize());
-                    } else {
-                        serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ANULL);
-                        serde.serialize(ANull.NULL, out);
-                    }
-                    break;
-                }
-            }
-        } catch (IOException e) {
-            throw new AlgebricksException(e);
+    protected void finishSystemNull(DataOutput out) throws IOException {
+        // Empty stream. For local agg return system null. For global agg return null.
+        if (isLocalAgg) {
+            out.writeByte(ATypeTag.SYSTEM_NULL.serialize());
+        } else {
+            serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ANULL);
+            serde.serialize(ANull.NULL, out);
         }
-
     }
 
-    @Override
-    public void finishPartial(byte[] state, int start, int len, DataOutput out) throws AlgebricksException {
-        finish(state, start, len, out);
-    }
 }
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/AbstractAvgAggregateFunction.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/AbstractAvgAggregateFunction.java
new file mode 100644
index 0000000..cfc5f1c
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/AbstractAvgAggregateFunction.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright 2009-2013 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.aggregates.std;
+
+import java.io.DataOutput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import edu.uci.ics.asterix.common.config.GlobalConfig;
+import edu.uci.ics.asterix.common.exceptions.AsterixException;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.ADoubleSerializerDeserializer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AFloatSerializerDeserializer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt16SerializerDeserializer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt32SerializerDeserializer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt64SerializerDeserializer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt8SerializerDeserializer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.ARecordSerializerDeserializer;
+import edu.uci.ics.asterix.formats.nontagged.AqlSerializerDeserializerProvider;
+import edu.uci.ics.asterix.om.base.ADouble;
+import edu.uci.ics.asterix.om.base.AInt64;
+import edu.uci.ics.asterix.om.base.AMutableDouble;
+import edu.uci.ics.asterix.om.base.AMutableInt64;
+import edu.uci.ics.asterix.om.base.ANull;
+import edu.uci.ics.asterix.om.types.ARecordType;
+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.types.IAType;
+import edu.uci.ics.asterix.om.types.hierachy.ATypeHierarchy;
+import edu.uci.ics.asterix.runtime.evaluators.common.AccessibleByteArrayEval;
+import edu.uci.ics.asterix.runtime.evaluators.common.ClosedRecordConstructorEvalFactory.ClosedRecordConstructorEval;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.NotImplementedException;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyAggregateFunction;
+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;
+import edu.uci.ics.hyracks.data.std.api.IDataOutputProvider;
+import edu.uci.ics.hyracks.data.std.util.ArrayBackedValueStorage;
+import edu.uci.ics.hyracks.data.std.util.ByteArrayAccessibleOutputStream;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+
+public abstract class AbstractAvgAggregateFunction implements ICopyAggregateFunction {
+    private static final int SUM_FIELD_ID = 0;
+    private static final int COUNT_FIELD_ID = 1;
+
+    private final ARecordType recType;
+
+    private DataOutput out;
+    private ArrayBackedValueStorage inputVal = new ArrayBackedValueStorage();
+    private ICopyEvaluator eval;
+    protected ATypeTag aggType;
+    private double sum;
+    private long count;
+    private AMutableDouble aDouble = new AMutableDouble(0);
+    private AMutableInt64 aInt64 = new AMutableInt64(0);
+
+    private ArrayBackedValueStorage avgBytes = new ArrayBackedValueStorage();
+    private ByteArrayAccessibleOutputStream sumBytes = new ByteArrayAccessibleOutputStream();
+    private DataOutput sumBytesOutput = new DataOutputStream(sumBytes);
+    private ByteArrayAccessibleOutputStream countBytes = new ByteArrayAccessibleOutputStream();
+    private DataOutput countBytesOutput = new DataOutputStream(countBytes);
+    private ICopyEvaluator evalSum = new AccessibleByteArrayEval(avgBytes.getDataOutput(), sumBytes);
+    private ICopyEvaluator evalCount = new AccessibleByteArrayEval(avgBytes.getDataOutput(), countBytes);
+    private ClosedRecordConstructorEval recordEval;
+
+    @SuppressWarnings("unchecked")
+    private ISerializerDeserializer<ADouble> doubleSerde = AqlSerializerDeserializerProvider.INSTANCE
+            .getSerializerDeserializer(BuiltinType.ADOUBLE);
+    @SuppressWarnings("unchecked")
+    private ISerializerDeserializer<AInt64> longSerde = AqlSerializerDeserializerProvider.INSTANCE
+            .getSerializerDeserializer(BuiltinType.AINT64);
+    @SuppressWarnings("unchecked")
+    private ISerializerDeserializer<ANull> nullSerde = AqlSerializerDeserializerProvider.INSTANCE
+            .getSerializerDeserializer(BuiltinType.ANULL);
+
+    public AbstractAvgAggregateFunction(ICopyEvaluatorFactory[] args, IDataOutputProvider output)
+            throws AlgebricksException {
+        eval = args[0].createEvaluator(inputVal);
+        out = output.getDataOutput();
+
+        ARecordType tmpRecType;
+        try {
+            tmpRecType = new ARecordType(null, new String[] { "sum", "count" }, new IAType[] { BuiltinType.ADOUBLE,
+                    BuiltinType.AINT64 }, false);
+        } catch (AsterixException e) {
+            throw new AlgebricksException(e);
+        }
+
+        recType = tmpRecType;
+        recordEval = new ClosedRecordConstructorEval(recType, new ICopyEvaluator[] { evalSum, evalCount }, avgBytes,
+                out);
+    }
+
+    @Override
+    public void init() {
+        aggType = ATypeTag.SYSTEM_NULL;
+        sum = 0.0;
+        count = 0;
+    }
+
+    public abstract void step(IFrameTupleReference tuple) throws AlgebricksException;
+
+    public abstract void finish() throws AlgebricksException;
+
+    public abstract void finishPartial() throws AlgebricksException;
+
+    protected abstract void processNull();
+
+    protected void processDataValues(IFrameTupleReference tuple) throws AlgebricksException {
+        if (skipStep()) {
+            return;
+        }
+        inputVal.reset();
+        eval.evaluate(tuple);
+        ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(inputVal.getByteArray()[0]);
+        if (typeTag == ATypeTag.NULL) {
+            processNull();
+            return;
+        } else if (aggType == ATypeTag.SYSTEM_NULL) {
+            aggType = typeTag;
+        } else if (typeTag != ATypeTag.SYSTEM_NULL && !ATypeHierarchy.isCompatible(typeTag, aggType)) {
+            throw new AlgebricksException("Unexpected type " + typeTag + " in aggregation input stream. Expected type "
+                    + aggType + ".");
+        } else if (ATypeHierarchy.canPromote(aggType, typeTag)) {
+            aggType = typeTag;
+        }
+        ++count;
+        switch (typeTag) {
+            case INT8: {
+                byte val = AInt8SerializerDeserializer.getByte(inputVal.getByteArray(), 1);
+                sum += val;
+                break;
+            }
+            case INT16: {
+                short val = AInt16SerializerDeserializer.getShort(inputVal.getByteArray(), 1);
+                sum += val;
+                break;
+            }
+            case INT32: {
+                int val = AInt32SerializerDeserializer.getInt(inputVal.getByteArray(), 1);
+                sum += val;
+                break;
+            }
+            case INT64: {
+                long val = AInt64SerializerDeserializer.getLong(inputVal.getByteArray(), 1);
+                sum += val;
+                break;
+            }
+            case FLOAT: {
+                float val = AFloatSerializerDeserializer.getFloat(inputVal.getByteArray(), 1);
+                sum += val;
+                break;
+            }
+            case DOUBLE: {
+                double val = ADoubleSerializerDeserializer.getDouble(inputVal.getByteArray(), 1);
+                sum += val;
+                break;
+            }
+            default: {
+                throw new NotImplementedException("Cannot compute AVG for values of type " + typeTag);
+            }
+        }
+        inputVal.reset();
+    }
+
+    protected void finishPartialResults() throws AlgebricksException {
+        try {
+            // Double check that count 0 is accounted
+            if (aggType == ATypeTag.SYSTEM_NULL) {
+                if (GlobalConfig.DEBUG) {
+                    GlobalConfig.ASTERIX_LOGGER.finest("AVG aggregate ran over empty input.");
+                }
+                out.writeByte(ATypeTag.SYSTEM_NULL.serialize());
+            } else if (aggType == ATypeTag.NULL) {
+                out.writeByte(ATypeTag.NULL.serialize());
+            } else {
+                sumBytes.reset();
+                aDouble.setValue(sum);
+                doubleSerde.serialize(aDouble, sumBytesOutput);
+                countBytes.reset();
+                aInt64.setValue(count);
+                longSerde.serialize(aInt64, countBytesOutput);
+                recordEval.evaluate(null);
+            }
+        } catch (IOException e) {
+            throw new AlgebricksException(e);
+        }
+    }
+
+    protected void processPartialResults(IFrameTupleReference tuple) throws AlgebricksException {
+        if (skipStep()) {
+            return;
+        }
+        inputVal.reset();
+        eval.evaluate(tuple);
+        byte[] serBytes = inputVal.getByteArray();
+        ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(serBytes[0]);
+        switch (typeTag) {
+            case NULL: {
+                processNull();
+                break;
+            }
+            case SYSTEM_NULL: {
+                // Ignore and return.
+                break;
+            }
+            case RECORD: {
+                // Expected.
+                int nullBitmapSize = 0;
+                int offset1 = ARecordSerializerDeserializer.getFieldOffsetById(serBytes, SUM_FIELD_ID, nullBitmapSize,
+                        false);
+                sum += ADoubleSerializerDeserializer.getDouble(serBytes, offset1);
+                int offset2 = ARecordSerializerDeserializer.getFieldOffsetById(serBytes, COUNT_FIELD_ID,
+                        nullBitmapSize, false);
+                count += AInt64SerializerDeserializer.getLong(serBytes, offset2);
+                break;
+            }
+            default: {
+                throw new AlgebricksException("Global-Avg is not defined for values of type "
+                        + EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(serBytes[0]));
+            }
+        }
+    }
+
+    protected void finishFinalResults() throws AlgebricksException {
+        try {
+            if (count == 0 || aggType == ATypeTag.NULL) {
+                nullSerde.serialize(ANull.NULL, out);
+            } else {
+                aDouble.setValue(sum / count);
+                doubleSerde.serialize(aDouble, out);
+            }
+        } catch (IOException e) {
+            throw new AlgebricksException(e);
+        }
+    }
+
+    protected boolean skipStep() {
+        return false;
+    }
+
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/AbstractCountAggregateFunction.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/AbstractCountAggregateFunction.java
new file mode 100644
index 0000000..29e57f5
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/AbstractCountAggregateFunction.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2009-2013 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.aggregates.std;
+
+import java.io.DataOutput;
+import java.io.IOException;
+
+import edu.uci.ics.asterix.formats.nontagged.AqlSerializerDeserializerProvider;
+import edu.uci.ics.asterix.om.base.AInt64;
+import edu.uci.ics.asterix.om.base.AMutableInt64;
+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.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyAggregateFunction;
+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;
+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;
+
+/**
+ * COUNT returns the number of items in the given list. Note that COUNT(NULL) is not allowed.
+ */
+public abstract class AbstractCountAggregateFunction implements ICopyAggregateFunction {
+    private AMutableInt64 result = new AMutableInt64(-1);
+    @SuppressWarnings("unchecked")
+    private ISerializerDeserializer<AInt64> int64Serde = AqlSerializerDeserializerProvider.INSTANCE
+            .getSerializerDeserializer(BuiltinType.AINT64);
+    private ArrayBackedValueStorage inputVal = new ArrayBackedValueStorage();
+    private ICopyEvaluator eval;
+    protected long cnt;
+    private DataOutput out;
+
+    public AbstractCountAggregateFunction(ICopyEvaluatorFactory[] args, IDataOutputProvider output)
+            throws AlgebricksException {
+        eval = args[0].createEvaluator(inputVal);
+        out = output.getDataOutput();
+    }
+
+    @Override
+    public void init() {
+        cnt = 0;
+    }
+
+    @Override
+    public void step(IFrameTupleReference tuple) throws AlgebricksException {
+        inputVal.reset();
+        eval.evaluate(tuple);
+        ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(inputVal.getByteArray()[0]);
+        // Ignore SYSTEM_NULL.
+        if (typeTag == ATypeTag.NULL) {
+            processNull();
+        } else if (typeTag != ATypeTag.SYSTEM_NULL) {
+            cnt++;
+        }
+    }
+
+    @Override
+    public void finish() throws AlgebricksException {
+        try {
+            result.setValue(cnt);
+            int64Serde.serialize(result, out);
+        } catch (IOException e) {
+            throw new AlgebricksException(e);
+        }
+    }
+
+    @Override
+    public void finishPartial() throws AlgebricksException {
+        finish();
+    }
+
+    protected abstract void processNull();
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/AbstractMinMaxAggregateFunction.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/AbstractMinMaxAggregateFunction.java
new file mode 100644
index 0000000..29aba33
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/AbstractMinMaxAggregateFunction.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2009-2013 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.aggregates.std;
+
+import java.io.DataOutput;
+import java.io.IOException;
+
+import edu.uci.ics.asterix.formats.nontagged.AqlBinaryComparatorFactoryProvider;
+import edu.uci.ics.asterix.om.types.ATypeTag;
+import edu.uci.ics.asterix.om.types.EnumDeserializer;
+import edu.uci.ics.asterix.om.types.hierachy.ATypeHierarchy;
+import edu.uci.ics.asterix.om.types.hierachy.ITypePromoteComputer;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyAggregateFunction;
+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.IBinaryComparator;
+import edu.uci.ics.hyracks.api.dataflow.value.IBinaryComparatorFactory;
+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;
+
+public abstract class AbstractMinMaxAggregateFunction implements ICopyAggregateFunction {
+    private ArrayBackedValueStorage inputVal = new ArrayBackedValueStorage();
+    private ArrayBackedValueStorage outputVal = new ArrayBackedValueStorage();
+    private ArrayBackedValueStorage tempValForCasting = new ArrayBackedValueStorage();
+    protected DataOutput out;
+    private ICopyEvaluator eval;
+    protected ATypeTag aggType;
+    private IBinaryComparator cmp;
+    private ITypePromoteComputer tpc;
+    private final boolean isMin;
+
+    public AbstractMinMaxAggregateFunction(ICopyEvaluatorFactory[] args, IDataOutputProvider provider, boolean isMin)
+            throws AlgebricksException {
+        out = provider.getDataOutput();
+        eval = args[0].createEvaluator(inputVal);
+        this.isMin = isMin;
+    }
+
+    @Override
+    public void init() {
+        aggType = ATypeTag.SYSTEM_NULL;
+        outputVal.reset();
+        tempValForCasting.reset();
+    }
+
+    @Override
+    public void step(IFrameTupleReference tuple) throws AlgebricksException {
+        inputVal.reset();
+        eval.evaluate(tuple);
+        ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(inputVal.getByteArray()[0]);
+        if (typeTag == ATypeTag.NULL) {
+            processNull();
+            return;
+        } else if (aggType == ATypeTag.NULL) {
+            return;
+        } else if (aggType == ATypeTag.SYSTEM_NULL) {
+            if (typeTag == ATypeTag.SYSTEM_NULL) {
+                // Ignore.
+                return;
+            }
+            // First value encountered. Set type, comparator, and initial value.
+            aggType = typeTag;
+            // Set comparator.
+            IBinaryComparatorFactory cmpFactory = AqlBinaryComparatorFactoryProvider.INSTANCE
+                    .getBinaryComparatorFactory(aggType, isMin);
+            cmp = cmpFactory.createBinaryComparator();
+            // Initialize min value.
+            outputVal.assign(inputVal);
+        } else if (typeTag != ATypeTag.SYSTEM_NULL && !ATypeHierarchy.isCompatible(typeTag, aggType)) {
+            throw new AlgebricksException("Unexpected type " + typeTag + " in aggregation input stream. Expected type "
+                    + aggType + ".");
+        } else {
+
+            // If a system_null is encountered locally, it would be an error; otherwise if it is seen
+            // by a global aggregator, it is simple ignored.
+            if (typeTag == ATypeTag.SYSTEM_NULL) {
+                processSystemNull();
+                return;
+            }
+
+            if (ATypeHierarchy.canPromote(aggType, typeTag)) {
+                tpc = ATypeHierarchy.getTypePromoteComputer(aggType, typeTag);
+                aggType = typeTag;
+                cmp = AqlBinaryComparatorFactoryProvider.INSTANCE.getBinaryComparatorFactory(aggType, isMin)
+                        .createBinaryComparator();
+                if (tpc != null) {
+                    tempValForCasting.reset();
+                    try {
+                        tpc.promote(outputVal.getByteArray(), outputVal.getStartOffset() + 1,
+                                outputVal.getLength() - 1, tempValForCasting);
+                    } catch (IOException e) {
+                        throw new AlgebricksException(e);
+                    }
+                    outputVal.reset();
+                    outputVal.assign(tempValForCasting);
+                }
+                if (cmp.compare(inputVal.getByteArray(), inputVal.getStartOffset(), inputVal.getLength(),
+                        outputVal.getByteArray(), outputVal.getStartOffset(), outputVal.getLength()) < 0) {
+                    outputVal.assign(inputVal);
+                }
+
+            } else {
+                tpc = ATypeHierarchy.getTypePromoteComputer(typeTag, aggType);
+                if (tpc != null) {
+                    tempValForCasting.reset();
+                    try {
+                        tpc.promote(inputVal.getByteArray(), inputVal.getStartOffset() + 1, inputVal.getLength() - 1,
+                                tempValForCasting);
+                    } catch (IOException e) {
+                        throw new AlgebricksException(e);
+                    }
+                    if (cmp.compare(tempValForCasting.getByteArray(), tempValForCasting.getStartOffset(),
+                            tempValForCasting.getLength(), outputVal.getByteArray(), outputVal.getStartOffset(),
+                            outputVal.getLength()) < 0) {
+                        outputVal.assign(tempValForCasting);
+                    }
+                } else {
+                    if (cmp.compare(inputVal.getByteArray(), inputVal.getStartOffset(), inputVal.getLength(),
+                            outputVal.getByteArray(), outputVal.getStartOffset(), outputVal.getLength()) < 0) {
+                        outputVal.assign(inputVal);
+                    }
+                }
+
+            }
+        }
+    }
+
+    @Override
+    public void finish() throws AlgebricksException {
+        try {
+            switch (aggType) {
+                case NULL: {
+                    out.writeByte(ATypeTag.NULL.serialize());
+                    break;
+                }
+                case SYSTEM_NULL: {
+                    finishSystemNull();
+                    break;
+                }
+                default: {
+                    out.write(outputVal.getByteArray(), outputVal.getStartOffset(), outputVal.getLength());
+                    break;
+                }
+            }
+        } catch (IOException e) {
+            throw new AlgebricksException(e);
+        }
+    }
+
+    @Override
+    public void finishPartial() throws AlgebricksException {
+        finish();
+    }
+
+    protected boolean skipStep() {
+        return false;
+    }
+
+    protected abstract void processNull();
+
+    protected abstract void processSystemNull() throws AlgebricksException;
+
+    protected abstract void finishSystemNull() throws IOException;
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/AbstractSumAggregateFunction.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/AbstractSumAggregateFunction.java
new file mode 100644
index 0000000..1332dd5
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/AbstractSumAggregateFunction.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2009-2013 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.aggregates.std;
+
+import java.io.DataOutput;
+import java.io.IOException;
+
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.ADoubleSerializerDeserializer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AFloatSerializerDeserializer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt16SerializerDeserializer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt32SerializerDeserializer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt64SerializerDeserializer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt8SerializerDeserializer;
+import edu.uci.ics.asterix.formats.nontagged.AqlSerializerDeserializerProvider;
+import edu.uci.ics.asterix.om.base.AMutableDouble;
+import edu.uci.ics.asterix.om.base.AMutableFloat;
+import edu.uci.ics.asterix.om.base.AMutableInt16;
+import edu.uci.ics.asterix.om.base.AMutableInt32;
+import edu.uci.ics.asterix.om.base.AMutableInt64;
+import edu.uci.ics.asterix.om.base.AMutableInt8;
+import edu.uci.ics.asterix.om.base.ANull;
+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.types.hierachy.ATypeHierarchy;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.NotImplementedException;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyAggregateFunction;
+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;
+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;
+
+public abstract class AbstractSumAggregateFunction implements ICopyAggregateFunction {
+    protected DataOutput out;
+    private ArrayBackedValueStorage inputVal = new ArrayBackedValueStorage();
+    private ICopyEvaluator eval;
+    private double sum;
+    protected ATypeTag aggType;
+    private AMutableDouble aDouble = new AMutableDouble(0);
+    private AMutableFloat aFloat = new AMutableFloat(0);
+    private AMutableInt64 aInt64 = new AMutableInt64(0);
+    private AMutableInt32 aInt32 = new AMutableInt32(0);
+    private AMutableInt16 aInt16 = new AMutableInt16((short) 0);
+    private AMutableInt8 aInt8 = new AMutableInt8((byte) 0);
+    @SuppressWarnings("rawtypes")
+    protected ISerializerDeserializer serde;
+
+    public AbstractSumAggregateFunction(ICopyEvaluatorFactory[] args, IDataOutputProvider provider)
+            throws AlgebricksException {
+        out = provider.getDataOutput();
+        eval = args[0].createEvaluator(inputVal);
+    }
+
+    @Override
+    public void init() {
+        aggType = ATypeTag.SYSTEM_NULL;
+        sum = 0.0;
+    }
+
+    @Override
+    public void step(IFrameTupleReference tuple) throws AlgebricksException {
+        if (skipStep()) {
+            return;
+        }
+        inputVal.reset();
+        eval.evaluate(tuple);
+        ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(inputVal.getByteArray()[0]);
+        if (typeTag == ATypeTag.NULL) {
+            processNull();
+            return;
+        } else if (aggType == ATypeTag.SYSTEM_NULL) {
+            aggType = typeTag;
+        } else if (typeTag != ATypeTag.SYSTEM_NULL && !ATypeHierarchy.isCompatible(typeTag, aggType)) {
+            throw new AlgebricksException("Unexpected type " + typeTag
+                    + " in aggregation input stream. Expected type (or a promotable type to)" + aggType + ".");
+        }
+
+        if (ATypeHierarchy.canPromote(aggType, typeTag)) {
+            aggType = typeTag;
+        }
+
+        switch (typeTag) {
+            case INT8: {
+                byte val = AInt8SerializerDeserializer.getByte(inputVal.getByteArray(), 1);
+                sum += val;
+                break;
+            }
+            case INT16: {
+                short val = AInt16SerializerDeserializer.getShort(inputVal.getByteArray(), 1);
+                sum += val;
+                break;
+            }
+            case INT32: {
+                int val = AInt32SerializerDeserializer.getInt(inputVal.getByteArray(), 1);
+                sum += val;
+                break;
+            }
+            case INT64: {
+                long val = AInt64SerializerDeserializer.getLong(inputVal.getByteArray(), 1);
+                sum += val;
+                break;
+            }
+            case FLOAT: {
+                float val = AFloatSerializerDeserializer.getFloat(inputVal.getByteArray(), 1);
+                sum += val;
+                break;
+            }
+            case DOUBLE: {
+                double val = ADoubleSerializerDeserializer.getDouble(inputVal.getByteArray(), 1);
+                sum += val;
+                break;
+            }
+            case NULL: {
+                break;
+            }
+            case SYSTEM_NULL: {
+                processSystemNull();
+                break;
+            }
+            default: {
+                throw new NotImplementedException("Cannot compute SUM for values of type " + typeTag + ".");
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public void finish() throws AlgebricksException {
+        try {
+            switch (aggType) {
+                case INT8: {
+                    serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AINT8);
+                    aInt8.setValue((byte) sum);
+                    serde.serialize(aInt8, out);
+                    break;
+                }
+                case INT16: {
+                    serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AINT16);
+                    aInt16.setValue((short) sum);
+                    serde.serialize(aInt16, out);
+                    break;
+                }
+                case INT32: {
+                    serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AINT32);
+                    aInt32.setValue((int) sum);
+                    serde.serialize(aInt32, out);
+                    break;
+                }
+                case INT64: {
+                    serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AINT64);
+                    aInt64.setValue((long) sum);
+                    serde.serialize(aInt64, out);
+                    break;
+                }
+                case FLOAT: {
+                    serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AFLOAT);
+                    aFloat.setValue((float) sum);
+                    serde.serialize(aFloat, out);
+                    break;
+                }
+                case DOUBLE: {
+                    serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ADOUBLE);
+                    aDouble.setValue(sum);
+                    serde.serialize(aDouble, out);
+                    break;
+                }
+                case NULL: {
+                    serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ANULL);
+                    serde.serialize(ANull.NULL, out);
+                    break;
+                }
+                case SYSTEM_NULL: {
+                    finishSystemNull();
+                    break;
+                }
+                default:
+                    throw new AlgebricksException("SumAggregationFunction: incompatible type for the result ("
+                            + aggType + "). ");
+            }
+        } catch (IOException e) {
+            throw new AlgebricksException(e);
+        }
+    }
+
+    @Override
+    public void finishPartial() throws AlgebricksException {
+        finish();
+    }
+
+    protected boolean skipStep() {
+        return false;
+    }
+    protected abstract void processNull();
+    protected abstract void processSystemNull() throws AlgebricksException;
+    protected abstract void finishSystemNull() throws IOException;
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/AvgAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/AvgAggregateDescriptor.java
index 7815606..3ff836a 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/AvgAggregateDescriptor.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/AvgAggregateDescriptor.java
@@ -15,51 +15,16 @@
 
 package edu.uci.ics.asterix.runtime.aggregates.std;
 
-import java.io.DataOutput;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import edu.uci.ics.asterix.common.config.GlobalConfig;
-import edu.uci.ics.asterix.common.exceptions.AsterixException;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.ADoubleSerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AFloatSerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt16SerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt32SerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt64SerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt8SerializerDeserializer;
-import edu.uci.ics.asterix.formats.nontagged.AqlSerializerDeserializerProvider;
-import edu.uci.ics.asterix.om.base.ADouble;
-import edu.uci.ics.asterix.om.base.AInt64;
-import edu.uci.ics.asterix.om.base.AMutableDouble;
-import edu.uci.ics.asterix.om.base.AMutableInt64;
-import edu.uci.ics.asterix.om.base.ANull;
 import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
 import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
 import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
-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.BuiltinType;
-import edu.uci.ics.asterix.om.types.EnumDeserializer;
-import edu.uci.ics.asterix.om.types.IAType;
-import edu.uci.ics.asterix.om.types.hierachy.ATypeHierarchy;
 import edu.uci.ics.asterix.runtime.aggregates.base.AbstractAggregateFunctionDynamicDescriptor;
-import edu.uci.ics.asterix.runtime.evaluators.common.AccessibleByteArrayEval;
-import edu.uci.ics.asterix.runtime.evaluators.common.ClosedRecordConstructorEvalFactory.ClosedRecordConstructorEval;
 import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
-import edu.uci.ics.hyracks.algebricks.common.exceptions.NotImplementedException;
 import edu.uci.ics.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
 import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyAggregateFunction;
 import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyAggregateFunctionFactory;
-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;
 import edu.uci.ics.hyracks.data.std.api.IDataOutputProvider;
-import edu.uci.ics.hyracks.data.std.util.ArrayBackedValueStorage;
-import edu.uci.ics.hyracks.data.std.util.ByteArrayAccessibleOutputStream;
-import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
 
 public class AvgAggregateDescriptor extends AbstractAggregateFunctionDynamicDescriptor {
 
@@ -78,165 +43,13 @@
     @Override
     public ICopyAggregateFunctionFactory createAggregateFunctionFactory(final ICopyEvaluatorFactory[] args)
             throws AlgebricksException {
-        List<IAType> unionList = new ArrayList<IAType>();
-        unionList.add(BuiltinType.ANULL);
-        unionList.add(BuiltinType.ADOUBLE);
-        ARecordType tmpRecType;
-        try {
-            tmpRecType = new ARecordType(null, new String[] { "sum", "count" }, new IAType[] {
-                    new AUnionType(unionList, "OptionalDouble"), BuiltinType.AINT64 }, true);
-        } catch (AsterixException e) {
-            throw new AlgebricksException(e);
-        }
-
-        final ARecordType recType = tmpRecType;
-
         return new ICopyAggregateFunctionFactory() {
             private static final long serialVersionUID = 1L;
 
             @Override
             public ICopyAggregateFunction createAggregateFunction(final IDataOutputProvider provider)
                     throws AlgebricksException {
-
-                return new ICopyAggregateFunction() {
-
-                    private DataOutput out = provider.getDataOutput();
-                    private ArrayBackedValueStorage inputVal = new ArrayBackedValueStorage();
-                    private ICopyEvaluator eval = args[0].createEvaluator(inputVal);
-                    private double sum;
-                    private long count;
-                    private ATypeTag aggType;
-                    private AMutableDouble aDouble = new AMutableDouble(0);
-                    private AMutableInt64 aInt64 = new AMutableInt64(0);
-
-                    private ArrayBackedValueStorage avgBytes = new ArrayBackedValueStorage();
-                    private ByteArrayAccessibleOutputStream sumBytes = new ByteArrayAccessibleOutputStream();
-                    private DataOutput sumBytesOutput = new DataOutputStream(sumBytes);
-                    private ByteArrayAccessibleOutputStream countBytes = new ByteArrayAccessibleOutputStream();
-                    private DataOutput countBytesOutput = new DataOutputStream(countBytes);
-                    private ICopyEvaluator evalSum = new AccessibleByteArrayEval(avgBytes.getDataOutput(), sumBytes);
-                    private ICopyEvaluator evalCount = new AccessibleByteArrayEval(avgBytes.getDataOutput(), countBytes);
-                    private ClosedRecordConstructorEval recordEval = new ClosedRecordConstructorEval(recType,
-                            new ICopyEvaluator[] { evalSum, evalCount }, avgBytes, out);
-
-                    @SuppressWarnings("unchecked")
-                    private ISerializerDeserializer<ADouble> doubleSerde = AqlSerializerDeserializerProvider.INSTANCE
-                            .getSerializerDeserializer(BuiltinType.ADOUBLE);
-                    @SuppressWarnings("unchecked")
-                    private ISerializerDeserializer<AInt64> intSerde = AqlSerializerDeserializerProvider.INSTANCE
-                            .getSerializerDeserializer(BuiltinType.AINT64);
-                    @SuppressWarnings("unchecked")
-                    private ISerializerDeserializer<ANull> nullSerde = AqlSerializerDeserializerProvider.INSTANCE
-                            .getSerializerDeserializer(BuiltinType.ANULL);
-
-                    @Override
-                    public void init() throws AlgebricksException {
-                        aggType = ATypeTag.SYSTEM_NULL;
-                        sum = 0.0;
-                        count = 0;
-                    }
-
-                    @Override
-                    public void step(IFrameTupleReference tuple) throws AlgebricksException {
-                        inputVal.reset();
-                        eval.evaluate(tuple);
-                        ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER
-                                .deserialize(inputVal.getByteArray()[0]);
-                        if (typeTag == ATypeTag.NULL || aggType == ATypeTag.NULL) {
-                            aggType = ATypeTag.NULL;
-                            return;
-                        } else if (aggType == ATypeTag.SYSTEM_NULL) {
-                            aggType = typeTag;
-                        } else if (typeTag != ATypeTag.SYSTEM_NULL && !ATypeHierarchy.isCompatible(typeTag, aggType)) {
-                            throw new AlgebricksException("Unexpected type " + typeTag
-                                    + " in aggregation input stream. Expected type " + aggType + ".");
-                        } else if (ATypeHierarchy.canPromote(aggType, typeTag)) {
-                            aggType = typeTag;
-                        }
-
-                        if (typeTag != ATypeTag.SYSTEM_NULL) {
-                            ++count;
-                        }
-                        switch (typeTag) {
-                            case INT8: {
-                                byte val = AInt8SerializerDeserializer.getByte(inputVal.getByteArray(), 1);
-                                sum += val;
-                                break;
-                            }
-                            case INT16: {
-                                short val = AInt16SerializerDeserializer.getShort(inputVal.getByteArray(), 1);
-                                sum += val;
-                                break;
-                            }
-                            case INT32: {
-                                int val = AInt32SerializerDeserializer.getInt(inputVal.getByteArray(), 1);
-                                sum += val;
-                                break;
-                            }
-                            case INT64: {
-                                long val = AInt64SerializerDeserializer.getLong(inputVal.getByteArray(), 1);
-                                sum += val;
-                                break;
-                            }
-                            case FLOAT: {
-                                float val = AFloatSerializerDeserializer.getFloat(inputVal.getByteArray(), 1);
-                                sum += val;
-                                break;
-                            }
-                            case DOUBLE: {
-                                double val = ADoubleSerializerDeserializer.getDouble(inputVal.getByteArray(), 1);
-                                sum += val;
-                                break;
-                            }
-                            case NULL: {
-                                break;
-                            }
-                            default: {
-                                throw new NotImplementedException("Cannot compute AVG for values of type " + typeTag);
-                            }
-                        }
-                    }
-
-                    @Override
-                    public void finish() throws AlgebricksException {
-                        try {
-                            if (count == 0 || aggType == ATypeTag.NULL) {
-                                nullSerde.serialize(ANull.NULL, out);
-                            } else {
-                                aDouble.setValue(sum / count);
-                                doubleSerde.serialize(aDouble, out);
-                            }
-                        } catch (IOException e) {
-                            throw new AlgebricksException(e);
-                        }
-                    }
-
-                    @Override
-                    public void finishPartial() throws AlgebricksException {
-                        if (count == 0) {
-                            if (GlobalConfig.DEBUG) {
-                                GlobalConfig.ASTERIX_LOGGER.finest("AVG aggregate ran over empty input.");
-                            }
-                        } else {
-                            try {
-                                if (aggType == ATypeTag.NULL) {
-                                    sumBytes.reset();
-                                    nullSerde.serialize(ANull.NULL, sumBytesOutput);
-                                } else {
-                                    sumBytes.reset();
-                                    aDouble.setValue(sum);
-                                    doubleSerde.serialize(aDouble, sumBytesOutput);
-                                }
-                                countBytes.reset();
-                                aInt64.setValue(count);
-                                intSerde.serialize(aInt64, countBytesOutput);
-                                recordEval.evaluate(null);
-                            } catch (IOException e) {
-                                throw new AlgebricksException(e);
-                            }
-                        }
-                    }
-                };
+                return new AvgAggregateFunction(args, provider);
             }
         };
     }
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/AvgAggregateFunction.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/AvgAggregateFunction.java
new file mode 100644
index 0000000..2470e5a
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/AvgAggregateFunction.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2009-2013 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.aggregates.std;
+
+import edu.uci.ics.asterix.om.types.ATypeTag;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.data.std.api.IDataOutputProvider;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+
+public class AvgAggregateFunction extends AbstractAvgAggregateFunction {
+
+    public AvgAggregateFunction(ICopyEvaluatorFactory[] args, IDataOutputProvider output) throws AlgebricksException {
+        super(args, output);
+    }
+
+    @Override
+    public void step(IFrameTupleReference tuple) throws AlgebricksException {
+        processDataValues(tuple);
+    }
+
+    @Override
+    public void finish() throws AlgebricksException {
+        finishFinalResults();
+    }
+
+    @Override
+    public void finishPartial() throws AlgebricksException {
+        finish();
+    }
+
+    @Override
+    protected void processNull() {
+        aggType = ATypeTag.NULL;
+    }
+
+    @Override
+    protected boolean skipStep() {
+        return (aggType == ATypeTag.NULL);
+    }
+
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/CountAggregateFunction.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/CountAggregateFunction.java
index c63ab62..7c97fc2 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/CountAggregateFunction.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/CountAggregateFunction.java
@@ -14,70 +14,21 @@
  */
 package edu.uci.ics.asterix.runtime.aggregates.std;
 
-import java.io.DataOutput;
-import java.io.IOException;
-
-import edu.uci.ics.asterix.formats.nontagged.AqlSerializerDeserializerProvider;
-import edu.uci.ics.asterix.om.base.AInt64;
-import edu.uci.ics.asterix.om.base.AMutableInt64;
-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.hyracks.algebricks.common.exceptions.AlgebricksException;
-import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyAggregateFunction;
-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;
 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;
 
 /**
  * COUNT returns the number of items in the given list. Note that COUNT(NULL) is not allowed.
  */
-public class CountAggregateFunction implements ICopyAggregateFunction {
-    private AMutableInt64 result = new AMutableInt64(-1);
-    @SuppressWarnings("unchecked")
-    private ISerializerDeserializer<AInt64> int64Serde = AqlSerializerDeserializerProvider.INSTANCE
-            .getSerializerDeserializer(BuiltinType.AINT64);
-    private ArrayBackedValueStorage inputVal = new ArrayBackedValueStorage();
-    private ICopyEvaluator eval;
-    private long cnt;
-    private DataOutput out;
+public class CountAggregateFunction extends AbstractCountAggregateFunction {
 
     public CountAggregateFunction(ICopyEvaluatorFactory[] args, IDataOutputProvider output) throws AlgebricksException {
-        eval = args[0].createEvaluator(inputVal);
-        out = output.getDataOutput();
+        super(args, output);
     }
 
-    @Override
-    public void init() {
-        cnt = 0;
+    protected void processNull() {
+        cnt++;
     }
 
-    @Override
-    public void step(IFrameTupleReference tuple) throws AlgebricksException {
-        inputVal.reset();
-        eval.evaluate(tuple);
-        ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(inputVal.getByteArray()[0]);
-        // Ignore SYSTEM_NULL.
-        if (typeTag != ATypeTag.SYSTEM_NULL) {
-            cnt++;
-        }
-    }
-
-    @Override
-    public void finish() throws AlgebricksException {
-        try {
-            result.setValue(cnt);
-            int64Serde.serialize(result, out);
-        } catch (IOException e) {
-            throw new AlgebricksException(e);
-        }
-    }
-
-    @Override
-    public void finishPartial() throws AlgebricksException {
-        finish();
-    }
 }
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 eb5d6bd..230e06b 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
@@ -15,45 +15,16 @@
 
 package edu.uci.ics.asterix.runtime.aggregates.std;
 
-import java.io.DataOutput;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import edu.uci.ics.asterix.common.exceptions.AsterixException;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.ADoubleSerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt64SerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.ARecordSerializerDeserializer;
-import edu.uci.ics.asterix.formats.nontagged.AqlSerializerDeserializerProvider;
-import edu.uci.ics.asterix.om.base.ADouble;
-import edu.uci.ics.asterix.om.base.AInt64;
-import edu.uci.ics.asterix.om.base.AMutableDouble;
-import edu.uci.ics.asterix.om.base.AMutableInt64;
-import edu.uci.ics.asterix.om.base.ANull;
 import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
 import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
 import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
-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.BuiltinType;
-import edu.uci.ics.asterix.om.types.EnumDeserializer;
-import edu.uci.ics.asterix.om.types.IAType;
 import edu.uci.ics.asterix.runtime.aggregates.base.AbstractAggregateFunctionDynamicDescriptor;
-import edu.uci.ics.asterix.runtime.evaluators.common.AccessibleByteArrayEval;
-import edu.uci.ics.asterix.runtime.evaluators.common.ClosedRecordConstructorEvalFactory.ClosedRecordConstructorEval;
 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.ICopyAggregateFunction;
 import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyAggregateFunctionFactory;
-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;
 import edu.uci.ics.hyracks.data.std.api.IDataOutputProvider;
-import edu.uci.ics.hyracks.data.std.util.ArrayBackedValueStorage;
-import edu.uci.ics.hyracks.data.std.util.ByteArrayAccessibleOutputStream;
-import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
 
 public class GlobalAvgAggregateDescriptor extends AbstractAggregateFunctionDynamicDescriptor {
 
@@ -73,142 +44,13 @@
     @Override
     public ICopyAggregateFunctionFactory createAggregateFunctionFactory(final ICopyEvaluatorFactory[] args)
             throws AlgebricksException {
-        List<IAType> unionList = new ArrayList<IAType>();
-        unionList.add(BuiltinType.ANULL);
-        unionList.add(BuiltinType.ADOUBLE);
-        ARecordType tmpRecType;
-        try {
-            tmpRecType = new ARecordType(null, new String[] { "sum", "count" }, new IAType[] {
-                    new AUnionType(unionList, "OptionalDouble"), BuiltinType.AINT64 }, false);
-        } catch (AsterixException e) {
-            throw new AlgebricksException(e);
-        }
-
-        final ARecordType recType = tmpRecType;
-
         return new ICopyAggregateFunctionFactory() {
             private static final long serialVersionUID = 1L;
 
             @Override
             public ICopyAggregateFunction createAggregateFunction(final IDataOutputProvider provider)
                     throws AlgebricksException {
-
-                return new ICopyAggregateFunction() {
-
-                    private DataOutput out = provider.getDataOutput();
-                    private ArrayBackedValueStorage inputVal = new ArrayBackedValueStorage();
-                    private ICopyEvaluator eval = args[0].createEvaluator(inputVal);
-                    private double globalSum;
-                    private long globalCount;
-                    private AMutableDouble aDouble = new AMutableDouble(0);
-                    private AMutableInt64 aInt64 = new AMutableInt64(0);
-
-                    private ArrayBackedValueStorage avgBytes = new ArrayBackedValueStorage();
-                    private ByteArrayAccessibleOutputStream sumBytes = new ByteArrayAccessibleOutputStream();
-                    private DataOutput sumBytesOutput = new DataOutputStream(sumBytes);
-                    private ByteArrayAccessibleOutputStream countBytes = new ByteArrayAccessibleOutputStream();
-                    private DataOutput countBytesOutput = new DataOutputStream(countBytes);
-                    private ICopyEvaluator evalSum = new AccessibleByteArrayEval(avgBytes.getDataOutput(), sumBytes);
-                    private ICopyEvaluator evalCount = new AccessibleByteArrayEval(avgBytes.getDataOutput(), countBytes);
-                    private ClosedRecordConstructorEval recordEval = new ClosedRecordConstructorEval(recType,
-                            new ICopyEvaluator[] { evalSum, evalCount }, avgBytes, out);
-
-                    @SuppressWarnings("unchecked")
-                    private ISerializerDeserializer<AInt64> longSerde = AqlSerializerDeserializerProvider.INSTANCE
-                            .getSerializerDeserializer(BuiltinType.AINT64);
-                    @SuppressWarnings("unchecked")
-                    private ISerializerDeserializer<ADouble> doubleSerde = AqlSerializerDeserializerProvider.INSTANCE
-                            .getSerializerDeserializer(BuiltinType.ADOUBLE);
-                    @SuppressWarnings("unchecked")
-                    private ISerializerDeserializer<ANull> nullSerde = AqlSerializerDeserializerProvider.INSTANCE
-                            .getSerializerDeserializer(BuiltinType.ANULL);
-                    private boolean metNull;
-
-                    @Override
-                    public void init() {
-                        globalSum = 0.0;
-                        globalCount = 0;
-                        metNull = false;
-                    }
-
-                    @Override
-                    public void step(IFrameTupleReference tuple) throws AlgebricksException {
-                        inputVal.reset();
-                        eval.evaluate(tuple);
-                        byte[] serBytes = inputVal.getByteArray();
-                        ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(serBytes[0]);
-                        switch (typeTag) {
-                            case NULL: {
-                                metNull = true;
-                                break;
-                            }
-                            case SYSTEM_NULL: {
-                                // Ignore and return.
-                                return;
-                            }
-                            case RECORD: {
-                                // Expected.
-                                break;
-                            }
-                            default: {
-                                throw new AlgebricksException("Global-Avg is not defined for values of type "
-                                        + EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(serBytes[0]));
-                            }
-                        }
-
-                        // 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, nullBitmapSize,
-                                false);
-                        if (offset2 != 0) // the count is not null
-                            globalCount += AInt64SerializerDeserializer.getLong(serBytes, offset2);
-
-                    }
-
-                    @Override
-                    public void finish() throws AlgebricksException {
-                        try {
-                            if (globalCount == 0 || metNull)
-                                nullSerde.serialize(ANull.NULL, out);
-                            else {
-                                aDouble.setValue(globalSum / globalCount);
-                                doubleSerde.serialize(aDouble, out);
-                            }
-                        } catch (IOException e) {
-                            throw new AlgebricksException(e);
-                        }
-                    }
-
-                    @Override
-                    public void finishPartial() throws AlgebricksException {
-                        try {
-                            if (metNull || globalCount == 0) {
-                                sumBytes.reset();
-                                nullSerde.serialize(ANull.NULL, sumBytesOutput);
-                            } else {
-                                sumBytes.reset();
-                                aDouble.setValue(globalSum);
-                                doubleSerde.serialize(aDouble, sumBytesOutput);
-                            }
-                            countBytes.reset();
-                            aInt64.setValue(globalCount);
-                            longSerde.serialize(aInt64, countBytesOutput);
-                            recordEval.evaluate(null);
-                        } catch (IOException e) {
-                            throw new AlgebricksException(e);
-                        }
-                    }
-                };
+                return new GlobalAvgAggregateFunction(args, provider);
             }
         };
     }
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/GlobalAvgAggregateFunction.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/GlobalAvgAggregateFunction.java
new file mode 100644
index 0000000..a63d4bc
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/GlobalAvgAggregateFunction.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2009-2013 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.aggregates.std;
+
+import edu.uci.ics.asterix.om.types.ATypeTag;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.data.std.api.IDataOutputProvider;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+
+public class GlobalAvgAggregateFunction extends AbstractAvgAggregateFunction {
+
+    public GlobalAvgAggregateFunction(ICopyEvaluatorFactory[] args, IDataOutputProvider output)
+            throws AlgebricksException {
+        super(args, output);
+    }
+
+    @Override
+    public void step(IFrameTupleReference tuple) throws AlgebricksException {
+        processPartialResults(tuple);
+    }
+
+    @Override
+    public void finish() throws AlgebricksException {
+        finishFinalResults();
+    }
+
+    @Override
+    public void finishPartial() throws AlgebricksException {
+        finishPartialResults();
+    }
+
+    @Override
+    protected void processNull() {
+        aggType = ATypeTag.NULL;
+    }
+
+    @Override
+    protected boolean skipStep() {
+        return (aggType == ATypeTag.NULL);
+    }
+
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/GlobalSqlAvgAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/GlobalSqlAvgAggregateDescriptor.java
new file mode 100644
index 0000000..0808e81
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/GlobalSqlAvgAggregateDescriptor.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2009-2013 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.aggregates.std;
+
+import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
+import edu.uci.ics.asterix.runtime.aggregates.base.AbstractAggregateFunctionDynamicDescriptor;
+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.ICopyAggregateFunction;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyAggregateFunctionFactory;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.data.std.api.IDataOutputProvider;
+
+public class GlobalSqlAvgAggregateDescriptor extends AbstractAggregateFunctionDynamicDescriptor {
+
+    private static final long serialVersionUID = 1L;
+
+    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new GlobalSqlAvgAggregateDescriptor();
+        }
+    };
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return AsterixBuiltinFunctions.GLOBAL_SQL_AVG;
+    }
+
+    @Override
+    public ICopyAggregateFunctionFactory createAggregateFunctionFactory(final ICopyEvaluatorFactory[] args)
+            throws AlgebricksException {
+        return new ICopyAggregateFunctionFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public ICopyAggregateFunction createAggregateFunction(final IDataOutputProvider provider)
+                    throws AlgebricksException {
+                return new GlobalSqlAvgAggregateFunction(args, provider);
+            }
+        };
+    }
+
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/GlobalSqlAvgAggregateFunction.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/GlobalSqlAvgAggregateFunction.java
new file mode 100644
index 0000000..02c3c2c
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/GlobalSqlAvgAggregateFunction.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2009-2013 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.aggregates.std;
+
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.data.std.api.IDataOutputProvider;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+
+public class GlobalSqlAvgAggregateFunction extends AbstractAvgAggregateFunction {
+
+    public GlobalSqlAvgAggregateFunction(ICopyEvaluatorFactory[] args, IDataOutputProvider output)
+            throws AlgebricksException {
+        super(args, output);
+    }
+
+    @Override
+    public void step(IFrameTupleReference tuple) throws AlgebricksException {
+        processPartialResults(tuple);
+    }
+
+    @Override
+    public void finish() throws AlgebricksException {
+        finishFinalResults();
+    }
+
+    @Override
+    public void finishPartial() throws AlgebricksException {
+        finishPartialResults();
+    }
+
+    @Override
+    protected void processNull() {
+    }
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/LocalAvgAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/LocalAvgAggregateDescriptor.java
index 09a659c..fd98764 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/LocalAvgAggregateDescriptor.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/LocalAvgAggregateDescriptor.java
@@ -15,50 +15,16 @@
 
 package edu.uci.ics.asterix.runtime.aggregates.std;
 
-import java.io.DataOutput;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import edu.uci.ics.asterix.common.exceptions.AsterixException;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.ADoubleSerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AFloatSerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt16SerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt32SerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt64SerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt8SerializerDeserializer;
-import edu.uci.ics.asterix.formats.nontagged.AqlSerializerDeserializerProvider;
-import edu.uci.ics.asterix.om.base.ADouble;
-import edu.uci.ics.asterix.om.base.AInt64;
-import edu.uci.ics.asterix.om.base.AMutableDouble;
-import edu.uci.ics.asterix.om.base.AMutableInt64;
-import edu.uci.ics.asterix.om.base.ANull;
 import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
 import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
 import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
-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.BuiltinType;
-import edu.uci.ics.asterix.om.types.EnumDeserializer;
-import edu.uci.ics.asterix.om.types.IAType;
-import edu.uci.ics.asterix.om.types.hierachy.ATypeHierarchy;
 import edu.uci.ics.asterix.runtime.aggregates.base.AbstractAggregateFunctionDynamicDescriptor;
-import edu.uci.ics.asterix.runtime.evaluators.common.AccessibleByteArrayEval;
-import edu.uci.ics.asterix.runtime.evaluators.common.ClosedRecordConstructorEvalFactory.ClosedRecordConstructorEval;
 import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
-import edu.uci.ics.hyracks.algebricks.common.exceptions.NotImplementedException;
 import edu.uci.ics.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
 import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyAggregateFunction;
 import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyAggregateFunctionFactory;
-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;
 import edu.uci.ics.hyracks.data.std.api.IDataOutputProvider;
-import edu.uci.ics.hyracks.data.std.util.ArrayBackedValueStorage;
-import edu.uci.ics.hyracks.data.std.util.ByteArrayAccessibleOutputStream;
-import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
 
 public class LocalAvgAggregateDescriptor extends AbstractAggregateFunctionDynamicDescriptor {
 
@@ -77,157 +43,13 @@
     @Override
     public ICopyAggregateFunctionFactory createAggregateFunctionFactory(final ICopyEvaluatorFactory[] args)
             throws AlgebricksException {
-
         return new ICopyAggregateFunctionFactory() {
             private static final long serialVersionUID = 1L;
 
             @Override
             public ICopyAggregateFunction createAggregateFunction(final IDataOutputProvider provider)
                     throws AlgebricksException {
-
-                List<IAType> unionList = new ArrayList<IAType>();
-                unionList.add(BuiltinType.ANULL);
-                unionList.add(BuiltinType.ADOUBLE);
-                ARecordType tmpRecType;
-                try {
-                    tmpRecType = new ARecordType(null, new String[] { "sum", "count" }, new IAType[] {
-                            new AUnionType(unionList, "OptionalDouble"), BuiltinType.AINT64 }, false);
-                } catch (AsterixException e) {
-                    throw new AlgebricksException(e);
-                }
-
-                final ARecordType recType = tmpRecType;
-
-                return new ICopyAggregateFunction() {
-
-                    private DataOutput out = provider.getDataOutput();
-                    private ArrayBackedValueStorage inputVal = new ArrayBackedValueStorage();
-                    private ICopyEvaluator eval = args[0].createEvaluator(inputVal);
-                    private ATypeTag aggType;
-                    private double sum;
-                    private long count;
-
-                    private ArrayBackedValueStorage avgBytes = new ArrayBackedValueStorage();
-                    private ByteArrayAccessibleOutputStream sumBytes = new ByteArrayAccessibleOutputStream();
-                    private DataOutput sumBytesOutput = new DataOutputStream(sumBytes);
-                    private ByteArrayAccessibleOutputStream countBytes = new ByteArrayAccessibleOutputStream();
-                    private DataOutput countBytesOutput = new DataOutputStream(countBytes);
-                    private ICopyEvaluator evalSum = new AccessibleByteArrayEval(avgBytes.getDataOutput(), sumBytes);
-                    private ICopyEvaluator evalCount = new AccessibleByteArrayEval(avgBytes.getDataOutput(), countBytes);
-                    private ClosedRecordConstructorEval recordEval = new ClosedRecordConstructorEval(recType,
-                            new ICopyEvaluator[] { evalSum, evalCount }, avgBytes, out);
-                    @SuppressWarnings("unchecked")
-                    private ISerializerDeserializer<ADouble> doubleSerde = AqlSerializerDeserializerProvider.INSTANCE
-                            .getSerializerDeserializer(BuiltinType.ADOUBLE);
-                    @SuppressWarnings("unchecked")
-                    private ISerializerDeserializer<AInt64> longSerde = AqlSerializerDeserializerProvider.INSTANCE
-                            .getSerializerDeserializer(BuiltinType.AINT64);
-                    @SuppressWarnings("unchecked")
-                    private ISerializerDeserializer<ANull> nullSerde = AqlSerializerDeserializerProvider.INSTANCE
-                            .getSerializerDeserializer(BuiltinType.ANULL);
-                    private AMutableDouble aDouble = new AMutableDouble(0);
-                    private AMutableInt64 aInt64 = new AMutableInt64(0);
-
-                    @Override
-                    public void init() {
-                        aggType = ATypeTag.SYSTEM_NULL;
-                        sum = 0.0;
-                        count = 0;
-                    }
-
-                    @Override
-                    public void step(IFrameTupleReference tuple) throws AlgebricksException {
-                        inputVal.reset();
-                        eval.evaluate(tuple);
-                        ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER
-                                .deserialize(inputVal.getByteArray()[0]);
-                        if (typeTag == ATypeTag.NULL || aggType == ATypeTag.NULL) {
-                            aggType = ATypeTag.NULL;
-                            return;
-                        } else if (aggType == ATypeTag.SYSTEM_NULL) {
-                            aggType = typeTag;
-                        } else if (typeTag != ATypeTag.SYSTEM_NULL && !ATypeHierarchy.isCompatible(typeTag, aggType)) {
-                            throw new AlgebricksException("Unexpected type " + typeTag
-                                    + " in aggregation input stream. Expected type " + aggType + ".");
-                        } else if (ATypeHierarchy.canPromote(aggType, typeTag)) {
-                            aggType = typeTag;
-                        }
-
-                        if (typeTag != ATypeTag.SYSTEM_NULL) {
-                            ++count;
-                        }
-
-                        switch (typeTag) {
-                            case INT8: {
-                                byte val = AInt8SerializerDeserializer.getByte(inputVal.getByteArray(), 1);
-                                sum += val;
-                                break;
-                            }
-                            case INT16: {
-                                short val = AInt16SerializerDeserializer.getShort(inputVal.getByteArray(), 1);
-                                sum += val;
-                                break;
-                            }
-                            case INT32: {
-                                int val = AInt32SerializerDeserializer.getInt(inputVal.getByteArray(), 1);
-                                sum += val;
-                                break;
-                            }
-                            case INT64: {
-                                long val = AInt64SerializerDeserializer.getLong(inputVal.getByteArray(), 1);
-                                sum += val;
-                                break;
-                            }
-                            case FLOAT: {
-                                float val = AFloatSerializerDeserializer.getFloat(inputVal.getByteArray(), 1);
-                                sum += val;
-                                break;
-                            }
-                            case DOUBLE: {
-                                double val = ADoubleSerializerDeserializer.getDouble(inputVal.getByteArray(), 1);
-                                sum += val;
-                                break;
-                            }
-                            case NULL: {
-                                break;
-                            }
-                            default: {
-                                throw new NotImplementedException("Cannot compute LOCAL-AVG for values of type "
-                                        + typeTag);
-                            }
-                        }
-                        inputVal.reset();
-                    }
-
-                    @Override
-                    public void finish() throws AlgebricksException {
-                        try {
-                            if (count == 0 && aggType != ATypeTag.NULL) {
-                                out.writeByte(ATypeTag.SYSTEM_NULL.serialize());
-                                return;
-                            }
-                            if (aggType == ATypeTag.NULL) {
-                                sumBytes.reset();
-                                nullSerde.serialize(ANull.NULL, sumBytesOutput);
-                            } else {
-                                sumBytes.reset();
-                                aDouble.setValue(sum);
-                                doubleSerde.serialize(aDouble, sumBytesOutput);
-                            }
-                            countBytes.reset();
-                            aInt64.setValue(count);
-                            longSerde.serialize(aInt64, countBytesOutput);
-                            recordEval.evaluate(null);
-                        } catch (IOException e) {
-                            throw new AlgebricksException(e);
-                        }
-                    }
-
-                    @Override
-                    public void finishPartial() throws AlgebricksException {
-                        finish();
-                    }
-                };
+                return new LocalAvgAggregateFunction(args, provider);
             }
         };
     }
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/LocalAvgAggregateFunction.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/LocalAvgAggregateFunction.java
new file mode 100644
index 0000000..2c7abd4
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/LocalAvgAggregateFunction.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2009-2013 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.aggregates.std;
+
+import edu.uci.ics.asterix.om.types.ATypeTag;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.data.std.api.IDataOutputProvider;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+
+public class LocalAvgAggregateFunction extends AbstractAvgAggregateFunction {
+
+    public LocalAvgAggregateFunction(ICopyEvaluatorFactory[] args, IDataOutputProvider output)
+            throws AlgebricksException {
+        super(args, output);
+    }
+
+    @Override
+    public void step(IFrameTupleReference tuple) throws AlgebricksException {
+        processDataValues(tuple);
+    }
+
+    @Override
+    public void finish() throws AlgebricksException {
+        finishPartialResults();
+    }
+
+    @Override
+    public void finishPartial() throws AlgebricksException {
+        finish();
+    }
+
+    @Override
+    protected void processNull() {
+        aggType = ATypeTag.NULL;
+    }
+
+    @Override
+    protected boolean skipStep() {
+        return (aggType == ATypeTag.NULL);
+    }
+
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/LocalMinAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/LocalMinAggregateDescriptor.java
index 9e411b6..c540c43 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/LocalMinAggregateDescriptor.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/LocalMinAggregateDescriptor.java
@@ -14,7 +14,6 @@
  */
 package edu.uci.ics.asterix.runtime.aggregates.std;
 
-import edu.uci.ics.asterix.common.functions.FunctionConstants;
 import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
 import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
 import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/LocalSqlAvgAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/LocalSqlAvgAggregateDescriptor.java
new file mode 100644
index 0000000..6a1f60e
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/LocalSqlAvgAggregateDescriptor.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2009-2013 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.aggregates.std;
+
+import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
+import edu.uci.ics.asterix.runtime.aggregates.base.AbstractAggregateFunctionDynamicDescriptor;
+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.ICopyAggregateFunction;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyAggregateFunctionFactory;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.data.std.api.IDataOutputProvider;
+
+public class LocalSqlAvgAggregateDescriptor extends AbstractAggregateFunctionDynamicDescriptor {
+
+    private static final long serialVersionUID = 1L;
+    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new LocalSqlAvgAggregateDescriptor();
+        }
+    };
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return AsterixBuiltinFunctions.LOCAL_SQL_AVG;
+    }
+
+    @Override
+    public ICopyAggregateFunctionFactory createAggregateFunctionFactory(final ICopyEvaluatorFactory[] args)
+            throws AlgebricksException {
+        return new ICopyAggregateFunctionFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public ICopyAggregateFunction createAggregateFunction(final IDataOutputProvider provider)
+                    throws AlgebricksException {
+                return new LocalSqlAvgAggregateFunction(args, provider);
+            }
+        };
+    }
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/LocalSqlAvgAggregateFunction.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/LocalSqlAvgAggregateFunction.java
new file mode 100644
index 0000000..6a97410
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/LocalSqlAvgAggregateFunction.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2009-2013 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.aggregates.std;
+
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.data.std.api.IDataOutputProvider;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+
+public class LocalSqlAvgAggregateFunction extends AbstractAvgAggregateFunction {
+
+    public LocalSqlAvgAggregateFunction(ICopyEvaluatorFactory[] args, IDataOutputProvider output)
+            throws AlgebricksException {
+        super(args, output);
+    }
+
+    @Override
+    public void step(IFrameTupleReference tuple) throws AlgebricksException {
+        processDataValues(tuple);
+    }
+
+    @Override
+    public void finish() throws AlgebricksException {
+        finishPartialResults();
+    }
+
+    @Override
+    public void finishPartial() throws AlgebricksException {
+        finish();
+    }
+
+    @Override
+    protected void processNull() {
+    }
+
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/LocalSqlMaxAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/LocalSqlMaxAggregateDescriptor.java
new file mode 100644
index 0000000..6b31244
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/LocalSqlMaxAggregateDescriptor.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2009-2013 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.aggregates.std;
+
+import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
+import edu.uci.ics.asterix.runtime.aggregates.base.AbstractAggregateFunctionDynamicDescriptor;
+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.ICopyAggregateFunction;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyAggregateFunctionFactory;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.data.std.api.IDataOutputProvider;
+
+public class LocalSqlMaxAggregateDescriptor extends AbstractAggregateFunctionDynamicDescriptor {
+
+    private static final long serialVersionUID = 1L;
+    private final static FunctionIdentifier FID = AsterixBuiltinFunctions.LOCAL_SQL_MAX;
+
+    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new LocalSqlMaxAggregateDescriptor();
+        }
+    };
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return FID;
+    }
+
+    @Override
+    public ICopyAggregateFunctionFactory createAggregateFunctionFactory(final ICopyEvaluatorFactory[] args)
+            throws AlgebricksException {
+        return new ICopyAggregateFunctionFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public ICopyAggregateFunction createAggregateFunction(final IDataOutputProvider provider)
+                    throws AlgebricksException {
+                return new SqlMinMaxAggregateFunction(args, provider, false, true);
+            }
+        };
+    }
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/LocalSqlMinAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/LocalSqlMinAggregateDescriptor.java
new file mode 100644
index 0000000..4946703
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/LocalSqlMinAggregateDescriptor.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2009-2013 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.aggregates.std;
+
+import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
+import edu.uci.ics.asterix.runtime.aggregates.base.AbstractAggregateFunctionDynamicDescriptor;
+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.ICopyAggregateFunction;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyAggregateFunctionFactory;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.data.std.api.IDataOutputProvider;
+
+public class LocalSqlMinAggregateDescriptor extends AbstractAggregateFunctionDynamicDescriptor {
+
+    private static final long serialVersionUID = 1L;
+    private final static FunctionIdentifier FID = AsterixBuiltinFunctions.LOCAL_SQL_MIN;
+    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new LocalSqlMinAggregateDescriptor();
+        }
+    };
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return FID;
+    }
+
+    @Override
+    public ICopyAggregateFunctionFactory createAggregateFunctionFactory(final ICopyEvaluatorFactory[] args)
+            throws AlgebricksException {
+        return new ICopyAggregateFunctionFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public ICopyAggregateFunction createAggregateFunction(final IDataOutputProvider provider)
+                    throws AlgebricksException {
+                return new SqlMinMaxAggregateFunction(args, provider, true, true);
+            }
+        };
+    }
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/LocalSqlSumAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/LocalSqlSumAggregateDescriptor.java
new file mode 100644
index 0000000..1f47727
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/LocalSqlSumAggregateDescriptor.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2009-2013 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.aggregates.std;
+
+import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
+import edu.uci.ics.asterix.runtime.aggregates.base.AbstractAggregateFunctionDynamicDescriptor;
+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.ICopyAggregateFunction;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyAggregateFunctionFactory;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.data.std.api.IDataOutputProvider;
+
+public class LocalSqlSumAggregateDescriptor extends AbstractAggregateFunctionDynamicDescriptor {
+
+    private static final long serialVersionUID = 1L;
+    private final static FunctionIdentifier FID = AsterixBuiltinFunctions.LOCAL_SQL_SUM;
+    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new LocalSqlSumAggregateDescriptor();
+        }
+    };
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return FID;
+    }
+
+    @Override
+    public ICopyAggregateFunctionFactory createAggregateFunctionFactory(final ICopyEvaluatorFactory[] args)
+            throws AlgebricksException {
+        return new ICopyAggregateFunctionFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public ICopyAggregateFunction createAggregateFunction(final IDataOutputProvider provider)
+                    throws AlgebricksException {
+                return new SqlSumAggregateFunction(args, provider, true);
+            };
+        };
+    }
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/LocalSumAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/LocalSumAggregateDescriptor.java
index 3e0b65c..0e35cd3 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/LocalSumAggregateDescriptor.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/LocalSumAggregateDescriptor.java
@@ -14,7 +14,6 @@
  */
 package edu.uci.ics.asterix.runtime.aggregates.std;
 
-import edu.uci.ics.asterix.common.functions.FunctionConstants;
 import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
 import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
 import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/MinMaxAggregateFunction.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/MinMaxAggregateFunction.java
index 8599913..0809701 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/MinMaxAggregateFunction.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/MinMaxAggregateFunction.java
@@ -14,164 +14,46 @@
  */
 package edu.uci.ics.asterix.runtime.aggregates.std;
 
-import java.io.DataOutput;
 import java.io.IOException;
 
-import edu.uci.ics.asterix.formats.nontagged.AqlBinaryComparatorFactoryProvider;
 import edu.uci.ics.asterix.om.types.ATypeTag;
-import edu.uci.ics.asterix.om.types.EnumDeserializer;
-import edu.uci.ics.asterix.om.types.hierachy.ATypeHierarchy;
-import edu.uci.ics.asterix.om.types.hierachy.ITypePromoteComputer;
 import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
-import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyAggregateFunction;
-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.IBinaryComparator;
-import edu.uci.ics.hyracks.api.dataflow.value.IBinaryComparatorFactory;
 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;
 
-public class MinMaxAggregateFunction implements ICopyAggregateFunction {
-    private ArrayBackedValueStorage inputVal = new ArrayBackedValueStorage();
-    private ArrayBackedValueStorage outputVal = new ArrayBackedValueStorage();
-    private ArrayBackedValueStorage tempValForCasting = new ArrayBackedValueStorage();
-    private DataOutput out;
-    private ICopyEvaluator eval;
-    private ATypeTag aggType;
-    private IBinaryComparator cmp;
-    private ITypePromoteComputer tpc;
-    private final boolean isMin;
+public class MinMaxAggregateFunction extends AbstractMinMaxAggregateFunction {
     private final boolean isLocalAgg;
 
     public MinMaxAggregateFunction(ICopyEvaluatorFactory[] args, IDataOutputProvider provider, boolean isMin,
             boolean isLocalAgg) throws AlgebricksException {
-        out = provider.getDataOutput();
-        eval = args[0].createEvaluator(inputVal);
-        this.isMin = isMin;
+        super(args, provider, isMin);
         this.isLocalAgg = isLocalAgg;
     }
 
-    @Override
-    public void init() {
-        aggType = ATypeTag.SYSTEM_NULL;
-        outputVal.reset();
-        tempValForCasting.reset();
+    protected void processNull() {
+        aggType = ATypeTag.NULL;
     }
 
     @Override
-    public void step(IFrameTupleReference tuple) throws AlgebricksException {
-        inputVal.reset();
-        eval.evaluate(tuple);
-        ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(inputVal.getByteArray()[0]);
-        if (typeTag == ATypeTag.NULL || aggType == ATypeTag.NULL) {
-            aggType = ATypeTag.NULL;
-            return;
+    protected boolean skipStep() {
+        return (aggType == ATypeTag.NULL);
+    }
+
+    @Override
+    protected void processSystemNull() throws AlgebricksException {
+        if (isLocalAgg) {
+            throw new AlgebricksException("Type SYSTEM_NULL encountered in local aggregate.");
         }
-        if (aggType == ATypeTag.SYSTEM_NULL) {
-            if (typeTag == ATypeTag.SYSTEM_NULL) {
-                // Ignore.
-                return;
-            }
-            // First value encountered. Set type, comparator, and initial value.
-            aggType = typeTag;
-            // Set comparator.
-            IBinaryComparatorFactory cmpFactory = AqlBinaryComparatorFactoryProvider.INSTANCE
-                    .getBinaryComparatorFactory(aggType, isMin);
-            cmp = cmpFactory.createBinaryComparator();
-            // Initialize min value.
-            outputVal.assign(inputVal);
-        } else if (typeTag != ATypeTag.SYSTEM_NULL && !ATypeHierarchy.isCompatible(typeTag, aggType)) {
-            throw new AlgebricksException("Unexpected type " + typeTag + " in aggregation input stream. Expected type "
-                    + aggType + ".");
+    }
+
+    @Override
+    protected void finishSystemNull() throws IOException {
+        // Empty stream. For local agg return system null. For global agg return null.
+        if (isLocalAgg) {
+            out.writeByte(ATypeTag.SYSTEM_NULL.serialize());
         } else {
-
-            // If a system_null is encountered locally, it would be an error; otherwise if it is seen
-            // by a global aggregator, it is simple ignored.
-            if (typeTag == ATypeTag.SYSTEM_NULL) {
-                if (isLocalAgg) {
-                    throw new AlgebricksException("Type SYSTEM_NULL encountered in local aggregate.");
-                } else {
-                    return;
-                }
-            }
-
-            if (ATypeHierarchy.canPromote(aggType, typeTag)) {
-                tpc = ATypeHierarchy.getTypePromoteComputer(aggType, typeTag);
-                aggType = typeTag;
-                cmp = AqlBinaryComparatorFactoryProvider.INSTANCE.getBinaryComparatorFactory(aggType, isMin)
-                        .createBinaryComparator();
-                if (tpc != null) {
-                    tempValForCasting.reset();
-                    try {
-                        tpc.promote(outputVal.getByteArray(), outputVal.getStartOffset() + 1,
-                                outputVal.getLength() - 1, tempValForCasting);
-                    } catch (IOException e) {
-                        throw new AlgebricksException(e);
-                    }
-                    outputVal.reset();
-                    outputVal.assign(tempValForCasting);
-                }
-                if (cmp.compare(inputVal.getByteArray(), inputVal.getStartOffset(), inputVal.getLength(),
-                        outputVal.getByteArray(), outputVal.getStartOffset(), outputVal.getLength()) < 0) {
-                    outputVal.assign(inputVal);
-                }
-
-            } else {
-                tpc = ATypeHierarchy.getTypePromoteComputer(typeTag, aggType);
-                if (tpc != null) {
-                    tempValForCasting.reset();
-                    try {
-                        tpc.promote(inputVal.getByteArray(), inputVal.getStartOffset() + 1, inputVal.getLength() - 1,
-                                tempValForCasting);
-                    } catch (IOException e) {
-                        throw new AlgebricksException(e);
-                    }
-                    if (cmp.compare(tempValForCasting.getByteArray(), tempValForCasting.getStartOffset(),
-                            tempValForCasting.getLength(), outputVal.getByteArray(), outputVal.getStartOffset(),
-                            outputVal.getLength()) < 0) {
-                        outputVal.assign(tempValForCasting);
-                    }
-                } else {
-                    if (cmp.compare(inputVal.getByteArray(), inputVal.getStartOffset(), inputVal.getLength(),
-                            outputVal.getByteArray(), outputVal.getStartOffset(), outputVal.getLength()) < 0) {
-                        outputVal.assign(inputVal);
-                    }
-                }
-
-            }
+            out.writeByte(ATypeTag.NULL.serialize());
         }
     }
 
-    @Override
-    public void finish() throws AlgebricksException {
-        try {
-            switch (aggType) {
-                case NULL: {
-                    out.writeByte(ATypeTag.NULL.serialize());
-                    break;
-                }
-                case SYSTEM_NULL: {
-                    // Empty stream. For local agg return system null. For global agg return null.
-                    if (isLocalAgg) {
-                        out.writeByte(ATypeTag.SYSTEM_NULL.serialize());
-                    } else {
-                        out.writeByte(ATypeTag.NULL.serialize());
-                    }
-                    break;
-                }
-                default: {
-                    out.write(outputVal.getByteArray(), outputVal.getStartOffset(), outputVal.getLength());
-                    break;
-                }
-            }
-        } catch (IOException e) {
-            throw new AlgebricksException(e);
-        }
-    }
-
-    @Override
-    public void finishPartial() throws AlgebricksException {
-        finish();
-    }
 }
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SqlAvgAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SqlAvgAggregateDescriptor.java
new file mode 100644
index 0000000..cf3f3dd
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SqlAvgAggregateDescriptor.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2009-2013 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.aggregates.std;
+
+import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
+import edu.uci.ics.asterix.runtime.aggregates.base.AbstractAggregateFunctionDynamicDescriptor;
+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.ICopyAggregateFunction;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyAggregateFunctionFactory;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.data.std.api.IDataOutputProvider;
+
+public class SqlAvgAggregateDescriptor extends AbstractAggregateFunctionDynamicDescriptor {
+
+    private static final long serialVersionUID = 1L;
+    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new SqlAvgAggregateDescriptor();
+        }
+    };
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return AsterixBuiltinFunctions.SQL_AVG;
+    }
+
+    @Override
+    public ICopyAggregateFunctionFactory createAggregateFunctionFactory(final ICopyEvaluatorFactory[] args)
+            throws AlgebricksException {
+        return new ICopyAggregateFunctionFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public ICopyAggregateFunction createAggregateFunction(final IDataOutputProvider provider)
+                    throws AlgebricksException {
+                return new SqlAvgAggregateFunction(args, provider);
+            }
+        };
+    }
+
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SqlAvgAggregateFunction.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SqlAvgAggregateFunction.java
new file mode 100644
index 0000000..11cf13f
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SqlAvgAggregateFunction.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2009-2013 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.aggregates.std;
+
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.data.std.api.IDataOutputProvider;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+
+public class SqlAvgAggregateFunction extends AbstractAvgAggregateFunction {
+
+    public SqlAvgAggregateFunction(ICopyEvaluatorFactory[] args, IDataOutputProvider output) throws AlgebricksException {
+        super(args, output);
+    }
+
+    @Override
+    public void step(IFrameTupleReference tuple) throws AlgebricksException {
+        processDataValues(tuple);
+    }
+
+    @Override
+    public void finish() throws AlgebricksException {
+        finishFinalResults();
+    }
+
+    @Override
+    public void finishPartial() throws AlgebricksException {
+        finish();
+    }
+
+    @Override
+    protected void processNull() {
+    }
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SqlCountAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SqlCountAggregateDescriptor.java
new file mode 100644
index 0000000..b484b53
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SqlCountAggregateDescriptor.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2009-2013 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.aggregates.std;
+
+import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
+import edu.uci.ics.asterix.runtime.aggregates.base.AbstractAggregateFunctionDynamicDescriptor;
+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.ICopyAggregateFunction;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyAggregateFunctionFactory;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.data.std.api.IDataOutputProvider;
+
+/**
+ * NULLs are also counted.
+ */
+public class SqlCountAggregateDescriptor extends AbstractAggregateFunctionDynamicDescriptor {
+
+    private static final long serialVersionUID = 1L;
+    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new SqlCountAggregateDescriptor();
+        }
+    };
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return AsterixBuiltinFunctions.SQL_COUNT;
+    }
+
+    @Override
+    public ICopyAggregateFunctionFactory createAggregateFunctionFactory(final ICopyEvaluatorFactory[] args)
+            throws AlgebricksException {
+        return new ICopyAggregateFunctionFactory() {
+
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public ICopyAggregateFunction createAggregateFunction(IDataOutputProvider provider)
+                    throws AlgebricksException {
+                return new SqlCountAggregateFunction(args, provider);
+            }
+        };
+    }
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SqlCountAggregateFunction.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SqlCountAggregateFunction.java
new file mode 100644
index 0000000..5fb5d72
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SqlCountAggregateFunction.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2009-2013 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.aggregates.std;
+
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.data.std.api.IDataOutputProvider;
+
+/**
+ * COUNT returns the number of non-null items in the given list. Note that COUNT(NULL) is not allowed.
+ */
+public class SqlCountAggregateFunction extends AbstractCountAggregateFunction {
+
+    public SqlCountAggregateFunction(ICopyEvaluatorFactory[] args, IDataOutputProvider output)
+            throws AlgebricksException {
+        super(args, output);
+    }
+
+    @Override
+    protected void processNull() {
+    }
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SqlMaxAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SqlMaxAggregateDescriptor.java
new file mode 100644
index 0000000..c8e415f
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SqlMaxAggregateDescriptor.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2009-2013 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.aggregates.std;
+
+import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
+import edu.uci.ics.asterix.runtime.aggregates.base.AbstractAggregateFunctionDynamicDescriptor;
+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.ICopyAggregateFunction;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyAggregateFunctionFactory;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.data.std.api.IDataOutputProvider;
+
+public class SqlMaxAggregateDescriptor extends AbstractAggregateFunctionDynamicDescriptor {
+
+    private static final long serialVersionUID = 1L;
+    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new SqlMaxAggregateDescriptor();
+        }
+    };
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return AsterixBuiltinFunctions.SQL_MAX;
+    }
+
+    @Override
+    public ICopyAggregateFunctionFactory createAggregateFunctionFactory(final ICopyEvaluatorFactory[] args)
+            throws AlgebricksException {
+        return new ICopyAggregateFunctionFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public ICopyAggregateFunction createAggregateFunction(final IDataOutputProvider provider)
+                    throws AlgebricksException {
+                return new SqlMinMaxAggregateFunction(args, provider, false, false);
+            }
+        };
+    }
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SqlMinAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SqlMinAggregateDescriptor.java
new file mode 100644
index 0000000..fe934f8
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SqlMinAggregateDescriptor.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2009-2013 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.aggregates.std;
+
+import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
+import edu.uci.ics.asterix.runtime.aggregates.base.AbstractAggregateFunctionDynamicDescriptor;
+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.ICopyAggregateFunction;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyAggregateFunctionFactory;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.data.std.api.IDataOutputProvider;
+
+public class SqlMinAggregateDescriptor extends AbstractAggregateFunctionDynamicDescriptor {
+
+    private static final long serialVersionUID = 1L;
+    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new SqlMinAggregateDescriptor();
+        }
+    };
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return AsterixBuiltinFunctions.SQL_MIN;
+    }
+
+    @Override
+    public ICopyAggregateFunctionFactory createAggregateFunctionFactory(final ICopyEvaluatorFactory[] args)
+            throws AlgebricksException {
+        return new ICopyAggregateFunctionFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public ICopyAggregateFunction createAggregateFunction(final IDataOutputProvider provider)
+                    throws AlgebricksException {
+                return new SqlMinMaxAggregateFunction(args, provider, true, false);
+            }
+        };
+    }
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SqlMinMaxAggregateFunction.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SqlMinMaxAggregateFunction.java
new file mode 100644
index 0000000..56236e3
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SqlMinMaxAggregateFunction.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2009-2013 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.aggregates.std;
+
+import java.io.IOException;
+
+import edu.uci.ics.asterix.om.types.ATypeTag;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.data.std.api.IDataOutputProvider;
+
+public class SqlMinMaxAggregateFunction extends AbstractMinMaxAggregateFunction {
+    private final boolean isLocalAgg;
+
+    public SqlMinMaxAggregateFunction(ICopyEvaluatorFactory[] args, IDataOutputProvider provider, boolean isMin,
+            boolean isLocalAgg) throws AlgebricksException {
+        super(args, provider, isMin);
+        this.isLocalAgg = isLocalAgg;
+    }
+
+    @Override
+    protected void processNull() {
+    }
+
+    @Override
+    protected void processSystemNull() throws AlgebricksException {
+        if (isLocalAgg) {
+            throw new AlgebricksException("Type SYSTEM_NULL encountered in local aggregate.");
+        }
+    }
+
+    @Override
+    protected void finishSystemNull() throws IOException {
+        // Empty stream. For local agg return system null. For global agg return null.
+        if (isLocalAgg) {
+            out.writeByte(ATypeTag.SYSTEM_NULL.serialize());
+        } else {
+            out.writeByte(ATypeTag.NULL.serialize());
+        }
+    }
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SqlSumAggregateDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SqlSumAggregateDescriptor.java
new file mode 100644
index 0000000..294d9c1
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SqlSumAggregateDescriptor.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2009-2013 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.aggregates.std;
+
+import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
+import edu.uci.ics.asterix.runtime.aggregates.base.AbstractAggregateFunctionDynamicDescriptor;
+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.ICopyAggregateFunction;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyAggregateFunctionFactory;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.data.std.api.IDataOutputProvider;
+
+public class SqlSumAggregateDescriptor extends AbstractAggregateFunctionDynamicDescriptor {
+
+    private static final long serialVersionUID = 1L;
+    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new SqlSumAggregateDescriptor();
+        }
+    };
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return AsterixBuiltinFunctions.SQL_SUM;
+    }
+
+    @Override
+    public ICopyAggregateFunctionFactory createAggregateFunctionFactory(final ICopyEvaluatorFactory[] args)
+            throws AlgebricksException {
+        return new ICopyAggregateFunctionFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public ICopyAggregateFunction createAggregateFunction(final IDataOutputProvider provider)
+                    throws AlgebricksException {
+                return new SqlSumAggregateFunction(args, provider, false);
+            };
+        };
+    }
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SqlSumAggregateFunction.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SqlSumAggregateFunction.java
new file mode 100644
index 0000000..4418288
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SqlSumAggregateFunction.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2009-2013 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.aggregates.std;
+
+import java.io.IOException;
+
+import edu.uci.ics.asterix.formats.nontagged.AqlSerializerDeserializerProvider;
+import edu.uci.ics.asterix.om.base.ANull;
+import edu.uci.ics.asterix.om.types.ATypeTag;
+import edu.uci.ics.asterix.om.types.BuiltinType;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.data.std.api.IDataOutputProvider;
+
+public class SqlSumAggregateFunction extends AbstractSumAggregateFunction {
+    private final boolean isLocalAgg;
+    
+    public SqlSumAggregateFunction(ICopyEvaluatorFactory[] args, IDataOutputProvider provider, boolean isLocalAgg)
+            throws AlgebricksException {
+        super(args, provider);
+        this.isLocalAgg = isLocalAgg;
+    }
+
+    @Override
+    protected void processNull() {
+    }
+
+    @Override
+    protected void processSystemNull() throws AlgebricksException {
+        // For global aggregates simply ignore system null here,
+        // but if all input value are system null, then we should return
+        // null in finish().
+        if (isLocalAgg) {
+            throw new AlgebricksException("Type SYSTEM_NULL encountered in local aggregate.");
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    protected void finishSystemNull() throws IOException {
+        // Empty stream. For local agg return system null. For global agg return null.
+        if (isLocalAgg) {
+            out.writeByte(ATypeTag.SYSTEM_NULL.serialize());
+        } else {
+            serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ANULL);
+            serde.serialize(ANull.NULL, out);
+        }
+    }
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SumAggregateFunction.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SumAggregateFunction.java
index 31ad055..42b0346 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SumAggregateFunction.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/aggregates/std/SumAggregateFunction.java
@@ -14,202 +14,54 @@
  */
 package edu.uci.ics.asterix.runtime.aggregates.std;
 
-import java.io.DataOutput;
 import java.io.IOException;
 
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.ADoubleSerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AFloatSerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt16SerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt32SerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt64SerializerDeserializer;
-import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt8SerializerDeserializer;
 import edu.uci.ics.asterix.formats.nontagged.AqlSerializerDeserializerProvider;
-import edu.uci.ics.asterix.om.base.AMutableDouble;
-import edu.uci.ics.asterix.om.base.AMutableFloat;
-import edu.uci.ics.asterix.om.base.AMutableInt16;
-import edu.uci.ics.asterix.om.base.AMutableInt32;
-import edu.uci.ics.asterix.om.base.AMutableInt64;
-import edu.uci.ics.asterix.om.base.AMutableInt8;
 import edu.uci.ics.asterix.om.base.ANull;
 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.types.hierachy.ATypeHierarchy;
 import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
-import edu.uci.ics.hyracks.algebricks.common.exceptions.NotImplementedException;
-import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyAggregateFunction;
-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;
 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;
 
-public class SumAggregateFunction implements ICopyAggregateFunction {
-    private DataOutput out;
-    private ArrayBackedValueStorage inputVal = new ArrayBackedValueStorage();
-    private ICopyEvaluator eval;
-    private double sum;
-    private ATypeTag aggType;
-    private AMutableDouble aDouble = new AMutableDouble(0);
-    private AMutableFloat aFloat = new AMutableFloat(0);
-    private AMutableInt64 aInt64 = new AMutableInt64(0);
-    private AMutableInt32 aInt32 = new AMutableInt32(0);
-    private AMutableInt16 aInt16 = new AMutableInt16((short) 0);
-    private AMutableInt8 aInt8 = new AMutableInt8((byte) 0);
-    @SuppressWarnings("rawtypes")
-    private ISerializerDeserializer serde;
-
+public class SumAggregateFunction extends AbstractSumAggregateFunction {
     private final boolean isLocalAgg;
 
     public SumAggregateFunction(ICopyEvaluatorFactory[] args, IDataOutputProvider provider, boolean isLocalAgg)
             throws AlgebricksException {
-        out = provider.getDataOutput();
-        eval = args[0].createEvaluator(inputVal);
+        super(args, provider);
         this.isLocalAgg = isLocalAgg;
     }
 
     @Override
-    public void init() {
-        aggType = ATypeTag.SYSTEM_NULL;
-        sum = 0.0;
+    protected boolean skipStep() { 
+        return (aggType == ATypeTag.NULL);
     }
 
     @Override
-    public void step(IFrameTupleReference tuple) throws AlgebricksException {
-        inputVal.reset();
-        eval.evaluate(tuple);
-        ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(inputVal.getByteArray()[0]);
-        if (typeTag == ATypeTag.NULL || aggType == ATypeTag.NULL) {
-            aggType = ATypeTag.NULL;
-            return;
-        } else if (aggType == ATypeTag.SYSTEM_NULL) {
-            aggType = typeTag;
-        } else if (typeTag != ATypeTag.SYSTEM_NULL && !ATypeHierarchy.isCompatible(typeTag, aggType)) {
-            throw new AlgebricksException("Unexpected type " + typeTag
-                    + " in aggregation input stream. Expected type (or a promotable type to)" + aggType + ".");
-        }
+    protected void processNull() {
+        aggType = ATypeTag.NULL;
+    }
 
-        if (ATypeHierarchy.canPromote(aggType, typeTag)) {
-            aggType = typeTag;
-        }
-
-        switch (typeTag) {
-            case INT8: {
-                byte val = AInt8SerializerDeserializer.getByte(inputVal.getByteArray(), 1);
-                sum += val;
-                break;
-            }
-            case INT16: {
-                short val = AInt16SerializerDeserializer.getShort(inputVal.getByteArray(), 1);
-                sum += val;
-                break;
-            }
-            case INT32: {
-                int val = AInt32SerializerDeserializer.getInt(inputVal.getByteArray(), 1);
-                sum += val;
-                break;
-            }
-            case INT64: {
-                long val = AInt64SerializerDeserializer.getLong(inputVal.getByteArray(), 1);
-                sum += val;
-                break;
-            }
-            case FLOAT: {
-                float val = AFloatSerializerDeserializer.getFloat(inputVal.getByteArray(), 1);
-                sum += val;
-                break;
-            }
-            case DOUBLE: {
-                double val = ADoubleSerializerDeserializer.getDouble(inputVal.getByteArray(), 1);
-                sum += val;
-                break;
-            }
-            case NULL: {
-                break;
-            }
-            case SYSTEM_NULL: {
-                // For global aggregates simply ignore system null here,
-                // but if all input value are system null, then we should return
-                // null in finish().
-                if (isLocalAgg) {
-                    throw new AlgebricksException("Type SYSTEM_NULL encountered in local aggregate.");
-                }
-                break;
-            }
-            default: {
-                throw new NotImplementedException("Cannot compute SUM for values of type " + typeTag + ".");
-            }
+    @Override
+    protected void processSystemNull() throws AlgebricksException {
+        // For global aggregates simply ignore system null here,
+        // but if all input value are system null, then we should return
+        // null in finish().
+        if (isLocalAgg) {
+            throw new AlgebricksException("Type SYSTEM_NULL encountered in local aggregate.");
         }
     }
 
     @SuppressWarnings("unchecked")
     @Override
-    public void finish() throws AlgebricksException {
-        try {
-            switch (aggType) {
-                case INT8: {
-                    serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AINT8);
-                    aInt8.setValue((byte) sum);
-                    serde.serialize(aInt8, out);
-                    break;
-                }
-                case INT16: {
-                    serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AINT16);
-                    aInt16.setValue((short) sum);
-                    serde.serialize(aInt16, out);
-                    break;
-                }
-                case INT32: {
-                    serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AINT32);
-                    aInt32.setValue((int) sum);
-                    serde.serialize(aInt32, out);
-                    break;
-                }
-                case INT64: {
-                    serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AINT64);
-                    aInt64.setValue((long) sum);
-                    serde.serialize(aInt64, out);
-                    break;
-                }
-                case FLOAT: {
-                    serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AFLOAT);
-                    aFloat.setValue((float) sum);
-                    serde.serialize(aFloat, out);
-                    break;
-                }
-                case DOUBLE: {
-                    serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ADOUBLE);
-                    aDouble.setValue(sum);
-                    serde.serialize(aDouble, out);
-                    break;
-                }
-                case NULL: {
-                    serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ANULL);
-                    serde.serialize(ANull.NULL, out);
-                    break;
-                }
-                case SYSTEM_NULL: {
-                    // Empty stream. For local agg return system null. For global agg return null.
-                    if (isLocalAgg) {
-                        out.writeByte(ATypeTag.SYSTEM_NULL.serialize());
-                    } else {
-                        serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ANULL);
-                        serde.serialize(ANull.NULL, out);
-                    }
-                    break;
-                }
-                default:
-                    throw new AlgebricksException("SumAggregationFunction: incompatible type for the result ("
-                            + aggType + "). ");
-            }
-        } catch (IOException e) {
-            throw new AlgebricksException(e);
+    protected void finishSystemNull() throws IOException {
+        // Empty stream. For local agg return system null. For global agg return null.
+        if (isLocalAgg) {
+            out.writeByte(ATypeTag.SYSTEM_NULL.serialize());
+        } else {
+            serde = AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ANULL);
+            serde.serialize(ANull.NULL, out);
         }
     }
-
-    @Override
-    public void finishPartial() throws AlgebricksException {
-        finish();
-    }
 }
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/formats/NonTaggedDataFormat.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/formats/NonTaggedDataFormat.java
index ea75c77..5ae2459 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/formats/NonTaggedDataFormat.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/formats/NonTaggedDataFormat.java
@@ -65,22 +65,43 @@
 import edu.uci.ics.asterix.runtime.aggregates.scalar.ScalarCountAggregateDescriptor;
 import edu.uci.ics.asterix.runtime.aggregates.scalar.ScalarMaxAggregateDescriptor;
 import edu.uci.ics.asterix.runtime.aggregates.scalar.ScalarMinAggregateDescriptor;
+import edu.uci.ics.asterix.runtime.aggregates.scalar.ScalarSqlAvgAggregateDescriptor;
+import edu.uci.ics.asterix.runtime.aggregates.scalar.ScalarSqlCountAggregateDescriptor;
+import edu.uci.ics.asterix.runtime.aggregates.scalar.ScalarSqlMaxAggregateDescriptor;
+import edu.uci.ics.asterix.runtime.aggregates.scalar.ScalarSqlMinAggregateDescriptor;
+import edu.uci.ics.asterix.runtime.aggregates.scalar.ScalarSqlSumAggregateDescriptor;
 import edu.uci.ics.asterix.runtime.aggregates.scalar.ScalarSumAggregateDescriptor;
 import edu.uci.ics.asterix.runtime.aggregates.serializable.std.SerializableAvgAggregateDescriptor;
 import edu.uci.ics.asterix.runtime.aggregates.serializable.std.SerializableCountAggregateDescriptor;
 import edu.uci.ics.asterix.runtime.aggregates.serializable.std.SerializableGlobalAvgAggregateDescriptor;
+import edu.uci.ics.asterix.runtime.aggregates.serializable.std.SerializableGlobalSqlAvgAggregateDescriptor;
 import edu.uci.ics.asterix.runtime.aggregates.serializable.std.SerializableLocalAvgAggregateDescriptor;
+import edu.uci.ics.asterix.runtime.aggregates.serializable.std.SerializableLocalSqlAvgAggregateDescriptor;
+import edu.uci.ics.asterix.runtime.aggregates.serializable.std.SerializableLocalSqlSumAggregateDescriptor;
 import edu.uci.ics.asterix.runtime.aggregates.serializable.std.SerializableLocalSumAggregateDescriptor;
+import edu.uci.ics.asterix.runtime.aggregates.serializable.std.SerializableSqlAvgAggregateDescriptor;
+import edu.uci.ics.asterix.runtime.aggregates.serializable.std.SerializableSqlCountAggregateDescriptor;
+import edu.uci.ics.asterix.runtime.aggregates.serializable.std.SerializableSqlSumAggregateDescriptor;
 import edu.uci.ics.asterix.runtime.aggregates.serializable.std.SerializableSumAggregateDescriptor;
 import edu.uci.ics.asterix.runtime.aggregates.std.AvgAggregateDescriptor;
 import edu.uci.ics.asterix.runtime.aggregates.std.CountAggregateDescriptor;
 import edu.uci.ics.asterix.runtime.aggregates.std.GlobalAvgAggregateDescriptor;
+import edu.uci.ics.asterix.runtime.aggregates.std.GlobalSqlAvgAggregateDescriptor;
 import edu.uci.ics.asterix.runtime.aggregates.std.LocalAvgAggregateDescriptor;
 import edu.uci.ics.asterix.runtime.aggregates.std.LocalMaxAggregateDescriptor;
 import edu.uci.ics.asterix.runtime.aggregates.std.LocalMinAggregateDescriptor;
+import edu.uci.ics.asterix.runtime.aggregates.std.LocalSqlAvgAggregateDescriptor;
+import edu.uci.ics.asterix.runtime.aggregates.std.LocalSqlMaxAggregateDescriptor;
+import edu.uci.ics.asterix.runtime.aggregates.std.LocalSqlMinAggregateDescriptor;
+import edu.uci.ics.asterix.runtime.aggregates.std.LocalSqlSumAggregateDescriptor;
 import edu.uci.ics.asterix.runtime.aggregates.std.LocalSumAggregateDescriptor;
 import edu.uci.ics.asterix.runtime.aggregates.std.MaxAggregateDescriptor;
 import edu.uci.ics.asterix.runtime.aggregates.std.MinAggregateDescriptor;
+import edu.uci.ics.asterix.runtime.aggregates.std.SqlAvgAggregateDescriptor;
+import edu.uci.ics.asterix.runtime.aggregates.std.SqlCountAggregateDescriptor;
+import edu.uci.ics.asterix.runtime.aggregates.std.SqlMaxAggregateDescriptor;
+import edu.uci.ics.asterix.runtime.aggregates.std.SqlMinAggregateDescriptor;
+import edu.uci.ics.asterix.runtime.aggregates.std.SqlSumAggregateDescriptor;
 import edu.uci.ics.asterix.runtime.aggregates.std.SumAggregateDescriptor;
 import edu.uci.ics.asterix.runtime.aggregates.stream.EmptyStreamAggregateDescriptor;
 import edu.uci.ics.asterix.runtime.aggregates.stream.NonEmptyStreamAggregateDescriptor;
@@ -426,6 +447,33 @@
         temp.add(ScalarMaxAggregateDescriptor.FACTORY);
         temp.add(ScalarMinAggregateDescriptor.FACTORY);
 
+        // SQL aggregates
+        temp.add(SqlCountAggregateDescriptor.FACTORY);
+        temp.add(SqlAvgAggregateDescriptor.FACTORY);
+        temp.add(LocalSqlAvgAggregateDescriptor.FACTORY);
+        temp.add(GlobalSqlAvgAggregateDescriptor.FACTORY);
+        temp.add(SqlSumAggregateDescriptor.FACTORY);
+        temp.add(LocalSqlSumAggregateDescriptor.FACTORY);
+        temp.add(SqlMaxAggregateDescriptor.FACTORY);
+        temp.add(LocalSqlMaxAggregateDescriptor.FACTORY);
+        temp.add(SqlMinAggregateDescriptor.FACTORY);
+        temp.add(LocalSqlMinAggregateDescriptor.FACTORY);
+
+        // SQL serializable aggregates
+        temp.add(SerializableSqlCountAggregateDescriptor.FACTORY);
+        temp.add(SerializableSqlAvgAggregateDescriptor.FACTORY);
+        temp.add(SerializableLocalSqlAvgAggregateDescriptor.FACTORY);
+        temp.add(SerializableGlobalSqlAvgAggregateDescriptor.FACTORY);
+        temp.add(SerializableSqlSumAggregateDescriptor.FACTORY);
+        temp.add(SerializableLocalSqlSumAggregateDescriptor.FACTORY);
+
+        // SQL scalar aggregates
+        temp.add(ScalarSqlCountAggregateDescriptor.FACTORY);
+        temp.add(ScalarSqlAvgAggregateDescriptor.FACTORY);
+        temp.add(ScalarSqlSumAggregateDescriptor.FACTORY);
+        temp.add(ScalarSqlMaxAggregateDescriptor.FACTORY);
+        temp.add(ScalarSqlMinAggregateDescriptor.FACTORY);
+
         // new functions - constructors
         temp.add(ABooleanConstructorDescriptor.FACTORY);
         temp.add(ANullConstructorDescriptor.FACTORY);