db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rhille...@apache.org
Subject svn commit: r1200492 - in /db/derby/code/trunk/java/engine/org/apache/derby: iapi/sql/execute/ impl/sql/compile/ impl/sql/execute/ loc/
Date Thu, 10 Nov 2011 19:31:57 GMT
Author: rhillegas
Date: Thu Nov 10 19:31:56 2011
New Revision: 1200492

URL: http://svn.apache.org/viewvc?rev=1200492&view=rev
Log:
DERBY-5488: Add JDBC limit/offset escape syntax.

Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/execute/ResultSetFactory.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CreateViewNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CursorNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/FromBaseTable.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/FromSubquery.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/InsertNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/IntersectOrExceptNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/NormalizeResultSetNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ProjectRestrictNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ResultSetNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/RowCountNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/RowResultSetNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SelectNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SetOperatorNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SubqueryNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/UnionNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/GenericResultSetFactory.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/RowCountResultSet.java
    db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/execute/ResultSetFactory.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/execute/ResultSetFactory.java?rev=1200492&r1=1200491&r2=1200492&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/execute/ResultSetFactory.java
(original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/execute/ResultSetFactory.java
Thu Nov 10 19:31:56 2011
@@ -1638,8 +1638,8 @@ public interface ResultSetFactory {
 	 *                        allocation operation
 	 * @param resultSetNumber The resultSetNumber for the ResultSet
 	 * @param offsetMethod   The OFFSET parameter was specified
-	 * @param fetchFirstMethod The FETCH FIRST/NEXT parameter was
-	 *                        specified
+	 * @param fetchFirstMethod The FETCH FIRST/NEXT parameter was specified
+	 * @param hasJDBClimitClause True if the offset/fetchFirst clauses were added by JDBC LIMIT
escape syntax
 	 * @param optimizerEstimatedRowCount
 	 *                        Estimated total # of rows by optimizer
 	 * @param optimizerEstimatedCost
@@ -1653,6 +1653,7 @@ public interface ResultSetFactory {
 		int resultSetNumber,
 		GeneratedMethod offsetMethod,
 		GeneratedMethod fetchFirstMethod,
+        boolean hasJDBClimitClause,
 		double optimizerEstimatedRowCount,
 		double optimizerEstimatedCost) throws StandardException;
 

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CreateViewNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CreateViewNode.java?rev=1200492&r1=1200491&r2=1200492&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CreateViewNode.java
(original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CreateViewNode.java
Thu Nov 10 19:31:56 2011
@@ -71,6 +71,7 @@ public class CreateViewNode extends DDLS
 	private OrderByList orderByList;
     private ValueNode   offset;
     private ValueNode   fetchFirst;
+    private boolean hasJDBClimitClause; // true if using JDBC limit/offset escape syntax
 
 	/**
 	 * Initializer for a CreateViewNode
@@ -85,6 +86,7 @@ public class CreateViewNode extends DDLS
 	 * @param orderCols         ORDER BY list
      * @param offset            OFFSET if any, or null
      * @param fetchFirst        FETCH FIRST if any, or null
+	 * @param hasJDBClimitClause True if the offset/fetchFirst clauses come from JDBC limit/offset
escape syntax
 	 *
 	 * @exception StandardException		Thrown on error
 	 */
@@ -96,7 +98,8 @@ public class CreateViewNode extends DDLS
 				   Object qeText,
                    Object orderCols,
                    Object offset,
-                   Object fetchFirst)
+                   Object fetchFirst,
+                   Object hasJDBClimitClause)
 		throws StandardException
 	{
 		initAndCheck(newObjectName);
@@ -107,6 +110,7 @@ public class CreateViewNode extends DDLS
 		this.orderByList = (OrderByList)orderCols;
         this.offset = (ValueNode)offset;
         this.fetchFirst = (ValueNode)fetchFirst;
+        this.hasJDBClimitClause = (hasJDBClimitClause == null) ? false : ((Boolean) hasJDBClimitClause).booleanValue();
 
 		implicitCreateSchema = true;
 	}
@@ -430,4 +434,7 @@ public class CreateViewNode extends DDLS
     public ValueNode getFetchFirst() {
         return fetchFirst;
     }
+    
+    public boolean hasJDBClimitClause() { return hasJDBClimitClause; }
+
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CursorNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CursorNode.java?rev=1200492&r1=1200491&r2=1200492&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CursorNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/CursorNode.java Thu
Nov 10 19:31:56 2011
@@ -55,6 +55,7 @@ public class CursorNode extends DMLState
 	private OrderByList	orderByList;
 	private ValueNode   offset;     // <result offset clause> value
 	private ValueNode   fetchFirst; // <fetch first clause> value
+    private boolean hasJDBClimitClause; // true if using JDBC limit/offset escape syntax
 	private String		statementType;
 	private int		updateMode;
 	private boolean		needTarget;
@@ -89,6 +90,7 @@ public class CursorNode extends DMLState
 	 *			order by list
 	 * @param offset The value of a <result offset clause> if present
 	 * @param fetchFirst The value of a <fetch first clause> if present
+	 * @param hasJDBClimitClause True if the offset/fetchFirst clauses come from JDBC limit/offset
escape syntax
 	 * @param updateMode	The user-specified update mode for the cursor,
 	 *			for example, CursorNode.READ_ONLY
 	 * @param updatableColumns The list of updatable columns specified by
@@ -105,6 +107,7 @@ public class CursorNode extends DMLState
 		Object orderByList,
 		Object offset,
 		Object fetchFirst,
+        Object hasJDBClimitClause,
 		Object updateMode,
 		Object updatableColumns)
 	{
@@ -114,6 +117,7 @@ public class CursorNode extends DMLState
 		this.orderByList = (OrderByList) orderByList;
 		this.offset = (ValueNode)offset;
 		this.fetchFirst = (ValueNode)fetchFirst;
+        this.hasJDBClimitClause = (hasJDBClimitClause == null) ? false : ((Boolean) hasJDBClimitClause).booleanValue();
 
 		this.updateMode = ((Integer) updateMode).intValue();
 		this.updatableColumns = (Vector) updatableColumns;
@@ -582,7 +586,7 @@ public class CursorNode extends DMLState
 			orderByList = null;
 		}
 
