mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-08 03:22:21 +03:00
Continuing work toward registerizing the code generator. (CVS 4703)
FossilOrigin-Name: 173698c963473ab1b9db88b23a2de82e4097b96d
This commit is contained in:
18
manifest
18
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Fix\smixing\squote\sexcapes\sin\san\sawk\sscript.\s\sTicket\s#2877.\s(CVS\s4702)
|
C Continuing\swork\stoward\sregisterizing\sthe\scode\sgenerator.\s(CVS\s4703)
|
||||||
D 2008-01-10T00:08:43
|
D 2008-01-10T03:46:36
|
||||||
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
|
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
|
||||||
F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9
|
F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9
|
||||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||||
@@ -92,11 +92,11 @@ F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
|
|||||||
F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6
|
F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6
|
||||||
F src/delete.c 4f760fb7e9b0bb3cf05534bb9d43ea9e726b7e74
|
F src/delete.c 4f760fb7e9b0bb3cf05534bb9d43ea9e726b7e74
|
||||||
F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
|
F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
|
||||||
F src/expr.c 27971029714d4b24081cf20b35e7c96d0e148311
|
F src/expr.c 522ba17fa6253a98dc6451e600341277ea43d5c6
|
||||||
F src/func.c 996071cf0af9d967e58b69fce1909555059ebc7d
|
F src/func.c 996071cf0af9d967e58b69fce1909555059ebc7d
|
||||||
F src/hash.c 45a7005aac044b6c86bd7e49c44bc15d30006d6c
|
F src/hash.c 45a7005aac044b6c86bd7e49c44bc15d30006d6c
|
||||||
F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53
|
F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53
|
||||||
F src/insert.c 8630ee92dac91944c9f7b75847fa4ef74292b220
|
F src/insert.c b8406b40cc1cac732932ef587cbc0da006bfd68b
|
||||||
F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2
|
F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2
|
||||||
F src/legacy.c 4ac53191fad2e3c4d59bde1228879b2dc5a96d66
|
F src/legacy.c 4ac53191fad2e3c4d59bde1228879b2dc5a96d66
|
||||||
F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35
|
F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35
|
||||||
@@ -131,12 +131,12 @@ F src/pragma.c bc6063d91d56a8b3cdad9e3478bba86700759cc4
|
|||||||
F src/prepare.c c31a879d6795f4765fd0b113675c6debbc96b7fd
|
F src/prepare.c c31a879d6795f4765fd0b113675c6debbc96b7fd
|
||||||
F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910
|
F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910
|
||||||
F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da
|
F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da
|
||||||
F src/select.c 7b88e17052dce3c89530cd6be014505b00d6ff4c
|
F src/select.c 095296a572c296c9ce718768c6c984d33b239e5a
|
||||||
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
|
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
|
||||||
F src/shell.c 5391e889384d2062249f668110d64ed16f601c4b
|
F src/shell.c 5391e889384d2062249f668110d64ed16f601c4b
|
||||||
F src/sqlite.h.in 2a7e3776534bbe6ff2cdc058f3abebe91e7e429f
|
F src/sqlite.h.in 2a7e3776534bbe6ff2cdc058f3abebe91e7e429f
|
||||||
F src/sqlite3ext.h a93f59cdee3638dc0c9c086f80df743a4e68c3cb
|
F src/sqlite3ext.h a93f59cdee3638dc0c9c086f80df743a4e68c3cb
|
||||||
F src/sqliteInt.h c2866ab4a8eb42e4daffe30d19afc82952ed67c1
|
F src/sqliteInt.h 0606321d38df78adef2325e0b51cd3963731f290
|
||||||
F src/sqliteLimit.h ee4430f88f69bf63527967bb35ca52af7b0ccb1e
|
F src/sqliteLimit.h ee4430f88f69bf63527967bb35ca52af7b0ccb1e
|
||||||
F src/table.c 1aeb9eab57b4235db86fe15a35dec76fb445a9c4
|
F src/table.c 1aeb9eab57b4235db86fe15a35dec76fb445a9c4
|
||||||
F src/tclsqlite.c 9923abeffc9b3d7dad58e92b319661521f60debf
|
F src/tclsqlite.c 9923abeffc9b3d7dad58e92b319661521f60debf
|
||||||
@@ -605,7 +605,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
|
|||||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||||
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
||||||
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
||||||
P 1134c5ea7116bb2f342ccf09548d075c308c427b
|
P 05fbca91085cb1b271a05e62181596b4f6f1bb9e
|
||||||
R 965fc5391bf9a2a36bfcbb9b6a1fc252
|
R 44353c14eaa458d109462754e477c6c2
|
||||||
U drh
|
U drh
|
||||||
Z b84d4a6ab04978dba07488e081c74e60
|
Z d88167e0b41893f49eaf4061856356de
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
05fbca91085cb1b271a05e62181596b4f6f1bb9e
|
173698c963473ab1b9db88b23a2de82e4097b96d
|
||||||
80
src/expr.c
80
src/expr.c
@@ -12,7 +12,7 @@
|
|||||||
** This file contains routines used for analyzing expressions and
|
** This file contains routines used for analyzing expressions and
|
||||||
** for generating VDBE code that evaluates expressions in SQLite.
|
** for generating VDBE code that evaluates expressions in SQLite.
|
||||||
**
|
**
|
||||||
** $Id: expr.c,v 1.340 2008/01/09 23:04:12 drh Exp $
|
** $Id: expr.c,v 1.341 2008/01/10 03:46:36 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -1610,8 +1610,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int mustBeUnique){
|
|||||||
int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||||
sqlite3VdbeUsesBtree(v, iDb);
|
sqlite3VdbeUsesBtree(v, iDb);
|
||||||
|
|
||||||
sqlite3VdbeAddOp1(v, OP_SCopy, iMem);
|
iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem);
|
||||||
iAddr = sqlite3VdbeAddOp2(v, OP_If, 0, iMem);
|
|
||||||
sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);
|
sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);
|
||||||
|
|
||||||
sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
|
sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
|
||||||
@@ -1647,8 +1646,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int mustBeUnique){
|
|||||||
iDb = sqlite3SchemaToIndex(db, pIdx->pSchema);
|
iDb = sqlite3SchemaToIndex(db, pIdx->pSchema);
|
||||||
sqlite3VdbeUsesBtree(v, iDb);
|
sqlite3VdbeUsesBtree(v, iDb);
|
||||||
|
|
||||||
sqlite3VdbeAddOp1(v, OP_SCopy, iMem);
|
iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem);
|
||||||
iAddr = sqlite3VdbeAddOp2(v, OP_If, 0, iMem);
|
|
||||||
sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);
|
sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);
|
||||||
|
|
||||||
sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb,
|
sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb,
|
||||||
@@ -1704,10 +1702,9 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
|
|||||||
*/
|
*/
|
||||||
if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->trigStack ){
|
if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->trigStack ){
|
||||||
int mem = ++pParse->nMem;
|
int mem = ++pParse->nMem;
|
||||||
sqlite3VdbeAddOp1(v, OP_SCopy, mem);
|
sqlite3VdbeAddOp1(v, OP_If, mem);
|
||||||
testAddr = sqlite3VdbeAddOp0(v, OP_If);
|
testAddr = sqlite3VdbeAddOp2(v, OP_Integer, 1, mem);
|
||||||
assert( testAddr>0 || pParse->db->mallocFailed );
|
assert( testAddr>0 || pParse->db->mallocFailed );
|
||||||
sqlite3VdbeAddOp2(v, OP_Integer, 1, mem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch( pExpr->op ){
|
switch( pExpr->op ){
|
||||||
@@ -1783,8 +1780,8 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
|
|||||||
** this code only executes once. Because for a non-constant
|
** this code only executes once. Because for a non-constant
|
||||||
** expression we need to rerun this code each time.
|
** expression we need to rerun this code each time.
|
||||||
*/
|
*/
|
||||||
if( testAddr>0 && !sqlite3ExprIsConstant(pE2) ){
|
if( testAddr && !sqlite3ExprIsConstant(pE2) ){
|
||||||
sqlite3VdbeChangeToNoop(v, testAddr-1, 3);
|
sqlite3VdbeChangeToNoop(v, testAddr-1, 2);
|
||||||
testAddr = 0;
|
testAddr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1830,7 +1827,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
|
|||||||
}
|
}
|
||||||
|
|
||||||
if( testAddr ){
|
if( testAddr ){
|
||||||
sqlite3VdbeJumpHere(v, testAddr);
|
sqlite3VdbeJumpHere(v, testAddr-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -2178,7 +2175,12 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
|
|||||||
nId = pExpr->token.n;
|
nId = pExpr->token.n;
|
||||||
pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, enc, 0);
|
pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, enc, 0);
|
||||||
assert( pDef!=0 );
|
assert( pDef!=0 );
|
||||||
nExpr = sqlite3ExprCodeExprList(pParse, pList, 0);
|
if( pList ){
|
||||||
|
nExpr = pList->nExpr;
|
||||||
|
sqlite3ExprCodeExprList(pParse, pList, 0);
|
||||||
|
}else{
|
||||||
|
nExpr = 0;
|
||||||
|
}
|
||||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||||
/* Possibly overload the function if the first argument is
|
/* Possibly overload the function if the first argument is
|
||||||
** a virtual table column.
|
** a virtual table column.
|
||||||
@@ -2402,9 +2404,10 @@ void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr){
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
** Generate code that pushes the value of every element of the given
|
** Generate code that pushes the value of every element of the given
|
||||||
** expression list onto the stack.
|
** expression list onto the stack if target==0 or into a sequence of
|
||||||
|
** registers beginning at target.
|
||||||
**
|
**
|
||||||
** Return the number of elements pushed onto the stack.
|
** Return the number of elements evaluated.
|
||||||
*/
|
*/
|
||||||
int sqlite3ExprCodeExprList(
|
int sqlite3ExprCodeExprList(
|
||||||
Parse *pParse, /* Parsing context */
|
Parse *pParse, /* Parsing context */
|
||||||
@@ -2413,12 +2416,13 @@ int sqlite3ExprCodeExprList(
|
|||||||
){
|
){
|
||||||
struct ExprList_item *pItem;
|
struct ExprList_item *pItem;
|
||||||
int i, n, incr = 1;
|
int i, n, incr = 1;
|
||||||
if( pList==0 ) return 0;
|
assert( pList!=0 || pParse->db->mallocFailed );
|
||||||
|
if( pList==0 ){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
assert( target>=0 );
|
||||||
n = pList->nExpr;
|
n = pList->nExpr;
|
||||||
if( target<0 ){
|
if( target==0 ){
|
||||||
target = pParse->nMem+1;
|
|
||||||
pParse->nMem += n;
|
|
||||||
}else if( target==0 ){
|
|
||||||
incr = 0;
|
incr = 0;
|
||||||
}
|
}
|
||||||
for(pItem=pList->a, i=n; i>0; i--, pItem++){
|
for(pItem=pList->a, i=n; i>0; i--, pItem++){
|
||||||
@@ -2888,3 +2892,41 @@ int sqlite3ExprAnalyzeAggList(NameContext *pNC, ExprList *pList){
|
|||||||
}
|
}
|
||||||
return nErr;
|
return nErr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Allocate or deallocate temporary use registers during code generation.
|
||||||
|
*/
|
||||||
|
int sqlite3GetTempReg(Parse *pParse){
|
||||||
|
if( pParse->nTempReg ){
|
||||||
|
return pParse->aTempReg[--pParse->nTempReg];
|
||||||
|
}else{
|
||||||
|
return ++pParse->nMem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void sqlite3ReleaseTempReg(Parse *pParse, int iReg){
|
||||||
|
if( pParse->nTempReg<sizeof(pParse->aTempReg)/sizeof(pParse->aTempReg[0]) ){
|
||||||
|
pParse->aTempReg[pParse->nTempReg++] = iReg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Allocate or deallocate a block of nReg consecutive registers
|
||||||
|
*/
|
||||||
|
int sqlite3GetTempRange(Parse *pParse, int nReg){
|
||||||
|
int i;
|
||||||
|
if( nReg<=pParse->nRangeReg ){
|
||||||
|
i = pParse->iRangeReg;
|
||||||
|
pParse->iRangeReg += nReg;
|
||||||
|
pParse->nRangeReg -= nReg;
|
||||||
|
}else{
|
||||||
|
i = pParse->nMem+1;
|
||||||
|
pParse->nMem += nReg;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
void sqlite3ReleaseTempRange(Parse *pParse, int iReg, int nReg){
|
||||||
|
if( nReg>pParse->nRangeReg ){
|
||||||
|
pParse->nRangeReg = nReg;
|
||||||
|
pParse->iRangeReg = iReg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
12
src/insert.c
12
src/insert.c
@@ -12,7 +12,7 @@
|
|||||||
** This file contains C code routines that are called by the parser
|
** This file contains C code routines that are called by the parser
|
||||||
** to handle INSERT statements in SQLite.
|
** to handle INSERT statements in SQLite.
|
||||||
**
|
**
|
||||||
** $Id: insert.c,v 1.220 2008/01/09 23:04:12 drh Exp $
|
** $Id: insert.c,v 1.221 2008/01/10 03:46:36 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -1107,9 +1107,7 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if( isUpdate ){
|
if( isUpdate ){
|
||||||
sqlite3VdbeAddOp1(v, OP_SCopy, regRowid-1);
|
j2 = sqlite3VdbeAddOp3(v, OP_Eq, regRowid, 0, regRowid-1);
|
||||||
sqlite3VdbeAddOp1(v, OP_SCopy, regRowid);
|
|
||||||
j2 = sqlite3VdbeAddOp2(v, OP_Eq, 0, 0);
|
|
||||||
}
|
}
|
||||||
j3 = sqlite3VdbeAddOp3(v, OP_NotExists, baseCur, 0, regRowid);
|
j3 = sqlite3VdbeAddOp3(v, OP_NotExists, baseCur, 0, regRowid);
|
||||||
switch( onError ){
|
switch( onError ){
|
||||||
@@ -1127,8 +1125,7 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
case OE_Replace: {
|
case OE_Replace: {
|
||||||
sqlite3GenerateRowIndexDelete(v, pTab, baseCur, 0);
|
sqlite3GenerateRowIndexDelete(v, pTab, baseCur, 0);
|
||||||
if( isUpdate ){
|
if( isUpdate ){
|
||||||
sqlite3VdbeAddOp1(v, OP_SCopy, regRowid-hasTwoRowids);
|
sqlite3VdbeAddOp3(v, OP_MoveGe, baseCur, 0, regRowid-hasTwoRowids);
|
||||||
sqlite3VdbeAddOp2(v, OP_MoveGe, baseCur, 0);
|
|
||||||
}
|
}
|
||||||
seenReplace = 1;
|
seenReplace = 1;
|
||||||
break;
|
break;
|
||||||
@@ -1142,8 +1139,7 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
sqlite3VdbeJumpHere(v, j3);
|
sqlite3VdbeJumpHere(v, j3);
|
||||||
if( isUpdate ){
|
if( isUpdate ){
|
||||||
sqlite3VdbeJumpHere(v, j2);
|
sqlite3VdbeJumpHere(v, j2);
|
||||||
sqlite3VdbeAddOp1(v, OP_SCopy, regRowid-1);
|
sqlite3VdbeAddOp3(v, OP_MoveGe, baseCur, 0, regRowid-1);
|
||||||
sqlite3VdbeAddOp2(v, OP_MoveGe, baseCur, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
58
src/select.c
58
src/select.c
@@ -12,7 +12,7 @@
|
|||||||
** This file contains C code routines that are called by the parser
|
** This file contains C code routines that are called by the parser
|
||||||
** to handle SELECT statements in SQLite.
|
** to handle SELECT statements in SQLite.
|
||||||
**
|
**
|
||||||
** $Id: select.c,v 1.395 2008/01/09 23:04:12 drh Exp $
|
** $Id: select.c,v 1.396 2008/01/10 03:46:36 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -397,11 +397,16 @@ static void pushOntoSorter(
|
|||||||
Select *pSelect /* The whole SELECT statement */
|
Select *pSelect /* The whole SELECT statement */
|
||||||
){
|
){
|
||||||
Vdbe *v = pParse->pVdbe;
|
Vdbe *v = pParse->pVdbe;
|
||||||
sqlite3ExprCodeExprList(pParse, pOrderBy, 0);
|
int nExpr = pOrderBy->nExpr;
|
||||||
sqlite3VdbeAddOp1(v, OP_Sequence, pOrderBy->iECursor);
|
int regBase = sqlite3GetTempRange(pParse, nExpr+2);
|
||||||
sqlite3VdbeAddOp1(v, OP_Pull, pOrderBy->nExpr + 1);
|
int regRecord = sqlite3GetTempReg(pParse);
|
||||||
sqlite3VdbeAddOp1(v, OP_MakeRecord, pOrderBy->nExpr + 2);
|
sqlite3ExprCodeExprList(pParse, pOrderBy, regBase);
|
||||||
sqlite3VdbeAddOp1(v, OP_IdxInsert, pOrderBy->iECursor);
|
sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr);
|
||||||
|
sqlite3VdbeAddOp2(v, OP_Move, 0, regBase+nExpr+1);
|
||||||
|
sqlite3VdbeAddOp3(v, OP_RegMakeRec, regBase, nExpr + 2, regRecord);
|
||||||
|
sqlite3VdbeAddOp2(v, OP_IdxInsert, pOrderBy->iECursor, regRecord);
|
||||||
|
sqlite3ReleaseTempReg(pParse, regRecord);
|
||||||
|
sqlite3ReleaseTempRange(pParse, regBase, nExpr+2);
|
||||||
if( pSelect->iLimit>=0 ){
|
if( pSelect->iLimit>=0 ){
|
||||||
int addr1, addr2;
|
int addr1, addr2;
|
||||||
addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, pSelect->iLimit+1);
|
addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, pSelect->iLimit+1);
|
||||||
@@ -3002,8 +3007,8 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
|
|||||||
ExprList *pList = pF->pExpr->pList;
|
ExprList *pList = pF->pExpr->pList;
|
||||||
if( pList ){
|
if( pList ){
|
||||||
nArg = pList->nExpr;
|
nArg = pList->nExpr;
|
||||||
sqlite3ExprCodeExprList(pParse, pList, 0);
|
regAgg = sqlite3GetTempRange(pParse, nArg);
|
||||||
regAgg = sqlite3StackToReg(pParse, nArg);
|
sqlite3ExprCodeExprList(pParse, pList, regAgg);
|
||||||
}else{
|
}else{
|
||||||
nArg = 0;
|
nArg = 0;
|
||||||
regAgg = 0;
|
regAgg = 0;
|
||||||
@@ -3029,6 +3034,7 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
|
|||||||
sqlite3VdbeAddOp4(v, OP_AggStep, 0, regAgg, pF->iMem,
|
sqlite3VdbeAddOp4(v, OP_AggStep, 0, regAgg, pF->iMem,
|
||||||
(void*)pF->pFunc, P4_FUNCDEF);
|
(void*)pF->pFunc, P4_FUNCDEF);
|
||||||
sqlite3VdbeChangeP5(v, nArg);
|
sqlite3VdbeChangeP5(v, nArg);
|
||||||
|
sqlite3ReleaseTempRange(pParse, regAgg, nArg);
|
||||||
if( addrNext ){
|
if( addrNext ){
|
||||||
sqlite3VdbeResolveLabel(v, addrNext);
|
sqlite3VdbeResolveLabel(v, addrNext);
|
||||||
}
|
}
|
||||||
@@ -3545,18 +3551,38 @@ int sqlite3Select(
|
|||||||
** then loop over the sorting index in order to get the output
|
** then loop over the sorting index in order to get the output
|
||||||
** in sorted order
|
** in sorted order
|
||||||
*/
|
*/
|
||||||
|
int regBase;
|
||||||
|
int regRecord;
|
||||||
|
int nCol;
|
||||||
|
int nGroupBy;
|
||||||
|
|
||||||
groupBySort = 1;
|
groupBySort = 1;
|
||||||
sqlite3ExprCodeExprList(pParse, pGroupBy, 0);
|
nGroupBy = pGroupBy->nExpr;
|
||||||
sqlite3VdbeAddOp2(v, OP_Sequence, sAggInfo.sortingIdx, 0);
|
nCol = nGroupBy + 1;
|
||||||
j = pGroupBy->nExpr+1;
|
j = nGroupBy+1;
|
||||||
|
for(i=0; i<sAggInfo.nColumn; i++){
|
||||||
|
if( sAggInfo.aCol[i].iSorterColumn>=j ){
|
||||||
|
nCol++;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
regBase = sqlite3GetTempRange(pParse, nCol);
|
||||||
|
sqlite3ExprCodeExprList(pParse, pGroupBy, regBase);
|
||||||
|
sqlite3VdbeAddOp2(v, OP_Sequence, sAggInfo.sortingIdx,regBase+nGroupBy);
|
||||||
|
j = nGroupBy+1;
|
||||||
for(i=0; i<sAggInfo.nColumn; i++){
|
for(i=0; i<sAggInfo.nColumn; i++){
|
||||||
struct AggInfo_col *pCol = &sAggInfo.aCol[i];
|
struct AggInfo_col *pCol = &sAggInfo.aCol[i];
|
||||||
if( pCol->iSorterColumn<j ) continue;
|
if( pCol->iSorterColumn>=j ){
|
||||||
sqlite3ExprCodeGetColumn(v, pCol->pTab, pCol->iColumn,pCol->iTable,0);
|
sqlite3ExprCodeGetColumn(v, pCol->pTab, pCol->iColumn, pCol->iTable,
|
||||||
j++;
|
j + regBase);
|
||||||
|
j++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sqlite3VdbeAddOp2(v, OP_MakeRecord, j, 0);
|
regRecord = sqlite3GetTempReg(pParse);
|
||||||
sqlite3VdbeAddOp2(v, OP_IdxInsert, sAggInfo.sortingIdx, 0);
|
sqlite3VdbeAddOp3(v, OP_RegMakeRec, regBase, nCol, regRecord);
|
||||||
|
sqlite3VdbeAddOp2(v, OP_IdxInsert, sAggInfo.sortingIdx, regRecord);
|
||||||
|
sqlite3ReleaseTempReg(pParse, regRecord);
|
||||||
|
sqlite3ReleaseTempRange(pParse, regBase, nCol);
|
||||||
sqlite3WhereEnd(pWInfo);
|
sqlite3WhereEnd(pWInfo);
|
||||||
sqlite3VdbeAddOp2(v, OP_Sort, sAggInfo.sortingIdx, addrEnd);
|
sqlite3VdbeAddOp2(v, OP_Sort, sAggInfo.sortingIdx, addrEnd);
|
||||||
VdbeComment((v, "GROUP BY sort"));
|
VdbeComment((v, "GROUP BY sort"));
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
*************************************************************************
|
*************************************************************************
|
||||||
** Internal interface definitions for SQLite.
|
** Internal interface definitions for SQLite.
|
||||||
**
|
**
|
||||||
** @(#) $Id: sqliteInt.h,v 1.645 2008/01/09 23:04:12 drh Exp $
|
** @(#) $Id: sqliteInt.h,v 1.646 2008/01/10 03:46:36 drh Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef _SQLITEINT_H_
|
#ifndef _SQLITEINT_H_
|
||||||
#define _SQLITEINT_H_
|
#define _SQLITEINT_H_
|
||||||
@@ -1399,6 +1399,10 @@ struct Parse {
|
|||||||
u8 checkSchema; /* Causes schema cookie check after an error */
|
u8 checkSchema; /* Causes schema cookie check after an error */
|
||||||
u8 nested; /* Number of nested calls to the parser/code generator */
|
u8 nested; /* Number of nested calls to the parser/code generator */
|
||||||
u8 parseError; /* True after a parsing error. Ticket #1794 */
|
u8 parseError; /* True after a parsing error. Ticket #1794 */
|
||||||
|
u8 nTempReg; /* Number of temporary registers in aTempReg[] */
|
||||||
|
int aTempReg[8]; /* Holding area for temporary registers */
|
||||||
|
int nRangeReg; /* Size of the temporary register block */
|
||||||
|
int iRangeReg; /* First register in temporary register block */
|
||||||
int nErr; /* Number of errors seen */
|
int nErr; /* Number of errors seen */
|
||||||
int nTab; /* Number of previously allocated VDBE cursors */
|
int nTab; /* Number of previously allocated VDBE cursors */
|
||||||
int nMem; /* Number of memory cells used so far */
|
int nMem; /* Number of memory cells used so far */
|
||||||
@@ -1692,6 +1696,10 @@ void sqlite3DequoteExpr(sqlite3*, Expr*);
|
|||||||
int sqlite3KeywordCode(const unsigned char*, int);
|
int sqlite3KeywordCode(const unsigned char*, int);
|
||||||
int sqlite3RunParser(Parse*, const char*, char **);
|
int sqlite3RunParser(Parse*, const char*, char **);
|
||||||
void sqlite3FinishCoding(Parse*);
|
void sqlite3FinishCoding(Parse*);
|
||||||
|
int sqlite3GetTempReg(Parse*);
|
||||||
|
void sqlite3ReleaseTempReg(Parse*,int);
|
||||||
|
int sqlite3GetTempRange(Parse*,int);
|
||||||
|
void sqlite3ReleaseTempRange(Parse*,int,int);
|
||||||
Expr *sqlite3Expr(sqlite3*, int, Expr*, Expr*, const Token*);
|
Expr *sqlite3Expr(sqlite3*, int, Expr*, Expr*, const Token*);
|
||||||
Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*, const Token*);
|
Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*, const Token*);
|
||||||
Expr *sqlite3RegisterExpr(Parse*,Token*);
|
Expr *sqlite3RegisterExpr(Parse*,Token*);
|
||||||
|
|||||||
Reference in New Issue
Block a user