Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Reenable the memory management logic. The quick.test script now runs with SQLITE_MEMDEBUG and SQLITE_ENABLE_MEMORY_MANAGEMENT. 7 minor errors. (CVS 4265) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
1914044b8832041f13b20ead613bd137 |
User & Date: | drh 2007-08-22 00:39:20.000 |
Context
2007-08-22
| ||
02:56 | A complete run of quick.test with mutex debugging enabled. (CVS 4266) (check-in: 783e07d561 user: drh tags: trunk) | |
00:39 | Reenable the memory management logic. The quick.test script now runs with SQLITE_MEMDEBUG and SQLITE_ENABLE_MEMORY_MANAGEMENT. 7 minor errors. (CVS 4265) (check-in: 1914044b88 user: drh tags: trunk) | |
2007-08-21
| ||
20:25 | All mutexing and locking appears to be in place. Now we just have to test it and make it all work. (CVS 4264) (check-in: 0f7941aef9 user: drh tags: trunk) | |
Changes
Changes to src/btree.c.
1 2 3 4 5 6 7 8 9 10 11 | /* ** 2004 April 6 ** ** 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 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | /* ** 2004 April 6 ** ** 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.407 2007/08/22 00:39:20 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. ** Including a description of file format and an overview of operation. */ #include "btreeInt.h" /* ** The header string that appears at the beginning of every ** SQLite database. */ static const char zMagicHeader[] = SQLITE_FILE_HEADER; /* ** Set this global variable to 1 to enable tracing using the TRACE ** macro. */ #if SQLITE_TEST int sqlite3_btree_trace=0; /* True to enable tracing */ #endif #ifndef SQLITE_OMIT_SHARED_CACHE /* ** A flag to indicate whether or not shared cache is enabled. Also, ** a list of BtShared objects that are eligible for participation ** in shared cache. The variables have file scope during normal builds, ** but the test harness needs to access these variables so we make them ** global for test builds. */ #ifdef SQLITE_TEST BtShared *sqlite3SharedCacheList = 0; int sqlite3SharedCacheEnabled = 0; #else static BtShared *sqlite3SharedCacheList = 0; |
︙ | ︙ |
Changes to src/btreeInt.h.
1 2 3 4 5 6 7 8 9 10 11 | /* ** 2004 April 6 ** ** 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 | /* ** 2004 April 6 ** ** 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: btreeInt.h,v 1.9 2007/08/22 00:39:20 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. |
︙ | ︙ | |||
378 379 380 381 382 383 384 385 386 387 | int maxLeaf; /* Maximum local payload in a LEAFDATA table */ int minLeaf; /* Minimum local payload in a LEAFDATA table */ BusyHandler *pBusyHandler; /* Callback for when there is lock contention */ u8 inTransaction; /* Transaction state */ int nTransaction; /* Number of open transactions (read + write) */ void *pSchema; /* Pointer to space allocated by sqlite3BtreeSchema() */ void (*xFreeSchema)(void*); /* Destructor for BtShared.pSchema */ #ifndef SQLITE_OMIT_SHARED_CACHE int nRef; /* Number of references to this structure */ BtShared *pNext; /* Next on a list of sharable BtShared structs */ | > < | 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 | int maxLeaf; /* Maximum local payload in a LEAFDATA table */ int minLeaf; /* Minimum local payload in a LEAFDATA table */ BusyHandler *pBusyHandler; /* Callback for when there is lock contention */ u8 inTransaction; /* Transaction state */ int nTransaction; /* Number of open transactions (read + write) */ void *pSchema; /* Pointer to space allocated by sqlite3BtreeSchema() */ void (*xFreeSchema)(void*); /* Destructor for BtShared.pSchema */ sqlite3_mutex *mutex; /* Non-recursive mutex required to access this struct */ #ifndef SQLITE_OMIT_SHARED_CACHE int nRef; /* Number of references to this structure */ BtShared *pNext; /* Next on a list of sharable BtShared structs */ BtLock *pLock; /* List of locks held on this shared-btree struct */ #endif }; /* ** An instance of the following structure is used to hold information ** about a cell. The parseCellPtr() function fills in this structure |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** ** $Id: main.c,v 1.394 2007/08/22 00:39:20 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** The version of the library */ |
︙ | ︙ | |||
767 768 769 770 771 772 773 | */ const char *sqlite3_errmsg(sqlite3 *db){ const char *z; if( !db ){ return sqlite3ErrStr(SQLITE_NOMEM); } sqlite3_mutex_enter(db->mutex); | < > | 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 | */ const char *sqlite3_errmsg(sqlite3 *db){ const char *z; if( !db ){ return sqlite3ErrStr(SQLITE_NOMEM); } sqlite3_mutex_enter(db->mutex); if( sqlite3SafetyCheck(db) || db->errCode==SQLITE_MISUSE ){ return sqlite3ErrStr(SQLITE_MISUSE); } assert( !db->mallocFailed ); z = (char*)sqlite3_value_text(db->pErr); if( z==0 ){ z = sqlite3ErrStr(db->errCode); } sqlite3_mutex_leave(db->mutex); return z; } |
︙ | ︙ |
Changes to src/malloc.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. ** ************************************************************************* ** Memory allocation functions used throughout 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. ** ************************************************************************* ** Memory allocation functions used throughout sqlite. ** ** ** $Id: malloc.c,v 1.9 2007/08/22 00:39:20 drh Exp $ */ #include "sqliteInt.h" #include <stdarg.h> #include <ctype.h> /* ** This routine runs when the memory allocator sees that the |
︙ | ︙ | |||
54 55 56 57 58 59 60 | } } /* ** Release memory held by SQLite instances created by the current thread. */ int sqlite3_release_memory(int n){ | | | 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | } } /* ** Release memory held by SQLite instances created by the current thread. */ int sqlite3_release_memory(int n){ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT return sqlite3PagerReleaseMemory(n); #else return SQLITE_OK; #endif } |
︙ | ︙ |
Changes to src/mutex.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 file contains the C functions that implement mutexes for ** use by the SQLite core. ** | | | 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 file contains the C functions that implement mutexes for ** use by the SQLite core. ** ** $Id: mutex.c,v 1.7 2007/08/22 00:39:20 drh Exp $ */ /* ** If SQLITE_MUTEX_APPDEF is defined, then this whole module is ** omitted and equivalent functionality must be provided by the ** application that links against the SQLite library. */ #ifndef SQLITE_MUTEX_APPDEF |
︙ | ︙ | |||
122 123 124 125 126 127 128 | /* ** The sqlite3_mutex_alloc() routine allocates a new ** mutex and returns a pointer to it. If it returns NULL ** that means that a mutex could not be allocated. */ sqlite3_mutex *sqlite3_mutex_alloc(int id){ | | > > | 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | /* ** The sqlite3_mutex_alloc() routine allocates a new ** mutex and returns a pointer to it. If it returns NULL ** that means that a mutex could not be allocated. */ sqlite3_mutex *sqlite3_mutex_alloc(int id){ static sqlite3_mutex aStatic[4]; sqlite3_mutex *pNew = 0; switch( id ){ case SQLITE_MUTEX_FAST: case SQLITE_MUTEX_RECURSIVE: { pNew = sqlite3_malloc(sizeof(*pNew)); if( pNew ){ pNew->id = id; pNew->cnt = 0; } break; } default: { assert( id-SQLITE_MUTEX_STATIC_MASTER >= 0 ); assert( id-SQLITE_MUTEX_STATIC_MASTER < count(aStatic) ); pNew = &aStatic[id-SQLITE_MUTEX_STATIC_MASTER]; pNew->id = id; break; } } return pNew; } |
︙ | ︙ | |||
265 266 267 268 269 270 271 272 273 274 275 276 277 278 | ** the same type number. */ sqlite3_mutex *sqlite3_mutex_alloc(int iType){ static sqlite3_mutex staticMutexes[] = { { PTHREAD_MUTEX_INITIALIZER, }, { PTHREAD_MUTEX_INITIALIZER, }, { PTHREAD_MUTEX_INITIALIZER, }, }; sqlite3_mutex *p; switch( iType ){ case SQLITE_MUTEX_FAST: { p = sqlite3MallocZero( sizeof(*p) ); if( p ){ p->id = iType; | > | 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 | ** the same type number. */ sqlite3_mutex *sqlite3_mutex_alloc(int iType){ static sqlite3_mutex staticMutexes[] = { { PTHREAD_MUTEX_INITIALIZER, }, { PTHREAD_MUTEX_INITIALIZER, }, { PTHREAD_MUTEX_INITIALIZER, }, { PTHREAD_MUTEX_INITIALIZER, }, }; sqlite3_mutex *p; switch( iType ){ case SQLITE_MUTEX_FAST: { p = sqlite3MallocZero( sizeof(*p) ); if( p ){ p->id = iType; |
︙ | ︙ | |||
287 288 289 290 291 292 293 294 295 296 297 298 299 300 | pthread_mutex_init(&px->auxMutex, 0); pthread_mutex_init(&px->mainMutex, 0); px->nRef = 0; } break; } default: { p = &staticMutexes[iType-2]; p->id = iType; break; } } return p; } | > > | 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 | pthread_mutex_init(&px->auxMutex, 0); pthread_mutex_init(&px->mainMutex, 0); px->nRef = 0; } break; } default: { assert( iType-2 >= 0 ); assert( iType-2 < count(staticMutexes) ); p = &staticMutexes[iType-2]; p->id = iType; break; } } return p; } |
︙ | ︙ |
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.365 2007/08/22 00:39:20 drh Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" #include <assert.h> #include <string.h> /* |
︙ | ︙ | |||
358 359 360 361 362 363 364 | #ifdef SQLITE_HAS_CODEC void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */ void *pCodecArg; /* First argument to xCodec() */ #endif int nHash; /* Size of the pager hash table */ PgHdr **aHash; /* Hash table to map page number to PgHdr */ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT | | > > > > > > > > > > > > | 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 | #ifdef SQLITE_HAS_CODEC void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */ void *pCodecArg; /* First argument to xCodec() */ #endif int nHash; /* Size of the pager hash table */ PgHdr **aHash; /* Hash table to map page number to PgHdr */ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT Pager *pNext; /* Doubly linked list of pagers on which */ Pager *pPrev; /* sqlite3_release_memory() will work */ int iInUseMM; /* Non-zero if unavailable to MM */ int iInUseDB; /* Non-zero if in sqlite3_release_memory() */ #endif char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */ char dbFileVers[16]; /* Changes whenever database file changes */ }; /* ** The following global variables hold counters used for ** testing purposes only. These variables do not exist in ** a non-testing build. These variables are not thread-safe. */ #ifdef SQLITE_TEST int sqlite3_pager_readdb_count = 0; /* Number of full pages read from DB */ int sqlite3_pager_writedb_count = 0; /* Number of full pages written to DB */ int sqlite3_pager_writej_count = 0; /* Number of pages written to journal */ int sqlite3_pager_pgfree_count = 0; /* Number of cache pages freed */ # define PAGER_INCR(v) v++ #else # define PAGER_INCR(v) #endif /* ** The following variable points to the head of a double-linked list ** of all pagers that are eligible for page stealing by the ** sqlite3_release_memory() interface. Access to this list is ** protected by the SQLITE_MUTEX_STATIC_MEM2 mutex. */ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT static Pager *sqlite3PagerList = 0; #endif /* ** Journal files begin with the following magic string. The data ** was obtained from /dev/random. It is used only as a sanity check. ** ** Since version 2.8.0, the journal format contains additional sanity |
︙ | ︙ | |||
448 449 450 451 452 453 454 455 456 457 458 459 460 461 | #define PAGER_MJ_PGNO(x) ((PENDING_BYTE/((x)->pageSize))+1) /* ** The maximum legal page number is (2^31 - 1). */ #define PAGER_MAX_PGNO 2147483647 /* ** Enable reference count tracking (for debugging) here: */ #ifdef SQLITE_DEBUG int pager3_refinfo_enable = 0; static void pager_refinfo(PgHdr *p){ static int cnt = 0; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 | #define PAGER_MJ_PGNO(x) ((PENDING_BYTE/((x)->pageSize))+1) /* ** The maximum legal page number is (2^31 - 1). */ #define PAGER_MAX_PGNO 2147483647 /* ** The pagerEnter() and pagerLeave() routines acquire and release ** a mutex on each pager. The mutex is recursive. ** ** This is a special-purpose mutex. It only provides mutual exclusion ** between the Btree and the Memory Management sqlite3_release_memory() ** function. It does not prevent, for example, two Btrees from accessing ** the same pager at the same time. Other general-purpose mutexes in ** the btree layer handle that chore. */ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT static void pagerEnter(Pager *p){ p->iInUseDB++; if( p->iInUseMM && p->iInUseDB==1 ){ sqlite3_mutex *mutex; mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2); p->iInUseDB = 0; sqlite3_mutex_enter(mutex); p->iInUseDB = 1; sqlite3_mutex_leave(mutex); } assert( p->iInUseMM==0 ); } static void pagerLeave(Pager *p){ p->iInUseDB--; assert( p->iInUseDB>=0 ); } #else # define pagerEnter(X) # define pagerLeave(X) #endif /* ** Enable reference count tracking (for debugging) here: */ #ifdef SQLITE_DEBUG int pager3_refinfo_enable = 0; static void pager_refinfo(PgHdr *p){ static int cnt = 0; |
︙ | ︙ | |||
1756 1757 1758 1759 1760 1761 1762 | ** automatically when it is closed. ** ** If zFilename is ":memory:" then all information is held in cache. ** It is never written to disk. This can be used to implement an ** in-memory database. */ int sqlite3PagerOpen( | | < < < < < < < < < < < | < < < < < < | 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 | ** automatically when it is closed. ** ** If zFilename is ":memory:" then all information is held in cache. ** It is never written to disk. This can be used to implement an ** in-memory database. */ int sqlite3PagerOpen( sqlite3_vfs *pVfs, /* The virtual file system to use */ Pager **ppPager, /* Return the Pager structure here */ const char *zFilename, /* Name of the database file to open */ int nExtra, /* Extra bytes append to each in-memory page */ int flags /* flags controlling this file */ ){ u8 *pPtr; Pager *pPager = 0; char *zFullPathname = 0; int rc = SQLITE_OK; int i; int tempFile = 0; int memDb = 0; int readOnly = 0; int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; int noReadlock = (flags & PAGER_NO_READLOCK)!=0; /* The default return is a NULL pointer */ *ppPager = 0; /* Allocate memory for the pager structure */ pPager = sqlite3MallocZero( sizeof(*pPager) + /* Pager structure */ pVfs->szOsFile * 3 + /* The db, journal and stmt journal files */ pVfs->mxPathname * 3 + 30 /* zFilename, zDirectory, zJournal */ |
︙ | ︙ | |||
1911 1912 1913 1914 1915 1916 1917 | if( !memDb ){ setSectorSize(pPager); } /* pPager->pBusyHandler = 0; */ /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */ *ppPager = pPager; #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT | > > > > > | > > > > > | > > | 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 | if( !memDb ){ setSectorSize(pPager); } /* pPager->pBusyHandler = 0; */ /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */ *ppPager = pPager; #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT pPager->iInUseMM = 0; pPager->iInUseDB = 0; if( !memDb ){ sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2); sqlite3_mutex_enter(mutex); pPager->pNext = sqlite3PagerList; if( sqlite3PagerList ){ assert( sqlite3PagerList->pPrev==0 ); sqlite3PagerList->pPrev = pPager; } pPager->pPrev = 0; sqlite3PagerList = pPager; sqlite3_mutex_leave(mutex); } #endif return SQLITE_OK; } /* ** Set the busy handler function. */ |
︙ | ︙ | |||
1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 | ** Set the page size. Return the new size. If the suggest new page ** size is inappropriate, then an alternative page size is selected ** and returned. */ int sqlite3PagerSetPagesize(Pager *pPager, int pageSize){ assert( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE ); if( !pPager->memDb && pPager->nRef==0 ){ pager_reset(pPager); pPager->pageSize = pageSize; sqlite3_free(pPager->pTmpSpace); pPager->pTmpSpace = sqlite3_malloc(pageSize); } return pPager->pageSize; } /* | > > | 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 | ** Set the page size. Return the new size. If the suggest new page ** size is inappropriate, then an alternative page size is selected ** and returned. */ int sqlite3PagerSetPagesize(Pager *pPager, int pageSize){ assert( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE ); if( !pPager->memDb && pPager->nRef==0 ){ pagerEnter(pPager); pager_reset(pPager); pPager->pageSize = pageSize; pagerLeave(pPager); sqlite3_free(pPager->pTmpSpace); pPager->pTmpSpace = sqlite3_malloc(pageSize); } return pPager->pageSize; } /* |
︙ | ︙ | |||
2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 | return SQLITE_OK; } if( MEMDB ){ pPager->dbSize = nPage; pager_truncate_cache(pPager); return SQLITE_OK; } rc = syncJournal(pPager); if( rc!=SQLITE_OK ){ return rc; } /* Get an exclusive lock on the database before truncating. */ rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); if( rc!=SQLITE_OK ){ return rc; } rc = pager_truncate(pPager, nPage); return rc; } | > > > > | 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 | return SQLITE_OK; } if( MEMDB ){ pPager->dbSize = nPage; pager_truncate_cache(pPager); return SQLITE_OK; } pagerEnter(pPager); rc = syncJournal(pPager); pagerLeave(pPager); if( rc!=SQLITE_OK ){ return rc; } /* Get an exclusive lock on the database before truncating. */ pagerEnter(pPager); rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); pagerLeave(pPager); if( rc!=SQLITE_OK ){ return rc; } rc = pager_truncate(pPager, nPage); return rc; } |
︙ | ︙ | |||
2269 2270 2271 2272 2273 2274 2275 | ** This function always succeeds. If a transaction is active an attempt ** is made to roll it back. If an error occurs during the rollback ** a hot journal may be left in the filesystem but no error is returned ** to the caller. */ int sqlite3PagerClose(Pager *pPager){ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT | | | < < < | | > > > > | > > > > | 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 | ** This function always succeeds. If a transaction is active an attempt ** is made to roll it back. If an error occurs during the rollback ** a hot journal may be left in the filesystem but no error is returned ** to the caller. */ int sqlite3PagerClose(Pager *pPager){ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT if( !MEMDB ){ sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2); sqlite3_mutex_enter(mutex); if( pPager->pPrev ){ pPager->pPrev->pNext = pPager->pNext; }else{ sqlite3PagerList = pPager->pNext; } if( pPager->pNext ){ pPager->pNext->pPrev = pPager->pPrev; } sqlite3_mutex_leave(mutex); } #endif disable_simulated_io_errors(); pPager->errCode = 0; pPager->exclusiveMode = 0; pager_reset(pPager); pagerUnlockAndRollback(pPager); |
︙ | ︙ | |||
2302 2303 2304 2305 2306 2307 2308 | sqlite3OsClose(pPager->fd); /* Temp files are automatically deleted by the OS ** if( pPager->tempFile ){ ** sqlite3OsDelete(pPager->zFilename); ** } */ | < < < < < < < < < < < < | 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 | sqlite3OsClose(pPager->fd); /* Temp files are automatically deleted by the OS ** if( pPager->tempFile ){ ** sqlite3OsDelete(pPager->zFilename); ** } */ sqlite3_free(pPager->aHash); sqlite3_free(pPager->pTmpSpace); sqlite3_free(pPager); return SQLITE_OK; } #if !defined(NDEBUG) || defined(SQLITE_TEST) |
︙ | ︙ | |||
2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 | #endif /* ** Increment the reference count for a page. The input pointer is ** a reference to the page data. */ int sqlite3PagerRef(DbPage *pPg){ page_ref(pPg); return SQLITE_OK; } /* ** Sync the journal. In other words, make sure all the pages that have ** been written to the journal have actually reached the surface of the ** disk. It is not safe to modify the original database file until after | > > | 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 | #endif /* ** Increment the reference count for a page. The input pointer is ** a reference to the page data. */ int sqlite3PagerRef(DbPage *pPg){ pagerEnter(pPg->pPager); page_ref(pPg); pagerLeave(pPg->pPager); return SQLITE_OK; } /* ** Sync the journal. In other words, make sure all the pages that have ** been written to the journal have actually reached the surface of the ** disk. It is not safe to modify the original database file until after |
︙ | ︙ | |||
2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 | unlinkPage(pPg); assert( pPg->pgno==0 ); *ppPg = pPg; return SQLITE_OK; } /* ** This function is called to free superfluous dynamically allocated memory ** held by the pager system. Memory in use by any SQLite pager allocated ** by the current thread may be sqlite3_free()ed. ** ** nReq is the number of bytes of memory required. Once this much has | > | < < < | > > | | > | > | > | < | < > < | > | < | > > | 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 | unlinkPage(pPg); assert( pPg->pgno==0 ); *ppPg = pPg; return SQLITE_OK; } #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT /* ** This function is called to free superfluous dynamically allocated memory ** held by the pager system. Memory in use by any SQLite pager allocated ** by the current thread may be sqlite3_free()ed. ** ** nReq is the number of bytes of memory required. Once this much has ** been released, the function returns. The return value is the total number ** of bytes of memory released. */ int sqlite3PagerReleaseMemory(int nReq){ int nReleased = 0; /* Bytes of memory released so far */ sqlite3_mutex *mutex; /* The MEM2 mutex */ Pager *pPager; /* For looping over pagers */ int i; /* Passes over pagers */ /* Acquire the memory-management mutex */ mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2); sqlite3_mutex_enter(mutex); /* Signal all database connections that memory management wants ** to have access to the pagers. */ for(pPager=sqlite3PagerList; pPager; pPager=pPager->pNext){ pPager->iInUseMM = 1; } /* Outermost loop runs for at most two iterations. First iteration we ** try to find memory that can be released without calling fsync(). Second ** iteration (which only runs if the first failed to free nReq bytes of ** memory) is permitted to call fsync(). This is of course much more ** expensive. */ for(i=0; i<=1; i++){ /* Loop through all the SQLite pagers opened by the current thread. */ Pager *pPager = sqlite3PagerList; for( ; pPager && (nReq<0 || nReleased<nReq); pPager=pPager->pNext){ PgHdr *pPg; int rc; /* In-memory databases should not appear on the pager list */ assert( !MEMDB ); /* Skip pagers that are currently in use by the b-tree layer */ if( pPager->iInUseDB ) continue; /* For each pager, try to free as many pages as possible (without ** calling fsync() if this is the first iteration of the outermost ** loop). */ while( SQLITE_OK==(rc = pager_recycle(pPager, i, &pPg)) && pPg) { /* We've found a page to free. At this point the page has been |
︙ | ︙ | |||
2818 2819 2820 2821 2822 2823 2824 | assert( pPg ); if( pPg==pPager->pAll ){ pPager->pAll = pPg->pNextAll; }else{ for( pTmp=pPager->pAll; pTmp->pNextAll!=pPg; pTmp=pTmp->pNextAll ){} pTmp->pNextAll = pPg->pNextAll; } | < < < < | 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 | assert( pPg ); if( pPg==pPager->pAll ){ pPager->pAll = pPg->pNextAll; }else{ for( pTmp=pPager->pAll; pTmp->pNextAll!=pPg; pTmp=pTmp->pNextAll ){} pTmp->pNextAll = pPg->pNextAll; } nReleased += ( sizeof(*pPg) + pPager->pageSize + sizeof(u32) + pPager->nExtra + MEMDB*sizeof(PgHistory) ); IOTRACE(("PGFREE %p %d *\n", pPager, pPg->pgno)); PAGER_INCR(sqlite3_pager_pgfree_count); sqlite3_free(pPg); } if( rc!=SQLITE_OK ){ /* An error occured whilst writing to the database file or |
︙ | ︙ | |||
2850 2851 2852 2853 2854 2855 2856 2857 2858 | ); assert( pPager->state>=PAGER_RESERVED ); pager_error(pPager, rc); } } } return nReleased; } | > > > > > > > > > | | 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 | ); assert( pPager->state>=PAGER_RESERVED ); pager_error(pPager, rc); } } } /* Clear the memory management flags and release the mutex */ for(pPager=sqlite3PagerList; pPager; pPager=pPager->pNext){ pPager->iInUseMM = 0; } sqlite3_mutex_leave(mutex); /* Return the number of bytes released */ return nReleased; } #endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */ /* ** Read the content of page pPg out of the database file. */ static int readDbPage(Pager *pPager, PgHdr *pPg, Pgno pgno){ int rc; i64 offset; |
︙ | ︙ | |||
3158 3159 3160 3161 3162 3163 3164 | ** of the page at this time, so do not do a disk read. Just fill in the ** page content with zeros. But mark the fact that we have not read the ** content by setting the PgHdr.needRead flag. Later on, if ** sqlite3PagerWrite() is called on this page or if this routine is ** called again with noContent==0, that means that the content is needed ** and the disk read should occur at that point. */ | | | 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 | ** of the page at this time, so do not do a disk read. Just fill in the ** page content with zeros. But mark the fact that we have not read the ** content by setting the PgHdr.needRead flag. Later on, if ** sqlite3PagerWrite() is called on this page or if this routine is ** called again with noContent==0, that means that the content is needed ** and the disk read should occur at that point. */ static int pagerAcquire( Pager *pPager, /* The pager open on the database file */ Pgno pgno, /* Page number to fetch */ DbPage **ppPage, /* Write a pointer to the page here */ int noContent /* Do not bother reading content from disk if true */ ){ PgHdr *pPg; int rc; |
︙ | ︙ | |||
3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 | } } page_ref(pPg); } *ppPage = pPg; return SQLITE_OK; } /* ** Acquire a page if it is already in the in-memory cache. Do ** not read the page from disk. Return a pointer to the page, ** or 0 if the page is not in cache. ** ** See also sqlite3PagerGet(). The difference between this routine ** and sqlite3PagerGet() is that _get() will go to the disk and read ** in the page if the page is not already in cache. This routine ** returns NULL if the page is not in cache or if a disk I/O error ** has ever happened. */ DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){ | > > > > > > > > > > > > > | > < < | < < > | < | > > > | 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 | } } page_ref(pPg); } *ppPage = pPg; return SQLITE_OK; } int sqlite3PagerAcquire( Pager *pPager, /* The pager open on the database file */ Pgno pgno, /* Page number to fetch */ DbPage **ppPage, /* Write a pointer to the page here */ int noContent /* Do not bother reading content from disk if true */ ){ int rc; pagerEnter(pPager); rc = pagerAcquire(pPager, pgno, ppPage, noContent); pagerLeave(pPager); return rc; } /* ** Acquire a page if it is already in the in-memory cache. Do ** not read the page from disk. Return a pointer to the page, ** or 0 if the page is not in cache. ** ** See also sqlite3PagerGet(). The difference between this routine ** and sqlite3PagerGet() is that _get() will go to the disk and read ** in the page if the page is not already in cache. This routine ** returns NULL if the page is not in cache or if a disk I/O error ** has ever happened. */ DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){ PgHdr *pPg = 0; assert( pPager!=0 ); assert( pgno!=0 ); pagerEnter(pPager); if( pPager->state==PAGER_UNLOCK ){ assert( !pPager->pAll || pPager->exclusiveMode ); }else if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){ /* Do nothing */ }else if( (pPg = pager_lookup(pPager, pgno))!=0 ){ page_ref(pPg); } pagerLeave(pPager); return pPg; } /* ** Release a page. ** ** If the number of references to the page drop to zero, then the ** page is added to the LRU list. When all references to all pages ** are released, a rollback occurs and the lock on the database is ** removed. */ int sqlite3PagerUnref(DbPage *pPg){ /* Decrement the reference count for this page */ assert( pPg->nRef>0 ); pagerEnter(pPg->pPager); pPg->nRef--; REFINFO(pPg); CHECK_PAGE(pPg); /* When the number of references to a page reach 0, call the ** destructor and add the page to the freelist. |
︙ | ︙ | |||
3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 | */ pPager->nRef--; assert( pPager->nRef>=0 ); if( pPager->nRef==0 && (!pPager->exclusiveMode || pPager->journalOff>0) ){ pagerUnlockAndRollback(pPager); } } return SQLITE_OK; } /* ** Create a journal file for pPager. There should already be a RESERVED ** or EXCLUSIVE lock on the database file when this routine is called. ** | > | 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 | */ pPager->nRef--; assert( pPager->nRef>=0 ); if( pPager->nRef==0 && (!pPager->exclusiveMode || pPager->journalOff>0) ){ pagerUnlockAndRollback(pPager); } } pagerLeave(pPg->pPager); return SQLITE_OK; } /* ** Create a journal file for pPager. There should already be a RESERVED ** or EXCLUSIVE lock on the database file when this routine is called. ** |
︙ | ︙ | |||
3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 | ** If exFlag is true, go ahead and get an EXCLUSIVE lock on the file ** immediately instead of waiting until we try to flush the cache. The ** exFlag is ignored if a transaction is already active. */ int sqlite3PagerBegin(DbPage *pPg, int exFlag){ Pager *pPager = pPg->pPager; int rc = SQLITE_OK; assert( pPg->nRef>0 ); assert( pPager->state!=PAGER_UNLOCK ); if( pPager->state==PAGER_SHARED ){ assert( pPager->aInJournal==0 ); if( MEMDB ){ pPager->state = PAGER_EXCLUSIVE; pPager->origDbSize = pPager->dbSize; }else{ rc = sqlite3OsLock(pPager->fd, RESERVED_LOCK); if( rc==SQLITE_OK ){ pPager->state = PAGER_RESERVED; if( exFlag ){ rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); } } if( rc!=SQLITE_OK ){ return rc; } pPager->dirtyCache = 0; PAGERTRACE2("TRANSACTION %d\n", PAGERID(pPager)); if( pPager->useJournal && !pPager->tempFile ){ rc = pager_open_journal(pPager); } | > > | 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 | ** If exFlag is true, go ahead and get an EXCLUSIVE lock on the file ** immediately instead of waiting until we try to flush the cache. The ** exFlag is ignored if a transaction is already active. */ int sqlite3PagerBegin(DbPage *pPg, int exFlag){ Pager *pPager = pPg->pPager; int rc = SQLITE_OK; pagerEnter(pPager); assert( pPg->nRef>0 ); assert( pPager->state!=PAGER_UNLOCK ); if( pPager->state==PAGER_SHARED ){ assert( pPager->aInJournal==0 ); if( MEMDB ){ pPager->state = PAGER_EXCLUSIVE; pPager->origDbSize = pPager->dbSize; }else{ rc = sqlite3OsLock(pPager->fd, RESERVED_LOCK); if( rc==SQLITE_OK ){ pPager->state = PAGER_RESERVED; if( exFlag ){ rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); } } if( rc!=SQLITE_OK ){ pagerLeave(pPager); return rc; } pPager->dirtyCache = 0; PAGERTRACE2("TRANSACTION %d\n", PAGERID(pPager)); if( pPager->useJournal && !pPager->tempFile ){ rc = pager_open_journal(pPager); } |
︙ | ︙ | |||
3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 | rc = SQLITE_NOMEM; }else{ pPager->origDbSize = pPager->dbSize; rc = writeJournalHdr(pPager); } } assert( !pPager->journalOpen || pPager->journalOff>0 || rc!=SQLITE_OK ); return rc; } /* ** Make a page dirty. Set its dirty flag and add it to the dirty ** page list. */ | > | 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 | rc = SQLITE_NOMEM; }else{ pPager->origDbSize = pPager->dbSize; rc = writeJournalHdr(pPager); } } assert( !pPager->journalOpen || pPager->journalOff>0 || rc!=SQLITE_OK ); pagerLeave(pPager); return rc; } /* ** Make a page dirty. Set its dirty flag and add it to the dirty ** page list. */ |
︙ | ︙ | |||
3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 | int sqlite3PagerWrite(DbPage *pDbPage){ int rc = SQLITE_OK; PgHdr *pPg = pDbPage; Pager *pPager = pPg->pPager; Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize); if( !MEMDB && nPagePerSector>1 ){ Pgno nPageCount; /* Total number of pages in database file */ Pgno pg1; /* First page of the sector pPg is located on. */ int nPage; /* Number of pages starting at pg1 to journal */ int ii; /* Set the doNotSync flag to 1. This is because we cannot allow a journal | > | 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 | int sqlite3PagerWrite(DbPage *pDbPage){ int rc = SQLITE_OK; PgHdr *pPg = pDbPage; Pager *pPager = pPg->pPager; Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize); pagerEnter(pPager); if( !MEMDB && nPagePerSector>1 ){ Pgno nPageCount; /* Total number of pages in database file */ Pgno pg1; /* First page of the sector pPg is located on. */ int nPage; /* Number of pages starting at pg1 to journal */ int ii; /* Set the doNotSync flag to 1. This is because we cannot allow a journal |
︙ | ︙ | |||
3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 | } assert( pPager->doNotSync==1 ); pPager->doNotSync = 0; }else{ rc = pager_write(pDbPage); } return rc; } /* ** Return TRUE if the page given in the argument was previously passed ** to sqlite3PagerWrite(). In other words, return TRUE if it is ok ** to change the content of the page. | > | 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 | } assert( pPager->doNotSync==1 ); pPager->doNotSync = 0; }else{ rc = pager_write(pDbPage); } pagerLeave(pPager); return rc; } /* ** Return TRUE if the page given in the argument was previously passed ** to sqlite3PagerWrite(). In other words, return TRUE if it is ok ** to change the content of the page. |
︙ | ︙ | |||
3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 | ** Replace the content of a single page with the information in the third ** argument. */ int sqlite3PagerOverwrite(Pager *pPager, Pgno pgno, void *pData){ PgHdr *pPg; int rc; rc = sqlite3PagerGet(pPager, pgno, &pPg); if( rc==SQLITE_OK ){ rc = sqlite3PagerWrite(pPg); if( rc==SQLITE_OK ){ memcpy(sqlite3PagerGetData(pPg), pData, pPager->pageSize); } sqlite3PagerUnref(pPg); } return rc; } #endif /* ** A call to this routine tells the pager that it is not necessary to ** write the information on page pPg back to the disk, even though | > > | 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 | ** Replace the content of a single page with the information in the third ** argument. */ int sqlite3PagerOverwrite(Pager *pPager, Pgno pgno, void *pData){ PgHdr *pPg; int rc; pagerEnter(pPager); rc = sqlite3PagerGet(pPager, pgno, &pPg); if( rc==SQLITE_OK ){ rc = sqlite3PagerWrite(pPg); if( rc==SQLITE_OK ){ memcpy(sqlite3PagerGetData(pPg), pData, pPager->pageSize); } sqlite3PagerUnref(pPg); } pagerLeave(pPager); return rc; } #endif /* ** A call to this routine tells the pager that it is not necessary to ** write the information on page pPg back to the disk, even though |
︙ | ︙ | |||
3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 | ** rolled back in spite of the sqlite3PagerDontRollback() call. */ void sqlite3PagerDontWrite(DbPage *pDbPage){ PgHdr *pPg = pDbPage; Pager *pPager = pPg->pPager; if( MEMDB ) return; pPg->alwaysRollback = 1; if( pPg->dirty && !pPager->stmtInUse ){ assert( pPager->state>=PAGER_SHARED ); if( pPager->dbSize==(int)pPg->pgno && pPager->origDbSize<pPager->dbSize ){ /* If this pages is the last page in the file and the file has grown ** during the current transaction, then do NOT mark the page as clean. ** When the database file grows, we must make sure that the last page | > | 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 | ** rolled back in spite of the sqlite3PagerDontRollback() call. */ void sqlite3PagerDontWrite(DbPage *pDbPage){ PgHdr *pPg = pDbPage; Pager *pPager = pPg->pPager; if( MEMDB ) return; pagerEnter(pPager); pPg->alwaysRollback = 1; if( pPg->dirty && !pPager->stmtInUse ){ assert( pPager->state>=PAGER_SHARED ); if( pPager->dbSize==(int)pPg->pgno && pPager->origDbSize<pPager->dbSize ){ /* If this pages is the last page in the file and the file has grown ** during the current transaction, then do NOT mark the page as clean. ** When the database file grows, we must make sure that the last page |
︙ | ︙ | |||
3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 | IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno)) makeClean(pPg); #ifdef SQLITE_CHECK_PAGES pPg->pageHash = pager_pagehash(pPg); #endif } } } /* ** A call to this routine tells the pager that if a rollback occurs, ** it is not necessary to restore the data on the given page. This ** means that the pager does not have to record the given page in the ** rollback journal. ** ** If we have not yet actually read the content of this page (if ** the PgHdr.needRead flag is set) then this routine acts as a promise ** that we will never need to read the page content in the future. ** so the needRead flag can be cleared at this point. */ void sqlite3PagerDontRollback(DbPage *pPg){ Pager *pPager = pPg->pPager; assert( pPager->state>=PAGER_RESERVED ); if( pPager->journalOpen==0 ) return; if( pPg->alwaysRollback || pPager->alwaysRollback || MEMDB ) return; if( !pPg->inJournal && (int)pPg->pgno <= pPager->origDbSize ){ assert( pPager->aInJournal!=0 ); pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7); pPg->inJournal = 1; | > > | 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 | IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno)) makeClean(pPg); #ifdef SQLITE_CHECK_PAGES pPg->pageHash = pager_pagehash(pPg); #endif } } pagerLeave(pPager); } /* ** A call to this routine tells the pager that if a rollback occurs, ** it is not necessary to restore the data on the given page. This ** means that the pager does not have to record the given page in the ** rollback journal. ** ** If we have not yet actually read the content of this page (if ** the PgHdr.needRead flag is set) then this routine acts as a promise ** that we will never need to read the page content in the future. ** so the needRead flag can be cleared at this point. */ void sqlite3PagerDontRollback(DbPage *pPg){ Pager *pPager = pPg->pPager; pagerEnter(pPager); assert( pPager->state>=PAGER_RESERVED ); if( pPager->journalOpen==0 ) return; if( pPg->alwaysRollback || pPager->alwaysRollback || MEMDB ) return; if( !pPg->inJournal && (int)pPg->pgno <= pPager->origDbSize ){ assert( pPager->aInJournal!=0 ); pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7); pPg->inJournal = 1; |
︙ | ︙ | |||
3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 | && !pageInStatement(pPg) && (int)pPg->pgno<=pPager->stmtSize ){ assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize ); assert( pPager->aInStmt!=0 ); pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7); } } /* ** This routine is called to increment the database file change-counter, ** stored at byte 24 of the pager file. */ | > | 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 | && !pageInStatement(pPg) && (int)pPg->pgno<=pPager->stmtSize ){ assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize ); assert( pPager->aInStmt!=0 ); pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7); } pagerLeave(pPager); } /* ** This routine is called to increment the database file change-counter, ** stored at byte 24 of the pager file. */ |
︙ | ︙ | |||
3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 | ** nTrunc pages (this is used by auto-vacuum databases). */ int sqlite3PagerCommitPhaseOne(Pager *pPager, const char *zMaster, Pgno nTrunc){ int rc = SQLITE_OK; PAGERTRACE4("DATABASE SYNC: File=%s zMaster=%s nTrunc=%d\n", pPager->zFilename, zMaster, nTrunc); /* If this is an in-memory db, or no pages have been written to, or this ** function has already been called, it is a no-op. */ if( pPager->state!=PAGER_SYNCED && !MEMDB && pPager->dirtyCache ){ PgHdr *pPg; assert( pPager->journalOpen ); | > | 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 | ** nTrunc pages (this is used by auto-vacuum databases). */ int sqlite3PagerCommitPhaseOne(Pager *pPager, const char *zMaster, Pgno nTrunc){ int rc = SQLITE_OK; PAGERTRACE4("DATABASE SYNC: File=%s zMaster=%s nTrunc=%d\n", pPager->zFilename, zMaster, nTrunc); pagerEnter(pPager); /* If this is an in-memory db, or no pages have been written to, or this ** function has already been called, it is a no-op. */ if( pPager->state!=PAGER_SYNCED && !MEMDB && pPager->dirtyCache ){ PgHdr *pPg; assert( pPager->journalOpen ); |
︙ | ︙ | |||
4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 | /* pager_incr_changecounter() may attempt to obtain an exclusive * lock to spill the cache and return IOERR_BLOCKED. But since * there is no chance the cache is inconsistent, it's * better to return SQLITE_BUSY. */ rc = SQLITE_BUSY; } return rc; } /* ** Commit all changes to the database and release the write lock. ** | > | 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 | /* pager_incr_changecounter() may attempt to obtain an exclusive * lock to spill the cache and return IOERR_BLOCKED. But since * there is no chance the cache is inconsistent, it's * better to return SQLITE_BUSY. */ rc = SQLITE_BUSY; } pagerLeave(pPager); return rc; } /* ** Commit all changes to the database and release the write lock. ** |
︙ | ︙ | |||
4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 | if( pPager->errCode ){ return pPager->errCode; } if( pPager->state<PAGER_RESERVED ){ return SQLITE_ERROR; } PAGERTRACE2("COMMIT %d\n", PAGERID(pPager)); if( MEMDB ){ pPg = pager_get_all_dirty_pages(pPager); while( pPg ){ PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); clearHistory(pHist); pPg->dirty = 0; | > | 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 | if( pPager->errCode ){ return pPager->errCode; } if( pPager->state<PAGER_RESERVED ){ return SQLITE_ERROR; } pagerEnter(pPager); PAGERTRACE2("COMMIT %d\n", PAGERID(pPager)); if( MEMDB ){ pPg = pager_get_all_dirty_pages(pPager); while( pPg ){ PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); clearHistory(pHist); pPg->dirty = 0; |
︙ | ︙ | |||
4103 4104 4105 4106 4107 4108 4109 | pPager->pStmt = 0; pPager->state = PAGER_SHARED; return SQLITE_OK; } assert( pPager->journalOpen || !pPager->dirtyCache ); assert( pPager->state==PAGER_SYNCED || !pPager->dirtyCache ); rc = pager_end_transaction(pPager); | | > > | 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 | pPager->pStmt = 0; pPager->state = PAGER_SHARED; return SQLITE_OK; } assert( pPager->journalOpen || !pPager->dirtyCache ); assert( pPager->state==PAGER_SYNCED || !pPager->dirtyCache ); rc = pager_end_transaction(pPager); rc = pager_error(pPager, rc); pagerLeave(pPager); return rc; } /* ** Rollback all changes. The database falls back to PAGER_SHARED mode. ** All in-memory cache pages revert to their original data contents. ** The journal is deleted. ** |
︙ | ︙ | |||
4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 | pPager->dbSize = pPager->origDbSize; pager_truncate_cache(pPager); pPager->stmtInUse = 0; pPager->state = PAGER_SHARED; return SQLITE_OK; } if( !pPager->dirtyCache || !pPager->journalOpen ){ rc = pager_end_transaction(pPager); return rc; } if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){ if( pPager->state>=PAGER_EXCLUSIVE ){ pager_playback(pPager, 0); } return pPager->errCode; } if( pPager->state==PAGER_RESERVED ){ int rc2; rc = pager_playback(pPager, 0); rc2 = pager_end_transaction(pPager); if( rc==SQLITE_OK ){ rc = rc2; } }else{ rc = pager_playback(pPager, 0); } /* pager_reset(pPager); */ pPager->dbSize = -1; /* If an error occurs during a ROLLBACK, we can no longer trust the pager ** cache. So call pager_error() on the way out to make any error ** persistent. */ | > > > | > > | 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 | pPager->dbSize = pPager->origDbSize; pager_truncate_cache(pPager); pPager->stmtInUse = 0; pPager->state = PAGER_SHARED; return SQLITE_OK; } pagerEnter(pPager); if( !pPager->dirtyCache || !pPager->journalOpen ){ rc = pager_end_transaction(pPager); pagerLeave(pPager); return rc; } if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){ if( pPager->state>=PAGER_EXCLUSIVE ){ pager_playback(pPager, 0); } pagerLeave(pPager); return pPager->errCode; } if( pPager->state==PAGER_RESERVED ){ int rc2; rc = pager_playback(pPager, 0); rc2 = pager_end_transaction(pPager); if( rc==SQLITE_OK ){ rc = rc2; } }else{ rc = pager_playback(pPager, 0); } /* pager_reset(pPager); */ pPager->dbSize = -1; /* If an error occurs during a ROLLBACK, we can no longer trust the pager ** cache. So call pager_error() on the way out to make any error ** persistent. */ rc = pager_error(pPager, rc); pagerLeave(pPager); return rc; } /* ** Return TRUE if the database file is opened read-only. Return FALSE ** if the database is (in theory) writable. */ int sqlite3PagerIsreadonly(Pager *pPager){ |
︙ | ︙ | |||
4231 4232 4233 4234 4235 4236 4237 | /* ** Set the statement rollback point. ** ** This routine should be called with the transaction journal already ** open. A new statement journal is created that can be used to rollback ** changes of a single SQL command within a larger transaction. */ | | | 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 | /* ** Set the statement rollback point. ** ** This routine should be called with the transaction journal already ** open. A new statement journal is created that can be used to rollback ** changes of a single SQL command within a larger transaction. */ static int pagerStmtBegin(Pager *pPager){ int rc; assert( !pPager->stmtInUse ); assert( pPager->state>=PAGER_SHARED ); assert( pPager->dbSize>=0 ); PAGERTRACE2("STMT-BEGIN %d\n", PAGERID(pPager)); if( MEMDB ){ pPager->stmtInUse = 1; |
︙ | ︙ | |||
4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 | stmt_begin_failed: if( pPager->aInStmt ){ sqlite3_free(pPager->aInStmt); pPager->aInStmt = 0; } return rc; } /* ** Commit a statement. */ int sqlite3PagerStmtCommit(Pager *pPager){ if( pPager->stmtInUse ){ PgHdr *pPg, *pNext; PAGERTRACE2("STMT-COMMIT %d\n", PAGERID(pPager)); if( !MEMDB ){ /* sqlite3OsTruncate(pPager->stfd, 0); */ sqlite3_free( pPager->aInStmt ); pPager->aInStmt = 0; | > > > > > > > > | 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 | stmt_begin_failed: if( pPager->aInStmt ){ sqlite3_free(pPager->aInStmt); pPager->aInStmt = 0; } return rc; } int sqlite3PagerStmtBegin(Pager *pPager){ int rc; pagerEnter(pPager); rc = pagerStmtBegin(pPager); pagerLeave(pPager); return rc; } /* ** Commit a statement. */ int sqlite3PagerStmtCommit(Pager *pPager){ pagerEnter(pPager); if( pPager->stmtInUse ){ PgHdr *pPg, *pNext; PAGERTRACE2("STMT-COMMIT %d\n", PAGERID(pPager)); if( !MEMDB ){ /* sqlite3OsTruncate(pPager->stfd, 0); */ sqlite3_free( pPager->aInStmt ); pPager->aInStmt = 0; |
︙ | ︙ | |||
4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 | } } pPager->stmtNRec = 0; pPager->stmtInUse = 0; pPager->pStmt = 0; } pPager->stmtAutoopen = 0; return SQLITE_OK; } /* ** Rollback a statement. */ int sqlite3PagerStmtRollback(Pager *pPager){ int rc; if( pPager->stmtInUse ){ PAGERTRACE2("STMT-ROLLBACK %d\n", PAGERID(pPager)); if( MEMDB ){ PgHdr *pPg; PgHistory *pHist; for(pPg=pPager->pStmt; pPg; pPg=pHist->pNextStmt){ pHist = PGHDR_TO_HIST(pPg, pPager); | > > | 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 | } } pPager->stmtNRec = 0; pPager->stmtInUse = 0; pPager->pStmt = 0; } pPager->stmtAutoopen = 0; pagerLeave(pPager); return SQLITE_OK; } /* ** Rollback a statement. */ int sqlite3PagerStmtRollback(Pager *pPager){ int rc; pagerEnter(pPager); if( pPager->stmtInUse ){ PAGERTRACE2("STMT-ROLLBACK %d\n", PAGERID(pPager)); if( MEMDB ){ PgHdr *pPg; PgHistory *pHist; for(pPg=pPager->pStmt; pPg; pPg=pHist->pNextStmt){ pHist = PGHDR_TO_HIST(pPg, pPager); |
︙ | ︙ | |||
4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 | rc = pager_stmt_playback(pPager); } sqlite3PagerStmtCommit(pPager); }else{ rc = SQLITE_OK; } pPager->stmtAutoopen = 0; return rc; } /* ** Return the full pathname of the database file. */ const char *sqlite3PagerFilename(Pager *pPager){ | > | 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 | rc = pager_stmt_playback(pPager); } sqlite3PagerStmtCommit(pPager); }else{ rc = SQLITE_OK; } pPager->stmtAutoopen = 0; pagerLeave(pPager); return rc; } /* ** Return the full pathname of the database file. */ const char *sqlite3PagerFilename(Pager *pPager){ |
︙ | ︙ | |||
4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 | ** transaction is active). */ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno){ PgHdr *pPgOld; /* The page being overwritten. */ int h; Pgno needSyncPgno = 0; assert( pPg->nRef>0 ); PAGERTRACE5("MOVE %d page %d (needSync=%d) moves to %d\n", PAGERID(pPager), pPg->pgno, pPg->needSync, pgno); IOTRACE(("MOVE %p %d %d\n", pPager, pPg->pgno, pgno)) pager_get_content(pPg); | > | 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 | ** transaction is active). */ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno){ PgHdr *pPgOld; /* The page being overwritten. */ int h; Pgno needSyncPgno = 0; pagerEnter(pPager); assert( pPg->nRef>0 ); PAGERTRACE5("MOVE %d page %d (needSync=%d) moves to %d\n", PAGERID(pPager), pPg->pgno, pPg->needSync, pgno); IOTRACE(("MOVE %p %d %d\n", pPager, pPg->pgno, pgno)) pager_get_content(pPg); |
︙ | ︙ | |||
4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 | pPager->needSync = 1; pPgHdr->needSync = 1; pPgHdr->inJournal = 1; makeDirty(pPgHdr); sqlite3PagerUnref(pPgHdr); } return SQLITE_OK; } #endif /* ** Return a pointer to the data for the specified page. */ | > | 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 | pPager->needSync = 1; pPgHdr->needSync = 1; pPgHdr->inJournal = 1; makeDirty(pPgHdr); sqlite3PagerUnref(pPgHdr); } pagerLeave(pPager); return SQLITE_OK; } #endif /* ** Return a pointer to the data for the specified page. */ |
︙ | ︙ |
Changes to src/prepare.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the implementation of the sqlite3_prepare() ** interface, and routines that contribute to loading the database schema ** from disk. ** | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the implementation of the sqlite3_prepare() ** interface, and routines that contribute to loading the database schema ** from disk. ** ** $Id: prepare.c,v 1.57 2007/08/22 00:39:20 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** Fill the InitData structure with an error message that indicates ** that the database is corrupt. |
︙ | ︙ | |||
458 459 460 461 462 463 464 | const char **pzTail /* OUT: End of parsed string */ ){ Parse sParse; char *zErrMsg = 0; int rc = SQLITE_OK; int i; | < < < > | 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 | const char **pzTail /* OUT: End of parsed string */ ){ Parse sParse; char *zErrMsg = 0; int rc = SQLITE_OK; int i; assert( ppStmt ); *ppStmt = 0; if( sqlite3SafetyOn(db) ){ return SQLITE_MISUSE; } assert( !db->mallocFailed ); assert( sqlite3_mutex_held(db->mutex) ); /* If any attached database schemas are locked, do not proceed with ** compilation. Instead return SQLITE_LOCKED immediately. */ for(i=0; i<db->nDb; i++) { Btree *pBt = db->aDb[i].pBt; |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
26 27 28 29 30 31 32 | ** on how SQLite interfaces are suppose to operate. ** ** The name of this file under configuration management is "sqlite.h.in". ** The makefile makes some minor changes to this file (such as inserting ** the version number) and changes its name to "sqlite3.h" as ** part of the build process. ** | | | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | ** on how SQLite interfaces are suppose to operate. ** ** The name of this file under configuration management is "sqlite.h.in". ** The makefile makes some minor changes to this file (such as inserting ** the version number) and changes its name to "sqlite3.h" as ** part of the build process. ** ** @(#) $Id: sqlite.h.in,v 1.236 2007/08/22 00:39:20 drh Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ #include <stdarg.h> /* Needed for the definition of va_list */ /* ** Make sure we can call this stuff from C++. |
︙ | ︙ | |||
3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 | ** to sqlite3_mutex_alloc() is one of these integer constants: ** ** <ul> ** <li> SQLITE_MUTEX_FAST ** <li> SQLITE_MUTEX_RECURSIVE ** <li> SQLITE_MUTEX_STATIC_MASTER ** <li> SQLITE_MUTEX_STATIC_MEM ** <li> SQLITE_MUTEX_STATIC_PRNG ** </ul> ** ** The first two constants cause sqlite3_mutex_alloc() to create ** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE ** is used but not necessarily so when SQLITE_MUTEX_FAST is used. ** The mutex implementation does not need to make a distinction | > | 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 | ** to sqlite3_mutex_alloc() is one of these integer constants: ** ** <ul> ** <li> SQLITE_MUTEX_FAST ** <li> SQLITE_MUTEX_RECURSIVE ** <li> SQLITE_MUTEX_STATIC_MASTER ** <li> SQLITE_MUTEX_STATIC_MEM ** <li> SQLITE_MUTEX_STATIC_MEM2 ** <li> SQLITE_MUTEX_STATIC_PRNG ** </ul> ** ** The first two constants cause sqlite3_mutex_alloc() to create ** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE ** is used but not necessarily so when SQLITE_MUTEX_FAST is used. ** The mutex implementation does not need to make a distinction |
︙ | ︙ | |||
3341 3342 3343 3344 3345 3346 3347 | ** ** The [sqlite3_mutex_alloc()] interface takes a single argument ** which is one of these integer constants. */ #define SQLITE_MUTEX_FAST 0 #define SQLITE_MUTEX_RECURSIVE 1 #define SQLITE_MUTEX_STATIC_MASTER 2 | | > | | 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 | ** ** The [sqlite3_mutex_alloc()] interface takes a single argument ** which is one of these integer constants. */ #define SQLITE_MUTEX_FAST 0 #define SQLITE_MUTEX_RECURSIVE 1 #define SQLITE_MUTEX_STATIC_MASTER 2 #define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */ #define SQLITE_MUTEX_STATIC_MEM2 4 /* sqlite3_release_memory() */ #define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */ /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. */ #ifdef SQLITE_OMIT_FLOATING_POINT |
︙ | ︙ |
Changes to src/tclsqlite.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. ** ************************************************************************* ** A TCL Interface to SQLite. Append this file to sqlite3.c and ** compile the whole thing to build a TCL-enabled version of 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. ** ************************************************************************* ** A TCL Interface to SQLite. Append this file to sqlite3.c and ** compile the whole thing to build a TCL-enabled version of SQLite. ** ** $Id: tclsqlite.c,v 1.197 2007/08/22 00:39:21 drh Exp $ */ #include "tcl.h" #include <errno.h> /* ** Some additional include files are needed if this file is not ** appended to the amalgamation. |
︙ | ︙ | |||
2366 2367 2368 2369 2370 2371 2372 | /* If compiled with SQLITE_TEST turned on, then register the "md5sum" ** SQL function. */ #ifdef SQLITE_TEST { extern void Md5_Register(sqlite3*); | | | | 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 | /* If compiled with SQLITE_TEST turned on, then register the "md5sum" ** SQL function. */ #ifdef SQLITE_TEST { extern void Md5_Register(sqlite3*); #if 0 int mallocfail = sqlite3_iMallocFail; sqlite3_iMallocFail = 0; #endif Md5_Register(p->db); #if 0 sqlite3_iMallocFail = mallocfail; #endif } #endif return TCL_OK; } |
︙ | ︙ |
Changes to src/test1.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** Code for testing all sorts of SQLite interfaces. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** Code for testing all sorts of SQLite interfaces. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** ** $Id: test1.c,v 1.268 2007/08/22 00:39:21 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" #include <stdlib.h> #include <string.h> /* |
︙ | ︙ | |||
912 913 914 915 916 917 918 | } #ifndef SQLITE_OMIT_UTF16 /* Use the sqlite3_create_function16() API here. Mainly for fun, but also ** because it is not tested anywhere else. */ if( rc==SQLITE_OK ){ sqlite3_value *pVal; | < < < < < | 912 913 914 915 916 917 918 919 920 921 922 923 924 925 | } #ifndef SQLITE_OMIT_UTF16 /* Use the sqlite3_create_function16() API here. Mainly for fun, but also ** because it is not tested anywhere else. */ if( rc==SQLITE_OK ){ sqlite3_value *pVal; pVal = sqlite3ValueNew(db); sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC); rc = sqlite3_create_function16(db, sqlite3ValueText(pVal, SQLITE_UTF16NATIVE), 1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0); sqlite3ValueFree(pVal); } |
︙ | ︙ | |||
2091 2092 2093 2094 2095 2096 2097 | (void *)SQLITE_UTF8, val?test_collate_func:0); if( rc==SQLITE_OK ){ if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR; rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE, (void *)SQLITE_UTF16LE, val?test_collate_func:0); if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR; | | | 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 | (void *)SQLITE_UTF8, val?test_collate_func:0); if( rc==SQLITE_OK ){ if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR; rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE, (void *)SQLITE_UTF16LE, val?test_collate_func:0); if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR; #if 0 if( sqlite3_iMallocFail>0 ){ sqlite3_iMallocFail++; } #endif pVal = sqlite3ValueNew(0); sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC); rc = sqlite3_create_collation16(db, |
︙ | ︙ | |||
4014 4015 4016 4017 4018 4019 4020 | */ static int test_soft_heap_limit( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ | | | > < | 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 | */ static int test_soft_heap_limit( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ static int softHeapLimit = 0; int amt; if( objc!=1 && objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "?N?"); return TCL_ERROR; } amt = softHeapLimit; if( objc==2 ){ int N; if( Tcl_GetIntFromObj(interp, objv[1], &N) ) return TCL_ERROR; sqlite3_soft_heap_limit(N); softHeapLimit = N; } Tcl_SetObjResult(interp, Tcl_NewIntObj(amt)); return TCL_OK; } /* ** Usage: sqlite3_clear_tsd_memdebug ** ** Clear all of the MEMDEBUG information out of thread-specific data. |
︙ | ︙ | |||
4057 4058 4059 4060 4061 4062 4063 | */ static int test_tsd_release( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ | < < < | 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 | */ static int test_tsd_release( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ return TCL_OK; } /* ** Usage: sqlite3_thread_cleanup ** ** Call the sqlite3_thread_cleanup API. |
︙ | ︙ | |||
4317 4318 4319 4320 4321 4322 4323 | #endif }; static int bitmask_size = sizeof(Bitmask)*8; int i; extern int sqlite3_where_trace; extern int sqlite3_sync_count, sqlite3_fullsync_count; extern int sqlite3_opentemp_count; | < < | 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 | #endif }; static int bitmask_size = sizeof(Bitmask)*8; int i; extern int sqlite3_where_trace; extern int sqlite3_sync_count, sqlite3_fullsync_count; extern int sqlite3_opentemp_count; extern int sqlite3_like_count; extern int sqlite3_xferopt_count; extern int sqlite3_pager_readdb_count; extern int sqlite3_pager_writedb_count; extern int sqlite3_pager_writej_count; extern int sqlite3_pager_pgfree_count; #if OS_UNIX && defined(SQLITE_TEST) && SQLITE_THREADSAFE |
︙ | ︙ | |||
4399 4400 4401 4402 4403 4404 4405 | Tcl_LinkVar(interp, "sqlite_addop_trace", (char*)&sqlite3_vdbe_addop_trace, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_where_trace", (char*)&sqlite3_where_trace, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_os_trace", (char*)&sqlite3_os_trace, TCL_LINK_INT); #endif | < < < < < < | 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 | Tcl_LinkVar(interp, "sqlite_addop_trace", (char*)&sqlite3_vdbe_addop_trace, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_where_trace", (char*)&sqlite3_where_trace, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_os_trace", (char*)&sqlite3_os_trace, TCL_LINK_INT); #endif #ifndef SQLITE_OMIT_DISKIO Tcl_LinkVar(interp, "sqlite_opentemp_count", (char*)&sqlite3_opentemp_count, TCL_LINK_INT); #endif Tcl_LinkVar(interp, "sqlite_static_bind_value", (char*)&sqlite_static_bind_value, TCL_LINK_STRING); Tcl_LinkVar(interp, "sqlite_static_bind_nbyte", |
︙ | ︙ |
Changes to src/vdbeapi.c.
︙ | ︙ | |||
40 41 42 43 44 45 46 | */ int sqlite3_finalize(sqlite3_stmt *pStmt){ int rc; if( pStmt==0 ){ rc = SQLITE_OK; }else{ Vdbe *v = (Vdbe*)pStmt; | > | | | 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | */ int sqlite3_finalize(sqlite3_stmt *pStmt){ int rc; if( pStmt==0 ){ rc = SQLITE_OK; }else{ Vdbe *v = (Vdbe*)pStmt; sqlite3_mutex *mutex = v->db->mutex; sqlite3_mutex_enter(mutex); rc = sqlite3VdbeFinalize(v); sqlite3_mutex_leave(mutex); } return rc; } /* ** Terminate the current execution of an SQL statement and reset it ** back to its starting state so that it can be reused. A success code from |
︙ | ︙ |
Changes to test/capi2.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2003 January 29 # # 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. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script testing the callback-free C/C++ API. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2003 January 29 # # 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. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script testing the callback-free C/C++ API. # # $Id: capi2.test,v 1.34 2007/08/22 00:39:21 drh Exp $ # set testdir [file dirname $argv0] source $testdir/tester.tcl # Return the text values from the current row pointed at by STMT as a list. proc get_row_values {STMT} { |
︙ | ︙ | |||
204 205 206 207 208 209 210 | # finalized. Is this going to cause trouble for anyone? Lee Nelson maybe? # (Later:) The change now happens just before SQLITE_DONE is returned. do_test capi2-3.10b {db changes} {1} do_test capi2-3.11 { sqlite3_finalize $VM } {SQLITE_OK} do_test capi2-3.11b {db changes} {1} | | | | | 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 | # finalized. Is this going to cause trouble for anyone? Lee Nelson maybe? # (Later:) The change now happens just before SQLITE_DONE is returned. do_test capi2-3.10b {db changes} {1} do_test capi2-3.11 { sqlite3_finalize $VM } {SQLITE_OK} do_test capi2-3.11b {db changes} {1} #do_test capi2-3.12-misuse { # sqlite3_finalize $VM #} {SQLITE_MISUSE} do_test capi2-3.13 { set VM [sqlite3_prepare $DB {INSERT INTO t1 VALUES(1,3,4)} -1 TAIL] list [sqlite3_step $VM] \ [sqlite3_column_count $VM] \ [get_row_values $VM] \ [get_column_names $VM] } {SQLITE_ERROR 0 {} {}} |
︙ | ︙ |