-        resultSet.pushOffsetFetchFirst(offset, fetchFirst);
+        resultSet.pushOffsetFetchFirst( offset, fetchFirst, hasJDBClimitClause );
 
         super.optimizeStatement();
 

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/FromBaseTable.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/FromBaseTable.java?rev=1200492&r1=1200491&r2=1200492&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/FromBaseTable.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/FromBaseTable.java Thu
Nov 10 19:31:56 2011
@@ -2287,6 +2287,7 @@ public class FromBaseTable extends FromT
                     cvn.getOrderByList(),
                     cvn.getOffset(),
                     cvn.getFetchFirst(),
+                    new Boolean( cvn.hasJDBClimitClause() ),
 					(correlationName != null) ? 
                         correlationName : getOrigTableName().getTableName(), 
 					resultColumns,

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/FromSubquery.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/FromSubquery.java?rev=1200492&r1=1200491&r2=1200492&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/FromSubquery.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/FromSubquery.java Thu
Nov 10 19:31:56 2011
@@ -50,6 +50,7 @@ public class FromSubquery extends FromTa
 	private OrderByList orderByList;
     private ValueNode offset;
     private ValueNode fetchFirst;
+    private boolean hasJDBClimitClause; // true if using JDBC limit/offset escape syntax
 
 	/**
 	 * DERBY-3270: If this subquery represents an expanded view, this holds the
@@ -64,6 +65,7 @@ public class FromSubquery extends FromTa
 	 * @param orderByList   ORDER BY list if any, or null
      * @param offset        OFFSET if any, or null
      * @param fetchFirst    FETCH FIRST if any, or null
+	 * @param hasJDBClimitClause True if the offset/fetchFirst clauses come from JDBC limit/offset
escape syntax
 	 * @param correlationName	The correlation name
 	 * @param derivedRCL		The derived column list
 	 * @param tableProperties	Properties list associated with the table
@@ -73,6 +75,7 @@ public class FromSubquery extends FromTa
 					Object orderByList,
                     Object offset,
                     Object fetchFirst,
+                    Object hasJDBClimitClause,
 					Object correlationName,
 				 	Object derivedRCL,
 					Object tableProperties)
@@ -82,6 +85,7 @@ public class FromSubquery extends FromTa
 		this.orderByList = (OrderByList)orderByList;
         this.offset = (ValueNode)offset;
         this.fetchFirst = (ValueNode)fetchFirst;
+        this.hasJDBClimitClause = (hasJDBClimitClause == null) ? false : ((Boolean) hasJDBClimitClause).booleanValue();
 		resultColumns = (ResultColumnList) derivedRCL;
 	}
 
@@ -390,7 +394,7 @@ public class FromSubquery extends FromTa
 			orderByList = null;
 		}
 
-        subquery.pushOffsetFetchFirst(offset, fetchFirst);
+        subquery.pushOffsetFetchFirst( offset, fetchFirst, hasJDBClimitClause );
 
 		/* We want to chop out the FromSubquery from the tree and replace it 
 		 * with a ProjectRestrictNode.  One complication is that there may be 

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/InsertNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/InsertNode.java?rev=1200492&r1=1200491&r2=1200492&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/InsertNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/InsertNode.java Thu
Nov 10 19:31:56 2011
@@ -113,6 +113,7 @@ public final class InsertNode extends DM
 	private     OrderByList         orderByList;
     private     ValueNode           offset;
     private     ValueNode           fetchFirst;
+    private     boolean           hasJDBClimitClause; // true if using JDBC limit/offset
escape syntax
 
 	protected   RowLocation[] 		autoincRowLocation;
 	/**
@@ -127,8 +128,10 @@ public final class InsertNode extends DM
 	 * @param queryExpression	The query expression that will generate
 	 *				the rows to insert into the given table
 	 * @param targetProperties	The properties specified on the target table
-     * @param orderByList The order by list for the source result set, null if
-	 *			no order by list
+     * @param orderByList The order by list for the source result set, null if no order by
list
+	 * @param offset The value of a <result offset clause> if present
+	 * @param fetchFirst The value of a <fetch first clause> if present
+	 * @param hasJDBClimitClause True if the offset/fetchFirst clauses come from JDBC limit/offset
escape syntax
 	 */
 
 	public void init(
@@ -138,7 +141,8 @@ public final class InsertNode extends DM
 			Object targetProperties,
             Object orderByList,
             Object offset,
-            Object fetchFirst)
+            Object fetchFirst,
+            Object hasJDBClimitClause)
 	{
 		/* statementType gets set in super() before we've validated
 		 * any properties, so we've kludged the code to get the
@@ -155,6 +159,7 @@ public final class InsertNode extends DM
 		this.orderByList = (OrderByList) orderByList;
         this.offset = (ValueNode)offset;
         this.fetchFirst = (ValueNode)fetchFirst;
+        this.hasJDBClimitClause = (hasJDBClimitClause == null) ? false : ((Boolean) hasJDBClimitClause).booleanValue();
 
 		/* Remember that the query expression is the source to an INSERT */
 		getResultSetNode().setInsertSource();
@@ -850,7 +855,7 @@ public final class InsertNode extends DM
 			orderByList = null;
 		}
 
