Add opcodes OP_ResultRow and OP_RegMakeRec which are register-based

equivalents to OP_Callback and OP_MakeRecord.  Use the new opcodes. (CVS 4656)

FossilOrigin-Name: 4c7f35da7751c61a9b61b1d95adddcc37fff3266
This commit is contained in:
drh 2008-01-02 14:28:13 +00:00
parent 2f6751f91e
commit a2a49dc9df
6 changed files with 96 additions and 47 deletions

View File

@ -1,5 +1,5 @@
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
@ -79,7 +79,7 @@ F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
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
@ -92,7 +92,7 @@ F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
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
@ -131,7 +131,7 @@ F src/pragma.c 4a7f377a509eb14e35b09d4bf7b808ef647aad0b
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
@ -168,7 +168,7 @@ F src/update.c 24ab2157d360bc20ac4447f50d3a70cd993a7d98
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
@ -603,7 +603,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
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

View File

@ -1 +1 @@
03cc91b3b0ff9be192532f8a404b3c7b827e1449
4c7f35da7751c61a9b61b1d95adddcc37fff3266

View File

@ -11,7 +11,7 @@
*************************************************************************
** This file contains code associated with the ANALYZE command.
**
** @(#) $Id: analyze.c,v 1.25 2008/01/02 00:34:37 drh Exp $
** @(#) $Id: analyze.c,v 1.26 2008/01/02 14:28:13 drh Exp $
*/
#ifndef SQLITE_OMIT_ANALYZE
#include "sqliteInt.h"
@ -149,7 +149,7 @@ static void analyzeOneTable(
sqlite3VdbeAddOp(v, OP_MemInt, 0, iMem+i);
}
for(i=0; i<nCol; i++){
sqlite3VdbeAddOp(v, OP_MemNull, iMem+nCol+i+1, 0);
sqlite3VdbeAddOp(v, OP_MemNull, 0, iMem+nCol+i+1);
}
/* Do the analysis.

View File

@ -12,7 +12,7 @@
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.322 2008/01/02 00:34:37 drh Exp $
** $Id: expr.c,v 1.323 2008/01/02 14:28:13 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -1798,14 +1798,14 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
*/
static const Token one = { (u8*)"1", 0, 1 };
Select *pSel;
int iMem;
int sop;
int iMem;
pExpr->iColumn = iMem = pParse->nMem++;
pSel = pExpr->pSelect;
iMem = pParse->nMem++;
if( pExpr->op==TK_SELECT ){
sop = SRT_Mem;
sqlite3VdbeAddOp(v, OP_MemNull, iMem, 0);
sqlite3VdbeAddOp(v, OP_MemNull, 0, iMem);
VdbeComment((v, "Init subquery result"));
}else{
sop = SRT_Exists;
@ -1817,6 +1817,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
if( sqlite3Select(pParse, pSel, sop, iMem, 0, 0, 0, 0) ){
return;
}
pExpr->iColumn = iMem;
break;
}
}

View File

@ -12,7 +12,7 @@
** 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"
@ -436,7 +436,7 @@ static void codeOffset(
** 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 */
@ -450,6 +450,29 @@ static void codeDistinct(
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
@ -490,8 +513,9 @@ static int selectInnerLoop(
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 );
@ -506,14 +530,24 @@ static int selectInnerLoop(
/* 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
@ -522,7 +556,7 @@ static int selectInnerLoop(
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);
}
@ -538,7 +572,7 @@ static int selectInnerLoop(
*/
#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);
}
@ -552,7 +586,7 @@ static int selectInnerLoop(
*/
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);
@ -564,7 +598,7 @@ static int selectInnerLoop(
*/
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{
@ -581,22 +615,20 @@ static int selectInnerLoop(
** 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);
@ -607,7 +639,6 @@ static int selectInnerLoop(
*/
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;
}
@ -618,6 +649,7 @@ static int selectInnerLoop(
*/
case SRT_Mem: {
assert( nColumn==1 );
sqlite3VdbeAddOp(v, OP_MemLoad, iMem+1, 0);
if( pOrderBy ){
pushOntoSorter(pParse, pOrderBy, p);
}else{
@ -635,12 +667,13 @@ static int selectInnerLoop(
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;
}
@ -653,7 +686,6 @@ static int selectInnerLoop(
*/
default: {
assert( eDest==SRT_Discard );
sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0);
break;
}
#endif
@ -2876,10 +2908,10 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
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 ){
@ -2934,7 +2966,7 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
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;

View File

@ -43,7 +43,7 @@
** 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>
@ -2384,6 +2384,7 @@ case OP_MakeRecord: {
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. */
@ -2411,11 +2412,13 @@ case OP_MakeRecord: {
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;
@ -2424,7 +2427,7 @@ case OP_MakeRecord: {
/* 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);
@ -2484,14 +2487,14 @@ case OP_MakeRecord: {
/* 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 ){
@ -4719,13 +4722,26 @@ case OP_IfMemZero: { /* no-push */
break;
}
/* Opcode: MemNull P1 * *
/* Opcode: IfMemNull P1 P2 *
**
** Store a NULL in memory cell P1
** 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 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;
}