Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Code optimizations to help the library run faster. (CVS 808) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
db745e87dc26cf1a35cdcec18f4b6597 |
User & Date: | drh 2003-01-02 14:43:56.000 |
Context
2003-01-03
| ||
02:04 | Allow the rollback journal to be empty except for its header. Ticket #212. (CVS 809) (check-in: 1ba41bc2af user: drh tags: trunk) | |
2003-01-02
| ||
14:43 | Code optimizations to help the library run faster. (CVS 808) (check-in: db745e87dc user: drh tags: trunk) | |
2003-01-01
| ||
23:06 | If compiled with the -DVDBE_PROFILE=1 option, special code is inserted that uses the pentium RDTSC instruction to compute very precise runtimes on all VDBE opcodes. (This only works on i586 processors, of course.) The results are written into the vdbe_profile.out file for analysis. Hopefully, this new feature will reveal hot spots that can be optimized to make the VDBE run faster. (CVS 807) (check-in: a1c071ea18 user: drh tags: trunk) | |
Changes
Changes to src/btree.c.
1 2 3 4 5 6 7 8 9 10 11 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** $Id: btree.c,v 1.76 2003/01/02 14:43:56 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to ** ** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3: ** "Sorting And Searching", pages 473-480. Addison-Wesley ** Publishing Company, Reading, Massachusetts. |
︙ | ︙ | |||
1102 1103 1104 1105 1106 1107 1108 | ** the database is empty) then *pSize is set to 0. */ int sqliteBtreeKeySize(BtCursor *pCur, int *pSize){ Cell *pCell; MemPage *pPage; pPage = pCur->pPage; | > | | 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 | ** the database is empty) then *pSize is set to 0. */ int sqliteBtreeKeySize(BtCursor *pCur, int *pSize){ Cell *pCell; MemPage *pPage; pPage = pCur->pPage; assert( pPage!=0 ); if( pCur->idx >= pPage->nCell ){ *pSize = 0; }else{ pCell = pPage->apCell[pCur->idx]; *pSize = NKEY(pCur->pBt, pCell->h); } return SQLITE_OK; } |
︙ | ︙ | |||
1176 1177 1178 1179 1180 1181 1182 | return SQLITE_OK; } /* ** Read part of the key associated with cursor pCur. A maximum ** of "amt" bytes will be transfered into zBuf[]. The transfer ** begins at "offset". The number of bytes actually read is | | > > | | > > > < | | | < | < < < < < < > | < | | | | | < < < < < < | 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 | return SQLITE_OK; } /* ** Read part of the key associated with cursor pCur. A maximum ** of "amt" bytes will be transfered into zBuf[]. The transfer ** begins at "offset". The number of bytes actually read is ** returned. ** ** Change: It used to be that the amount returned will be smaller ** than the amount requested if there are not enough bytes in the key ** to satisfy the request. But now, it must be the case that there ** is enough data available to satisfy the request. If not, an exception ** is raised. The change was made in an effort to boost performance ** by eliminating unneeded tests. */ int sqliteBtreeKey(BtCursor *pCur, int offset, int amt, char *zBuf){ MemPage *pPage; assert( amt>=0 ); assert( offset>=0 ); assert( pCur->pPage!=0 ); pPage = pCur->pPage; if( pCur->idx >= pPage->nCell ){ return 0; } assert( amt+offset <= NKEY(pCur->pBt, pPage->apCell[pCur->idx]->h) ); getPayload(pCur, offset, amt, zBuf); return amt; } /* ** Set *pSize to the number of bytes of data in the entry the ** cursor currently points to. Always return SQLITE_OK. ** Failure is not possible. If the cursor is not currently ** pointing to an entry (which can happen, for example, if ** the database is empty) then *pSize is set to 0. */ int sqliteBtreeDataSize(BtCursor *pCur, int *pSize){ Cell *pCell; MemPage *pPage; pPage = pCur->pPage; assert( pPage!=0 ); if( pCur->idx >= pPage->nCell ){ *pSize = 0; }else{ pCell = pPage->apCell[pCur->idx]; *pSize = NDATA(pCur->pBt, pCell->h); } return SQLITE_OK; } /* ** Read part of the data associated with cursor pCur. A maximum ** of "amt" bytes will be transfered into zBuf[]. The transfer ** begins at "offset". The number of bytes actually read is ** returned. The amount returned will be smaller than the ** amount requested if there are not enough bytes in the data ** to satisfy the request. */ int sqliteBtreeData(BtCursor *pCur, int offset, int amt, char *zBuf){ Cell *pCell; MemPage *pPage; assert( amt>=0 ); assert( offset>=0 ); assert( pCur->pPage!=0 ); pPage = pCur->pPage; if( pCur->idx >= pPage->nCell ){ return 0; } pCell = pPage->apCell[pCur->idx]; assert( amt+offset <= NDATA(pCur->pBt, pCell->h) ); getPayload(pCur, offset + NKEY(pCur->pBt, pCell->h), amt, zBuf); return amt; } /* ** Compare an external key against the key on the entry that pCur points to. ** |
︙ | ︙ | |||
1548 1549 1550 1551 1552 1553 1554 | if( rc ) return rc; } /* NOT REACHED */ } /* ** Advance the cursor to the next entry in the database. If | | | > > | | | < | | | < | | | < | | | 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 | if( rc ) return rc; } /* NOT REACHED */ } /* ** Advance the cursor to the next entry in the database. If ** successful then set *pRes=0. If the cursor ** was already pointing to the last entry in the database before ** this routine was called, then set *pRes=1. */ int sqliteBtreeNext(BtCursor *pCur, int *pRes){ int rc; assert( pRes!=0 ); /* assert( pCur->pPage!=0 ); */ if( pCur->pPage==0 ){ *pRes = 1; return SQLITE_ABORT; } assert( pCur->pPage->isInit ); assert( pCur->eSkip!=SKIP_INVALID ); if( pCur->pPage->nCell==0 ){ *pRes = 1; return SQLITE_OK; } assert( pCur->idx<pCur->pPage->nCell ); if( pCur->eSkip==SKIP_NEXT ){ pCur->eSkip = SKIP_NONE; *pRes = 0; return SQLITE_OK; } pCur->eSkip = SKIP_NONE; pCur->idx++; if( pCur->idx>=pCur->pPage->nCell ){ if( pCur->pPage->u.hdr.rightChild ){ rc = moveToChild(pCur, SWAB32(pCur->pBt, pCur->pPage->u.hdr.rightChild)); if( rc ) return rc; rc = moveToLeftmost(pCur); *pRes = 0; return rc; } do{ if( pCur->pPage->pParent==0 ){ *pRes = 1; return SQLITE_OK; } rc = moveToParent(pCur); }while( rc==SQLITE_OK && pCur->idx>=pCur->pPage->nCell ); *pRes = 0; return rc; } rc = moveToLeftmost(pCur); *pRes = 0; return rc; } /* ** Step the cursor to the back to the previous entry in the database. If ** successful and pRes!=NULL then set *pRes=0. If the cursor ** was already pointing to the first entry in the database before ** this routine was called, then set *pRes=1 if pRes!=NULL. |
︙ | ︙ | |||
2617 2618 2619 2620 2621 2622 2623 2624 | ** We have to fill the hole by moving in a cell from a leaf. The ** next Cell after the one to be deleted is guaranteed to exist and ** to be a leaf so we can use it. */ BtCursor leafCur; Cell *pNext; int szNext; getTempCursor(pCur, &leafCur); | > | | 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 | ** We have to fill the hole by moving in a cell from a leaf. The ** next Cell after the one to be deleted is guaranteed to exist and ** to be a leaf so we can use it. */ BtCursor leafCur; Cell *pNext; int szNext; int notUsed; getTempCursor(pCur, &leafCur); rc = sqliteBtreeNext(&leafCur, ¬Used); if( rc!=SQLITE_OK ){ return SQLITE_CORRUPT; } rc = sqlitepager_write(leafCur.pPage); if( rc ) return rc; dropCell(pBt, pPage, pCur->idx, cellSize(pBt, pCell)); pNext = leafCur.pPage->apCell[leafCur.idx]; |
︙ | ︙ | |||
3153 3154 3155 3156 3157 3158 3159 | int nPage = (sz - MX_LOCAL_PAYLOAD + OVERFLOW_SIZE - 1)/OVERFLOW_SIZE; checkList(pCheck, 0, SWAB32(pBt, pCell->ovfl), nPage, zContext); } /* Check that keys are in the right order */ cur.idx = i; | | | 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 | int nPage = (sz - MX_LOCAL_PAYLOAD + OVERFLOW_SIZE - 1)/OVERFLOW_SIZE; checkList(pCheck, 0, SWAB32(pBt, pCell->ovfl), nPage, zContext); } /* Check that keys are in the right order */ cur.idx = i; zKey2 = sqliteMallocRaw( nKey2+1 ); getPayload(&cur, 0, nKey2, zKey2); if( zKey1 && keyCompare(zKey1, nKey1, zKey2, nKey2)>=0 ){ checkAppendMsg(pCheck, zContext, "Key is out of order"); } /* Check sanity of left child page. */ |
︙ | ︙ | |||
3249 3250 3251 3252 3253 3254 3255 | sCheck.pBt = pBt; sCheck.pPager = pBt->pPager; sCheck.nPage = sqlitepager_pagecount(sCheck.pPager); if( sCheck.nPage==0 ){ unlockBtreeIfUnused(pBt); return 0; } | | | 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 | sCheck.pBt = pBt; sCheck.pPager = pBt->pPager; sCheck.nPage = sqlitepager_pagecount(sCheck.pPager); if( sCheck.nPage==0 ){ unlockBtreeIfUnused(pBt); return 0; } sCheck.anRef = sqliteMallocRaw( (sCheck.nPage+1)*sizeof(sCheck.anRef[0]) ); sCheck.anRef[1] = 1; for(i=2; i<=sCheck.nPage; i++){ sCheck.anRef[i] = 0; } sCheck.zErrMsg = 0; /* Check the integrity of the freelist */ checkList(&sCheck, 1, SWAB32(pBt, pBt->page1->freeList), |
︙ | ︙ |
Changes to src/build.c.
︙ | ︙ | |||
21 22 23 24 25 26 27 | ** COPY ** VACUUM ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** PRAGMA ** | | | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | ** COPY ** VACUUM ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** PRAGMA ** ** $Id: build.c,v 1.118 2003/01/02 14:43:56 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** This routine is called when a new SQL statement is beginning to ** be parsed. Check to see if the schema for the database needs |
︙ | ︙ | |||
723 724 725 726 727 728 729 | zEnd = ")"; }else{ zSep = "\n "; zSep2 = ",\n "; zEnd = "\n)"; } n += 35 + 6*p->nCol; | | | 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 | zEnd = ")"; }else{ zSep = "\n "; zSep2 = ",\n "; zEnd = "\n)"; } n += 35 + 6*p->nCol; zStmt = sqliteMallocRaw( n ); if( zStmt==0 ) return 0; strcpy(zStmt, p->isTemp ? "CREATE TEMP TABLE " : "CREATE TABLE "); k = strlen(zStmt); identPut(zStmt, &k, p->zName); zStmt[k++] = '('; for(i=0; i<p->nCol; i++){ strcpy(&zStmt[k], zSep); |
︙ | ︙ | |||
1160 1161 1162 1163 1164 1165 1166 | void sqliteAddIdxKeyType(Vdbe *v, Index *pIdx){ char *zType; Table *pTab; int i, n; assert( pIdx!=0 && pIdx->pTable!=0 ); pTab = pIdx->pTable; n = pIdx->nColumn; | | | 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 | void sqliteAddIdxKeyType(Vdbe *v, Index *pIdx){ char *zType; Table *pTab; int i, n; assert( pIdx!=0 && pIdx->pTable!=0 ); pTab = pIdx->pTable; n = pIdx->nColumn; zType = sqliteMallocRaw( n+1 ); if( zType==0 ) return; for(i=0; i<n; i++){ int iCol = pIdx->aiColumn[i]; assert( iCol>=0 && iCol<pTab->nCol ); if( (pTab->aCol[iCol].sortOrder & SQLITE_SO_TYPEMASK)==SQLITE_SO_TEXT ){ zType[i] = 't'; }else{ |
︙ | ︙ |
Changes to src/hash.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This is the implementation of generic hash-tables ** used in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This is the implementation of generic hash-tables ** used in SQLite. ** ** $Id: hash.c,v 1.9 2003/01/02 14:43:57 drh Exp $ */ #include "sqliteInt.h" #include <assert.h> /* Turn bulk memory into a hash table object by initializing the ** fields of the Hash structure. ** |
︙ | ︙ | |||
309 310 311 312 313 314 315 | } return old_data; } if( data==0 ) return 0; new_elem = (HashElem*)sqliteMalloc( sizeof(HashElem) ); if( new_elem==0 ) return data; if( pH->copyKey && pKey!=0 ){ | | | 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 | } return old_data; } if( data==0 ) return 0; new_elem = (HashElem*)sqliteMalloc( sizeof(HashElem) ); if( new_elem==0 ) return data; if( pH->copyKey && pKey!=0 ){ new_elem->pKey = sqliteMallocRaw( nKey ); if( new_elem->pKey==0 ){ sqliteFree(new_elem); return data; } memcpy((void*)new_elem->pKey, pKey, nKey); }else{ new_elem->pKey = (void*)pKey; |
︙ | ︙ |
Changes to src/pager.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 | ** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** | | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | ** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** ** @(#) $Id: pager.c,v 1.63 2003/01/02 14:43:57 drh Exp $ */ #include "os.h" /* Must be first to enable large file support */ #include "sqliteInt.h" #include "pager.h" #include <assert.h> #include <string.h> |
︙ | ︙ | |||
958 959 960 961 962 963 964 | } if( pPg==0 ){ /* The requested page is not in the page cache. */ int h; pPager->nMiss++; if( pPager->nPage<pPager->mxPage || pPager->pFirst==0 ){ /* Create a new page */ | | > | 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 | } if( pPg==0 ){ /* The requested page is not in the page cache. */ int h; pPager->nMiss++; if( pPager->nPage<pPager->mxPage || pPager->pFirst==0 ){ /* Create a new page */ pPg = sqliteMallocRaw( sizeof(*pPg) + SQLITE_PAGE_SIZE + pPager->nExtra ); if( pPg==0 ){ *ppPage = 0; pager_unwritelock(pPager); pPager->errMask |= PAGER_ERR_MEM; return SQLITE_NOMEM; } memset(pPg, 0, sizeof(*pPg)); pPg->pPager = pPager; pPg->pNextAll = pPager->pAll; if( pPager->pAll ){ pPager->pAll->pPrevAll = pPg; } pPg->pPrevAll = 0; pPager->pAll = pPg; |
︙ | ︙ |
Changes to src/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.151 2003/01/02 14:43:57 drh Exp $ */ #include "config.h" #include "sqlite.h" #include "hash.h" #include "vdbe.h" #include "parse.h" #include "btree.h" |
︙ | ︙ | |||
115 116 117 118 119 120 121 | ** -DMEMORY_DEBUG=2 ** ** and a line of text will be written to standard error for ** each malloc() and free(). This output can be analyzed ** by an AWK script to determine if there are any leaks. */ #ifdef MEMORY_DEBUG | | > | 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | ** -DMEMORY_DEBUG=2 ** ** and a line of text will be written to standard error for ** each malloc() and free(). This output can be analyzed ** by an AWK script to determine if there are any leaks. */ #ifdef MEMORY_DEBUG # define sqliteMalloc(X) sqliteMalloc_(X,1,__FILE__,__LINE__) # define sqliteMallocRaw(X) sqliteMalloc_(X,0,__FILE__,__LINE__) # define sqliteFree(X) sqliteFree_(X,__FILE__,__LINE__) # define sqliteRealloc(X,Y) sqliteRealloc_(X,Y,__FILE__,__LINE__) # define sqliteStrDup(X) sqliteStrDup_(X,__FILE__,__LINE__) # define sqliteStrNDup(X,Y) sqliteStrNDup_(X,Y,__FILE__,__LINE__) void sqliteStrRealloc(char**); #else # define sqliteStrRealloc(X) |
︙ | ︙ | |||
889 890 891 892 893 894 895 | int sqliteStrICmp(const char *, const char *); int sqliteStrNICmp(const char *, const char *, int); int sqliteHashNoCase(const char *, int); int sqliteCompare(const char *, const char *); int sqliteSortCompare(const char *, const char *); void sqliteRealToSortable(double r, char *); #ifdef MEMORY_DEBUG | | > | 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 | int sqliteStrICmp(const char *, const char *); int sqliteStrNICmp(const char *, const char *, int); int sqliteHashNoCase(const char *, int); int sqliteCompare(const char *, const char *); int sqliteSortCompare(const char *, const char *); void sqliteRealToSortable(double r, char *); #ifdef MEMORY_DEBUG void *sqliteMalloc_(int,int,char*,int); void sqliteFree_(void*,char*,int); void *sqliteRealloc_(void*,int,char*,int); char *sqliteStrDup_(const char*,char*,int); char *sqliteStrNDup_(const char*, int,char*,int); #else void *sqliteMalloc(int); void *sqliteMallocRaw(int); void sqliteFree(void*); void *sqliteRealloc(void*,int); char *sqliteStrDup(const char*); char *sqliteStrNDup(const char*, int); #endif void sqliteSetString(char **, const char *, ...); void sqliteSetNString(char **, ...); |
︙ | ︙ |
Changes to src/util.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** ** $Id: util.c,v 1.54 2003/01/02 14:43:57 drh Exp $ */ #include "sqliteInt.h" #include <stdarg.h> #include <ctype.h> /* ** If malloc() ever fails, this global variable gets set to 1. |
︙ | ︙ | |||
44 45 46 47 48 49 50 | #endif /* ** Allocate new memory and set it to zero. Return NULL if ** no memory is available. */ | | | 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | #endif /* ** Allocate new memory and set it to zero. Return NULL if ** no memory is available. */ void *sqliteMalloc_(int n, int bZero, char *zFile, int line){ void *p; int *pi; int k; if( sqlite_iMallocFail>=0 ){ sqlite_iMallocFail--; if( sqlite_iMallocFail==0 ){ sqlite_malloc_failed++; |
︙ | ︙ | |||
72 73 74 75 76 77 78 | return 0; } sqlite_nMalloc++; pi[0] = 0xdead1122; pi[1] = n; pi[k+2] = 0xdead3344; p = &pi[2]; | | | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | return 0; } sqlite_nMalloc++; pi[0] = 0xdead1122; pi[1] = n; pi[k+2] = 0xdead3344; p = &pi[2]; memset(p, bZero==0, n); #if MEMORY_DEBUG>1 fprintf(stderr,"%06d malloc %d bytes at 0x%x from %s:%d\n", ++memcnt, n, (int)p, zFile,line); #endif return p; } |
︙ | ︙ | |||
117 118 119 120 121 122 123 | ** works just like sqliteMalloc(). If n==0, then this routine ** works just like sqliteFree(). */ void *sqliteRealloc_(void *oldP, int n, char *zFile, int line){ int *oldPi, *pi, k, oldN, oldK; void *p; if( oldP==0 ){ | | | 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | ** works just like sqliteMalloc(). If n==0, then this routine ** works just like sqliteFree(). */ void *sqliteRealloc_(void *oldP, int n, char *zFile, int line){ int *oldPi, *pi, k, oldN, oldK; void *p; if( oldP==0 ){ return sqliteMalloc_(n,1,zFile,line); } if( n==0 ){ sqliteFree_(oldP,zFile,line); return 0; } oldPi = oldP; oldPi -= 2; |
︙ | ︙ | |||
149 150 151 152 153 154 155 | pi[1] = n; pi[k+2] = 0xdead3344; p = &pi[2]; memcpy(p, oldP, n>oldN ? oldN : n); if( n>oldN ){ memset(&((char*)p)[oldN], 0, n-oldN); } | | | 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 | pi[1] = n; pi[k+2] = 0xdead3344; p = &pi[2]; memcpy(p, oldP, n>oldN ? oldN : n); if( n>oldN ){ memset(&((char*)p)[oldN], 0, n-oldN); } memset(oldPi, 0xab, (oldK+3)*sizeof(int)); free(oldPi); #if MEMORY_DEBUG>1 fprintf(stderr,"%06d realloc %d to %d bytes at 0x%x to 0x%x at %s:%d\n", ++memcnt, oldN, n, (int)oldP, (int)p, zFile, line); #endif return p; } |
︙ | ︙ | |||
186 187 188 189 190 191 192 | /* ** Make a copy of a string in memory obtained from sqliteMalloc() */ char *sqliteStrDup_(const char *z, char *zFile, int line){ char *zNew; if( z==0 ) return 0; | | | | > > > > > > > > > > > > > > > | 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 | /* ** Make a copy of a string in memory obtained from sqliteMalloc() */ char *sqliteStrDup_(const char *z, char *zFile, int line){ char *zNew; if( z==0 ) return 0; zNew = sqliteMalloc_(strlen(z)+1, 0, zFile, line); if( zNew ) strcpy(zNew, z); return zNew; } char *sqliteStrNDup_(const char *z, int n, char *zFile, int line){ char *zNew; if( z==0 ) return 0; zNew = sqliteMalloc_(n+1, 0, zFile, line); if( zNew ){ memcpy(zNew, z, n); zNew[n] = 0; } return zNew; } #endif /* MEMORY_DEBUG */ /* ** The following versions of malloc() and free() are for use in a ** normal build. */ #if !defined(MEMORY_DEBUG) /* ** Allocate new memory and set it to zero. Return NULL if ** no memory is available. See also sqliteMallocRaw(). */ void *sqliteMalloc(int n){ void *p; if( n==0 ) return 0; p = malloc(n); if( p==0 ){ sqlite_malloc_failed++; return 0; } memset(p, 0, n); return p; } /* ** Allocate new memory but do not set it to zero. Return NULL if ** no memory is available. See also sqliteMalloc(). */ void *sqliteMallocRaw(int n){ void *p; if( n==0 ) return 0; p = malloc(n); if( p==0 ){ sqlite_malloc_failed++; return 0; } return p; } /* ** Free memory previously obtained from sqliteMalloc() */ void sqliteFree(void *p){ if( p ){ free(p); |
︙ | ︙ | |||
260 261 262 263 264 265 266 | /* ** Make a copy of a string in memory obtained from sqliteMalloc() */ char *sqliteStrDup(const char *z){ char *zNew; if( z==0 ) return 0; | | | | 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 | /* ** Make a copy of a string in memory obtained from sqliteMalloc() */ char *sqliteStrDup(const char *z){ char *zNew; if( z==0 ) return 0; zNew = sqliteMallocRaw(strlen(z)+1); if( zNew ) strcpy(zNew, z); return zNew; } char *sqliteStrNDup(const char *z, int n){ char *zNew; if( z==0 ) return 0; zNew = sqliteMallocRaw(n+1); if( zNew ){ memcpy(zNew, z, n); zNew[n] = 0; } return zNew; } #endif /* !defined(MEMORY_DEBUG) */ |
︙ | ︙ | |||
296 297 298 299 300 301 302 | nByte = strlen(zFirst) + 1; va_start(ap, zFirst); while( (z = va_arg(ap, const char*))!=0 ){ nByte += strlen(z); } va_end(ap); sqliteFree(*pz); | | | 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 | nByte = strlen(zFirst) + 1; va_start(ap, zFirst); while( (z = va_arg(ap, const char*))!=0 ){ nByte += strlen(z); } va_end(ap); sqliteFree(*pz); *pz = zResult = sqliteMallocRaw( nByte ); if( zResult==0 ){ return; } strcpy(zResult, zFirst); zResult += strlen(zResult); va_start(ap, zFirst); while( (z = va_arg(ap, const char*))!=0 ){ |
︙ | ︙ | |||
337 338 339 340 341 342 343 | while( (z = va_arg(ap, const char*))!=0 ){ n = va_arg(ap, int); if( n<=0 ) n = strlen(z); nByte += n; } va_end(ap); sqliteFree(*pz); | | | 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 | while( (z = va_arg(ap, const char*))!=0 ){ n = va_arg(ap, int); if( n<=0 ) n = strlen(z); nByte += n; } va_end(ap); sqliteFree(*pz); *pz = zResult = sqliteMallocRaw( nByte + 1 ); if( zResult==0 ) return; va_start(ap, pz); while( (z = va_arg(ap, const char*))!=0 ){ n = va_arg(ap, int); if( n<=0 ) n = strlen(z); strncpy(zResult, z, n); zResult += n; |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
32 33 34 35 36 37 38 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** | | | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** 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.189 2003/01/02 14:43:57 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** The makefile scans this source file and creates the following ** array of string constants which are the names of all VDBE opcodes. |
︙ | ︙ | |||
605 606 607 608 609 610 611 | 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; }else{ | | | 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 | 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; }else{ p->z = sqliteMallocRaw( n+1 ); if( p->z ){ memcpy(p->z, zResult, n); p->z[n] = 0; } p->s.flags = STK_Str | STK_Dyn; } p->s.n = n+1; |
︙ | ︙ | |||
813 814 815 816 817 818 819 | #define Deephemeralize(P,I) \ if( ((P)->aStack[I].flags&STK_Ephem)!=0 && hardDeephem(P,I) ){ goto no_mem;} static int hardDeephem(Vdbe *p, int i){ Stack *pStack = &p->aStack[i]; char **pzStack = &p->zStack[i]; char *z; assert( (pStack->flags & STK_Ephem)!=0 ); | | | 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 | #define Deephemeralize(P,I) \ if( ((P)->aStack[I].flags&STK_Ephem)!=0 && hardDeephem(P,I) ){ goto no_mem;} static int hardDeephem(Vdbe *p, int i){ Stack *pStack = &p->aStack[i]; char **pzStack = &p->zStack[i]; char *z; assert( (pStack->flags & STK_Ephem)!=0 ); z = sqliteMallocRaw( pStack->n ); if( z==0 ) return 1; memcpy(z, *pzStack, pStack->n); *pzStack = z; return 0; } /* |
︙ | ︙ | |||
1658 1659 1660 1661 1662 1663 1664 | aStack[j].flags &= ~STK_Dyn; if( !isStatic ) aStack[j].flags |= STK_Ephem; }else if( aStack[i].n<=NBFS ){ memcpy(aStack[j].z, zStack[i], aStack[j].n); zStack[j] = aStack[j].z; aStack[j].flags &= ~(STK_Static|STK_Dyn|STK_Ephem); }else{ | | | 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 | aStack[j].flags &= ~STK_Dyn; if( !isStatic ) aStack[j].flags |= STK_Ephem; }else if( aStack[i].n<=NBFS ){ memcpy(aStack[j].z, zStack[i], aStack[j].n); zStack[j] = aStack[j].z; aStack[j].flags &= ~(STK_Static|STK_Dyn|STK_Ephem); }else{ zStack[j] = sqliteMallocRaw( aStack[j].n ); if( zStack[j]==0 ) goto no_mem; memcpy(zStack[j], zStack[i], aStack[j].n); aStack[j].flags &= ~(STK_Static|STK_Ephem); aStack[j].flags |= STK_Dyn; } } break; |
︙ | ︙ | |||
1867 1868 1869 1870 1871 1872 1873 | if( pOp->p2==0 ) PopStack(p, nField); VERIFY( NeedStack(p, p->tos+1); ) p->tos++; aStack[p->tos].flags = STK_Null; zStack[p->tos] = 0; break; } | | | 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 | if( pOp->p2==0 ) PopStack(p, nField); VERIFY( NeedStack(p, p->tos+1); ) p->tos++; aStack[p->tos].flags = STK_Null; zStack[p->tos] = 0; break; } zNew = sqliteMallocRaw( nByte ); if( zNew==0 ) goto no_mem; j = 0; for(i=p->tos-nField+1; i<=p->tos; i++){ if( (aStack[i].flags & STK_Null)==0 ){ memcpy(&zNew[j], zStack[i], aStack[i].n-1); j += aStack[i].n-1; } |
︙ | ︙ | |||
2778 2779 2780 2781 2782 2783 2784 | idxWidth = 3; } nByte += idxWidth*(nField + 1); if( nByte>MAX_BYTES_PER_ROW ){ rc = SQLITE_TOOBIG; goto abort_due_to_error; } | | | 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 | idxWidth = 3; } nByte += idxWidth*(nField + 1); if( nByte>MAX_BYTES_PER_ROW ){ rc = SQLITE_TOOBIG; goto abort_due_to_error; } zNewRecord = sqliteMallocRaw( nByte ); if( zNewRecord==0 ) goto no_mem; j = 0; addr = idxWidth*(nField+1) + addUnique*sizeof(uniqueCnt); for(i=p->tos-nField+1; i<=p->tos; i++){ zNewRecord[j++] = addr & 0xff; if( idxWidth>1 ){ zNewRecord[j++] = (addr>>8)&0xff; |
︙ | ︙ | |||
2932 2933 2934 2935 2936 2937 2938 | } } if( nByte+sizeof(u32)>MAX_BYTES_PER_ROW ){ rc = SQLITE_TOOBIG; goto abort_due_to_error; } if( addRowid ) nByte += sizeof(u32); | | | 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 | } } if( nByte+sizeof(u32)>MAX_BYTES_PER_ROW ){ rc = SQLITE_TOOBIG; goto abort_due_to_error; } if( addRowid ) nByte += sizeof(u32); zNewKey = sqliteMallocRaw( nByte ); if( zNewKey==0 ) goto no_mem; j = 0; for(i=p->tos-nField+1; i<=p->tos; i++){ if( aStack[i].flags & STK_Null ){ zNewKey[j++] = 'a'; zNewKey[j++] = 0; }else{ |
︙ | ︙ | |||
3925 3926 3927 3928 3929 3930 3931 | zStack[tos] = &zRec[offset]; }else{ if( amt<=NBFS ){ aStack[tos].flags = STK_Str; zStack[tos] = aStack[tos].z; aStack[tos].n = amt; }else{ | | | 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 | zStack[tos] = &zRec[offset]; }else{ if( amt<=NBFS ){ aStack[tos].flags = STK_Str; zStack[tos] = aStack[tos].z; aStack[tos].n = amt; }else{ char *z = sqliteMallocRaw( amt ); if( z==0 ) goto no_mem; aStack[tos].flags = STK_Str | STK_Dyn; zStack[tos] = z; aStack[tos].n = amt; } if( pC->keyAsData ){ sqliteBtreeKey(pCrsr, offset, amt, zStack[tos]); |
︙ | ︙ | |||
3997 3998 3999 4000 4001 4002 4003 | sqliteBtreeKeySize(pCrsr, &amt); if( amt<=0 ){ rc = SQLITE_CORRUPT; goto abort_due_to_error; } if( amt>NBFS ){ | | | 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 | sqliteBtreeKeySize(pCrsr, &amt); if( amt<=0 ){ rc = SQLITE_CORRUPT; goto abort_due_to_error; } if( amt>NBFS ){ z = sqliteMallocRaw( amt ); aStack[tos].flags = STK_Str | STK_Dyn; }else{ z = aStack[tos].z; aStack[tos].flags = STK_Str; } sqliteBtreeKey(pCrsr, 0, amt, z); zStack[tos] = z; |
︙ | ︙ | |||
4091 4092 4093 4094 4095 4096 4097 | ** Back up cursor P1 so that it points to the previous key/data pair in its ** table or index. If there is no previous key/value pairs then fall through ** to the following instruction. But if the cursor backup was successful, ** jump immediately to P2. */ case OP_Prev: case OP_Next: { | < | | | 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 | ** Back up cursor P1 so that it points to the previous key/data pair in its ** table or index. If there is no previous key/value pairs then fall through ** to the following instruction. But if the cursor backup was successful, ** jump immediately to P2. */ case OP_Prev: case OP_Next: { Cursor *pC; BtCursor *pCrsr; if( VERIFY( pOp->p1>=0 && pOp->p1<p->nCursor && ) (pCrsr = (pC = &p->aCsr[pOp->p1])->pCursor)!=0 ){ int res; if( pC->nullRow ){ res = 1; }else{ rc = pOp->opcode==OP_Next ? sqliteBtreeNext(pCrsr, &res) : sqliteBtreePrevious(pCrsr, &res); pC->nullRow = res; |
︙ | ︙ | |||
4402 4403 4404 4405 4406 4407 4408 | ** into the temporary storage list. */ case OP_ListWrite: { Keylist *pKeylist; VERIFY( if( p->tos<0 ) goto not_enough_stack; ) pKeylist = p->pList; if( pKeylist==0 || pKeylist->nUsed>=pKeylist->nKey ){ | | | 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 | ** into the temporary storage list. */ case OP_ListWrite: { Keylist *pKeylist; VERIFY( if( p->tos<0 ) goto not_enough_stack; ) pKeylist = p->pList; if( pKeylist==0 || pKeylist->nUsed>=pKeylist->nKey ){ pKeylist = sqliteMallocRaw( sizeof(Keylist)+999*sizeof(pKeylist->aKey[0]) ); if( pKeylist==0 ) goto no_mem; pKeylist->nKey = 1000; pKeylist->nRead = 0; pKeylist->nUsed = 0; pKeylist->pNext = p->pList; p->pList = pKeylist; } |
︙ | ︙ | |||
4512 4513 4514 4515 4516 4517 4518 | */ case OP_SortPut: { int tos = p->tos; int nos = tos - 1; Sorter *pSorter; VERIFY( if( tos<1 ) goto not_enough_stack; ) if( Stringify(p, tos) || Stringify(p, nos) ) goto no_mem; | | | 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 | */ case OP_SortPut: { int tos = p->tos; int nos = tos - 1; Sorter *pSorter; VERIFY( if( tos<1 ) goto not_enough_stack; ) if( Stringify(p, tos) || Stringify(p, nos) ) goto no_mem; pSorter = sqliteMallocRaw( sizeof(Sorter) ); if( pSorter==0 ) goto no_mem; pSorter->pNext = p->pSort; p->pSort = pSorter; assert( aStack[tos].flags & STK_Dyn ); pSorter->nKey = aStack[tos].n; pSorter->zKey = zStack[tos]; pSorter->nData = aStack[nos].n; |
︙ | ︙ | |||
4556 4557 4558 4559 4560 4561 4562 | for(i=p->tos-nField+1; i<=p->tos; i++){ if( (aStack[i].flags & STK_Null)==0 ){ if( Stringify(p, i) ) goto no_mem; nByte += aStack[i].n; } } nByte += sizeof(char*)*(nField+1); | | | 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 | for(i=p->tos-nField+1; i<=p->tos; i++){ if( (aStack[i].flags & STK_Null)==0 ){ if( Stringify(p, i) ) goto no_mem; nByte += aStack[i].n; } } nByte += sizeof(char*)*(nField+1); azArg = sqliteMallocRaw( nByte ); if( azArg==0 ) goto no_mem; z = (char*)&azArg[nField+1]; for(j=0, i=p->tos-nField+1; i<=p->tos; i++, j++){ if( aStack[i].flags & STK_Null ){ azArg[j] = 0; }else{ azArg[j] = z; |
︙ | ︙ | |||
4609 4610 4611 4612 4613 4614 4615 | if( (aStack[i].flags & STK_Null)!=0 ){ nByte += 2; }else{ if( Stringify(p, i) ) goto no_mem; nByte += aStack[i].n+2; } } | | | 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 | if( (aStack[i].flags & STK_Null)!=0 ){ nByte += 2; }else{ if( Stringify(p, i) ) goto no_mem; nByte += aStack[i].n+2; } } zNewKey = sqliteMallocRaw( nByte ); if( zNewKey==0 ) goto no_mem; j = 0; k = 0; for(i=p->tos-nField+1; i<=p->tos; i++){ if( (aStack[i].flags & STK_Null)!=0 ){ zNewKey[j++] = 'N'; zNewKey[j++] = 0; |
︙ | ︙ | |||
4938 4939 4940 4941 4942 4943 4944 | } pMem->s = aStack[tos]; flags = pMem->s.flags; if( flags & (STK_Static|STK_Dyn|STK_Ephem) ){ if( (flags & STK_Static)!=0 || (pOp->p2 && (flags & STK_Dyn)!=0) ){ pMem->z = zStack[tos]; }else if( flags & STK_Str ){ | | | 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 | } pMem->s = aStack[tos]; flags = pMem->s.flags; if( flags & (STK_Static|STK_Dyn|STK_Ephem) ){ if( (flags & STK_Static)!=0 || (pOp->p2 && (flags & STK_Dyn)!=0) ){ pMem->z = zStack[tos]; }else if( flags & STK_Str ){ pMem->z = sqliteMallocRaw( pMem->s.n ); if( pMem->z==0 ) goto no_mem; memcpy(pMem->z, zStack[tos], pMem->s.n); pMem->s.flags |= STK_Dyn; pMem->s.flags &= ~(STK_Static|STK_Ephem); } }else{ pMem->z = pMem->s.z; |
︙ | ︙ |