-        resultSet.pushOffsetFetchFirst(offset, fetchFirst);
+        resultSet.pushOffsetFetchFirst( offset, fetchFirst, hasJDBClimitClause );
 
 		super.optimizeStatement();
         

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/IntersectOrExceptNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/IntersectOrExceptNode.java?rev=1200492&r1=1200491&r2=1200492&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/IntersectOrExceptNode.java
(original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/IntersectOrExceptNode.java
Thu Nov 10 19:31:56 2011
@@ -335,6 +335,7 @@ public class IntersectOrExceptNode exten
                 newRcl,
                 offset,
                 fetchFirst,
+                new Boolean( hasJDBClimitClause ),
                 getContextManager());
         }
 

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/NormalizeResultSetNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/NormalizeResultSetNode.java?rev=1200492&r1=1200491&r2=1200492&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/NormalizeResultSetNode.java
(original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/NormalizeResultSetNode.java
Thu Nov 10 19:31:56 2011
@@ -704,9 +704,10 @@ public class NormalizeResultSetNode exte
      *
      * @param offset    the OFFSET, if any
      * @param fetchFirst the OFFSET FIRST, if any
+     * @param hasJDBClimitClause true if the clauses were added by (and have the semantics
of) a JDBC limit clause
      */
-    void pushOffsetFetchFirst(ValueNode offset, ValueNode fetchFirst)
+    void pushOffsetFetchFirst( ValueNode offset, ValueNode fetchFirst, boolean hasJDBClimitClause
)
     {
-        childResult.pushOffsetFetchFirst(offset, fetchFirst);
+        childResult.pushOffsetFetchFirst( offset, fetchFirst, hasJDBClimitClause );
     }
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ProjectRestrictNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ProjectRestrictNode.java?rev=1200492&r1=1200491&r2=1200492&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ProjectRestrictNode.java
(original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ProjectRestrictNode.java
Thu Nov 10 19:31:56 2011
@@ -1892,9 +1892,10 @@ public class ProjectRestrictNode extends
      *
      * @param offset    the OFFSET, if any
      * @param fetchFirst the OFFSET FIRST, if any
+     * @param hasJDBClimitClause true if the clauses were added by (and have the semantics
of) a JDBC limit clause
      */
-    void pushOffsetFetchFirst(ValueNode offset, ValueNode fetchFirst)
+    void pushOffsetFetchFirst( ValueNode offset, ValueNode fetchFirst, boolean hasJDBClimitClause
)
     {
-        childResult.pushOffsetFetchFirst(offset, fetchFirst);
+        childResult.pushOffsetFetchFirst( offset, fetchFirst, hasJDBClimitClause );
     }
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ResultSetNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ResultSetNode.java?rev=1200492&r1=1200491&r2=1200492&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ResultSetNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/ResultSetNode.java Thu
Nov 10 19:31:56 2011
@@ -1671,8 +1671,9 @@ public abstract class ResultSetNode exte
      *
      * @param offset    the OFFSET, if any
      * @param fetchFirst the OFFSET FIRST, if any
+     * @param hasJDBClimitClause true if the clauses were added by (and have the semantics
of) a JDBC limit clause
      */
-    void pushOffsetFetchFirst(ValueNode offset, ValueNode fetchFirst)
+    void pushOffsetFetchFirst( ValueNode offset, ValueNode fetchFirst, boolean hasJDBClimitClause
)
     {
         if (SanityManager.DEBUG)
         {

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/RowCountNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/RowCountNode.java?rev=1200492&r1=1200491&r2=1200492&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/RowCountNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/RowCountNode.java Thu
Nov 10 19:31:56 2011
@@ -48,6 +48,10 @@ public final class RowCountNode extends 
      * If not null, this represents the value of a <fetch first clause>.
      */
     private ValueNode fetchFirst;
+    /**
+     * True if the offset/fetchFirst clauses were added by JDBC LIMIT syntax.
+     */
+    private boolean hasJDBClimitClause;
 
 
     /**
@@ -58,7 +62,8 @@ public final class RowCountNode extends 
     public void init(Object childResult,
                      Object rcl,
                      Object offset,
-                     Object fetchFirst)
+                     Object fetchFirst,
+                     Object hasJDBClimitClause)
         throws StandardException {
 
         init(childResult, null);
@@ -66,6 +71,7 @@ public final class RowCountNode extends 
 
         this.offset = (ValueNode)offset;
         this.fetchFirst = (ValueNode)fetchFirst;
+        this.hasJDBClimitClause = (hasJDBClimitClause == null) ? false : ((Boolean) hasJDBClimitClause).booleanValue();
     }
 
 
@@ -112,14 +118,16 @@ public final class RowCountNode extends 
             mb.pushNull(ClassName.GeneratedMethod);
         }
 
-        mb.push(costEstimate.rowCount()); // arg6
-        mb.push(costEstimate.getEstimatedCost()); // arg7
+        mb.push( hasJDBClimitClause );  // arg6
+
+        mb.push(costEstimate.rowCount()); // arg7
+        mb.push(costEstimate.getEstimatedCost()); // arg8
 
         mb.callMethod(VMOpcode.INVOKEINTERFACE,
                       (String) null,
                       "getRowCountResultSet",
                       ClassName.NoPutResultSet,
-                      7);
+                      8);
     }
 
 

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/RowResultSetNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/RowResultSetNode.java?rev=1200492&r1=1200491&r2=1200492&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/RowResultSetNode.java
(original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/RowResultSetNode.java
Thu Nov 10 19:31:56 2011
@@ -63,6 +63,7 @@ public class RowResultSetNode extends Fr
 	OrderByList	 orderByList;
     ValueNode    offset; // OFFSET n ROWS
     ValueNode    fetchFirst; // FETCH FIRST n ROWS ONLY
+    boolean   hasJDBClimitClause; //  were OFFSET/FETCH FIRST specified by a JDBC LIMIT clause?
 
 	/**
 	 * Initializer for a RowResultSetNode.
@@ -377,11 +378,13 @@ public class RowResultSetNode extends Fr
      *
      * @param offset    the OFFSET, if any
      * @param fetchFirst the OFFSET FIRST, if any
+     * @param hasJDBClimitClause true if the clauses were added by (and have the semantics
of) a JDBC limit clause
      */
-    void pushOffsetFetchFirst(ValueNode offset, ValueNode fetchFirst)
+    void pushOffsetFetchFirst( ValueNode offset, ValueNode fetchFirst, boolean hasJDBClimitClause
)
     {
         this.offset = offset;
         this.fetchFirst = fetchFirst;
+        this.hasJDBClimitClause = hasJDBClimitClause;
     }
 
 
@@ -655,6 +658,7 @@ public class RowResultSetNode extends Fr
                 newRcl,
                 offset,
                 fetchFirst,
+                new Boolean( hasJDBClimitClause ),
                 getContextManager());
         }
 

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SelectNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SelectNode.java?rev=1200492&r1=1200491&r2=1200492&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SelectNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SelectNode.java Thu
Nov 10 19:31:56 2011
@@ -107,6 +107,7 @@ public class SelectNode extends ResultSe
 
     ValueNode   offset;  // OFFSET n ROWS, if given
     ValueNode   fetchFirst; // FETCH FIRST n ROWS ONLY, if given
+    boolean   hasJDBClimitClause; //  were OFFSET/FETCH FIRST specified by a JDBC LIMIT clause?
 
 
 	/* PredicateLists for where clause */
@@ -934,11 +935,13 @@ public class SelectNode extends ResultSe
      *
      * @param offset    the OFFSET, if any
      * @param fetchFirst the OFFSET FIRST, if any
+     * @param hasJDBClimitClause true if the clauses were added by (and have the semantics
of) a JDBC limit clause
      */
-    void pushOffsetFetchFirst(ValueNode offset, ValueNode fetchFirst)
+    void pushOffsetFetchFirst( ValueNode offset, ValueNode fetchFirst, boolean hasJDBClimitClause
)
     {
         this.offset = offset;
         this.fetchFirst = fetchFirst;
+        this.hasJDBClimitClause = hasJDBClimitClause;
     }
 
 
@@ -1654,6 +1657,7 @@ public class SelectNode extends ResultSe
                 topList,
                 offset,
                 fetchFirst,
+                new Boolean( hasJDBClimitClause ),
                 getContextManager());
         }
 

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SetOperatorNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SetOperatorNode.java?rev=1200492&r1=1200491&r2=1200492&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SetOperatorNode.java
(original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SetOperatorNode.java
Thu Nov 10 19:31:56 2011
@@ -63,6 +63,7 @@ abstract class SetOperatorNode extends T
 	OrderByList orderByList;
     ValueNode   offset; // OFFSET n ROWS
     ValueNode   fetchFirst; // FETCH FIRST n ROWS ONLY
+    boolean   hasJDBClimitClause; // were OFFSET/FETCH FIRST specified by a JDBC LIMIT clause?
 	// List of scoped predicates for pushing during optimization.
 	private PredicateList leftOptPredicates;
 	private PredicateList rightOptPredicates;
@@ -803,11 +804,13 @@ abstract class SetOperatorNode extends T
      *
      * @param offset    the OFFSET, if any
      * @param fetchFirst the OFFSET FIRST, if any
+     * @param hasJDBClimitClause true if the clauses were added by (and have the semantics
of) a JDBC limit clause
      */
-    void pushOffsetFetchFirst(ValueNode offset, ValueNode fetchFirst)
+    void pushOffsetFetchFirst( ValueNode offset, ValueNode fetchFirst, boolean hasJDBClimitClause
)
     {
         this.offset = offset;
         this.fetchFirst = fetchFirst;
+        this.hasJDBClimitClause = hasJDBClimitClause;
     }
 
 

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SubqueryNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SubqueryNode.java?rev=1200492&r1=1200491&r2=1200492&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SubqueryNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/SubqueryNode.java Thu
Nov 10 19:31:56 2011
@@ -170,6 +170,7 @@ public class SubqueryNode extends ValueN
 	private OrderByList orderByList;
     private ValueNode   offset;
     private ValueNode   fetchFirst;
+    private boolean hasJDBClimitClause; // true if using JDBC limit/offset escape syntax
 
 	/* Subquery types.
 	 * NOTE: FROM_SUBQUERY only exists for a brief second in the parser.  It
@@ -209,6 +210,7 @@ public class SubqueryNode extends ValueN
 	 * @param orderCols     ORDER BY list
      * @param offset        OFFSET n ROWS
      * @param fetchFirst    FETCH FIRST n ROWS ONLY
+	 * @param hasJDBClimitClause True if the offset/fetchFirst clauses come from JDBC limit/offset
escape syntax
 	 */
 
 	public void init(
@@ -217,13 +219,15 @@ public class SubqueryNode extends ValueN
 							Object leftOperand,
                             Object orderCols,
                             Object offset,
-                            Object fetchFirst)
+                            Object fetchFirst,
+                            Object hasJDBClimitClause)
 	{
 		this.resultSet = (ResultSetNode) resultSet;
 		this.subqueryType = ((Integer) subqueryType).intValue();
 		this.orderByList = (OrderByList)orderCols;
         this.offset = (ValueNode)offset;
         this.fetchFirst = (ValueNode)fetchFirst;
+        this.hasJDBClimitClause = (hasJDBClimitClause == null) ? false : ((Boolean) hasJDBClimitClause).booleanValue();
 
 		/* Subqueries are presumed not to be under a top level AndNode by
 		 * default.  This is because expression normalization only recurses
@@ -868,7 +872,7 @@ public class SubqueryNode extends ValueN
 		}
 
 
-        resultSet.pushOffsetFetchFirst(offset, fetchFirst);
+        resultSet.pushOffsetFetchFirst( offset, fetchFirst, hasJDBClimitClause );
 
 		/* We transform the leftOperand and the select list for quantified 
 		 * predicates that have a leftOperand into a new predicate and push it
@@ -2575,4 +2579,14 @@ public class SubqueryNode extends ValueN
     public ValueNode getFetchFirst() {
         return fetchFirst;
     }
+
+    /**
+     * Return true if the offset/fetchFirst clauses were added by JDBC LIMIT escape syntax.
+     * This method is used to construct a FROM_SUBQUERY only, cf.
+     * FromSubquery, for which this node is transient.
+     *
+     * @return true if the JDBC limit/offset semantics (rather than the SQL Standard OFFSET/FETCH
NEXT) semantics apply
+     */
+    public boolean hasJDBClimitClause() { return hasJDBClimitClause; }
+
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/UnionNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/UnionNode.java?rev=1200492&r1=1200491&r2=1200492&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/UnionNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/UnionNode.java Thu Nov
10 19:31:56 2011
@@ -493,6 +493,7 @@ public class UnionNode extends SetOperat
                 newRcl,
                 offset,
                 fetchFirst,
+                new Boolean( hasJDBClimitClause ),
                 getContextManager());
         }
 

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj?rev=1200492&r1=1200491&r2=1200492&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj Thu Nov
10 19:31:56 2011
@@ -226,6 +226,11 @@ public class SQLParser
     private static final int IDX_CYCLE_OPTION = IDX_MIN_VALUE_OPTION + 1;
     private static final int IDX_OPTION_COUNT = IDX_CYCLE_OPTION + 1;
 
