Fix some errors to do with attached databases and text encodings in shared-cache mode. (CVS 2895)

FossilOrigin-Name: 3e75d3d5efebc0dfff1adfc13d85e85ec39db3eb
This commit is contained in:
danielk1977 2006-01-09 16:12:04 +00:00
parent 52622828ce
commit 14db26653a
19 changed files with 205 additions and 143 deletions

View File

@ -1,5 +1,5 @@
C Add\sa\sruntime\sinterface\sto\senable\smemory-management\sfeatures.\s(CVS\s2894)
D 2006-01-09T09:59:49
C Fix\ssome\serrors\sto\sdo\swith\sattached\sdatabases\sand\stext\sencodings\sin\sshared-cache\smode.\s(CVS\s2895)
D 2006-01-09T16:12:05
F Makefile.in c79fbdaa264c6afcd435f2fb492551de5a8cf80d
F Makefile.linux-gcc aee18d8a05546dcf1888bd4547e442008a49a092
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@ -32,23 +32,23 @@ F sqlite3.def c413e514217736884254739a105c8c942fdf0c2f
F sqlite3.pc.in 985b9bf34192a549d7d370e0f0b6b34a4f61369a
F src/alter.c d0dd079b9ef0d551ff4a4ce09ee270c07b307bbb
F src/analyze.c ed87abad3f6f60e1bd5308ed6ff6e0fa396db52b
F src/attach.c 833e38b4fa6966de05fcf875c94cd521478a2811
F src/attach.c fed27f5430db877012886c4b740a4a42f9176dbd
F src/auth.c cdec356a5cd8b217c346f816c5912221537fe87f
F src/btree.c 5e5dff4a667d93d49925d38de2d451a5bd1eabfd
F src/btree.h 5663c4f43e8521546ccebc8fc95acb013b8f3184
F src/build.c e40a4caaba4afab3fc7f0866ca8766e8146dd62c
F src/callback.c 79cfbac59139b525e3a195ee27b8be1ca06fbd38
F src/build.c ff75e783aa638482d2598a443f88e2ff40abc301
F src/callback.c 1c2b78a210fda18cdd4d0b604ed41bf0e1f5125c
F src/complete.c df1681cef40dec33a286006981845f87b194e7a4
F src/date.c a927bdbb51296ac398d2f667086a7072c099e5ab
F src/delete.c 66199ba71a0f753033073b080baebb349157c960
F src/experimental.c 50c1e3b34f752f4ac10c36f287db095c2b61766d
F src/expr.c 3bf54eca0b0d34bd097750c622d4490a08e78a2b
F src/func.c 5e4204b2ebe89de5228d78eef9352a0ed253f4c0
F src/expr.c 426717b11cf55cb538ccd3db8a3b22a0f956ce8d
F src/func.c e013c3b6c607c6a1654f5260eab59f5609a5ce4a
F src/hash.c 8747cf51d12de46512880dfcf1b68b4e24072863
F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
F src/insert.c 16610475976dc9b25d231338e283dd4b4362a430
F src/legacy.c f651ccd3700f99fa05766ac53506bf9a0694761b
F src/main.c 2e6d9482919371c9d0c522fd87273b6261473b29
F src/main.c 68563cfa3f67d2784506aafd680eeefd0138cae8
F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217
F src/os.c 1d1a61cdf150e9f9520a3bc787c8465148ea2e78
F src/os.h 8710c0068f3386a73a37f8ad242b92c7580464df
@ -62,17 +62,17 @@ F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
F src/pager.c 6fbcc25f1f3fbe62cbbda3af3dbb9c3d758f8050
F src/pager.h e0acb095b3ad0bca48f2ab00c87346665643f64f
F src/parse.y 83df51fea35f68f7e07384d75dce83d1ed30434c
F src/pragma.c 7358baf8e2be14a0f3d71e7afae41e430d76b054
F src/prepare.c e0812d49ef30e07cabb8f77df943e557e6bf927a
F src/pragma.c 05abacaa5a1817a44876d9dbb4790aa7c784427b
F src/prepare.c 41d9a8563e2b988932922c9f96a7bb1271932564
F src/printf.c f47a2f4b5387cd2ebb12e9117a1a5d6bd9a2b812
F src/random.c d40f8d356cecbd351ccfab6eaedd7ec1b54f5261
F src/select.c d97a43973d82a2e1e24be43ca5543c08b93e9e8d
F src/select.c acfeda959fe07eac04950d945ac7ec0518ef4b7d
F src/shell.c 66b073375efbdee19045e7e0cd38b85f9aff71da
F src/sqlite.h.in 537bac9e9ef703695268aaad5c56b6bf64f815be
F src/sqliteInt.h f9e4b620da09737e678271d45135088027d80307
F src/sqliteInt.h 175c7cc358f15aa4f621257ce035e1f2ec2511f3
F src/table.c 486dcfce532685b53b5a2b5da8bba0ded6fb2316
F src/tclsqlite.c 42151e6c78502277be77b88c00535d53ce89b917
F src/test1.c a526810f7d1c73b7b9a85621dd655d4357e0ae6d
F src/test1.c 5f634ce9aa452dbcc362993c9612047df800216c
F src/test2.c ca74a1d8aeb7d9606e8f6b762c5daf85c1a3f92b
F src/test3.c 9742aa146eb750cab81c1d5605286c3a0eb88054
F src/test4.c a8fd681e139e1c61f22a77d07fc3a99cb28fff3f
@ -80,14 +80,14 @@ F src/test5.c 7162f8526affb771c4ed256826eee7bb9eca265f
F src/test6.c 74d91b487c68154156eded457925d96aa2a3fdbb
F src/tokenize.c 196486012c871cdcad6cc84a820cc988603f1b9d
F src/trigger.c c515afa5fe964e9854c54dc66dde179a90d0cfe3
F src/update.c 9a3761250c2ac9e6871f4e9c37560b224ba0067e
F src/update.c e09da54cb8e042f89f4177f4ef879b594d8ab946
F src/utf.c b7bffac4260177ae7f83c01d025fe0f5ed70ce71
F src/util.c 0153015d99468e994a2c9bc6746262654ed5914a
F src/vacuum.c f5a068096b22fad438bf1f1cf69ccb7f9e8cc7fb
F src/vdbe.c ce31105fc91e1ea346e2383cd536149cc66c34bd
F src/vdbe.c 490b9b48a8f616b9a15b0151b86212b0fab311b2
F src/vdbe.h 8729a4ee16ff9aeab2af9667df3cf300ff978e13
F src/vdbeInt.h 5451cf71f229e366ac543607c0a17f36e5737ea9
F src/vdbeapi.c 2e22bd0c845fc380f112aacfc6c5af29be73152e
F src/vdbeapi.c 6d20e92de62b90ae27aeea3a7b18653734b0b1cb
F src/vdbeaux.c e4b8f492e41e3b8ecee8f66045e897dae92d1356
F src/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5
F src/vdbemem.c d712dfd80d58011db688fa8234c1821262a57cae
@ -206,7 +206,7 @@ F test/pagesize.test cbc6a312b6f6c0f02619b189985df2a14164b690
F test/pragma.test 8759b46702f6d8ee4f5dd520216c69dbc9080b60
F test/printf.test 9e10c74e16bf889f8495ddb3d6f5f891e75ff1b7
F test/progress.test 16496001da445e6534afb94562c286708316d82f x
F test/quick.test 24ef81e4e9c1784e7f081e7ce4576c15659b97a7
F test/quick.test 51284a17a631110d0d93d0fdcdc0ed25fcc58259
F test/quote.test 5891f2338980916cf7415484b4ce785294044adb
F test/reindex.test 38b138abe36bf9a08c791ed44d9f76cd6b97b78b
F test/rollback.test fc6be5a5e4b1347fd96777c65484a24fc75e8f0e
@ -220,7 +220,7 @@ F test/select4.test c239f516aa31f42f2ef7c6d7cd01105f08f934ca
F test/select5.test 07a90ab3c7e3f0a241a9cdea1d997b2c8a89ff0b
F test/select6.test f459a19bdac0501c4d3eb1a4df4b7a76f1bb8ad4
F test/select7.test 1bf795b948c133a15a2a5e99d3270e652ec58ce6
F test/shared.test f37afcdc0f4d521fbf1b6d573e7aae1950e71848
F test/shared.test 413289e177e73c844cfc9896b6d78e0f2e62d963
F test/sort.test 0e4456e729e5a92a625907c63dcdedfbe72c5dc5
F test/subquery.test e6de53332c0301b3cfa34edc3f3cd5fa1e859efd
F test/subselect.test 2d13fb7f450db3595adcdd24079a0dd1d2d6abc2
@ -326,7 +326,7 @@ F www/optimizing.tcl f0b2538988d1bbad16cbfe63ec6e8f48c9eb04e5
F www/optoverview.tcl 815df406a38c9f69b27d37e8f7ede004c6d9f19e
F www/pragma.tcl 44f7b665ca598ad24724f35991653638a36a6e3f
F www/quickstart.tcl 2f3daf8038e82a102e1e8cc877aafa7a413f5f11
F www/sharedcache.tcl 884a93bf0f814204b24959c0c6229d61dd4734cc
F www/sharedcache.tcl ce211997860d9dd8fa9a6aa86cdfaf1235ccfcb6
F www/speed.tcl 656ed5be8cc9d536353e1a96927b925634a62933
F www/sqlite.tcl a883ed7b47371d31d471e6aea5ed1f972ae8e1be
F www/support.tcl 7961ce16290692578d783bb11f0dc8391a9be9c3
@ -335,7 +335,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
P 82b81f69c78cb3f54634d9aea4f6a838474dc5e5
R bcf9f7930a1367ea3da4936a55af71d7
P 44f8e3139aa3ad3fcce9028565dd9ad23bbe62a2
R 424a3ae2d9dc1730235de15ae4d0b2f5
U danielk1977
Z b19a6ec12413214a65f445404992c64a
Z d93961474b12e5136b83257759364e0b

