[teiid-commits] teiid SVN: r3347 - in trunk: build/kits/jboss-container and 11 other directories.

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Thu Jul 28 15:58:09 EDT 2011


Author: shawkins
Date: 2011-07-28 15:58:08 -0400 (Thu, 28 Jul 2011)
New Revision: 3347

Added:
   trunk/documentation/reference/src/main/docbook/en-US/content/sql_clauses.xml
Modified:
   trunk/api/src/main/java/org/teiid/translator/ExecutionFactory.java
   trunk/build/kits/jboss-container/teiid-releasenotes.html
   trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/sqlserver/SQLServerExecutionFactory.java
   trunk/documentation/reference/src/main/docbook/en-US/Reference.xml
   trunk/documentation/reference/src/main/docbook/en-US/content/grammar.xml
   trunk/documentation/reference/src/main/docbook/en-US/content/sql_support.xml
   trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/CapabilitiesConverter.java
   trunk/engine/src/main/java/org/teiid/query/function/aggregate/RankingFunction.java
   trunk/engine/src/main/java/org/teiid/query/optimizer/capabilities/SourceCapabilities.java
   trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/CriteriaCapabilityValidatorVisitor.java
   trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleAssignOutputElements.java
   trunk/engine/src/main/java/org/teiid/query/processor/relational/WindowFunctionProjectNode.java
   trunk/engine/src/main/java/org/teiid/query/sql/symbol/AggregateSymbol.java
   trunk/engine/src/main/resources/org/teiid/query/i18n.properties
   trunk/engine/src/test/java/org/teiid/query/processor/TestWindowFunctions.java
Log:
TEIID-1667 finishing off window function support

Modified: trunk/api/src/main/java/org/teiid/translator/ExecutionFactory.java
===================================================================
--- trunk/api/src/main/java/org/teiid/translator/ExecutionFactory.java	2011-07-28 11:43:06 UTC (rev 3346)
+++ trunk/api/src/main/java/org/teiid/translator/ExecutionFactory.java	2011-07-28 19:58:08 UTC (rev 3347)
@@ -879,6 +879,14 @@
     }
     
     /**
+     * @return true if all aggregates can have window function order by clauses.
+     * @since 7.5
+     */
+    public boolean supportsWindowOrderByWithAggregates() {
+    	return supportsElementaryOlapOperations();
+    }
+    
+    /**
      * @return true if array_agg is supported
      * @since 7.5
      */

Modified: trunk/build/kits/jboss-container/teiid-releasenotes.html
===================================================================
--- trunk/build/kits/jboss-container/teiid-releasenotes.html	2011-07-28 11:43:06 UTC (rev 3346)
+++ trunk/build/kits/jboss-container/teiid-releasenotes.html	2011-07-28 19:58:08 UTC (rev 3347)
@@ -26,6 +26,7 @@
 </UL>
 <H2><A NAME="Highlights"></A>Highlights</H2>
 <UL>
+    <LI><B>Window function support</B> - Teiid and pushdown support was added for SQL 2003 OLAP window functions.  The analytical ranking functions RANK, DENSE_RANK, and ROW_NUMBER were also added.  See the reference for more.
 	<LI><B>Subquery optimization control</B> - added the DJ hint to indicate that a subquery should be the independent side of a dependent join.
 	<LI><B>MAKEIND Hint</B> - The MAKEIND hint can be used to indicate that the other side of the join should be made dependent.
     <LI><B>ODBC SSL</B> - added support for SSL encrypted ODBC connections.

Modified: trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/sqlserver/SQLServerExecutionFactory.java
===================================================================
--- trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/sqlserver/SQLServerExecutionFactory.java	2011-07-28 11:43:06 UTC (rev 3346)
+++ trunk/connectors/translator-jdbc/src/main/java/org/teiid/translator/jdbc/sqlserver/SQLServerExecutionFactory.java	2011-07-28 19:58:08 UTC (rev 3347)
@@ -231,5 +231,10 @@
     public boolean supportsElementaryOlapOperations() {
     	return true;
     }
+    
+    @Override
+    public boolean supportsWindowOrderByWithAggregates() {
+    	return false;
+    }
     
 }

Modified: trunk/documentation/reference/src/main/docbook/en-US/Reference.xml
===================================================================
--- trunk/documentation/reference/src/main/docbook/en-US/Reference.xml	2011-07-28 11:43:06 UTC (rev 3346)
+++ trunk/documentation/reference/src/main/docbook/en-US/Reference.xml	2011-07-28 19:58:08 UTC (rev 3347)
@@ -48,6 +48,7 @@
   <toc />
   <xi:include href="content/preface.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
   <xi:include href="content/sql_support.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+  <xi:include href="content/sql_clauses.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
   <xi:include href="content/ddl_support.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
   <xi:include href="content/xml_queries.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
   <xi:include href="content/datatypes.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />

Modified: trunk/documentation/reference/src/main/docbook/en-US/content/grammar.xml
===================================================================
--- trunk/documentation/reference/src/main/docbook/en-US/content/grammar.xml	2011-07-28 11:43:06 UTC (rev 3346)
+++ trunk/documentation/reference/src/main/docbook/en-US/content/grammar.xml	2011-07-28 19:58:08 UTC (rev 3347)
@@ -1,7 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE appendix PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
 <appendix id="grammar">
-  <title>BNF for SQL Grammar</title><section>
+  <title>BNF for SQL Grammar</title>
+<section>
 <title>TOKENS</title>
 <informaltable frame="none">
 <tgroup cols="1">
@@ -189,6 +190,7 @@
 | &lt;NOT: "not"&gt;
 | &lt;NULL: "null"&gt;
 | &lt;OF: "of"&gt;
+| &lt;OFFSET: "offset"&gt;
 | &lt;OLD: "old"&gt;
 | &lt;ON: "on"&gt;
 | &lt;ONLY: "only"&gt;
@@ -543,15 +545,15 @@
 <row>
 <entry align="right" valign="top"><para><anchor id="prod16" xreflabel="insert"/>insert</para></entry>
 <entry align="left" valign="top"><para>::= 
-&lt;INSERT&gt; &lt;INTO&gt; <link linkend="prod2">id</link> ( <link linkend="prod47">columnList</link> )? ( ( &lt;VALUES&gt; <link linkend="prod48">rowValues</link> ) | ( <link linkend="prod13">queryExpression</link> ) ) ( <link linkend="prod45">option</link> )?</para></entry></row>
+&lt;INSERT&gt; &lt;INTO&gt; <link linkend="prod2">id</link> ( <link linkend="prod47">columnList</link> )? ( ( &lt;VALUES&gt; &lt;LPAREN&gt; <link linkend="prod48">expressionList</link> &lt;RPAREN&gt; ) | ( <link linkend="prod13">queryExpression</link> ) ) ( <link linkend="prod45">option</link> )?</para></entry></row>
 <row>
 <entry align="right" valign="top"><para><anchor id="prod47" xreflabel="columnList"/>columnList</para></entry>
 <entry align="left" valign="top"><para>::= 
 &lt;LPAREN&gt; <link linkend="prod2">id</link> ( &lt;COMMA&gt; <link linkend="prod2">id</link> )* &lt;RPAREN&gt;</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod48" xreflabel="rowValues"/>rowValues</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod48" xreflabel="expressionList"/>expressionList</para></entry>
 <entry align="left" valign="top"><para>::= 
-&lt;LPAREN&gt; <link linkend="prod24">expression</link> ( &lt;COMMA&gt; <link linkend="prod24">expression</link> )* &lt;RPAREN&gt;</para></entry></row>
+<link linkend="prod24">expression</link> ( &lt;COMMA&gt; <link linkend="prod24">expression</link> )*</para></entry></row>
 <row>
 <entry align="right" valign="top"><para><anchor id="prod17" xreflabel="update"/>update</para></entry>
 <entry align="left" valign="top"><para>::= 
@@ -609,47 +611,47 @@
 <entry align="left" valign="top"><para>::= 
 &lt;ALL_IN_GROUP&gt;</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod66" xreflabel="xmlAgg"/>xmlAgg</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod66" xreflabel="orderedAgg"/>orderedAgg</para></entry>
 <entry align="left" valign="top"><para>::= 
-&lt;XMLAGG&gt; &lt;LPAREN&gt; <link linkend="prod24">expression</link> ( <link linkend="prod53">orderby</link> )? &lt;RPAREN&gt;</para></entry></row>
+( &lt;XMLAGG&gt; | &lt;ARRAY_AGG&gt; ) &lt;LPAREN&gt; <link linkend="prod24">expression</link> ( <link linkend="prod53">orderby</link> )? &lt;RPAREN&gt; <link linkend="prod67">filterClause</link></para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod67" xreflabel="arrayAgg"/>arrayAgg</para></entry>
-<entry align="left" valign="top"><para>::= 
-&lt;ARRAY_AGG&gt; &lt;LPAREN&gt; <link linkend="prod24">expression</link> ( <link linkend="prod53">orderby</link> )? &lt;RPAREN&gt;</para></entry></row>
-<row>
 <entry align="right" valign="top"><para><anchor id="prod68" xreflabel="textAgg"/>textAgg</para></entry>
 <entry align="left" valign="top"><para>::= 
-<link linkend="prod11">nonReserved</link> &lt;LPAREN&gt; &lt;FOR&gt; <link linkend="prod65">derivedColumn</link> ( &lt;COMMA&gt; <link linkend="prod65">derivedColumn</link> )* ( &lt;ID&gt; <link linkend="prod69">charVal</link> )? ( ( &lt;ID&gt; <link linkend="prod69">charVal</link> ) )? ( &lt;ID&gt; )? ( ( &lt;ID&gt; <link linkend="prod2">id</link> ) )? ( <link linkend="prod53">orderby</link> )? &lt;RPAREN&gt;</para></entry></row>
+<link linkend="prod11">nonReserved</link> &lt;LPAREN&gt; &lt;FOR&gt; <link linkend="prod65">derivedColumn</link> ( &lt;COMMA&gt; <link linkend="prod65">derivedColumn</link> )* ( &lt;ID&gt; <link linkend="prod69">charVal</link> )? ( ( &lt;ID&gt; <link linkend="prod69">charVal</link> ) )? ( &lt;ID&gt; )? ( ( &lt;ID&gt; <link linkend="prod2">id</link> ) )? ( <link linkend="prod53">orderby</link> )? &lt;RPAREN&gt; <link linkend="prod67">filterClause</link></para></entry></row>
 <row>
 <entry align="right" valign="top"><para><anchor id="prod70" xreflabel="aggregateSymbol"/>aggregateSymbol</para></entry>
 <entry align="left" valign="top"><para>::= 
-( ( <link linkend="prod11">nonReserved</link> &lt;LPAREN&gt; &lt;STAR&gt; &lt;RPAREN&gt; ) | ( ( <link linkend="prod11">nonReserved</link> | &lt;ANY&gt; | &lt;SOME&gt; ) &lt;LPAREN&gt; ( &lt;DISTINCT&gt; | &lt;ALL&gt; )? <link linkend="prod24">expression</link> &lt;RPAREN&gt; ) )</para></entry></row>
+( ( ( <link linkend="prod11">nonReserved</link> &lt;LPAREN&gt; &lt;STAR&gt; &lt;RPAREN&gt; ) | ( <link linkend="prod11">nonReserved</link> &lt;LPAREN&gt; &lt;RPAREN&gt; ) | ( ( <link linkend="prod11">nonReserved</link> | &lt;ANY&gt; | &lt;SOME&gt; ) &lt;LPAREN&gt; ( &lt;DISTINCT&gt; | &lt;ALL&gt; )? <link linkend="prod24">expression</link> &lt;RPAREN&gt; ) ) <link linkend="prod67">filterClause</link> )</para></entry></row>
 <row>
+<entry align="right" valign="top"><para><anchor id="prod67" xreflabel="filterClause"/>filterClause</para></entry>
+<entry align="left" valign="top"><para>::= 
+( &lt;FILTER&gt; &lt;LPAREN&gt; &lt;WHERE&gt; <link linkend="prod71">booleanPrimary</link> &lt;RPAREN&gt; )?</para></entry></row>
+<row>
 <entry align="right" valign="top"><para><anchor id="prod59" xreflabel="from"/>from</para></entry>
 <entry align="left" valign="top"><para>::= 
-&lt;FROM&gt; ( <link linkend="prod71">tableReference</link> ( &lt;COMMA&gt; <link linkend="prod71">tableReference</link> )* )</para></entry></row>
+&lt;FROM&gt; ( <link linkend="prod72">tableReference</link> ( &lt;COMMA&gt; <link linkend="prod72">tableReference</link> )* )</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod71" xreflabel="tableReference"/>tableReference</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod72" xreflabel="tableReference"/>tableReference</para></entry>
 <entry align="left" valign="top"><para>::= 
-( ( &lt;LBRACE&gt; <link linkend="prod11">nonReserved</link> <link linkend="prod72">joinedTable</link> &lt;RBRACE&gt; ) | <link linkend="prod72">joinedTable</link> )</para></entry></row>
+( ( &lt;LBRACE&gt; <link linkend="prod11">nonReserved</link> <link linkend="prod73">joinedTable</link> &lt;RBRACE&gt; ) | <link linkend="prod73">joinedTable</link> )</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod72" xreflabel="joinedTable"/>joinedTable</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod73" xreflabel="joinedTable"/>joinedTable</para></entry>
 <entry align="left" valign="top"><para>::= 
-<link linkend="prod73">tablePrimary</link> ( ( <link linkend="prod74">crossJoin</link> | <link linkend="prod75">qualifiedJoin</link> ) )*</para></entry></row>
+<link linkend="prod74">tablePrimary</link> ( ( <link linkend="prod75">crossJoin</link> | <link linkend="prod76">qualifiedJoin</link> ) )*</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod74" xreflabel="crossJoin"/>crossJoin</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod75" xreflabel="crossJoin"/>crossJoin</para></entry>
 <entry align="left" valign="top"><para>::= 
-( ( &lt;CROSS&gt; | &lt;UNION&gt; ) &lt;JOIN&gt; <link linkend="prod73">tablePrimary</link> )</para></entry></row>
+( ( &lt;CROSS&gt; | &lt;UNION&gt; ) &lt;JOIN&gt; <link linkend="prod74">tablePrimary</link> )</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod75" xreflabel="qualifiedJoin"/>qualifiedJoin</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod76" xreflabel="qualifiedJoin"/>qualifiedJoin</para></entry>
 <entry align="left" valign="top"><para>::= 
-( ( ( &lt;RIGHT&gt; ( &lt;OUTER&gt; )? ) | ( &lt;LEFT&gt; ( &lt;OUTER&gt; )? ) | ( &lt;FULL&gt; ( &lt;OUTER&gt; )? ) | &lt;INNER&gt; )? &lt;JOIN&gt; <link linkend="prod71">tableReference</link> &lt;ON&gt; <link linkend="prod35">criteria</link> )</para></entry></row>
+( ( ( &lt;RIGHT&gt; ( &lt;OUTER&gt; )? ) | ( &lt;LEFT&gt; ( &lt;OUTER&gt; )? ) | ( &lt;FULL&gt; ( &lt;OUTER&gt; )? ) | &lt;INNER&gt; )? &lt;JOIN&gt; <link linkend="prod72">tableReference</link> &lt;ON&gt; <link linkend="prod35">criteria</link> )</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod73" xreflabel="tablePrimary"/>tablePrimary</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod74" xreflabel="tablePrimary"/>tablePrimary</para></entry>
 <entry align="left" valign="top"><para>::= 
-( <link linkend="prod76">textTable</link> | <link linkend="prod77">arrayTable</link> | <link linkend="prod78">xmlTable</link> | <link linkend="prod79">unaryFromClause</link> | <link linkend="prod80">subqueryFromClause</link> | ( &lt;LPAREN&gt; <link linkend="prod72">joinedTable</link> &lt;RPAREN&gt; ) ) ( ( &lt;MAKEDEP&gt; ) | ( &lt;MAKENOTDEP&gt; ) )?</para></entry></row>
+( <link linkend="prod77">textTable</link> | <link linkend="prod78">arrayTable</link> | <link linkend="prod79">xmlTable</link> | <link linkend="prod80">unaryFromClause</link> | <link linkend="prod81">subqueryFromClause</link> | ( &lt;LPAREN&gt; <link linkend="prod73">joinedTable</link> &lt;RPAREN&gt; ) ) ( ( &lt;MAKEDEP&gt; ) | ( &lt;MAKENOTDEP&gt; ) )?</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod81" xreflabel="xmlSerialize"/>xmlSerialize</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod82" xreflabel="xmlSerialize"/>xmlSerialize</para></entry>
 <entry align="left" valign="top"><para>::= 
 &lt;XMLSERIALIZE&gt; &lt;LPAREN&gt; ( <link linkend="prod11">nonReserved</link> )? <link linkend="prod24">expression</link> ( &lt;AS&gt; ( &lt;STRING&gt; | &lt;VARCHAR&gt; | &lt;CLOB&gt; ) )? &lt;RPAREN&gt;</para></entry></row>
 <row>
