From 477df4b3ac7c7dfe62bde3672cbc22d0339e4183 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 5 Jan 2008 18:48:24 +0000 Subject: [PATCH] Modify OP_RegMakeRec to take a base register and count and optionally store results in the register specified by P3. (CVS 4689) FossilOrigin-Name: 6bb1b1bc1858028b743a4f660d42d5e9595dc022 --- manifest | 20 +++++++------- manifest.uuid | 2 +- src/build.c | 4 +-- src/select.c | 36 ++++++++++++------------- src/sqliteInt.h | 6 ++--- src/vdbe.c | 72 ++++++++++++++++++++++++++++++++----------------- 6 files changed, 81 insertions(+), 59 deletions(-) diff --git a/manifest b/manifest index 4248e4d700..8c9dd4e2fe 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\smemory\sleak\sintroduced\swith\s#4687.\s(CVS\s4688) -D 2008-01-05T18:44:29 +C Modify\sOP_RegMakeRec\sto\stake\sa\sbase\sregister\sand\scount\sand\soptionally\nstore\sresults\sin\sthe\sregister\sspecified\sby\sP3.\s(CVS\s4689) +D 2008-01-05T18:48:24 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7 F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -86,7 +86,7 @@ F src/btmutex.c 5d39da37c9d1282f3c6f9967afae6a34ee36b7ff F src/btree.c 5164b32950cfd41f2c5c31e8ff82c4a499918aef F src/btree.h 19dcf5ad23c17b98855da548e9a8e3eb4429d5eb F src/btreeInt.h 1c5a9da165718ef7de81e35ce9ab5d9ba9283f76 -F src/build.c 60a3ec74b45634654e06a72224ac01bd33ac69f1 +F src/build.c 26690c519a4e4d77f128cf3e9865e63bec24afd0 F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0 F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131 F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6 @@ -131,12 +131,12 @@ F src/pragma.c dfb200ec383b5ab3e81cd7bc4e1305e71053ef9a F src/prepare.c f1bb8eb642082e618a359c08e3e107490eafe0e3 F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910 F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da -F src/select.c fcde4b33ef106b64685ce842dc05e56e1c1116eb +F src/select.c faf793d135bdc6136c38db898ccf05a28d634d87 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96 F src/shell.c 5391e889384d2062249f668110d64ed16f601c4b F src/sqlite.h.in 2a7e3776534bbe6ff2cdc058f3abebe91e7e429f F src/sqlite3ext.h a93f59cdee3638dc0c9c086f80df743a4e68c3cb -F src/sqliteInt.h 1e7a6545eda5e5e670000775f5d74003e0bc4fbb +F src/sqliteInt.h 29a9502c0d9152580c3de8cb115da9aa8f9ce094 F src/sqliteLimit.h ee4430f88f69bf63527967bb35ca52af7b0ccb1e F src/table.c 1aeb9eab57b4235db86fe15a35dec76fb445a9c4 F src/tclsqlite.c 9923abeffc9b3d7dad58e92b319661521f60debf @@ -168,7 +168,7 @@ F src/update.c f322317ee492c0a648f8a44fd805dd85dbbe2f05 F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736 F src/util.c 05f31144bbd3f1a24f4139ae029c42545cb72624 F src/vacuum.c 3f34f278809bf3eb0b62ec46ff779e9c385b28f0 -F src/vdbe.c 0c16e643e83c8f14364213c6862864f31dbadca3 +F src/vdbe.c 2dda056501489818fc5e1fc2d90454718a1c7a61 F src/vdbe.h bb128757b84280504a1243c450fd13ead248ede5 F src/vdbeInt.h 31bd686595356284d5484592e2dc6e58025aa346 F src/vdbeapi.c f14174843bf4be2c9afdf2ef48b61e7c3ac62d7c @@ -604,7 +604,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 -P c449e04f1870b1ff726c95c0bf1c6c6a22ca588a -R 7feff0f8e24ec4a4191ddc4ce03d03a2 -U danielk1977 -Z 92958faf5e34756c3b8dada9d72fd997 +P 2b98b0fca82e285ae6b38384587aafa27985fa34 +R 39c27616db1d209bf42cb60b3febdbfc +U drh +Z d2a8f69e443e5ecf651b682bda1fceaf diff --git a/manifest.uuid b/manifest.uuid index 3244264c62..9306d07a7e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2b98b0fca82e285ae6b38384587aafa27985fa34 \ No newline at end of file +6bb1b1bc1858028b743a4f660d42d5e9595dc022 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 177c1e8056..0635fabc8c 100644 --- a/src/build.c +++ b/src/build.c @@ -22,7 +22,7 @@ ** COMMIT ** ROLLBACK ** -** $Id: build.c,v 1.459 2008/01/05 05:20:10 drh Exp $ +** $Id: build.c,v 1.460 2008/01/05 18:48:24 drh Exp $ */ #include "sqliteInt.h" #include @@ -1491,7 +1491,7 @@ void sqlite3EndTable( ** be redundant. */ if( pSelect ){ - SelectDest dest = {SRT_Table, 1, 0}; + SelectDest dest = {SRT_Table, 0, 1}; Table *pSelTab; sqlite3VdbeAddOp0(v, OP_Copy); sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, 0, iDb); diff --git a/src/select.c b/src/select.c index 4a3c8c83c4..98b64e52cd 100644 --- a/src/select.c +++ b/src/select.c @@ -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.388 2008/01/05 18:44:29 danielk1977 Exp $ +** $Id: select.c,v 1.389 2008/01/05 18:48:24 drh Exp $ */ #include "sqliteInt.h" @@ -463,9 +463,10 @@ 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 N, /* Number of elements */ int iMem /* First element */ ){ - sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, 0); + sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, N); sqlite3VdbeAddOp2(v, OP_Distinct, iTab, sqlite3VdbeCurrentAddr(v)+3); sqlite3VdbeAddOp2(v, OP_Pop, 1, 0); sqlite3VdbeAddOp2(v, OP_Goto, 0, addrRepeat); @@ -541,19 +542,18 @@ static int selectInnerLoop( }else{ n = pEList->nExpr; } - iMem = ++pParse->nMem; - pParse->nMem += n+1; - sqlite3VdbeAddOp2(v, OP_Integer, n, iMem); + iMem = pParse->nMem+1; + pParse->nMem += n; if( nColumn>0 ){ for(i=0; ia[i].pExpr, iMem+i+1); + sqlite3ExprCode(pParse, pEList->a[i].pExpr, iMem+i); } } nColumn = n; @@ -565,7 +565,7 @@ static int selectInnerLoop( if( hasDistinct ){ assert( pEList!=0 ); assert( pEList->nExpr==nColumn ); - codeDistinct(v, distinct, iContinue, iMem); + codeDistinct(v, distinct, iContinue, nColumn, iMem); if( pOrderBy==0 ){ codeOffset(v, p, iContinue, nColumn); } @@ -581,7 +581,7 @@ static int selectInnerLoop( */ #ifndef SQLITE_OMIT_COMPOUND_SELECT case SRT_Union: { - sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, 0); + sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, nColumn); if( aff ){ sqlite3VdbeChangeP4(v, -1, aff, P4_STATIC); } @@ -595,7 +595,7 @@ static int selectInnerLoop( */ case SRT_Except: { int addr; - addr = sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, 0); + addr = sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, nColumn); sqlite3VdbeChangeP4(v, -1, aff, P4_STATIC); sqlite3VdbeAddOp2(v, OP_NotFound, iParm, addr+3); sqlite3VdbeAddOp2(v, OP_Delete, iParm, 0); @@ -607,7 +607,7 @@ static int selectInnerLoop( */ case SRT_Table: case SRT_EphemTab: { - sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, 0); + sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, nColumn); if( pOrderBy ){ pushOntoSorter(pParse, pOrderBy, p); }else{ @@ -627,17 +627,17 @@ static int selectInnerLoop( int addr2; assert( nColumn==1 ); - addr2 = sqlite3VdbeAddOp2(v, OP_IfMemNull, iMem+1, 0); + addr2 = sqlite3VdbeAddOp2(v, OP_IfMemNull, iMem, 0); p->affinity = sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affinity); 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 */ - sqlite3VdbeAddOp2(v, OP_SCopy, iMem+1, 0); + sqlite3VdbeAddOp2(v, OP_SCopy, iMem, 0); pushOntoSorter(pParse, pOrderBy, p); }else{ - sqlite3VdbeAddOp4(v, OP_RegMakeRec, iMem, 0, 0, &p->affinity, 1); + sqlite3VdbeAddOp4(v, OP_RegMakeRec, iMem, 1, 0, &p->affinity, 1); sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, 0); } sqlite3VdbeJumpHere(v, addr2); @@ -658,7 +658,7 @@ static int selectInnerLoop( */ case SRT_Mem: { assert( nColumn==1 ); - sqlite3VdbeAddOp2(v, OP_SCopy, iMem+1, 0); + sqlite3VdbeAddOp2(v, OP_SCopy, iMem, 0); if( pOrderBy ){ pushOntoSorter(pParse, pOrderBy, p); }else{ @@ -676,13 +676,13 @@ static int selectInnerLoop( case SRT_Subroutine: case SRT_Callback: { if( pOrderBy ){ - sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, 0); + sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, nColumn); pushOntoSorter(pParse, pOrderBy, p); }else if( eDest==SRT_Subroutine ){ - for(i=0; i @@ -2131,6 +2131,25 @@ case OP_IsNull: { /* same as TK_ISNULL, no-push, jump */ break; } +/* Opcode: AnyNull P1 P2 P3 * * +** +** Check P3 registers beginning with P1. If any are NULL then jump +** to P2. +*/ +case OP_AnyNull: { /* no-push, jump, in1 */ + int n = pOp->p3; + assert( n>0 && pOp->p1+n<=p->nMem ); + while( n>0 ){ + if( pIn1->flags & MEM_Null ){ + pc = pOp->p2-1; + break; + } + n--; + pIn1++; + } + break; +} + /* Opcode: NotNull P1 P2 * ** ** Jump to P2 if the top abs(P1) values on the stack are all not NULL. @@ -2463,12 +2482,13 @@ op_column_out: ** This results in an index key. */ /* -** Opcode: RegMakeRec P1 P2 P4 +** Opcode: RegMakeRec P1 P2 P3 P4 * ** -** Works like OP_MakeRecord except data is taken from registers -** rather than from the stack. The P1 register is an integer which -** is the number of register to use in building the new record. -** Data is taken from P1+1, P1+2, ..., P1+mem[P1]. +** Builds a record like OP_MakeRecord. But the data is taken from +** P2 registers beginning with P1: P1, P1+1, P1+2, ..., P1+P2-1. +** The result is written into P3 or pushed onto the stack if P3 is zero. +** There is no jump on NULL - that can be done with a separate +** OP_AnyNull opcode. */ /* ** Opcode: RegMakeIRec P1 P2 P4 @@ -2526,21 +2546,18 @@ case OP_MakeRecord: { /* jump */ leaveOnStack = 0; nField = pOp->p1; } - jumpIfNull = pOp->p2; addRowid = pOp->opcode==OP_MakeIdxRec || pOp->opcode==OP_RegMakeIRec; zAffinity = pOp->p4.z; if( pOp->opcode==OP_RegMakeRec || pOp->opcode==OP_RegMakeIRec ){ - Mem *pCount; - assert( nField>0 && nField<=p->nMem ); - pCount = &p->aMem[nField]; - assert( pCount->flags & MEM_Int ); - assert( pCount->u.i>0 && pCount->u.i+nField<=p->nMem ); + assert( nField>0 && pOp->p2>0 && pOp->p2+nField<=p->nMem ); + pData0 = &p->aMem[nField]; + nField = pOp->p2; leaveOnStack = 1; - nField = pCount->u.i; - pData0 = &pCount[1]; + jumpIfNull = 0; pLast = &pData0[nField-1]; }else{ + jumpIfNull = pOp->p2; pData0 = &pTos[1-nField]; pLast = pTos; assert( pData0>=p->aStack ); @@ -2630,24 +2647,29 @@ case OP_MakeRecord: { /* jump */ if( !leaveOnStack ){ popStack(&pTos, nField+addRowid); } - pTos++; - pTos->n = nByte; + if( pOp->p3==0 ){ + pOut = ++pTos; + }else{ + pOut = &p->aMem[pOp->p3]; + Release(pOut); + } + pOut->n = nByte; if( nByte<=sizeof(zTemp) ){ assert( zNewRecord==(unsigned char *)zTemp ); - pTos->z = pTos->zShort; - memcpy(pTos->zShort, zTemp, nByte); - pTos->flags = MEM_Blob | MEM_Short; + pOut->z = pOut->zShort; + memcpy(pOut->zShort, zTemp, nByte); + pOut->flags = MEM_Blob | MEM_Short; }else{ assert( zNewRecord!=(unsigned char *)zTemp ); - pTos->z = (char*)zNewRecord; - pTos->flags = MEM_Blob | MEM_Dyn; - pTos->xDel = 0; + pOut->z = (char*)zNewRecord; + pOut->flags = MEM_Blob | MEM_Dyn; + pOut->xDel = 0; } if( nZero ){ - pTos->u.i = nZero; - pTos->flags |= MEM_Zero; + pOut->u.i = nZero; + pOut->flags |= MEM_Zero; } - pTos->enc = SQLITE_UTF8; /* In case the blob is ever converted to text */ + pOut->enc = SQLITE_UTF8; /* In case the blob is ever converted to text */ /* If a NULL was encountered and jumpIfNull is non-zero, take the jump. */ if( jumpIfNull && containsNull ){ -- 2.47.3