aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/attach.c3
-rw-r--r--src/delete.c22
-rw-r--r--src/expr.c14
-rw-r--r--src/fkey.c4
-rw-r--r--src/insert.c1
-rw-r--r--src/parse.y45
-rw-r--r--src/resolve.c3
-rw-r--r--src/select.c60
-rw-r--r--src/sqliteInt.h11
-rw-r--r--src/treeview.c13
-rw-r--r--src/trigger.c4
-rw-r--r--src/update.c12
-rw-r--r--src/walker.c1
13 files changed, 73 insertions, 120 deletions
diff --git a/src/attach.c b/src/attach.c
index 68a9a77c6..fa38e8415 100644
--- a/src/attach.c
+++ b/src/attach.c
@@ -504,9 +504,6 @@ int sqlite3FixSelect(
if( sqlite3FixExpr(pFix, pSelect->pLimit) ){
return 1;
}
- if( sqlite3FixExpr(pFix, pSelect->pOffset) ){
- return 1;
- }
pSelect = pSelect->pPrior;
}
return 0;
diff --git a/src/delete.c b/src/delete.c
index 5c96fdfb8..8e25b36f5 100644
--- a/src/delete.c
+++ b/src/delete.c
@@ -92,7 +92,6 @@ void sqlite3MaterializeView(
Expr *pWhere, /* Optional WHERE clause to be added */
ExprList *pOrderBy, /* Optional ORDER BY clause */
Expr *pLimit, /* Optional LIMIT clause */
- Expr *pOffset, /* Optional OFFSET clause */
int iCur /* Cursor number for ephemeral table */
){
SelectDest dest;
@@ -110,7 +109,7 @@ void sqlite3MaterializeView(
assert( pFrom->a[0].pUsing==0 );
}
pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, pOrderBy,
- SF_IncludeHidden, pLimit, pOffset);
+ SF_IncludeHidden, pLimit);
sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
sqlite3Select(pParse, pSel, &dest);
sqlite3SelectDelete(db, pSel);
@@ -132,7 +131,6 @@ Expr *sqlite3LimitWhere(
Expr *pWhere, /* The WHERE clause. May be null */
ExprList *pOrderBy, /* The ORDER BY clause. May be null */
Expr *pLimit, /* The LIMIT clause. May be null */
- Expr *pOffset, /* The OFFSET clause. May be null */
char *zStmtType /* Either DELETE or UPDATE. For err msgs. */
){
sqlite3 *db = pParse->db;
@@ -149,8 +147,6 @@ Expr *sqlite3LimitWhere(
sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on %s", zStmtType);
sqlite3ExprDelete(pParse->db, pWhere);
sqlite3ExprListDelete(pParse->db, pOrderBy);
- sqlite3ExprDelete(pParse->db, pLimit);
- sqlite3ExprDelete(pParse->db, pOffset);
return 0;
}
@@ -158,8 +154,6 @@ Expr *sqlite3LimitWhere(
** is a limit/offset term to enforce.
*/
if( pLimit == 0 ) {
- /* if pLimit is null, pOffset will always be null as well. */
- assert( pOffset == 0 );
return pWhere;
}
@@ -206,7 +200,7 @@ Expr *sqlite3LimitWhere(
/* generate the SELECT expression tree. */
pSelect = sqlite3SelectNew(pParse, pEList, pSelectSrc, pWhere, 0 ,0,
- pOrderBy,0,pLimit,pOffset
+ pOrderBy,0,pLimit
);
/* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */
@@ -229,8 +223,7 @@ void sqlite3DeleteFrom(
SrcList *pTabList, /* The table from which we should delete things */
Expr *pWhere, /* The WHERE clause. May be null */
ExprList *pOrderBy, /* ORDER BY clause. May be null */
- Expr *pLimit, /* LIMIT clause. May be null */
- Expr *pOffset /* OFFSET clause. May be null */
+ Expr *pLimit /* LIMIT clause. May be null */
){
Vdbe *v; /* The virtual database engine */
Table *pTab; /* The table from which records will be deleted */
@@ -303,10 +296,10 @@ void sqlite3DeleteFrom(
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
if( !isView ){
pWhere = sqlite3LimitWhere(
- pParse, pTabList, pWhere, pOrderBy, pLimit, pOffset, "DELETE"
+ pParse, pTabList, pWhere, pOrderBy, pLimit, "DELETE"
);
pOrderBy = 0;
- pLimit = pOffset = 0;
+ pLimit = 0;
}
#endif
@@ -358,11 +351,11 @@ void sqlite3DeleteFrom(
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
if( isView ){
sqlite3MaterializeView(pParse, pTab,
- pWhere, pOrderBy, pLimit, pOffset, iTabCur
+ pWhere, pOrderBy, pLimit, iTabCur
);
iDataCur = iIdxCur = iTabCur;
pOrderBy = 0;
- pLimit = pOffset = 0;
+ pLimit = 0;
}
#endif
@@ -609,7 +602,6 @@ delete_from_cleanup:
#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT)
sqlite3ExprListDelete(db, pOrderBy);
sqlite3ExprDelete(db, pLimit);
- sqlite3ExprDelete(db, pOffset);
#endif
sqlite3DbFree(db, aToOpen);
return;
diff --git a/src/expr.c b/src/expr.c
index 0a5dc913f..5027f994d 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -663,7 +663,6 @@ static void heightOfSelect(Select *p, int *pnHeight){
heightOfExpr(p->pWhere, pnHeight);
heightOfExpr(p->pHaving, pnHeight);
heightOfExpr(p->pLimit, pnHeight);
- heightOfExpr(p->pOffset, pnHeight);
heightOfExprList(p->pEList, pnHeight);
heightOfExprList(p->pGroupBy, pnHeight);
heightOfExprList(p->pOrderBy, pnHeight);
@@ -1462,7 +1461,6 @@ Select *sqlite3SelectDup(sqlite3 *db, Select *pDup, int flags){
pNew->pNext = pNext;
pNew->pPrior = 0;
pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags);
- pNew->pOffset = sqlite3ExprDup(db, p->pOffset, flags);
pNew->iLimit = 0;
pNew->iOffset = 0;
pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
@@ -2099,7 +2097,6 @@ static Select *isCandidateForInOpt(Expr *pX){
}
assert( p->pGroupBy==0 ); /* Has no GROUP BY clause */
if( p->pLimit ) return 0; /* Has no LIMIT clause */
- assert( p->pOffset==0 ); /* No LIMIT means no OFFSET */
if( p->pWhere ) return 0; /* Has no WHERE clause */
pSrc = p->pSrc;
assert( pSrc!=0 );
@@ -2739,6 +2736,7 @@ int sqlite3CodeSubselect(
Select *pSel; /* SELECT statement to encode */
SelectDest dest; /* How to deal with SELECT result */
int nReg; /* Registers to allocate */
+ Expr *pLimit; /* New limit expression */
testcase( pExpr->op==TK_EXISTS );
testcase( pExpr->op==TK_SELECT );
@@ -2760,9 +2758,13 @@ int sqlite3CodeSubselect(
sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iSDParm);
VdbeComment((v, "Init EXISTS result"));
}
- sqlite3ExprDelete(pParse->db, pSel->pLimit);
- pSel->pLimit = sqlite3ExprAlloc(pParse->db, TK_INTEGER,
- &sqlite3IntTokens[1], 0);
+ pLimit = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[1], 0);
+ if( pSel->pLimit ){
+ sqlite3ExprDelete(pParse->db, pSel->pLimit->pLeft);
+ pSel->pLimit->pLeft = pLimit;
+ }else{
+ pSel->pLimit = sqlite3PExpr(pParse, TK_LIMIT, pLimit, 0);
+ }
pSel->iLimit = 0;
pSel->selFlags &= ~SF_MultiValue;
if( sqlite3Select(pParse, pSel, &dest) ){
diff --git a/src/fkey.c b/src/fkey.c
index 44ef3c7c7..c366c1b3a 100644
--- a/src/fkey.c
+++ b/src/fkey.c
@@ -725,7 +725,7 @@ void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){
}
pParse->disableTriggers = 1;
- sqlite3DeleteFrom(pParse, sqlite3SrcListDup(db, pName, 0), 0, 0, 0, 0);
+ sqlite3DeleteFrom(pParse, sqlite3SrcListDup(db, pName, 0), 0, 0, 0);
pParse->disableTriggers = 0;
/* If the DELETE has generated immediate foreign key constraint
@@ -1283,7 +1283,7 @@ static Trigger *fkActionTrigger(
sqlite3ExprListAppend(pParse, 0, pRaise),
sqlite3SrcListAppend(db, 0, &tFrom, 0),
pWhere,
- 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0
);
pWhere = 0;
}
diff --git a/src/insert.c b/src/insert.c
index 3a531495c..f0af0fbd1 100644
--- a/src/insert.c
+++ b/src/insert.c
@@ -2007,7 +2007,6 @@ static int xferOptimization(
if( pSelect->pLimit ){
return 0; /* SELECT may not have a LIMIT clause */
}
- assert( pSelect->pOffset==0 ); /* Must be so if pLimit==0 */
if( pSelect->pPrior ){
return 0; /* SELECT may not be a compound query */
}
diff --git a/src/parse.y b/src/parse.y
index 18f587c05..0867d1e0c 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -85,15 +85,6 @@
#define YYMALLOCARGTYPE u64
/*
-** An instance of this structure holds information about the
-** LIMIT clause of a SELECT statement.
-*/
-struct LimitVal {
- Expr *pLimit; /* The LIMIT expression. NULL if there is no limit */
- Expr *pOffset; /* The OFFSET expression. NULL if there is none */
-};
-
-/*
** An instance of the following structure describes the event of a
** TRIGGER. "a" is the event type, one of TK_UPDATE, TK_INSERT,
** TK_DELETE, or TK_INSTEAD. If the event is of the form
@@ -470,7 +461,7 @@ selectnowith(A) ::= selectnowith(A) multiselect_op(Y) oneselect(Z). {
x.n = 0;
parserDoubleLinkSelect(pParse, pRhs);
pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0,0);
- pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0,0);
+ pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0);
}
if( pRhs ){
pRhs->op = (u8)Y;
@@ -493,7 +484,7 @@ oneselect(A) ::= SELECT(S) distinct(D) selcollist(W) from(X) where_opt(Y)
#if SELECTTRACE_ENABLED
Token s = S; /*A-overwrites-S*/
#endif
- A = sqlite3SelectNew(pParse,W,X,Y,P,Q,Z,D,L.pLimit,L.pOffset);
+ A = sqlite3SelectNew(pParse,W,X,Y,P,Q,Z,D,L);
#if SELECTTRACE_ENABLED
/* Populate the Select.zSelName[] string that is used to help with
** query planner debugging, to differentiate between multiple Select
@@ -524,11 +515,11 @@ oneselect(A) ::= values(A).
%type values {Select*}
%destructor values {sqlite3SelectDelete(pParse->db, $$);}
values(A) ::= VALUES LP nexprlist(X) RP. {
- A = sqlite3SelectNew(pParse,X,0,0,0,0,0,SF_Values,0,0);
+ A = sqlite3SelectNew(pParse,X,0,0,0,0,0,SF_Values,0);
}
values(A) ::= values(A) COMMA LP exprlist(Y) RP. {
Select *pRight, *pLeft = A;
- pRight = sqlite3SelectNew(pParse,Y,0,0,0,0,0,SF_Values|SF_MultiValue,0,0);
+ pRight = sqlite3SelectNew(pParse,Y,0,0,0,0,0,SF_Values|SF_MultiValue,0);
if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue;
if( pRight ){
pRight->op = TK_ALL;
@@ -639,7 +630,7 @@ seltablist(A) ::= stl_prefix(A) nm(Y) dbnm(D) LP exprlist(E) RP as(Z)
}else{
Select *pSubquery;
sqlite3SrcListShiftJoinType(F);
- pSubquery = sqlite3SelectNew(pParse,0,F,0,0,0,0,SF_NestedFrom,0,0);
+ pSubquery = sqlite3SelectNew(pParse,0,F,0,0,0,0,SF_NestedFrom,0);
A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,pSubquery,N,U);
}
}
@@ -726,7 +717,7 @@ groupby_opt(A) ::= GROUP BY nexprlist(X). {A = X;}
having_opt(A) ::= . {A = 0;}
having_opt(A) ::= HAVING expr(X). {A = X.pExpr;}
-%type limit_opt {struct LimitVal}
+%type limit_opt {Expr*}
// The destructor for limit_opt will never fire in the current grammar.
// The limit_opt non-terminal only occurs at the end of a single production
@@ -735,16 +726,14 @@ having_opt(A) ::= HAVING expr(X). {A = X.pExpr;}
// reduce. So there is never a limit_opt non-terminal on the stack
// except as a transient. So there is never anything to destroy.
//
-//%destructor limit_opt {
-// sqlite3ExprDelete(pParse->db, $$.pLimit);
-// sqlite3ExprDelete(pParse->db, $$.pOffset);
-//}
-limit_opt(A) ::= . {A.pLimit = 0; A.pOffset = 0;}
-limit_opt(A) ::= LIMIT expr(X). {A.pLimit = X.pExpr; A.pOffset = 0;}
+//%destructor limit_opt {sqlite3ExprDelete(pParse->db, $$);}
+limit_opt(A) ::= . {A = 0;}
+limit_opt(A) ::= LIMIT expr(X).
+ {A = sqlite3PExpr(pParse,TK_LIMIT,X.pExpr,0);}
limit_opt(A) ::= LIMIT expr(X) OFFSET expr(Y).
- {A.pLimit = X.pExpr; A.pOffset = Y.pExpr;}
+ {A = sqlite3PExpr(pParse,TK_LIMIT,X.pExpr,Y.pExpr);}
limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y).
- {A.pOffset = X.pExpr; A.pLimit = Y.pExpr;}
+ {A = sqlite3PExpr(pParse,TK_LIMIT,Y.pExpr,X.pExpr);}
/////////////////////////// The DELETE statement /////////////////////////////
//
@@ -753,14 +742,14 @@ cmd ::= with(C) DELETE FROM fullname(X) indexed_opt(I) where_opt(W)
orderby_opt(O) limit_opt(L). {
sqlite3WithPush(pParse, C, 1);
sqlite3SrcListIndexedBy(pParse, X, &I);
- sqlite3DeleteFrom(pParse,X,W,O,L.pLimit,L.pOffset);
+ sqlite3DeleteFrom(pParse,X,W,O,L);
}
%endif
%ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
cmd ::= with(C) DELETE FROM fullname(X) indexed_opt(I) where_opt(W). {
sqlite3WithPush(pParse, C, 1);
sqlite3SrcListIndexedBy(pParse, X, &I);
- sqlite3DeleteFrom(pParse,X,W,0,0,0);
+ sqlite3DeleteFrom(pParse,X,W,0,0);
}
%endif
@@ -778,7 +767,7 @@ cmd ::= with(C) UPDATE orconf(R) fullname(X) indexed_opt(I) SET setlist(Y)
sqlite3WithPush(pParse, C, 1);
sqlite3SrcListIndexedBy(pParse, X, &I);
sqlite3ExprListCheckLength(pParse,Y,"set list");
- sqlite3Update(pParse,X,Y,W,R,O,L.pLimit,L.pOffset);
+ sqlite3Update(pParse,X,Y,W,R,O,L);
}
%endif
%ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
@@ -787,7 +776,7 @@ cmd ::= with(C) UPDATE orconf(R) fullname(X) indexed_opt(I) SET setlist(Y)
sqlite3WithPush(pParse, C, 1);
sqlite3SrcListIndexedBy(pParse, X, &I);
sqlite3ExprListCheckLength(pParse,Y,"set list");
- sqlite3Update(pParse,X,Y,W,R,0,0,0);
+ sqlite3Update(pParse,X,Y,W,R,0,0);
}
%endif
@@ -1189,7 +1178,7 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
}
expr(A) ::= expr(A) in_op(N) nm(Y) dbnm(Z) paren_exprlist(E). [IN] {
SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&Y,&Z);
- Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
+ Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0);
if( E ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, E);
A.pExpr = sqlite3PExpr(pParse, TK_IN, A.pExpr, 0);
sqlite3PExprAddSelect(pParse, A.pExpr, pSelect);
diff --git a/src/resolve.c b/src/resolve.c
index 17dbbccfc..f735fffa0 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -1196,8 +1196,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
*/
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
- if( sqlite3ResolveExprNames(&sNC, p->pLimit) ||
- sqlite3ResolveExprNames(&sNC, p->pOffset) ){
+ if( sqlite3ResolveExprNames(&sNC, p->pLimit) ){
return WRC_Abort;
}
diff --git a/src/select.c b/src/select.c
index 46c69d71f..97eaf21b4 100644
--- a/src/select.c
+++ b/src/select.c
@@ -74,7 +74,6 @@ static void clearSelect(sqlite3 *db, Select *p, int bFree){
sqlite3ExprDelete(db, p->pHaving);
sqlite3ExprListDelete(db, p->pOrderBy);
sqlite3ExprDelete(db, p->pLimit);
- sqlite3ExprDelete(db, p->pOffset);
if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith);
if( bFree ) sqlite3DbFreeNN(db, p);
p = pPrior;
@@ -107,8 +106,7 @@ Select *sqlite3SelectNew(
Expr *pHaving, /* the HAVING clause */
ExprList *pOrderBy, /* the ORDER BY clause */
u32 selFlags, /* Flag parameters, such as SF_Distinct */
- Expr *pLimit, /* LIMIT value. NULL means not used */
- Expr *pOffset /* OFFSET value. NULL means no offset */
+ Expr *pLimit /* LIMIT value. NULL means not used */
){
Select *pNew;
Select standin;
@@ -141,10 +139,7 @@ Select *sqlite3SelectNew(
pNew->pPrior = 0;
pNew->pNext = 0;
pNew->pLimit = pLimit;
- pNew->pOffset = pOffset;
pNew->pWith = 0;
- assert( pOffset==0 || pLimit!=0 || pParse->nErr>0
- || pParse->db->mallocFailed!=0 );
if( pParse->db->mallocFailed ) {
clearSelect(pParse->db, pNew, pNew!=&standin);
pNew = 0;
@@ -1874,7 +1869,7 @@ Vdbe *sqlite3GetVdbe(Parse *pParse){
/*
** Compute the iLimit and iOffset fields of the SELECT based on the
-** pLimit and pOffset expressions. pLimit and pOffset hold the expressions
+** pLimit expressions. pLimit->pLeft and pLimit->pRight hold the expressions
** that appear in the original SQL statement after the LIMIT and OFFSET
** keywords. Or NULL if those keywords are omitted. iLimit and iOffset
** are the integer memory register numbers for counters used to compute
@@ -1882,15 +1877,15 @@ Vdbe *sqlite3GetVdbe(Parse *pParse){
** iLimit and iOffset are negative.
**
** This routine changes the values of iLimit and iOffset only if
-** a limit or offset is defined by pLimit and pOffset. iLimit and
-** iOffset should have been preset to appropriate default values (zero)
+** a limit or offset is defined by pLimit->pLeft and pLimit->pRight. iLimit
+** and iOffset should have been preset to appropriate default values (zero)
** prior to calling this routine.
**
** The iOffset register (if it exists) is initialized to the value
** of the OFFSET. The iLimit register is initialized to LIMIT. Register
** iOffset+1 is initialized to LIMIT+OFFSET.
**
-** Only if pLimit!=0 or pOffset!=0 do the limit registers get
+** Only if pLimit->pLeft!=0 do the limit registers get
** redefined. The UNION ALL operator uses this property to force
** the reuse of the same limit and offset registers across multiple
** SELECT statements.
@@ -1900,6 +1895,8 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
int iLimit = 0;
int iOffset;
int n;
+ Expr *pLimit = p->pLimit;
+
if( p->iLimit ) return;
/*
@@ -1909,12 +1906,13 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
** no rows.
*/
sqlite3ExprCacheClear(pParse);
- assert( p->pOffset==0 || p->pLimit!=0 );
- if( p->pLimit ){
+ if( pLimit ){
+ assert( pLimit->op==TK_LIMIT );
+ assert( pLimit->pLeft!=0 );
p->iLimit = iLimit = ++pParse->nMem;
v = sqlite3GetVdbe(pParse);
assert( v!=0 );
- if( sqlite3ExprIsInteger(p->pLimit, &n) ){
+ if( sqlite3ExprIsInteger(pLimit->pLeft, &n) ){
sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit);
VdbeComment((v, "LIMIT counter"));
if( n==0 ){
@@ -1924,15 +1922,15 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
p->selFlags |= SF_FixedLimit;
}
}else{
- sqlite3ExprCode(pParse, p->pLimit, iLimit);
+ sqlite3ExprCode(pParse, pLimit->pLeft, iLimit);
sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); VdbeCoverage(v);
VdbeComment((v, "LIMIT counter"));
sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, iBreak); VdbeCoverage(v);
}
- if( p->pOffset ){
+ if( pLimit->pRight ){
p->iOffset = iOffset = ++pParse->nMem;
pParse->nMem++; /* Allocate an extra register for limit+offset */
- sqlite3ExprCode(pParse, p->pOffset, iOffset);
+ sqlite3ExprCode(pParse, pLimit->pRight, iOffset);
sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v);
VdbeComment((v, "OFFSET counter"));
sqlite3VdbeAddOp3(v, OP_OffsetLimit, iLimit, iOffset+1, iOffset);
@@ -2062,7 +2060,7 @@ static void generateWithRecursiveQuery(
int i; /* Loop counter */
int rc; /* Result code */
ExprList *pOrderBy; /* The ORDER BY clause */
- Expr *pLimit, *pOffset; /* Saved LIMIT and OFFSET */
+ Expr *pLimit; /* Saved LIMIT and OFFSET */
int regLimit, regOffset; /* Registers used by LIMIT and OFFSET */
/* Obtain authorization to do a recursive query */
@@ -2073,10 +2071,9 @@ static void generateWithRecursiveQuery(
p->nSelectRow = 320; /* 4 billion rows */
computeLimitRegisters(pParse, p, addrBreak);
pLimit = p->pLimit;
- pOffset = p->pOffset;
regLimit = p->iLimit;
regOffset = p->iOffset;
- p->pLimit = p->pOffset = 0;
+ p->pLimit = 0;
p->iLimit = p->iOffset = 0;
pOrderBy = p->pOrderBy;
@@ -2169,7 +2166,6 @@ end_of_recursive_query:
sqlite3ExprListDelete(pParse->db, p->pOrderBy);
p->pOrderBy = pOrderBy;
p->pLimit = pLimit;
- p->pOffset = pOffset;
return;
}
#endif /* SQLITE_OMIT_CTE */
@@ -2205,7 +2201,6 @@ static int multiSelectValues(
assert( p->selFlags & SF_Values );
assert( p->op==TK_ALL || (p->op==TK_SELECT && p->pPrior==0) );
assert( p->pLimit==0 );
- assert( p->pOffset==0 );
assert( p->pNext==0 || p->pEList->nExpr==p->pNext->pEList->nExpr );
if( p->pPrior==0 ) break;
assert( p->pPrior->pNext==p );
@@ -2332,11 +2327,9 @@ static int multiSelect(
pPrior->iLimit = p->iLimit;
pPrior->iOffset = p->iOffset;
pPrior->pLimit = p->pLimit;
- pPrior->pOffset = p->pOffset;
explainSetInteger(iSub1, pParse->iNextSelectId);
rc = sqlite3Select(pParse, pPrior, &dest);
p->pLimit = 0;
- p->pOffset = 0;
if( rc ){
goto multi_select_end;
}
@@ -2358,7 +2351,7 @@ static int multiSelect(
p->pPrior = pPrior;
p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
if( pPrior->pLimit
- && sqlite3ExprIsInteger(pPrior->pLimit, &nLimit)
+ && sqlite3ExprIsInteger(pPrior->pLimit->pLeft, &nLimit)
&& nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit)
){
p->nSelectRow = sqlite3LogEst((u64)nLimit);
@@ -2373,7 +2366,7 @@ static int multiSelect(
int unionTab; /* Cursor number of the temporary table holding result */
u8 op = 0; /* One of the SRT_ operations to apply to self */
int priorOp; /* The SRT_ operation to apply to prior selects */
- Expr *pLimit, *pOffset; /* Saved values of p->nLimit and p->nOffset */
+ Expr *pLimit; /* Saved values of p->nLimit */
int addr;
SelectDest uniondest;
@@ -2385,7 +2378,6 @@ static int multiSelect(
** right.
*/
assert( p->pLimit==0 ); /* Not allowed on leftward elements */
- assert( p->pOffset==0 ); /* Not allowed on leftward elements */
unionTab = dest.iSDParm;
}else{
/* We will need to create our own temporary table to hold the
@@ -2421,8 +2413,6 @@ static int multiSelect(
p->pPrior = 0;
pLimit = p->pLimit;
p->pLimit = 0;
- pOffset = p->pOffset;
- p->pOffset = 0;
uniondest.eDest = op;
explainSetInteger(iSub2, pParse->iNextSelectId);
rc = sqlite3Select(pParse, p, &uniondest);
@@ -2438,7 +2428,6 @@ static int multiSelect(
}
sqlite3ExprDelete(db, p->pLimit);
p->pLimit = pLimit;
- p->pOffset = pOffset;
p->iLimit = 0;
p->iOffset = 0;
@@ -2466,7 +2455,7 @@ static int multiSelect(
default: assert( p->op==TK_INTERSECT ); {
int tab1, tab2;
int iCont, iBreak, iStart;
- Expr *pLimit, *pOffset;
+ Expr *pLimit;
int addr;
SelectDest intersectdest;
int r1;
@@ -2502,8 +2491,6 @@ static int multiSelect(
p->pPrior = 0;
pLimit = p->pLimit;
p->pLimit = 0;
- pOffset = p->pOffset;
- p->pOffset = 0;
intersectdest.iSDParm = tab2;
explainSetInteger(iSub2, pParse->iNextSelectId);
rc = sqlite3Select(pParse, p, &intersectdest);
@@ -2513,7 +2500,6 @@ static int multiSelect(
if( p->nSelectRow>pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow;
sqlite3ExprDelete(db, p->pLimit);
p->pLimit = pLimit;
- p->pOffset = pOffset;
/* Generate code to take the intersection of the two temporary
** tables.
@@ -2992,8 +2978,6 @@ static int multiSelectOrderBy(
}
sqlite3ExprDelete(db, p->pLimit);
p->pLimit = 0;
- sqlite3ExprDelete(db, p->pOffset);
- p->pOffset = 0;
regAddrA = ++pParse->nMem;
regAddrB = ++pParse->nMem;
@@ -3457,7 +3441,7 @@ static int flattenSubquery(
** became arbitrary expressions, we were forced to add restrictions (13)
** and (14). */
if( pSub->pLimit && p->pLimit ) return 0; /* Restriction (13) */
- if( pSub->pOffset ) return 0; /* Restriction (14) */
+ if( pSub->pLimit && pSub->pLimit->pRight ) return 0; /* Restriction (14) */
if( (p->selFlags & SF_Compound)!=0 && pSub->pLimit ){
return 0; /* Restriction (15) */
}
@@ -3605,16 +3589,13 @@ static int flattenSubquery(
Select *pNew;
ExprList *pOrderBy = p->pOrderBy;
Expr *pLimit = p->pLimit;
- Expr *pOffset = p->pOffset;
Select *pPrior = p->pPrior;
p->pOrderBy = 0;
p->pSrc = 0;
p->pPrior = 0;
p->pLimit = 0;
- p->pOffset = 0;
pNew = sqlite3SelectDup(db, p, 0);
sqlite3SelectSetName(pNew, pSub->zSelName);
- p->pOffset = pOffset;
p->pLimit = pLimit;
p->pOrderBy = pOrderBy;
p->pSrc = pSrc;
@@ -4080,7 +4061,6 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
assert( pNew->pPrior!=0 );
pNew->pPrior->pNext = pNew;
pNew->pLimit = 0;
- pNew->pOffset = 0;
return WRC_Continue;
}
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 95a66b4fe..058fee146 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -2749,7 +2749,6 @@ struct Select {
Select *pPrior; /* Prior select in a compound select statement */
Select *pNext; /* Next select to the left in a compound */
Expr *pLimit; /* LIMIT expression. NULL means not used. */
- Expr *pOffset; /* OFFSET expression. NULL means not used. */
With *pWith; /* WITH clause attached to this select. Or NULL. */
};
@@ -3756,16 +3755,16 @@ void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
void sqlite3DropIndex(Parse*, SrcList*, int);
int sqlite3Select(Parse*, Select*, SelectDest*);
Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
- Expr*,ExprList*,u32,Expr*,Expr*);
+ Expr*,ExprList*,u32,Expr*);
void sqlite3SelectDelete(sqlite3*, Select*);
Table *sqlite3SrcListLookup(Parse*, SrcList*);
int sqlite3IsReadOnly(Parse*, Table*, int);
void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
-Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,Expr*,char*);
+Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,char*);
#endif
-void sqlite3DeleteFrom(Parse*, SrcList*, Expr*, ExprList*, Expr*, Expr*);
-void sqlite3Update(Parse*, SrcList*, ExprList*,Expr*,int,ExprList*,Expr*,Expr*);
+void sqlite3DeleteFrom(Parse*, SrcList*, Expr*, ExprList*, Expr*);
+void sqlite3Update(Parse*, SrcList*, ExprList*,Expr*,int,ExprList*,Expr*);
WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int);
void sqlite3WhereEnd(WhereInfo*);
LogEst sqlite3WhereOutputRowCount(WhereInfo*);
@@ -3889,7 +3888,7 @@ int sqlite3SafetyCheckSickOrOk(sqlite3*);
void sqlite3ChangeCookie(Parse*, int);
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
-void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,Expr*,int);
+void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int);
#endif
#ifndef SQLITE_OMIT_TRIGGER
diff --git a/src/treeview.c b/src/treeview.c
index ba9fa7b2f..8d171a473 100644
--- a/src/treeview.c
+++ b/src/treeview.c
@@ -153,7 +153,6 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
if( p->pHaving ) n++;
if( p->pOrderBy ) n++;
if( p->pLimit ) n++;
- if( p->pOffset ) n++;
}
sqlite3TreeViewExprList(pView, p->pEList, (n--)>0, "result-set");
if( p->pSrc && p->pSrc->nSrc ){
@@ -210,12 +209,12 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
}
if( p->pLimit ){
sqlite3TreeViewItem(pView, "LIMIT", (n--)>0);
- sqlite3TreeViewExpr(pView, p->pLimit, 0);
- sqlite3TreeViewPop(pView);
- }
- if( p->pOffset ){
- sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
- sqlite3TreeViewExpr(pView, p->pOffset, 0);
+ sqlite3TreeViewExpr(pView, p->pLimit->pLeft, p->pLimit->pRight!=0);
+ if( p->pLimit->pRight ){
+ sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
+ sqlite3TreeViewExpr(pView, p->pLimit->pRight, 0);
+ sqlite3TreeViewPop(pView);
+ }
sqlite3TreeViewPop(pView);
}
if( p->pPrior ){
diff --git a/src/trigger.c b/src/trigger.c
index a17769ae9..a64fb291a 100644
--- a/src/trigger.c
+++ b/src/trigger.c
@@ -711,7 +711,7 @@ static int codeTriggerProgram(
targetSrcList(pParse, pStep),
sqlite3ExprListDup(db, pStep->pExprList, 0),
sqlite3ExprDup(db, pStep->pWhere, 0),
- pParse->eOrconf, 0, 0, 0
+ pParse->eOrconf, 0, 0
);
break;
}
@@ -727,7 +727,7 @@ static int codeTriggerProgram(
case TK_DELETE: {
sqlite3DeleteFrom(pParse,
targetSrcList(pParse, pStep),
- sqlite3ExprDup(db, pStep->pWhere, 0), 0, 0, 0
+ sqlite3ExprDup(db, pStep->pWhere, 0), 0, 0
);
break;
}
diff --git a/src/update.c b/src/update.c
index 4cfa4019e..15e8f4a6c 100644
--- a/src/update.c
+++ b/src/update.c
@@ -93,8 +93,7 @@ void sqlite3Update(
Expr *pWhere, /* The WHERE clause. May be null */
int onError, /* How to handle constraint errors */
ExprList *pOrderBy, /* ORDER BY clause. May be null */
- Expr *pLimit, /* LIMIT clause. May be null */
- Expr *pOffset /* OFFSET clause. May be null */
+ Expr *pLimit /* LIMIT clause. May be null */
){
int i, j; /* Loop counters */
Table *pTab; /* The table to be updated */
@@ -182,10 +181,10 @@ void sqlite3Update(
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
if( !isView ){
pWhere = sqlite3LimitWhere(
- pParse, pTabList, pWhere, pOrderBy, pLimit, pOffset, "UPDATE"
+ pParse, pTabList, pWhere, pOrderBy, pLimit, "UPDATE"
);
pOrderBy = 0;
- pLimit = pOffset = 0;
+ pLimit = 0;
}
#endif
@@ -358,10 +357,10 @@ void sqlite3Update(
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
if( isView ){
sqlite3MaterializeView(pParse, pTab,
- pWhere, pOrderBy, pLimit, pOffset, iDataCur
+ pWhere, pOrderBy, pLimit, iDataCur
);
pOrderBy = 0;
- pLimit = pOffset = 0;
+ pLimit = 0;
}
#endif
@@ -748,7 +747,6 @@ update_cleanup:
#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT)
sqlite3ExprListDelete(db, pOrderBy);
sqlite3ExprDelete(db, pLimit);
- sqlite3ExprDelete(db, pOffset);
#endif
return;
}
diff --git a/src/walker.c b/src/walker.c
index ae7545bf5..60bf8226f 100644
--- a/src/walker.c
+++ b/src/walker.c
@@ -91,7 +91,6 @@ int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){
if( sqlite3WalkExpr(pWalker, p->pHaving) ) return WRC_Abort;
if( sqlite3WalkExprList(pWalker, p->pOrderBy) ) return WRC_Abort;
if( sqlite3WalkExpr(pWalker, p->pLimit) ) return WRC_Abort;
- if( sqlite3WalkExpr(pWalker, p->pOffset) ) return WRC_Abort;
return WRC_Continue;
}