mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
Add new Compare and Jump codes to the virtual machine. Use them in the
implementation of aggregate queries. (CVS 5257) FossilOrigin-Name: 083113652ff8f69b18cf1611710fdbbe5fbd9fef
This commit is contained in:
22
manifest
22
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)
|
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-20T17:51:17
|
D 2008-06-20T18:13:25
|
||||||
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
|
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
|
||||||
F Makefile.in ff6f90048555a0088f6a4b7406bed5e55a7c4eff
|
F Makefile.in ff6f90048555a0088f6a4b7406bed5e55a7c4eff
|
||||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||||
@@ -141,7 +141,7 @@ F src/pragma.c 70e7c865dce85fdf9df81848af2169009a56ed08
|
|||||||
F src/prepare.c 3c19149e75fbf3b08471a389f064da7302cad9c5
|
F src/prepare.c 3c19149e75fbf3b08471a389f064da7302cad9c5
|
||||||
F src/printf.c 8b063da9dcde26b7c500a01444b718d86f21bc6e
|
F src/printf.c 8b063da9dcde26b7c500a01444b718d86f21bc6e
|
||||||
F src/random.c 5c754319d38abdd6acd74601ee0105504adc508a
|
F src/random.c 5c754319d38abdd6acd74601ee0105504adc508a
|
||||||
F src/select.c 672a4812f7bf889176b52d3257bf21d2c08009f1
|
F src/select.c 8393c47a170923f40602622bfa59b8e7cbff9027
|
||||||
F src/shell.c a12ea645271b7876c8f080146f48e20b00d367ec
|
F src/shell.c a12ea645271b7876c8f080146f48e20b00d367ec
|
||||||
F src/sqlite.h.in 4c41b702bf6a105a485dfb61065f941c8cb0357d
|
F src/sqlite.h.in 4c41b702bf6a105a485dfb61065f941c8cb0357d
|
||||||
F src/sqlite3ext.h f162a72daef5ebf8b211fe8c0ec96e85d22fbf9b
|
F src/sqlite3ext.h f162a72daef5ebf8b211fe8c0ec96e85d22fbf9b
|
||||||
@@ -182,11 +182,11 @@ F src/update.c 2d7143b9014e955509cc4f323f9a9584fb898f34
|
|||||||
F src/utf.c 8c94fa10efc78c2568d08d436acc59df4df7191b
|
F src/utf.c 8c94fa10efc78c2568d08d436acc59df4df7191b
|
||||||
F src/util.c 920d6d5dfdf25f7b85d2093705d8716f9b387e3b
|
F src/util.c 920d6d5dfdf25f7b85d2093705d8716f9b387e3b
|
||||||
F src/vacuum.c 14eb21b480924d87e791cd8ab6fb35ac563243ef
|
F src/vacuum.c 14eb21b480924d87e791cd8ab6fb35ac563243ef
|
||||||
F src/vdbe.c d4b0efeedb4bfb088931addf926e99f4977346c9
|
F src/vdbe.c b733eaea9bb821b710c7ccc0a80551e1daaae733
|
||||||
F src/vdbe.h 1e3722d471739c2b213c6283b60373290e52f7ea
|
F src/vdbe.h 1246ace5511258b2192487581f23985bbc61b1be
|
||||||
F src/vdbeInt.h de321b2c02593e1420106634ed1f5a7d77ad35a7
|
F src/vdbeInt.h 723fb796fc13346e01fb7269dcfe28f74006c5b3
|
||||||
F src/vdbeapi.c a7c6b8db324cf7eccff32de871dea36aa305c994
|
F src/vdbeapi.c a7c6b8db324cf7eccff32de871dea36aa305c994
|
||||||
F src/vdbeaux.c c61240e6776a4a88d61624734234d103bd7a31fa
|
F src/vdbeaux.c 5645351aed834221dac9f059f79021b5295a8626
|
||||||
F src/vdbeblob.c 9345f6dcd675fdcfdb537d2d2f487542d9ea136a
|
F src/vdbeblob.c 9345f6dcd675fdcfdb537d2d2f487542d9ea136a
|
||||||
F src/vdbefifo.c c46dae1194e4277bf007144d7e5b0c0b1c24f136
|
F src/vdbefifo.c c46dae1194e4277bf007144d7e5b0c0b1c24f136
|
||||||
F src/vdbemem.c a39a822e6ae61c4cab4a512df4a315888b206911
|
F src/vdbemem.c a39a822e6ae61c4cab4a512df4a315888b206911
|
||||||
@@ -600,7 +600,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
|
|||||||
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||||
F tool/speedtest8.c 1dbced29de5f59ba2ebf877edcadf171540374d1
|
F tool/speedtest8.c 1dbced29de5f59ba2ebf877edcadf171540374d1
|
||||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||||
P 6b9d92fc3f265ef75c9182e537812490bb818950
|
P 3546e245aaf5d75b9f52ffb3268da9bc26946396
|
||||||
R 71da1fcba8c73c8171b73b407d6eada6
|
R 9ebc5eb0b944955c55dacd9381beebe7
|
||||||
U danielk1977
|
U drh
|
||||||
Z d3489b3e80ddc7822f5885b135f3fa25
|
Z 957de0aa116eb421d5f8567d774f0a1d
|
||||||
|
@@ -1 +1 @@
|
|||||||
3546e245aaf5d75b9f52ffb3268da9bc26946396
|
083113652ff8f69b18cf1611710fdbbe5fbd9fef
|
31
src/select.c
31
src/select.c
@@ -12,7 +12,7 @@
|
|||||||
** This file contains C code routines that are called by the parser
|
** This file contains C code routines that are called by the parser
|
||||||
** to handle SELECT statements in SQLite.
|
** 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"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -1875,8 +1875,9 @@ static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){
|
|||||||
|
|
||||||
#ifndef SQLITE_OMIT_COMPOUND_SELECT
|
#ifndef SQLITE_OMIT_COMPOUND_SELECT
|
||||||
/*
|
/*
|
||||||
** This routine is called to process a query that is really the union
|
** This routine is called to process a compound query form from
|
||||||
** or intersection of two or more separate queries.
|
** 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
|
** "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
|
** 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
|
/* The following variables hold addresses or labels for parts of the
|
||||||
** virtual machine program we are putting together */
|
** virtual machine program we are putting together */
|
||||||
int addrOutputRow; /* Start of subroutine that outputs a result row */
|
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 addrSetAbort; /* Set the abort flag and return */
|
||||||
int addrInitializeLoop; /* Start of code that initializes the input loop */
|
int addrInitializeLoop; /* Start of code that initializes the input loop */
|
||||||
int addrTopOfLoop; /* Top of 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 addrEnd; /* End of all processing */
|
||||||
int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */
|
int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */
|
||||||
int addrReset; /* Subroutine for resetting the accumulator */
|
int addrReset; /* Subroutine for resetting the accumulator */
|
||||||
@@ -3330,13 +3329,11 @@ int sqlite3Select(
|
|||||||
*/
|
*/
|
||||||
if( pGroupBy ){
|
if( pGroupBy ){
|
||||||
KeyInfo *pKeyInfo; /* Keying information for the group by clause */
|
KeyInfo *pKeyInfo; /* Keying information for the group by clause */
|
||||||
|
int j1;
|
||||||
|
|
||||||
/* Create labels that we will be needing
|
/* Create labels that we will be needing
|
||||||
*/
|
*/
|
||||||
|
|
||||||
addrInitializeLoop = sqlite3VdbeMakeLabel(v);
|
addrInitializeLoop = sqlite3VdbeMakeLabel(v);
|
||||||
addrGroupByChange = sqlite3VdbeMakeLabel(v);
|
|
||||||
addrProcessRow = sqlite3VdbeMakeLabel(v);
|
|
||||||
|
|
||||||
/* If there is a GROUP BY clause we might need a sorting index to
|
/* 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
|
** 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);
|
sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(j=pGroupBy->nExpr-1; j>=0; j--){
|
sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr,
|
||||||
if( j==0 ){
|
(char*)pKeyInfo, P4_KEYINFO_STATIC);
|
||||||
sqlite3VdbeAddOp3(v, OP_Eq, iAMem+j, addrProcessRow, iBMem+j);
|
j1 = sqlite3VdbeCurrentAddr(v);
|
||||||
}else{
|
sqlite3VdbeAddOp3(v, OP_Jump, j1+1, 0, j1+1);
|
||||||
sqlite3VdbeAddOp3(v, OP_Ne, iAMem+j, addrGroupByChange, iBMem+j);
|
|
||||||
}
|
|
||||||
sqlite3VdbeChangeP4(v, -1, (void*)pKeyInfo->aColl[j], P4_COLLSEQ);
|
|
||||||
sqlite3VdbeChangeP5(v, SQLITE_NULLEQUAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Generate code that runs whenever the GROUP BY changes.
|
/* Generate code that runs whenever the GROUP BY changes.
|
||||||
** Changes in the GROUP BY are detected by the previous code
|
** 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
|
** and resets the aggregate accumulator registers in preparation
|
||||||
** for the next GROUP BY batch.
|
** for the next GROUP BY batch.
|
||||||
*/
|
*/
|
||||||
sqlite3VdbeResolveLabel(v, addrGroupByChange);
|
|
||||||
for(j=0; j<pGroupBy->nExpr; j++){
|
for(j=0; j<pGroupBy->nExpr; j++){
|
||||||
sqlite3ExprCodeMove(pParse, iBMem+j, iAMem+j);
|
sqlite3ExprCodeMove(pParse, iBMem+j, iAMem+j);
|
||||||
}
|
}
|
||||||
@@ -3507,7 +3498,7 @@ int sqlite3Select(
|
|||||||
/* Update the aggregate accumulators based on the content of
|
/* Update the aggregate accumulators based on the content of
|
||||||
** the current row
|
** the current row
|
||||||
*/
|
*/
|
||||||
sqlite3VdbeResolveLabel(v, addrProcessRow);
|
sqlite3VdbeJumpHere(v, j1);
|
||||||
updateAccumulator(pParse, &sAggInfo);
|
updateAccumulator(pParse, &sAggInfo);
|
||||||
sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag);
|
sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag);
|
||||||
VdbeComment((v, "indicate data in accumulator"));
|
VdbeComment((v, "indicate data in accumulator"));
|
||||||
|
49
src/vdbe.c
49
src/vdbe.c
@@ -43,7 +43,7 @@
|
|||||||
** in this file for details. If in doubt, do not deviate from existing
|
** in this file for details. If in doubt, do not deviate from existing
|
||||||
** commenting and indentation practices when changing or adding code.
|
** 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 "sqliteInt.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -1731,6 +1731,53 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
|
|||||||
break;
|
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-1<p->nMem );
|
||||||
|
p2 = pOp->p2;
|
||||||
|
assert( p2>0 && p2+n-1<p->nMem );
|
||||||
|
for(i=0; i<n; i++, p1++, p2++){
|
||||||
|
REGISTER_TRACE(p1, &p->aMem[p1]);
|
||||||
|
REGISTER_TRACE(p2, &p->aMem[p2]);
|
||||||
|
p->iCompare = sqlite3MemCompare(&p->aMem[p1], &p->aMem[p2],
|
||||||
|
pKeyInfo && i<pKeyInfo->nField ? 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 * *
|
/* Opcode: And P1 P2 P3 * *
|
||||||
**
|
**
|
||||||
** Take the logical AND of the values in registers P1 and P2 and
|
** Take the logical AND of the values in registers P1 and P2 and
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
** or VDBE. The VDBE implements an abstract machine that runs a
|
** or VDBE. The VDBE implements an abstract machine that runs a
|
||||||
** simple program to access and modify the underlying database.
|
** 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_
|
#ifndef _SQLITE_VDBE_H_
|
||||||
#define _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
|
** from a single sqliteMalloc(). But no copy is made and the calling
|
||||||
** function should *not* try to free the KeyInfo.
|
** 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
|
** The Vdbe.aColName array contains 5n Mem structures, where n is the
|
||||||
@@ -193,8 +194,11 @@ int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
|
|||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
void sqlite3VdbeComment(Vdbe*, const char*, ...);
|
void sqlite3VdbeComment(Vdbe*, const char*, ...);
|
||||||
# define VdbeComment(X) sqlite3VdbeComment X
|
# define VdbeComment(X) sqlite3VdbeComment X
|
||||||
|
void sqlite3VdbeNoopComment(Vdbe*, const char*, ...);
|
||||||
|
# define VdbeNoopComment(X) sqlite3VdbeNoopComment X
|
||||||
#else
|
#else
|
||||||
# define VdbeComment(X)
|
# define VdbeComment(X)
|
||||||
|
# define VdbeNoopComment(X)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
** 6000 lines long) it was split up into several smaller files and
|
** 6000 lines long) it was split up into several smaller files and
|
||||||
** this header information was factored out.
|
** 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_
|
#ifndef _VDBEINT_H_
|
||||||
#define _VDBEINT_H_
|
#define _VDBEINT_H_
|
||||||
@@ -321,6 +321,7 @@ struct Vdbe {
|
|||||||
u8 expired; /* True if the VM needs to be recompiled */
|
u8 expired; /* True if the VM needs to be recompiled */
|
||||||
u8 minWriteFileFormat; /* Minimum file format for writable database files */
|
u8 minWriteFileFormat; /* Minimum file format for writable database files */
|
||||||
u8 inVtabMethod; /* See comments above */
|
u8 inVtabMethod; /* See comments above */
|
||||||
|
int iCompare; /* Result of most recent OP_Compare comparison */
|
||||||
int nChange; /* Number of db changes made since last reset */
|
int nChange; /* Number of db changes made since last reset */
|
||||||
i64 startTime; /* Time when query started - used for profiling */
|
i64 startTime; /* Time when query started - used for profiling */
|
||||||
int btreeMask; /* Bitmask of db->aDb[] entries referenced */
|
int btreeMask; /* Bitmask of db->aDb[] entries referenced */
|
||||||
|
@@ -14,7 +14,7 @@
|
|||||||
** to version 2.8.7, all this code was combined into the vdbe.c source file.
|
** 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.
|
** 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 "sqliteInt.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -581,7 +581,10 @@ void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){
|
|||||||
|
|
||||||
#ifndef NDEBUG
|
#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, ...){
|
void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){
|
||||||
va_list ap;
|
va_list ap;
|
||||||
@@ -595,7 +598,20 @@ void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){
|
|||||||
va_end(ap);
|
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.
|
** Return the opcode for a given address.
|
||||||
@@ -616,6 +632,7 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
|
|||||||
char *zP4 = zTemp;
|
char *zP4 = zTemp;
|
||||||
assert( nTemp>=20 );
|
assert( nTemp>=20 );
|
||||||
switch( pOp->p4type ){
|
switch( pOp->p4type ){
|
||||||
|
case P4_KEYINFO_STATIC:
|
||||||
case P4_KEYINFO: {
|
case P4_KEYINFO: {
|
||||||
int i, j;
|
int i, j;
|
||||||
KeyInfo *pKeyInfo = pOp->p4.pKeyInfo;
|
KeyInfo *pKeyInfo = pOp->p4.pKeyInfo;
|
||||||
|
Reference in New Issue
Block a user