mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
Rework the VDBE data structures to combine string representations into the
same structure with integer and floating point. This opens the door to significant optimizations. (CVS 1202) FossilOrigin-Name: c0faa1c67a967f028cd018e58988fb08bc814d3d
This commit is contained in:
18
manifest
18
manifest
@@ -1,5 +1,5 @@
|
||||
C Make\ssure\smin()\sand\smax()\soptimizations\swork\sfor\ssubqueries.\sTicket\s#587.\s(CVS\s1201)
|
||||
D 2004-01-30T02:01:04
|
||||
C Rework\sthe\sVDBE\sdata\sstructures\sto\scombine\sstring\srepresentations\sinto\sthe\nsame\sstructure\swith\sinteger\sand\sfloating\spoint.\s\sThis\sopens\sthe\sdoor\sto\nsignificant\soptimizations.\s(CVS\s1202)
|
||||
D 2004-01-30T14:49:17
|
||||
F Makefile.in 0515ff9218ad8d5a8f6220f0494b8ef94c67013b
|
||||
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
||||
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
||||
@@ -32,7 +32,7 @@ F src/date.c c6b7e3fa5364d50fe19641882194f3c75364a5af
|
||||
F src/delete.c 0778fe05df0a1d62ac27fd1a3dba237c186ff4d1
|
||||
F src/encode.c 9e70ea1e4e746f23f18180949e94f1bb1c2220d3
|
||||
F src/expr.c 3928893e8a7576484cd2ed5548468ba978d8005a
|
||||
F src/func.c fd710743e4026dfebfd48c12d20b1a5c27318fa5
|
||||
F src/func.c 5a0face8c3a948c62677243987a18ba2f9ef9c9b
|
||||
F src/hash.c 9b56ef3b291e25168f630d5643a4264ec011c70e
|
||||
F src/hash.h 3247573ab95b9dd90bcca0307a75d9a16da1ccc7
|
||||
F src/insert.c 01f66866f35c986eab4a57373ca689a3255ef2df
|
||||
@@ -61,10 +61,10 @@ F src/trigger.c ce83e017b407d046e909d05373d7f8ee70f9f7f9
|
||||
F src/update.c 24260b4fda00c9726d27699a0561d53c0dccc397
|
||||
F src/util.c 64995b5949a5d377629ffd2598747bc771cade1e
|
||||
F src/vacuum.c 77485a64a6e4e358170f150fff681c1624a092b0
|
||||
F src/vdbe.c 802364c5b1b989ec4592aaffcbf575fa3eb0478b
|
||||
F src/vdbe.c fcd5b6f27b3041ef022cf04ecaf63bbdccf88950
|
||||
F src/vdbe.h 3957844e46fea71fd030e78f6a3bd2f7e320fb43
|
||||
F src/vdbeInt.h eab39bc209b267271bc4afbcf4991d6c229bae9a
|
||||
F src/vdbeaux.c dae9f8de7140daebbd621bfccb0982e17c352a9f
|
||||
F src/vdbeInt.h 6f12f5b9344cbb0e5cc2277458d84f7b951122bf
|
||||
F src/vdbeaux.c 358d955a23d29e268a3b45c428e49292b89dfcf5
|
||||
F src/where.c 1302d728bd338c237e6a8282e4e3eadbbdf11e45
|
||||
F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242
|
||||
F test/attach.test c26848402e7ac829e043e1fa5e0eb87032e5d81d
|
||||
@@ -182,7 +182,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
|
||||
F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
|
||||
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
|
||||
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
|
||||
P eafa714d1f0abe7e4822a6d137c2a7c6179ffab3
|
||||
R d39fa065e30e1e0532ab6dc3e864bd94
|
||||
P af73fbca839f8cbe39c21f1f9e439fe9b79005c8
|
||||
R 498fe1480c9c56c03607a7a6c9f9b96c
|
||||
U drh
|
||||
Z c358c54959e4dcb73fab284646bd586a
|
||||
Z 222ac74ccb7f92ccb269c2c94a8bca52
|
||||
|
@@ -1 +1 @@
|
||||
af73fbca839f8cbe39c21f1f9e439fe9b79005c8
|
||||
c0faa1c67a967f028cd018e58988fb08bc814d3d
|
20
src/func.c
20
src/func.c
@@ -16,7 +16,7 @@
|
||||
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
|
||||
** All other code has file scope.
|
||||
**
|
||||
** $Id: func.c,v 1.37 2004/01/19 04:53:25 jplyon Exp $
|
||||
** $Id: func.c,v 1.38 2004/01/30 14:49:17 drh Exp $
|
||||
*/
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
@@ -495,14 +495,16 @@ static void minStep(sqlite_func *context, int argc, const char **argv){
|
||||
if( p==0 || argc<1 || argv[0]==0 ) return;
|
||||
if( p->z==0 || sqliteCompare(argv[0],p->z)<0 ){
|
||||
int len;
|
||||
if( p->z && p->z!=p->zBuf ){
|
||||
if( !p->zBuf[0] ){
|
||||
sqliteFree(p->z);
|
||||
}
|
||||
len = strlen(argv[0]);
|
||||
if( len < sizeof(p->zBuf) ){
|
||||
p->z = p->zBuf;
|
||||
if( len < sizeof(p->zBuf)-1 ){
|
||||
p->z = &p->zBuf[1];
|
||||
p->zBuf[0] = 1;
|
||||
}else{
|
||||
p->z = sqliteMalloc( len+1 );
|
||||
p->zBuf[0] = 0;
|
||||
if( p->z==0 ) return;
|
||||
}
|
||||
strcpy(p->z, argv[0]);
|
||||
@@ -514,14 +516,16 @@ static void maxStep(sqlite_func *context, int argc, const char **argv){
|
||||
if( p==0 || argc<1 || argv[0]==0 ) return;
|
||||
if( p->z==0 || sqliteCompare(argv[0],p->z)>0 ){
|
||||
int len;
|
||||
if( p->z && p->z!=p->zBuf ){
|
||||
if( !p->zBuf[0] ){
|
||||
sqliteFree(p->z);
|
||||
}
|
||||
len = strlen(argv[0]);
|
||||
if( len < sizeof(p->zBuf) ){
|
||||
p->z = p->zBuf;
|
||||
if( len < sizeof(p->zBuf)-1 ){
|
||||
p->z = &p->zBuf[1];
|
||||
p->zBuf[0] = 1;
|
||||
}else{
|
||||
p->z = sqliteMalloc( len+1 );
|
||||
p->zBuf[0] = 0;
|
||||
if( p->z==0 ) return;
|
||||
}
|
||||
strcpy(p->z, argv[0]);
|
||||
@@ -533,7 +537,7 @@ static void minMaxFinalize(sqlite_func *context){
|
||||
if( p && p->z ){
|
||||
sqlite_set_result_string(context, p->z, strlen(p->z));
|
||||
}
|
||||
if( p && p->z && p->z!=p->zBuf ){
|
||||
if( p && !p->zBuf[0] ){
|
||||
sqliteFree(p->z);
|
||||
}
|
||||
}
|
||||
|
683
src/vdbe.c
683
src/vdbe.c
File diff suppressed because it is too large
Load Diff
@@ -106,47 +106,35 @@ struct Sorter {
|
||||
#define NBFS 32
|
||||
|
||||
/*
|
||||
** A single level of the stack is an instance of the following
|
||||
** structure. Except, string values are stored on a separate
|
||||
** list of of pointers to character. The reason for storing
|
||||
** strings separately is so that they can be easily passed
|
||||
** to the callback function.
|
||||
*/
|
||||
struct Stack {
|
||||
int i; /* Integer value */
|
||||
int n; /* Number of characters in string value, including '\0' */
|
||||
int flags; /* Some combination of STK_Null, STK_Str, STK_Dyn, etc. */
|
||||
double r; /* Real value */
|
||||
char z[NBFS]; /* Space for short strings */
|
||||
};
|
||||
typedef struct Stack Stack;
|
||||
|
||||
/*
|
||||
** Memory cells use the same structure as the stack except that space
|
||||
** for an arbitrary string is added.
|
||||
** A single level of the stack or a single memory cell
|
||||
** is an instance of the following structure.
|
||||
*/
|
||||
struct Mem {
|
||||
Stack s; /* All values of the memory cell besides string */
|
||||
char *z; /* String value for this memory cell */
|
||||
int i; /* Integer value */
|
||||
int n; /* Number of characters in string value, including '\0' */
|
||||
int flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
|
||||
double r; /* Real value */
|
||||
char *z; /* String value */
|
||||
char zShort[NBFS]; /* Space for short strings */
|
||||
};
|
||||
typedef struct Mem Mem;
|
||||
|
||||
/*
|
||||
** Allowed values for Stack.flags
|
||||
** Allowed values for Mem.flags
|
||||
*/
|
||||
#define STK_Null 0x0001 /* Value is NULL */
|
||||
#define STK_Str 0x0002 /* Value is a string */
|
||||
#define STK_Int 0x0004 /* Value is an integer */
|
||||
#define STK_Real 0x0008 /* Value is a real number */
|
||||
#define STK_Dyn 0x0010 /* Need to call sqliteFree() on zStack[] */
|
||||
#define STK_Static 0x0020 /* zStack[] points to a static string */
|
||||
#define STK_Ephem 0x0040 /* zStack[] points to an ephemeral string */
|
||||
#define MEM_Null 0x0001 /* Value is NULL */
|
||||
#define MEM_Str 0x0002 /* Value is a string */
|
||||
#define MEM_Int 0x0004 /* Value is an integer */
|
||||
#define MEM_Real 0x0008 /* Value is a real number */
|
||||
#define MEM_Dyn 0x0010 /* Need to call sqliteFree() on Mem.z */
|
||||
#define MEM_Static 0x0020 /* Mem.z points to a static string */
|
||||
#define MEM_Ephem 0x0040 /* Mem.z points to an ephemeral string */
|
||||
|
||||
/* The following STK_ value appears only in AggElem.aMem.s.flag fields.
|
||||
/* The following MEM_ value appears only in AggElem.aMem.s.flag fields.
|
||||
** It indicates that the corresponding AggElem.aMem.z points to a
|
||||
** aggregate function context that needs to be finalized.
|
||||
*/
|
||||
#define STK_AggCtx 0x0040 /* zStack[] points to an agg function context */
|
||||
#define MEM_AggCtx 0x0040 /* Mem.z points to an agg function context */
|
||||
|
||||
/*
|
||||
** The "context" argument for a installable function. A pointer to an
|
||||
@@ -159,12 +147,11 @@ typedef struct Mem Mem;
|
||||
** structure are known.
|
||||
**
|
||||
** This structure is defined inside of vdbe.c because it uses substructures
|
||||
** (Stack) which are only defined there.
|
||||
** (Mem) which are only defined there.
|
||||
*/
|
||||
struct sqlite_func {
|
||||
FuncDef *pFunc; /* Pointer to function information. MUST BE FIRST */
|
||||
Stack s; /* Small strings, ints, and double values go here */
|
||||
char *z; /* Space for holding dynamic string results */
|
||||
Mem s; /* The return value is stored here */
|
||||
void *pAgg; /* Aggregate context */
|
||||
u8 isError; /* Set to true for an error */
|
||||
u8 isStep; /* Current in the step function */
|
||||
@@ -237,8 +224,8 @@ struct Vdbe {
|
||||
int nLabelAlloc; /* Number of slots allocated in aLabel[] */
|
||||
int *aLabel; /* Space to hold the labels */
|
||||
int tos; /* Index of top of stack */
|
||||
Stack *aStack; /* The operand stack, except string values */
|
||||
char **zStack; /* Text or binary values of the stack */
|
||||
Mem *aStack; /* The operand stack, except string values */
|
||||
char **zArgv; /* Text values used by the callback */
|
||||
char **azColName; /* Becomes the 4th parameter to callbacks */
|
||||
int nCursor; /* Number of slots in aCsr[] */
|
||||
Cursor *aCsr; /* One element of this array for each open cursor */
|
||||
@@ -294,7 +281,7 @@ struct Vdbe {
|
||||
*/
|
||||
#define POPSTACK \
|
||||
assert(p->tos>=0); \
|
||||
if( aStack[p->tos].flags & STK_Dyn ) sqliteFree(zStack[p->tos]); \
|
||||
if( aStack[p->tos].flags & MEM_Dyn ) sqliteFree(aStack[p->tos].z); \
|
||||
p->tos--;
|
||||
|
||||
/*
|
||||
|
@@ -375,48 +375,48 @@ VdbeOp *sqliteVdbeGetOp(Vdbe *p, int addr){
|
||||
*/
|
||||
char *sqlite_set_result_string(sqlite_func *p, const char *zResult, int n){
|
||||
assert( !p->isStep );
|
||||
if( p->s.flags & STK_Dyn ){
|
||||
sqliteFree(p->z);
|
||||
if( p->s.flags & MEM_Dyn ){
|
||||
sqliteFree(p->s.z);
|
||||
}
|
||||
if( zResult==0 ){
|
||||
p->s.flags = STK_Null;
|
||||
p->s.flags = MEM_Null;
|
||||
n = 0;
|
||||
p->z = 0;
|
||||
p->s.z = 0;
|
||||
p->s.n = 0;
|
||||
}else{
|
||||
if( n<0 ) n = strlen(zResult);
|
||||
if( n<NBFS-1 ){
|
||||
memcpy(p->s.z, zResult, n);
|
||||
p->s.z[n] = 0;
|
||||
p->s.flags = STK_Str;
|
||||
p->z = p->s.z;
|
||||
memcpy(p->s.zShort, zResult, n);
|
||||
p->s.zShort[n] = 0;
|
||||
p->s.flags = MEM_Str;
|
||||
p->s.z = p->s.zShort;
|
||||
}else{
|
||||
p->z = sqliteMallocRaw( n+1 );
|
||||
if( p->z ){
|
||||
memcpy(p->z, zResult, n);
|
||||
p->z[n] = 0;
|
||||
p->s.z = sqliteMallocRaw( n+1 );
|
||||
if( p->s.z ){
|
||||
memcpy(p->s.z, zResult, n);
|
||||
p->s.z[n] = 0;
|
||||
}
|
||||
p->s.flags = STK_Str | STK_Dyn;
|
||||
p->s.flags = MEM_Str | MEM_Dyn;
|
||||
}
|
||||
p->s.n = n+1;
|
||||
}
|
||||
return p->z;
|
||||
return p->s.z;
|
||||
}
|
||||
void sqlite_set_result_int(sqlite_func *p, int iResult){
|
||||
assert( !p->isStep );
|
||||
if( p->s.flags & STK_Dyn ){
|
||||
sqliteFree(p->z);
|
||||
if( p->s.flags & MEM_Dyn ){
|
||||
sqliteFree(p->s.z);
|
||||
}
|
||||
p->s.i = iResult;
|
||||
p->s.flags = STK_Int;
|
||||
p->s.flags = MEM_Int;
|
||||
}
|
||||
void sqlite_set_result_double(sqlite_func *p, double rResult){
|
||||
assert( !p->isStep );
|
||||
if( p->s.flags & STK_Dyn ){
|
||||
sqliteFree(p->z);
|
||||
if( p->s.flags & MEM_Dyn ){
|
||||
sqliteFree(p->s.z);
|
||||
}
|
||||
p->s.r = rResult;
|
||||
p->s.flags = STK_Real;
|
||||
p->s.flags = MEM_Real;
|
||||
}
|
||||
void sqlite_set_result_error(sqlite_func *p, const char *zMsg, int n){
|
||||
assert( !p->isStep );
|
||||
@@ -446,7 +446,8 @@ void *sqlite_aggregate_context(sqlite_func *p, int nByte){
|
||||
assert( p && p->pFunc && p->pFunc->xStep );
|
||||
if( p->pAgg==0 ){
|
||||
if( nByte<=NBFS ){
|
||||
p->pAgg = (void*)p->z;
|
||||
p->pAgg = (void*)p->s.z;
|
||||
memset(p->pAgg, 0, nByte);
|
||||
}else{
|
||||
p->pAgg = sqliteMalloc( nByte );
|
||||
}
|
||||
@@ -508,8 +509,8 @@ int sqliteVdbeList(
|
||||
assert( p->popStack==0 );
|
||||
assert( p->explain );
|
||||
p->azColName = azColumnNames;
|
||||
p->azResColumn = p->zStack;
|
||||
for(i=0; i<5; i++) p->zStack[i] = p->aStack[i].z;
|
||||
p->azResColumn = p->zArgv;
|
||||
for(i=0; i<5; i++) p->zArgv[i] = p->aStack[i].zShort;
|
||||
p->rc = SQLITE_OK;
|
||||
for(i=p->pc; p->rc==SQLITE_OK && i<p->nOp; i++){
|
||||
if( db->flags & SQLITE_Interrupt ){
|
||||
@@ -522,19 +523,19 @@ int sqliteVdbeList(
|
||||
sqliteSetString(&p->zErrMsg, sqlite_error_string(p->rc), (char*)0);
|
||||
break;
|
||||
}
|
||||
sprintf(p->zStack[0],"%d",i);
|
||||
sprintf(p->zStack[2],"%d", p->aOp[i].p1);
|
||||
sprintf(p->zStack[3],"%d", p->aOp[i].p2);
|
||||
sprintf(p->zArgv[0],"%d",i);
|
||||
sprintf(p->zArgv[2],"%d", p->aOp[i].p1);
|
||||
sprintf(p->zArgv[3],"%d", p->aOp[i].p2);
|
||||
if( p->aOp[i].p3type==P3_POINTER ){
|
||||
sprintf(p->aStack[4].z, "ptr(%#x)", (int)p->aOp[i].p3);
|
||||
p->zStack[4] = p->aStack[4].z;
|
||||
sprintf(p->aStack[4].zShort, "ptr(%#x)", (int)p->aOp[i].p3);
|
||||
p->zArgv[4] = p->aStack[4].zShort;
|
||||
}else{
|
||||
p->zStack[4] = p->aOp[i].p3;
|
||||
p->zArgv[4] = p->aOp[i].p3;
|
||||
}
|
||||
p->zStack[1] = sqliteOpcodeNames[p->aOp[i].opcode];
|
||||
p->zArgv[1] = sqliteOpcodeNames[p->aOp[i].opcode];
|
||||
if( p->xCallback==0 ){
|
||||
p->pc = i+1;
|
||||
p->azResColumn = p->zStack;
|
||||
p->azResColumn = p->zArgv;
|
||||
p->nResColumn = 5;
|
||||
return SQLITE_ROW;
|
||||
}
|
||||
@@ -542,7 +543,7 @@ int sqliteVdbeList(
|
||||
p->rc = SQLITE_MISUSE;
|
||||
break;
|
||||
}
|
||||
if( p->xCallback(p->pCbArg, 5, p->zStack, p->azColName) ){
|
||||
if( p->xCallback(p->pCbArg, 5, p->zArgv, p->azColName) ){
|
||||
p->rc = SQLITE_ABORT;
|
||||
}
|
||||
if( sqliteSafetyOn(db) ){
|
||||
@@ -596,11 +597,11 @@ void sqliteVdbeMakeReady(
|
||||
assert( nVar>=0 );
|
||||
n = isExplain ? 10 : p->nOp;
|
||||
p->aStack = sqliteMalloc(
|
||||
n*(sizeof(p->aStack[0]) + 2*sizeof(char*)) /* aStack and zStack */
|
||||
n*(sizeof(p->aStack[0]) + 2*sizeof(char*)) /* aStack and zArgv */
|
||||
+ p->nVar*(sizeof(char*)+sizeof(int)+1) /* azVar, anVar, abVar */
|
||||
);
|
||||
p->zStack = (char**)&p->aStack[n];
|
||||
p->azColName = (char**)&p->zStack[n];
|
||||
p->zArgv = (char**)&p->aStack[n];
|
||||
p->azColName = (char**)&p->zArgv[n];
|
||||
p->azVar = (char**)&p->azColName[n];
|
||||
p->anVar = (int*)&p->azVar[p->nVar];
|
||||
p->abVar = (u8*)&p->anVar[p->nVar];
|
||||
@@ -656,15 +657,12 @@ void sqliteVdbeSorterReset(Vdbe *p){
|
||||
*/
|
||||
void sqliteVdbePopStack(Vdbe *p, int N){
|
||||
assert( N>=0 );
|
||||
if( p->zStack==0 ) return;
|
||||
assert( p->aStack || sqlite_malloc_failed );
|
||||
if( p->aStack==0 ) return;
|
||||
while( N-- > 0 ){
|
||||
if( p->aStack[p->tos].flags & STK_Dyn ){
|
||||
sqliteFree(p->zStack[p->tos]);
|
||||
if( p->aStack[p->tos].flags & MEM_Dyn ){
|
||||
sqliteFree(p->aStack[p->tos].z);
|
||||
}
|
||||
p->aStack[p->tos].flags = 0;
|
||||
p->zStack[p->tos] = 0;
|
||||
p->tos--;
|
||||
}
|
||||
}
|
||||
@@ -686,20 +684,19 @@ void sqliteVdbeAggReset(Agg *pAgg){
|
||||
assert( pAgg->apFunc!=0 );
|
||||
for(i=0; i<pAgg->nMem; i++){
|
||||
Mem *pMem = &pElem->aMem[i];
|
||||
if( pAgg->apFunc[i] && (pMem->s.flags & STK_AggCtx)!=0 ){
|
||||
if( pAgg->apFunc[i] && (pMem->flags & MEM_AggCtx)!=0 ){
|
||||
sqlite_func ctx;
|
||||
ctx.pFunc = pAgg->apFunc[i];
|
||||
ctx.s.flags = STK_Null;
|
||||
ctx.z = 0;
|
||||
ctx.s.flags = MEM_Null;
|
||||
ctx.pAgg = pMem->z;
|
||||
ctx.cnt = pMem->s.i;
|
||||
ctx.cnt = pMem->i;
|
||||
ctx.isStep = 0;
|
||||
ctx.isError = 0;
|
||||
(*pAgg->apFunc[i]->xFinalize)(&ctx);
|
||||
if( pMem->z!=0 && pMem->z!=pMem->s.z ){
|
||||
if( pMem->z!=0 && pMem->z!=pMem->zShort ){
|
||||
sqliteFree(pMem->z);
|
||||
}
|
||||
}else if( pMem->s.flags & STK_Dyn ){
|
||||
}else if( pMem->flags & MEM_Dyn ){
|
||||
sqliteFree(pMem->z);
|
||||
}
|
||||
}
|
||||
@@ -765,7 +762,7 @@ static void Cleanup(Vdbe *p){
|
||||
closeAllCursors(p);
|
||||
if( p->aMem ){
|
||||
for(i=0; i<p->nMem; i++){
|
||||
if( p->aMem[i].s.flags & STK_Dyn ){
|
||||
if( p->aMem[i].flags & MEM_Dyn ){
|
||||
sqliteFree(p->aMem[i].z);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user