-C Remove\sa\ssurplus\sOP_Close\sfrom\sdelete.c.\s\sFixes\sa\sproblem\swith\s(4654).\s(CVS\s4655)
-D 2008-01-02T13:05:51
+C Add\sopcodes\sOP_ResultRow\sand\sOP_RegMakeRec\swhich\sare\sregister-based\nequivalents\sto\sOP_Callback\sand\sOP_MakeRecord.\s\sUse\sthe\snew\sopcodes.\s(CVS\s4656)
+D 2008-01-02T14:28:13
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
F sqlite3.def a96c1d0d39362b763d2ddba220a32da41a15c4b4
F sqlite3.pc.in abed4664817e1cd500f2276142c71958087c16bc
F src/alter.c 23d18ec53ef27fcb5e5ae9ca050217231ae15a0d
-F src/analyze.c cb25936f0148ee65c825a49f8064292a98050a50
+F src/analyze.c 40806c79cf2cd4fd0f6396d3d283fa05711439d1
F src/attach.c 95658e74e3e0d1cbdb8658817516d4d1467fc13d
F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627
F src/btmutex.c 5d39da37c9d1282f3c6f9967afae6a34ee36b7ff
F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6
F src/delete.c 9a98d854ac2613d14616f5023577a6bec53b2d0e
F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
-F src/expr.c c3fb939d6801071ce19243521ca444eca40b057a
+F src/expr.c 9f46128496d750edc0a2b32585a109defd9ce74c
F src/func.c 996071cf0af9d967e58b69fce1909555059ebc7d
F src/hash.c 45a7005aac044b6c86bd7e49c44bc15d30006d6c
F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53
F src/prepare.c 7aeba7851773fbe3950a26b35d3389bef0eb1c62
F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910
F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da
-F src/select.c 55b1a99e1d28a6ec3db2870a9f3f932fb3e7cb2a
+F src/select.c c0a225dc3133f914760908c7a73fce83b2834fbb
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
F src/shell.c 77895a54c2082157e169c857a2e244525ec25af7
F src/sqlite.h.in 2a7e3776534bbe6ff2cdc058f3abebe91e7e429f
F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736
F src/util.c 05f31144bbd3f1a24f4139ae029c42545cb72624
F src/vacuum.c 25ffbd766f25bca099ead1c1e11f5528c86102b8
-F src/vdbe.c 56a6e80d3357622305cffe6ea509e5d643e7dadb
+F src/vdbe.c 85e44649ad750d4c249751693ca93b4f57737b0f
F src/vdbe.h a042e6d3b567ac81f182ca5b4639807621355822
F src/vdbeInt.h 2985f1369273e635898cf5952237efcb3fdb21f3
F src/vdbeapi.c 4acfaab3e10c99eb66c5332979d7b14a1c3505ae
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P f1966a8a47fca85f7862c0797a527ab01ac8b0c1
-R 087c5875afd19f460dd964b443ff0b13
+P 03cc91b3b0ff9be192532f8a404b3c7b827e1449
+R 7a6df4f12366724f53264755c79c306d
U drh
-Z 539bcbd7c9fe31e2d5dc24d68f84bb81
+Z 99aefce3e13cf9b619d1d8015ce6d124
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
-** $Id: select.c,v 1.374 2008/01/02 00:34:37 drh Exp $
+** $Id: select.c,v 1.375 2008/01/02 14:28:13 drh Exp $
*/
#include "sqliteInt.h"
** A jump to addrRepeat is made and the N+1 values are popped from the
** stack if the top N elements are not distinct.
*/
-static void codeDistinct(
+static void codeDistinct_OLD(
Vdbe *v, /* Generate code into this VM */
int iTab, /* A sorting index used to test for distinctness */
int addrRepeat, /* Jump to here if not distinct */
sqlite3VdbeAddOp(v, OP_IdxInsert, iTab, 0);
}
+/*
+** Add code that will check to make sure the top N elements of the
+** stack are distinct. iTab is a sorting index that holds previously
+** seen combinations of the N values. A new entry is made in iTab
+** if the current N values are new.
+**
+** A jump to addrRepeat is made and the N+1 values are popped from the
+** stack if the top N elements are not distinct.
+*/
+static void codeDistinct(
+ Vdbe *v, /* Generate code into this VM */
+ int iTab, /* A sorting index used to test for distinctness */
+ int addrRepeat, /* Jump to here if not distinct */
+ int iMem /* First element */
+){
+ sqlite3VdbeAddOp(v, OP_RegMakeRec, iMem, 0);
+ sqlite3VdbeAddOp(v, OP_Distinct, iTab, sqlite3VdbeCurrentAddr(v)+3);
+ sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
+ sqlite3VdbeAddOp(v, OP_Goto, 0, addrRepeat);
+ VdbeComment((v, "skip indistinct records"));
+ sqlite3VdbeAddOp(v, OP_IdxInsert, iTab, 0);
+}
+
/*
** Generate an error message when a SELECT is used within a subexpression
** (example: "a IN (SELECT * FROM table)") but it has more than 1 result
char *aff /* affinity string if eDest is SRT_Union */
){
Vdbe *v = pParse->pVdbe;
- int i;
+ int i, n;
int hasDistinct; /* True if the DISTINCT keyword is present */
+ int iMem; /* Start of memory holding result set */
if( v==0 ) return 0;
assert( pEList!=0 );
/* Pull the requested columns.
*/
+ if( nColumn>0 ){
+ n = nColumn;
+ }else{
+ n = pEList->nExpr;
+ }
+ iMem = pParse->nMem;
+ pParse->nMem += n+1;
+ sqlite3VdbeAddOp(v, OP_MemInt, n, iMem);
if( nColumn>0 ){
for(i=0; i<nColumn; i++){
- sqlite3VdbeAddOp(v, OP_Column, srcTab, i);
+ sqlite3VdbeOp3Int(v, OP_Column, srcTab, i, iMem+i+1);
}
}else{
- nColumn = pEList->nExpr;
- sqlite3ExprCodeExprList(pParse, pEList);
+ for(i=0; i<n; i++){
+ sqlite3ExprIntoReg(pParse, pEList->a[i].pExpr, iMem+i+1);
+ }
}
+ nColumn = n;
/* If the DISTINCT keyword was present on the SELECT statement
** and this row has been seen before, then do not make this row
if( hasDistinct ){
assert( pEList!=0 );
assert( pEList->nExpr==nColumn );
- codeDistinct(v, distinct, iContinue, nColumn);
+ codeDistinct(v, distinct, iContinue, iMem);
if( pOrderBy==0 ){
codeOffset(v, p, iContinue, nColumn);
}
*/
#ifndef SQLITE_OMIT_COMPOUND_SELECT
case SRT_Union: {
- sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);
+ sqlite3VdbeAddOp(v, OP_RegMakeRec, iMem, 0);
if( aff ){
sqlite3VdbeChangeP3(v, -1, aff, P3_STATIC);
}
*/
case SRT_Except: {
int addr;
- addr = sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);
+ addr = sqlite3VdbeAddOp(v, OP_RegMakeRec, iMem, 0);
sqlite3VdbeChangeP3(v, -1, aff, P3_STATIC);
sqlite3VdbeAddOp(v, OP_NotFound, iParm, addr+3);
sqlite3VdbeAddOp(v, OP_Delete, iParm, 0);
*/
case SRT_Table:
case SRT_EphemTab: {
- sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);
+ sqlite3VdbeAddOp(v, OP_RegMakeRec, iMem, 0);
if( pOrderBy ){
pushOntoSorter(pParse, pOrderBy, p);
}else{
** item into the set table with bogus data.
*/
case SRT_Set: {
- int addr1 = sqlite3VdbeCurrentAddr(v);
int addr2;
assert( nColumn==1 );
- sqlite3VdbeAddOp(v, OP_NotNull, -1, addr1+3);
- sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
- addr2 = sqlite3VdbeAddOp(v, OP_Goto, 0, 0);
+ addr2 = sqlite3VdbeAddOp(v, OP_IfMemNull, iMem+1, 0);
p->affinity = sqlite3CompareAffinity(pEList->a[0].pExpr,(iParm>>16)&0xff);
if( pOrderBy ){
/* At first glance you would think we could optimize out the
** 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
** case the order does matter */
+ sqlite3VdbeAddOp(v, OP_MemLoad, iMem+1, 0);
pushOntoSorter(pParse, pOrderBy, p);
}else{
- sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &p->affinity, 1);
+ sqlite3VdbeOp3(v, OP_RegMakeRec, iMem, 0, &p->affinity, 1);
sqlite3VdbeAddOp(v, OP_IdxInsert, (iParm&0x0000FFFF), 0);
}
sqlite3VdbeJumpHere(v, addr2);
*/
case SRT_Exists: {
sqlite3VdbeAddOp(v, OP_MemInt, 1, iParm);
- sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0);
/* The LIMIT clause will terminate the loop for us */
break;
}
*/
case SRT_Mem: {
assert( nColumn==1 );
+ sqlite3VdbeAddOp(v, OP_MemLoad, iMem+1, 0);
if( pOrderBy ){
pushOntoSorter(pParse, pOrderBy, p);
}else{
case SRT_Subroutine:
case SRT_Callback: {
if( pOrderBy ){
- sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);
+ sqlite3VdbeAddOp(v, OP_RegMakeRec, iMem, 0);
pushOntoSorter(pParse, pOrderBy, p);
}else if( eDest==SRT_Subroutine ){
+ for(i=0; i<nColumn; i++) sqlite3VdbeAddOp(v, OP_MemLoad, iMem+i+1, 0);
sqlite3VdbeAddOp(v, OP_Gosub, 0, iParm);
}else{
- sqlite3VdbeAddOp(v, OP_Callback, nColumn, 0);
+ sqlite3VdbeAddOp(v, OP_ResultRow, iMem+1, nColumn);
}
break;
}
*/
default: {
assert( eDest==SRT_Discard );
- sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0);
break;
}
#endif
return;
}
for(i=0; i<pAggInfo->nColumn; i++){
- sqlite3VdbeAddOp(v, OP_MemNull, pAggInfo->aCol[i].iMem, 0);
+ sqlite3VdbeAddOp(v, OP_MemNull, 0, pAggInfo->aCol[i].iMem);
}
for(pFunc=pAggInfo->aFunc, i=0; i<pAggInfo->nFunc; i++, pFunc++){
- sqlite3VdbeAddOp(v, OP_MemNull, pFunc->iMem, 0);
+ sqlite3VdbeAddOp(v, OP_MemNull, 0, pFunc->iMem);
if( pFunc->iDistinct>=0 ){
Expr *pE = pFunc->pExpr;
if( pE->pList==0 || pE->pList->nExpr!=1 ){
if( pF->iDistinct>=0 ){
addrNext = sqlite3VdbeMakeLabel(v);
assert( nArg==1 );
- codeDistinct(v, pF->iDistinct, addrNext, 1);
+ codeDistinct_OLD(v, pF->iDistinct, addrNext, 1);
}
if( pF->pFunc->needCollSeq ){
CollSeq *pColl = 0;
** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
-** $Id: vdbe.c,v 1.662 2008/01/02 00:34:37 drh Exp $
+** $Id: vdbe.c,v 1.663 2008/01/02 14:28:13 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
u32 serial_type; /* Type field */
int containsNull = 0; /* True if any of the data fields are NULL */
Mem *pData0; /* Bottom of the stack */
+ Mem *pLast; /* Top of the stack */
int leaveOnStack; /* If true, leave the entries on the stack */
int nField; /* Number of fields in the record */
int jumpIfNull; /* Jump here if non-zero and any entries are NULL. */
pCount = &p->aMem[nField];
assert( pCount->flags & MEM_Int );
assert( pCount->u.i>=0 && pCount->u.i+nField<p->nMem );
- assert( leaveOnStack==1 );
+ leaveOnStack = 1;
nField = pCount->u.i;
pData0 = &pCount[1];
+ pLast = &pData0[nField-1];
}else{
pData0 = &pTos[1-nField];
+ pLast = pTos;
assert( pData0>=p->aStack );
}
containsNull = 0;
/* Loop through the elements that will make up the record to figure
** out how much space is required for the new record.
*/
- for(pRec=pData0; pRec<=pTos; pRec++){
+ for(pRec=pData0; pRec<=pLast; pRec++){
int len;
if( zAffinity ){
applyAffinity(pRec, zAffinity[pRec-pData0], encoding);
/* Write the record */
i = sqlite3PutVarint(zNewRecord, nHdr);
- for(pRec=pData0; pRec<=pTos; pRec++){
+ for(pRec=pData0; pRec<=pLast; pRec++){
serial_type = sqlite3VdbeSerialType(pRec, file_format);
i += sqlite3PutVarint(&zNewRecord[i], serial_type); /* serial type */
}
if( addRowid ){
i += sqlite3PutVarint(&zNewRecord[i], sqlite3VdbeSerialType(pRowid, 0));
}
- for(pRec=pData0; pRec<=pTos; pRec++){ /* serial data */
+ for(pRec=pData0; pRec<=pLast; pRec++){ /* serial data */
i += sqlite3VdbeSerialPut(&zNewRecord[i], nByte-i, pRec, file_format);
}
if( addRowid ){
break;
}
-/* Opcode: MemNull P1 * *
+/* Opcode: IfMemNull P1 P2 *
+**
+** If the value of memory cell P1 is NULL, jump to P2.
+*/
+case OP_IfMemNull: { /* no-push */
+ int i = pOp->p1;
+ assert( i>=0 && i<p->nMem );
+ if( p->aMem[i].flags & MEM_Null ){
+ pc = pOp->p2 - 1;
+ }
+ break;
+}
+
+/* Opcode: MemNull * P2 *
**
-** Store a NULL in memory cell P1
+** Store a NULL in memory cell P2
*/
case OP_MemNull: {
- assert( pOp->p1>=0 && pOp->p1<p->nMem );
- sqlite3VdbeMemSetNull(&p->aMem[pOp->p1]);
+ assert( pOp->p2>=0 && pOp->p2<p->nMem );
+ sqlite3VdbeMemSetNull(&p->aMem[pOp->p2]);
break;
}