]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add opcodes OP_ResultRow and OP_RegMakeRec which are register-based
authordrh <drh@noemail.net>
Wed, 2 Jan 2008 14:28:13 +0000 (14:28 +0000)
committerdrh <drh@noemail.net>
Wed, 2 Jan 2008 14:28:13 +0000 (14:28 +0000)
equivalents to OP_Callback and OP_MakeRecord.  Use the new opcodes. (CVS 4656)

FossilOrigin-Name: 4c7f35da7751c61a9b61b1d95adddcc37fff3266

manifest
manifest.uuid
src/analyze.c
src/expr.c
src/select.c
src/vdbe.c

index e078a512466d186b617b2999ce36c5460ee29cd6..d7caafca7f36c2ab68719a72f69032ce4198dbdb 100644 (file)
--- a/manifest
+++ b/manifest
@@ -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
index c38acced6cc49a1d20bfe30f94cbbdf80ceeaddc..79c505e502f3e2ade5a77d9be4592dd1d94717c0 100644 (file)
@@ -1 +1 @@
-03cc91b3b0ff9be192532f8a404b3c7b827e1449
\ No newline at end of file
+4c7f35da7751c61a9b61b1d95adddcc37fff3266
\ No newline at end of file
index 13e3ad34b1feb59f5e6073657caa92bce23a9ae7..8228d416c6198be96791be70f2e6075d36b3a977 100644 (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.
index 05932e2f2b544e4ed2da8d963654f5254249de14..c5e3a8fbd967165fd75cab3f816494f1f789bf34 100644 (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;
     }
   }
index 23f2c70a2174859e7d1bc6e4e7d9f7e8d6c47c25..e684966ba463df42283b44199750a1bd901baa39 100644 (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;
index 4c1071e21a90cc49df0a3a4dfc3ed2990ad7f2d8..1bfb812210121c40e52f018e3bed80fb7556f589 100644 (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 *
+**
+** 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;
 }