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 @@
| <NOT: "not">
| <NULL: "null">
| <OF: "of">
+| <OFFSET: "offset">
| <OLD: "old">
| <ON: "on">
| <ONLY: "only">
@@ -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>::=
-<INSERT> <INTO> <link
linkend="prod2">id</link> ( <link
linkend="prod47">columnList</link> )? ( ( <VALUES>
<link linkend="prod48">rowValues</link> ) | ( <link
linkend="prod13">queryExpression</link> ) ) ( <link
linkend="prod45">option</link>
)?</para></entry></row>
+<INSERT> <INTO> <link
linkend="prod2">id</link> ( <link
linkend="prod47">columnList</link> )? ( ( <VALUES>
<LPAREN> <link linkend="prod48">expressionList</link>
<RPAREN> ) | ( <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>::=
<LPAREN> <link linkend="prod2">id</link> (
<COMMA> <link linkend="prod2">id</link> )*
<RPAREN></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>::=
-<LPAREN> <link linkend="prod24">expression</link> (
<COMMA> <link linkend="prod24">expression</link> )*
<RPAREN></para></entry></row>
+<link linkend="prod24">expression</link> ( <COMMA>
<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>::=
<ALL_IN_GROUP></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>::=
-<XMLAGG> <LPAREN> <link
linkend="prod24">expression</link> ( <link
linkend="prod53">orderby</link> )?
<RPAREN></para></entry></row>
+( <XMLAGG> | <ARRAY_AGG> ) <LPAREN> <link
linkend="prod24">expression</link> ( <link
linkend="prod53">orderby</link> )? <RPAREN> <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>::=
-<ARRAY_AGG> <LPAREN> <link
linkend="prod24">expression</link> ( <link
linkend="prod53">orderby</link> )?
<RPAREN></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> <LPAREN>
<FOR> <link linkend="prod65">derivedColumn</link> (
<COMMA> <link linkend="prod65">derivedColumn</link> )*
( <ID> <link linkend="prod69">charVal</link> )? ( (
<ID> <link linkend="prod69">charVal</link> ) )? (
<ID> )? ( ( <ID> <link
linkend="prod2">id</link> ) )? ( <link
linkend="prod53">orderby</link> )?
<RPAREN></para></entry></row>
+<link linkend="prod11">nonReserved</link> <LPAREN>
<FOR> <link linkend="prod65">derivedColumn</link> (
<COMMA> <link linkend="prod65">derivedColumn</link> )*
( <ID> <link linkend="prod69">charVal</link> )? ( (
<ID> <link linkend="prod69">charVal</link> ) )? (
<ID> )? ( ( <ID> <link
linkend="prod2">id</link> ) )? ( <link
linkend="prod53">orderby</link> )? <RPAREN> <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>
<LPAREN> <STAR> <RPAREN> ) | ( ( <link
linkend="prod11">nonReserved</link> | <ANY> |
<SOME> ) <LPAREN> ( <DISTINCT> |
<ALL> )? <link linkend="prod24">expression</link>
<RPAREN> ) )</para></entry></row>
+( ( ( <link linkend="prod11">nonReserved</link>
<LPAREN> <STAR> <RPAREN> ) | ( <link
linkend="prod11">nonReserved</link> <LPAREN>
<RPAREN> ) | ( ( <link
linkend="prod11">nonReserved</link> | <ANY> |
<SOME> ) <LPAREN> ( <DISTINCT> |
<ALL> )? <link linkend="prod24">expression</link>
<RPAREN> ) ) <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>::=
+( <FILTER> <LPAREN> <WHERE> <link
linkend="prod71">booleanPrimary</link> <RPAREN>
)?</para></entry></row>
+<row>
<entry align="right" valign="top"><para><anchor
id="prod59" xreflabel="from"/>from</para></entry>
<entry align="left" valign="top"><para>::=
-<FROM> ( <link linkend="prod71">tableReference</link>
( <COMMA> <link linkend="prod71">tableReference</link>
)* )</para></entry></row>
+<FROM> ( <link linkend="prod72">tableReference</link>
( <COMMA> <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>::=
-( ( <LBRACE> <link
linkend="prod11">nonReserved</link> <link
linkend="prod72">joinedTable</link> <RBRACE> ) | <link
linkend="prod72">joinedTable</link>
)</para></entry></row>
+( ( <LBRACE> <link
linkend="prod11">nonReserved</link> <link
linkend="prod73">joinedTable</link> <RBRACE> ) | <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>::=
-( ( <CROSS> | <UNION> ) <JOIN> <link
linkend="prod73">tablePrimary</link>
)</para></entry></row>
+( ( <CROSS> | <UNION> ) <JOIN> <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>::=
-( ( ( <RIGHT> ( <OUTER> )? ) | ( <LEFT> (
<OUTER> )? ) | ( <FULL> ( <OUTER> )? ) |
<INNER> )? <JOIN> <link
linkend="prod71">tableReference</link> <ON> <link
linkend="prod35">criteria</link>
)</para></entry></row>
+( ( ( <RIGHT> ( <OUTER> )? ) | ( <LEFT> (
<OUTER> )? ) | ( <FULL> ( <OUTER> )? ) |
<INNER> )? <JOIN> <link
linkend="prod72">tableReference</link> <ON> <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> | ( <LPAREN>
<link linkend="prod72">joinedTable</link> <RPAREN> ) )
( ( <MAKEDEP> ) | ( <MAKENOTDEP> )
)?</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> | ( <LPAREN>
<link linkend="prod73">joinedTable</link> <RPAREN> ) )
( ( <MAKEDEP> ) | ( <MAKENOTDEP> )
)?</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>::=
<XMLSERIALIZE> <LPAREN> ( <link
linkend="prod11">nonReserved</link> )? <link
linkend="prod24">expression</link> ( <AS> (
<STRING> | <VARCHAR> | <CLOB> ) )?
<RPAREN></para></entry></row>
<row>
@@ -657,39 +659,39 @@
<entry align="left" valign="top"><para>::=
<ID></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>::=
<ID> <LPAREN> <link
linkend="prod24">expression</link> <link
linkend="prod11">nonReserved</link> <link
linkend="prod42">createElementsWithTypes</link> <RPAREN>
( <AS> )? <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>::=
-<ID> <LPAREN> <link
linkend="prod24">expression</link> <link
linkend="prod11">nonReserved</link> <link
linkend="prod82">textColumn</link> ( <COMMA> <link
linkend="prod82">textColumn</link> )* ( <ID> <link
linkend="prod69">charVal</link> )? ( ( <ESCAPE> <link
linkend="prod69">charVal</link> ) | ( <ID> <link
linkend="prod69">charVal</link> ) )? ( <ID> ( <link
linkend="prod83">intVal</link> )? )? ( <ID> <link
linkend="prod83">intVal</link> )? <RPAREN> (
<AS> )? <link
linkend="prod2">id</link></para></entry></row>
+<ID> <LPAREN> <link
linkend="prod24">expression</link> <link
linkend="prod11">nonReserved</link> <link
linkend="prod83">textColumn</link> ( <COMMA> <link
linkend="prod83">textColumn</link> )* ( <ID> <link
linkend="prod69">charVal</link> )? ( ( <ESCAPE> <link
linkend="prod69">charVal</link> ) | ( <ID> <link
linkend="prod69">charVal</link> ) )? ( <ID> ( <link
linkend="prod84">intVal</link> )? )? ( <ID> <link
linkend="prod84">intVal</link> )? <RPAREN> (
<AS> )? <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> ( <ID> <link
linkend="prod83">intVal</link>
)?</para></entry></row>
+<link linkend="prod2">id</link> <link
linkend="prod38">dataType</link> ( <ID> <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>::=
-<XMLQUERY> <LPAREN> ( <link
linkend="prod85">xmlNamespaces</link> <COMMA> )? <link
linkend="prod1">stringVal</link> ( <ID> <link
linkend="prod65">derivedColumn</link> ( <COMMA> <link
linkend="prod65">derivedColumn</link> )* )? ( ( <NULL> |
<link linkend="prod11">nonReserved</link> ) <ON>
<link linkend="prod11">nonReserved</link> )?
<RPAREN></para></entry></row>
+<XMLQUERY> <LPAREN> ( <link
linkend="prod86">xmlNamespaces</link> <COMMA> )? <link
linkend="prod1">stringVal</link> ( <ID> <link
linkend="prod65">derivedColumn</link> ( <COMMA> <link
linkend="prod65">derivedColumn</link> )* )? ( ( <NULL> |
<link linkend="prod11">nonReserved</link> ) <ON>
<link linkend="prod11">nonReserved</link> )?
<RPAREN></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>::=
-<XMLTABLE> <LPAREN> ( <link
linkend="prod85">xmlNamespaces</link> <COMMA> )? <link
linkend="prod1">stringVal</link> ( <ID> <link
linkend="prod65">derivedColumn</link> ( <COMMA> <link
linkend="prod65">derivedColumn</link> )* )? ( <ID>
<link linkend="prod86">xmlColumn</link> ( <COMMA>
<link linkend="prod86">xmlColumn</link> )* )? <RPAREN>
( <AS> )? <link
linkend="prod2">id</link></para></entry></row>
+<XMLTABLE> <LPAREN> ( <link
linkend="prod86">xmlNamespaces</link> <COMMA> )? <link
linkend="prod1">stringVal</link> ( <ID> <link
linkend="prod65">derivedColumn</link> ( <COMMA> <link
linkend="prod65">derivedColumn</link> )* )? ( <ID>
<link linkend="prod87">xmlColumn</link> ( <COMMA>
<link linkend="prod87">xmlColumn</link> )* )? <RPAREN>
( <AS> )? <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> ( ( <FOR> <link
linkend="prod11">nonReserved</link> ) | ( <link
linkend="prod38">dataType</link> ( <DEFAULT_KEYWORD>
<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>::=
<INTEGERVAL></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>::=
( <TABLE> )? <LPAREN> ( <link
linkend="prod13">queryExpression</link> | <link
linkend="prod15">storedProcedure</link> ) <RPAREN> (
<AS> )? <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>::=
( <ID> ( ( <AS> )? <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> ( <OR>
<link linkend="prod88">compoundCritAnd</link>
)*</para></entry></row>
+<link linkend="prod89">compoundCritAnd</link> ( <OR>
<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> ( <AND>
<link linkend="prod89">notCrit</link>
)*</para></entry></row>
+<link linkend="prod90">notCrit</link> ( <AND>
<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>::=
-( <NOT> )? <link
linkend="prod90">booleanPrimary</link></para></entry></row>
+( <NOT> )? <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>::=
-<GROUP> <BY> ( <link
linkend="prod102">groupByItem</link> ( <COMMA> <link
linkend="prod102">groupByItem</link> )*
)</para></entry></row>
+<GROUP> <BY> <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>::=
<HAVING> <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>::=
-<ORDER> <BY> <link
linkend="prod103">sortSpecification</link> ( <COMMA>
<link linkend="prod103">sortSpecification</link>
)*</para></entry></row>
+<ORDER> <BY> <link
linkend="prod102">sortSpecification</link> ( <COMMA>
<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> ( <ASC> |
<DESC> )? ( <link linkend="prod11">nonReserved</link>
<link linkend="prod11">nonReserved</link>
)?</para></entry></row>
+<link linkend="prod103">sortKey</link> ( <ASC> |
<DESC> )? ( <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> | <QMARK>
)</para></entry></row>
+<row>
<entry align="right" valign="top"><para><anchor
id="prod54" xreflabel="limit"/>limit</para></entry>
<entry align="left" valign="top"><para>::=
-<LIMIT> ( <INTEGERVAL> | <QMARK> ) (
<COMMA> ( <INTEGERVAL> | <QMARK> )
)?</para></entry></row>
+( ( <LIMIT> <link linkend="prod104">intParam</link> (
<COMMA> <link linkend="prod104">intParam</link> )? ) |
( <OFFSET> <link linkend="prod104">intParam</link> (
<ROW> | <ROWS> ) ( <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>::=
+<FETCH> <link linkend="prod11">nonReserved</link> (
<link linkend="prod104">intParam</link> )? ( <ROW> |
<ROWS> ) <ONLY></para></entry></row>
+<row>
<entry align="right" valign="top"><para><anchor
id="prod45" xreflabel="option"/>option</para></entry>
<entry align="left" valign="top"><para>::=
<OPTION> ( <MAKEDEP> <link
linkend="prod2">id</link> ( <COMMA> <link
linkend="prod2">id</link> )* | <MAKENOTDEP> <link
linkend="prod2">id</link> ( <COMMA> <link
linkend="prod2">id</link> )* | <NOCACHE> ( <link
linkend="prod2">id</link> ( <COMMA> <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> (
<CONCAT_OP> <link
linkend="prod105">plusExpression</link> )*
)</para></entry></row>
+( <link linkend="prod106">plusExpression</link> (
<CONCAT_OP> <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>::=
( <PLUS> | <MINUS> )</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>::=
( <STAR> | <SLASH> )</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>::=
-( <QMARK> | <POS_REF> | <link
linkend="prod110">literal</link> | ( <LBRACE> <link
linkend="prod11">nonReserved</link> <link
linkend="prod111">function</link> <RBRACE> ) | ( <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> ) | ( <ID> (
<LSBRACE> <link linkend="prod83">intVal</link>
<RSBRACE> )? ) | <link
linkend="prod100">subquery</link> | ( <LPAREN> <link
linkend="prod24">expression</link> <RPAREN> (
<LSBRACE> <link linkend="prod83">intVal</link>
<RSBRACE> )? ) | <link
linkend="prod112">searchedCaseExpression</link> | <link
linkend="prod113">caseExpression</link>
)</para></entry></row>
+( <QMARK> | <POS_REF> | <link
linkend="prod111">literal</link> | ( <LBRACE> <link
linkend="prod11">nonReserved</link> <link
linkend="prod112">function</link> <RBRACE> ) | ( <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> ) | ( <ID> (
<LSBRACE> <link linkend="prod84">intVal</link>
<RSBRACE> )? ) | <link
linkend="prod100">subquery</link> | ( <LPAREN> <link
linkend="prod24">expression</link> <RPAREN> (
<LSBRACE> <link!
linkend="prod84">intVal</link> <RSBRACE> )? ) |
<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>::=
+<OVER> <LPAREN> ( <PARTITION>
<BY> <link linkend="prod48">expressionList</link> )? (
<link linkend="prod53">orderby</link> )?
<RPAREN></para></entry></row>
+<row>
+<entry align="right" valign="top"><para><anchor
id="prod115"
xreflabel="caseExpression"/>caseExpression</para></entry>
+<entry align="left" valign="top"><para>::=
<CASE> <link linkend="prod24">expression</link> (
<WHEN> <link linkend="prod24">expression</link>
<THEN> <link linkend="prod24">expression</link> )+ (
<ELSE> <link linkend="prod24">expression</link> )?
<END></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>::=
<CASE> ( <WHEN> <link
linkend="prod35">criteria</link> <THEN> <link
linkend="prod24">expression</link> )+ ( <ELSE> <link
linkend="prod24">expression</link> )?
<END></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>::=
-( ( <CONVERT> <LPAREN> <link
linkend="prod24">expression</link> <COMMA> <link
linkend="prod38">dataType</link> <RPAREN> ) | (
<CAST> <LPAREN> <link
linkend="prod24">expression</link> <AS> <link
linkend="prod38">dataType</link> <RPAREN> ) | ( <link
linkend="prod11">nonReserved</link> <LPAREN> <link
linkend="prod24">expression</link> <COMMA> <link
linkend="prod114">stringConstant</link> <RPAREN> ) | (
<link linkend="prod11">nonReserved</link> <LPAREN>
<link linkend="prod115">intervalType</link> <COMMA>
<link linkend="prod24">expression</link> <COMMA>
<link linkend="prod24">expression</link> <RPAREN> ) |
<link linkend="prod116">queryString</link> | ( (
<LEFT> | <RIGHT> | <CHAR> | <USER>
| <YEAR> | <MONTH> | <HOUR> |
<MINUTE> | <SECOND> | <XMLCONCAT> |
<XMLCOMMENT> ) <LPAREN> ( <link
linkend="prod24">expression</link> !
( <COMMA> <link linkend="prod24">expression</link> )*
)? <RPAREN> ) | ( ( <INSERT> ) <LPAREN> (
<link linkend="prod24">expression</link> ( <COMMA>
<link linkend="prod24">expression</link> )* )?
<RPAREN> ) | ( ( <TRANSLATE> ) <LPAREN> (
<link linkend="prod24">expression</link> ( <COMMA>
<link linkend="prod24">expression</link> )* )?
<RPAREN> ) | <link linkend="prod117">xmlParse</link> |
<link linkend="prod118">xmlElement</link> | ( <XMLPI>
<LPAREN> ( <ID> <link
linkend="prod119">idExpression</link> | <link
linkend="prod119">idExpression</link> ) ( <COMMA>
<link linkend="prod24">expression</link> )? <RPAREN> )
| <link linkend="prod120">xmlForest</link> | <link
linkend="prod81">xmlSerialize</link> | <link
linkend="prod84">xmlQuery</link> | ( <link
linkend="prod2">id</link> <LPAREN> ( <link
linkend="prod24">expression</link> ( <COMMA> <link
linkend="prod24">expression</link> )*!
)? <RPAREN> ) )</para></entry></row>
+( ( <CONVERT> <LPAREN> <link
linkend="prod24">expression</link> <COMMA> <link
linkend="prod38">dataType</link> <RPAREN> ) | (
<CAST> <LPAREN> <link
linkend="prod24">expression</link> <AS> <link
linkend="prod38">dataType</link> <RPAREN> ) | ( <link
linkend="prod11">nonReserved</link> <LPAREN> <link
linkend="prod24">expression</link> <COMMA> <link
linkend="prod116">stringConstant</link> <RPAREN> ) | (
<link linkend="prod11">nonReserved</link> <LPAREN>
<link linkend="prod117">intervalType</link> <COMMA>
<link linkend="prod24">expression</link> <COMMA>
<link linkend="prod24">expression</link> <RPAREN> ) |
<link linkend="prod118">queryString</link> | ( (
<LEFT> | <RIGHT> | <CHAR> | <USER>
| <YEAR> | <MONTH> | <HOUR> |
<MINUTE> | <SECOND> | <XMLCONCAT> |
<XMLCOMMENT> ) <LPAREN> ( <link
linkend="prod48">expressionList</li!
nk> )? <RPAREN> ) | ( ( <TRANSLATE> |
<INSERT> ) <LPAREN> ( <link
linkend="prod48">expressionList</link> )? <RPAREN> ) |
<link linkend="prod119">xmlParse</link> | <link
linkend="prod120">xmlElement</link> | ( <XMLPI>
<LPAREN> ( <ID> <link
linkend="prod121">idExpression</link> | <link
linkend="prod121">idExpression</link> ) ( <COMMA>
<link linkend="prod24">expression</link> )? <RPAREN> )
| <link linkend="prod122">xmlForest</link> | <link
linkend="prod82">xmlSerialize</link> | <link
linkend="prod85">xmlQuery</link> | ( <link
linkend="prod2">id</link> <LPAREN> ( <link
linkend="prod48">expressionList</link> )? <RPAREN> )
)</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>::=
<XMLPARSE> <LPAREN> <link
linkend="prod11">nonReserved</link> <link
linkend="prod24">expression</link> ( <link
linkend="prod11">nonReserved</link> )?
<RPAREN></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> <LPAREN>
<link linkend="prod24">expression</link> ( <COMMA>
<link linkend="prod65">derivedColumn</link> )*
<RPAREN></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>::=
-<XMLELEMENT> <LPAREN> ( <ID> <link
linkend="prod2">id</link> | <link
linkend="prod2">id</link> ) ( <COMMA> <link
linkend="prod85">xmlNamespaces</link> )? ( <COMMA>
<link linkend="prod121">xmlAttributes</link> )? (
<COMMA> <link linkend="prod24">expression</link> )*
<RPAREN></para></entry></row>
+<XMLELEMENT> <LPAREN> ( <ID> <link
linkend="prod2">id</link> | <link
linkend="prod2">id</link> ) ( <COMMA> <link
linkend="prod86">xmlNamespaces</link> )? ( <COMMA>
<link linkend="prod123">xmlAttributes</link> )? (
<COMMA> <link linkend="prod24">expression</link> )*
<RPAREN></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>::=
<XMLATTRIBUTES> <LPAREN> <link
linkend="prod65">derivedColumn</link> ( <COMMA> <link
linkend="prod65">derivedColumn</link> )*
<RPAREN></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>::=
-<XMLFOREST> <LPAREN> ( <link
linkend="prod85">xmlNamespaces</link> <COMMA> )? <link
linkend="prod65">derivedColumn</link> ( <COMMA> <link
linkend="prod65">derivedColumn</link> )*
<RPAREN></para></entry></row>
+<XMLFOREST> <LPAREN> ( <link
linkend="prod86">xmlNamespaces</link> <COMMA> )? <link
linkend="prod65">derivedColumn</link> ( <COMMA> <link
linkend="prod65">derivedColumn</link> )*
<RPAREN></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>::=
-<XMLNAMESPACES> <LPAREN> <link
linkend="prod122">namespaceItem</link> ( <COMMA> <link
linkend="prod122">namespaceItem</link> )*
<RPAREN></para></entry></row>
+<XMLNAMESPACES> <LPAREN> <link
linkend="prod124">namespaceItem</link> ( <COMMA> <link
linkend="prod124">namespaceItem</link> )*
<RPAREN></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> <AS>
<link linkend="prod2">id</link>
)</para></entry></row>
<row>
@@ -873,7 +883,7 @@
<entry align="left" valign="top"><para>::=
( <DEFAULT_KEYWORD> <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> |
<INTEGERVAL> | <FLOATVAL> | <FALSE> |
<TRUE> | <UNKNOWN> | <NULL> | ( (
<BOOLEANTYPE> | <TIMESTAMPTYPE> | <DATETYPE> |
<TIMETYPE> ) <link linkend="prod1">stringVal</link>
<RBRACE> ) )</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
<COLUMN>, ... [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([<NSP>,]
xquery-expression [<PASSING>] [COLUMNS <COLUMN>, ... )] 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 '<a
id="1"/>') 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
<COLUMN>, ...) 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
<COLUMN>, ... [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([<NSP>,]
xquery-expression [<PASSING>] [COLUMNS <COLUMN>, ... )] 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 '<a
id="1"/>') 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
<COLUMN>, ...) 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);
+ }
+
}