@@ -657,39 +659,39 @@
 <entry align="left" valign="top"><para>::= 
 &lt;ID&gt;</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod77" xreflabel="arrayTable"/>arrayTable</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod78" xreflabel="arrayTable"/>arrayTable</para></entry>
 <entry align="left" valign="top"><para>::= 
 &lt;ID&gt; &lt;LPAREN&gt; <link linkend="prod24">expression</link> <link linkend="prod11">nonReserved</link> <link linkend="prod42">createElementsWithTypes</link> &lt;RPAREN&gt; ( &lt;AS&gt; )? <link linkend="prod2">id</link></para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod76" xreflabel="textTable"/>textTable</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod77" xreflabel="textTable"/>textTable</para></entry>
 <entry align="left" valign="top"><para>::= 
-&lt;ID&gt; &lt;LPAREN&gt; <link linkend="prod24">expression</link> <link linkend="prod11">nonReserved</link> <link linkend="prod82">textColumn</link> ( &lt;COMMA&gt; <link linkend="prod82">textColumn</link> )* ( &lt;ID&gt; <link linkend="prod69">charVal</link> )? ( ( &lt;ESCAPE&gt; <link linkend="prod69">charVal</link> ) | ( &lt;ID&gt; <link linkend="prod69">charVal</link> ) )? ( &lt;ID&gt; ( <link linkend="prod83">intVal</link> )? )? ( &lt;ID&gt; <link linkend="prod83">intVal</link> )? &lt;RPAREN&gt; ( &lt;AS&gt; )? <link linkend="prod2">id</link></para></entry></row>
+&lt;ID&gt; &lt;LPAREN&gt; <link linkend="prod24">expression</link> <link linkend="prod11">nonReserved</link> <link linkend="prod83">textColumn</link> ( &lt;COMMA&gt; <link linkend="prod83">textColumn</link> )* ( &lt;ID&gt; <link linkend="prod69">charVal</link> )? ( ( &lt;ESCAPE&gt; <link linkend="prod69">charVal</link> ) | ( &lt;ID&gt; <link linkend="prod69">charVal</link> ) )? ( &lt;ID&gt; ( <link linkend="prod84">intVal</link> )? )? ( &lt;ID&gt; <link linkend="prod84">intVal</link> )? &lt;RPAREN&gt; ( &lt;AS&gt; )? <link linkend="prod2">id</link></para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod82" xreflabel="textColumn"/>textColumn</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod83" xreflabel="textColumn"/>textColumn</para></entry>
 <entry align="left" valign="top"><para>::= 
-<link linkend="prod2">id</link> <link linkend="prod38">dataType</link> ( &lt;ID&gt; <link linkend="prod83">intVal</link> )?</para></entry></row>
+<link linkend="prod2">id</link> <link linkend="prod38">dataType</link> ( &lt;ID&gt; <link linkend="prod84">intVal</link> )?</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod84" xreflabel="xmlQuery"/>xmlQuery</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod85" xreflabel="xmlQuery"/>xmlQuery</para></entry>
 <entry align="left" valign="top"><para>::= 
-&lt;XMLQUERY&gt; &lt;LPAREN&gt; ( <link linkend="prod85">xmlNamespaces</link> &lt;COMMA&gt; )? <link linkend="prod1">stringVal</link> ( &lt;ID&gt; <link linkend="prod65">derivedColumn</link> ( &lt;COMMA&gt; <link linkend="prod65">derivedColumn</link> )* )? ( ( &lt;NULL&gt; | <link linkend="prod11">nonReserved</link> ) &lt;ON&gt; <link linkend="prod11">nonReserved</link> )? &lt;RPAREN&gt;</para></entry></row>
+&lt;XMLQUERY&gt; &lt;LPAREN&gt; ( <link linkend="prod86">xmlNamespaces</link> &lt;COMMA&gt; )? <link linkend="prod1">stringVal</link> ( &lt;ID&gt; <link linkend="prod65">derivedColumn</link> ( &lt;COMMA&gt; <link linkend="prod65">derivedColumn</link> )* )? ( ( &lt;NULL&gt; | <link linkend="prod11">nonReserved</link> ) &lt;ON&gt; <link linkend="prod11">nonReserved</link> )? &lt;RPAREN&gt;</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod78" xreflabel="xmlTable"/>xmlTable</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod79" xreflabel="xmlTable"/>xmlTable</para></entry>
 <entry align="left" valign="top"><para>::= 
-&lt;XMLTABLE&gt; &lt;LPAREN&gt; ( <link linkend="prod85">xmlNamespaces</link> &lt;COMMA&gt; )? <link linkend="prod1">stringVal</link> ( &lt;ID&gt; <link linkend="prod65">derivedColumn</link> ( &lt;COMMA&gt; <link linkend="prod65">derivedColumn</link> )* )? ( &lt;ID&gt; <link linkend="prod86">xmlColumn</link> ( &lt;COMMA&gt; <link linkend="prod86">xmlColumn</link> )* )? &lt;RPAREN&gt; ( &lt;AS&gt; )? <link linkend="prod2">id</link></para></entry></row>
+&lt;XMLTABLE&gt; &lt;LPAREN&gt; ( <link linkend="prod86">xmlNamespaces</link> &lt;COMMA&gt; )? <link linkend="prod1">stringVal</link> ( &lt;ID&gt; <link linkend="prod65">derivedColumn</link> ( &lt;COMMA&gt; <link linkend="prod65">derivedColumn</link> )* )? ( &lt;ID&gt; <link linkend="prod87">xmlColumn</link> ( &lt;COMMA&gt; <link linkend="prod87">xmlColumn</link> )* )? &lt;RPAREN&gt; ( &lt;AS&gt; )? <link linkend="prod2">id</link></para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod86" xreflabel="xmlColumn"/>xmlColumn</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod87" xreflabel="xmlColumn"/>xmlColumn</para></entry>
 <entry align="left" valign="top"><para>::= 
 <link linkend="prod2">id</link> ( ( &lt;FOR&gt; <link linkend="prod11">nonReserved</link> ) | ( <link linkend="prod38">dataType</link> ( &lt;DEFAULT_KEYWORD&gt; <link linkend="prod24">expression</link> )? ( <link linkend="prod11">nonReserved</link> <link linkend="prod1">stringVal</link> )? ) )</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod83" xreflabel="intVal"/>intVal</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod84" xreflabel="intVal"/>intVal</para></entry>
 <entry align="left" valign="top"><para>::= 
 &lt;INTEGERVAL&gt;</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod80" xreflabel="subqueryFromClause"/>subqueryFromClause</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod81" xreflabel="subqueryFromClause"/>subqueryFromClause</para></entry>
 <entry align="left" valign="top"><para>::= 
 ( &lt;TABLE&gt; )? &lt;LPAREN&gt; ( <link linkend="prod13">queryExpression</link> | <link linkend="prod15">storedProcedure</link> ) &lt;RPAREN&gt; ( &lt;AS&gt; )? <link linkend="prod2">id</link></para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod79" xreflabel="unaryFromClause"/>unaryFromClause</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod80" xreflabel="unaryFromClause"/>unaryFromClause</para></entry>
 <entry align="left" valign="top"><para>::= 
 ( &lt;ID&gt; ( ( &lt;AS&gt; )? <link linkend="prod2">id</link> )? )</para></entry></row>
 <row>
@@ -699,21 +701,21 @@
 <row>
 <entry align="right" valign="top"><para><anchor id="prod35" xreflabel="criteria"/>criteria</para></entry>
 <entry align="left" valign="top"><para>::= 
-<link linkend="prod87">compoundCritOr</link></para></entry></row>
+<link linkend="prod88">compoundCritOr</link></para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod87" xreflabel="compoundCritOr"/>compoundCritOr</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod88" xreflabel="compoundCritOr"/>compoundCritOr</para></entry>
 <entry align="left" valign="top"><para>::= 
-<link linkend="prod88">compoundCritAnd</link> ( &lt;OR&gt; <link linkend="prod88">compoundCritAnd</link> )*</para></entry></row>
+<link linkend="prod89">compoundCritAnd</link> ( &lt;OR&gt; <link linkend="prod89">compoundCritAnd</link> )*</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod88" xreflabel="compoundCritAnd"/>compoundCritAnd</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod89" xreflabel="compoundCritAnd"/>compoundCritAnd</para></entry>
 <entry align="left" valign="top"><para>::= 
-<link linkend="prod89">notCrit</link> ( &lt;AND&gt; <link linkend="prod89">notCrit</link> )*</para></entry></row>
+<link linkend="prod90">notCrit</link> ( &lt;AND&gt; <link linkend="prod90">notCrit</link> )*</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod89" xreflabel="notCrit"/>notCrit</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod90" xreflabel="notCrit"/>notCrit</para></entry>
 <entry align="left" valign="top"><para>::= 
-( &lt;NOT&gt; )? <link linkend="prod90">booleanPrimary</link></para></entry></row>
+( &lt;NOT&gt; )? <link linkend="prod71">booleanPrimary</link></para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod90" xreflabel="booleanPrimary"/>booleanPrimary</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod71" xreflabel="booleanPrimary"/>booleanPrimary</para></entry>
 <entry align="left" valign="top"><para>::= 
 ( <link linkend="prod41">translateCriteria</link> | ( <link linkend="prod91">commonValueExpression</link> ( ( <link linkend="prod92">betweenCrit</link> | <link linkend="prod93">matchCrit</link> | <link linkend="prod94">setCrit</link> | <link linkend="prod95">isNullCrit</link> | <link linkend="prod96">subqueryCompareCriteria</link> | <link linkend="prod97">compareCrit</link> ) )? ) | <link linkend="prod98">existsCriteria</link> | <link linkend="prod37">hasCriteria</link> )</para></entry></row>
 <row>
@@ -763,32 +765,36 @@
 <row>
 <entry align="right" valign="top"><para><anchor id="prod60" xreflabel="groupBy"/>groupBy</para></entry>
 <entry align="left" valign="top"><para>::= 
-&lt;GROUP&gt; &lt;BY&gt; ( <link linkend="prod102">groupByItem</link> ( &lt;COMMA&gt; <link linkend="prod102">groupByItem</link> )* )</para></entry></row>
+&lt;GROUP&gt; &lt;BY&gt; <link linkend="prod48">expressionList</link></para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod102" xreflabel="groupByItem"/>groupByItem</para></entry>
-<entry align="left" valign="top"><para>::= 
-<link linkend="prod24">expression</link></para></entry></row>
-<row>
 <entry align="right" valign="top"><para><anchor id="prod61" xreflabel="having"/>having</para></entry>
 <entry align="left" valign="top"><para>::= 
 &lt;HAVING&gt; <link linkend="prod35">criteria</link></para></entry></row>
 <row>
 <entry align="right" valign="top"><para><anchor id="prod53" xreflabel="orderby"/>orderby</para></entry>
 <entry align="left" valign="top"><para>::= 
-&lt;ORDER&gt; &lt;BY&gt; <link linkend="prod103">sortSpecification</link> ( &lt;COMMA&gt; <link linkend="prod103">sortSpecification</link> )*</para></entry></row>
+&lt;ORDER&gt; &lt;BY&gt; <link linkend="prod102">sortSpecification</link> ( &lt;COMMA&gt; <link linkend="prod102">sortSpecification</link> )*</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod103" xreflabel="sortSpecification"/>sortSpecification</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod102" xreflabel="sortSpecification"/>sortSpecification</para></entry>
 <entry align="left" valign="top"><para>::= 
-<link linkend="prod104">sortKey</link> ( &lt;ASC&gt; | &lt;DESC&gt; )? ( <link linkend="prod11">nonReserved</link> <link linkend="prod11">nonReserved</link> )?</para></entry></row>
+<link linkend="prod103">sortKey</link> ( &lt;ASC&gt; | &lt;DESC&gt; )? ( <link linkend="prod11">nonReserved</link> <link linkend="prod11">nonReserved</link> )?</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod104" xreflabel="sortKey"/>sortKey</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod103" xreflabel="sortKey"/>sortKey</para></entry>
 <entry align="left" valign="top"><para>::= 
 <link linkend="prod24">expression</link></para></entry></row>
 <row>
+<entry align="right" valign="top"><para><anchor id="prod104" xreflabel="intParam"/>intParam</para></entry>
+<entry align="left" valign="top"><para>::= 
+( <link linkend="prod84">intVal</link> | &lt;QMARK&gt; )</para></entry></row>
+<row>
 <entry align="right" valign="top"><para><anchor id="prod54" xreflabel="limit"/>limit</para></entry>
 <entry align="left" valign="top"><para>::= 
-&lt;LIMIT&gt; ( &lt;INTEGERVAL&gt; | &lt;QMARK&gt; ) ( &lt;COMMA&gt; ( &lt;INTEGERVAL&gt; | &lt;QMARK&gt; ) )?</para></entry></row>
+( ( &lt;LIMIT&gt; <link linkend="prod104">intParam</link> ( &lt;COMMA&gt; <link linkend="prod104">intParam</link> )? ) | ( &lt;OFFSET&gt; <link linkend="prod104">intParam</link> ( &lt;ROW&gt; | &lt;ROWS&gt; ) ( <link linkend="prod105">fetchLimit</link> )? ) | ( <link linkend="prod105">fetchLimit</link> ) )</para></entry></row>
 <row>
+<entry align="right" valign="top"><para><anchor id="prod105" xreflabel="fetchLimit"/>fetchLimit</para></entry>
+<entry align="left" valign="top"><para>::= 
+&lt;FETCH&gt; <link linkend="prod11">nonReserved</link> ( <link linkend="prod104">intParam</link> )? ( &lt;ROW&gt; | &lt;ROWS&gt; ) &lt;ONLY&gt;</para></entry></row>
+<row>
 <entry align="right" valign="top"><para><anchor id="prod45" xreflabel="option"/>option</para></entry>
 <entry align="left" valign="top"><para>::= 
 &lt;OPTION&gt; ( &lt;MAKEDEP&gt; <link linkend="prod2">id</link> ( &lt;COMMA&gt; <link linkend="prod2">id</link> )* | &lt;MAKENOTDEP&gt; <link linkend="prod2">id</link> ( &lt;COMMA&gt; <link linkend="prod2">id</link> )* | &lt;NOCACHE&gt; ( <link linkend="prod2">id</link> ( &lt;COMMA&gt; <link linkend="prod2">id</link> )* )? )*</para></entry></row>
@@ -799,69 +805,73 @@
 <row>
 <entry align="right" valign="top"><para><anchor id="prod91" xreflabel="commonValueExpression"/>commonValueExpression</para></entry>
 <entry align="left" valign="top"><para>::= 
-( <link linkend="prod105">plusExpression</link> ( &lt;CONCAT_OP&gt; <link linkend="prod105">plusExpression</link> )* )</para></entry></row>
+( <link linkend="prod106">plusExpression</link> ( &lt;CONCAT_OP&gt; <link linkend="prod106">plusExpression</link> )* )</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod105" xreflabel="plusExpression"/>plusExpression</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod106" xreflabel="plusExpression"/>plusExpression</para></entry>
 <entry align="left" valign="top"><para>::= 
-( <link linkend="prod106">timesExpression</link> ( <link linkend="prod107">plusOperator</link> <link linkend="prod106">timesExpression</link> )* )</para></entry></row>
+( <link linkend="prod107">timesExpression</link> ( <link linkend="prod108">plusOperator</link> <link linkend="prod107">timesExpression</link> )* )</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod107" xreflabel="plusOperator"/>plusOperator</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod108" xreflabel="plusOperator"/>plusOperator</para></entry>
 <entry align="left" valign="top"><para>::= 
 ( &lt;PLUS&gt; | &lt;MINUS&gt; )</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod106" xreflabel="timesExpression"/>timesExpression</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod107" xreflabel="timesExpression"/>timesExpression</para></entry>
 <entry align="left" valign="top"><para>::= 
