Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Documentation updates. Fix to date.c. But most importantly: database connections are now allowed to change threads as long as they are not holding a lock. (CVS 2944) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
03c422ecb508dd84dfafc8b7a0b790a4 |
User & Date: | drh 2006-01-15 00:13:16.000 |
Context
2006-01-15
| ||
02:30 | Add tests and fix bugs in the new cross-thread lock resolution code. When an unlock fails, do not leak file descriptors (ticket #1611). But we really ought to report SQLITE_MISUSE or some other error instead of just returning SQLITE_OK. (CVS 2945) (check-in: f68e05cb2b user: drh tags: trunk) | |
00:13 | Documentation updates. Fix to date.c. But most importantly: database connections are now allowed to change threads as long as they are not holding a lock. (CVS 2944) (check-in: 03c422ecb5 user: drh tags: trunk) | |
2006-01-14
| ||
08:02 | Fixes for OMIT_SUBQUERY builds: Disable where clause OR->IN optimization. Include EXISTS keyword (for new CREATE TABLE syntax). Test file fixes. (CVS 2943) (check-in: 8e79a0c24a user: danielk1977 tags: trunk) | |
Changes
Changes to src/date.c.
︙ | ︙ | |||
12 13 14 15 16 17 18 | ** This file contains the C functions that implement date and time ** functions for SQLite. ** ** There is only one exported symbol in this file - the function ** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. ** All other code has file scope. ** | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | ** This file contains the C functions that implement date and time ** functions for SQLite. ** ** There is only one exported symbol in this file - the function ** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. ** All other code has file scope. ** ** $Id: date.c,v 1.51 2006/01/15 00:13:16 drh Exp $ ** ** NOTES: ** ** SQLite processes all times and dates as Julian Day numbers. The ** dates and times are stored as the number of days since noon ** in Greenwich on November 24, 4714 B.C. according to the Gregorian ** calendar system. |
︙ | ︙ | |||
101 102 103 104 105 106 107 | min = va_arg(ap, int); max = va_arg(ap, int); nextC = va_arg(ap, int); pVal = va_arg(ap, int*); val = 0; while( N-- ){ if( !isdigit(*(u8*)zDate) ){ | | | > | 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | min = va_arg(ap, int); max = va_arg(ap, int); nextC = va_arg(ap, int); pVal = va_arg(ap, int*); val = 0; while( N-- ){ if( !isdigit(*(u8*)zDate) ){ goto end_getDigits; } val = val*10 + *zDate - '0'; zDate++; } if( val<min || val>max || (nextC!=0 && nextC!=*zDate) ){ goto end_getDigits; } *pVal = val; zDate++; cnt++; }while( nextC ); va_end(ap); end_getDigits: return cnt; } /* ** Read text from z[] and convert into a floating point number. Return ** the number of digits converted. */ |
︙ | ︙ |
Changes to src/os_unix.c.
︙ | ︙ | |||
161 162 163 164 165 166 167 | ** is first opened. All subsequent uses of the OsFile verify that the ** same thread is operating on the OsFile. Some operating systems do ** not allow locks to be overridden by other threads and that restriction ** means that sqlite3* database handles cannot be moved from one thread ** to another. This logic makes sure a user does not try to do that ** by mistake. */ | | > | | 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | ** is first opened. All subsequent uses of the OsFile verify that the ** same thread is operating on the OsFile. Some operating systems do ** not allow locks to be overridden by other threads and that restriction ** means that sqlite3* database handles cannot be moved from one thread ** to another. This logic makes sure a user does not try to do that ** by mistake. */ #if defined(SQLITE_UNIX_THREADS) # define SET_THREADID(X) (X)->tid = pthread_self() # define CHECK_THREADID(X) (threadsOverrideEachOthersLocks==0 && \ !pthread_equal((X)->tid, pthread_self())) #else # define SET_THREADID(X) # define CHECK_THREADID(X) 0 #endif /* ** Here is the dirt on POSIX advisory locks: ANSI STD 1003.1 (1996) |
︙ | ︙ | |||
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 | ** This variable records whether or not threads can override each others ** locks. ** ** 0: No. Threads cannot override each others locks. ** 1: Yes. Threads can override each others locks. ** -1: We don't know yet. */ static int threadsOverrideEachOthersLocks = -1; /* ** This structure holds information passed into individual test ** threads by the testThreadLockingBehavior() routine. */ struct threadTestData { int fd; /* File to be locked */ | > > > > | 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 | ** This variable records whether or not threads can override each others ** locks. ** ** 0: No. Threads cannot override each others locks. ** 1: Yes. Threads can override each others locks. ** -1: We don't know yet. */ #ifdef SQLITE_TEST int threadsOverrideEachOthersLocks = -1; #else static int threadsOverrideEachOthersLocks = -1; #endif /* ** This structure holds information passed into individual test ** threads by the testThreadLockingBehavior() routine. */ struct threadTestData { int fd; /* File to be locked */ |
︙ | ︙ | |||
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 | } #endif /* SQLITE_UNIX_THREADS */ /* ** Release a lockInfo structure previously allocated by findLockInfo(). */ static void releaseLockInfo(struct lockInfo *pLock){ pLock->nRef--; if( pLock->nRef==0 ){ sqlite3HashInsert(&lockHash, &pLock->key, sizeof(pLock->key), 0); sqliteFree(pLock); } } /* ** Release a openCnt structure previously allocated by findLockInfo(). */ static void releaseOpenCnt(struct openCnt *pOpen){ pOpen->nRef--; if( pOpen->nRef==0 ){ sqlite3HashInsert(&openHash, &pOpen->key, sizeof(pOpen->key), 0); sqliteFree(pOpen->aPending); sqliteFree(pOpen); } } /* ** Given a file descriptor, locate lockInfo and openCnt structures that | > > | | > | 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 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 | } #endif /* SQLITE_UNIX_THREADS */ /* ** Release a lockInfo structure previously allocated by findLockInfo(). */ static void releaseLockInfo(struct lockInfo *pLock){ assert( sqlite3OsInMutex() ); pLock->nRef--; if( pLock->nRef==0 ){ sqlite3HashInsert(&lockHash, &pLock->key, sizeof(pLock->key), 0); sqliteFree(pLock); } } /* ** Release a openCnt structure previously allocated by findLockInfo(). */ static void releaseOpenCnt(struct openCnt *pOpen){ assert( sqlite3OsInMutex() ); pOpen->nRef--; if( pOpen->nRef==0 ){ sqlite3HashInsert(&openHash, &pOpen->key, sizeof(pOpen->key), 0); sqliteFree(pOpen->aPending); sqliteFree(pOpen); } } /* ** Given a file descriptor, locate lockInfo and openCnt structures that ** describes that file descriptor. Create new ones if necessary. The ** return values might be uninitialized if an error occurs. ** ** Return the number of errors. */ static int findLockInfo( int fd, /* The file descriptor used in the key */ struct lockInfo **ppLock, /* Return the lockInfo structure here */ struct openCnt **ppOpen /* Return the openCnt structure here */ ){ int rc; struct lockKey key1; struct openKey key2; struct stat statbuf; struct lockInfo *pLock; struct openCnt *pOpen; rc = fstat(fd, &statbuf); if( rc!=0 ) return 1; assert( sqlite3OsInMutex() ); memset(&key1, 0, sizeof(key1)); key1.dev = statbuf.st_dev; key1.ino = statbuf.st_ino; #ifdef SQLITE_UNIX_THREADS if( threadsOverrideEachOthersLocks<0 ){ testThreadLockingBehavior(fd); } |
︙ | ︙ | |||
536 537 538 539 540 541 542 | rc = 1; goto exit_findlockinfo; } }else{ pLock->nRef++; } *ppLock = pLock; | > | | | | | | | | | | | | | | | | | | | | | | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 | rc = 1; goto exit_findlockinfo; } }else{ pLock->nRef++; } *ppLock = pLock; if( ppOpen!=0 ){ pOpen = (struct openCnt*)sqlite3HashFind(&openHash, &key2, sizeof(key2)); if( pOpen==0 ){ struct openCnt *pOld; pOpen = sqliteMallocRaw( sizeof(*pOpen) ); if( pOpen==0 ){ releaseLockInfo(pLock); rc = 1; goto exit_findlockinfo; } pOpen->key = key2; pOpen->nRef = 1; pOpen->nLock = 0; pOpen->nPending = 0; pOpen->aPending = 0; pOld = sqlite3HashInsert(&openHash, &pOpen->key, sizeof(key2), pOpen); if( pOld!=0 ){ assert( pOld==pOpen ); sqliteFree(pOpen); releaseLockInfo(pLock); rc = 1; goto exit_findlockinfo; } }else{ pOpen->nRef++; } *ppOpen = pOpen; } exit_findlockinfo: return rc; } /* ** If we are currently in a different thread than the thread that the ** unixFile argument belongs to, then transfer ownership of the unixFile ** over to the current thread. ** ** A unixFile is only owned by a thread on systems where one thread is ** unable to override locks created by a different thread. RedHat9 is ** an example of such a system. ** ** Ownership transfer is only allowed if the unixFile is currently unlocked. ** If the unixFile is locked and an ownership is wrong, then return ** SQLITE_MISUSE. Otherwise return SQLITE_OK. */ #ifdef SQLITE_UNIX_THREADS static int transferOwnership(unixFile *pFile){ pthread_t hSelf; if( threadsOverrideEachOthersLocks ){ /* Ownership transfers not needed on this system */ return SQLITE_OK; } hSelf = pthread_self(); if( pthread_equal(pFile->tid, hSelf) ){ /* We are still in the same thread */ return SQLITE_OK; } if( pFile->locktype!=NO_LOCK ){ /* We cannot change ownership while we are holding a lock! */ return SQLITE_MISUSE; } pFile->tid = hSelf; releaseLockInfo(pFile->pLock); return findLockInfo(pFile->h, &pFile->pLock, 0); } #else # define transferOwnership(X) SQLITE_OK #endif /* ** Delete the named file */ int sqlite3UnixDelete(const char *zFilename){ unlink(zFilename); return SQLITE_OK; } |
︙ | ︙ | |||
1043 1044 1045 1046 1047 1048 1049 | ** return zero. */ static int unixCheckReservedLock(OsFile *id){ int r = 0; unixFile *pFile = (unixFile*)id; assert( pFile ); | < | 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 | ** return zero. */ static int unixCheckReservedLock(OsFile *id){ int r = 0; unixFile *pFile = (unixFile*)id; assert( pFile ); sqlite3OsEnterMutex(); /* Because pFile->pLock is shared across threads */ /* Check if a thread in this process holds such a lock */ if( pFile->pLock->locktype>SHARED_LOCK ){ r = 1; } |
︙ | ︙ | |||
1162 1163 1164 1165 1166 1167 1168 | struct flock lock; int s; assert( pFile ); TRACE7("LOCK %d %s was %s(%s,%d) pid=%d\n", pFile->h, locktypeName(locktype), locktypeName(pFile->locktype), locktypeName(pLock->locktype), pLock->cnt , getpid()); | < > > > > > > > > | 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 | struct flock lock; int s; assert( pFile ); TRACE7("LOCK %d %s was %s(%s,%d) pid=%d\n", pFile->h, locktypeName(locktype), locktypeName(pFile->locktype), locktypeName(pLock->locktype), pLock->cnt , getpid()); /* If there is already a lock of this type or more restrictive on the ** OsFile, do nothing. Don't use the end_lock: exit path, as ** sqlite3OsEnterMutex() hasn't been called yet. */ if( pFile->locktype>=locktype ){ TRACE3("LOCK %d %s ok (already held)\n", pFile->h, locktypeName(locktype)); return SQLITE_OK; } /* Make sure the locking sequence is correct */ assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); assert( locktype!=PENDING_LOCK ); assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); /* This mutex is needed because pFile->pLock is shared across threads */ sqlite3OsEnterMutex(); /* Make sure the current thread owns the pFile. */ rc = transferOwnership(pFile); if( rc!=SQLITE_OK ){ sqlite3OsLeaveMutex(); return rc; } /* If some thread using this PID has a lock via a different OsFile* ** handle that precludes the requested lock, return BUSY. */ if( (pFile->locktype!=pLock->locktype && (pLock->locktype>=PENDING_LOCK || locktype>SHARED_LOCK)) ){ |
︙ | ︙ | |||
1320 1321 1322 1323 1324 1325 1326 | struct flock lock; int rc = SQLITE_OK; unixFile *pFile = (unixFile*)id; assert( pFile ); TRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", pFile->h, locktype, pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid()); | < > | 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 | struct flock lock; int rc = SQLITE_OK; unixFile *pFile = (unixFile*)id; assert( pFile ); TRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", pFile->h, locktype, pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid()); assert( locktype<=SHARED_LOCK ); if( pFile->locktype<=locktype ){ return SQLITE_OK; } if( CHECK_THREADID(pFile) ) return SQLITE_MISUSE; sqlite3OsEnterMutex(); pLock = pFile->pLock; assert( pLock->cnt!=0 ); if( pFile->locktype>SHARED_LOCK ){ assert( pLock->locktype==pFile->locktype ); if( locktype==SHARED_LOCK ){ lock.l_type = F_RDLCK; |
︙ | ︙ | |||
1397 1398 1399 1400 1401 1402 1403 1404 | } /* ** Close a file. */ static int unixClose(OsFile **pId){ unixFile *id = (unixFile*)*pId; if( !id ) return SQLITE_OK; | > > < | > | 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 | } /* ** Close a file. */ static int unixClose(OsFile **pId){ unixFile *id = (unixFile*)*pId; int rc; if( !id ) return SQLITE_OK; rc = unixUnlock(*pId, NO_LOCK); if( rc ) return rc; if( id->dirfd>=0 ) close(id->dirfd); id->dirfd = -1; sqlite3OsEnterMutex(); if( id->pOpen->nLock ){ /* If there are outstanding locks, do not actually close the file just ** yet because that would clear those locks. Instead, add the file |
︙ | ︙ | |||
1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 | ** OsFile. If we run out of memory, close the file and return NULL. */ static int allocateUnixFile(unixFile *pInit, OsFile **pId){ unixFile *pNew; pNew = sqliteMalloc( sizeof(unixFile) ); if( pNew==0 ){ close(pInit->h); releaseLockInfo(pInit->pLock); releaseOpenCnt(pInit->pOpen); *pId = 0; return SQLITE_NOMEM; }else{ *pNew = *pInit; pNew->pMethod = &sqlite3UnixIoMethod; *pId = (OsFile*)pNew; OpenCounter(+1); | > > | 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 | ** OsFile. If we run out of memory, close the file and return NULL. */ static int allocateUnixFile(unixFile *pInit, OsFile **pId){ unixFile *pNew; pNew = sqliteMalloc( sizeof(unixFile) ); if( pNew==0 ){ close(pInit->h); sqlite3OsEnterMutex(); releaseLockInfo(pInit->pLock); releaseOpenCnt(pInit->pOpen); sqlite3OsLeaveMutex(); *pId = 0; return SQLITE_NOMEM; }else{ *pNew = *pInit; pNew->pMethod = &sqlite3UnixIoMethod; *pId = (OsFile*)pNew; OpenCounter(+1); |
︙ | ︙ |
Changes to src/server.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 | ** or linked into the SQLite library unless you use a non-standard option: ** ** -DSQLITE_SERVER=1 ** ** The configure script will never generate a Makefile with the option ** above. You will need to manually modify the Makefile if you want to ** include any of the code from this file in your project. Or, at your | | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | ** or linked into the SQLite library unless you use a non-standard option: ** ** -DSQLITE_SERVER=1 ** ** The configure script will never generate a Makefile with the option ** above. You will need to manually modify the Makefile if you want to ** include any of the code from this file in your project. Or, at your ** option, you may copy and paste the code from this file and ** thereby avoiding a recompile of SQLite. ** ** ** This source file demonstrates how to use SQLite to create an SQL database ** server thread in a multiple-threaded program. One or more client threads ** send messages to the server thread and the server thread processes those ** messages in the order received and returns the results to the client. |
︙ | ︙ | |||
36 37 38 39 40 41 42 | ** a thread different from the one where they were created. With ** the client/server approach, all database connections are created ** and used within the server thread. Client calls to the database ** can be made from multiple threads (though not at the same time!) ** ** (2) Beginning with SQLite version 3.3.0, when two or more ** connections to the same database occur within the same thread, | | | > | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | ** a thread different from the one where they were created. With ** the client/server approach, all database connections are created ** and used within the server thread. Client calls to the database ** can be made from multiple threads (though not at the same time!) ** ** (2) Beginning with SQLite version 3.3.0, when two or more ** connections to the same database occur within the same thread, ** they can optionally share their database cache. This reduces ** I/O and memory requirements. Cache shared is controlled using ** the sqlite3_enable_shared_cache() API. ** ** (3) Database connections on a shared cache use table-level locking ** instead of file-level locking for improved concurrency. ** ** (4) Database connections on a shared cache can by optionally ** set to READ UNCOMMITTED isolation. (The default isolation for ** SQLite is SERIALIZABLE.) When this occurs, readers will |
︙ | ︙ | |||
92 93 94 95 96 97 98 | ** sqlite3_client_reset ** sqlite3_client_finalize ** sqlite3_client_close ** ** These interfaces work exactly like the standard core SQLite interfaces ** having the same names without the "_client_" infix. Many other SQLite ** interfaces can be used directly without having to send messages to the | > | < < < | | > > > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 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 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | ** sqlite3_client_reset ** sqlite3_client_finalize ** sqlite3_client_close ** ** These interfaces work exactly like the standard core SQLite interfaces ** having the same names without the "_client_" infix. Many other SQLite ** interfaces can be used directly without having to send messages to the ** server as long as SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined. ** The following interfaces fall into this second category: ** ** sqlite3_bind_* ** sqlite3_changes ** sqlite3_clear_bindings ** sqlite3_column_* ** sqlite3_complete ** sqlite3_create_collation ** sqlite3_create_function ** sqlite3_data_count ** sqlite3_db_handle ** sqlite3_errcode ** sqlite3_errmsg ** sqlite3_last_insert_rowid ** sqlite3_total_changes ** sqlite3_transfer_bindings ** ** A single SQLite connection (an sqlite3* object) or an SQLite statement ** (an sqlite3_stmt* object) should only be passed to a single interface ** function at a time. The connections and statements can be passed from ** any thread to any of the functions listed in the second group above as ** long as the same connection is not in use by two threads at once and ** as long as SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined. Additional ** information about the SQLITE_ENABLE_MEMORY_MANAGEMENT constraint is ** below. ** ** The busy handler for all database connections should remain turned ** off. That means that any lock contention will cause the associated ** sqlite3_client_step() call to return immediately with an SQLITE_BUSY ** error code. If a busy handler is enabled and lock contention occurs, ** then the entire server thread will block. This will cause not only ** the requesting client to block but every other database client as ** well. It is possible to enhance the code below so that lock ** contention will cause the message to be placed back on the top of ** the queue to be tried again later. But such enhanced processing is ** not included here, in order to keep the example simple. ** ** This example code assumes the use of pthreads. Pthreads ** implementations are available for windows. (See, for example ** http://sourceware.org/pthreads-win32/announcement.html.) Or, you ** can translate the locking and thread synchronization code to use ** windows primitives easily enough. The details are left as an ** exercise to the reader. ** **** Restrictions Associated With SQLITE_ENABLE_MEMORY_MANAGEMENT **** ** ** If you compile with SQLITE_ENABLE_MEMORY_MANAGEMENT defined, then ** SQLite includes code that tracks how much memory is being used by ** each thread. These memory counts can become confused if memory ** is allocated by one thread and then freed by another. For that ** reason, when SQLITE_ENABLE_MEMORY_MANAGEMENT is used, all operations ** that might allocate or free memory should be performanced in the same ** thread that originally created the database connection. In that case, ** many of the operations that are listed above as safe to be performed ** in separate threads would need to be sent over to the server to be ** done there. If SQLITE_ENABLE_MEMORY_MANAGEMENT is defined, then ** the following functions can be used safely from different threads ** without messing up the allocation counts: ** ** sqlite3_bind_parameter_name ** sqlite3_bind_parameter_index ** sqlite3_changes ** sqlite3_column_blob ** sqlite3_column_count ** sqlite3_complete ** sqlite3_data_count ** sqlite3_db_handle ** sqlite3_errcode ** sqlite3_errmsg ** sqlite3_last_insert_rowid ** sqlite3_total_changes ** ** The remaining functions are not thread-safe when memory management ** is enabled. So one would have to define some new interface routines ** along the following lines: ** ** sqlite3_client_bind_* ** sqlite3_client_clear_bindings ** sqlite3_client_column_* ** sqlite3_client_create_collation ** sqlite3_client_create_function ** sqlite3_client_transfer_bindings ** ** The example code in this file is intended for use with memory ** management turned off. So the implementation of these additional ** client interfaces is left as an exercise to the reader. ** ** It may seem surprising to the reader that the list of safe functions ** above does not include things like sqlite3_bind_int() or ** sqlite3_column_int(). But those routines might, in fact, allocate ** or deallocate memory. In the case of sqlite3_bind_int(), if the ** parameter was previously bound to a string that string might need ** to be deallocated before the new integer value is inserted. In ** the case of sqlite3_column_int(), the value of the column might be ** a UTF-16 string which will need to be converted to UTF-8 then into ** an integer. */ /* ** Only compile the code in this file on UNIX with a THREADSAFE build ** and only if the SQLITE_SERVER macro is defined. */ #ifdef SQLITE_SERVER |
︙ | ︙ |
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 the printf() interface to SQLite. 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 the printf() interface to SQLite. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** ** $Id: test1.c,v 1.190 2006/01/15 00:13:16 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" #include "os.h" #include <stdlib.h> #include <string.h> |
︙ | ︙ | |||
3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 | extern int sqlite3_sync_count, sqlite3_fullsync_count; extern int sqlite3_opentemp_count; extern int sqlite3_memUsed; extern int sqlite3_malloc_id; extern int sqlite3_memMax; extern int sqlite3_like_count; extern int sqlite3_tsd_count; #if OS_WIN extern int sqlite3_os_type; #endif #ifdef SQLITE_DEBUG extern int sqlite3_vdbe_addop_trace; #endif #ifdef SQLITE_TEST | > > > | 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 | extern int sqlite3_sync_count, sqlite3_fullsync_count; extern int sqlite3_opentemp_count; extern int sqlite3_memUsed; extern int sqlite3_malloc_id; extern int sqlite3_memMax; extern int sqlite3_like_count; extern int sqlite3_tsd_count; #if OS_UNIX && defined(SQLITE_TEST) && defined(THREADSAFE) && THREADSAFE extern int threadsOverrideEachOthersLocks; #endif #if OS_WIN extern int sqlite3_os_type; #endif #ifdef SQLITE_DEBUG extern int sqlite3_vdbe_addop_trace; #endif #ifdef SQLITE_TEST |
︙ | ︙ | |||
3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 | (char*)&sqlite3_open_file_count, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_current_time", (char*)&sqlite3_current_time, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_os_trace", (char*)&sqlite3_os_trace, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite3_tsd_count", (char*)&sqlite3_tsd_count, TCL_LINK_INT); #ifndef SQLITE_OMIT_UTF16 Tcl_LinkVar(interp, "sqlite_last_needed_collation", (char*)&pzNeededCollation, TCL_LINK_STRING|TCL_LINK_READ_ONLY); #endif #ifdef SQLITE_MEMDEBUG Tcl_LinkVar(interp, "sqlite_malloc_id", (char*)&sqlite3_malloc_id, TCL_LINK_STRING); | > > > > | 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 | (char*)&sqlite3_open_file_count, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_current_time", (char*)&sqlite3_current_time, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_os_trace", (char*)&sqlite3_os_trace, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite3_tsd_count", (char*)&sqlite3_tsd_count, TCL_LINK_INT); #if OS_UNIX && defined(SQLITE_TEST) && defined(THREADSAFE) && THREADSAFE Tcl_LinkVar(interp, "threadsOverrideEachOthersLocks", (char*)&threadsOverrideEachOthersLocks, TCL_LINK_INT); #endif #ifndef SQLITE_OMIT_UTF16 Tcl_LinkVar(interp, "sqlite_last_needed_collation", (char*)&pzNeededCollation, TCL_LINK_STRING|TCL_LINK_READ_ONLY); #endif #ifdef SQLITE_MEMDEBUG Tcl_LinkVar(interp, "sqlite_malloc_id", (char*)&sqlite3_malloc_id, TCL_LINK_STRING); |
︙ | ︙ |
Changes to test/server1.test.
︙ | ︙ | |||
9 10 11 12 13 14 15 | # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script is testing the server mode of SQLite. # # This file is derived from thread1.test # | | > > > > > > > > | 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 | # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script is testing the server mode of SQLite. # # This file is derived from thread1.test # # $Id: server1.test,v 1.4 2006/01/15 00:13:16 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Skip this whole file if the server testing code is not enabled # if {[llength [info command client_step]]==0 || [sqlite3 -has-codec]} { finish_test return } # The sample server implementation does not work right when memory # management is enabled. # ifcapable memorymanage { finish_test return } # Create some data to work with # do_test server1-1.1 { execsql { CREATE TABLE t1(a,b); INSERT INTO t1 VALUES(1,'abcdefgh'); |
︙ | ︙ |