mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-09 14:21:03 +03:00
Reuse registers better in the inner loop of a SELECT statement. (CVS 4719)
FossilOrigin-Name: 5ba4e5adf638c6812a2813961ea30a11a670409c
This commit is contained in:
14
manifest
14
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Registerification\sof\sthe\sVDBE\sis\scomplete.\s\sThe\soperand\sstack\shas\sbeen\nremoved\sfrom\sthe\scode.\s\sAll\sinstructions\soperate\sout\sof\sregisters\sonly.\s(CVS\s4718)
|
C Reuse\sregisters\sbetter\sin\sthe\sinner\sloop\sof\sa\sSELECT\sstatement.\s(CVS\s4719)
|
||||||
D 2008-01-17T16:22:14
|
D 2008-01-17T17:15:56
|
||||||
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,7 +92,7 @@ F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
|
|||||||
F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6
|
F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6
|
||||||
F src/delete.c 739ccbab8fa7478762bded5c9cc67f16a4d09dbe
|
F src/delete.c 739ccbab8fa7478762bded5c9cc67f16a4d09dbe
|
||||||
F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
|
F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
|
||||||
F src/expr.c 217ba4f47ffc17b10c79b091d896535e28aaa033
|
F src/expr.c f13ad688f64d93efe6c4f86c46e9d172d9166217
|
||||||
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
|
||||||
@@ -131,7 +131,7 @@ F src/pragma.c 155315ee3e6a861a0060ba4d184dfffd08ebbc03
|
|||||||
F src/prepare.c c31a879d6795f4765fd0b113675c6debbc96b7fd
|
F src/prepare.c c31a879d6795f4765fd0b113675c6debbc96b7fd
|
||||||
F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910
|
F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910
|
||||||
F src/random.c 02ef38b469237482f1ea14a78b2087cfbaec48bd
|
F src/random.c 02ef38b469237482f1ea14a78b2087cfbaec48bd
|
||||||
F src/select.c fb2d6653954478c0a7f4ca64b5c4a6f024212296
|
F src/select.c d9a394a2566849f9f7b03e2da3fd3ed4a91611eb
|
||||||
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
|
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
|
||||||
F src/shell.c 0691a3d52dc37cf6ac2f74838e5ff8ae1055ac9b
|
F src/shell.c 0691a3d52dc37cf6ac2f74838e5ff8ae1055ac9b
|
||||||
F src/sqlite.h.in 2a7e3776534bbe6ff2cdc058f3abebe91e7e429f
|
F src/sqlite.h.in 2a7e3776534bbe6ff2cdc058f3abebe91e7e429f
|
||||||
@@ -606,7 +606,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 5581160f43c60825d03de58e67aa66904d9d8964
|
P 706b41b70bd1e2030e6fa44358c38a26c5cf0985
|
||||||
R 9b66d11764748ee0bf0a1a49c0663779
|
R 87052e903d0b7d48d785076f690c7979
|
||||||
U drh
|
U drh
|
||||||
Z a08c417a1e9cffb9cc564c4f53d0978f
|
Z 0235b0e407d857e973632bb3bd532b62
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
706b41b70bd1e2030e6fa44358c38a26c5cf0985
|
5ba4e5adf638c6812a2813961ea30a11a670409c
|
||||||
@@ -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.347 2008/01/17 16:22:15 drh Exp $
|
** $Id: expr.c,v 1.348 2008/01/17 17:15:56 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -2162,7 +2162,7 @@ static int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
|||||||
r1 = sqlite3GetTempRange(pParse, nExpr);
|
r1 = sqlite3GetTempRange(pParse, nExpr);
|
||||||
sqlite3ExprCodeExprList(pParse, pList, r1);
|
sqlite3ExprCodeExprList(pParse, pList, r1);
|
||||||
}else{
|
}else{
|
||||||
nExpr = 0;
|
nExpr = r1 = 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
|
||||||
|
|||||||
55
src/select.c
55
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.404 2008/01/17 16:22:15 drh Exp $
|
** $Id: select.c,v 1.405 2008/01/17 17:15:56 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -516,11 +516,13 @@ static int selectInnerLoop(
|
|||||||
char *aff /* affinity string if eDest is SRT_Union */
|
char *aff /* affinity string if eDest is SRT_Union */
|
||||||
){
|
){
|
||||||
Vdbe *v = pParse->pVdbe;
|
Vdbe *v = pParse->pVdbe;
|
||||||
int i, n;
|
int i;
|
||||||
int hasDistinct; /* True if the DISTINCT keyword is present */
|
int hasDistinct; /* True if the DISTINCT keyword is present */
|
||||||
int iMem; /* Start of memory holding result set */
|
int regResult; /* Start of memory holding result set */
|
||||||
int eDest = pDest->eDest;
|
int eDest = pDest->eDest; /* How to dispose of results */
|
||||||
int iParm = pDest->iParm;
|
int iParm = pDest->iParm; /* First argument to disposal method */
|
||||||
|
int nResultCol; /* Number of result columns */
|
||||||
|
int nToFree; /* Number of result columns to release */
|
||||||
|
|
||||||
if( v==0 ) return 0;
|
if( v==0 ) return 0;
|
||||||
assert( pEList!=0 );
|
assert( pEList!=0 );
|
||||||
@@ -536,29 +538,30 @@ static int selectInnerLoop(
|
|||||||
/* Pull the requested columns.
|
/* Pull the requested columns.
|
||||||
*/
|
*/
|
||||||
if( nColumn>0 ){
|
if( nColumn>0 ){
|
||||||
n = nColumn;
|
nResultCol = nColumn;
|
||||||
}else{
|
}else{
|
||||||
n = pEList->nExpr;
|
nResultCol = pEList->nExpr;
|
||||||
}
|
}
|
||||||
if( pDest->iMem>0 ){
|
if( pDest->iMem>0 ){
|
||||||
iMem = pDest->iMem;
|
regResult = pDest->iMem;
|
||||||
|
nToFree = 0;
|
||||||
}else{
|
}else{
|
||||||
pDest->iMem = iMem = pParse->nMem+1;
|
pDest->iMem = regResult = sqlite3GetTempRange(pParse, nResultCol);
|
||||||
pParse->nMem += n;
|
nToFree = nResultCol;
|
||||||
}
|
}
|
||||||
if( nColumn>0 ){
|
if( nColumn>0 ){
|
||||||
for(i=0; i<nColumn; i++){
|
for(i=0; i<nColumn; i++){
|
||||||
sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, iMem+i);
|
sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult+i);
|
||||||
}
|
}
|
||||||
}else if( eDest!=SRT_Exists ){
|
}else if( eDest!=SRT_Exists ){
|
||||||
/* If the destination is an EXISTS(...) expression, the actual
|
/* If the destination is an EXISTS(...) expression, the actual
|
||||||
** values returned by the SELECT are not required.
|
** values returned by the SELECT are not required.
|
||||||
*/
|
*/
|
||||||
for(i=0; i<n; i++){
|
for(i=0; i<nResultCol; i++){
|
||||||
sqlite3ExprCode(pParse, pEList->a[i].pExpr, iMem+i);
|
sqlite3ExprCode(pParse, pEList->a[i].pExpr, regResult+i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nColumn = n;
|
nColumn = nResultCol;
|
||||||
|
|
||||||
/* If the DISTINCT keyword was present on the SELECT statement
|
/* If the DISTINCT keyword was present on the SELECT statement
|
||||||
** and this row has been seen before, then do not make this row
|
** and this row has been seen before, then do not make this row
|
||||||
@@ -567,7 +570,7 @@ static int selectInnerLoop(
|
|||||||
if( hasDistinct ){
|
if( hasDistinct ){
|
||||||
assert( pEList!=0 );
|
assert( pEList!=0 );
|
||||||
assert( pEList->nExpr==nColumn );
|
assert( pEList->nExpr==nColumn );
|
||||||
codeDistinct(pParse, distinct, iContinue, nColumn, iMem);
|
codeDistinct(pParse, distinct, iContinue, nColumn, regResult);
|
||||||
if( pOrderBy==0 ){
|
if( pOrderBy==0 ){
|
||||||
codeOffset(v, p, iContinue);
|
codeOffset(v, p, iContinue);
|
||||||
}
|
}
|
||||||
@@ -585,7 +588,7 @@ static int selectInnerLoop(
|
|||||||
case SRT_Union: {
|
case SRT_Union: {
|
||||||
int r1;
|
int r1;
|
||||||
r1 = sqlite3GetTempReg(pParse);
|
r1 = sqlite3GetTempReg(pParse);
|
||||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, nColumn, r1);
|
sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);
|
||||||
if( aff ){
|
if( aff ){
|
||||||
sqlite3VdbeChangeP4(v, -1, aff, P4_STATIC);
|
sqlite3VdbeChangeP4(v, -1, aff, P4_STATIC);
|
||||||
}
|
}
|
||||||
@@ -601,7 +604,7 @@ static int selectInnerLoop(
|
|||||||
case SRT_Except: {
|
case SRT_Except: {
|
||||||
int addr, r1;
|
int addr, r1;
|
||||||
r1 = sqlite3GetTempReg(pParse);
|
r1 = sqlite3GetTempReg(pParse);
|
||||||
addr = sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, nColumn, r1);
|
addr = sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);
|
||||||
sqlite3VdbeChangeP4(v, -1, aff, P4_STATIC);
|
sqlite3VdbeChangeP4(v, -1, aff, P4_STATIC);
|
||||||
sqlite3VdbeAddOp3(v, OP_NotFound, iParm, addr+3, r1);
|
sqlite3VdbeAddOp3(v, OP_NotFound, iParm, addr+3, r1);
|
||||||
sqlite3VdbeAddOp1(v, OP_Delete, iParm);
|
sqlite3VdbeAddOp1(v, OP_Delete, iParm);
|
||||||
@@ -615,7 +618,7 @@ static int selectInnerLoop(
|
|||||||
case SRT_Table:
|
case SRT_Table:
|
||||||
case SRT_EphemTab: {
|
case SRT_EphemTab: {
|
||||||
int r1 = sqlite3GetTempReg(pParse);
|
int r1 = sqlite3GetTempReg(pParse);
|
||||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, nColumn, r1);
|
sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);
|
||||||
if( pOrderBy ){
|
if( pOrderBy ){
|
||||||
pushOntoSorter(pParse, pOrderBy, p, r1);
|
pushOntoSorter(pParse, pOrderBy, p, r1);
|
||||||
}else{
|
}else{
|
||||||
@@ -638,17 +641,17 @@ static int selectInnerLoop(
|
|||||||
int addr2;
|
int addr2;
|
||||||
|
|
||||||
assert( nColumn==1 );
|
assert( nColumn==1 );
|
||||||
addr2 = sqlite3VdbeAddOp2(v, OP_IsNull, iMem, 0);
|
addr2 = sqlite3VdbeAddOp1(v, OP_IsNull, regResult);
|
||||||
p->affinity = sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affinity);
|
p->affinity = sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affinity);
|
||||||
if( pOrderBy ){
|
if( pOrderBy ){
|
||||||
/* At first glance you would think we could optimize out the
|
/* At first glance you would think we could optimize out the
|
||||||
** ORDER BY in this case since the order of entries in the set
|
** ORDER BY in this case since the order of entries in the set
|
||||||
** does not matter. But there might be a LIMIT clause, in which
|
** does not matter. But there might be a LIMIT clause, in which
|
||||||
** case the order does matter */
|
** case the order does matter */
|
||||||
pushOntoSorter(pParse, pOrderBy, p, iMem);
|
pushOntoSorter(pParse, pOrderBy, p, regResult);
|
||||||
}else{
|
}else{
|
||||||
int r1 = sqlite3GetTempReg(pParse);
|
int r1 = sqlite3GetTempReg(pParse);
|
||||||
sqlite3VdbeAddOp4(v, OP_MakeRecord, iMem, 1, r1, &p->affinity, 1);
|
sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, 1, r1, &p->affinity, 1);
|
||||||
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
|
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
|
||||||
sqlite3ReleaseTempReg(pParse, r1);
|
sqlite3ReleaseTempReg(pParse, r1);
|
||||||
}
|
}
|
||||||
@@ -671,9 +674,9 @@ static int selectInnerLoop(
|
|||||||
case SRT_Mem: {
|
case SRT_Mem: {
|
||||||
assert( nColumn==1 );
|
assert( nColumn==1 );
|
||||||
if( pOrderBy ){
|
if( pOrderBy ){
|
||||||
pushOntoSorter(pParse, pOrderBy, p, iMem);
|
pushOntoSorter(pParse, pOrderBy, p, regResult);
|
||||||
}else{
|
}else{
|
||||||
sqlite3VdbeAddOp2(v, OP_Move, iMem, iParm);
|
sqlite3VdbeAddOp2(v, OP_Move, regResult, iParm);
|
||||||
/* The LIMIT clause will jump out of the loop for us */
|
/* The LIMIT clause will jump out of the loop for us */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -688,13 +691,14 @@ static int selectInnerLoop(
|
|||||||
case SRT_Callback: {
|
case SRT_Callback: {
|
||||||
if( pOrderBy ){
|
if( pOrderBy ){
|
||||||
int r1 = sqlite3GetTempReg(pParse);
|
int r1 = sqlite3GetTempReg(pParse);
|
||||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, nColumn, r1);
|
sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);
|
||||||
pushOntoSorter(pParse, pOrderBy, p, r1);
|
pushOntoSorter(pParse, pOrderBy, p, r1);
|
||||||
sqlite3ReleaseTempReg(pParse, r1);
|
sqlite3ReleaseTempReg(pParse, r1);
|
||||||
}else if( eDest==SRT_Subroutine ){
|
}else if( eDest==SRT_Subroutine ){
|
||||||
|
nToFree = 0; /* Preserve registers. Subroutine will need them. */
|
||||||
sqlite3VdbeAddOp2(v, OP_Gosub, 0, iParm);
|
sqlite3VdbeAddOp2(v, OP_Gosub, 0, iParm);
|
||||||
}else{
|
}else{
|
||||||
sqlite3VdbeAddOp2(v, OP_ResultRow, iMem, nColumn);
|
sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nColumn);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -718,6 +722,7 @@ static int selectInnerLoop(
|
|||||||
sqlite3VdbeAddOp2(v, OP_AddImm, p->iLimit, -1);
|
sqlite3VdbeAddOp2(v, OP_AddImm, p->iLimit, -1);
|
||||||
sqlite3VdbeAddOp2(v, OP_IfZero, p->iLimit, iBreak);
|
sqlite3VdbeAddOp2(v, OP_IfZero, p->iLimit, iBreak);
|
||||||
}
|
}
|
||||||
|
sqlite3ReleaseTempRange(pParse, regResult, nToFree);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user