-( <link linkend="prod108">valueExpressionPrimary</link> ( <link linkend="prod109">timesOperator</link> <link linkend="prod108">valueExpressionPrimary</link> )* )</para></entry></row>
+( <link linkend="prod109">valueExpressionPrimary</link> ( <link linkend="prod110">timesOperator</link> <link linkend="prod109">valueExpressionPrimary</link> )* )</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod109" xreflabel="timesOperator"/>timesOperator</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod110" xreflabel="timesOperator"/>timesOperator</para></entry>
 <entry align="left" valign="top"><para>::= 
 ( &lt;STAR&gt; | &lt;SLASH&gt; )</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod108" xreflabel="valueExpressionPrimary"/>valueExpressionPrimary</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod109" xreflabel="valueExpressionPrimary"/>valueExpressionPrimary</para></entry>
 <entry align="left" valign="top"><para>::= 
-( &lt;QMARK&gt; | &lt;POS_REF&gt; | <link linkend="prod110">literal</link> | ( &lt;LBRACE&gt; <link linkend="prod11">nonReserved</link> <link linkend="prod111">function</link> &lt;RBRACE&gt; ) | ( <link linkend="prod68">textAgg</link> ) | ( <link linkend="prod70">aggregateSymbol</link> ) | ( <link linkend="prod70">aggregateSymbol</link> ) | ( <link linkend="prod70">aggregateSymbol</link> ) | ( <link linkend="prod66">xmlAgg</link> ) | ( <link linkend="prod67">arrayAgg</link> ) | ( <link linkend="prod111">function</link> ) | ( &lt;ID&gt; ( &lt;LSBRACE&gt; <link linkend="prod83">intVal</link> &lt;RSBRACE&gt; )? ) | <link linkend="prod100">subquery</link> | ( &lt;LPAREN&gt; <link linkend="prod24">expression</link> &lt;RPAREN&gt; ( &lt;LSBRACE&gt; <link linkend="prod83">intVal</link> &lt;RSBRACE&gt; )? ) | <link linkend="prod112">searchedCaseExpression</link> | <link linkend="prod113">caseExpression</link> )</para></entry></row>
+( &lt;QMARK&gt; | &lt;POS_REF&gt; | <link linkend="prod111">literal</link> | ( &lt;LBRACE&gt; <link linkend="prod11">nonReserved</link> <link linkend="prod112">function</link> &lt;RBRACE&gt; ) | ( <link linkend="prod68">textAgg</link> ( <link linkend="prod113">windowSpecification</link> )? ) | ( <link linkend="prod70">aggregateSymbol</link> ( <link linkend="prod113">windowSpecification</link> )? ) | ( <link linkend="prod70">aggregateSymbol</link> ( <link linkend="prod113">windowSpecification</link> )? ) | <link linkend="prod66">orderedAgg</link> ( <link linkend="prod113">windowSpecification</link> )? | ( <link linkend="prod70">aggregateSymbol</link> <link linkend="prod113">windowSpecification</link> ) | ( <link linkend="prod112">function</link> ) | ( &lt;ID&gt; ( &lt;LSBRACE&gt; <link linkend="prod84">intVal</link> &lt;RSBRACE&gt; )? ) | <link linkend="prod100">subquery</link> | ( &lt;LPAREN&gt; <link linkend="prod24">expression</link> &lt;RPAREN&gt; ( &lt;LSBRACE&gt; <link!
  linkend="prod84">intVal</link> &lt;RSBRACE&gt; )? ) | <link linkend="prod114">searchedCaseExpression</link> | <link linkend="prod115">caseExpression</link> )</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod113" xreflabel="caseExpression"/>caseExpression</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod113" xreflabel="windowSpecification"/>windowSpecification</para></entry>
 <entry align="left" valign="top"><para>::= 
+&lt;OVER&gt; &lt;LPAREN&gt; ( &lt;PARTITION&gt; &lt;BY&gt; <link linkend="prod48">expressionList</link> )? ( <link linkend="prod53">orderby</link> )? &lt;RPAREN&gt;</para></entry></row>
+<row>
+<entry align="right" valign="top"><para><anchor id="prod115" xreflabel="caseExpression"/>caseExpression</para></entry>
+<entry align="left" valign="top"><para>::= 
 &lt;CASE&gt; <link linkend="prod24">expression</link> ( &lt;WHEN&gt; <link linkend="prod24">expression</link> &lt;THEN&gt; <link linkend="prod24">expression</link> )+ ( &lt;ELSE&gt; <link linkend="prod24">expression</link> )? &lt;END&gt;</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod112" xreflabel="searchedCaseExpression"/>searchedCaseExpression</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod114" xreflabel="searchedCaseExpression"/>searchedCaseExpression</para></entry>
 <entry align="left" valign="top"><para>::= 
 &lt;CASE&gt; ( &lt;WHEN&gt; <link linkend="prod35">criteria</link> &lt;THEN&gt; <link linkend="prod24">expression</link> )+ ( &lt;ELSE&gt; <link linkend="prod24">expression</link> )? &lt;END&gt;</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod111" xreflabel="function"/>function</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod112" xreflabel="function"/>function</para></entry>
 <entry align="left" valign="top"><para>::= 
-( ( &lt;CONVERT&gt; &lt;LPAREN&gt; <link linkend="prod24">expression</link> &lt;COMMA&gt; <link linkend="prod38">dataType</link> &lt;RPAREN&gt; ) | ( &lt;CAST&gt; &lt;LPAREN&gt; <link linkend="prod24">expression</link> &lt;AS&gt; <link linkend="prod38">dataType</link> &lt;RPAREN&gt; ) | ( <link linkend="prod11">nonReserved</link> &lt;LPAREN&gt; <link linkend="prod24">expression</link> &lt;COMMA&gt; <link linkend="prod114">stringConstant</link> &lt;RPAREN&gt; ) | ( <link linkend="prod11">nonReserved</link> &lt;LPAREN&gt; <link linkend="prod115">intervalType</link> &lt;COMMA&gt; <link linkend="prod24">expression</link> &lt;COMMA&gt; <link linkend="prod24">expression</link> &lt;RPAREN&gt; ) | <link linkend="prod116">queryString</link> | ( ( &lt;LEFT&gt; | &lt;RIGHT&gt; | &lt;CHAR&gt; | &lt;USER&gt; | &lt;YEAR&gt; | &lt;MONTH&gt; | &lt;HOUR&gt; | &lt;MINUTE&gt; | &lt;SECOND&gt; | &lt;XMLCONCAT&gt; | &lt;XMLCOMMENT&gt; ) &lt;LPAREN&gt; ( <link linkend="prod24">expression</link> !
 ( &lt;COMMA&gt; <link linkend="prod24">expression</link> )* )? &lt;RPAREN&gt; ) | ( ( &lt;INSERT&gt; ) &lt;LPAREN&gt; ( <link linkend="prod24">expression</link> ( &lt;COMMA&gt; <link linkend="prod24">expression</link> )* )? &lt;RPAREN&gt; ) | ( ( &lt;TRANSLATE&gt; ) &lt;LPAREN&gt; ( <link linkend="prod24">expression</link> ( &lt;COMMA&gt; <link linkend="prod24">expression</link> )* )? &lt;RPAREN&gt; ) | <link linkend="prod117">xmlParse</link> | <link linkend="prod118">xmlElement</link> | ( &lt;XMLPI&gt; &lt;LPAREN&gt; ( &lt;ID&gt; <link linkend="prod119">idExpression</link> | <link linkend="prod119">idExpression</link> ) ( &lt;COMMA&gt; <link linkend="prod24">expression</link> )? &lt;RPAREN&gt; ) | <link linkend="prod120">xmlForest</link> | <link linkend="prod81">xmlSerialize</link> | <link linkend="prod84">xmlQuery</link> | ( <link linkend="prod2">id</link> &lt;LPAREN&gt; ( <link linkend="prod24">expression</link> ( &lt;COMMA&gt; <link linkend="prod24">expression</link> )*!
  )? &lt;RPAREN&gt; ) )</para></entry></row>
+( ( &lt;CONVERT&gt; &lt;LPAREN&gt; <link linkend="prod24">expression</link> &lt;COMMA&gt; <link linkend="prod38">dataType</link> &lt;RPAREN&gt; ) | ( &lt;CAST&gt; &lt;LPAREN&gt; <link linkend="prod24">expression</link> &lt;AS&gt; <link linkend="prod38">dataType</link> &lt;RPAREN&gt; ) | ( <link linkend="prod11">nonReserved</link> &lt;LPAREN&gt; <link linkend="prod24">expression</link> &lt;COMMA&gt; <link linkend="prod116">stringConstant</link> &lt;RPAREN&gt; ) | ( <link linkend="prod11">nonReserved</link> &lt;LPAREN&gt; <link linkend="prod117">intervalType</link> &lt;COMMA&gt; <link linkend="prod24">expression</link> &lt;COMMA&gt; <link linkend="prod24">expression</link> &lt;RPAREN&gt; ) | <link linkend="prod118">queryString</link> | ( ( &lt;LEFT&gt; | &lt;RIGHT&gt; | &lt;CHAR&gt; | &lt;USER&gt; | &lt;YEAR&gt; | &lt;MONTH&gt; | &lt;HOUR&gt; | &lt;MINUTE&gt; | &lt;SECOND&gt; | &lt;XMLCONCAT&gt; | &lt;XMLCOMMENT&gt; ) &lt;LPAREN&gt; ( <link linkend="prod48">expressionList</li!
 nk> )? &lt;RPAREN&gt; ) | ( ( &lt;TRANSLATE&gt; | &lt;INSERT&gt; ) &lt;LPAREN&gt; ( <link linkend="prod48">expressionList</link> )? &lt;RPAREN&gt; ) | <link linkend="prod119">xmlParse</link> | <link linkend="prod120">xmlElement</link> | ( &lt;XMLPI&gt; &lt;LPAREN&gt; ( &lt;ID&gt; <link linkend="prod121">idExpression</link> | <link linkend="prod121">idExpression</link> ) ( &lt;COMMA&gt; <link linkend="prod24">expression</link> )? &lt;RPAREN&gt; ) | <link linkend="prod122">xmlForest</link> | <link linkend="prod82">xmlSerialize</link> | <link linkend="prod85">xmlQuery</link> | ( <link linkend="prod2">id</link> &lt;LPAREN&gt; ( <link linkend="prod48">expressionList</link> )? &lt;RPAREN&gt; ) )</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod114" xreflabel="stringConstant"/>stringConstant</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod116" xreflabel="stringConstant"/>stringConstant</para></entry>
 <entry align="left" valign="top"><para>::= 
 <link linkend="prod1">stringVal</link></para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod117" xreflabel="xmlParse"/>xmlParse</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod119" xreflabel="xmlParse"/>xmlParse</para></entry>
 <entry align="left" valign="top"><para>::= 
 &lt;XMLPARSE&gt; &lt;LPAREN&gt; <link linkend="prod11">nonReserved</link> <link linkend="prod24">expression</link> ( <link linkend="prod11">nonReserved</link> )? &lt;RPAREN&gt;</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod116" xreflabel="queryString"/>queryString</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod118" xreflabel="queryString"/>queryString</para></entry>
 <entry align="left" valign="top"><para>::= 
 <link linkend="prod11">nonReserved</link> &lt;LPAREN&gt; <link linkend="prod24">expression</link> ( &lt;COMMA&gt; <link linkend="prod65">derivedColumn</link> )* &lt;RPAREN&gt;</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod118" xreflabel="xmlElement"/>xmlElement</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod120" xreflabel="xmlElement"/>xmlElement</para></entry>
 <entry align="left" valign="top"><para>::= 
-&lt;XMLELEMENT&gt; &lt;LPAREN&gt; ( &lt;ID&gt; <link linkend="prod2">id</link> | <link linkend="prod2">id</link> ) ( &lt;COMMA&gt; <link linkend="prod85">xmlNamespaces</link> )? ( &lt;COMMA&gt; <link linkend="prod121">xmlAttributes</link> )? ( &lt;COMMA&gt; <link linkend="prod24">expression</link> )* &lt;RPAREN&gt;</para></entry></row>
+&lt;XMLELEMENT&gt; &lt;LPAREN&gt; ( &lt;ID&gt; <link linkend="prod2">id</link> | <link linkend="prod2">id</link> ) ( &lt;COMMA&gt; <link linkend="prod86">xmlNamespaces</link> )? ( &lt;COMMA&gt; <link linkend="prod123">xmlAttributes</link> )? ( &lt;COMMA&gt; <link linkend="prod24">expression</link> )* &lt;RPAREN&gt;</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod121" xreflabel="xmlAttributes"/>xmlAttributes</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod123" xreflabel="xmlAttributes"/>xmlAttributes</para></entry>
 <entry align="left" valign="top"><para>::= 
 &lt;XMLATTRIBUTES&gt; &lt;LPAREN&gt; <link linkend="prod65">derivedColumn</link> ( &lt;COMMA&gt; <link linkend="prod65">derivedColumn</link> )* &lt;RPAREN&gt;</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod120" xreflabel="xmlForest"/>xmlForest</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod122" xreflabel="xmlForest"/>xmlForest</para></entry>
 <entry align="left" valign="top"><para>::= 
-&lt;XMLFOREST&gt; &lt;LPAREN&gt; ( <link linkend="prod85">xmlNamespaces</link> &lt;COMMA&gt; )? <link linkend="prod65">derivedColumn</link> ( &lt;COMMA&gt; <link linkend="prod65">derivedColumn</link> )* &lt;RPAREN&gt;</para></entry></row>
+&lt;XMLFOREST&gt; &lt;LPAREN&gt; ( <link linkend="prod86">xmlNamespaces</link> &lt;COMMA&gt; )? <link linkend="prod65">derivedColumn</link> ( &lt;COMMA&gt; <link linkend="prod65">derivedColumn</link> )* &lt;RPAREN&gt;</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod85" xreflabel="xmlNamespaces"/>xmlNamespaces</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod86" xreflabel="xmlNamespaces"/>xmlNamespaces</para></entry>
 <entry align="left" valign="top"><para>::= 
-&lt;XMLNAMESPACES&gt; &lt;LPAREN&gt; <link linkend="prod122">namespaceItem</link> ( &lt;COMMA&gt; <link linkend="prod122">namespaceItem</link> )* &lt;RPAREN&gt;</para></entry></row>
+&lt;XMLNAMESPACES&gt; &lt;LPAREN&gt; <link linkend="prod124">namespaceItem</link> ( &lt;COMMA&gt; <link linkend="prod124">namespaceItem</link> )* &lt;RPAREN&gt;</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod122" xreflabel="namespaceItem"/>namespaceItem</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod124" xreflabel="namespaceItem"/>namespaceItem</para></entry>
 <entry align="left" valign="top"><para>::= 
 ( <link linkend="prod1">stringVal</link> &lt;AS&gt; <link linkend="prod2">id</link> )</para></entry></row>
 <row>
@@ -873,7 +883,7 @@
 <entry align="left" valign="top"><para>::= 
 ( &lt;DEFAULT_KEYWORD&gt; <link linkend="prod1">stringVal</link> )</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod119" xreflabel="idExpression"/>idExpression</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod121" xreflabel="idExpression"/>idExpression</para></entry>
 <entry align="left" valign="top"><para>::= 
 <link linkend="prod2">id</link></para></entry></row>
 <row>
@@ -885,15 +895,15 @@
 <entry align="left" valign="top"><para>::= 
 <link linkend="prod22">dataTypeString</link></para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod115" xreflabel="intervalType"/>intervalType</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod117" xreflabel="intervalType"/>intervalType</para></entry>
 <entry align="left" valign="top"><para>::= 
 ( <link linkend="prod11">nonReserved</link> )</para></entry></row>
 <row>
-<entry align="right" valign="top"><para><anchor id="prod110" xreflabel="literal"/>literal</para></entry>
+<entry align="right" valign="top"><para><anchor id="prod111" xreflabel="literal"/>literal</para></entry>
 <entry align="left" valign="top"><para>::= 
 ( <link linkend="prod1">stringVal</link> | &lt;INTEGERVAL&gt; | &lt;FLOATVAL&gt; | &lt;FALSE&gt; | &lt;TRUE&gt; | &lt;UNKNOWN&gt; | &lt;NULL&gt; | ( ( &lt;BOOLEANTYPE&gt; | &lt;TIMESTAMPTYPE&gt; | &lt;DATETYPE&gt; | &lt;TIMETYPE&gt; ) <link linkend="prod1">stringVal</link> &lt;RBRACE&gt; ) )</para></entry></row>
 </tbody>
 </tgroup>
 </informaltable>
 </section>
