From: drh Date: Fri, 20 Jun 2008 18:13:25 +0000 (+0000) Subject: Add new Compare and Jump codes to the virtual machine. Use them in the X-Git-Tag: version-3.6.10~920 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=16ee60fff91b43d615fbc5df51037e83abc8b424;p=thirdparty%2Fsqlite.git Add new Compare and Jump codes to the virtual machine. Use them in the implementation of aggregate queries. (CVS 5257) FossilOrigin-Name: 083113652ff8f69b18cf1611710fdbbe5fbd9fef --- diff --git a/manifest b/manifest index 2e9b3ff62e..eb7a7f9cff 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sa\stest\sto\scheck\sthat\sopening\sa\ssecond\sconnection\sto\sa\sshared\scache\sdoes\snot\sreset\sthe\scache\ssize\sto\sits\sdefault\svalue.\s(CVS\s5256) -D 2008-06-20T17:51:17 +C Add\snew\sCompare\sand\sJump\scodes\sto\sthe\svirtual\smachine.\s\sUse\sthem\sin\sthe\nimplementation\sof\saggregate\squeries.\s(CVS\s5257) +D 2008-06-20T18:13:25 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7 F Makefile.in ff6f90048555a0088f6a4b7406bed5e55a7c4eff F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -141,7 +141,7 @@ F src/pragma.c 70e7c865dce85fdf9df81848af2169009a56ed08 F src/prepare.c 3c19149e75fbf3b08471a389f064da7302cad9c5 F src/printf.c 8b063da9dcde26b7c500a01444b718d86f21bc6e F src/random.c 5c754319d38abdd6acd74601ee0105504adc508a -F src/select.c 672a4812f7bf889176b52d3257bf21d2c08009f1 +F src/select.c 8393c47a170923f40602622bfa59b8e7cbff9027 F src/shell.c a12ea645271b7876c8f080146f48e20b00d367ec F src/sqlite.h.in 4c41b702bf6a105a485dfb61065f941c8cb0357d F src/sqlite3ext.h f162a72daef5ebf8b211fe8c0ec96e85d22fbf9b @@ -182,11 +182,11 @@ F src/update.c 2d7143b9014e955509cc4f323f9a9584fb898f34 F src/utf.c 8c94fa10efc78c2568d08d436acc59df4df7191b F src/util.c 920d6d5dfdf25f7b85d2093705d8716f9b387e3b F src/vacuum.c 14eb21b480924d87e791cd8ab6fb35ac563243ef -F src/vdbe.c d4b0efeedb4bfb088931addf926e99f4977346c9 -F src/vdbe.h 1e3722d471739c2b213c6283b60373290e52f7ea -F src/vdbeInt.h de321b2c02593e1420106634ed1f5a7d77ad35a7 +F src/vdbe.c b733eaea9bb821b710c7ccc0a80551e1daaae733 +F src/vdbe.h 1246ace5511258b2192487581f23985bbc61b1be +F src/vdbeInt.h 723fb796fc13346e01fb7269dcfe28f74006c5b3 F src/vdbeapi.c a7c6b8db324cf7eccff32de871dea36aa305c994 -F src/vdbeaux.c c61240e6776a4a88d61624734234d103bd7a31fa +F src/vdbeaux.c 5645351aed834221dac9f059f79021b5295a8626 F src/vdbeblob.c 9345f6dcd675fdcfdb537d2d2f487542d9ea136a F src/vdbefifo.c c46dae1194e4277bf007144d7e5b0c0b1c24f136 F src/vdbemem.c a39a822e6ae61c4cab4a512df4a315888b206911 @@ -600,7 +600,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 1dbced29de5f59ba2ebf877edcadf171540374d1 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e -P 6b9d92fc3f265ef75c9182e537812490bb818950 -R 71da1fcba8c73c8171b73b407d6eada6 -U danielk1977 -Z d3489b3e80ddc7822f5885b135f3fa25 +P 3546e245aaf5d75b9f52ffb3268da9bc26946396 +R 9ebc5eb0b944955c55dacd9381beebe7 +U drh +Z 957de0aa116eb421d5f8567d774f0a1d diff --git a/manifest.uuid b/manifest.uuid index 6457ad3bd7..75cd795ed9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3546e245aaf5d75b9f52ffb3268da9bc26946396 \ No newline at end of file +083113652ff8f69b18cf1611710fdbbe5fbd9fef \ No newline at end of file diff --git a/src/select.c b/src/select.c index f66214de0b..2de5b94e63 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.431 2008/06/20 15:24:02 drh Exp $ +** $Id: select.c,v 1.432 2008/06/20 18:13:25 drh Exp $ */ #include "sqliteInt.h" @@ -1875,8 +1875,9 @@ static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){ #ifndef SQLITE_OMIT_COMPOUND_SELECT /* -** This routine is called to process a query that is really the union -** or intersection of two or more separate queries. +** This routine is called to process a compound query form from +** two or more separate queries using UNION, UNION ALL, EXCEPT, or +** INTERSECT ** ** "p" points to the right-most of the two queries. the query on the ** left is p->pPrior. The left query could also be a compound query @@ -3291,12 +3292,10 @@ int sqlite3Select( /* The following variables hold addresses or labels for parts of the ** virtual machine program we are putting together */ int addrOutputRow; /* Start of subroutine that outputs a result row */ - int regOutputRow; /* Return address register for outputrow subroutine */ + int regOutputRow; /* Return address register for output subroutine */ int addrSetAbort; /* Set the abort flag and return */ int addrInitializeLoop; /* Start of code that initializes the input loop */ int addrTopOfLoop; /* Top of the input loop */ - int addrGroupByChange; /* Code that runs when any GROUP BY term changes */ - int addrProcessRow; /* Code to process a single input row */ int addrEnd; /* End of all processing */ int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */ int addrReset; /* Subroutine for resetting the accumulator */ @@ -3330,13 +3329,11 @@ int sqlite3Select( */ if( pGroupBy ){ KeyInfo *pKeyInfo; /* Keying information for the group by clause */ + int j1; /* Create labels that we will be needing */ - addrInitializeLoop = sqlite3VdbeMakeLabel(v); - addrGroupByChange = sqlite3VdbeMakeLabel(v); - addrProcessRow = sqlite3VdbeMakeLabel(v); /* If there is a GROUP BY clause we might need a sorting index to ** implement it. Allocate that sorting index now. If it turns out @@ -3474,15 +3471,10 @@ int sqlite3Select( sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j); } } - for(j=pGroupBy->nExpr-1; j>=0; j--){ - if( j==0 ){ - sqlite3VdbeAddOp3(v, OP_Eq, iAMem+j, addrProcessRow, iBMem+j); - }else{ - sqlite3VdbeAddOp3(v, OP_Ne, iAMem+j, addrGroupByChange, iBMem+j); - } - sqlite3VdbeChangeP4(v, -1, (void*)pKeyInfo->aColl[j], P4_COLLSEQ); - sqlite3VdbeChangeP5(v, SQLITE_NULLEQUAL); - } + sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr, + (char*)pKeyInfo, P4_KEYINFO_STATIC); + j1 = sqlite3VdbeCurrentAddr(v); + sqlite3VdbeAddOp3(v, OP_Jump, j1+1, 0, j1+1); /* Generate code that runs whenever the GROUP BY changes. ** Changes in the GROUP BY are detected by the previous code @@ -3493,7 +3485,6 @@ int sqlite3Select( ** and resets the aggregate accumulator registers in preparation ** for the next GROUP BY batch. */ - sqlite3VdbeResolveLabel(v, addrGroupByChange); for(j=0; jnExpr; j++){ sqlite3ExprCodeMove(pParse, iBMem+j, iAMem+j); } @@ -3507,7 +3498,7 @@ int sqlite3Select( /* Update the aggregate accumulators based on the content of ** the current row */ - sqlite3VdbeResolveLabel(v, addrProcessRow); + sqlite3VdbeJumpHere(v, j1); updateAccumulator(pParse, &sAggInfo); sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag); VdbeComment((v, "indicate data in accumulator")); @@ -3579,7 +3570,7 @@ int sqlite3Select( updateAccumulator(pParse, &sAggInfo); if( !pMinMax && flag ){ sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iBreak); - VdbeComment((v, "%s() by index", (flag==WHERE_ORDERBY_MIN?"min":"max"))); + VdbeComment((v, "%s() by index",(flag==WHERE_ORDERBY_MIN?"min":"max"))); } sqlite3WhereEnd(pWInfo); finalizeAggFunctions(pParse, &sAggInfo); diff --git a/src/vdbe.c b/src/vdbe.c index 2c0d12a70a..eec7b37314 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -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.751 2008/06/20 15:24:02 drh Exp $ +** $Id: vdbe.c,v 1.752 2008/06/20 18:13:25 drh Exp $ */ #include "sqliteInt.h" #include @@ -1731,6 +1731,53 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ break; } +/* Opcode: Compare P1 P2 P3 P4 * +** +** Compare to vectors of registers in reg(P1)..reg(P1+P3-1) (all this +** one "A") and in reg(P2)..reg(P2+P3-1) ("B"). Save the result of +** the comparison for use by the next OP_Jump instruct. +** +** P4 is a KeyInfo structure that defines collating sequences usedused for affinity purposes. The +** comparison is done for sorting purposes, so NULLs compare +** equal, NULLs are less than numbers, numbers are less than strings, +** and strings are less than blobs. +*/ +case OP_Compare: { + int n = pOp->p3; + int i, p1, p2; + const KeyInfo *pKeyInfo = pOp->p4.pKeyInfo; + assert( n>0 ); + p1 = pOp->p1; + assert( p1>0 && p1+n-1nMem ); + p2 = pOp->p2; + assert( p2>0 && p2+n-1nMem ); + for(i=0; iaMem[p1]); + REGISTER_TRACE(p2, &p->aMem[p2]); + p->iCompare = sqlite3MemCompare(&p->aMem[p1], &p->aMem[p2], + pKeyInfo && inField ? pKeyInfo->aColl[i] : 0); + if( p->iCompare ) break; + } + break; +} + +/* Opcode: Jump P1 P2 P3 * * +** +** Jump to the instruction at address P1, P2, or P3 depending on whether +** in the most recent OP_Compare instruction the P1 vector was less than +** equal to, or greater than the P2 vector, respectively. +*/ +case OP_Jump: { + if( p->iCompare<0 ){ + pc = pOp->p1 - 1; + }else if( p->iCompare==0 ){ + pc = pOp->p2 - 1; + }else{ + pc = pOp->p3 - 1; + } + break; +} + /* Opcode: And P1 P2 P3 * * ** ** Take the logical AND of the values in registers P1 and P2 and diff --git a/src/vdbe.h b/src/vdbe.h index 9a1e4a2de9..b19e66dc2c 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -15,7 +15,7 @@ ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** -** $Id: vdbe.h,v 1.132 2008/05/29 20:22:37 shane Exp $ +** $Id: vdbe.h,v 1.133 2008/06/20 18:13:25 drh Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ @@ -109,7 +109,8 @@ typedef struct VdbeOpList VdbeOpList; ** from a single sqliteMalloc(). But no copy is made and the calling ** function should *not* try to free the KeyInfo. */ -#define P4_KEYINFO_HANDOFF (-9) +#define P4_KEYINFO_HANDOFF (-15) +#define P4_KEYINFO_STATIC (-16) /* ** The Vdbe.aColName array contains 5n Mem structures, where n is the @@ -193,8 +194,11 @@ int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*); #ifndef NDEBUG void sqlite3VdbeComment(Vdbe*, const char*, ...); # define VdbeComment(X) sqlite3VdbeComment X + void sqlite3VdbeNoopComment(Vdbe*, const char*, ...); +# define VdbeNoopComment(X) sqlite3VdbeNoopComment X #else # define VdbeComment(X) +# define VdbeNoopComment(X) #endif #endif diff --git a/src/vdbeInt.h b/src/vdbeInt.h index ea8fafb623..7cbcb8e3aa 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -15,7 +15,7 @@ ** 6000 lines long) it was split up into several smaller files and ** this header information was factored out. ** -** $Id: vdbeInt.h,v 1.147 2008/06/06 15:04:37 drh Exp $ +** $Id: vdbeInt.h,v 1.148 2008/06/20 18:13:25 drh Exp $ */ #ifndef _VDBEINT_H_ #define _VDBEINT_H_ @@ -321,6 +321,7 @@ struct Vdbe { u8 expired; /* True if the VM needs to be recompiled */ u8 minWriteFileFormat; /* Minimum file format for writable database files */ u8 inVtabMethod; /* See comments above */ + int iCompare; /* Result of most recent OP_Compare comparison */ int nChange; /* Number of db changes made since last reset */ i64 startTime; /* Time when query started - used for profiling */ int btreeMask; /* Bitmask of db->aDb[] entries referenced */ diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 762377fdc5..e139fa9716 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -14,7 +14,7 @@ ** to version 2.8.7, all this code was combined into the vdbe.c source file. ** But that file was getting too big so this subroutines were split out. ** -** $Id: vdbeaux.c,v 1.389 2008/06/20 14:59:51 danielk1977 Exp $ +** $Id: vdbeaux.c,v 1.390 2008/06/20 18:13:25 drh Exp $ */ #include "sqliteInt.h" #include @@ -581,7 +581,10 @@ void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){ #ifndef NDEBUG /* -** Change the comment on the the most recently coded instruction. +** Change the comment on the the most recently coded instruction. Or +** insert a No-op and add the comment to that new instruction. This +** makes the code easier to read during debugging. None of this happens +** in a production build. */ void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){ va_list ap; @@ -595,7 +598,20 @@ void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){ va_end(ap); } } -#endif +void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){ + va_list ap; + sqlite3VdbeAddOp0(p, OP_Noop); + assert( p->nOp>0 || p->aOp==0 ); + assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed ); + if( p->nOp ){ + char **pz = &p->aOp[p->nOp-1].zComment; + va_start(ap, zFormat); + sqlite3_free(*pz); + *pz = sqlite3VMPrintf(p->db, zFormat, ap); + va_end(ap); + } +} +#endif /* NDEBUG */ /* ** Return the opcode for a given address. @@ -616,6 +632,7 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ char *zP4 = zTemp; assert( nTemp>=20 ); switch( pOp->p4type ){ + case P4_KEYINFO_STATIC: case P4_KEYINFO: { int i, j; KeyInfo *pKeyInfo = pOp->p4.pKeyInfo;