diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/pager.c | 4 | ||||
-rw-r--r-- | src/printf.c | 62 | ||||
-rw-r--r-- | src/vdbeaux.c | 196 |
3 files changed, 131 insertions, 131 deletions
diff --git a/src/pager.c b/src/pager.c index c246ff874..a40df566a 100644 --- a/src/pager.c +++ b/src/pager.c @@ -18,7 +18,7 @@ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.163 2004/09/08 20:13:05 drh Exp $ +** @(#) $Id: pager.c,v 1.164 2004/09/24 22:32:31 drh Exp $ */ #include "os.h" /* Must be first to enable large file support */ #include "sqliteInt.h" @@ -228,12 +228,12 @@ struct Pager { PgHdr *pFirstSynced; /* First free page with PgHdr.needSync==0 */ PgHdr *pAll; /* List of all pages */ PgHdr *pStmt; /* List of pages in the statement subjournal */ - PgHdr *aHash[N_PG_HASH]; /* Hash table to map page number to PgHdr */ off_t journalOff; /* Current byte offset in the journal file */ off_t journalHdr; /* Byte offset to previous journal header */ off_t stmtHdrOff; /* First journal header written this statement */ off_t stmtCksum; /* cksumInit when statement was started */ int sectorSize; /* Assumed sector size during rollback */ + PgHdr *aHash[N_PG_HASH]; /* Hash table to map page number to PgHdr */ }; /* diff --git a/src/printf.c b/src/printf.c index 768e331bf..716e59d55 100644 --- a/src/printf.c +++ b/src/printf.c @@ -90,8 +90,8 @@ typedef struct et_info { /* Information about each format field */ etByte base; /* The base for radix conversion */ etByte flags; /* One or more of FLAG_ constants below */ etByte type; /* Conversion paradigm */ - char *charset; /* The character set for conversion */ - char *prefix; /* Prefix on non-zero values in alt format */ + etByte charset; /* Offset into aDigits[] of the digits string */ + etByte prefix; /* Offset into aPrefix[] of the prefix string */ } et_info; /* @@ -105,28 +105,30 @@ typedef struct et_info { /* Information about each format field */ ** The following table is searched linearly, so it is good to put the ** most frequently used conversion types first. */ +static const char aDigits[] = "0123456789ABCDEF0123456789abcdef"; +static const char aPrefix[] = "-x0\000X0"; static et_info fmtinfo[] = { - { 'd', 10, 1, etRADIX, "0123456789", 0 }, - { 's', 0, 0, etSTRING, 0, 0 }, - { 'z', 0, 2, etDYNSTRING, 0, 0 }, - { 'q', 0, 0, etSQLESCAPE, 0, 0 }, - { 'Q', 0, 0, etSQLESCAPE2, 0, 0 }, - { 'c', 0, 0, etCHARX, 0, 0 }, - { 'o', 8, 0, etRADIX, "01234567", "0" }, - { 'u', 10, 0, etRADIX, "0123456789", 0 }, - { 'x', 16, 0, etRADIX, "0123456789abcdef", "x0" }, - { 'X', 16, 0, etRADIX, "0123456789ABCDEF", "X0" }, - { 'f', 0, 1, etFLOAT, 0, 0 }, - { 'e', 0, 1, etEXP, "e", 0 }, - { 'E', 0, 1, etEXP, "E", 0 }, - { 'g', 0, 1, etGENERIC, "e", 0 }, - { 'G', 0, 1, etGENERIC, "E", 0 }, - { 'i', 10, 1, etRADIX, "0123456789", 0 }, - { 'n', 0, 0, etSIZE, 0, 0 }, - { '%', 0, 0, etPERCENT, 0, 0 }, - { 'p', 16, 0, etPOINTER, "0123456789abcdef", "x0" }, - { 'T', 0, 2, etTOKEN, 0, 0 }, - { 'S', 0, 2, etSRCLIST, 0, 0 }, + { 'd', 10, 1, etRADIX, 0, 0 }, + { 's', 0, 0, etSTRING, 0, 0 }, + { 'z', 0, 2, etDYNSTRING, 0, 0 }, + { 'q', 0, 0, etSQLESCAPE, 0, 0 }, + { 'Q', 0, 0, etSQLESCAPE2, 0, 0 }, + { 'c', 0, 0, etCHARX, 0, 0 }, + { 'o', 8, 0, etRADIX, 0, 2 }, + { 'u', 10, 0, etRADIX, 0, 0 }, + { 'x', 16, 0, etRADIX, 16, 1 }, + { 'X', 16, 0, etRADIX, 0, 4 }, + { 'f', 0, 1, etFLOAT, 0, 0 }, + { 'e', 0, 1, etEXP, 30, 0 }, + { 'E', 0, 1, etEXP, 14, 0 }, + { 'g', 0, 1, etGENERIC, 30, 0 }, + { 'G', 0, 1, etGENERIC, 14, 0 }, + { 'i', 10, 1, etRADIX, 0, 0 }, + { 'n', 0, 0, etSIZE, 0, 0 }, + { '%', 0, 0, etPERCENT, 0, 0 }, + { 'p', 16, 0, etPOINTER, 0, 1 }, + { 'T', 0, 2, etTOKEN, 0, 0 }, + { 'S', 0, 2, etSRCLIST, 0, 0 }, }; #define etNINFO (sizeof(fmtinfo)/sizeof(fmtinfo[0])) @@ -377,9 +379,9 @@ static int vxprintf( } bufpt = &buf[etBUFSIZE-1]; { - register char *cset; /* Use registers for speed */ + register const char *cset; /* Use registers for speed */ register int base; - cset = infop->charset; + cset = &aDigits[infop->charset]; base = infop->base; do{ /* Convert to ascii */ *(--bufpt) = cset[longvalue%base]; @@ -392,10 +394,11 @@ static int vxprintf( } if( prefix ) *(--bufpt) = prefix; /* Add sign */ if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */ - char *pre, x; - pre = infop->prefix; + const char *pre; + char x; + pre = &aPrefix[infop->prefix]; if( *bufpt!=pre[0] ){ - for(pre=infop->prefix; (x=(*pre))!=0; pre++) *(--bufpt) = x; + for(; (x=(*pre))!=0; pre++) *(--bufpt) = x; } } length = &buf[etBUFSIZE-1]-bufpt; @@ -493,7 +496,7 @@ static int vxprintf( } bufpt++; /* point to next free slot */ if( exp || flag_exp ){ - *(bufpt++) = infop->charset[0]; + *(bufpt++) = aDigits[infop->charset]; if( exp<0 ){ *(bufpt++) = '-'; exp = -exp; } /* sign of exp */ else { *(bufpt++) = '+'; } if( exp>=100 ){ @@ -809,6 +812,7 @@ char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ ** and segfaults if you give it a long long int. */ void sqlite3DebugPrintf(const char *zFormat, ...){ + extern int getpid(void); va_list ap; char zBuf[500]; va_start(ap, zFormat); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 7c3477600..15a5b57bd 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -56,6 +56,21 @@ void sqlite3VdbeTrace(Vdbe *p, FILE *trace){ } /* +** Resize the Vdbe.aOp array so that it contains at least N +** elements. +*/ +static void resizeOpArray(Vdbe *p, int N){ + if( p->nOpAlloc<N ){ + int oldSize = p->nOpAlloc; + p->nOpAlloc = N+100; + p->aOp = sqliteRealloc(p->aOp, p->nOpAlloc*sizeof(Op)); + if( p->aOp ){ + memset(&p->aOp[oldSize], 0, (p->nOpAlloc-oldSize)*sizeof(Op)); + } + } +} + +/* ** Add a new instruction to the list of instructions current in the ** VDBE. Return the address of the new instruction. ** @@ -78,24 +93,13 @@ int sqlite3VdbeAddOp(Vdbe *p, int op, int p1, int p2){ i = p->nOp; p->nOp++; assert( p->magic==VDBE_MAGIC_INIT ); - if( i>=p->nOpAlloc ){ - int oldSize = p->nOpAlloc; - Op *aNew; - p->nOpAlloc = p->nOpAlloc*2 + 100; - aNew = sqliteRealloc(p->aOp, p->nOpAlloc*sizeof(Op)); - if( aNew==0 ){ - p->nOpAlloc = oldSize; - return 0; - } - p->aOp = aNew; - memset(&p->aOp[oldSize], 0, (p->nOpAlloc-oldSize)*sizeof(Op)); + resizeOpArray(p, i+1); + if( p->aOp==0 ){ + return 0; } pOp = &p->aOp[i]; pOp->opcode = op; pOp->p1 = p1; - if( p2<0 && (-1-p2)<p->nLabel && p->aLabel[-1-p2]>=0 ){ - p2 = p->aLabel[-1-p2]; - } pOp->p2 = p2; pOp->p3 = 0; pOp->p3type = P3_NOTUSED; @@ -133,20 +137,12 @@ int sqlite3VdbeMakeLabel(Vdbe *p){ i = p->nLabel++; assert( p->magic==VDBE_MAGIC_INIT ); if( i>=p->nLabelAlloc ){ - int *aNew; p->nLabelAlloc = p->nLabelAlloc*2 + 10; - aNew = sqliteRealloc( p->aLabel, p->nLabelAlloc*sizeof(p->aLabel[0])); - if( aNew==0 ){ - sqliteFree(p->aLabel); - } - p->aLabel = aNew; + p->aLabel = sqliteRealloc( p->aLabel, p->nLabelAlloc*sizeof(p->aLabel[0])); } - if( p->aLabel==0 ){ - p->nLabel = 0; - p->nLabelAlloc = 0; - return 0; + if( p->aLabel ){ + p->aLabel[i] = -1; } - p->aLabel[i] = -1; return -1-i; } @@ -156,19 +152,36 @@ int sqlite3VdbeMakeLabel(Vdbe *p){ ** a prior call to sqlite3VdbeMakeLabel(). */ void sqlite3VdbeResolveLabel(Vdbe *p, int x){ - int j; + int j = -1-x; assert( p->magic==VDBE_MAGIC_INIT ); - if( x<0 && (-x)<=p->nLabel && p->aOp ){ - if( p->aLabel[-1-x]==p->nOp ) return; - assert( p->aLabel[-1-x]<0 ); - p->aLabel[-1-x] = p->nOp; - for(j=0; j<p->nOp; j++){ - if( p->aOp[j].p2==x ) p->aOp[j].p2 = p->nOp; - } + assert( j>=0 && j<p->nLabel ); + if( p->aLabel ){ + p->aLabel[j] = p->nOp; } } /* +** Loop through the program looking for P2 values that are negative. +** Each such value is a label. Resolve the label by setting the P2 +** value to its correct non-zero value. +** +** This routine is called once after all opcodes have been inserted. +*/ +static void resolveP2Values(Vdbe *p){ + int i; + Op *pOp; + int *aLabel = p->aLabel; + if( aLabel==0 ) return; + for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){ + if( pOp->p2>=0 ) continue; + assert( -1-pOp->p2<p->nLabel ); + pOp->p2 = aLabel[-1-pOp->p2]; + } + sqliteFree(p->aLabel); + p->aLabel = 0; +} + +/* ** Return the address of the next instruction to be inserted. */ int sqlite3VdbeCurrentAddr(Vdbe *p){ @@ -183,17 +196,9 @@ int sqlite3VdbeCurrentAddr(Vdbe *p){ int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){ int addr; assert( p->magic==VDBE_MAGIC_INIT ); - if( p->nOp + nOp >= p->nOpAlloc ){ - int oldSize = p->nOpAlloc; - Op *aNew; - p->nOpAlloc = p->nOpAlloc*2 + nOp + 10; - aNew = sqliteRealloc(p->aOp, p->nOpAlloc*sizeof(Op)); - if( aNew==0 ){ - p->nOpAlloc = oldSize; - return 0; - } - p->aOp = aNew; - memset(&p->aOp[oldSize], 0, (p->nOpAlloc-oldSize)*sizeof(Op)); + resizeOpArray(p, p->nOp + nOp); + if( p->aOp==0 ){ + return 0; } addr = p->nOp; if( nOp>0 ){ @@ -312,7 +317,7 @@ void sqlite3VdbeChangeP3(Vdbe *p, int addr, const char *zP3, int n){ void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){ va_list ap; assert( p->nOp>0 ); - assert( p->aOp[p->nOp-1].p3==0 ); + assert( p->aOp==0 || p->aOp[p->nOp-1].p3==0 ); va_start(ap, zFormat); sqlite3VdbeChangeP3(p, -1, sqlite3VMPrintf(zFormat, ap), P3_DYNAMIC); va_end(ap); @@ -457,6 +462,17 @@ void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){ #endif /* +** Release an array of N Mem elements +*/ +static void releaseMemArray(Mem *p, int N){ + if( p ){ + while( N-->0 ){ + sqlite3VdbeMemRelease(p++); + } + } +} + +/* ** Give a listing of the program in the virtual machine. ** ** The interface is the same as sqlite3VdbeExec(). But instead of @@ -477,10 +493,7 @@ int sqlite3VdbeList( ** sqlite3_column_text16(), causing a translation to UTF-16 encoding. */ if( p->pTos==&p->aStack[4] ){ - for(i=0; i<5; i++){ - sqlite3VdbeMemRelease(&p->aStack[i]); - p->aStack[i].flags = 0; - } + releaseMemArray(p->aStack, 5); } p->resOnStack = 0; @@ -586,6 +599,7 @@ void sqlite3VdbeMakeReady( ** Allocation all the stack space we will ever need. */ if( p->aStack==0 ){ + resolveP2Values(p); assert( nVar>=0 ); n = isExplain ? 10 : p->nOp; p->aStack = sqliteMalloc( @@ -846,27 +860,23 @@ static void closeAllCursors(Vdbe *p){ static void Cleanup(Vdbe *p){ int i; if( p->aStack ){ - Mem *pTos = p->pTos; - while( pTos>=p->aStack ){ - sqlite3VdbeMemRelease(pTos); - pTos--; - } - p->pTos = pTos; + releaseMemArray(p->aStack, 1 + (p->pTos - p->aStack)); + p->pTos = &p->aStack[-1]; } closeAllCursors(p); - for(i=0; i<p->nMem; i++){ - sqlite3VdbeMemRelease(&p->aMem[i]); - } + releaseMemArray(p->aMem, p->nMem); if( p->pList ){ sqlite3VdbeKeylistFree(p->pList); p->pList = 0; } - for(i=0; i<p->contextStackTop; i++){ - sqlite3VdbeKeylistFree(p->contextStack[i].pList); + if( p->contextStack ){ + for(i=0; i<p->contextStackTop; i++){ + sqlite3VdbeKeylistFree(p->contextStack[i].pList); + } + sqliteFree(p->contextStack); } sqlite3VdbeSorterReset(p); sqlite3VdbeAggReset(0, &p->agg, 0); - sqliteFree(p->contextStack); p->contextStack = 0; p->contextStackDepth = 0; p->contextStackTop = 0; @@ -881,8 +891,16 @@ static void Cleanup(Vdbe *p){ ** be called on an SQL statement before sqlite3_step(). */ void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){ + Mem *pColName; + int n; assert( 0==p->nResColumn ); p->nResColumn = nResColumn; + n = nResColumn*2; + p->aColName = pColName = (Mem*)sqliteMalloc( sizeof(Mem)*n ); + if( p->aColName==0 ) return; + while( n-- > 0 ){ + (pColName++)->flags = MEM_Null; + } } /* @@ -900,21 +918,8 @@ int sqlite3VdbeSetColName(Vdbe *p, int idx, const char *zName, int N){ int rc; Mem *pColName; assert( idx<(2*p->nResColumn) ); - - /* If the Vdbe.aColName array has not yet been allocated, allocate - ** it now. - */ - if( !p->aColName ){ - int i; - p->aColName = (Mem *)sqliteMalloc(sizeof(Mem)*p->nResColumn*2); - if( !p->aColName ){ - return SQLITE_NOMEM; - } - for(i=0; i<(2*p->nResColumn); i++){ - p->aColName[i].flags = MEM_Null; - } - } - + if( sqlite3_malloc_failed ) return SQLITE_NOMEM; + assert( p->aColName!=0 ); pColName = &(p->aColName[idx]); if( N==P3_DYNAMIC || N==P3_STATIC ){ rc = sqlite3VdbeMemSetStr(pColName, zName, -1, SQLITE_UTF8, SQLITE_STATIC); @@ -1381,34 +1386,25 @@ void sqlite3VdbeDelete(Vdbe *p){ if( p->pNext ){ p->pNext->pPrev = p->pPrev; } - p->pPrev = p->pNext = 0; - if( p->nOpAlloc==0 ){ - p->aOp = 0; - p->nOp = 0; - } - for(i=0; i<p->nOp; i++){ - Op *pOp = &p->aOp[i]; - if( pOp->p3type==P3_DYNAMIC || pOp->p3type==P3_KEYINFO ){ - sqliteFree(pOp->p3); - } - if( pOp->p3type==P3_VDBEFUNC ){ - VdbeFunc *pVdbeFunc = (VdbeFunc *)pOp->p3; - sqlite3VdbeDeleteAuxData(pVdbeFunc, 0); - sqliteFree(pVdbeFunc); + if( p->aOp ){ + for(i=0; i<p->nOp; i++){ + Op *pOp = &p->aOp[i]; + if( pOp->p3type==P3_DYNAMIC || pOp->p3type==P3_KEYINFO ){ + sqliteFree(pOp->p3); + } + if( pOp->p3type==P3_VDBEFUNC ){ + VdbeFunc *pVdbeFunc = (VdbeFunc *)pOp->p3; + sqlite3VdbeDeleteAuxData(pVdbeFunc, 0); + sqliteFree(pVdbeFunc); + } } + sqliteFree(p->aOp); } - for(i=0; i<p->nVar; i++){ - sqlite3VdbeMemRelease(&p->aVar[i]); - } - sqliteFree(p->aOp); + releaseMemArray(p->aVar, p->nVar); sqliteFree(p->aLabel); sqliteFree(p->aStack); - if( p->aColName ){ - for(i=0; i<(p->nResColumn)*2; i++){ - sqlite3VdbeMemRelease(&(p->aColName[i])); - } - sqliteFree(p->aColName); - } + releaseMemArray(p->aColName, p->nResColumn*2); + sqliteFree(p->aColName); p->magic = VDBE_MAGIC_DEAD; sqliteFree(p); } |