-</appendix>
+</appendix>
\ No newline at end of file

Added: trunk/documentation/reference/src/main/docbook/en-US/content/sql_clauses.xml
===================================================================
--- trunk/documentation/reference/src/main/docbook/en-US/content/sql_clauses.xml	                        (rev 0)
+++ trunk/documentation/reference/src/main/docbook/en-US/content/sql_clauses.xml	2011-07-28 19:58:08 UTC (rev 3347)
@@ -0,0 +1,502 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter id="sql_clauses">
+    <title>SQL Clauses</title>
+    <para>This section describes the clauses that are used in the various <link linkend="sql_commands">SQL commands</link> described in the previous section. Nearly all these features follow standard SQL syntax and functionality, so any SQL reference can be used for more information.</para>
+    <section id="with_clause">
+      <title>WITH Clause</title>
+      <para>
+      Teiid supports non-recursive common table expressions via the WITH clause.  With clause items may be referenced as tables in subsequent with clause items and in the main query.  The WITH clause can be thought of as providing query scoped temporary tables.
+      </para>
+      <para>
+        Usage:
+        <synopsis label="Usage">WITH name [(column, ...)] AS (query expression) ... </synopsis>
+      </para>
+      <itemizedlist>
+        <para>Syntax Rules:</para>
+        <listitem><para>All of the projected column names must be unique.  If they are not unique, then the column name list must be provided.</para></listitem>
+        <listitem><para>If the columns of the WITH clause item are declared, then they must match the number of columns projected by the query expression.</para></listitem>
+        <listitem><para>Each with clause item must have a unique name.</para></listitem>
+      </itemizedlist> 
+    </section>
+    <section id="select_clause">
+      <title>SELECT Clause</title>
+      <para>
+      SQL queries that start with the SELECT keyword and are often referred to as "SELECT statements". Teiid supports most of the standard SQL query constructs.
+      </para>
+      <para>
+        Usage:
+        <synopsis label="Usage">SELECT [DISTINCT|ALL] ((expression [[AS] name])|(group identifier.STAR))*|STAR ...</synopsis>
+      </para>
+      <itemizedlist>
+        <para>Syntax Rules:</para>
+        <listitem><para>Aliased expressions are only used as the output column names and in the ORDER BY clause. They cannot be used in other clauses of the query.</para></listitem>
+        <listitem><para>DISTINCT may only be specified if the SELECT symbols are comparable.</para></listitem>
+      </itemizedlist> 
+    </section>
+    <section id="from_clause">
+      <title>FROM Clause</title>
+      <para>
+      The FROM clause specifies the target table(s) for SELECT, UPDATE, and DELETE statements. 
+      </para>
+      <itemizedlist>
+        <para>Example Syntax:</para>
+        <listitem><para>FROM table [[AS] alias]</para></listitem>
+        <listitem><para>FROM table1 [INNER|LEFT OUTER|RIGHT OUTER|FULL OUTER] JOIN table2 ON join-criteria</para></listitem>
+        <listitem><para>FROM table1 CROSS JOIN table2</para></listitem>
+        <listitem><para>FROM (subquery) [AS] alias</para></listitem>
+        <listitem><para>FROM <link linkend="nested_table">TABLE(subquery)</link> [AS] alias</para></listitem>
+        <listitem><para>FROM table1 JOIN /*+ MAKEDEP */ table2 ON join-criteria</para></listitem>
+        <listitem><para>FROM table1 JOIN /*+ MAKENOTDEP */ table2 ON join-criteria</para></listitem>
+        <listitem><para>FROM /*+ MAKEIND */ table1 JOIN table2 ON join-criteria</para></listitem>
+        <listitem><para>FROM table1 left outer join <link linkend="optional_join">/*+ optional */</link> table2 ON join-criteria</para></listitem>
+        <listitem><para>FROM <link linkend="texttable">TEXTTABLE...</link></para></listitem>
+        <listitem><para>FROM <link linkend="xmltable">XMLTABLE...</link></para></listitem>
+        <listitem><para>FROM <link linkend="arraytable">ARRAYTABLE...</link></para></listitem>
+        <listitem><para>FROM <link linkend="from_subquery">(SELECT ...</link></para></listitem>
+      </itemizedlist> 
+      <note>
+        <title>DEP Hints</title>
+        <para>
+          MAKEIND, MAKEDEP, and MAKENOTDEP are hints used to control
+          <link linkend="dependent_joins">dependent join</link>
+          behavior. They should only be used in situations where the optimizer
+          does not choose the most optimal plan based upon query structure,
+          metadata, and costing information.  The hints may appear in a comment that proceeds the from clause.  
+          The hints can be specified against any from clause, not just a named table.
+        </para>
+      </note>
+      <section id="nested_table">
+		<title>Nested Table Reference</title>
+		<para>Nested tables may appear in the FROM clause with the TABLE
+			keyword. They are an alternative to using a view with normal join
+			semantics.  The columns projected from the command contained in the nested table
+			 may be used just as any of the other FROM clause projected columns in join criteria, the where clause, etc.
+      	</para>
+		<para>A nested table may have correlated references to preceeding FROM
+			clause column references as long as INNER and LEFT OUTER joins are used. This is
+			especially useful in cases where then nested expression is a
+			procedure or function call.</para>
+		<para>Valid example: 
+		<programlisting>select * from t1, TABLE(call proc(t1.x)) t2</programlisting>
+		</para>
+		<para>Invalid example, since t1 appears after the nested table in the from clause: 
+		<programlisting>select * from TABLE(call proc(t1.x)) t2, t1</programlisting>
+		</para>
+		<note>
+			<title>Multiple Execution</title>
+			<para>The usage of a correlated nested table may result in multiple
+				executions of the table expression - once for each correlated row.
+			</para>
+		</note>
+	  </section>
+	  <section id="texttable">
+		<title>TEXTTABLE</title>
+		<para>The TEXTTABLE funciton processes character input to produce tabular ouptut.  It supports both fixed and delimited file format parsing.  
+			The function itself defines what columns it projects.  
+		    The TEXTTABLE function is implicitly a nested table and may be correlated to preceeding FROM clause entries.
+      	</para>
+      	<para>
+        Usage:
+        	<synopsis label="Usage">TEXTTABLE(expression COLUMNS &lt;COLUMN&gt;, ... [DELIMITER char] [(QUOTE|ESCAPE) char] [HEADER [integer]] [SKIP integer]) AS name</synopsis>
+        	<synopsis label="Usage">COLUMN := name datatype [WIDTH integer]</synopsis> 
+      	</para>
+      	<itemizedlist>
+        	<para>Parameters</para>
+        <listitem>
+          <para>expression - the text content to process, which should be convertable to CLOB.
+          </para>
+        </listitem>
+        <listitem>
+        	<para>DELIMITER sets the field delimiter character to use.  Defaults to ','.
+        	</para>
+        </listitem>
+        <listitem>
+        	<para>QUOTE sets the quote, or qualifier, character used to wrap field values.  Defaults to '"'.  
+        	</para>
+        </listitem>
+        <listitem>
+        	<para>ESCAPE sets the escape character to use if no quoting character is in use.  
+        	This is used in situations where the delimiter or new line characters are escaped with a preceding character, e.g. \,  
+        	</para>
+        </listitem>
+        <listitem>
+        	<para>HEADER specifies the text line number (counting every new line) on which the column names occur.  All lines prior to the header will be skipped.
+        	If HEADER is specified, then the header line will be used to determine the TEXTTABLE column position by case-insensitive name matching.  This is especially useful in situations where only a subset of the columns are needed.
+        	If the HEADER value is not specified, it defaults to 1.  
+        	If HEADER is not specified, then columns are expected to match positionally with the text contents. 
+        	</para>
+        </listitem>
+        <listitem>
+        	<para>SKIP specifies the number of text lines (counting every new line) to skip before parsing the contents.  HEADER may still be specified with SKP.
+        	</para>
+        </listitem>
+      	</itemizedlist>
+      	<itemizedlist>
+        <para>Syntax Rules:
+        </para>
+        <listitem>
+          <para>If width is specified for one column it must be specified for all columns.
+          </para>
+        </listitem>
+        <listitem>
+          <para>If width is specified, then fixed width parsing is used and ESCAPE, QUOTE, and HEADER should not be specified.
+          </para>
+        </listitem>
+        <listitem>
+          <para>The columns names must be not contain duplicates.
+          </para>
+        </listitem>
+        </itemizedlist>
+      	<itemizedlist>
+        	<para>Examples</para>
+        	<listitem>
+		        <para>Use of the HEADER parameter, returns 1 row ['b']: <programlisting>select * from texttable('col1,col2,col3\na,b,c' COLUMNS col2 string HEADER) x</programlisting>
+				</para>		
+        	</listitem>
+        	<listitem>
+		        <para>Use of fixed width, returns 1 row ['a', 'b', 'c']: <programlisting>select * from texttable('abc' COLUMNS col1 string width 1, col2 string width 1, col3 string width 1) x</programlisting>
+				</para>		
+        	</listitem>
+        	<listitem>
+		        <para>Use of ESCAPE parameter, returns 1 row ['a,', 'b']: <programlisting>select * from texttable('a:,,b' COLUMNS col1 string, col2 string ESCAPE ':') x</programlisting>
+				</para>		
+        	</listitem>
+        	<listitem>
+		        <para>As a nested table: <programlisting>select x.* from t, texttable(t.clobcolumn COLUMNS first string, second date SKIP 1) x</programlisting>
+				</para>		
+        	</listitem>
+		</itemizedlist>		
+	  </section>
+	  <section id="xmltable">
+		<title>XMLTABLE</title>
+		<para>The XMLTABLE funciton uses XQuery to produce tabular ouptut.  
+		    The XMLTABLE function is implicitly a nested table and may be correlated to preceeding FROM clause entries.  XMLTABLE is part of the SQL/XML 2006 specification. 
+      	</para>
+      	<para>
+        Usage:
+        	<synopsis label="Usage">XMLTABLE([&lt;NSP&gt;,] xquery-expression [&lt;PASSING&gt;] [COLUMNS &lt;COLUMN&gt;, ... )] AS name</synopsis>
+        	<synopsis label="Usage">COLUMN := name (FOR ORDINALITY | (datatype [DEFAULT expression] [PATH string]))</synopsis> 
+      	</para>
+      	<para>See XMLELEMENT for the definition of NSP - <link linkend="xmlnamespaces">XMLNAMESPACES</link>.</para>
+      	<para>See XMLQUERY for the definition of <link linkend="passing">PASSING</link>.</para>
+      	<para>See also <link linkend="xmlquery">XMLQUERY</link></para>
+      	<note><para>See also <xref linkend="xquery_optimization"/></para></note>
+      	<itemizedlist>
+        	<para>Parameters</para>
+        <listitem>
+        	<para>The optional XMLNAMESPACES clause specifies the namepaces for use in the XQuery and COLUMN path expressions.
+        	</para>
+        </listitem>
+        <listitem>
+        	<para>The xquery-expression should be a valid XQuery.  Each sequence item returned by the xquery will be used to create a row of values as defined by the COLUMNS clause.
+        	</para>
+        </listitem>
+        <listitem>
+        	<para>If COLUMNS is not specified, then that is the same as having the COLUMNS clause: "COLUMNS OBJECT_VALUE XML PATH '.'", which returns the entire item as an XML value.   
+        	</para>
+        </listitem>
+        <listitem>
+        	<para>A FOR ORDINALITY column is typed as integer and will return the 1-based item number as its value.
+        	</para>
+        </listitem>
+        <listitem>
+        	<para>Each non-ordinality column specifies a type and optionally a PATH and a DEFAULT expression.
+        	</para>
+        </listitem>
+        <listitem>
+        	<para>If PATH is not specified, then the path will be the same as the column name.
+        	</para>
+        </listitem>
+      	</itemizedlist>
+      	<itemizedlist>
+        <para>Syntax Rules:
+        </para>
+        <listitem>
+          <para>Only 1 FOR ORDINALITY column may be specified.
+          </para>
+        </listitem>
+        <listitem>
+          <para>The columns names must be not contain duplicates.
+          </para>
+        </listitem>
+        </itemizedlist>
+      	<itemizedlist>
+        	<para>Examples</para>
+        	<listitem>
+		        <para>Use of passing, returns 1 row [1]: <programlisting>select * from xmltable('/a' PASSING xmlparse(document '&lt;a id="1"/&gt;') COLUMNS id integer PATH '@id') x</programlisting>
+				</para>		
+        	</listitem>
+        	<listitem>
+		        <para>As a nested table: <programlisting>select x.* from t, xmltable('/x/y' PASSING t.doc COLUMNS first string, second FOR ORDINALITY) x</programlisting>
+				</para>		
+        	</listitem>
+		</itemizedlist>		
+	  </section>
+    </section>
+    	  <section id="arraytable">
+		<title>ARRAYTABLE</title>
+		<para>The ARRAYTABLE funciton processes an array input to produce tabular ouptut.  
+			The function itself defines what columns it projects.  
+		    The ARRAYTABLE function is implicitly a nested table and may be correlated to preceeding FROM clause entries.
+      	</para>
+      	<para>
+        Usage:
+        	<synopsis label="Usage">ARRAYTABLE(expression COLUMNS &lt;COLUMN&gt;, ...) AS name</synopsis>
+        	<synopsis label="Usage">COLUMN := name datatype</synopsis> 
+      	</para>
+      	<itemizedlist>
+        	<para>Parameters</para>
+        <listitem>
+          <para>expression - the array to process, which should be a java.sql.Array or java array value.
+          </para>
+        </listitem>
+      	</itemizedlist>
+      	<itemizedlist>
+        <para>Syntax Rules:
+        </para>
+        <listitem>
+          <para>The columns names must be not contain duplicates.
+          </para>
+        </listitem>
+        </itemizedlist>
+      	<itemizedlist>
+        	<para>Examples</para>
+        	<listitem>
+		        <para>As a nested table: <programlisting>select x.* from (call source.invokeMDX('some query')) r, arraytable(r.tuple COLUMNS first string, second bigdecimal) x</programlisting>
+				</para>		
+        	</listitem>
+		</itemizedlist>
+		<para>ARRAYTABLE is effectively a shortcut for using the <xref linkend="array_get"/> function in a nested table.  For example "ARRAYGET(val COLUMNS col1 string, col2 integer) AS X" is the same as "TABLE(SELECT cast(array_get(val, 1) AS string) AS col1, cast(array_get(val, 2) AS integer) AS col2) AS X".</para>		
+	  </section>
+    <section id="where_clause">
+      <title>WHERE Clause</title>
+      <para>
+      The WHERE clause defines the criteria to limit the records affected by SELECT, UPDATE, and DELETE statements.  
+      </para>
+      <itemizedlist>
+        <para>The general form of the WHERE is:
+        </para>
+        <listitem>
+          <para>WHERE <link linkend="criteria">criteria</link>
+          </para>
+        </listitem>
+      </itemizedlist>
+    </section>
+    <section id="groupby_clause">
+      <title>GROUP BY Clause</title>
+      <para>
+      The GROUP BY clause denotes that rows should be grouped according to the specified expression values. One row will be returned for each group, after optionally filtering those aggregate rows based on a HAVING clause.   
+      </para>
+      <itemizedlist>
+        <para>The general form of the GROUP BY is:
+        </para>
+        <listitem>
+          <para>GROUP BY expression (,expression)*
+          </para>
+        </listitem>
+      </itemizedlist>
+      <itemizedlist>
+        <para>Syntax Rules:
+        </para>
+        <listitem>
+          <para>Column references in the group by clause must by to unaliased output columns.
+          </para>
+        </listitem>
+        <listitem>
+          <para>Expressions used in the group by must appear in the select clause.
+          </para>
+        </listitem>
+        <listitem>
+          <para>Column references and expessions in the select clause that are not used in the group by clause must appear in aggregate functions. 
+          </para>
+        </listitem>
+        <listitem>
+          <para>If an aggregate function is used in the SELECT clause and no
+            GROUP BY is specified, an implicit GROUP BY will be performed with
+            the entire result set as a single group. In this case, every column
+            in the SELECT must be an aggregate function as no other column value
+            will be fixed across the entire group. 
+          </para>
+        </listitem>
+        <listitem>
+          <para>The group by columns must be of a comparable type.</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+    <section id="having_clause">
+      <title>HAVING Clause</title>
+      <para>
+      The HAVING clause operates exactly as a WHERE clause although it operates on the output of a GROUP BY. It supports the same syntax as the WHERE clause.
+      </para>
+      <itemizedlist>
+        <para>Syntax Rules:
+        </para>
+        <listitem>
+          <para>Expressions used in the group by clause must either
+            contain an aggregate function: COUNT, AVG, SUM, MIN, MAX. or be one
+            of the grouping expressions.</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+    <section id="orderby_clause">
+      <title>ORDER BY Clause</title>
+      <para>
+      The ORDER BY clause specifies how records should be sorted. The options are ASC (ascending) and DESC (descending).
+      </para>
+      <para>
+        Usage:
+        <synopsis label="Usage">ORDER BY expression [ASC|DESC] [NULLS (FIRST|LAST)], ...</synopsis>
+      </para>
+      <itemizedlist>
+        <para>Syntax Rules:
+        </para>
+        <listitem>
+          <para>Sort columns may be specified positionally by a 1-based positional
+	        integer, by SELECT clause alias name, by SELECT clause expression, or by an unrelated expression.</para>
+        </listitem>
+        <listitem>
+          <para>Column references may appear in the SELECT clause as the
+			expression for an aliased column or may reference columns from tables
+			in the FROM clause.
+			If the column reference is not in the SELECT clause the query must not
+			be a set operation, specify SELECT DISTINCT, or contain a GROUP BY
+			clause.</para>
+        </listitem>
+        <listitem>
+          <para>Unrelated expressions, expressions not appearing as an aliased expression in the select clause, 
+          are allowed in the order by clause of a non-set QUERY.  The columns referenced in the expression must come from the
+          from clause table references.  The column references cannot be to alias names or positional.
+          </para>
+        </listitem>
+        <listitem>
+          <para>The ORDER BY columns must be of a comparable type.</para>
+        </listitem>
+        <listitem>
+          <para>If an ORDER BY is used in an inline view or view
+	         definition without a limit clause, it will be removed by the Teiid
+	         optimizer.</para>
+        </listitem>
+        <listitem>
+        	<para>If NULLS FIRST/LAST is specified, then nulls are guaranteed to be sorted either first or last.  If the null ordering is not specified, then results will 
+        	typically be sorted with nulls as low values, which is Teiid's internal default sorting behavior.   
+        	However not all sources return results with nulss sorted as low values by default, and Teiid may return results with different null orderings. 
+        	</para>
+        </listitem>
+      </itemizedlist>
+      <warning>
+		<para>The use of positional ordering is no longer supported by the
+				ANSI SQL standard and is a deprecated feature in Teiid. It is
+				preferable to use alias names in the order by clause.</para>
+	  </warning>
+    </section>
+    <section id="limit_clause">
+      <title>LIMIT Clause</title>
+      <para>
+      The LIMIT clause specifies a limit on the number of records returned from the SELECT command. An optional offset (the number of rows to skip) can be specified.  The LIMIT clause can also be specfied using the SQL 2008 OFFSET/FETCH FIRST clauses.  
+      If an ORDER BY is also specified, it will be applied before the OFFSET/LIMIT are applied.  If an ORDER BY is not specified there is generally no guarantee what subset of rows will be returned.
+      </para>
+      <para>
+        Usage:
+        <synopsis label="Usage">LIMIT [offset,] limit</synopsis>
+        <synopsis label="Usage">[OFFSET offset ROW|ROWS] [FETCH FIRST|NEXT [limit] ROW|ROWS ONLY</synopsis>
+      </para>
+      <itemizedlist>
+        <para>Syntax Rules:
+        </para>
+        <listitem>
+          <para>The limit/offset expressions must be a non-negative integer or a parameter reference (?).  An offset of 0 is ignored.  A limit of 0 will return no rows.
+          </para>
+        </listitem>
+        <listitem>
+          <para>The terms FIRST/NEXT are interchangable as well as ROW/ROWS.
+          </para>
+        </listitem>
+      </itemizedlist>
+      <itemizedlist>
+        <para>Examples:
+        </para>
+        <listitem>
+          <para>LIMIT 100 - returns the first 100 records (rows 1-100)</para>
+        </listitem>
+        <listitem>
+          <para>LIMIT 500, 100 - skips 500 records and returns the next 100 records (rows 501-600)</para>
+        </listitem>
+        <listitem>
+          <para>OFFSET 500 ROWS - skips 500 records</para>
+        </listitem>
+        <listitem>
+          <para>OFFSET 500 ROWS FETCH NEXT 100 ROWS ONLY - skips 500 records and returns the next 100 records (rows 501-600)</para>
+        </listitem>
+        <listitem>
+          <para>FETCH FIRST ROW ONLY - returns only the first record</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+    <section id="into_clause">
+      <title>INTO Clause</title>
+      <warning>
+      	<para>Usage of the INTO Clause for inserting into a table has been been deprecated.  An <link linkend="insert_command">INSERT</link> with a query command should be used instead.</para>
+      </warning>
+      <para>
+      When the into clause is specified with a SELECT, the results of the query are inserted into the specified table. This is often used to insert records into a temporary table. The INTO clause immediately precedes the FROM clause.   
+      </para>
+      <para>
+        Usage:
+        <synopsis label="Usage">INTO table FROM ...</synopsis>
+      </para>
+      <itemizedlist>
+        <para>Syntax Rules:
+        </para>
+        <listitem>
+          <para>The INTO clause is logically applied last in processing, after the ORDER BY and LIMIT clauses.</para>
+        </listitem>
+        <listitem>
+          <para>Teiid's support for SELECT INTO is similar to
+            MS SQL Server. The target of the INTO clause is a table where
+            the result of the rest select command will be inserted. SELECT
+            INTO should not be used UNION query.</para>
+        </listitem>
+      </itemizedlist>
+    </section>    
+    <section id="option_clause">
+      <title>OPTION Clause</title>
+      <para>
+      The OPTION keyword denotes options the user can pass in with the command. These options are Teiid-specific and not covered by any SQL specification.  
+      </para>
+      <para>
+        Usage:
+        <synopsis label="Usage">OPTION option, (option)*</synopsis>
+      </para>
+      <itemizedlist>
+        <para>Supported options:
+        </para>
+        <listitem>
+          <para>MAKEDEP table [(,table)*] - specifies source tables that should be made dependent in the join
+          </para>
+        </listitem>
+        <listitem>
+          <para>MAKENOTDEP table [(,table)*] - prevents a dependent join from being used
+          </para>
+        </listitem>
+        <listitem>
+          <para>NOCACHE [table (,table)*] - prevents cache from being used for all tables or for the given tables
+          </para>
+        </listitem>
+      </itemizedlist>
+      <itemizedlist>
+        <para>Examples:
+        </para>
+        <listitem>
+          <para>OPTION MAKEDEP table1</para>
+        </listitem>
+        <listitem>
+          <para>OPTION NOCACHE</para>
+        </listitem>
+      </itemizedlist>
+      <para>All tables specified in the OPTION clause should be fully qualified.</para>
+      <note><para>Previous versions of Teiid accepted the PLANONLY, DEBUG, and SHOWPLAN option arguments.  These are no longer accepted in the OPTION clause.
+      Please see the Client Developers Guide for replacements to those options.
+      </para></note>
+    </section>
+</chapter>
\ No newline at end of file


Property changes on: trunk/documentation/reference/src/main/docbook/en-US/content/sql_clauses.xml
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Modified: trunk/documentation/reference/src/main/docbook/en-US/content/sql_support.xml
===================================================================
--- trunk/documentation/reference/src/main/docbook/en-US/content/sql_support.xml	2011-07-28 11:43:06 UTC (rev 3346)
+++ trunk/documentation/reference/src/main/docbook/en-US/content/sql_support.xml	2011-07-28 19:58:08 UTC (rev 3347)
@@ -115,7 +115,7 @@
     	 </para>
     </section>
   </section>
-  <section>
+  <section id="expressions">
     <title>Expressions</title>
     <para> Identifiers, literals, and functions can be combined into
       expressions. Expressions can be used almost anywhere in a query --
@@ -136,6 +136,9 @@
         <para><link linkend="aggregate_functions">Aggregate functions</link></para>
       </listitem>
       <listitem>
+        <para><link linkend="window_functions">Window functions</link></para>
+      </listitem>
+      <listitem>
         <para><link linkend="case">Case and searched case</link></para>
       </listitem>
       <listitem>
@@ -253,7 +256,7 @@
           </para>
         </listitem>                
         <listitem>
-          <para>XMLAGG(xml_expr <link linkend="orderby_clause">[ORDER BY ...]</link>) – xml concatination of all xml expressions in a group (excluding null)</para>
+          <para>XMLAGG(xml_expr <link linkend="orderby_clause">[ORDER BY ...]</link>) – xml concatination of all xml expressions in a group (excluding null).  The ORDER BY clause cannot reference alias names or use positional ordering.</para>
         </listitem>                
       </itemizedlist>
       <itemizedlist>
@@ -285,6 +288,123 @@
       For more information on aggregates, see the sections on GROUP BY or HAVING.
       </para>
     </section>
+    <section id="window_functions">
+      <title>Window functions</title>
+      <para>Teiid supports ANSI SQL 2003 window functions.  A window function allows an aggregrate function to be applied to a subset of the result set, without the need for a GROUP BY clause.  
+      A window function is similar to an aggregate function, but requires the use of an OVER clause or window specification.
+      </para>
+      <para>
+        Usage:
+        <synopsis label="Usage">aggregate|ranking OVER ([PARTION BY expression [, expression]*] <link linkend="orderby_clause">[ORDER BY ...]</link>)</synopsis>
+        aggregate can be any <xref linkend="aggregate_functions"/>.  Ranking can be one of ROW_NUMBER(), RANK(), DENSE_RANK().   
+      </para>
+      <itemizedlist>
+        <para>Syntax Rules:
+        </para>
+        <listitem>
+	      <para>Window functions can only appear in the SELECT and ORDER BY clauses of a query expression.
+	      </para>
+        </listitem>
+        <listitem>
+	      <para>Window functions cannot be nested in one another.
+	      </para>
+        </listitem>
+        <listitem>
+	      <para>Partitioning and order by expressions cannot contain subqueries or outer references.
+	      </para>
+        </listitem>
+        <listitem>
+	      <para>The ranking (ROW_NUMBER, RANK, DENSE_RANK) functions require the use of the window specification ORDER BY clause.
+	      </para>
+        </listitem>
+        <listitem>
+	      <para>An XMLAGG ORDER BY clause cannot be used when windowed.
+	      </para>
+        </listitem>        
+        <listitem>
+	      <para>The window specification ORDER BY clause cannot reference alias names or use positional ordering.
+	      </para>
+        </listitem>
+        <listitem>
+	      <para>Windowed aggregates may not use DISTINCT.
+	      </para>
+        </listitem>
+	  </itemizedlist>
+	  <section>
+	  	<title>Function Definitions</title>
+	  	<itemizedlist>
+	        <listitem>
+	          <para>ROW_NUMBER() – functional the same as COUNT(*) with the same window specification.  Assigns a number to each row in a partition starting at 1.</para>
+	        </listitem>
+	        <listitem>
+	          <para>RANK() – Assigns a number to each unique ordering value within each partition starting at 1, such that the next rank is equal to the count of prior rows.</para>
+	        </listitem>
+	        <listitem>
+	          <para>DENSE_RANK() – Assigns a number to each unique ordering value within each partition starting at 1, such that the next rank is sequential.</para>
+	        </listitem>
+		</itemizedlist>	  	
+	  </section>
+	  <section>
+	  	<title>Processing</title>
+	  	<para>Window functions are logically processed just before creating the output from the SELECT clause. 	Window functions can use nested aggregates if a GROUP BY clause is present.
+	  	The is no guarenteed affect on the output ordering from the presense of window functions.  The SELECT statement must have an ORDER BY clause to have a predictable ordering.
+	  	</para><para>
+	  	Teiid will process all window functions with the same window specification together.  In general a full pass over the row values coming into the SELECT clause will be required for each unique window specification.
+	  	For each window specification the values will be grouped according to the PARTITION BY clause.  If no PARTITION BY clause is specified, then the entire input is treated as a single partition.
+	  	The output value is determined based upon the current row value, it's peers (that is rows that are the same with respect to their ordering), and all prior row values based upon ordering in the partition.
+	  	The ROW_NUMBER function will assign a unique value to every row regardless of the number of peers.
+	  	</para>
+	  	<example>
+          <title>Example Windowed Results</title>
+          <programlisting language="SQL">SELECT name, salary, max(salary) over (partition by name) as max_sal, 
+          rank() over (order by salary) as rank, dense_rank() over (order by salary) as dense_rank, 
+          row_number() over (order by salary) as row_num FROM employees</programlisting>
+          <informaltable frame="all">
+			<tgroup cols="6">
+				<thead>
+					<row>
+						<entry>
+							<para>name</para>
+						</entry>
+						<entry>
+							<para>salary</para>
+						</entry>
+						<entry>
+							<para>max_sal</para>
+						</entry>
+						<entry>
+							<para>rank</para>
+						</entry>
+						<entry>
+							<para>dense_rank</para>
+						</entry>
+						<entry>
+							<para>row_num</para>
+						</entry>
+					</row>
+				</thead>
+				<tbody>
+					<row>
+					<entry><para>John</para></entry><entry><para>100000</para></entry><entry><para>100000</para></entry><entry><para>2</para></entry><entry><para>2</para></entry><entry><para>2</para></entry>
+					</row>
+					<row>
+					<entry><para>Henry</para></entry><entry><para>50000</para></entry><entry><para>100000</para></entry><entry><para>5</para></entry><entry><para>4</para></entry><entry><para>5</para></entry>
+					</row>
+					<row>
+					<entry><para>John</para></entry><entry><para>60000</para></entry><entry><para>60000</para></entry><entry><para>3</para></entry><entry><para>3</para></entry><entry><para>3</para></entry>
+					</row>
+					<row>
+					<entry><para>Suzie</para></entry><entry><para>60000</para></entry><entry><para>150000</para></entry><entry><para>3</para></entry><entry><para>3</para></entry><entry><para>4</para></entry>
+					</row>
+					<row>
+					<entry><para>Suzie</para></entry><entry><para>150000</para></entry><entry><para>150000</para></entry><entry><para>1</para></entry><entry><para>1</para></entry><entry><para>1</para></entry>
+					</row>
+				</tbody>
+				</tgroup>
+			</informaltable>						
+        </example>
+	  </section>
+    </section>
     <section id="case">
       <title>Case and searched case</title>
       <para>
@@ -666,506 +786,6 @@
 	  </note>
     </section>
   </section>
-  <section>
-    <title>SQL Clauses</title>
-    <para>This section describes the clauses that are used in the various <link linkend="sql_commands">SQL commands</link> described in the previous section. Nearly all these features follow standard SQL syntax and functionality, so any SQL reference can be used for more information.</para>
-    <section id="with_clause">
-      <title>WITH Clause</title>
-      <para>
-      Teiid supports non-recursive common table expressions via the WITH clause.  With clause items may be referenced as tables in subsequent with clause items and in the main query.  The WITH clause can be thought of as providing query scoped temporary tables.
-      </para>
-      <para>
-        Usage:
-        <synopsis label="Usage">WITH name [(column, ...)] AS (query expression) ... </synopsis>
-      </para>
-      <itemizedlist>
-        <para>Syntax Rules:</para>
-        <listitem><para>All of the projected column names must be unique.  If they are not unique, then the column name list must be provided.</para></listitem>
-        <listitem><para>If the columns of the WITH clause item are declared, then they must match the number of columns projected by the query expression.</para></listitem>
-        <listitem><para>Each with clause item must have a unique name.</para></listitem>
-      </itemizedlist> 
-    </section>
-    <section id="select_clause">
-      <title>SELECT Clause</title>
-      <para>
-      SQL queries that start with the SELECT keyword and are often referred to as "SELECT statements". Teiid supports most of the standard SQL query constructs.
-      </para>
-      <para>
-        Usage:
-        <synopsis label="Usage">SELECT [DISTINCT|ALL] ((expression [[AS] name])|(group identifier.STAR))*|STAR ...</synopsis>
-      </para>
-      <itemizedlist>
-        <para>Syntax Rules:</para>
-        <listitem><para>Aliased expressions are only used as the output column names and in the ORDER BY clause. They cannot be used in other clauses of the query.</para></listitem>
-        <listitem><para>DISTINCT may only be specified if the SELECT symbols are comparable.</para></listitem>
-      </itemizedlist> 
-    </section>
-    <section id="from_clause">
-      <title>FROM Clause</title>
-      <para>
-      The FROM clause specifies the target table(s) for SELECT, UPDATE, and DELETE statements. 
-      </para>
-      <itemizedlist>
-        <para>Example Syntax:</para>
-        <listitem><para>FROM table [[AS] alias]</para></listitem>
-        <listitem><para>FROM table1 [INNER|LEFT OUTER|RIGHT OUTER|FULL OUTER] JOIN table2 ON join-criteria</para></listitem>
-        <listitem><para>FROM table1 CROSS JOIN table2</para></listitem>
-        <listitem><para>FROM (subquery) [AS] alias</para></listitem>
-        <listitem><para>FROM <link linkend="nested_table">TABLE(subquery)</link> [AS] alias</para></listitem>
-        <listitem><para>FROM table1 JOIN /*+ MAKEDEP */ table2 ON join-criteria</para></listitem>
-        <listitem><para>FROM table1 JOIN /*+ MAKENOTDEP */ table2 ON join-criteria</para></listitem>
-        <listitem><para>FROM /*+ MAKEIND */ table1 JOIN table2 ON join-criteria</para></listitem>
-        <listitem><para>FROM table1 left outer join <link linkend="optional_join">/*+ optional */</link> table2 ON join-criteria</para></listitem>
-        <listitem><para>FROM <link linkend="texttable">TEXTTABLE...</link></para></listitem>
-        <listitem><para>FROM <link linkend="xmltable">XMLTABLE...</link></para></listitem>
-        <listitem><para>FROM <link linkend="arraytable">ARRAYTABLE...</link></para></listitem>
-        <listitem><para>FROM <link linkend="from_subquery">(SELECT ...</link></para></listitem>
-      </itemizedlist> 
-      <note>
-        <title>DEP Hints</title>
-        <para>
-          MAKEIND, MAKEDEP, and MAKENOTDEP are hints used to control
-          <link linkend="dependent_joins">dependent join</link>
-          behavior. They should only be used in situations where the optimizer
-          does not choose the most optimal plan based upon query structure,
-          metadata, and costing information.  The hints may appear in a comment that proceeds the from clause.  
-          The hints can be specified against any from clause, not just a named table.
-        </para>
-      </note>
-      <section id="nested_table">
-		<title>Nested Table Reference</title>
-		<para>Nested tables may appear in the FROM clause with the TABLE
-			keyword. They are an alternative to using a view with normal join
-			semantics.  The columns projected from the command contained in the nested table
-			 may be used just as any of the other FROM clause projected columns in join criteria, the where clause, etc.
-      	</para>
-		<para>A nested table may have correlated references to preceeding FROM
-			clause column references as long as INNER and LEFT OUTER joins are used. This is
-			especially useful in cases where then nested expression is a
-			procedure or function call.</para>
-		<para>Valid example: 
-		<programlisting>select * from t1, TABLE(call proc(t1.x)) t2</programlisting>
-		</para>
-		<para>Invalid example, since t1 appears after the nested table in the from clause: 
-		<programlisting>select * from TABLE(call proc(t1.x)) t2, t1</programlisting>
-		</para>
-		<note>
-			<title>Multiple Execution</title>
-			<para>The usage of a correlated nested table may result in multiple
-				executions of the table expression - once for each correlated row.
-			</para>
-		</note>
-	  </section>
-	  <section id="texttable">
-		<title>TEXTTABLE</title>
-		<para>The TEXTTABLE funciton processes character input to produce tabular ouptut.  It supports both fixed and delimited file format parsing.  
-			The function itself defines what columns it projects.  
-		    The TEXTTABLE function is implicitly a nested table and may be correlated to preceeding FROM clause entries.
-      	</para>
-      	<para>
-        Usage:
-        	<synopsis label="Usage">TEXTTABLE(expression COLUMNS &lt;COLUMN&gt;, ... [DELIMITER char] [(QUOTE|ESCAPE) char] [HEADER [integer]] [SKIP integer]) AS name</synopsis>
-        	<synopsis label="Usage">COLUMN := name datatype [WIDTH integer]</synopsis> 
-      	</para>
-      	<itemizedlist>
-        	<para>Parameters</para>
-        <listitem>
-          <para>expression - the text content to process, which should be convertable to CLOB.
-          </para>
-        </listitem>
-        <listitem>
-        	<para>DELIMITER sets the field delimiter character to use.  Defaults to ','.
-        	</para>
-        </listitem>
-        <listitem>
-        	<para>QUOTE sets the quote, or qualifier, character used to wrap field values.  Defaults to '"'.  
-        	</para>
-        </listitem>
-        <listitem>
-        	<para>ESCAPE sets the escape character to use if no quoting character is in use.  
-        	This is used in situations where the delimiter or new line characters are escaped with a preceding character, e.g. \,  
-        	</para>
-        </listitem>
-        <listitem>
-        	<para>HEADER specifies the text line number (counting every new line) on which the column names occur.  All lines prior to the header will be skipped.
-        	If HEADER is specified, then the header line will be used to determine the TEXTTABLE column position by case-insensitive name matching.  This is especially useful in situations where only a subset of the columns are needed.
-        	If the HEADER value is not specified, it defaults to 1.  
-        	If HEADER is not specified, then columns are expected to match positionally with the text contents. 
-        	</para>
-        </listitem>
-        <listitem>
-        	<para>SKIP specifies the number of text lines (counting every new line) to skip before parsing the contents.  HEADER may still be specified with SKP.
-        	</para>
-        </listitem>
-      	</itemizedlist>
-      	<itemizedlist>
-        <para>Syntax Rules:
-        </para>
-        <listitem>
-          <para>If width is specified for one column it must be specified for all columns.
-          </para>
-        </listitem>
-        <listitem>
-          <para>If width is specified, then fixed width parsing is used and ESCAPE, QUOTE, and HEADER should not be specified.
-          </para>
-        </listitem>
-        <listitem>
-          <para>The columns names must be not contain duplicates.
-          </para>
-        </listitem>
-        </itemizedlist>
-      	<itemizedlist>
-        	<para>Examples</para>
-        	<listitem>
-		        <para>Use of the HEADER parameter, returns 1 row ['b']: <programlisting>select * from texttable('col1,col2,col3\na,b,c' COLUMNS col2 string HEADER) x</programlisting>
-				</para>		
-        	</listitem>
-        	<listitem>
-		        <para>Use of fixed width, returns 1 row ['a', 'b', 'c']: <programlisting>select * from texttable('abc' COLUMNS col1 string width 1, col2 string width 1, col3 string width 1) x</programlisting>
-				</para>		
-        	</listitem>
-        	<listitem>
-		        <para>Use of ESCAPE parameter, returns 1 row ['a,', 'b']: <programlisting>select * from texttable('a:,,b' COLUMNS col1 string, col2 string ESCAPE ':') x</programlisting>
-				</para>		
-        	</listitem>
-        	<listitem>
-		        <para>As a nested table: <programlisting>select x.* from t, texttable(t.clobcolumn COLUMNS first string, second date SKIP 1) x</programlisting>
-				</para>		
-        	</listitem>
-		</itemizedlist>		
-	  </section>
-	  <section id="xmltable">
-		<title>XMLTABLE</title>
-		<para>The XMLTABLE funciton uses XQuery to produce tabular ouptut.  
-		    The XMLTABLE function is implicitly a nested table and may be correlated to preceeding FROM clause entries.  XMLTABLE is part of the SQL/XML 2006 specification. 
-      	</para>
-      	<para>
-        Usage:
-        	<synopsis label="Usage">XMLTABLE([&lt;NSP&gt;,] xquery-expression [&lt;PASSING&gt;] [COLUMNS &lt;COLUMN&gt;, ... )] AS name</synopsis>
-        	<synopsis label="Usage">COLUMN := name (FOR ORDINALITY | (datatype [DEFAULT expression] [PATH string]))</synopsis> 
-      	</para>
-      	<para>See XMLELEMENT for the definition of NSP - <link linkend="xmlnamespaces">XMLNAMESPACES</link>.</para>
-      	<para>See XMLQUERY for the definition of <link linkend="passing">PASSING</link>.</para>
-      	<para>See also <link linkend="xmlquery">XMLQUERY</link></para>
-      	<note><para>See also <xref linkend="xquery_optimization"/></para></note>
-      	<itemizedlist>
-        	<para>Parameters</para>
-        <listitem>
-        	<para>The optional XMLNAMESPACES clause specifies the namepaces for use in the XQuery and COLUMN path expressions.
-        	</para>
-        </listitem>
-        <listitem>
-        	<para>The xquery-expression should be a valid XQuery.  Each sequence item returned by the xquery will be used to create a row of values as defined by the COLUMNS clause.
-        	</para>
-        </listitem>
-        <listitem>
-        	<para>If COLUMNS is not specified, then that is the same as having the COLUMNS clause: "COLUMNS OBJECT_VALUE XML PATH '.'", which returns the entire item as an XML value.   
-        	</para>
-        </listitem>
-        <listitem>
-        	<para>A FOR ORDINALITY column is typed as integer and will return the 1-based item number as its value.
-        	</para>
-        </listitem>
-        <listitem>
-        	<para>Each non-ordinality column specifies a type and optionally a PATH and a DEFAULT expression.
-        	</para>
-        </listitem>
-        <listitem>
-        	<para>If PATH is not specified, then the path will be the same as the column name.
-        	</para>
-        </listitem>
-      	</itemizedlist>
-      	<itemizedlist>
-        <para>Syntax Rules:
-        </para>
-        <listitem>
-          <para>Only 1 FOR ORDINALITY column may be specified.
-          </para>
-        </listitem>
-        <listitem>
-          <para>The columns names must be not contain duplicates.
-          </para>
-        </listitem>
-        </itemizedlist>
-      	<itemizedlist>
-        	<para>Examples</para>
-        	<listitem>
-		        <para>Use of passing, returns 1 row [1]: <programlisting>select * from xmltable('/a' PASSING xmlparse(document '&lt;a id="1"/&gt;') COLUMNS id integer PATH '@id') x</programlisting>
-				</para>		
-        	</listitem>
-        	<listitem>
-		        <para>As a nested table: <programlisting>select x.* from t, xmltable('/x/y' PASSING t.doc COLUMNS first string, second FOR ORDINALITY) x</programlisting>
-				</para>		
-        	</listitem>
-		</itemizedlist>		
-	  </section>
-    </section>
-    	  <section id="arraytable">
-		<title>ARRAYTABLE</title>
-		<para>The ARRAYTABLE funciton processes an array input to produce tabular ouptut.  
-			The function itself defines what columns it projects.  
-		    The ARRAYTABLE function is implicitly a nested table and may be correlated to preceeding FROM clause entries.
-      	</para>
-      	<para>
-        Usage:
-        	<synopsis label="Usage">ARRAYTABLE(expression COLUMNS &lt;COLUMN&gt;, ...) AS name</synopsis>
-        	<synopsis label="Usage">COLUMN := name datatype</synopsis> 
-      	</para>
-      	<itemizedlist>
-        	<para>Parameters</para>
-        <listitem>
-          <para>expression - the array to process, which should be a java.sql.Array or java array value.
-          </para>
-        </listitem>
-      	</itemizedlist>
-      	<itemizedlist>
-        <para>Syntax Rules:
-        </para>
-        <listitem>
-          <para>The columns names must be not contain duplicates.
-          </para>
-        </listitem>
-        </itemizedlist>
-      	<itemizedlist>
-        	<para>Examples</para>
-        	<listitem>
-		        <para>As a nested table: <programlisting>select x.* from (call source.invokeMDX('some query')) r, arraytable(r.tuple COLUMNS first string, second bigdecimal) x</programlisting>
-				</para>		
-        	</listitem>
-		</itemizedlist>
-		<para>ARRAYTABLE is effectively a shortcut for using the <xref linkend="array_get"/> function in a nested table.  For example "ARRAYGET(val COLUMNS col1 string, col2 integer) AS X" is the same as "TABLE(SELECT cast(array_get(val, 1) AS string) AS col1, cast(array_get(val, 2) AS integer) AS col2) AS X".</para>		
-	  </section>
-    <section id="where_clause">
-      <title>WHERE Clause</title>
-      <para>
-      The WHERE clause defines the criteria to limit the records affected by SELECT, UPDATE, and DELETE statements.  
-      </para>
-      <itemizedlist>
-        <para>The general form of the WHERE is:
-        </para>
-        <listitem>
-          <para>WHERE <link linkend="criteria">criteria</link>
-          </para>
-        </listitem>
-      </itemizedlist>
-    </section>
-    <section id="groupby_clause">
-      <title>GROUP BY Clause</title>
-      <para>
-      The GROUP BY clause denotes that rows should be grouped according to the specified expression values. One row will be returned for each group, after optionally filtering those aggregate rows based on a HAVING clause.   
-      </para>
-      <itemizedlist>
-        <para>The general form of the GROUP BY is:
-        </para>
-        <listitem>
-          <para>GROUP BY expression (,expression)*
-          </para>
-        </listitem>
-      </itemizedlist>
-      <itemizedlist>
-        <para>Syntax Rules:
-        </para>
-        <listitem>
-          <para>Column references in the group by clause must by to unaliased output columns.
-          </para>
-        </listitem>
-        <listitem>
-          <para>Expressions used in the group by must appear in the select clause.
-          </para>
-        </listitem>
-        <listitem>
-          <para>Column references and expessions in the select clause that are not used in the group by clause must appear in aggregate functions. 
-          </para>
-        </listitem>
-        <listitem>
-          <para>If an aggregate function is used in the SELECT clause and no
-            GROUP BY is specified, an implicit GROUP BY will be performed with
-            the entire result set as a single group. In this case, every column
-            in the SELECT must be an aggregate function as no other column value
-            will be fixed across the entire group. 
-          </para>
-        </listitem>
-        <listitem>
-          <para>The group by columns must be of a comparable type.</para>
-        </listitem>
-      </itemizedlist>
-    </section>
-    <section id="having_clause">
-      <title>HAVING Clause</title>
-      <para>
-      The HAVING clause operates exactly as a WHERE clause although it operates on the output of a GROUP BY. It supports the same syntax as the WHERE clause.
-      </para>
-      <itemizedlist>
-        <para>Syntax Rules:
-        </para>
-        <listitem>
-          <para>Expressions used in the group by clause must either
-            contain an aggregate function: COUNT, AVG, SUM, MIN, MAX. or be one
-            of the grouping expressions.</para>
-        </listitem>
-      </itemizedlist>
-    </section>
-    <section id="orderby_clause">
-      <title>ORDER BY Clause</title>
-      <para>
-      The ORDER BY clause specifies how records should be sorted. The options are ASC (ascending) and DESC (descending).
-      </para>
-      <para>
-        Usage:
-        <synopsis label="Usage">ORDER BY expression [ASC|DESC] [NULLS (FIRST|LAST)], ...</synopsis>
-      </para>
-      <itemizedlist>
-        <para>Syntax Rules:
-        </para>
-        <listitem>
-          <para>Sort columns may be specified positionally by a 1-based positional
-	        integer, by SELECT clause alias name, by SELECT clause expression, or by an unrelated expression.</para>
-        </listitem>
-        <listitem>
-          <para>Column references may appear in the SELECT clause as the
-			expression for an aliased column or may reference columns from tables
-			in the FROM clause.
-			If the column reference is not in the SELECT clause the query must not
-			be a set operation, specify SELECT DISTINCT, or contain a GROUP BY
-			clause.</para>
-        </listitem>
-        <listitem>
-          <para>Unrelated expressions, expressions not appearing as an aliased expression in the select clause, 
-          are allowed in the order by clause of a non-set QUERY.  The columns referenced in the expression must come from the
-          from clause table references.  The column references cannot be to alias names or positional.
-          </para>
-        </listitem>
-        <listitem>
-          <para>The ORDER BY columns must be of a comparable type.</para>
-        </listitem>
-        <listitem>
-          <para>If an ORDER BY is used in an inline view or view
-	         definition without a limit clause, it will be removed by the Teiid
-	         optimizer.</para>
-        </listitem>
-        <listitem>
-        	<para>If NULLS FIRST/LAST is specified, then nulls are guaranteed to be sorted either first or last.  If the null ordering is not specified, then results will 
-        	typically be sorted with nulls as low values, which is Teiid's internal default sorting behavior.   
-        	However not all sources return results with nulss sorted as low values by default, and Teiid may return results with different null orderings. 
-        	</para>
-        </listitem>
-      </itemizedlist>
-      <warning>
-		<para>The use of positional ordering is no longer supported by the
-				ANSI SQL standard and is a deprecated feature in Teiid. It is
-				preferable to use alias names in the order by clause.</para>
-	  </warning>
-    </section>
-    <section id="limit_clause">
-      <title>LIMIT Clause</title>
-      <para>
-      The LIMIT clause specifies a limit on the number of records returned from the SELECT command. An optional offset (the number of rows to skip) can be specified.  The LIMIT clause can also be specfied using the SQL 2008 OFFSET/FETCH FIRST clauses.  
-      If an ORDER BY is also specified, it will be applied before the OFFSET/LIMIT are applied.  If an ORDER BY is not specified there is generally no guarantee what subset of rows will be returned.
-      </para>
-      <para>
-        Usage:
-        <synopsis label="Usage">LIMIT [offset,] limit</synopsis>
-        <synopsis label="Usage">[OFFSET offset ROW|ROWS] [FETCH FIRST|NEXT [limit] ROW|ROWS ONLY</synopsis>
-      </para>
-      <itemizedlist>
-        <para>Syntax Rules:
-        </para>
-        <listitem>
-          <para>The limit/offset expressions must be a non-negative integer or a parameter reference (?).  An offset of 0 is ignored.  A limit of 0 will return no rows.
-          </para>
-        </listitem>
-        <listitem>
-          <para>The terms FIRST/NEXT are interchangable as well as ROW/ROWS.
-          </para>
-        </listitem>
-      </itemizedlist>
-      <itemizedlist>
-        <para>Examples:
-        </para>
-        <listitem>
-          <para>LIMIT 100 - returns the first 100 records (rows 1-100)</para>
-        </listitem>
-        <listitem>
-          <para>LIMIT 500, 100 - skips 500 records and returns the next 100 records (rows 501-600)</para>
-        </listitem>
-        <listitem>
-          <para>OFFSET 500 ROWS - skips 500 records</para>
-        </listitem>
-        <listitem>
-          <para>OFFSET 500 ROWS FETCH NEXT 100 ROWS ONLY - skips 500 records and returns the next 100 records (rows 501-600)</para>
-        </listitem>
-        <listitem>
-          <para>FETCH FIRST ROW ONLY - returns only the first record</para>
-        </listitem>
-      </itemizedlist>
-    </section>
-    <section id="into_clause">
-      <title>INTO Clause</title>
-      <warning>
-      	<para>Usage of the INTO Clause for inserting into a table has been been deprecated.  An <link linkend="insert_command">INSERT</link> with a query command should be used instead.</para>
-      </warning>
-      <para>
-      When the into clause is specified with a SELECT, the results of the query are inserted into the specified table. This is often used to insert records into a temporary table. The INTO clause immediately precedes the FROM clause.   
-      </para>
-      <para>
-        Usage:
-        <synopsis label="Usage">INTO table FROM ...</synopsis>
-      </para>
-      <itemizedlist>
-        <para>Syntax Rules:
-        </para>
-        <listitem>
-          <para>The INTO clause is logically applied last in processing, after the ORDER BY and LIMIT clauses.</para>
-        </listitem>
-        <listitem>
-          <para>Teiid's support for SELECT INTO is similar to
-            MS SQL Server. The target of the INTO clause is a table where
-            the result of the rest select command will be inserted. SELECT
-            INTO should not be used UNION query.</para>
-        </listitem>
-      </itemizedlist>
-    </section>    
-    <section id="option_clause">
-      <title>OPTION Clause</title>
-      <para>
-      The OPTION keyword denotes options the user can pass in with the command. These options are Teiid-specific and not covered by any SQL specification.  
-      </para>
-      <para>
-        Usage:
-        <synopsis label="Usage">OPTION option, (option)*</synopsis>
-      </para>
-      <itemizedlist>
-        <para>Supported options:
-        </para>
-        <listitem>
-          <para>MAKEDEP table [(,table)*] - specifies source tables that should be made dependent in the join
-          </para>
-        </listitem>
-        <listitem>
-          <para>MAKENOTDEP table [(,table)*] - prevents a dependent join from being used
-          </para>
-        </listitem>
-        <listitem>
-          <para>NOCACHE [table (,table)*] - prevents cache from being used for all tables or for the given tables
-          </para>
-        </listitem>
-      </itemizedlist>
-      <itemizedlist>
-        <para>Examples:
-        </para>
-        <listitem>
-          <para>OPTION MAKEDEP table1</para>
-        </listitem>
-        <listitem>
-          <para>OPTION NOCACHE</para>
-        </listitem>
-      </itemizedlist>
-      <para>All tables specified in the OPTION clause should be fully qualified.</para>
-      <note><para>Previous versions of Teiid accepted the PLANONLY, DEBUG, and SHOWPLAN option arguments.  These are no longer accepted in the OPTION clause.
-      Please see the Client Developers Guide for replacements to those options.
-      </para></note>
-    </section>
-  </section>
   <section id="set_operations">
     <title>Set Operations</title>
     <para>Teiid supports the UNION, UNION ALL, INTERSECT, EXCEPT set operation as a way of combining the results of query expressions.</para>

Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/CapabilitiesConverter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/CapabilitiesConverter.java	2011-07-28 11:43:06 UTC (rev 3346)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/CapabilitiesConverter.java	2011-07-28 19:58:08 UTC (rev 3347)
@@ -101,6 +101,7 @@
         tgtCaps.setCapabilitySupport(Capability.COMMON_TABLE_EXPRESSIONS, srcCaps.supportsCommonTableExpressions());
         tgtCaps.setCapabilitySupport(Capability.ADVANCED_OLAP, srcCaps.supportsAdvancedOlapOperations());
         tgtCaps.setCapabilitySupport(Capability.ELEMENTARY_OLAP, srcCaps.supportsAdvancedOlapOperations());
+        tgtCaps.setCapabilitySupport(Capability.WINDOW_FUNCTION_ORDER_BY_AGGREGATES, srcCaps.supportsWindowOrderByWithAggregates());
         tgtCaps.setCapabilitySupport(Capability.QUERY_AGGREGATES_ARRAY, srcCaps.supportsArrayAgg());
         List functions = srcCaps.getSupportedFunctions();
         if(functions != null && functions.size() > 0) {

Modified: trunk/engine/src/main/java/org/teiid/query/function/aggregate/RankingFunction.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/aggregate/RankingFunction.java	2011-07-28 11:43:06 UTC (rev 3346)
+++ trunk/engine/src/main/java/org/teiid/query/function/aggregate/RankingFunction.java	2011-07-28 19:58:08 UTC (rev 3347)
@@ -27,7 +27,6 @@
 import org.teiid.api.exception.query.ExpressionEvaluationException;
 import org.teiid.api.exception.query.FunctionExecutionException;
 import org.teiid.core.TeiidComponentException;
-import org.teiid.query.processor.relational.GroupingNode;
 import org.teiid.query.sql.symbol.AggregateSymbol.Type;
 
 /**
@@ -36,38 +35,37 @@
 public class RankingFunction extends AggregateFunction {
 	
 	private int count = 0;
-	private int result = 0;
-	private int[] orderIndexes;
+	private int lastCount = 0;
 	private Type type;
-	private List<?> previousTuple;
 	
-	public RankingFunction(Type function, int[] orderIndexes) {
+	public RankingFunction(Type function) {
 		this.type = function;
-		this.orderIndexes = orderIndexes;
 	}
 
 	@Override
 	public void reset() {
 		count = 0;
-		result = 0;
+		lastCount = 0;
 	}
 	
 	@Override
 	public void addInputDirect(Object input, List<?> tuple)
 			throws FunctionExecutionException, ExpressionEvaluationException,
 			TeiidComponentException {
-		if (previousTuple == null || !GroupingNode.sameGroup(orderIndexes, tuple, previousTuple)) {
+		if (type == Type.RANK) {
 			count++;
-			result = count;
-		} else if (type == Type.RANK) {
-			count++;
 		}
-		previousTuple = tuple;
 	}
 	
 	@Override
 	public Object getResult() throws FunctionExecutionException,
 			ExpressionEvaluationException, TeiidComponentException {
+		if (type == Type.DENSE_RANK) {
+			count++;
+			return count;
+		}
+		int result = ++lastCount;
+		lastCount = count;
 		return result;
 	}
 

Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/capabilities/SourceCapabilities.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/capabilities/SourceCapabilities.java	2011-07-28 11:43:06 UTC (rev 3346)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/capabilities/SourceCapabilities.java	2011-07-28 19:58:08 UTC (rev 3347)
@@ -323,7 +323,8 @@
         MAX_DEPENDENT_PREDICATES,
         ADVANCED_OLAP, 
         QUERY_AGGREGATES_ARRAY, 
-        ELEMENTARY_OLAP
+        ELEMENTARY_OLAP, 
+        WINDOW_FUNCTION_ORDER_BY_AGGREGATES
     }
 
     public enum Scope {

Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/CriteriaCapabilityValidatorVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/CriteriaCapabilityValidatorVisitor.java	2011-07-28 11:43:06 UTC (rev 3346)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/CriteriaCapabilityValidatorVisitor.java	2011-07-28 19:58:08 UTC (rev 3347)
@@ -168,7 +168,14 @@
     public void visit(WindowFunction windowFunction) {
     	if(! this.caps.supportsCapability(Capability.ELEMENTARY_OLAP)) {
             markInvalid(windowFunction, "Window function not supported by source"); //$NON-NLS-1$
-        }
+            return;
+        } 
+    	if (!this.caps.supportsCapability(Capability.WINDOW_FUNCTION_ORDER_BY_AGGREGATES) 
+    			&& windowFunction.getWindowSpecification().getOrderBy() != null
+    			&& !windowFunction.getFunction().isAnalytical()) {
+    		markInvalid(windowFunction, "Window function order by with aggregate not supported by source"); //$NON-NLS-1$
+            return;
+    	}
     }
     
     public void visit(CaseExpression obj) {

Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleAssignOutputElements.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleAssignOutputElements.java	2011-07-28 11:43:06 UTC (rev 3346)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleAssignOutputElements.java	2011-07-28 19:58:08 UTC (rev 3347)
@@ -498,7 +498,7 @@
                         ss = ((AliasSymbol)ss).getSymbol();
                     }
                     
-                    if (ss instanceof ExpressionSymbol && !(ss instanceof AggregateSymbol)) {
+                    if (ss instanceof WindowFunction || (ss instanceof ExpressionSymbol && !(ss instanceof AggregateSymbol))) {
                         createdSymbols.add(ss);
                     }
                     ElementCollectorVisitor.getElements(ss, requiredSymbols);

Modified: trunk/engine/src/main/java/org/teiid/query/processor/relational/WindowFunctionProjectNode.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/relational/WindowFunctionProjectNode.java	2011-07-28 11:43:06 UTC (rev 3346)
+++ trunk/engine/src/main/java/org/teiid/query/processor/relational/WindowFunctionProjectNode.java	2011-07-28 19:58:08 UTC (rev 3347)
@@ -73,6 +73,8 @@
 
 public class WindowFunctionProjectNode extends SubqueryAwareRelationalNode {
 	
+	private static final List<Integer> SINGLE_VALUE_ID = Arrays.asList(0);
+
 	private enum Phase {
 		COLLECT,
 		PROCESS,
@@ -92,6 +94,7 @@
 		List<NullOrdering> nullOrderings = new ArrayList<NullOrdering>();
 		List<Boolean> orderType = new ArrayList<Boolean>();
 		List<WindowFunctionInfo> functions = new ArrayList<WindowFunctionInfo>();
+		List<WindowFunctionInfo> rowValuefunctions = new ArrayList<WindowFunctionInfo>();
 	}
 	
 	private LinkedHashMap<WindowSpecification, WindowSpecificationInfo> windows = new LinkedHashMap<WindowSpecification, WindowSpecificationInfo>();
@@ -106,6 +109,7 @@
 	private TupleSource inputTs;
 	private STree[] partitionMapping;
 	private STree[] valueMapping;
+	private STree[] rowValueMapping;
 	private IndexedTupleSource outputTs;
 	
 	public WindowFunctionProjectNode(int nodeId) {
@@ -123,6 +127,7 @@
 		this.phase = Phase.COLLECT;
 		this.partitionMapping = null;
 		this.valueMapping = null;
+		this.rowValueMapping = null;
 		this.outputTs = null;
 	}
 	
@@ -132,20 +137,22 @@
 			tb.remove();
 			tb = null;
 		}
-		if (partitionMapping != null) {
-			for (STree tree : partitionMapping) {
+		removeMappings(partitionMapping);
+		partitionMapping = null;
+		removeMappings(valueMapping);
+		valueMapping = null;
+		removeMappings(rowValueMapping);
+		rowValueMapping = null;
+	}
+
+	private void removeMappings(STree[] mappings) {
+		if (mappings != null) {
+			for (STree tree : mappings) {
 				if (tree != null) {
 					tree.remove();
 				}
 			}
-			partitionMapping = null;
 		}
-		if (valueMapping != null) {
-			for (STree tree : valueMapping) {
-				tree.remove();
-			}
-			valueMapping = null;
-		}
 	}
 	
 	public Object clone(){
@@ -201,7 +208,11 @@
 					wfi.conditionIndex = getIndex(ex);
 				}
 				wfi.outputIndex = i;
-				wsi.functions.add(wfi);
+				if (wf.getFunction().getAggregateFunction() == Type.ROW_NUMBER) {
+					wsi.rowValuefunctions.add(wfi);
+				} else {
+					wsi.functions.add(wfi);
+				}
 			} else {
 				int index = getIndex(ex);
 				passThrough.put(i, index);
@@ -218,6 +229,7 @@
 			phase = Phase.PROCESS;
 			partitionMapping = new STree[this.windows.size()];
 			valueMapping = new STree[this.windows.size()];
+			rowValueMapping = new STree[this.windows.size()];
 		}
 		
 		if (phase == Phase.PROCESS) {
@@ -244,15 +256,27 @@
 				for (int specIndex = 0; specIndex < specs.size(); specIndex++) {
 					Map.Entry<WindowSpecification, WindowSpecificationInfo> entry = specs.get(specIndex);
 					List<?> idRow = Arrays.asList(rowId);
-					if (partitionMapping[specIndex] != null) {
-						idRow = partitionMapping[specIndex].find(idRow);
-						idRow = idRow.subList(1, 2);
+					List<WindowFunctionInfo> functions = entry.getValue().rowValuefunctions;
+					if (!functions.isEmpty()) {
+						List<?> valueRow = rowValueMapping[specIndex].find(idRow);
+						for (int i = 0; i < functions.size(); i++) {
+							WindowFunctionInfo wfi = functions.get(i);
+							outputRow.set(wfi.outputIndex, valueRow.get(i+1));
+						}
 					}
-					List<?> valueRow = valueMapping[specIndex].find(idRow);
-					List<WindowFunctionInfo> functions = entry.getValue().functions;
-					for (int i = 0; i < functions.size(); i++) {
-						WindowFunctionInfo wfi = functions.get(i);
-						outputRow.set(wfi.outputIndex, valueRow.get(i+1));
+					functions = entry.getValue().functions;
+					if (!functions.isEmpty()) {
+						if (partitionMapping[specIndex] != null) {
+							idRow = partitionMapping[specIndex].find(idRow);
+							idRow = idRow.subList(1, 2);
+						} else {
+							idRow = SINGLE_VALUE_ID;
+						}
+						List<?> valueRow = valueMapping[specIndex].find(idRow);
+						for (int i = 0; i < functions.size(); i++) {
+							WindowFunctionInfo wfi = functions.get(i);
+							outputRow.set(wfi.outputIndex, valueRow.get(i+1));
+						}
 					}
 				}
 				this.addBatchRow(outputRow);
@@ -281,24 +305,20 @@
 			Map.Entry<WindowSpecification, WindowSpecificationInfo> entry = specs.get(specIndex);
 			WindowSpecificationInfo info = entry.getValue();
 			IndexedTupleSource specificationTs = tb.createIndexedTupleSource();
-			int[] groupingIndexes = null;
+			boolean multiGroup = false;
+			int[] partitionIndexes = null;
 			int[] orderIndexes = null;
 
 			//if there is partitioning or ordering, then sort
 			if (!info.orderType.isEmpty()) {
+				multiGroup = true;
 				int[] sortKeys = new int[info.orderType.size()];
 				int i = 0;
 				if (!info.groupIndexes.isEmpty()) {
 					for (Integer sortIndex : info.groupIndexes) {
 						sortKeys[i++] = sortIndex;
 					}
-					groupingIndexes = Arrays.copyOf(sortKeys, info.groupIndexes.size());
-					ElementSymbol key = new ElementSymbol("rowid"); //$NON-NLS-1$
-					key.setType(DataTypeManager.DefaultDataClasses.INTEGER);
-					ElementSymbol value = new ElementSymbol("partitionid"); //$NON-NLS-1$
-					key.setType(DataTypeManager.DefaultDataClasses.INTEGER);
-					List<ElementSymbol> elements = Arrays.asList(key, value);
-					partitionMapping[specIndex] = this.getBufferManager().createSTree(elements, this.getConnectionID(), 1);
+					partitionIndexes = Arrays.copyOf(sortKeys, info.groupIndexes.size());
 				}
 				if (!info.sortIndexes.isEmpty()) {
 					for (Integer sortIndex : info.sortIndexes) {
@@ -306,73 +326,97 @@
 					}
 					orderIndexes = Arrays.copyOfRange(sortKeys, info.groupIndexes.size(), info.groupIndexes.size() + info.sortIndexes.size());
 				}
+				if (!info.functions.isEmpty()) {
+					ElementSymbol key = new ElementSymbol("rowId"); //$NON-NLS-1$
+					key.setType(DataTypeManager.DefaultDataClasses.INTEGER);
+					ElementSymbol value = new ElementSymbol("partitionId"); //$NON-NLS-1$
+					key.setType(DataTypeManager.DefaultDataClasses.INTEGER);
+					List<ElementSymbol> elements = Arrays.asList(key, value);
+					partitionMapping[specIndex] = this.getBufferManager().createSTree(elements, this.getConnectionID(), 1);
+				}
 				SortUtility su = new SortUtility(specificationTs, Mode.SORT, this.getBufferManager(), this.getConnectionID(), tb.getSchema(), info.orderType, info.nullOrderings, sortKeys);
 				TupleBuffer sorted = su.sort();
 				specificationTs = sorted.createIndexedTupleSource(true);
 			}
-			List<AggregateFunction> aggs = initializeAccumulators(info, specIndex, orderIndexes);
+			List<AggregateFunction> aggs = initializeAccumulators(info.functions, specIndex, false);
+			List<AggregateFunction> rowValueAggs = initializeAccumulators(info.rowValuefunctions, specIndex, true);
 
-			int partitionId = 0;
+			int groupId = 0;
 			List<?> lastRow = null;
 			while (specificationTs.hasNext()) {
 				List<?> tuple = specificationTs.nextTuple();
-				boolean sameGroup = true;
-				if (lastRow != null) {
-		        	sameGroup = GroupingNode.sameGroup(groupingIndexes, tuple, lastRow);
-		        	if (!sameGroup || orderIndexes != null) {
-		        		saveValues(specIndex, orderIndexes, aggs, partitionId, lastRow, sameGroup);
+				if (multiGroup) {
+				    if (lastRow != null) {
+				    	boolean samePartition = GroupingNode.sameGroup(partitionIndexes, tuple, lastRow);
+				    	if (!aggs.isEmpty() && (!samePartition || !GroupingNode.sameGroup(orderIndexes, tuple, lastRow))) {
+			        		saveValues(specIndex, aggs, groupId, samePartition, false);
+		        			groupId++;
+				    	}
+		        		saveValues(specIndex, rowValueAggs, lastRow.get(lastRow.size() - 1), samePartition, true);
 		        	}
-				}
-		        if (orderIndexes == null) {
-		        	if (!sameGroup) {
-		        		partitionId++;
-		        	}
-		        	List<Object> partitionTuple = Arrays.asList(tuple.get(tuple.size() - 1), partitionId);
-					partitionMapping[specIndex].insert(partitionTuple, InsertMode.NEW, -1);
+				    if (!aggs.isEmpty()) {
+			        	List<Object> partitionTuple = Arrays.asList(tuple.get(tuple.size() - 1), groupId);
+						partitionMapping[specIndex].insert(partitionTuple, InsertMode.NEW, -1);
+				    }
 		        }
 		        for (AggregateFunction function : aggs) {
 		        	function.addInput(tuple);
 		        }
+		        for (AggregateFunction function : rowValueAggs) {
+		        	function.addInput(tuple);
+		        }
 		        lastRow = tuple;
 			}
 		    if(lastRow != null) {
-		    	saveValues(specIndex, orderIndexes, aggs, partitionId, lastRow, true);
+		    	saveValues(specIndex, aggs, groupId, true, false);
+		    	saveValues(specIndex, rowValueAggs, lastRow.get(lastRow.size() - 1), true, true);
 		    }
 		}
 	}
 
-	private void saveValues(int specIndex, int[] orderIndexes,
-			List<AggregateFunction> aggs, int partitionId, List<?> tuple,
-			boolean sameGroup) throws FunctionExecutionException,
+	private void saveValues(int specIndex,
+			List<AggregateFunction> aggs, Object id,
+			boolean samePartition, boolean rowValue) throws FunctionExecutionException,
 			ExpressionEvaluationException, TeiidComponentException,
 			TeiidProcessingException {
+		if (aggs.isEmpty()) {
+			return;
+		}
 		List<Object> row = new ArrayList<Object>(aggs.size() + 1);
-		if (orderIndexes == null) {
-			row.add(partitionId);
-		} else {
-			//use the rowid
-			row.add(tuple.get(tuple.size() - 1));
-		}
+		row.add(id);
 		for (AggregateFunction function : aggs) {
 			row.add(function.getResult());
-			if (!sameGroup) {
+			if (!samePartition) {
 				function.reset();
 			}
 		}
-		valueMapping[specIndex].insert(row, orderIndexes != null?InsertMode.NEW:InsertMode.ORDERED, -1);
+		if (rowValue) {
+			rowValueMapping[specIndex].insert(row, InsertMode.NEW, -1);
+		} else {
+			valueMapping[specIndex].insert(row, InsertMode.ORDERED, -1);	
+		}
 	}
 
-	private List<AggregateFunction> initializeAccumulators(WindowSpecificationInfo info, int specIndex,
-			int[] orderIndexes) {
-		List<AggregateFunction> aggs = new ArrayList<AggregateFunction>();
+	/**
+	 * TODO: consolidate with {@link GroupingNode}
+	 * @param functions
+	 * @param specIndex
+	 * @param rowValues
+	 * @return
+	 */
+	private List<AggregateFunction> initializeAccumulators(List<WindowFunctionInfo> functions, int specIndex, boolean rowValues) {
+		List<AggregateFunction> aggs = new ArrayList<AggregateFunction>(functions.size());
+		if (functions.isEmpty()) {
+			return aggs;
+		}
 		//initialize the function accumulators
-		List<ElementSymbol> elements = new ArrayList<ElementSymbol>(info.functions.size() + 1);
+		List<ElementSymbol> elements = new ArrayList<ElementSymbol>(functions.size() + 1);
 		ElementSymbol key = new ElementSymbol("id"); //$NON-NLS-1$
 		key.setType(DataTypeManager.DefaultDataClasses.INTEGER);
 		elements.add(key);
 
 		CommandContext context = this.getContext();
-		for (WindowFunctionInfo wfi : info.functions) {
+		for (WindowFunctionInfo wfi : functions) {
 			AggregateSymbol aggSymbol = wfi.function.getFunction();
 		    Class<?> outputType = aggSymbol.getType();
 		    ElementSymbol value = new ElementSymbol("val"); //$NON-NLS-1$
@@ -387,7 +431,7 @@
 			switch (function) {
 			case RANK:
 			case DENSE_RANK:
-				af = new RankingFunction(function, orderIndexes);
+				af = new RankingFunction(function);
 				break;
 			case ROW_NUMBER: //same as count(*)
 			case COUNT:
@@ -424,7 +468,13 @@
 			aggs.add(af);
 		}
 		
-		valueMapping[specIndex] = this.getBufferManager().createSTree(elements, this.getConnectionID(), 1);
+		if (!aggs.isEmpty()) {
+			if (!rowValues) {
+				valueMapping[specIndex] = this.getBufferManager().createSTree(elements, this.getConnectionID(), 1);
+			} else {
+				rowValueMapping[specIndex] = this.getBufferManager().createSTree(elements, this.getConnectionID(), 1);
+			}
+		}
 
 		return aggs;
 	}

Modified: trunk/engine/src/main/java/org/teiid/query/sql/symbol/AggregateSymbol.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/symbol/AggregateSymbol.java	2011-07-28 11:43:06 UTC (rev 3346)
+++ trunk/engine/src/main/java/org/teiid/query/sql/symbol/AggregateSymbol.java	2011-07-28 19:58:08 UTC (rev 3347)
@@ -176,18 +176,28 @@
 			return DataTypeManager.DefaultDataClasses.OBJECT;
 		case TEXTAGG:
 			return DataTypeManager.DefaultDataClasses.BLOB;
-		case RANK:
-		case ROW_NUMBER:
-		case DENSE_RANK:
-			return DataTypeManager.DefaultDataClasses.INTEGER;
 		}
 		if (isBoolean()) {
 			return DataTypeManager.DefaultDataClasses.BOOLEAN;
-		} else if (isEnhancedNumeric()) {
+		}
+		if (isEnhancedNumeric()) {
 			return DataTypeManager.DefaultDataClasses.DOUBLE;
 		}
+		if (isAnalytical()) {
+			return DataTypeManager.DefaultDataClasses.INTEGER;
+		}
 		return this.getExpression().getType();
 	}
+	
+	public boolean isAnalytical() {
+		switch (this.aggregate) {
+		case RANK:
+		case ROW_NUMBER:
+		case DENSE_RANK:
+			return true;
+		}
+		return false;
+	}
 
 	public boolean isBoolean() {
 		return this.aggregate == Type.EVERY 

Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties	2011-07-28 11:43:06 UTC (rev 3346)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties	2011-07-28 19:58:08 UTC (rev 3347)
@@ -113,7 +113,7 @@
 ERR.015.008.0040= The function ''{0}'' is a valid function form, but the arguments do not match a known type signature and cannot be converted using implicit type conversions.
 ERR.015.008.0041= Expected value of type ''{0}'' but ''{1}'' is of type ''{2}'' and no implicit conversion is available.
 ERR.015.008.0042= Element ''{0}'' in ORDER BY is ambiguous and may refer to more than one element of SELECT clause.
-ERR.015.008.0043= Element ''{0}'' in ORDER BY was not found in SELECT clause.
+ERR.015.008.0043= Element ''{0}'' in ORDER BY was not found in the FROM clause.
 ERR.015.008.0045= Failed parsing {1} plan for {0}
 ERR.015.008.0046= The symbol {0} may only be used once in the FROM clause.
 ERR.015.008.0047= The symbol {0} refers to a group not defined in the FROM clause.

Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestWindowFunctions.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestWindowFunctions.java	2011-07-28 11:43:06 UTC (rev 3346)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestWindowFunctions.java	2011-07-28 19:58:08 UTC (rev 3347)
@@ -51,6 +51,46 @@
         checkNodeTypes(plan, FULL_PUSHDOWN);                                    
     }
     
+    @Test public void testWindowFunctionPushdown() throws Exception {
+    	BasicSourceCapabilities caps = getTypicalCapabilities();
+    	caps.setCapabilitySupport(Capability.ELEMENTARY_OLAP, true);
+    	caps.setCapabilitySupport(Capability.WINDOW_FUNCTION_ORDER_BY_AGGREGATES, true);
+    	caps.setCapabilitySupport(Capability.QUERY_AGGREGATES_MAX, true);
+        ProcessorPlan plan = TestOptimizer.helpPlan("select max(e1) over (order by e1) as y from pm1.g1", //$NON-NLS-1$
+                                      RealMetadataFactory.example1Cached(), null, new DefaultCapabilitiesFinder(caps),
+                                      new String[] {
+                                          "SELECT MAX(g_0.e1) OVER (ORDER BY g_0.e1) FROM pm1.g1 AS g_0"}, ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$
+    
+        checkNodeTypes(plan, FULL_PUSHDOWN);                                    
+    }
+
+    @Test public void testWindowFunctionPushdown1() throws Exception {
+    	BasicSourceCapabilities caps = getTypicalCapabilities();
+    	caps.setCapabilitySupport(Capability.ELEMENTARY_OLAP, true);
+    	caps.setCapabilitySupport(Capability.QUERY_AGGREGATES_MAX, true);
+        ProcessorPlan plan = TestOptimizer.helpPlan("select max(e1) over (order by e1) as y from pm1.g1", //$NON-NLS-1$
+                                      RealMetadataFactory.example1Cached(), null, new DefaultCapabilitiesFinder(caps),
+                                      new String[] {
+                                          "SELECT g_0.e1 FROM pm1.g1 AS g_0"}, ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$
+    
+        checkNodeTypes(plan, new int[] {
+                1,      // Access
+                0,      // DependentAccess
+                0,      // DependentSelect
+                0,      // DependentProject
+                0,      // DupRemove
+                0,      // Grouping
+                0,      // NestedLoopJoinStrategy
+                0,      // MergeJoinStrategy
+                0,      // Null
+                0,      // PlanExecution
+                1,      // Project
+                0,      // Select
+                0,      // Sort
+                0       // UnionAll
+            });                                     
+    }
+    
 	@Test public void testRanking() throws Exception {
     	String sql = "select e1, row_number() over (order by e1), rank() over (order by e1), dense_rank() over (order by e1 nulls last) from pm1.g1";
         
@@ -127,5 +167,73 @@
         helpProcess(plan, dataManager, expected);
     }
 
+    /**
+     * Note that we've optimized the ordering to be performed prior to the windowing.
+     * If we change the windowing logic to not preserve the incoming row ordering, then this optimization will need to change
+     * @throws Exception
+     */
+    @Test public void testCountDuplicates() throws Exception {
+    	String sql = "select e1, count(e1) over (order by e1) as c from pm1.g1 order by e1";
+        
+    	List<?>[] expected = new List[] {
+        		Arrays.asList("a", 2),
+        		Arrays.asList("a", 2),
+        		Arrays.asList("b", 3),
+        };
+    	
+    	HardcodedDataManager dataManager = new HardcodedDataManager();
+    	dataManager.addData("SELECT g_0.e1 AS c_0 FROM pm1.g1 AS g_0 ORDER BY c_0", new List[] {Arrays.asList("a"), Arrays.asList("a"), Arrays.asList("b")});
+        ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached(), TestOptimizer.getGenericFinder());
+        
+        helpProcess(plan, dataManager, expected);
+    }
     
+    @Test public void testEmptyOver() throws Exception {
+    	String sql = "select e1, max(e1) over () as c from pm1.g1";
+        
+    	List<?>[] expected = new List[] {
+        		Arrays.asList("a", "c"),
+        		Arrays.asList(null, "c"),
+        		Arrays.asList("a", "c"),
+        		Arrays.asList("c", "c"),
+        		Arrays.asList("b", "c"),
+        		Arrays.asList("a", "c"),
+        };
+    	
+    	FakeDataManager dataManager = new FakeDataManager();
+    	sampleData1(dataManager);
+        ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached(), TestOptimizer.getGenericFinder());
+        
+        helpProcess(plan, dataManager, expected);
+    }
+    
+    @Test public void testRowNumberMedian() throws Exception {
+    	String sql = "select e1, r, c from (select e1, row_number() over (order by e1) as r, count(*) over () c from pm1.g1) x where r = ceiling(c/2)";
+        
+    	List<?>[] expected = new List[] {
+        		Arrays.asList("a", 3, 6),
+        };
+    	
+    	FakeDataManager dataManager = new FakeDataManager();
+    	sampleData1(dataManager);
+        ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached(), TestOptimizer.getGenericFinder());
+        
+        helpProcess(plan, dataManager, expected);
+    }
+    
+    @Test public void testPartitionedRowNumber() throws Exception {
+    	String sql = "select e1, e3, row_number() over (partition by e3 order by e1) as r from pm1.g1 order by r limit 2";
+        
+    	List<?>[] expected = new List[] {
+        		Arrays.asList(null, Boolean.FALSE, 1),
+        		Arrays.asList("a", Boolean.TRUE, 1),
+        };
+    	
+    	FakeDataManager dataManager = new FakeDataManager();
+    	sampleData1(dataManager);
+        ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached(), TestOptimizer.getGenericFinder());
+        
+        helpProcess(plan, dataManager, expected);
+    }
+    
 }



More information about the teiid-commits mailing list