+    // indexes into array of clauses for OFFSET FETCH NEXT
+    private static final int OFFSET_CLAUSE = 0;
+    private static final int FETCH_FIRST_CLAUSE = OFFSET_CLAUSE + 1;
+    private static final int OFFSET_CLAUSE_COUNT = FETCH_FIRST_CLAUSE + 1;
+
 	private Object[]					paramDefaults;
 	private String						statementSQLText;
 	private NodeFactory					nodeFactory;
@@ -2437,6 +2442,7 @@ TOKEN [IGNORE_CASE] :
 |	<LARGE: "large">
 |	<LENGTH: "length">
 |	<LEVEL: "level">
+|	<LIMIT: "limit">
 |	<LOCKS: "locks">
 |	<LOCKSIZE: "locksize">
 |	<LOGGED: "logged">
@@ -3361,14 +3367,13 @@ preparableSelectStatement(boolean checkP
 	int				  isolationLevel = ExecutionContext.UNSPECIFIED_ISOLATION_LEVEL;
 	CursorNode		  retval;
 	OrderByList orderCols = null;
-	ValueNode offset = null;
-	ValueNode fetchFirst = null;
+    ValueNode[] offsetClauses = new ValueNode[ OFFSET_CLAUSE_COUNT ];
+    boolean     hasJDBClimitClause = false;
 }
 {
 	queryExpression = queryExpression(null, NO_SET_OP) 
 		[ orderCols = orderByClause() ]
-		[ offset = offsetClause() ]
-		[ fetchFirst = fetchFirstClause() ]
+        hasJDBClimitClause = offsetFetchFirstClause( offsetClauses )
 		[ <FOR> forUpdateState = forUpdateClause(updateColumns) ]
 		[ isolationLevel = atIsolationLevel() ]
 	{
@@ -3382,8 +3387,9 @@ preparableSelectStatement(boolean checkP
 				queryExpression,
 				null,
 				orderCols,
-				offset,
-				fetchFirst,
+				offsetClauses[ OFFSET_CLAUSE ],
+				offsetClauses[ FETCH_FIRST_CLAUSE ],
+                new Boolean( hasJDBClimitClause ),
 				ReuseFactory.getInteger(forUpdateState),
 				(forUpdateState == CursorNode.READ_ONLY ? null : updateColumns ),
 				getContextManager());
@@ -3654,6 +3660,7 @@ bareCallStatement() throws StandardExcep
 						null,
 						null,
 						null,
+						null,
 						ReuseFactory.getInteger(CursorNode.READ_ONLY),
 						null,
 						getContextManager());
@@ -5573,6 +5580,7 @@ remainingNegatablePredicate(ValueNode le
 	<LIKE> likePattern = additiveExpression(null, 0)
             [
                 <ESCAPE> escapeValue = additiveExpression(null, 0) |
+                LOOKAHEAD ( { getToken(1).kind == LEFT_BRACE && getToken(2).kind
!= LIMIT } )
                 <LEFT_BRACE> <ESCAPE> escapeValue = additiveExpression(null,
0) <RIGHT_BRACE>
             ]
 	{
@@ -8246,6 +8254,75 @@ nullOrdering(OrderByColumn orderCol) :
 
 
 /*
+ * <A NAME="offsetFetchFirstClause">offsetFetchFirstClause</A>
+ */
+boolean
+offsetFetchFirstClause( ValueNode[] clauses ) throws StandardException :
+{}
+{
+    LOOKAHEAD ( { getToken(1).kind == OFFSET || getToken(1).kind == FETCH } )
+    sqlStandardOffsetFetchFirst( clauses )
+    {
+        return false;
+    }
+|
+    [
+        LOOKAHEAD ( { getToken(1).kind == LEFT_BRACE } )
+        jdbcLimitOffset( clauses )
+    ]
+    {
+        return true;
+    }
+}
+
+/*
+ * <A NAME="sqlStandardOffsetFetchFirst">sqlStandardOffsetFetchFirst</A>
+ */
+void
+sqlStandardOffsetFetchFirst( ValueNode[] clauses ) throws StandardException :
+{}
+{
+    [ clauses[ OFFSET_CLAUSE ] = offsetClause() ]
+    [ clauses[ FETCH_FIRST_CLAUSE ] = fetchFirstClause() ]
+}
+
+/*
+ * <A NAME="jdbcLimitOffset">jdbcLimitOffset</A>
+ */
+void
+jdbcLimitOffset( ValueNode[] clauses ) throws StandardException :
+{
+    ValueNode rowCount = null;
+    ValueNode startRow = null;
+}
+{
+    <LEFT_BRACE>
+        <LIMIT> ( rowCount = intLiteral() | rowCount = dynamicParameterSpecification()
)
+        [ <OFFSET> ( startRow = intLiteral() | startRow = dynamicParameterSpecification()
) ]
+    <RIGHT_BRACE>
+    {
+        // LIMIT of 0 means omit the FETCH/FIRST CLAUSE
+        if ( 
+             (rowCount instanceof NumericConstantNode) &&
+             ((NumericConstantNode) rowCount).getValue().getInt() == 0
+           )
+        {
+            rowCount = null;
+        }
+
+        // default OFFSET is 0
+        if ( startRow == null )
+        {
+            startRow = getNumericNode( "0", true );
+        }
+
+        clauses[ FETCH_FIRST_CLAUSE ] = rowCount;
+        clauses[ OFFSET_CLAUSE ] = startRow;
+        return;
+    }
+}
+
+/*
  * <A NAME="offsetClause">offsetClause</A>
  */
 ValueNode
@@ -8441,8 +8518,8 @@ insertColumnsAndSource(QueryTreeNode tar
 	ResultSetNode	queryExpression;
 	ResultColumnList	columnList = null;
 	OrderByList orderCols = null;
-    ValueNode offset = null;
-    ValueNode fetchFirst = null;
+    ValueNode[] offsetClauses = new ValueNode[ OFFSET_CLAUSE_COUNT ];
+    boolean     hasJDBClimitClause = false;
 }
 {
 	[
@@ -8457,8 +8534,7 @@ insertColumnsAndSource(QueryTreeNode tar
 	[ targetProperties = propertyList(false) <CHECK_PROPERTIES>]
 	queryExpression = queryExpression(null, NO_SET_OP)
 	[ orderCols = orderByClause() ]
-    [ offset = offsetClause() ]
-    [ fetchFirst = fetchFirstClause() ]
+    hasJDBClimitClause = offsetFetchFirstClause( offsetClauses )
 	{
 		if (orderCols != null && isTableValueConstructor(queryExpression)) {
 			// Not allowed by the standard since this is a <contextually typed
@@ -8470,11 +8546,15 @@ insertColumnsAndSource(QueryTreeNode tar
 				SQLState.LANG_SYNTAX_ERROR, "ORDER BY");
 		}
 
-        if ((offset != null || fetchFirst != null) &&
-                isTableValueConstructor(queryExpression)) {
-            throw StandardException.newException(
-                SQLState.LANG_SYNTAX_ERROR,
-                (offset != null) ? "OFFSET" : "FETCH");
+        if ((offsetClauses[ OFFSET_CLAUSE ] != null || offsetClauses[ FETCH_FIRST_CLAUSE
] != null) &&
+                isTableValueConstructor(queryExpression))
+        {
+            String tokenName;
+            if ( hasJDBClimitClause ) { tokenName = "LIMIT"; }
+            else if ( offsetClauses[ OFFSET_CLAUSE ] != null ) { tokenName = "OFFSET"; }
+            else { tokenName = "FETCH"; }
+
+            throw StandardException.newException( SQLState.LANG_SYNTAX_ERROR, tokenName );
         }
 
 		return (StatementNode) nodeFactory.getNode(
@@ -8484,8 +8564,9 @@ insertColumnsAndSource(QueryTreeNode tar
 							queryExpression,
 							targetProperties,
 							orderCols,
-                            offset,
-                            fetchFirst,
+                            offsetClauses[ OFFSET_CLAUSE ],
+                            offsetClauses[ FETCH_FIRST_CLAUSE ],
+                            new Boolean( hasJDBClimitClause ),
 							getContextManager());
 	}
 	/* RESOLVE: Ignoring default values for now
@@ -8724,14 +8805,13 @@ subquery(int subqueryType, ValueNode lef
 	ResultSetNode	queryExpression;
 	SubqueryNode	subqueryNode;
 	OrderByList orderCols = null;
-    ValueNode offset = null;
-    ValueNode fetchFirst = null;
+    ValueNode[] offsetClauses = new ValueNode[ OFFSET_CLAUSE_COUNT ];
+    boolean     hasJDBClimitClause = false;
 }
 {
 	queryExpression = queryExpression(null, NO_SET_OP)
 	[ orderCols = orderByClause() ]
-    [ offset = offsetClause() ]
-    [ fetchFirst = fetchFirstClause() ]
+    hasJDBClimitClause = offsetFetchFirstClause( offsetClauses )
 	{
 		subqueryNode = (SubqueryNode) nodeFactory.getNode(
 										C_NodeTypes.SUBQUERY_NODE,
@@ -8739,8 +8819,9 @@ subquery(int subqueryType, ValueNode lef
 										ReuseFactory.getInteger(subqueryType),
 										leftOperand,
 										orderCols,
-                                        offset,
-                                        fetchFirst,
+                                        offsetClauses[ OFFSET_CLAUSE ],
+                                        offsetClauses[ FETCH_FIRST_CLAUSE ],
+                                        new Boolean( hasJDBClimitClause ),
 										getContextManager());
 		return subqueryNode;
 	}
@@ -9217,6 +9298,7 @@ FromTable tableFactor() throws StandardE
 											derivedTable.getOrderByList(),
                                             derivedTable.getOffset(),
                                             derivedTable.getFetchFirst(),
+                                            new Boolean( derivedTable.hasJDBClimitClause()
),
 											correlationName,
 											derivedRCL,
 											((optionalTableClauses != null) ?
@@ -10970,16 +11052,15 @@ viewDefinition(Token beginToken) throws 
 	Token				checkTok = null;
 	Token				endToken;
 	OrderByList         orderCols = null;
-    ValueNode           offset = null;
-    ValueNode           fetchFirst = null;
+    ValueNode[] offsetClauses = new ValueNode[ OFFSET_CLAUSE_COUNT ];
+    boolean     hasJDBClimitClause = false;
 }
 {
 	<VIEW> tableName = qualifiedName(Limits.MAX_IDENTIFIER_LENGTH) 
 		[ <LEFT_PAREN> resultColumns = viewColumnList() <RIGHT_PAREN> ]
 		<AS> queryExpression = queryExpression(null, NO_SET_OP)
 		[ orderCols = orderByClause() ]
-        [ offset = offsetClause() ]
-        [ fetchFirst = fetchFirstClause() ]
+        hasJDBClimitClause = offsetFetchFirstClause( offsetClauses )
 	{
 		checkOptionType = ViewDescriptor.NO_CHECK_OPTION;
 		endToken = getToken(0);
@@ -11001,8 +11082,9 @@ viewDefinition(Token beginToken) throws 
 												beginToken.beginOffset,
 												endToken.endOffset,false),
 								orderCols,
-                                offset,
-                                fetchFirst,
+                                offsetClauses[ OFFSET_CLAUSE ],
+                                offsetClauses[ FETCH_FIRST_CLAUSE ],
+                                new Boolean( hasJDBClimitClause ),
 								getContextManager());
 	}
 }
@@ -14520,6 +14602,7 @@ nonReservedKeyword()  :
     |   tok = <LCASE>
 	|	tok = <LENGTH>
 	|	tok = <LEVEL>
+    |   tok = <LIMIT>
     |   tok = <LOCATE>
 	|	tok = <LOCK>
 	|	tok = <LOCKS>

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/GenericResultSetFactory.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/GenericResultSetFactory.java?rev=1200492&r1=1200491&r2=1200492&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/GenericResultSetFactory.java
(original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/GenericResultSetFactory.java
Thu Nov 10 19:31:56 2011
@@ -1283,6 +1283,7 @@ public class GenericResultSetFactory imp
 		int resultSetNumber,
 		GeneratedMethod offsetMethod,
 		GeneratedMethod fetchFirstMethod,
+        boolean hasJDBClimitClause,
 		double optimizerEstimatedRowCount,
 		double optimizerEstimatedCost)
 		throws StandardException
@@ -1292,6 +1293,7 @@ public class GenericResultSetFactory imp
 									 resultSetNumber,
 									 offsetMethod,
 									 fetchFirstMethod,
+									 hasJDBClimitClause,
 									 optimizerEstimatedRowCount,
 									 optimizerEstimatedCost);
 	}

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/RowCountResultSet.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/RowCountResultSet.java?rev=1200492&r1=1200491&r2=1200492&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/RowCountResultSet.java
(original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/RowCountResultSet.java
Thu Nov 10 19:31:56 2011
@@ -56,6 +56,7 @@ class RowCountResultSet extends NoPutRes
     private long fetchFirst;
     final private GeneratedMethod offsetMethod;
     final private GeneratedMethod fetchFirstMethod;
+    final private boolean hasJDBClimitClause;
 
     /**
      * True if we haven't yet fetched any rows from this result set.
@@ -79,6 +80,7 @@ class RowCountResultSet extends NoPutRes
      * @param resultSetNumber The resultSetNumber for the ResultSet
      * @param offsetMethod   Generated method
      * @param fetchFirstMethod Generated method
+     * @param hasJDBClimitClause True if offset/fetchFirst clauses were added by JDBC LIMIT
escape syntax
      * @param optimizerEstimatedRowCount
      *                        Estimated total # of rows by optimizer
      * @param optimizerEstimatedCost
@@ -91,6 +93,7 @@ class RowCountResultSet extends NoPutRes
          int resultSetNumber,
          GeneratedMethod offsetMethod,
          GeneratedMethod fetchFirstMethod,
+         boolean hasJDBClimitClause,
          double optimizerEstimatedRowCount,
          double optimizerEstimatedCost)
             throws StandardException {
@@ -102,6 +105,7 @@ class RowCountResultSet extends NoPutRes
 
         this.offsetMethod = offsetMethod;
         this.fetchFirstMethod = fetchFirstMethod;
+        this.hasJDBClimitClause = hasJDBClimitClause;
 
         source = s;
 
@@ -215,6 +219,18 @@ class RowCountResultSet extends NoPutRes
 
                     fetchFirst = fetchFirstVal.getLong();
 
+                    //
+                    // According to section 13.4.6 of the JDBC 4.1 MR spec, you
+                    // can specify a LIMIT of 0. This means that you want all rows
+                    // to be returned from the OFFSET onwards. This diverges from
+                    // the SQL Standard treatment of the FETCH FIRST clause. For the
+                    // SQL Standard, a FETCH FIRST value of 0 rows is supposed to
+                    // raise an error. See the functional spec attached to DERBY-5488.
+                    // Here we translate a JDBC LIMIT of 0 into a FETCH FIRST value of
+                    // Long.MAX_VALUE so that all rows will be returned from OFFSET onwards.
+                    //
+                    if ( hasJDBClimitClause && (fetchFirst == 0) ) { fetchFirst =
Long.MAX_VALUE; }
+
                     if (fetchFirst < 1) {
                         throw StandardException.newException(
                             SQLState.LANG_INVALID_ROW_COUNT_FIRST,

Modified: db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml?rev=1200492&r1=1200491&r2=1200492&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml Thu Nov 10 19:31:56
2011
@@ -800,7 +800,7 @@ Guide.
 
             <msg>
                 <name>2201W</name>
-                <text>Invalid row count for FIRST/NEXT, must be >= 1.</text>
+                <text>Row count for FIRST/NEXT must be >= 1 and row count for LIMIT
must be >= 0.</text>
             </msg>
 
             <msg>



Mime
View raw message