View File

@ -1 +1 @@
44f8e3139aa3ad3fcce9028565dd9ad23bbe62a2
3e75d3d5efebc0dfff1adfc13d85e85ec39db3eb

View File

@ -11,7 +11,7 @@
*************************************************************************
** This file contains code used to implement the ATTACH and DETACH commands.
**
** $Id: attach.c,v 1.41 2006/01/09 06:29:48 danielk1977 Exp $
** $Id: attach.c,v 1.42 2006/01/09 16:12:05 danielk1977 Exp $
*/
#include "sqliteInt.h"
@ -127,6 +127,11 @@ static void attachFunc(
if( !aNew->pSchema ){
rc = SQLITE_NOMEM;
}
if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){
strcpy(zErr,
"attached databases must use the same text encoding as main database");
goto attach_error;
}
}
aNew->zName = sqliteStrDup(zName);
aNew->safety_level = 3;

View File

@ -22,7 +22,7 @@
** COMMIT
** ROLLBACK
**
** $Id: build.c,v 1.371 2006/01/09 06:29:48 danielk1977 Exp $
** $Id: build.c,v 1.372 2006/01/09 16:12:05 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -68,7 +68,7 @@ void sqlite3TableLock(
TableLock *p;
ThreadData *pTsd = sqlite3ThreadData();
if( 0==pTsd->useSharedData ){
if( 0==pTsd->useSharedData || iDb<0 ){
return;
}
@ -846,7 +846,7 @@ void sqlite3StartTable(
sqlite3VdbeAddOp(v, OP_If, 0, lbl);
sqlite3VdbeAddOp(v, OP_Integer, SQLITE_DEFAULT_FILE_FORMAT, 0);
sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 1);
sqlite3VdbeAddOp(v, OP_Integer, db->enc, 0);
sqlite3VdbeAddOp(v, OP_Integer, ENC(db), 0);
sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 4);
sqlite3VdbeResolveLabel(v, lbl);
@ -1220,7 +1220,7 @@ int sqlite3CheckIndexCollSeq(Parse *pParse, Index *pIdx){
*/
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName){
sqlite3 *db = pParse->db;
u8 enc = db->enc;
u8 enc = ENC(db);
u8 initbusy = db->init.busy;
CollSeq *pColl = sqlite3FindCollSeq(db, enc, zName, nName, initbusy);
@ -2955,12 +2955,6 @@ static int sqlite3OpenTempDatabase(Parse *pParse){
pParse->rc = rc;
return 1;
}
/*
db->aDb[1].pSchema = sqlite3SchemaGet(db->aDb[1].pBt);
if( !db->aDb[1].pSchema ){
return SQLITE_NOMEM;
}
*/
if( db->flags & !db->autoCommit ){
rc = sqlite3BtreeBeginTrans(db->aDb[1].pBt, 1);
if( rc!=SQLITE_OK ){
@ -2970,6 +2964,7 @@ static int sqlite3OpenTempDatabase(Parse *pParse){
return 1;
}
}
assert( db->aDb[1].pSchema );
}
return 0;
}
@ -3144,7 +3139,7 @@ void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){
reindexDatabases(pParse, 0);
return;
}else if( pName2==0 || pName2->z==0 ){
pColl = sqlite3FindCollSeq(db, db->enc, (char*)pName1->z, pName1->n, 0);
pColl = sqlite3FindCollSeq(db, ENC(db), (char*)pName1->z, pName1->n, 0);
if( pColl ){
reindexDatabases(pParse, pColl);
return;

View File

@ -13,7 +13,7 @@
** This file contains functions used to access the internal hash tables
** of user defined functions and collation sequences.
**
** $Id: callback.c,v 1.8 2006/01/09 06:29:48 danielk1977 Exp $
** $Id: callback.c,v 1.9 2006/01/09 16:12:05 danielk1977 Exp $
*/
#include "sqliteInt.h"
@ -29,7 +29,7 @@ static void callCollNeeded(sqlite3 *db, const char *zName, int nName){
if( db->xCollNeeded ){
char *zExternal = sqliteStrNDup(zName, nName);
if( !zExternal ) return;
db->xCollNeeded(db->pCollNeededArg, db, (int)db->enc, zExternal);
db->xCollNeeded(db->pCollNeededArg, db, (int)ENC(db), zExternal);
sqliteFree(zExternal);
}
#ifndef SQLITE_OMIT_UTF16
@ -39,7 +39,7 @@ static void callCollNeeded(sqlite3 *db, const char *zName, int nName){
sqlite3ValueSetStr(pTmp, nName, zName, SQLITE_UTF8, SQLITE_STATIC);
zExternal = sqlite3ValueText(pTmp, SQLITE_UTF16NATIVE);
if( zExternal ){
db->xCollNeeded16(db->pCollNeededArg, db, (int)db->enc, zExternal);
db->xCollNeeded16(db->pCollNeededArg, db, (int)ENC(db), zExternal);
}
sqlite3ValueFree(pTmp);
}
@ -92,14 +92,14 @@ CollSeq *sqlite3GetCollSeq(
p = pColl;
if( !p ){
p = sqlite3FindCollSeq(db, db->enc, zName, nName, 0);
p = sqlite3FindCollSeq(db, ENC(db), zName, nName, 0);
}
if( !p || !p->xCmp ){
/* No collation sequence of this type for this encoding is registered.
** Call the collation factory to see if it can supply us with one.
*/
callCollNeeded(db, zName, nName);
p = sqlite3FindCollSeq(db, db->enc, zName, nName, 0);
p = sqlite3FindCollSeq(db, ENC(db), zName, nName, 0);
}
if( p && !p->xCmp && synthCollSeq(db, p) ){
p = 0;

View File

@ -12,7 +12,7 @@
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.245 2006/01/09 06:29:48 danielk1977 Exp $
** $Id: expr.c,v 1.246 2006/01/09 16:12:05 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -1149,7 +1149,7 @@ static int nameResolverStep(void *pArg, Expr *pExpr){
int nId; /* Number of characters in function name */
const char *zId; /* The function name. */
FuncDef *pDef; /* Information about the function */
int enc = pParse->db->enc; /* The database encoding */
int enc = ENC(pParse->db); /* The database encoding */
zId = (char*)pExpr->token.z;
nId = pExpr->token.n;
@ -1666,7 +1666,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
const char *zId;
int constMask = 0;
int i;
u8 enc = pParse->db->enc;
u8 enc = ENC(pParse->db);
CollSeq *pColl = 0;
zId = (char*)pExpr->token.z;
nId = pExpr->token.n;
@ -2233,7 +2233,7 @@ static int analyzeAggregate(void *pArg, Expr *pExpr){
if( i>=pAggInfo->nFunc ){
/* pExpr is original. Make a new entry in pAggInfo->aFunc[]
*/
u8 enc = pParse->db->enc;
u8 enc = ENC(pParse->db);
i = addAggInfoFunc(pAggInfo);
if( i>=0 ){
pItem = &pAggInfo->aFunc[i];

View File

@ -16,7 +16,7 @@
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
**
** $Id: func.c,v 1.114 2006/01/06 21:52:50 drh Exp $
** $Id: func.c,v 1.115 2006/01/09 16:12:05 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -728,17 +728,17 @@ static void test_destructor(
test_destructor_count_var++;
assert( nArg==1 );
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
len = sqlite3ValueBytes(argv[0], db->enc);
len = sqlite3ValueBytes(argv[0], ENC(db));
zVal = sqliteMalloc(len+3);
zVal[len] = 0;
zVal[len-1] = 0;
assert( zVal );
zVal++;
memcpy(zVal, sqlite3ValueText(argv[0], db->enc), len);
if( db->enc==SQLITE_UTF8 ){
memcpy(zVal, sqlite3ValueText(argv[0], ENC(db)), len);
if( ENC(db)==SQLITE_UTF8 ){
sqlite3_result_text(pCtx, zVal, -1, destructor);
#ifndef SQLITE_OMIT_UTF16
}else if( db->enc==SQLITE_UTF16LE ){
}else if( ENC(db)==SQLITE_UTF16LE ){
sqlite3_result_text16le(pCtx, zVal, -1, destructor);
}else{
sqlite3_result_text16be(pCtx, zVal, -1, destructor);

View File

@ -14,7 +14,7 @@
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.319 2006/01/09 06:29:49 danielk1977 Exp $
** $Id: main.c,v 1.320 2006/01/09 16:12:05 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -725,7 +725,6 @@ static int openDatabase(
db->magic = SQLITE_MAGIC_BUSY;
db->nDb = 2;
db->aDb = db->aDbStatic;
db->enc = SQLITE_UTF8;
db->autoCommit = 1;
db->flags |= SQLITE_ShortColNames;
sqlite3HashInit(&db->aFunc, SQLITE_HASH_STRING, 0);
@ -739,14 +738,14 @@ static int openDatabase(
sqlite3HashInit(&db->aDb[i].aFKey, SQLITE_HASH_STRING, 1);
}
#endif
/* Add the default collation sequence BINARY. BINARY works for both UTF-8
** and UTF-16, so add a version for each to avoid any unnecessary
** conversions. The only error that can occur here is a malloc() failure.
*/
if( sqlite3_create_collation(db, "BINARY", SQLITE_UTF8, 0,binCollFunc) ||
sqlite3_create_collation(db, "BINARY", SQLITE_UTF16, 0,binCollFunc) ||
(db->pDfltColl = sqlite3FindCollSeq(db, db->enc, "BINARY", 6, 0))==0
(db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0))==0
){
/* sqlite3_create_collation() is an external API. So the mallocFailed flag
** will have been cleared before returning. So set it explicitly here.
@ -778,6 +777,10 @@ static int openDatabase(
db->aDb[1].pSchema = sqlite3SchemaGet(0);
#endif
if( db->aDb[0].pSchema ){
ENC(db) = SQLITE_UTF8;
}
/* The default safety_level for the main database is 'full'; for the temp
** database it is 'NONE'. This matches the pager layer defaults.
*/

View File

@ -11,7 +11,7 @@
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
** $Id: pragma.c,v 1.110 2006/01/08 18:10:18 drh Exp $
** $Id: pragma.c,v 1.111 2006/01/09 16:12:05 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -287,8 +287,8 @@ void sqlite3Pragma(
sqlite3VdbeAddOp(v, OP_Ge, 0, addr+3);
sqlite3VdbeAddOp(v, OP_Negative, 0, 0);
sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 2);
pDb->cache_size = size;
sqlite3BtreeSetCacheSize(pDb->pBt, pDb->cache_size);
pDb->pSchema->cache_size = size;
sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
}
}else
@ -349,12 +349,12 @@ void sqlite3Pragma(
if( sqlite3StrICmp(zLeft,"cache_size")==0 ){
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
if( !zRight ){
returnSingleInt(pParse, "cache_size", pDb->cache_size);
returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size);
}else{
int size = atoi(zRight);
if( size<0 ) size = -size;
pDb->cache_size = size;
sqlite3BtreeSetCacheSize(pDb->pBt, pDb->cache_size);
pDb->pSchema->cache_size = size;
sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
}
}else
@ -797,7 +797,7 @@ void sqlite3Pragma(
sqlite3VdbeSetColName(v, 0, "encoding", P3_STATIC);
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
for(pEnc=&encnames[0]; pEnc->zName; pEnc++){
if( pEnc->enc==pParse->db->enc ){
if( pEnc->enc==ENC(pParse->db) ){
sqlite3VdbeChangeP3(v, -1, pEnc->zName, P3_STATIC);
break;
}
@ -812,7 +812,7 @@ void sqlite3Pragma(
if( !(pParse->db->flags&SQLITE_Initialized) ){
for(pEnc=&encnames[0]; pEnc->zName; pEnc++){
if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){
pParse->db->enc = pEnc->enc;
ENC(pParse->db) = pEnc->enc;
break;
}
}

View File

@ -13,7 +13,7 @@
** interface, and routines that contribute to loading the database schema
** from disk.
**
** $Id: prepare.c,v 1.16 2006/01/09 06:29:49 danielk1977 Exp $
** $Id: prepare.c,v 1.17 2006/01/09 16:12:05 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -155,21 +155,26 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
assert( iDb>=0 && iDb<db->nDb );
assert( db->aDb[iDb].pSchema );
#if 0
if( 0==db->aDb[iDb].pSchema ){
Schema *pS = sqlite3BtreeSchema(db->aDb[iDb].pBt, sizeof(Schema),
sqlite3SchemaFree);
Schema *pS = sqlite3SchemaGet(db->aDb[iDb].pBt);
db->aDb[iDb].pSchema = pS;
if( !pS ){
return SQLITE_NOMEM;
}else if( pS->file_format!=0 ){
/* This means that the shared-schema associated with the the btree
** is already open and populated.
*/
if( pS->enc!=ENC(db) ){
sqlite3SetString(pzErrMsg, "attached databases must use the same"
" text encoding as main database", (char*)0);
return SQLITE_ERROR;
}
return SQLITE_OK;
}else{
sqlite3HashInit(&pS->tblHash, SQLITE_HASH_STRING, 0);
sqlite3HashInit(&pS->idxHash, SQLITE_HASH_STRING, 0);
sqlite3HashInit(&pS->trigHash, SQLITE_HASH_STRING, 0);
sqlite3HashInit(&pS->aFKey, SQLITE_HASH_STRING, 1);
}
}
#endif
/* zMasterSchema and zInitScript are set to point at the master schema
** and initialisation script appropriate for the database being
@ -255,12 +260,12 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
*/
if( meta[4] ){ /* text encoding */
if( iDb==0 ){
/* If opening the main database, set db->enc. */
db->enc = (u8)meta[4];
db->pDfltColl = sqlite3FindCollSeq(db, db->enc, "BINARY", 6, 0);
/* If opening the main database, set ENC(db). */
ENC(db) = (u8)meta[4];
db->pDfltColl = sqlite3FindCollSeq(db, ENC(db), "BINARY", 6, 0);
}else{
/* If opening an attached database, the encoding much match db->enc */
if( meta[4]!=db->enc ){
/* If opening an attached database, the encoding much match ENC(db) */
if( meta[4]!=ENC(db) ){
sqlite3BtreeCloseCursor(curMain);
sqlite3SetString(pzErrMsg, "attached databases must use the same"
" text encoding as main database", (char*)0);
@ -268,11 +273,12 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
}
}
}
pDb->pSchema->enc = ENC(db);
size = meta[2];
if( size==0 ){ size = MAX_PAGES; }
pDb->cache_size = size;
sqlite3BtreeSetCacheSize(pDb->pBt, pDb->cache_size);
pDb->pSchema->cache_size = size;
sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
/*
** file_format==1 Version 3.0.0.

View File

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.290 2006/01/09 06:29:49 danielk1977 Exp $
** $Id: select.c,v 1.291 2006/01/09 16:12:05 danielk1977 Exp $
*/
#include "sqliteInt.h"
@ -650,7 +650,7 @@ static KeyInfo *keyInfoFromExprList(Parse *pParse, ExprList *pList){
if( pInfo ){
pInfo->aSortOrder = (u8*)&pInfo->aColl[nExpr];
pInfo->nField = nExpr;
pInfo->enc = db->enc;
pInfo->enc = ENC(db);
for(i=0, pItem=pList->a; i<nExpr; i++, pItem++){
CollSeq *pColl;
pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr);
@ -1828,7 +1828,7 @@ static int multiSelect(
goto multi_select_end;
}
pKeyInfo->enc = pParse->db->enc;
pKeyInfo->enc = ENC(pParse->db);
pKeyInfo->nField = nCol;
for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){
@ -2302,6 +2302,7 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
** or last entry in the main table.
*/
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
assert( iDb>=0 || pTab->isTransient );
sqlite3CodeVerifySchema(pParse, iDb);
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
base = pSrc->a[0].iCursor;

View File

@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.455 2006/01/09 09:59:49 danielk1977 Exp $
** @(#) $Id: sqliteInt.h,v 1.456 2006/01/09 16:12:05 danielk1977 Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
@ -382,7 +382,6 @@ struct Db {
Btree *pBt; /* The B*Tree structure for this database file */
u8 inTrans; /* 0: not writable. 1: Transaction. 2: Checkpoint */
u8 safety_level; /* How aggressive at synching data to disk */
int cache_size; /* Number of pages to use in the cache */
void *pAux; /* Auxiliary data. Usually NULL */
void (*xFreeAux)(void*); /* Routine to free pAux */
Schema *pSchema; /* Pointer to database schema (possibly shared) */
@ -400,6 +399,8 @@ struct Schema {
Table *pSeqTab; /* The sqlite_sequence table used by AUTOINCREMENT */
u8 file_format; /* Schema format version for this file */
u16 flags; /* Flags associated with this schema */
int cache_size; /* Number of pages to use in the cache */
u8 enc; /* Text encoding used by this database */
};
/*
@ -457,7 +458,6 @@ struct sqlite3 {
Db *aDb; /* All backends */
int flags; /* Miscellanous flags. See below */
int errCode; /* Most recent error code (SQLITE_*) */
u8 enc; /* Text encoding for this database. */
u8 autoCommit; /* The auto-commit flag. */
u8 temp_store; /* 1: file 2: memory 0: default */
int nTable; /* Number of tables in the database */
@ -513,6 +513,8 @@ struct sqlite3 {
#endif
};
#define ENC(db) ((db)->aDb[0].pSchema->enc)
/*
** Possible values for the sqlite.flags and or Db.flags fields.
**

View File

@ -13,7 +13,7 @@
** is not included in the SQLite library. It is used for automated
** testing of the SQLite library.
**
** $Id: test1.c,v 1.185 2006/01/09 09:59:49 danielk1977 Exp $
** $Id: test1.c,v 1.186 2006/01/09 16:12:05 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
@ -1389,7 +1389,7 @@ static void test_collate_needed_cb(
int eTextRep,
const void *pName
){
int enc = db->enc;
int enc = ENC(db);
int i;
char *z;
for(z = (char*)pName, i=0; *z || z[1]; z++){
@ -1397,7 +1397,7 @@ static void test_collate_needed_cb(
}
zNeededCollation[i] = 0;
sqlite3_create_collation(
db, "test_collate", db->enc, (void *)enc, test_collate_func);
db, "test_collate", ENC(db), (void *)enc, test_collate_func);
}
/*

View File

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.117 2006/01/09 06:29:49 danielk1977 Exp $
** $Id: update.c,v 1.118 2006/01/09 16:12:05 danielk1977 Exp $
*/
#include "sqliteInt.h"
@ -44,7 +44,7 @@
void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i){
if( pTab && !pTab->pSelect ){
sqlite3_value *pValue;
u8 enc = sqlite3VdbeDb(v)->enc;
u8 enc = ENC(sqlite3VdbeDb(v));
Column *pCol = &pTab->aCol[i];
sqlite3ValueFromExpr(pCol->pDflt, enc, pCol->affinity, &pValue);
if( pValue ){

View File

@ -43,7 +43,7 @@
** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.519 2006/01/09 06:29:49 danielk1977 Exp $
** $Id: vdbe.c,v 1.520 2006/01/09 16:12:05 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -639,7 +639,7 @@ case OP_Real: { /* same as TK_FLOAT, */
pTos->enc = SQLITE_UTF8;
pTos->r = sqlite3VdbeRealValue(pTos);
pTos->flags |= MEM_Real;
sqlite3VdbeChangeEncoding(pTos, db->enc);
sqlite3VdbeChangeEncoding(pTos, ENC(db));
break;
}
@ -655,10 +655,10 @@ case OP_String8: { /* same as TK_STRING */
pOp->p1 = strlen(pOp->p3);
#ifndef SQLITE_OMIT_UTF16
if( db->enc!=SQLITE_UTF8 ){
if( ENC(db)!=SQLITE_UTF8 ){
pTos++;
sqlite3VdbeMemSetStr(pTos, pOp->p3, -1, SQLITE_UTF8, SQLITE_STATIC);
if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pTos, db->enc) ) goto no_mem;
if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pTos, ENC(db)) ) goto no_mem;
if( SQLITE_OK!=sqlite3VdbeMemDynamicify(pTos) ) goto no_mem;
pTos->flags &= ~(MEM_Dyn);
pTos->flags |= MEM_Static;
@ -684,7 +684,7 @@ case OP_String: {
pTos->flags = MEM_Str|MEM_Static|MEM_Term;
pTos->z = pOp->p3;
pTos->n = pOp->p1;
pTos->enc = db->enc;
pTos->enc = ENC(db);
break;
}
@ -888,7 +888,7 @@ case OP_Callback: { /* no-push */
*/
for(; pMem<=pTos; pMem++ ){
sqlite3VdbeMemNulTerminate(pMem);
storeTypeInfo(pMem, db->enc);
storeTypeInfo(pMem, ENC(db));
}
/* Set up the statement structure so that it will pop the current
@ -929,7 +929,7 @@ case OP_Concat: { /* same as TK_CONCAT */
nByte = -1;
break;
}
Stringify(pTerm, db->enc);
Stringify(pTerm, ENC(db));
nByte += pTerm->n;
}
@ -968,7 +968,7 @@ case OP_Concat: { /* same as TK_CONCAT */
pTos->n = j;
pTos->flags = MEM_Str|MEM_Dyn|MEM_Term;
pTos->xDel = 0;
pTos->enc = db->enc;
pTos->enc = ENC(db);
pTos->z = zNew;
}
break;
@ -1142,7 +1142,7 @@ case OP_Function: {
pArg = &pTos[1-n];
for(i=0; i<n; i++, pArg++){
apVal[i] = pArg;
storeTypeInfo(pArg, db->enc);
storeTypeInfo(pArg, ENC(db));
}
assert( pOp->p3type==P3_FUNCDEF || pOp->p3type==P3_VDBEFUNC );
@ -1180,7 +1180,7 @@ case OP_Function: {
}
/* Copy the result of the function to the top of the stack */
sqlite3VdbeChangeEncoding(&ctx.s, db->enc);
sqlite3VdbeChangeEncoding(&ctx.s, ENC(db));
pTos++;
pTos->flags = 0;
sqlite3VdbeMemMove(pTos, &ctx.s);
@ -1191,7 +1191,7 @@ case OP_Function: {
sqlite3SetString(&p->zErrMsg, "user function error", (char*)0);
}else{
sqlite3SetString(&p->zErrMsg, sqlite3_value_text(pTos), (char*)0);
sqlite3VdbeChangeEncoding(pTos, db->enc);
sqlite3VdbeChangeEncoding(pTos, ENC(db));
}
rc = SQLITE_ERROR;
}
@ -1284,7 +1284,7 @@ case OP_AddImm: { /* no-push */
case OP_ForceInt: { /* no-push */
i64 v;
assert( pTos>=p->aStack );
applyAffinity(pTos, SQLITE_AFF_NUMERIC, db->enc);
applyAffinity(pTos, SQLITE_AFF_NUMERIC, ENC(db));
if( (pTos->flags & (MEM_Int|MEM_Real))==0 ){
Release(pTos);
pTos--;
@ -1319,7 +1319,7 @@ case OP_ForceInt: { /* no-push */
*/
case OP_MustBeInt: { /* no-push */
assert( pTos>=p->aStack );
applyAffinity(pTos, SQLITE_AFF_NUMERIC, db->enc);
applyAffinity(pTos, SQLITE_AFF_NUMERIC, ENC(db));
if( (pTos->flags & MEM_Int)==0 ){
if( pOp->p2==0 ){
rc = SQLITE_MISMATCH;
@ -1367,7 +1367,7 @@ case OP_ToText: { /* same as TK_TO_TEXT, no-push */
if( pTos->flags & MEM_Null ) break;
assert( MEM_Str==(MEM_Blob>>3) );
pTos->flags |= (pTos->flags&MEM_Blob)>>3;
applyAffinity(pTos, SQLITE_AFF_TEXT, db->enc);
applyAffinity(pTos, SQLITE_AFF_TEXT, ENC(db));
assert( pTos->flags & MEM_Str );
pTos->flags &= ~(MEM_Int|MEM_Real|MEM_Blob);
break;
@ -1386,7 +1386,7 @@ case OP_ToBlob: { /* same as TK_TO_BLOB, no-push */
assert( pTos>=p->aStack );
if( pTos->flags & MEM_Null ) break;
if( (pTos->flags & MEM_Blob)==0 ){
applyAffinity(pTos, SQLITE_AFF_TEXT, db->enc);
applyAffinity(pTos, SQLITE_AFF_TEXT, ENC(db));
assert( pTos->flags & MEM_Str );
pTos->flags |= MEM_Blob;
}
@ -1567,8 +1567,8 @@ case OP_Ge: { /* same as TK_GE, no-push */
affinity = pOp->p1 & 0xFF;
if( affinity ){
applyAffinity(pNos, affinity, db->enc);
applyAffinity(pTos, affinity, db->enc);
applyAffinity(pNos, affinity, ENC(db));
applyAffinity(pTos, affinity, ENC(db));
}
assert( pOp->p3type==P3_COLLSEQ || pOp->p3==0 );
@ -2068,7 +2068,7 @@ case OP_Column: {
zData = sMem.z;
}
sqlite3VdbeSerialGet((u8*)zData, aType[p2], pTos);
pTos->enc = db->enc;
pTos->enc = ENC(db);
}else{
if( pOp->p3type==P3_MEM ){
sqlite3VdbeMemShallowCopy(pTos, (Mem *)(pOp->p3), MEM_Static);
@ -2192,7 +2192,7 @@ case OP_MakeRecord: {
*/
for(pRec=pData0; pRec<=pTos; pRec++){
if( zAffinity ){
applyAffinity(pRec, zAffinity[pRec-pData0], db->enc);
applyAffinity(pRec, zAffinity[pRec-pData0], ENC(db));
}
if( pRec->flags&MEM_Null ){
containsNull = 1;
@ -2582,7 +2582,7 @@ case OP_OpenWrite: { /* no-push */
if( pOp->p3type==P3_KEYINFO ){
pCur->pKeyInfo = (KeyInfo*)pOp->p3;
pCur->pIncrKey = &pCur->pKeyInfo->incrKey;
pCur->pKeyInfo->enc = p->db->enc;
pCur->pKeyInfo->enc = ENC(p->db);
}else{
pCur->pKeyInfo = 0;
pCur->pIncrKey = &pCur->bogusIncrKey;
@ -2670,7 +2670,7 @@ case OP_OpenVirtual: { /* no-push */
rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, sqlite3VdbeRecordCompare,
pOp->p3, &pCx->pCursor);
pCx->pKeyInfo = (KeyInfo*)pOp->p3;
pCx->pKeyInfo->enc = p->db->enc;
pCx->pKeyInfo->enc = ENC(p->db);
pCx->pIncrKey = &pCx->pKeyInfo->incrKey;
}
pCx->isTable = 0;
@ -2800,7 +2800,7 @@ case OP_MoveGt: { /* no-push */
pC->rowidIsValid = res==0;
}else{
assert( pTos->flags & MEM_Blob );
/* Stringify(pTos, db->enc); */
/* Stringify(pTos, ENC(db)); */
rc = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
@ -2905,7 +2905,7 @@ case OP_Found: { /* no-push */
if( (pC = p->apCsr[i])->pCursor!=0 ){
int res, rx;
assert( pC->isTable==0 );
Stringify(pTos, db->enc);
Stringify(pTos, ENC(db));
rx = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
alreadyExists = rx==SQLITE_OK && res==0;
pC->deferredMoveto = 0;
@ -2972,7 +2972,7 @@ case OP_IsUnique: { /* no-push */
/* Make sure K is a string and make zKey point to K
*/
Stringify(pNos, db->enc);
Stringify(pNos, ENC(db));
zKey = pNos->z;
nKey = pNos->n;
@ -3802,7 +3802,7 @@ case OP_IdxGE: { /* no-push */
int res, rc;
assert( pTos->flags & MEM_Blob ); /* Created using OP_Make*Key */
Stringify(pTos, db->enc);
Stringify(pTos, ENC(db));
assert( pC->deferredMoveto==0 );
*pC->pIncrKey = pOp->p3!=0;
assert( pOp->p3==0 || pOp->opcode!=OP_IdxGT );
@ -4131,7 +4131,7 @@ case OP_IntegrityCk: {
pTos->xDel = 0;
}
pTos->enc = SQLITE_UTF8;
sqlite3VdbeChangeEncoding(pTos, db->enc);
sqlite3VdbeChangeEncoding(pTos, ENC(db));
sqliteFree(aRoot);
break;
}
@ -4407,7 +4407,7 @@ case OP_AggStep: { /* no-push */
assert( apVal || n==0 );
for(i=0; i<n; i++, pRec++){
apVal[i] = pRec;
storeTypeInfo(pRec, db->enc);
storeTypeInfo(pRec, ENC(db));
}
ctx.pFunc = (FuncDef*)pOp->p3;
assert( pOp->p1>=0 && pOp->p1<p->nMem );
@ -4552,7 +4552,7 @@ default: {
#ifndef NDEBUG
/* Sanity checking on the top element of the stack */
if( pTos>=p->aStack ){
sqlite3VdbeMemSanity(pTos, db->enc);
sqlite3VdbeMemSanity(pTos, ENC(db));
}
assert( pc>=-1 && pc<p->nOp );
#ifdef SQLITE_DEBUG

View File

@ -634,7 +634,7 @@ static int bindText(
return rc;
}
if( rc==SQLITE_OK && encoding!=0 ){
rc = sqlite3VdbeChangeEncoding(pVar, p->db->enc);
rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db));
}
return rc;
}

View File

@ -6,7 +6,7 @@
#***********************************************************************
# This file runs all tests.
#
# $Id: quick.test,v 1.39 2005/12/30 16:28:02 danielk1977 Exp $
# $Id: quick.test,v 1.40 2006/01/09 16:12:05 danielk1977 Exp $
proc lshift {lvar} {
upvar $lvar l
@ -49,6 +49,8 @@ set EXCLUDE {
memleak.test
misuse.test
quick.test
attachmalloc.test
utf16.test
autovacuum_crash.test
btree8.test

View File

@ -8,10 +8,8 @@
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this file is testing the SELECT statement.
#
# $Id: shared.test,v 1.7 2006/01/09 06:29:49 danielk1977 Exp $
# $Id: shared.test,v 1.8 2006/01/09 16:12:05 danielk1977 Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -35,7 +33,7 @@ set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
# shared-5.*: Test that creating/dropping schema items works when databases
# are attached in different orders to different handles.
# shared-6.*: Locking, UNION ALL queries and sub-queries.
# shared-6.*: Autovacuum and shared-cache.
# shared-7.*: Autovacuum and shared-cache.
#
do_test shared-1.1 {
@ -475,6 +473,10 @@ foreach f [list test.db test2.db] {
# COMMIT.
#
do_test shared-7.1 {
# This test case sets up a test database in auto-vacuum mode consisting
# of two tables, t1 and t2. Both have a single index. Table t1 is
# populated first (so consists of pages toward the start of the db file),
# t2 second (pages toward the end of the file).
sqlite3 db test.db
sqlite3 db2 test.db
execsql {
@ -500,6 +502,13 @@ do_test shared-7.1 {
}
} {1}
do_test shared-7.2 {
# This test case deletes the contents of table t1 (the one at the start of
# the file) while many cursors are open on table t2 and it's index. All of
# the non-root pages will be moved from the end to the start of the file
# when the DELETE is committed - this test verifies that moving the pages
# does not disturb the open cursors.
#
proc lockrow {db tbl oids body} {
set ret [list]
db eval "SELECT oid AS i, a, b FROM $tbl ORDER BY a" {
@ -526,6 +535,8 @@ do_test shared-7.2 {
} db2
}]
set error 0
# Test that each SELECT query returned the expected contents of t2.
foreach s $scans {
if {[lsort -integer -index 0 $s]!=$::contents} {
set error 1
@ -537,6 +548,63 @@ do_test shared-7.2 {
catch {db close}
catch {db2 close}
#--------------------------------------------------------------------------
# The following tests try to trick the shared-cache code into assuming
# the wrong encoding for a database.
#
file delete -force test.db test.db-journal
do_test shared-8.1.1 {
sqlite3 db test.db
execsql {
PRAGMA encoding = 'UTF-16';
SELECT * FROM sqlite_master;
}
} {}
do_test shared-8.1.2 {
string range [execsql {PRAGMA encoding;}] 0 end-2
} {UTF-16}
do_test shared-8.1.3 {
sqlite3 db2 test.db
execsql {
PRAGMA encoding = 'UTF-8';
CREATE TABLE abc(a, b, c);
} db2
} {}
do_test shared-8.1.4 {
execsql {
SELECT * FROM sqlite_master;
}
} "table abc abc [expr $AUTOVACUUM?3:2] {CREATE TABLE abc(a, b, c)}"
do_test shared-8.1.5 {
db2 close
execsql {
PRAGMA encoding;
}
} {UTF-8}
file delete -force test2.db test2.db-journal
do_test shared-8.2.1 {
execsql {
ATTACH 'test2.db' AS aux;
SELECT * FROM aux.sqlite_master;
}
} {}
do_test shared-8.2.2 {
sqlite3 db2 test2.db
execsql {
PRAGMA encoding = 'UTF-16';
CREATE TABLE def(d, e, f);
} db2
string range [execsql {PRAGMA encoding;} db2] 0 end-2
} {UTF-16}
do_test shared-8.2.3 {
catchsql {
SELECT * FROM aux.sqlite_master;
}
} {1 {attached databases must use the same text encoding as main database}}
catch {db close}
catch {db2 close}
finish_test
sqlite3_enable_shared_cache $::enable_shared_cache

View File

@ -39,12 +39,11 @@ This can significantly reduce the quantity of memory and IO required by
the system.</p>
<p>Using shared-cache mode imposes some extra restrictions on
passing database handles between threads and also changes the semantics
passing database handles between threads and changes the semantics
of the locking model in some cases. These details are described in full by
this document. A basic understanding of the normal SQLite locking model (see
<a href="lockingv3.html">File Locking And Concurrency In SQLite Version 3</a>
for details) is assumed.
</p>
for details) is assumed.</p>
}
HEADING 1 {Shared-Cache Locking Model}
@ -185,25 +184,6 @@ database (including the default database, "main").
</ul>
}
HEADING 3 {Schema locking and attached databases}
puts {
<p>The final point in the bullet list is deceptively complicated when
multiple databases are attached to connections. Exactly when is access to a
specific database schema "required" to compile a statement? The way in
which SQLite resolves the names of schema objects (i.e. tables, indices,
triggers and views) depends on whether or not the name was qualified
or unqualified in the original SQL statement. The first statement below
uses a qualified table name, the second uses an unqualified table name.
Both refer to the same underlying table.
</p>
<pre>
SELECT name FROM main.sqlite_master;
SELECT name FROM sqlite_master;
</pre>
1
}
HEADING 1 {Thread Related Issues}
puts {