http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.82.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.82.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.82.adm
new file mode 100644
index 0000000..28dffeb
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.82.adm
@@ -0,0 +1,10 @@
+{ "last_value": 4, "ten": 0, "four": 0 }
+{ "last_value": 4, "ten": 0, "four": 0 }
+{ "last_value": 4, "ten": 4, "four": 0 }
+{ "last_value": 9, "ten": 1, "four": 1 }
+{ "last_value": 9, "ten": 1, "four": 1 }
+{ "last_value": 9, "ten": 7, "four": 1 }
+{ "last_value": 9, "ten": 9, "four": 1 }
+{ "last_value": 0, "ten": 0, "four": 2 }
+{ "last_value": 3, "ten": 1, "four": 3 }
+{ "last_value": 3, "ten": 3, "four": 3 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.83.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.83.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.83.adm
new file mode 100644
index 0000000..8dc1715
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.83.adm
@@ -0,0 +1,10 @@
+{ "nth_value": 0, "ten": 0, "four": 0 }
+{ "nth_value": 0, "ten": 0, "four": 0 }
+{ "nth_value": 0, "ten": 4, "four": 0 }
+{ "nth_value": 1, "ten": 1, "four": 1 }
+{ "nth_value": 1, "ten": 1, "four": 1 }
+{ "nth_value": 1, "ten": 7, "four": 1 }
+{ "nth_value": 1, "ten": 9, "four": 1 }
+{ "nth_value": null, "ten": 0, "four": 2 }
+{ "nth_value": null, "ten": 1, "four": 3 }
+{ "nth_value": null, "ten": 3, "four": 3 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.84.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.84.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.84.adm
new file mode 100644
index 0000000..28eff74
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.84.adm
@@ -0,0 +1,20 @@
+{ "four": 0, "ten": 0, "sum": 0, "last_value": 0 }
+{ "four": 0, "ten": 2, "sum": 2, "last_value": 2 }
+{ "four": 0, "ten": 4, "sum": 6, "last_value": 4 }
+{ "four": 0, "ten": 6, "sum": 12, "last_value": 6 }
+{ "four": 0, "ten": 8, "sum": 20, "last_value": 8 }
+{ "four": 1, "ten": 1, "sum": 1, "last_value": 1 }
+{ "four": 1, "ten": 3, "sum": 4, "last_value": 3 }
+{ "four": 1, "ten": 5, "sum": 9, "last_value": 5 }
+{ "four": 1, "ten": 7, "sum": 16, "last_value": 7 }
+{ "four": 1, "ten": 9, "sum": 25, "last_value": 9 }
+{ "four": 2, "ten": 0, "sum": 0, "last_value": 0 }
+{ "four": 2, "ten": 2, "sum": 2, "last_value": 2 }
+{ "four": 2, "ten": 4, "sum": 6, "last_value": 4 }
+{ "four": 2, "ten": 6, "sum": 12, "last_value": 6 }
+{ "four": 2, "ten": 8, "sum": 20, "last_value": 8 }
+{ "four": 3, "ten": 1, "sum": 1, "last_value": 1 }
+{ "four": 3, "ten": 3, "sum": 4, "last_value": 3 }
+{ "four": 3, "ten": 5, "sum": 9, "last_value": 5 }
+{ "four": 3, "ten": 7, "sum": 16, "last_value": 7 }
+{ "four": 3, "ten": 9, "sum": 25, "last_value": 9 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.85.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.85.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.85.adm
new file mode 100644
index 0000000..28eff74
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.85.adm
@@ -0,0 +1,20 @@
+{ "four": 0, "ten": 0, "sum": 0, "last_value": 0 }
+{ "four": 0, "ten": 2, "sum": 2, "last_value": 2 }
+{ "four": 0, "ten": 4, "sum": 6, "last_value": 4 }
+{ "four": 0, "ten": 6, "sum": 12, "last_value": 6 }
+{ "four": 0, "ten": 8, "sum": 20, "last_value": 8 }
+{ "four": 1, "ten": 1, "sum": 1, "last_value": 1 }
+{ "four": 1, "ten": 3, "sum": 4, "last_value": 3 }
+{ "four": 1, "ten": 5, "sum": 9, "last_value": 5 }
+{ "four": 1, "ten": 7, "sum": 16, "last_value": 7 }
+{ "four": 1, "ten": 9, "sum": 25, "last_value": 9 }
+{ "four": 2, "ten": 0, "sum": 0, "last_value": 0 }
+{ "four": 2, "ten": 2, "sum": 2, "last_value": 2 }
+{ "four": 2, "ten": 4, "sum": 6, "last_value": 4 }
+{ "four": 2, "ten": 6, "sum": 12, "last_value": 6 }
+{ "four": 2, "ten": 8, "sum": 20, "last_value": 8 }
+{ "four": 3, "ten": 1, "sum": 1, "last_value": 1 }
+{ "four": 3, "ten": 3, "sum": 4, "last_value": 3 }
+{ "four": 3, "ten": 5, "sum": 9, "last_value": 5 }
+{ "four": 3, "ten": 7, "sum": 16, "last_value": 7 }
+{ "four": 3, "ten": 9, "sum": 25, "last_value": 9 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.86.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.86.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.86.adm
new file mode 100644
index 0000000..97f0a4f
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.86.adm
@@ -0,0 +1,20 @@
+{ "four": 0, "ten": 0, "sum": 20, "last_value": 8 }
+{ "four": 0, "ten": 2, "sum": 20, "last_value": 8 }
+{ "four": 0, "ten": 4, "sum": 20, "last_value": 8 }
+{ "four": 0, "ten": 6, "sum": 20, "last_value": 8 }
+{ "four": 0, "ten": 8, "sum": 20, "last_value": 8 }
+{ "four": 1, "ten": 1, "sum": 25, "last_value": 9 }
+{ "four": 1, "ten": 3, "sum": 25, "last_value": 9 }
+{ "four": 1, "ten": 5, "sum": 25, "last_value": 9 }
+{ "four": 1, "ten": 7, "sum": 25, "last_value": 9 }
+{ "four": 1, "ten": 9, "sum": 25, "last_value": 9 }
+{ "four": 2, "ten": 0, "sum": 20, "last_value": 8 }
+{ "four": 2, "ten": 2, "sum": 20, "last_value": 8 }
+{ "four": 2, "ten": 4, "sum": 20, "last_value": 8 }
+{ "four": 2, "ten": 6, "sum": 20, "last_value": 8 }
+{ "four": 2, "ten": 8, "sum": 20, "last_value": 8 }
+{ "four": 3, "ten": 1, "sum": 25, "last_value": 9 }
+{ "four": 3, "ten": 3, "sum": 25, "last_value": 9 }
+{ "four": 3, "ten": 5, "sum": 25, "last_value": 9 }
+{ "four": 3, "ten": 7, "sum": 25, "last_value": 9 }
+{ "four": 3, "ten": 9, "sum": 25, "last_value": 9 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.87.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.87.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.87.adm
new file mode 100644
index 0000000..7709a85
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.87.adm
@@ -0,0 +1,20 @@
+{ "four": 0, "two": 0, "sum": 0, "last_value": 0 }
+{ "four": 0, "two": 0, "sum": 0, "last_value": 0 }
+{ "four": 0, "two": 1, "sum": 2, "last_value": 1 }
+{ "four": 0, "two": 1, "sum": 2, "last_value": 1 }
+{ "four": 0, "two": 2, "sum": 4, "last_value": 2 }
+{ "four": 1, "two": 0, "sum": 0, "last_value": 0 }
+{ "four": 1, "two": 0, "sum": 0, "last_value": 0 }
+{ "four": 1, "two": 1, "sum": 2, "last_value": 1 }
+{ "four": 1, "two": 1, "sum": 2, "last_value": 1 }
+{ "four": 1, "two": 2, "sum": 4, "last_value": 2 }
+{ "four": 2, "two": 0, "sum": 0, "last_value": 0 }
+{ "four": 2, "two": 0, "sum": 0, "last_value": 0 }
+{ "four": 2, "two": 1, "sum": 2, "last_value": 1 }
+{ "four": 2, "two": 1, "sum": 2, "last_value": 1 }
+{ "four": 2, "two": 2, "sum": 4, "last_value": 2 }
+{ "four": 3, "two": 0, "sum": 0, "last_value": 0 }
+{ "four": 3, "two": 0, "sum": 0, "last_value": 0 }
+{ "four": 3, "two": 1, "sum": 2, "last_value": 1 }
+{ "four": 3, "two": 1, "sum": 2, "last_value": 1 }
+{ "four": 3, "two": 2, "sum": 4, "last_value": 2 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.88.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.88.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.88.adm
new file mode 100644
index 0000000..25038e6
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.88.adm
@@ -0,0 +1,20 @@
+{ "four": 0, "two": 0, "sum": 0, "last_value": 0 }
+{ "four": 0, "two": 0, "sum": 0, "last_value": 0 }
+{ "four": 0, "two": 1, "sum": 1, "last_value": 1 }
+{ "four": 0, "two": 1, "sum": 2, "last_value": 1 }
+{ "four": 0, "two": 2, "sum": 4, "last_value": 2 }
+{ "four": 1, "two": 0, "sum": 0, "last_value": 0 }
+{ "four": 1, "two": 0, "sum": 0, "last_value": 0 }
+{ "four": 1, "two": 1, "sum": 1, "last_value": 1 }
+{ "four": 1, "two": 1, "sum": 2, "last_value": 1 }
+{ "four": 1, "two": 2, "sum": 4, "last_value": 2 }
+{ "four": 2, "two": 0, "sum": 0, "last_value": 0 }
+{ "four": 2, "two": 0, "sum": 0, "last_value": 0 }
+{ "four": 2, "two": 1, "sum": 1, "last_value": 1 }
+{ "four": 2, "two": 1, "sum": 2, "last_value": 1 }
+{ "four": 2, "two": 2, "sum": 4, "last_value": 2 }
+{ "four": 3, "two": 0, "sum": 0, "last_value": 0 }
+{ "four": 3, "two": 0, "sum": 0, "last_value": 0 }
+{ "four": 3, "two": 1, "sum": 1, "last_value": 1 }
+{ "four": 3, "two": 1, "sum": 2, "last_value": 1 }
+{ "four": 3, "two": 2, "sum": 4, "last_value": 2 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.89.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.89.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.89.adm
new file mode 100644
index 0000000..cb719b4
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.89.adm
@@ -0,0 +1,10 @@
+{ "unique1": 0, "four": 0, "first_value": 8 }
+{ "unique1": 8, "four": 0, "first_value": 4 }
+{ "unique1": 4, "four": 0, "first_value": 5 }
+{ "unique1": 5, "four": 1, "first_value": 9 }
+{ "unique1": 9, "four": 1, "first_value": 1 }
+{ "unique1": 1, "four": 1, "first_value": 6 }
+{ "unique1": 6, "four": 2, "first_value": 2 }
+{ "unique1": 2, "four": 2, "first_value": 7 }
+{ "unique1": 7, "four": 3, "first_value": 3 }
+{ "unique1": 3, "four": 3, "first_value": null }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.9.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.9.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.9.adm
new file mode 100644
index 0000000..5eed6f0
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.9.adm
@@ -0,0 +1,10 @@
+{ "dense_rank": 1, "ten": 0, "four": 0 }
+{ "dense_rank": 1, "ten": 0, "four": 0 }
+{ "dense_rank": 2, "ten": 4, "four": 0 }
+{ "dense_rank": 1, "ten": 1, "four": 1 }
+{ "dense_rank": 1, "ten": 1, "four": 1 }
+{ "dense_rank": 2, "ten": 7, "four": 1 }
+{ "dense_rank": 3, "ten": 9, "four": 1 }
+{ "dense_rank": 1, "ten": 0, "four": 2 }
+{ "dense_rank": 1, "ten": 1, "four": 3 }
+{ "dense_rank": 2, "ten": 3, "four": 3 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.90.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.90.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.90.adm
new file mode 100644
index 0000000..e8a57d0
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.90.adm
@@ -0,0 +1,10 @@
+{ "unique1": 0, "four": 0, "first_value": null }
+{ "unique1": 8, "four": 0, "first_value": 5 }
+{ "unique1": 4, "four": 0, "first_value": 5 }
+{ "unique1": 5, "four": 1, "first_value": null }
+{ "unique1": 9, "four": 1, "first_value": 6 }
+{ "unique1": 1, "four": 1, "first_value": 6 }
+{ "unique1": 6, "four": 2, "first_value": 7 }
+{ "unique1": 2, "four": 2, "first_value": 7 }
+{ "unique1": 7, "four": 3, "first_value": null }
+{ "unique1": 3, "four": 3, "first_value": null }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.91.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.91.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.91.adm
new file mode 100644
index 0000000..ddbad02
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.91.adm
@@ -0,0 +1,10 @@
+{ "unique1": 0, "four": 0, "first_value": 0 }
+{ "unique1": 8, "four": 0, "first_value": 8 }
+{ "unique1": 4, "four": 0, "first_value": 4 }
+{ "unique1": 5, "four": 1, "first_value": 5 }
+{ "unique1": 9, "four": 1, "first_value": 9 }
+{ "unique1": 1, "four": 1, "first_value": 1 }
+{ "unique1": 6, "four": 2, "first_value": 6 }
+{ "unique1": 2, "four": 2, "first_value": 2 }
+{ "unique1": 7, "four": 3, "first_value": 7 }
+{ "unique1": 3, "four": 3, "first_value": 3 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.92.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.92.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.92.adm
new file mode 100644
index 0000000..bdfb1d9
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.92.adm
@@ -0,0 +1,10 @@
+{ "unique1": 0, "four": 0, "last_value": 4 }
+{ "unique1": 8, "four": 0, "last_value": 5 }
+{ "unique1": 4, "four": 0, "last_value": 9 }
+{ "unique1": 5, "four": 1, "last_value": 1 }
+{ "unique1": 9, "four": 1, "last_value": 6 }
+{ "unique1": 1, "four": 1, "last_value": 2 }
+{ "unique1": 6, "four": 2, "last_value": 7 }
+{ "unique1": 2, "four": 2, "last_value": 3 }
+{ "unique1": 7, "four": 3, "last_value": 3 }
+{ "unique1": 3, "four": 3, "last_value": null }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.93.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.93.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.93.adm
new file mode 100644
index 0000000..dfeed13
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.93.adm
@@ -0,0 +1,10 @@
+{ "unique1": 0, "four": 0, "last_value": null }
+{ "unique1": 8, "four": 0, "last_value": 5 }
+{ "unique1": 4, "four": 0, "last_value": 9 }
+{ "unique1": 5, "four": 1, "last_value": null }
+{ "unique1": 9, "four": 1, "last_value": 6 }
+{ "unique1": 1, "four": 1, "last_value": 2 }
+{ "unique1": 6, "four": 2, "last_value": 7 }
+{ "unique1": 2, "four": 2, "last_value": 3 }
+{ "unique1": 7, "four": 3, "last_value": null }
+{ "unique1": 3, "four": 3, "last_value": null }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.94.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.94.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.94.adm
new file mode 100644
index 0000000..ebff40e
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.94.adm
@@ -0,0 +1,10 @@
+{ "unique1": 0, "four": 0, "last_value": 0 }
+{ "unique1": 8, "four": 0, "last_value": 5 }
+{ "unique1": 4, "four": 0, "last_value": 9 }
+{ "unique1": 5, "four": 1, "last_value": 5 }
+{ "unique1": 9, "four": 1, "last_value": 6 }
+{ "unique1": 1, "four": 1, "last_value": 2 }
+{ "unique1": 6, "four": 2, "last_value": 7 }
+{ "unique1": 2, "four": 2, "last_value": 3 }
+{ "unique1": 7, "four": 3, "last_value": 7 }
+{ "unique1": 3, "four": 3, "last_value": 3 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.95.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.95.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.95.adm
new file mode 100644
index 0000000..7f2030b
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.95.adm
@@ -0,0 +1,10 @@
+{ "unique1": 0, "four": 0, "first_value": 0, "nth_2": 8, "last_value": 3 }
+{ "unique1": 8, "four": 0, "first_value": 0, "nth_2": 8, "last_value": 3 }
+{ "unique1": 4, "four": 0, "first_value": 0, "nth_2": 8, "last_value": 3 }
+{ "unique1": 5, "four": 1, "first_value": 5, "nth_2": 9, "last_value": 3 }
+{ "unique1": 9, "four": 1, "first_value": 5, "nth_2": 9, "last_value": 3 }
+{ "unique1": 1, "four": 1, "first_value": 5, "nth_2": 9, "last_value": 3 }
+{ "unique1": 6, "four": 2, "first_value": 6, "nth_2": 2, "last_value": 3 }
+{ "unique1": 2, "four": 2, "first_value": 6, "nth_2": 2, "last_value": 3 }
+{ "unique1": 7, "four": 3, "first_value": 7, "nth_2": 3, "last_value": 3 }
+{ "unique1": 3, "four": 3, "first_value": 7, "nth_2": 3, "last_value": 3 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.96.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.96.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.96.adm
new file mode 100644
index 0000000..a0c8b34
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.96.adm
@@ -0,0 +1,10 @@
+{ "salary": 3500, "first_value": 3500, "lead": 3900, "nth_value": 3500 }
+{ "salary": 3900, "first_value": 3500, "lead": 4200, "nth_value": 3500 }
+{ "salary": 4200, "first_value": 3500, "lead": 4500, "nth_value": 3500 }
+{ "salary": 4500, "first_value": 3500, "lead": 4800, "nth_value": 3500 }
+{ "salary": 4800, "first_value": 3900, "lead": 4800, "nth_value": 3900 }
+{ "salary": 4800, "first_value": 3900, "lead": 5000, "nth_value": 3900 }
+{ "salary": 5000, "first_value": 4200, "lead": 5200, "nth_value": 4200 }
+{ "salary": 5200, "first_value": 4200, "lead": 5200, "nth_value": 4200 }
+{ "salary": 5200, "first_value": 4200, "lead": 6000, "nth_value": 4200 }
+{ "salary": 6000, "first_value": 5000, "lead": null, "nth_value": 5000 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.97.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.97.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.97.adm
new file mode 100644
index 0000000..826e4b5
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.97.adm
@@ -0,0 +1,10 @@
+{ "salary": 3500, "last_value": 4500, "lag": null }
+{ "salary": 3900, "last_value": 4800, "lag": 3500 }
+{ "salary": 4200, "last_value": 5200, "lag": 3900 }
+{ "salary": 4500, "last_value": 5200, "lag": 4200 }
+{ "salary": 4800, "last_value": 5200, "lag": 4500 }
+{ "salary": 4800, "last_value": 5200, "lag": 4800 }
+{ "salary": 5000, "last_value": 6000, "lag": 4800 }
+{ "salary": 5200, "last_value": 6000, "lag": 5000 }
+{ "salary": 5200, "last_value": 6000, "lag": 5200 }
+{ "salary": 6000, "last_value": 6000, "lag": 5200 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.98.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.98.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.98.adm
new file mode 100644
index 0000000..3526e5f
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.98.adm
@@ -0,0 +1,10 @@
+{ "salary": 3500, "first_value": 4500, "lead": 3900, "nth_value": 4500 }
+{ "salary": 3900, "first_value": 5000, "lead": 4200, "nth_value": 5000 }
+{ "salary": 4200, "first_value": 5200, "lead": 4500, "nth_value": 5200 }
+{ "salary": 4500, "first_value": 6000, "lead": 4800, "nth_value": 6000 }
+{ "salary": 4800, "first_value": 6000, "lead": 4800, "nth_value": 6000 }
+{ "salary": 4800, "first_value": 6000, "lead": 5000, "nth_value": 6000 }
+{ "salary": 5000, "first_value": 6000, "lead": 5200, "nth_value": 6000 }
+{ "salary": 5200, "first_value": null, "lead": 5200, "nth_value": null }
+{ "salary": 5200, "first_value": null, "lead": 6000, "nth_value": null }
+{ "salary": 6000, "first_value": null, "lead": null, "nth_value": null }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.99.adm
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.99.adm
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.99.adm
new file mode 100644
index 0000000..db59e8b
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results/window/pg_win/pg_win.99.adm
@@ -0,0 +1,10 @@
+{ "salary": 3500, "last_value": 6000, "lag": null }
+{ "salary": 3900, "last_value": 6000, "lag": 3500 }
+{ "salary": 4200, "last_value": 6000, "lag": 3900 }
+{ "salary": 4500, "last_value": 6000, "lag": 4200 }
+{ "salary": 4800, "last_value": 6000, "lag": 4500 }
+{ "salary": 4800, "last_value": 6000, "lag": 4800 }
+{ "salary": 5000, "last_value": 6000, "lag": 4800 }
+{ "salary": 5200, "last_value": null, "lag": 5000 }
+{ "salary": 5200, "last_value": null, "lag": 5200 }
+{ "salary": 6000, "last_value": null, "lag": 5200 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.1.ast
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.1.ast
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.1.ast
new file mode 100644
index 0000000..66bdbda
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.1.ast
@@ -0,0 +1,7 @@
+DataverseUse test
+TypeDecl t1Type [
+  open RecordType {
+    c1 : bigint
+  }
+]
+DatasetDecl t1(t1Type) partitioned by [[c1]]

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.2.ast
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.2.ast
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.2.ast
new file mode 100644
index 0000000..b016508
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.2.ast
@@ -0,0 +1,2 @@
+DataverseUse test
+Set import-private-functions=true

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.3.ast
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.3.ast
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.3.ast
new file mode 100644
index 0000000..528b379
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.3.ast
@@ -0,0 +1,209 @@
+DataverseUse test
+Query:
+Let Variable [ Name=$P ]
+  :=
+  LiteralExpr [LONG] [10]
+Let Variable [ Name=$N ]
+  :=
+  LiteralExpr [LONG] [10]
+Let Variable [ Name=$D ]
+  :=
+  LiteralExpr [LONG] [4]
+SELECT [
+FunctionCall asterix.sql-min@1[
+  (
+    SELECT ELEMENT [
+    FieldAccessor [
+      Variable [ Name=#2 ]
+      Field=rank_result_delta
+    ]
+    ]
+    FROM [      Variable [ Name=#1 ]
+      AS Variable [ Name=#2 ]
+    ]
+  )
+]
+rank_min_delta
+FunctionCall asterix.sql-max@1[
+  (
+    SELECT ELEMENT [
+    FieldAccessor [
+      Variable [ Name=#3 ]
+      Field=rank_result_delta
+    ]
+    ]
+    FROM [      Variable [ Name=#1 ]
+      AS Variable [ Name=#3 ]
+    ]
+  )
+]
+rank_max_delta
+FunctionCall asterix.sql-min@1[
+  (
+    SELECT ELEMENT [
+    FieldAccessor [
+      Variable [ Name=#4 ]
+      Field=percent_rank_result_delta
+    ]
+    ]
+    FROM [      Variable [ Name=#1 ]
+      AS Variable [ Name=#4 ]
+    ]
+  )
+]
+percent_rank_min_delta
+FunctionCall asterix.sql-max@1[
+  (
+    SELECT ELEMENT [
+    FieldAccessor [
+      Variable [ Name=#5 ]
+      Field=percent_rank_result_delta
+    ]
+    ]
+    FROM [      Variable [ Name=#1 ]
+      AS Variable [ Name=#5 ]
+    ]
+  )
+]
+percent_rank_max_delta
+]
+FROM [  FunctionCall asterix.dataset@1[
+    LiteralExpr [STRING] [test.t1]
+  ]
+  AS Variable [ Name=$t1 ]
+,
+  FunctionCall test.range@2[
+    FieldAccessor [
+      Variable [ Name=$t1 ]
+      Field=one
+    ]
+    Variable [ Name=$P ]
+  ]
+  AS Variable [ Name=$p ]
+,
+  FunctionCall test.range@2[
+    FieldAccessor [
+      Variable [ Name=$t1 ]
+      Field=one
+    ]
+    Variable [ Name=$N ]
+  ]
+  AS Variable [ Name=$n ]
+,
+  FunctionCall test.range@2[
+    FieldAccessor [
+      Variable [ Name=$t1 ]
+      Field=one
+    ]
+    Variable [ Name=$D ]
+  ]
+  AS Variable [ Name=$d ]
+]
+Let Variable [ Name=$rank_result_expected ]
+  :=
+  OperatorExpr [
+    OperatorExpr [
+      OperatorExpr [
+        Variable [ Name=$N ]
+        -
+        Variable [ Name=$n ]
+      ]
+      *
+      Variable [ Name=$D ]
+    ]
+    +
+    LiteralExpr [LONG] [1]
+  ]
+Let Variable [ Name=$rank_result_actual ]
+  :=
+  WINDOW test.rank@0[
+  ]
+  OVER (
+    PARTITION BY
+      FieldAccessor [
+        Variable [ Name=$t1 ]
+        Field=c2
+      ]
+      Variable [ Name=$p ]
+    ORDER BY
+      Variable [ Name=$n ]
+      DESC
+  )
+Let Variable [ Name=$rank_result_delta ]
+  :=
+  OperatorExpr [
+    Variable [ Name=$rank_result_expected ]
+    -
+    Variable [ Name=$rank_result_actual ]
+  ]
+Let Variable [ Name=$percent_rank_result_expected ]
+  :=
+  OperatorExpr [
+    OperatorExpr [
+      Variable [ Name=$rank_result_expected ]
+      -
+      LiteralExpr [LONG] [1]
+    ]
+    /
+    OperatorExpr [
+      OperatorExpr [
+        Variable [ Name=$N ]
+        *
+        Variable [ Name=$D ]
+      ]
+      -
+      LiteralExpr [LONG] [1]
+    ]
+  ]
+Let Variable [ Name=$percent_rank_result_actual ]
+  :=
+  WINDOW test.percent_rank@0[
+  ]
+  OVER (
+    PARTITION BY
+      FieldAccessor [
+        Variable [ Name=$t1 ]
+        Field=c2
+      ]
+      Variable [ Name=$p ]
+    ORDER BY
+      Variable [ Name=$n ]
+      DESC
+  )
+Let Variable [ Name=$percent_rank_result_delta_raw ]
+  :=
+  OperatorExpr [
+    Variable [ Name=$percent_rank_result_expected ]
+    -
+    Variable [ Name=$percent_rank_result_actual ]
+  ]
+Let Variable [ Name=$percent_rank_result_delta ]
+  :=
+  CASE      LiteralExpr [TRUE]
+
+  WHEN       OperatorExpr [
+        Variable [ Name=$percent_rank_result_delta_raw ]
+        <
+        LiteralExpr [DOUBLE] [0.001]
+      ]
+  THEN       LiteralExpr [LONG] [0]
+
+  ELSE       Variable [ Name=$percent_rank_result_delta_raw ]
+
+  END
+Group All
+  GROUP AS Variable [ Name=#1 ]
+  (
+    t1:=Variable [ Name=$t1 ]
+    p:=Variable [ Name=$p ]
+    n:=Variable [ Name=$n ]
+    d:=Variable [ Name=$d ]
+    rank_result_expected:=Variable [ Name=$rank_result_expected ]
+    rank_result_actual:=Variable [ Name=$rank_result_actual ]
+    rank_result_delta:=Variable [ Name=$rank_result_delta ]
+    percent_rank_result_expected:=Variable [ 
Name=$percent_rank_result_expected ]
+    percent_rank_result_actual:=Variable [ Name=$percent_rank_result_actual ]
+    percent_rank_result_delta_raw:=Variable [ 
Name=$percent_rank_result_delta_raw ]
+    percent_rank_result_delta:=Variable [ Name=$percent_rank_result_delta ]
+  )
+

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.4.ast
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.4.ast
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.4.ast
new file mode 100644
index 0000000..7330fe9
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.4.ast
@@ -0,0 +1,45 @@
+DataverseUse test
+Query:
+Let Variable [ Name=$P ]
+  :=
+  LiteralExpr [LONG] [4]
+SELECT [
+Variable [ Name=$p ]
+p
+WINDOW test.row_number@0[
+]
+OVER (
+  ORDER BY
+    Variable [ Name=$p ]
+    DESC
+)
+rn
+]
+FROM [  FunctionCall asterix.dataset@1[
+    LiteralExpr [STRING] [test.t1]
+  ]
+  AS Variable [ Name=$t1 ]
+,
+  FunctionCall test.range@2[
+    FieldAccessor [
+      Variable [ Name=$t1 ]
+      Field=one
+    ]
+    Variable [ Name=$P ]
+  ]
+  AS Variable [ Name=$p ]
+]
+Groupby
+  Variable [ Name=$p ]
+  :=
+  Variable [ Name=$p ]
+  GROUP AS Variable [ Name=#1 ]
+  (
+    t1:=Variable [ Name=$t1 ]
+    p:=Variable [ Name=$p ]
+  )
+
+Orderby
+  Variable [ Name=$p ]
+  ASC
+

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.5.ast
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.5.ast
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.5.ast
new file mode 100644
index 0000000..cfad0ae
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.5.ast
@@ -0,0 +1,77 @@
+DataverseUse test
+Query:
+Let Variable [ Name=$P ]
+  :=
+  LiteralExpr [LONG] [4]
+SELECT [
+Variable [ Name=$p ]
+p
+(
+  SELECT [
+  FieldAccessor [
+    FieldAccessor [
+      Variable [ Name=$g ]
+      Field=t1
+    ]
+    Field=c1
+  ]
+  c1
+  WINDOW test.row_number@0[
+  ]
+  OVER (
+    ORDER BY
+      FieldAccessor [
+        FieldAccessor [
+          Variable [ Name=$g ]
+          Field=t1
+        ]
+        Field=c2
+      ]
+      DESC
+  )
+  rn
+  ]
+  FROM [    Variable [ Name=$g ]
+    AS Variable [ Name=$g ]
+  ]
+  Orderby
+    FieldAccessor [
+      FieldAccessor [
+        Variable [ Name=$g ]
+        Field=t1
+      ]
+      Field=c1
+    ]
+    ASC
+
+)
+gg
+]
+FROM [  FunctionCall asterix.dataset@1[
+    LiteralExpr [STRING] [test.t1]
+  ]
+  AS Variable [ Name=$t1 ]
+,
+  FunctionCall test.range@2[
+    FieldAccessor [
+      Variable [ Name=$t1 ]
+      Field=one
+    ]
+    Variable [ Name=$P ]
+  ]
+  AS Variable [ Name=$p ]
+]
+Groupby
+  Variable [ Name=$p ]
+  :=
+  Variable [ Name=$p ]
+  GROUP AS Variable [ Name=$g ]
+  (
+    t1:=Variable [ Name=$t1 ]
+    p:=Variable [ Name=$p ]
+  )
+
+Orderby
+  Variable [ Name=$p ]
+  ASC
+

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.6.ast
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.6.ast
 
b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.6.ast
new file mode 100644
index 0000000..94f13a5
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/window/misc_01/misc_01.6.ast
@@ -0,0 +1,50 @@
+DataverseUse test
+Query:
+SELECT [
+FunctionCall asterix.field-access-by-name@2[
+  Variable [ Name=$t1 ]
+  LiteralExpr [STRING] [c1]
+]
+c1
+WINDOW test.array_sum@1[
+  (
+    SELECT ELEMENT [
+    FieldAccessor [
+      FieldAccessor [
+        Variable [ Name=$w ]
+        Field=t1
+      ]
+      Field=c1
+    ]
+    ]
+    FROM [      Variable [ Name=$w ]
+      AS Variable [ Name=$w ]
+    ]
+  )
+]
+  AS Variable [ Name=$w ]
+OVER (
+  PARTITION BY
+    OperatorExpr [
+      FunctionCall asterix.field-access-by-name@2[
+        Variable [ Name=$t1 ]
+        LiteralExpr [STRING] [c2]
+      ]
+      mod
+      LiteralExpr [LONG] [2]
+    ]
+)
+sum
+]
+FROM [  FunctionCall asterix.dataset@1[
+    LiteralExpr [STRING] [test.t1]
+  ]
+  AS Variable [ Name=$t1 ]
+]
+Orderby
+  FunctionCall asterix.field-access-by-name@2[
+    Variable [ Name=$t1 ]
+    LiteralExpr [STRING] [c1]
+  ]
+  ASC
+

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml 
b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
index 39a3c76..7bd1eaf 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -9246,6 +9246,11 @@
       </compilation-unit>
     </test-case>
     <test-case FilePath="window">
+      <compilation-unit name="pg_win">
+        <output-dir compare="Text">pg_win</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="window">
       <compilation-unit name="rank_01">
         <output-dir compare="Text">rank_01</output-dir>
       </compilation-unit>

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp_parser.xml
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp_parser.xml 
b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp_parser.xml
index 48a9553..aef4a79 100644
--- 
a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp_parser.xml
+++ 
b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp_parser.xml
@@ -7354,4 +7354,11 @@
       </compilation-unit>
     </test-case>
   </test-group>
+  <test-group name="window">
+    <test-case FilePath="window">
+      <compilation-unit name="misc_01">
+        <output-dir compare="AST">misc_01</output-dir>
+      </compilation-unit>
+    </test-case>
+  </test-group>
 </test-suite>

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
 
b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
index 54fd65c..3d63936 100644
--- 
a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
+++ 
b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
@@ -183,6 +183,9 @@ public class ErrorCode {
     public static final int COMPILATION_EXPECTED_FUNCTION_CALL = 1095;
     public static final int UNKNOWN_COMPRESSION_SCHEME = 1096;
     public static final int UNSUPPORTED_WITH_SUBFIELD = 1097;
+    public static final int COMPILATION_INVALID_WINDOW_FRAME = 1098;
+    public static final int COMPILATION_UNEXPECTED_WINDOW_FRAME = 1099;
+    public static final int COMPILATION_UNEXPECTED_WINDOW_EXPRESSION = 1100;
 
     // Feed errors
     public static final int DATAFLOW_ILLEGAL_STATE = 3001;

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties 
b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
index 7aa9b91..12858ac 100644
--- a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
+++ b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
@@ -170,6 +170,9 @@
 1095 = Expected function call
 1096 = Unknown compression scheme %1$s. Supported schemes are %2$s
 1097 = Subfield(s) %1$s in \"%2$s\" unsupported in the with clause
+1098 = Invalid window frame definition
+1099 = Unexpected window frame definition
+1100 = Unexpected window expression
 
 # Feed Errors
 3001 = Illegal state.

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/rewrites/AqlQueryRewriter.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/rewrites/AqlQueryRewriter.java
 
b/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/rewrites/AqlQueryRewriter.java
index 967fdae..61cecfb 100644
--- 
a/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/rewrites/AqlQueryRewriter.java
+++ 
b/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/rewrites/AqlQueryRewriter.java
@@ -21,6 +21,7 @@ package org.apache.asterix.lang.aql.rewrites;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import org.apache.asterix.common.exceptions.CompilationException;
@@ -46,11 +47,13 @@ import 
org.apache.asterix.lang.common.expression.GbyVariableExpressionPair;
 import org.apache.asterix.lang.common.expression.VariableExpr;
 import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
 import org.apache.asterix.lang.common.statement.FunctionDecl;
+import org.apache.asterix.lang.common.struct.Identifier;
 import org.apache.asterix.lang.common.struct.VarIdentifier;
 import org.apache.asterix.lang.common.util.CommonFunctionMapUtil;
 import org.apache.asterix.lang.common.util.FunctionUtil;
 import org.apache.asterix.lang.common.visitor.GatherFunctionCallsVisitor;
 import org.apache.asterix.metadata.declared.MetadataProvider;
+import org.apache.hyracks.algebricks.common.utils.Pair;
 
 class AqlQueryRewriter implements IQueryRewriter {
 
@@ -176,8 +179,20 @@ class AqlQueryRewriter implements IQueryRewriter {
             for (GbyVariableExpressionPair p : gc.getGbyPairList()) {
                 p.getExpr().accept(this, arg);
             }
-            for (GbyVariableExpressionPair p : gc.getDecorPairList()) {
-                p.getExpr().accept(this, arg);
+            if (gc.hasDecorList()) {
+                for (GbyVariableExpressionPair p : gc.getDecorPairList()) {
+                    p.getExpr().accept(this, arg);
+                }
+            }
+            if (gc.hasGroupFieldList()) {
+                for (Pair<Expression, Identifier> p : gc.getGroupFieldList()) {
+                    p.first.accept(this, arg);
+                }
+            }
+            if (gc.hasWithMap()) {
+                for (Map.Entry<Expression, VariableExpr> me : 
gc.getWithVarMap().entrySet()) {
+                    me.getKey().accept(this, arg);
+                }
             }
             return null;
         }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/visitor/AQLToSQLPPPrintVisitor.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/visitor/AQLToSQLPPPrintVisitor.java
 
b/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/visitor/AQLToSQLPPPrintVisitor.java
index 8d84dbc..59dfbb5 100644
--- 
a/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/visitor/AQLToSQLPPPrintVisitor.java
+++ 
b/asterixdb/asterix-lang-aql/src/main/java/org/apache/asterix/lang/aql/visitor/AQLToSQLPPPrintVisitor.java
@@ -404,10 +404,14 @@ public class AQLToSQLPPPrintVisitor extends 
FormatPrintVisitor implements IAQLVi
         for (GbyVariableExpressionPair keyPair : gbyClause.getGbyPairList()) {
             producedVars.add(keyPair.getVar());
         }
-        for (GbyVariableExpressionPair keyPair : gbyClause.getDecorPairList()) 
{
-            producedVars.add(keyPair.getVar());
+        if (gbyClause.hasDecorList()) {
+            for (GbyVariableExpressionPair keyPair : 
gbyClause.getDecorPairList()) {
+                producedVars.add(keyPair.getVar());
+            }
+        }
+        if (gbyClause.hasWithMap()) {
+            producedVars.addAll(gbyClause.getWithVarMap().values());
         }
-        producedVars.addAll(gbyClause.getWithVarMap().values());
         return producedVars;
     }
 

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/ExpressionUtils.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/ExpressionUtils.java
 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/ExpressionUtils.java
index 6adb050..de5e931 100644
--- 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/ExpressionUtils.java
+++ 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/ExpressionUtils.java
@@ -18,6 +18,8 @@
  */
 package org.apache.asterix.lang.common.util;
 
+import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 
 import org.apache.asterix.common.exceptions.CompilationException;
@@ -97,4 +99,8 @@ public class ExpressionUtils {
                 throw new 
CompilationException(ErrorCode.LITERAL_TYPE_NOT_SUPPORTED_IN_CONSTANT_RECORD, 
literalType);
         }
     }
+
+    public static <T> Collection<T> emptyIfNull(Collection<T> coll) {
+        return coll == null ? Collections.emptyList() : coll;
+    }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/VariableCloneAndSubstitutionUtil.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/VariableCloneAndSubstitutionUtil.java
 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/VariableCloneAndSubstitutionUtil.java
index e5cf386..d235883 100644
--- 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/VariableCloneAndSubstitutionUtil.java
+++ 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/VariableCloneAndSubstitutionUtil.java
@@ -29,6 +29,7 @@ import 
org.apache.asterix.lang.common.expression.GbyVariableExpressionPair;
 import org.apache.asterix.lang.common.expression.VariableExpr;
 import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
 import org.apache.asterix.lang.common.rewrites.VariableSubstitutionEnvironment;
+import org.apache.asterix.lang.common.struct.Identifier;
 import 
org.apache.asterix.lang.common.visitor.CloneAndSubstituteVariablesVisitor;
 import org.apache.hyracks.algebricks.common.utils.Pair;
 
@@ -56,6 +57,17 @@ public class VariableCloneAndSubstitutionUtil {
         return veList;
     }
 
+    public static List<Pair<Expression, Identifier>> 
substInFieldList(List<Pair<Expression, Identifier>> fieldList,
+            VariableSubstitutionEnvironment newSubs, 
CloneAndSubstituteVariablesVisitor visitor)
+            throws CompilationException {
+        List<Pair<Expression, Identifier>> newFieldList = new 
ArrayList<>(fieldList.size());
+        for (Pair<Expression, Identifier> p : fieldList) {
+            Expression newExpr = (Expression) p.first.accept(visitor, 
newSubs).first;
+            newFieldList.add(new Pair<>(newExpr, p.second));
+        }
+        return newFieldList;
+    }
+
     public static VariableSubstitutionEnvironment 
eliminateSubstFromList(VariableExpr variableExpr,
             VariableSubstitutionEnvironment arg) {
         VariableSubstitutionEnvironment newArg = new 
VariableSubstitutionEnvironment(arg);
@@ -73,5 +85,4 @@ public class VariableCloneAndSubstitutionUtil {
         }
         return exprs;
     }
-
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/AbstractInlineUdfsVisitor.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/AbstractInlineUdfsVisitor.java
 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/AbstractInlineUdfsVisitor.java
index bf9cf89..1aab7f7 100644
--- 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/AbstractInlineUdfsVisitor.java
+++ 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/AbstractInlineUdfsVisitor.java
@@ -19,8 +19,10 @@
 package org.apache.asterix.lang.common.visitor;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.asterix.common.exceptions.CompilationException;
 import org.apache.asterix.common.exceptions.ErrorCode;
@@ -53,6 +55,7 @@ import 
org.apache.asterix.lang.common.rewrites.VariableSubstitutionEnvironment;
 import org.apache.asterix.lang.common.statement.FunctionDecl;
 import org.apache.asterix.lang.common.statement.InsertStatement;
 import org.apache.asterix.lang.common.statement.Query;
+import org.apache.asterix.lang.common.struct.Identifier;
 import org.apache.asterix.lang.common.struct.QuantifiedPair;
 import org.apache.asterix.lang.common.struct.VarIdentifier;
 import 
org.apache.asterix.lang.common.visitor.base.AbstractQueryExpressionVisitor;
@@ -204,20 +207,23 @@ public abstract class AbstractInlineUdfsVisitor extends 
AbstractQueryExpressionV
 
     @Override
     public Boolean visit(GroupbyClause gc, List<FunctionDecl> arg) throws 
CompilationException {
-        boolean changed = false;
-        for (GbyVariableExpressionPair p : gc.getGbyPairList()) {
-            Pair<Boolean, Expression> be = inlineUdfsInExpr(p.getExpr(), arg);
-            p.setExpr(be.second);
-            if (be.first) {
-                changed = true;
-            }
+        Pair<Boolean, List<GbyVariableExpressionPair>> p1 = 
inlineUdfsInGbyPairList(gc.getGbyPairList(), arg);
+        gc.setGbyPairList(p1.second);
+        boolean changed = p1.first;
+        if (gc.hasDecorList()) {
+            Pair<Boolean, List<GbyVariableExpressionPair>> p2 = 
inlineUdfsInGbyPairList(gc.getDecorPairList(), arg);
+            gc.setDecorPairList(p2.second);
+            changed |= p2.first;
         }
-        for (GbyVariableExpressionPair p : gc.getDecorPairList()) {
-            Pair<Boolean, Expression> be = inlineUdfsInExpr(p.getExpr(), arg);
-            p.setExpr(be.second);
-            if (be.first) {
-                changed = true;
-            }
+        if (gc.hasGroupFieldList()) {
+            Pair<Boolean, List<Pair<Expression, Identifier>>> p3 = 
inlineUdfsInFieldList(gc.getGroupFieldList(), arg);
+            gc.setGroupFieldList(p3.second);
+            changed |= p3.first;
+        }
+        if (gc.hasWithMap()) {
+            Pair<Boolean, Map<Expression, VariableExpr>> p4 = 
inlineUdfsInVarMap(gc.getWithVarMap(), arg);
+            gc.setWithVarMap(p4.second);
+            changed |= p4.first;
         }
         return changed;
     }
@@ -319,18 +325,52 @@ public abstract class AbstractInlineUdfsVisitor extends 
AbstractQueryExpressionV
 
     protected Pair<Boolean, List<Expression>> 
inlineUdfsInExprList(List<Expression> exprList, List<FunctionDecl> fds)
             throws CompilationException {
-        ArrayList<Expression> newList = new ArrayList<>();
+        List<Expression> newList = new ArrayList<>(exprList.size());
         boolean changed = false;
         for (Expression e : exprList) {
-            Pair<Boolean, Expression> p = inlineUdfsInExpr(e, fds);
-            newList.add(p.second);
-            if (p.first) {
-                changed = true;
-            }
+            Pair<Boolean, Expression> be = inlineUdfsInExpr(e, fds);
+            newList.add(be.second);
+            changed |= be.first;
+        }
+        return new Pair<>(changed, newList);
+    }
+
+    private Pair<Boolean, List<GbyVariableExpressionPair>> 
inlineUdfsInGbyPairList(
+            List<GbyVariableExpressionPair> gbyPairList, List<FunctionDecl> 
fds) throws CompilationException {
+        List<GbyVariableExpressionPair> newList = new 
ArrayList<>(gbyPairList.size());
+        boolean changed = false;
+        for (GbyVariableExpressionPair p : gbyPairList) {
+            Pair<Boolean, Expression> be = inlineUdfsInExpr(p.getExpr(), fds);
+            newList.add(new GbyVariableExpressionPair(p.getVar(), be.second));
+            changed |= be.first;
+        }
+        return new Pair<>(changed, newList);
+    }
+
+    protected Pair<Boolean, List<Pair<Expression, Identifier>>> 
inlineUdfsInFieldList(
+            List<Pair<Expression, Identifier>> fieldList, List<FunctionDecl> 
fds) throws CompilationException {
+        List<Pair<Expression, Identifier>> newList = new 
ArrayList<>(fieldList.size());
+        boolean changed = false;
+        for (Pair<Expression, Identifier> p : fieldList) {
+            Pair<Boolean, Expression> be = inlineUdfsInExpr(p.first, fds);
+            newList.add(new Pair<>(be.second, p.second));
+            changed |= be.first;
         }
         return new Pair<>(changed, newList);
     }
 
+    private Pair<Boolean, Map<Expression, VariableExpr>> 
inlineUdfsInVarMap(Map<Expression, VariableExpr> varMap,
+            List<FunctionDecl> fds) throws CompilationException {
+        Map<Expression, VariableExpr> newMap = new HashMap<>();
+        boolean changed = false;
+        for (Map.Entry<Expression, VariableExpr> me : varMap.entrySet()) {
+            Pair<Boolean, Expression> be = inlineUdfsInExpr(me.getKey(), fds);
+            newMap.put(be.second, me.getValue());
+            changed |= be.first;
+        }
+        return new Pair<>(changed, newMap);
+    }
+
     private Expression rewriteFunctionBody(FunctionDecl fnDecl) throws 
CompilationException {
         SourceLocation sourceLoc = fnDecl.getSourceLocation();
         Query wrappedQuery = new Query(false);
@@ -363,7 +403,7 @@ public abstract class AbstractInlineUdfsVisitor extends 
AbstractQueryExpressionV
         }
     }
 
-    protected static FunctionDecl findFuncDeclaration(FunctionSignature fid, 
List<FunctionDecl> sequence) {
+    private static FunctionDecl findFuncDeclaration(FunctionSignature fid, 
List<FunctionDecl> sequence) {
         for (FunctionDecl f : sequence) {
             if (f.getSignature().equals(fid)) {
                 return f;

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/CloneAndSubstituteVariablesVisitor.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/CloneAndSubstituteVariablesVisitor.java
 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/CloneAndSubstituteVariablesVisitor.java
index c387a9a..3a19254 100644
--- 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/CloneAndSubstituteVariablesVisitor.java
+++ 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/CloneAndSubstituteVariablesVisitor.java
@@ -101,13 +101,8 @@ public class CloneAndSubstituteVariablesVisitor extends
                 newWithMap.put(newKeyVar, newValueVar);
             }
         }
-        List<Pair<Expression, Identifier>> newGroupFieldList = new 
ArrayList<>();
-        if (gc.hasGroupFieldList()) {
-            for (Pair<Expression, Identifier> varId : gc.getGroupFieldList()) {
-                Expression newExpr = (Expression) varId.first.accept(this, 
env).first;
-                newGroupFieldList.add(new Pair<>(newExpr, varId.second));
-            }
-        }
+        List<Pair<Expression, Identifier>> newGroupFieldList = 
gc.hasGroupFieldList()
+                ? 
VariableCloneAndSubstitutionUtil.substInFieldList(gc.getGroupFieldList(), env, 
this) : null;
         GroupbyClause newGroup = new GroupbyClause(newGbyList, newDecorList, 
newWithMap, newGroupVar, newGroupFieldList,
                 gc.hasHashGroupByHint(), gc.isGroupAll());
         newGroup.setSourceLocation(gc.getSourceLocation());
@@ -124,7 +119,7 @@ public class CloneAndSubstituteVariablesVisitor extends
             VariableExpr newVar = generateNewVariable(context, t.getVarExpr());
             newSubs = 
VariableCloneAndSubstitutionUtil.eliminateSubstFromList(newVar, newSubs);
             Pair<ILangExpression, VariableSubstitutionEnvironment> p1 =
-                    visitUnnesBindingExpression(t.getExpr(), newSubs);
+                    visitUnnestBindingExpression(t.getExpr(), newSubs);
             QuantifiedPair t2 = new QuantifiedPair(newVar, (Expression) 
p1.first);
             newPairs.add(t2);
         }
@@ -392,7 +387,7 @@ public class CloneAndSubstituteVariablesVisitor extends
      * @return a pair of an ILangExpression and a variable substitution 
environment.
      * @throws CompilationException
      */
-    protected Pair<ILangExpression, VariableSubstitutionEnvironment> 
visitUnnesBindingExpression(Expression expr,
+    protected Pair<ILangExpression, VariableSubstitutionEnvironment> 
visitUnnestBindingExpression(Expression expr,
             VariableSubstitutionEnvironment env) throws CompilationException {
         return expr.accept(this, env);
     }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/GatherFunctionCallsVisitor.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/GatherFunctionCallsVisitor.java
 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/GatherFunctionCallsVisitor.java
index a239df1..1e20c96 100644
--- 
a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/GatherFunctionCallsVisitor.java
+++ 
b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/GatherFunctionCallsVisitor.java
@@ -20,6 +20,7 @@ package org.apache.asterix.lang.common.visitor;
  */
 
 import java.util.HashSet;
+import java.util.Map;
 import java.util.Set;
 
 import org.apache.asterix.common.exceptions.CompilationException;
@@ -48,8 +49,10 @@ import 
org.apache.asterix.lang.common.expression.VariableExpr;
 import org.apache.asterix.lang.common.statement.FunctionDecl;
 import org.apache.asterix.lang.common.statement.InsertStatement;
 import org.apache.asterix.lang.common.statement.Query;
+import org.apache.asterix.lang.common.struct.Identifier;
 import org.apache.asterix.lang.common.struct.QuantifiedPair;
 import 
org.apache.asterix.lang.common.visitor.base.AbstractQueryExpressionVisitor;
+import org.apache.hyracks.algebricks.common.utils.Pair;
 
 public class GatherFunctionCallsVisitor extends 
AbstractQueryExpressionVisitor<Void, Void> {
 
@@ -75,8 +78,20 @@ public class GatherFunctionCallsVisitor extends 
AbstractQueryExpressionVisitor<V
         for (GbyVariableExpressionPair p : gc.getGbyPairList()) {
             p.getExpr().accept(this, arg);
         }
-        for (GbyVariableExpressionPair p : gc.getDecorPairList()) {
-            p.getExpr().accept(this, arg);
+        if (gc.hasDecorList()) {
+            for (GbyVariableExpressionPair p : gc.getDecorPairList()) {
+                p.getExpr().accept(this, arg);
+            }
+        }
+        if (gc.hasGroupFieldList()) {
+            for (Pair<Expression, Identifier> p : gc.getGroupFieldList()) {
+                p.first.accept(this, arg);
+            }
+        }
+        if (gc.hasWithMap()) {
+            for (Map.Entry<Expression, VariableExpr> me : 
gc.getWithVarMap().entrySet()) {
+                me.getKey().accept(this, arg);
+            }
         }
         return null;
     }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/expression/WindowExpression.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/expression/WindowExpression.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/expression/WindowExpression.java
index d1c4e59..42b5605 100644
--- 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/expression/WindowExpression.java
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/expression/WindowExpression.java
@@ -20,29 +20,62 @@
 package org.apache.asterix.lang.sqlpp.expression;
 
 import java.util.List;
+import java.util.Objects;
 
 import org.apache.asterix.common.exceptions.CompilationException;
+import org.apache.asterix.common.functions.FunctionSignature;
 import org.apache.asterix.lang.common.base.AbstractExpression;
 import org.apache.asterix.lang.common.base.Expression;
 import org.apache.asterix.lang.common.clause.OrderbyClause;
+import org.apache.asterix.lang.common.expression.VariableExpr;
+import org.apache.asterix.lang.common.struct.Identifier;
+import org.apache.asterix.lang.common.util.ExpressionUtils;
 import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 import org.apache.asterix.lang.sqlpp.visitor.base.ISqlppVisitor;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.hyracks.algebricks.common.utils.Pair;
 
 public class WindowExpression extends AbstractExpression {
-    private Expression expr;
+
+    private FunctionSignature functionSignature;
+    private List<Expression> exprList;
+
     private List<Expression> partitionList;
     private List<Expression> orderbyList;
     private List<OrderbyClause.OrderModifier> orderbyModifierList;
 
-    public WindowExpression(Expression expr, List<Expression> partitionList, 
List<Expression> orderbyList,
-            List<OrderbyClause.OrderModifier> orderbyModifierList) {
-        if (expr == null || orderbyList == null) {
+    private FrameMode frameMode;
+    private FrameBoundaryKind frameStartKind;
+    private Expression frameStartExpr;
+    private FrameBoundaryKind frameEndKind;
+    private Expression frameEndExpr;
+    private FrameExclusionKind frameExclusionKind;
+
+    private VariableExpr windowVar;
+    private List<Pair<Expression, Identifier>> windowFieldList;
+
+    public WindowExpression(FunctionSignature functionSignature, 
List<Expression> exprList,
+            List<Expression> partitionList, List<Expression> orderbyList,
+            List<OrderbyClause.OrderModifier> orderbyModifierList, FrameMode 
frameMode,
+            FrameBoundaryKind frameStartKind, Expression frameStartExpr, 
FrameBoundaryKind frameEndKind,
+            Expression frameEndExpr, FrameExclusionKind frameExclusionKind, 
VariableExpr windowVar,
+            List<Pair<Expression, Identifier>> windowFieldList) {
+        if (functionSignature == null || exprList == null) {
             throw new NullPointerException();
         }
-        this.expr = expr;
+        this.functionSignature = functionSignature;
+        this.exprList = exprList;
         this.partitionList = partitionList;
         this.orderbyList = orderbyList;
         this.orderbyModifierList = orderbyModifierList;
+        this.frameMode = frameMode;
+        this.frameStartKind = frameStartKind;
+        this.frameStartExpr = frameStartExpr;
+        this.frameEndKind = frameEndKind;
+        this.frameEndExpr = frameEndExpr;
+        this.frameExclusionKind = frameExclusionKind;
+        this.windowVar = windowVar;
+        this.windowFieldList = windowFieldList;
     }
 
     @Override
@@ -50,15 +83,26 @@ public class WindowExpression extends AbstractExpression {
         return Kind.WINDOW_EXPRESSION;
     }
 
-    public Expression getExpr() {
-        return expr;
+    public FunctionSignature getFunctionSignature() {
+        return functionSignature;
+    }
+
+    public void setFunctionSignature(FunctionSignature functionSignature) {
+        if (functionSignature == null) {
+            throw new NullPointerException();
+        }
+        this.functionSignature = functionSignature;
+    }
+
+    public List<Expression> getExprList() {
+        return exprList;
     }
 
-    public void setExpr(Expression expr) {
-        if (expr == null) {
+    public void setExprList(List<Expression> exprList) {
+        if (exprList == null) {
             throw new NullPointerException();
         }
-        this.expr = expr;
+        this.exprList = exprList;
     }
 
     public boolean hasPartitionList() {
@@ -70,20 +114,18 @@ public class WindowExpression extends AbstractExpression {
     }
 
     public void setPartitionList(List<Expression> partitionList) {
-        if (partitionList == null) {
-            throw new NullPointerException();
-        }
         this.partitionList = partitionList;
     }
 
+    public boolean hasOrderByList() {
+        return orderbyList != null && !orderbyList.isEmpty();
+    }
+
     public List<Expression> getOrderbyList() {
         return orderbyList;
     }
 
     public void setOrderbyList(List<Expression> orderbyList) {
-        if (orderbyList == null) {
-            throw new NullPointerException();
-        }
         this.orderbyList = orderbyList;
     }
 
@@ -92,14 +134,235 @@ public class WindowExpression extends AbstractExpression {
     }
 
     public void setOrderbyModifierList(List<OrderbyClause.OrderModifier> 
orderbyModifierList) {
-        if (orderbyModifierList == null) {
-            throw new NullPointerException();
-        }
         this.orderbyModifierList = orderbyModifierList;
     }
 
+    public boolean hasFrameDefinition() {
+        return frameMode != null;
+    }
+
+    public FrameMode getFrameMode() {
+        return frameMode;
+    }
+
+    public void setFrameMode(FrameMode frameMode) {
+        this.frameMode = frameMode;
+    }
+
+    public FrameBoundaryKind getFrameStartKind() {
+        return frameStartKind;
+    }
+
+    public void setFrameStartKind(FrameBoundaryKind frameStartKind) {
+        this.frameStartKind = frameStartKind;
+    }
+
+    public boolean hasFrameStartExpr() {
+        return frameStartExpr != null;
+    }
+
+    public Expression getFrameStartExpr() {
+        return frameStartExpr;
+    }
+
+    public void setFrameStartExpr(Expression frameStartExpr) {
+        this.frameStartExpr = frameStartExpr;
+    }
+
+    public FrameBoundaryKind getFrameEndKind() {
+        return frameEndKind;
+    }
+
+    public void setFrameEndKind(FrameBoundaryKind frameEndKind) {
+        this.frameEndKind = frameEndKind;
+    }
+
+    public boolean hasFrameEndExpr() {
+        return frameEndExpr != null;
+    }
+
+    public Expression getFrameEndExpr() {
+        return frameEndExpr;
+    }
+
+    public void setFrameEndExpr(Expression frameEndExpr) {
+        this.frameEndExpr = frameEndExpr;
+    }
+
+    public FrameExclusionKind getFrameExclusionKind() {
+        return frameExclusionKind;
+    }
+
+    public void setFrameExclusionKind(FrameExclusionKind frameExclusionKind) {
+        this.frameExclusionKind = frameExclusionKind;
+    }
+
+    public boolean hasWindowVar() {
+        return windowVar != null;
+    }
+
+    public VariableExpr getWindowVar() {
+        return windowVar;
+    }
+
+    public void setWindowVar(VariableExpr windowVar) {
+        this.windowVar = windowVar;
+    }
+
+    public boolean hasWindowFieldList() {
+        return windowFieldList != null && !windowFieldList.isEmpty();
+    }
+
+    public List<Pair<Expression, Identifier>> getWindowFieldList() {
+        return windowFieldList;
+    }
+
+    public void setWindowFieldList(List<Pair<Expression, Identifier>> 
windowFieldList) {
+        this.windowFieldList = windowFieldList;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(functionSignature, exprList, 
ExpressionUtils.emptyIfNull(partitionList),
+                ExpressionUtils.emptyIfNull(orderbyList), 
ExpressionUtils.emptyIfNull(orderbyModifierList), frameMode,
+                frameStartKind, frameStartExpr, frameEndKind, frameEndExpr, 
frameExclusionKind, windowVar,
+                ExpressionUtils.emptyIfNull(windowFieldList));
+    }
+
+    @Override
+    @SuppressWarnings("squid:S1067") // expressions should not be too complex
+    public boolean equals(Object object) {
+        if (this == object) {
+            return true;
+        }
+        if (!(object instanceof WindowExpression)) {
+            return false;
+        }
+        WindowExpression target = (WindowExpression) object;
+        return Objects.equals(functionSignature, target.functionSignature) && 
Objects.equals(exprList, target.exprList)
+                && Objects.equals(ExpressionUtils.emptyIfNull(partitionList),
+                        ExpressionUtils.emptyIfNull(target.partitionList))
+                && Objects.equals(ExpressionUtils.emptyIfNull(orderbyList),
+                        ExpressionUtils.emptyIfNull(target.orderbyList))
+                && 
Objects.equals(ExpressionUtils.emptyIfNull(orderbyModifierList),
+                        
ExpressionUtils.emptyIfNull(target.orderbyModifierList))
+                && frameMode == target.frameMode && frameStartKind == 
target.frameStartKind
+                && Objects.equals(frameStartExpr, target.frameStartExpr) && 
frameEndKind == target.frameEndKind
+                && Objects.equals(frameEndExpr, target.frameEndExpr) && 
frameExclusionKind == target.frameExclusionKind
+                && Objects.equals(windowVar, target.windowVar)
+                && Objects.equals(ExpressionUtils.emptyIfNull(windowFieldList),
+                        ExpressionUtils.emptyIfNull(target.windowFieldList));
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("WINDOW ");
+        sb.append(functionSignature);
+        sb.append('(');
+        sb.append(StringUtils.join(exprList, ','));
+        sb.append(") OVER ");
+        if (hasWindowVar()) {
+            sb.append(windowVar);
+            if (hasWindowFieldList()) {
+                sb.append('{');
+                for (int i = 0, ln = windowFieldList.size(); i < ln; i++) {
+                    if (i > 0) {
+                        sb.append(',');
+                    }
+                    Pair<Expression, Identifier> p = windowFieldList.get(i);
+                    sb.append(p.first).append(':').append(p.second);
+                }
+                sb.append('}');
+            }
+            sb.append(" AS ");
+        }
+        sb.append('(');
+        if (hasPartitionList()) {
+            sb.append(" PARTITION BY ");
+            sb.append(StringUtils.join(partitionList, ','));
+        }
+        if (hasOrderByList()) {
+            sb.append(" ORDER BY ");
+            for (int i = 0, ln = orderbyList.size(); i < ln; i++) {
+                if (i > 0) {
+                    sb.append(',');
+                }
+                sb.append(orderbyList.get(i)).append(' 
').append(orderbyModifierList.get(i));
+            }
+        }
+        if (hasFrameDefinition()) {
+            sb.append(" FRAME ").append(frameMode);
+            sb.append(" BETWEEN ").append(frameStartKind);
+            if (hasFrameStartExpr()) {
+                sb.append(' ').append(frameStartExpr);
+            }
+            sb.append(" AND ").append(frameEndKind);
+            if (hasFrameEndExpr()) {
+                sb.append(' ').append(frameEndExpr);
+            }
+            sb.append(" EXCLUDE ").append(frameExclusionKind);
+        }
+        sb.append(')');
+        return sb.toString();
+    }
+
     @Override
     public <R, T> R accept(ILangVisitor<R, T> visitor, T arg) throws 
CompilationException {
         return ((ISqlppVisitor<R, T>) visitor).visit(this, arg);
     }
+
+    public enum FrameMode {
+        RANGE("range"),
+        ROWS("rows"),
+        GROUPS("groups");
+
+        private String text;
+
+        FrameMode(String text) {
+            this.text = text;
+        }
+
+        @Override
+        public String toString() {
+            return text;
+        }
+    }
+
+    public enum FrameBoundaryKind {
+        CURRENT_ROW("current row"),
+        UNBOUNDED_PRECEDING("unbounded preceding"),
+        UNBOUNDED_FOLLOWING("unbounded following"),
+        BOUNDED_PRECEDING("preceding"),
+        BOUNDED_FOLLOWING("following");
+
+        private String text;
+
+        FrameBoundaryKind(String text) {
+            this.text = text;
+        }
+
+        @Override
+        public String toString() {
+            return text;
+        }
+    }
+
+    public enum FrameExclusionKind {
+        CURRENT_ROW("current row"),
+        GROUP("group"),
+        TIES("ties"),
+        NO_OTHERS("no others");
+
+        private String text;
+
+        FrameExclusionKind(String text) {
+            this.text = text;
+        }
+
+        @Override
+        public String toString() {
+            return text;
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppFunctionBodyRewriter.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppFunctionBodyRewriter.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppFunctionBodyRewriter.java
index fa4018a..bde40de 100644
--- 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppFunctionBodyRewriter.java
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppFunctionBodyRewriter.java
@@ -46,6 +46,9 @@ class SqlppFunctionBodyRewriter extends SqlppQueryRewriter {
         // Group-by core rewrites
         rewriteGroupBys();
 
+        // Window expression core rewrites.
+        rewriteWindowExpressions();
+
         // Rewrites set operations.
         rewriteSetOperations();
 
@@ -58,6 +61,9 @@ class SqlppFunctionBodyRewriter extends SqlppQueryRewriter {
         // Rewrites SQL-92 global aggregations.
         rewriteGroupByAggregationSugar();
 
+        // Rewrite window expression aggregations.
+        rewriteWindowAggregationSugar();
+
         // Rewrites like/not-like expressions.
         rewriteOperatorExpression();
 

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/f2c18aa9/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
index b785cbd..69a3e5e 100644
--- 
a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
+++ 
b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/SqlppQueryRewriter.java
@@ -23,6 +23,9 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Set;
 
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
 import org.apache.asterix.common.exceptions.CompilationException;
 import org.apache.asterix.common.functions.FunctionSignature;
 import org.apache.asterix.lang.common.base.Expression;
@@ -32,9 +35,11 @@ import org.apache.asterix.lang.common.clause.LetClause;
 import org.apache.asterix.lang.common.expression.CallExpr;
 import org.apache.asterix.lang.common.rewrites.LangRewritingContext;
 import org.apache.asterix.lang.common.statement.FunctionDecl;
+import org.apache.asterix.lang.common.struct.Identifier;
 import org.apache.asterix.lang.common.struct.VarIdentifier;
 import org.apache.asterix.lang.common.util.FunctionUtil;
 import org.apache.asterix.lang.common.visitor.GatherFunctionCallsVisitor;
+import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
 import org.apache.asterix.lang.sqlpp.clause.AbstractBinaryCorrelateClause;
 import org.apache.asterix.lang.sqlpp.clause.FromClause;
 import org.apache.asterix.lang.sqlpp.clause.FromTerm;
@@ -65,14 +70,21 @@ import 
org.apache.asterix.lang.sqlpp.rewrites.visitor.SqlppGroupByAggregationSug
 import org.apache.asterix.lang.sqlpp.rewrites.visitor.SqlppGroupByVisitor;
 import org.apache.asterix.lang.sqlpp.rewrites.visitor.SqlppInlineUdfsVisitor;
 import 
org.apache.asterix.lang.sqlpp.rewrites.visitor.SqlppListInputFunctionRewriteVisitor;
+import 
org.apache.asterix.lang.sqlpp.rewrites.visitor.SqlppWindowRewriteVisitor;
+import 
org.apache.asterix.lang.sqlpp.rewrites.visitor.SqlppWindowAggregationSugarVisitor;
 import 
org.apache.asterix.lang.sqlpp.rewrites.visitor.SubstituteGroupbyExpressionWithVariableVisitor;
 import 
org.apache.asterix.lang.sqlpp.rewrites.visitor.VariableCheckAndRewriteVisitor;
 import org.apache.asterix.lang.sqlpp.struct.SetOperationRight;
 import org.apache.asterix.lang.sqlpp.util.FunctionMapUtil;
+import org.apache.asterix.lang.sqlpp.util.SqlppAstPrintUtil;
 import org.apache.asterix.lang.sqlpp.visitor.base.ISqlppVisitor;
 import org.apache.asterix.metadata.declared.MetadataProvider;
+import org.apache.hyracks.algebricks.common.utils.Pair;
 
 public class SqlppQueryRewriter implements IQueryRewriter {
+
+    private static final Logger LOGGER = 
LogManager.getLogger(SqlppQueryRewriter.class);
+
     public static final String INLINE_WITH_OPTION = "inline_with";
     private static final boolean INLINE_WITH_OPTION_DEFAULT = true;
     private final FunctionParser functionRepository = new FunctionParser(new 
SqlppParserFactory());
@@ -81,14 +93,18 @@ public class SqlppQueryRewriter implements IQueryRewriter {
     private LangRewritingContext context;
     private MetadataProvider metadataProvider;
     private Collection<VarIdentifier> externalVars;
+    private boolean isLogEnabled;
 
     protected void setup(List<FunctionDecl> declaredFunctions, 
IReturningStatement topExpr,
-            MetadataProvider metadataProvider, LangRewritingContext context, 
Collection<VarIdentifier> externalVars) {
+            MetadataProvider metadataProvider, LangRewritingContext context, 
Collection<VarIdentifier> externalVars)
+            throws CompilationException {
         this.topExpr = topExpr;
         this.context = context;
         this.declaredFunctions = declaredFunctions;
         this.metadataProvider = metadataProvider;
         this.externalVars = externalVars;
+        this.isLogEnabled = LOGGER.isTraceEnabled();
+        logExpression("Starting AST rewrites on", "");
     }
 
     @Override
@@ -117,12 +133,18 @@ public class SqlppQueryRewriter implements IQueryRewriter 
{
         // Inlines column aliases.
         inlineColumnAlias();
 
+        // Window expression core rewrites.
+        rewriteWindowExpressions();
+
         // Generate ids for variables (considering scopes) and replace global 
variable access with the dataset function.
         variableCheckAndRewrite();
 
         // Rewrites SQL-92 aggregate functions
         rewriteGroupByAggregationSugar();
 
+        // Rewrite window expression aggregations.
+        rewriteWindowAggregationSugar();
+
         // Rewrites like/not-like expressions.
         rewriteOperatorExpression();
 
@@ -150,23 +172,23 @@ public class SqlppQueryRewriter implements IQueryRewriter 
{
 
     protected void rewriteGroupByAggregationSugar() throws 
CompilationException {
         SqlppGroupByAggregationSugarVisitor visitor = new 
SqlppGroupByAggregationSugarVisitor(context);
-        topExpr.accept(visitor, null);
+        rewriteTopExpr(visitor, null);
     }
 
     protected void rewriteDistinctAggregations() throws CompilationException {
         SqlppDistinctAggregationSugarVisitor distinctAggregationVisitor =
                 new SqlppDistinctAggregationSugarVisitor(context);
-        topExpr.accept(distinctAggregationVisitor, null);
+        rewriteTopExpr(distinctAggregationVisitor, null);
     }
 
     protected void rewriteListInputFunctions() throws CompilationException {
         SqlppListInputFunctionRewriteVisitor listInputFunctionVisitor = new 
SqlppListInputFunctionRewriteVisitor();
-        topExpr.accept(listInputFunctionVisitor, null);
+        rewriteTopExpr(listInputFunctionVisitor, null);
     }
 
     protected void rewriteFunctionNames() throws CompilationException {
         SqlppBuiltinFunctionRewriteVisitor functionNameMapVisitor = new 
SqlppBuiltinFunctionRewriteVisitor();
-        topExpr.accept(functionNameMapVisitor, null);
+        rewriteTopExpr(functionNameMapVisitor, null);
     }
 
     protected void inlineWithExpressions() throws CompilationException {
@@ -175,49 +197,60 @@ public class SqlppQueryRewriter implements IQueryRewriter 
{
         }
         // Inlines with expressions.
         InlineWithExpressionVisitor inlineWithExpressionVisitor = new 
InlineWithExpressionVisitor(context);
-        topExpr.accept(inlineWithExpressionVisitor, null);
+        rewriteTopExpr(inlineWithExpressionVisitor, null);
     }
 
     protected void generateColumnNames() throws CompilationException {
         // Generate column names if they are missing in the user query.
         GenerateColumnNameVisitor generateColumnNameVisitor = new 
GenerateColumnNameVisitor(context);
-        topExpr.accept(generateColumnNameVisitor, null);
+        rewriteTopExpr(generateColumnNameVisitor, null);
     }
 
     protected void substituteGroupbyKeyExpression() throws 
CompilationException {
         // Substitute group-by key expressions that appear in the select 
clause.
         SubstituteGroupbyExpressionWithVariableVisitor 
substituteGbyExprVisitor =
                 new SubstituteGroupbyExpressionWithVariableVisitor(context);
-        topExpr.accept(substituteGbyExprVisitor, null);
+        rewriteTopExpr(substituteGbyExprVisitor, null);
     }
 
     protected void rewriteSetOperations() throws CompilationException {
         // Rewrites set operation queries that contain order-by and limit 
clauses.
         SetOperationVisitor setOperationVisitor = new 
SetOperationVisitor(context);
-        topExpr.accept(setOperationVisitor, null);
+        rewriteTopExpr(setOperationVisitor, null);
     }
 
     protected void rewriteOperatorExpression() throws CompilationException {
         // Rewrites like/not-like/in/not-in operators into function call 
expressions.
         OperatorExpressionVisitor operatorExpressionVisitor = new 
OperatorExpressionVisitor(context);
-        topExpr.accept(operatorExpressionVisitor, null);
+        rewriteTopExpr(operatorExpressionVisitor, null);
     }
 
     protected void inlineColumnAlias() throws CompilationException {
         // Inline column aliases.
         InlineColumnAliasVisitor inlineColumnAliasVisitor = new 
InlineColumnAliasVisitor(context);
-        topExpr.accept(inlineColumnAliasVisitor, null);
+        rewriteTopExpr(inlineColumnAliasVisitor, null);
     }
 
     protected void variableCheckAndRewrite() throws CompilationException {
         VariableCheckAndRewriteVisitor variableCheckAndRewriteVisitor =
                 new VariableCheckAndRewriteVisitor(context, metadataProvider, 
externalVars);
-        topExpr.accept(variableCheckAndRewriteVisitor, null);
+        rewriteTopExpr(variableCheckAndRewriteVisitor, null);
     }
 
     protected void rewriteGroupBys() throws CompilationException {
         SqlppGroupByVisitor groupByVisitor = new SqlppGroupByVisitor(context);
-        topExpr.accept(groupByVisitor, null);
+        rewriteTopExpr(groupByVisitor, null);
+    }
+
+    protected void rewriteWindowExpressions() throws CompilationException {
+        // Create window variables and extract aggregation inputs into LET 
clauses
+        SqlppWindowRewriteVisitor windowVisitor = new 
SqlppWindowRewriteVisitor(context);
+        rewriteTopExpr(windowVisitor, null);
+    }
+
+    protected void rewriteWindowAggregationSugar() throws CompilationException 
{
+        SqlppWindowAggregationSugarVisitor windowVisitor = new 
SqlppWindowAggregationSugarVisitor(context);
+        rewriteTopExpr(windowVisitor, null);
     }
 
     protected void inlineDeclaredUdfs(boolean inlineUdfs) throws 
CompilationException {
@@ -238,13 +271,25 @@ public class SqlppQueryRewriter implements IQueryRewriter 
{
             SqlppInlineUdfsVisitor visitor = new 
SqlppInlineUdfsVisitor(context,
                     new SqlppFunctionBodyRewriterFactory() /* the rewriter for 
function bodies expressions*/,
                     declaredFunctions, metadataProvider);
-            while (topExpr.accept(visitor, declaredFunctions)) {
+            while (rewriteTopExpr(visitor, declaredFunctions)) {
                 // loop until no more changes
             }
         }
         declaredFunctions.removeAll(usedStoredFunctionDecls);
     }
 
+    private <R, T> R rewriteTopExpr(ILangVisitor<R, T> visitor, T arg) throws 
CompilationException {
+        R result = topExpr.accept(visitor, arg);
+        logExpression(">>>> AST After", visitor.getClass().getSimpleName());
+        return result;
+    }
+
+    private void logExpression(String p0, String p1) throws 
CompilationException {
+        if (isLogEnabled) {
+            LOGGER.trace("{} {}\n{}", p0, p1, 
SqlppAstPrintUtil.toString(topExpr));
+        }
+    }
+
     @Override
     public Set<CallExpr> getFunctionCalls(Expression expression) throws 
CompilationException {
         GatherFunctionCalls gfc = new GatherFunctionCalls();
@@ -396,13 +441,28 @@ public class SqlppQueryRewriter implements IQueryRewriter 
{
 
         @Override
         public Void visit(WindowExpression winExpr, Void arg) throws 
CompilationException {
-            winExpr.getExpr().accept(this, arg);
             if (winExpr.hasPartitionList()) {
                 for (Expression expr : winExpr.getPartitionList()) {
                     expr.accept(this, arg);
                 }
             }
-            for (Expression expr : winExpr.getOrderbyList()) {
+            if (winExpr.hasOrderByList()) {
+                for (Expression expr : winExpr.getOrderbyList()) {
+                    expr.accept(this, arg);
+                }
+            }
+            if (winExpr.hasFrameStartExpr()) {
+                winExpr.getFrameStartExpr().accept(this, arg);
+            }
+            if (winExpr.hasFrameEndExpr()) {
+                winExpr.getFrameEndExpr().accept(this, arg);
+            }
+            if (winExpr.hasWindowFieldList()) {
+                for (Pair<Expression, Identifier> p : 
winExpr.getWindowFieldList()) {
+                    p.first.accept(this, arg);
+                }
+            }
+            for (Expression expr : winExpr.getExprList()) {
                 expr.accept(this, arg);
             }
             return null;

Reply via email to