1
0
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:
drh
2004-01-30 14:49:16 +00:00
parent 0c37e6309b
commit 00706be366
6 changed files with 428 additions and 445 deletions

View File

@@ -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

View File

@@ -1 +1 @@
af73fbca839f8cbe39c21f1f9e439fe9b79005c8
c0faa1c67a967f028cd018e58988fb08bc814d3d

View File

@@ -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);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -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--;
/*

View File

@@ -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);
}
}