mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
Merge all the latest trunk changes into the sessions branch, especially
the disappearing WAL transaction fix. FossilOrigin-Name: 5b1b536cf828850d0e8ac2ab08e8696082715877
This commit is contained in:
10
Makefile.in
10
Makefile.in
@ -378,7 +378,8 @@ TESTSRC = \
|
||||
$(TOP)/src/test_thread.c \
|
||||
$(TOP)/src/test_vfs.c \
|
||||
$(TOP)/src/test_wholenumber.c \
|
||||
$(TOP)/src/test_wsd.c
|
||||
$(TOP)/src/test_wsd.c \
|
||||
$(TOP)/ext/fts3/fts3_term.c
|
||||
|
||||
# Source code to the library files needed by the test fixture
|
||||
#
|
||||
@ -420,6 +421,7 @@ TESTSRC2 = \
|
||||
$(TOP)/ext/fts3/fts3.c \
|
||||
$(TOP)/ext/fts3/fts3_aux.c \
|
||||
$(TOP)/ext/fts3/fts3_expr.c \
|
||||
$(TOP)/ext/fts3/fts3_term.c \
|
||||
$(TOP)/ext/fts3/fts3_tokenizer.c \
|
||||
$(TOP)/ext/fts3/fts3_write.c \
|
||||
$(TOP)/ext/async/sqlite3async.c
|
||||
@ -828,12 +830,12 @@ fts3_hash.lo: $(TOP)/ext/fts3/fts3_hash.c $(HDR) $(EXTHDR)
|
||||
fts3_icu.lo: $(TOP)/ext/fts3/fts3_icu.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_icu.c
|
||||
|
||||
fts3_snippet.lo: $(TOP)/ext/fts3/fts3_snippet.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_snippet.c
|
||||
|
||||
fts3_porter.lo: $(TOP)/ext/fts3/fts3_porter.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_porter.c
|
||||
|
||||
fts3_snippet.lo: $(TOP)/ext/fts3/fts3_snippet.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_snippet.c
|
||||
|
||||
fts3_tokenizer.lo: $(TOP)/ext/fts3/fts3_tokenizer.c $(HDR) $(EXTHDR)
|
||||
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenizer.c
|
||||
|
||||
|
@ -1195,7 +1195,7 @@ static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
|
||||
** table is missing a row that is present in the full-text index.
|
||||
** The data structures are corrupt.
|
||||
*/
|
||||
rc = SQLITE_CORRUPT;
|
||||
rc = SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
pCsr->isEof = 1;
|
||||
if( pContext ){
|
||||
@ -1255,7 +1255,7 @@ static int fts3ScanInteriorNode(
|
||||
zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
|
||||
zCsr += sqlite3Fts3GetVarint(zCsr, &iChild);
|
||||
if( zCsr>zEnd ){
|
||||
return SQLITE_CORRUPT;
|
||||
return SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
|
||||
while( zCsr<zEnd && (piFirst || piLast) ){
|
||||
@ -1273,7 +1273,7 @@ static int fts3ScanInteriorNode(
|
||||
zCsr += sqlite3Fts3GetVarint32(zCsr, &nSuffix);
|
||||
|
||||
if( nPrefix<0 || nSuffix<0 || &zCsr[nSuffix]>zEnd ){
|
||||
rc = SQLITE_CORRUPT;
|
||||
rc = SQLITE_CORRUPT_VTAB;
|
||||
goto finish_scan;
|
||||
}
|
||||
if( nPrefix+nSuffix>nAlloc ){
|
||||
@ -3661,7 +3661,7 @@ static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
|
||||
}
|
||||
|
||||
static const sqlite3_module fts3Module = {
|
||||
/* iVersion */ 1,
|
||||
/* iVersion */ 2,
|
||||
/* xCreate */ fts3CreateMethod,
|
||||
/* xConnect */ fts3ConnectMethod,
|
||||
/* xBestIndex */ fts3BestIndexMethod,
|
||||
|
@ -381,6 +381,7 @@ int sqlite3Fts3ExprParse(sqlite3_tokenizer *,
|
||||
void sqlite3Fts3ExprFree(Fts3Expr *);
|
||||
#ifdef SQLITE_TEST
|
||||
int sqlite3Fts3ExprInitTestInterface(sqlite3 *db);
|
||||
int sqlite3Fts3InitTerm(sqlite3 *db);
|
||||
#endif
|
||||
|
||||
/* fts3_aux.c */
|
||||
|
@ -960,7 +960,7 @@ static int fts3MatchinfoSelectDoctotal(
|
||||
|
||||
a = sqlite3_column_blob(pStmt, 0);
|
||||
a += sqlite3Fts3GetVarint(a, &nDoc);
|
||||
if( nDoc==0 ) return SQLITE_CORRUPT;
|
||||
if( nDoc==0 ) return SQLITE_CORRUPT_VTAB;
|
||||
*pnDoc = (u32)nDoc;
|
||||
|
||||
if( paLen ) *paLen = a;
|
||||
@ -1555,7 +1555,7 @@ void sqlite3Fts3Offsets(
|
||||
);
|
||||
rc = fts3StringAppend(&res, aBuffer, -1);
|
||||
}else if( rc==SQLITE_DONE ){
|
||||
rc = SQLITE_CORRUPT;
|
||||
rc = SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -291,7 +291,7 @@ static int fts3SelectDocsize(
|
||||
rc = sqlite3_step(pStmt);
|
||||
if( rc!=SQLITE_ROW || sqlite3_column_type(pStmt, 0)!=SQLITE_BLOB ){
|
||||
rc = sqlite3_reset(pStmt);
|
||||
if( rc==SQLITE_OK ) rc = SQLITE_CORRUPT;
|
||||
if( rc==SQLITE_OK ) rc = SQLITE_CORRUPT_VTAB;
|
||||
pStmt = 0;
|
||||
}else{
|
||||
rc = SQLITE_OK;
|
||||
@ -972,7 +972,7 @@ static int fts3SegReaderNext(Fts3Table *p, Fts3SegReader *pReader){
|
||||
if( nPrefix<0 || nSuffix<=0
|
||||
|| &pNext[nSuffix]>&pReader->aNode[pReader->nNode]
|
||||
){
|
||||
return SQLITE_CORRUPT;
|
||||
return SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
|
||||
if( nPrefix+nSuffix>pReader->nTermAlloc ){
|
||||
@ -998,7 +998,7 @@ static int fts3SegReaderNext(Fts3Table *p, Fts3SegReader *pReader){
|
||||
if( &pReader->aDoclist[pReader->nDoclist]>&pReader->aNode[pReader->nNode]
|
||||
|| pReader->aDoclist[pReader->nDoclist-1]
|
||||
){
|
||||
return SQLITE_CORRUPT;
|
||||
return SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@ -1123,7 +1123,7 @@ int sqlite3Fts3SegReaderCost(
|
||||
}
|
||||
if( nDoc==0 || nByte==0 ){
|
||||
sqlite3_reset(pStmt);
|
||||
return SQLITE_CORRUPT;
|
||||
return SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
|
||||
pCsr->nRowAvg = (int)(((nByte / nDoc) + pgsz) / pgsz);
|
||||
@ -2762,7 +2762,7 @@ int sqlite3Fts3UpdateMethod(
|
||||
if( nArg>1 && rc==SQLITE_OK ){
|
||||
if( bInsertDone==0 ){
|
||||
rc = fts3InsertData(p, apVal, pRowid);
|
||||
if( rc==SQLITE_CONSTRAINT ) rc = SQLITE_CORRUPT;
|
||||
if( rc==SQLITE_CONSTRAINT ) rc = SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
if( rc==SQLITE_OK && (!isRemove || *pRowid!=iRemove) ){
|
||||
rc = fts3PendingTermsDocid(p, *pRowid);
|
||||
|
@ -517,17 +517,17 @@ nodeAcquire(
|
||||
if( pNode && iNode==1 ){
|
||||
pRtree->iDepth = readInt16(pNode->zData);
|
||||
if( pRtree->iDepth>RTREE_MAX_DEPTH ){
|
||||
rc = SQLITE_CORRUPT;
|
||||
rc = SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
}
|
||||
|
||||
/* If no error has occurred so far, check if the "number of entries"
|
||||
** field on the node is too large. If so, set the return code to
|
||||
** SQLITE_CORRUPT.
|
||||
** SQLITE_CORRUPT_VTAB.
|
||||
*/
|
||||
if( pNode && rc==SQLITE_OK ){
|
||||
if( NCELL(pNode)>((pRtree->iNodeSize-4)/pRtree->nBytesPerCell) ){
|
||||
rc = SQLITE_CORRUPT;
|
||||
rc = SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
}
|
||||
|
||||
@ -535,7 +535,7 @@ nodeAcquire(
|
||||
if( pNode!=0 ){
|
||||
nodeHashInsert(pRtree, pNode);
|
||||
}else{
|
||||
rc = SQLITE_CORRUPT;
|
||||
rc = SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
*ppNode = pNode;
|
||||
}else{
|
||||
@ -1062,7 +1062,7 @@ static int nodeRowidIndex(
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}
|
||||
return SQLITE_CORRUPT;
|
||||
return SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1657,7 +1657,7 @@ static int AdjustTree(
|
||||
int iCell;
|
||||
|
||||
if( nodeParentIndex(pRtree, p, &iCell) ){
|
||||
return SQLITE_CORRUPT;
|
||||
return SQLITE_CORRUPT_VTAB;
|
||||
}
|
||||
|
||||
nodeGetCell(pRtree, pParent, iCell, &cell);
|
||||
@ -2329,7 +2329,7 @@ static int fixLeafParent(Rtree *pRtree, RtreeNode *pLeaf){
|
||||
}
|
||||
rc = sqlite3_reset(pRtree->pReadParent);
|
||||
if( rc==SQLITE_OK ) rc = rc2;
|
||||
if( rc==SQLITE_OK && !pChild->pParent ) rc = SQLITE_CORRUPT;
|
||||
if( rc==SQLITE_OK && !pChild->pParent ) rc = SQLITE_CORRUPT_VTAB;
|
||||
pChild = pChild->pParent;
|
||||
}
|
||||
return rc;
|
||||
|
4
main.mk
4
main.mk
@ -55,8 +55,8 @@ LIBOBJ+= alter.o analyze.o attach.o auth.o \
|
||||
backup.o bitvec.o btmutex.o btree.o build.o \
|
||||
callback.o complete.o ctime.o date.o delete.o expr.o fault.o fkey.o \
|
||||
fts3.o fts3_aux.o fts3_expr.o fts3_hash.o fts3_icu.o fts3_porter.o \
|
||||
fts3_snippet.o fts3_tokenizer.o fts3_tokenizer1.o fts3_write.o \
|
||||
func.o global.o hash.o \
|
||||
fts3_snippet.o fts3_tokenizer.o fts3_tokenizer1.o \
|
||||
fts3_write.o func.o global.o hash.o \
|
||||
icu.o insert.o journal.o legacy.o loadext.o \
|
||||
main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \
|
||||
memjournal.o \
|
||||
|
101
manifest
101
manifest
@ -1,7 +1,7 @@
|
||||
C Merge\sthe\slatest\strunk\schanges\sinto\sthe\ssessions\sbranch.
|
||||
D 2011-05-05T15:46:16.843
|
||||
C Merge\sall\sthe\slatest\strunk\schanges\sinto\sthe\ssessions\sbranch,\sespecially\nthe\sdisappearing\sWAL\stransaction\sfix.
|
||||
D 2011-05-19T02:48:46.609
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2
|
||||
F Makefile.in 11dcc00a8d0e5202def00e81732784fb0cc4fe1d
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
F Makefile.vxworks c85ec1d8597fe2f7bc225af12ac1666e21379151
|
||||
F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6
|
||||
@ -61,28 +61,28 @@ F ext/fts2/mkfts2amal.tcl 974d5d438cb3f7c4a652639262f82418c1e4cff0
|
||||
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
|
||||
F ext/fts3/README.tokenizers 998756696647400de63d5ba60e9655036cb966e9
|
||||
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
|
||||
F ext/fts3/fts3.c 73d6718dba1e4ef621ff8a4ac1c22019460c84cc
|
||||
F ext/fts3/fts3.c 18c2a079ba2b9154b7485fd39d1a6d12b5872a76
|
||||
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
||||
F ext/fts3/fts3Int.h 8c2ac39ee17362571c58ab2c4f0667324c31f738
|
||||
F ext/fts3/fts3Int.h 05d145152620e7849c452bd919f2cc3e2d75309f
|
||||
F ext/fts3/fts3_aux.c 9e931f55eed8498dafe7bc1160f10cbb1a652fdf
|
||||
F ext/fts3/fts3_expr.c 5f49e0deaf723724b08100bb3ff40aab02ad0c93
|
||||
F ext/fts3/fts3_hash.c 3c8f6387a4a7f5305588b203fa7c887d753e1f1c
|
||||
F ext/fts3/fts3_hash.h 8331fb2206c609f9fc4c4735b9ab5ad6137c88ec
|
||||
F ext/fts3/fts3_icu.c ac494aed69835008185299315403044664bda295
|
||||
F ext/fts3/fts3_porter.c d61cfd81fb0fd8fbcb25adcaee0ba671aefaa5c2
|
||||
F ext/fts3/fts3_snippet.c a4a3c7d2ab15ca9188e2d9b51a5e3927bf76580d
|
||||
F ext/fts3/fts3_snippet.c 92b40397b28422c35c4127492d7ac6da34d1966a
|
||||
F ext/fts3/fts3_term.c f115f5a5f4298303d3b22fc6c524b8d565c7b950
|
||||
F ext/fts3/fts3_tokenizer.c 055f3dc7369585350b28db1ee0f3b214dca6724d
|
||||
F ext/fts3/fts3_tokenizer.h 13ffd9fcb397fec32a05ef5cd9e0fa659bf3dbd3
|
||||
F ext/fts3/fts3_tokenizer1.c 6e5cbaa588924ac578263a598e4fb9f5c9bb179d
|
||||
F ext/fts3/fts3_write.c 7d6d904b89333448eb968fc82470a74985d0b61e
|
||||
F ext/fts3/fts3_write.c b50181e5ecf484c2f56e98d651424e4b69f96c89
|
||||
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
|
||||
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
|
||||
F ext/icu/README.txt bf8461d8cdc6b8f514c080e4e10dc3b2bbdfefa9
|
||||
F ext/icu/icu.c eb9ae1d79046bd7871aa97ee6da51eb770134b5a
|
||||
F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
|
||||
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
|
||||
F ext/rtree/rtree.c 829c6901a2b065ff93a68d431f9eaba8de7128e0
|
||||
F ext/rtree/rtree.c 2445bec932f58f8f4fe9de49a63bd6bf24db82d6
|
||||
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
|
||||
F ext/rtree/rtree1.test 28e1b8da4da98093ce3210187434dd760a8d89d8
|
||||
F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba
|
||||
@ -112,7 +112,7 @@ F ext/session/sqlite3session.h 665f5591562e3c71eb3d0da26f1a1efae26f7bcf
|
||||
F ext/session/test_session.c 311e5b9228374d0b5780448f289847ff1cf7d388
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F main.mk 352002cedf9e754ec96cfe0a8d1688cdea343fea
|
||||
F main.mk bc31e3b2cfa42337a34fc4509a1b550c0cd5b202
|
||||
F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a
|
||||
F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f
|
||||
F mkextw.sh 4123480947681d9b434a5e7b1ee08135abe409ac
|
||||
@ -127,15 +127,15 @@ F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
|
||||
F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
|
||||
F src/alter.c 280f5c04b11b492703a342222b3de0a999445280
|
||||
F src/analyze.c a425d62e8fa9ebcb4359ab84ff0c62c6563d2e2a
|
||||
F src/attach.c 7f97ca76ef2453440170929531a9c778267c0830
|
||||
F src/attach.c 12c6957996908edc31c96d7c68d4942c2474405f
|
||||
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
||||
F src/backup.c 986c15232757f2873dff35ee3b35cbf935fc573c
|
||||
F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef
|
||||
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
|
||||
F src/btree.c 6a9164af8a2ef4612ee30b253635a9bd8e5e1b1b
|
||||
F src/btree.h 11753dd46597a20702bca8746cb4caa4486a82b5
|
||||
F src/btree.c 975ad691a57eb1fb60f1ec76ad0b6571eace62f9
|
||||
F src/btree.h f5d775cd6cfc7ac32a2535b70e8d2af48ef5f2ce
|
||||
F src/btreeInt.h 67978c014fa4f7cc874032dd3aacadd8db656bc3
|
||||
F src/build.c f09c46c66a1e7668c6ee25c9a2518aaa6842044c
|
||||
F src/build.c 0132bc6631fa617a1d28ef805921f6dbac18a514
|
||||
F src/callback.c 0425c6320730e6d3981acfb9202c1bed9016ad1a
|
||||
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||
F src/ctime.c 7deec4534f3b5a0c3b4a4cbadf809d321f64f9c4
|
||||
@ -145,7 +145,7 @@ F src/expr.c e3cf0957c6b8faaaf7386a3bc69e53c0dc9705be
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c a43ba8a005fb5efd1deeee06853e3a6120d46a91
|
||||
F src/func.c b9117e40975245b8504cf3625d7e321d8d4b63dc
|
||||
F src/global.c 02335177cf6946fe5525c6f0755cf181140debf3
|
||||
F src/global.c 29bfb85611dd816b04f10fba0ca910366e128d38
|
||||
F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
|
||||
F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970
|
||||
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
||||
@ -154,8 +154,8 @@ F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e
|
||||
F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f
|
||||
F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e
|
||||
F src/loadext.c 3ae0d52da013a6326310655be6473fd472347b85
|
||||
F src/main.c 8b97db74cb876bf34ca4fb3720b18e4ffdcf9fd5
|
||||
F src/malloc.c 74c740e8ba22b806cfb980c8c0ddea1cbd54a20e
|
||||
F src/main.c 8206d7970cb858979ec84eea9a5eff2b575849a6
|
||||
F src/malloc.c 591aedb20ae40813f1045f2ef253438a334775d9
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 00bd8265c81abb665c48fea1e0c234eb3b922206
|
||||
F src/mem2.c e307323e86b5da1853d7111b68fd6b84ad6f09cf
|
||||
@ -173,32 +173,32 @@ F src/os.c 22ac61d06e72a0dac900400147333b07b13d8e1d
|
||||
F src/os.h 9dbed8c2b9c1f2f2ebabc09e49829d4777c26bf9
|
||||
F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f
|
||||
F src/os_os2.c 4a75888ba3dfc820ad5e8177025972d74d7f2440
|
||||
F src/os_unix.c 2c67d126874b78eb427371db4793f0e8fbc7448b
|
||||
F src/os_win.c 4271f0bf733c0b45635ddcfb41c935573de8284c
|
||||
F src/pager.c 055239dcdfe12b3f5d97f6f01f85da01e2d6d912
|
||||
F src/os_unix.c 6d4a58d81ad4b782406519f3790202f330e89bb7
|
||||
F src/os_win.c 218b899469e570d46eb8147c2383075f7c026230
|
||||
F src/pager.c 4b2358556c88660a94a4560de95dd728911e00fd
|
||||
F src/pager.h 3f8c783de1d4706b40b1ac15b64f5f896bcc78d1
|
||||
F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58
|
||||
F src/pcache.c 09d38c44ab275db581f7a2f6ff8b9bc7f8c0faaa
|
||||
F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050
|
||||
F src/pcache1.c d548e31beafa792d1994b663a29a5303569efc4e
|
||||
F src/pragma.c 49c90ab27a4339d4b5bc0b03c08cbcf20ed8d454
|
||||
F src/pragma.c 9e778decc3ee9bcaf88904b4a3b0a4360aaf0eab
|
||||
F src/prepare.c e64261559a3187698a3e7e6c8b001a4f4f98dab4
|
||||
F src/printf.c 585a36b6a963df832cfb69505afa3a34ed5ef8a1
|
||||
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
|
||||
F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706
|
||||
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
|
||||
F src/select.c d9d440809025a58547e39f4f268c2a296bfb56ff
|
||||
F src/shell.c 72e7e176bf46d5c6518d15ac4ad6847c4bb5df79
|
||||
F src/sqlite.h.in 628de30f6063695288eadf34c167e49bc34c9828
|
||||
F src/shell.c decd04236a7ef26be5ef46d4ea963044bfad9a48
|
||||
F src/sqlite.h.in b851102bb0840bf6d4dde5d6690c2ad127a65ade
|
||||
F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754
|
||||
F src/sqliteInt.h 1577ac69cb67a1dc0c07974a4e5129b1cde039a3
|
||||
F src/sqliteInt.h 2fb482cff778112e6b2797226f30f3862a627468
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c 7ac64842c86cec2fc1a1d0e5c16d3beb8ad332bf
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
F src/tclsqlite.c fe0da0eb0ebd8d21eec90683b779456e64351de6
|
||||
F src/test1.c e0e4af306b678da05334c2ccaf0377ae8f06e911
|
||||
F src/test1.c 4a1171af201be90c21d64a872e686b1333d9a2cf
|
||||
F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31
|
||||
F src/test3.c 056093cfef69ff4227a6bdb9108564dc7f45e4bc
|
||||
F src/test3.c 124ff9735fb6bb7d41de180d6bac90e7b1509432
|
||||
F src/test4.c d1e5a5e904d4b444cf572391fdcb017638e36ff7
|
||||
F src/test5.c e1a19845625144caf038031234a12185e40d315c
|
||||
F src/test6.c c7256cc21d2409486d094277d5b017e8eced44ba
|
||||
@ -209,7 +209,7 @@ F src/test_async.c 0612a752896fad42d55c3999a5122af10dcf22ad
|
||||
F src/test_autoext.c 30e7bd98ab6d70a62bb9ba572e4c7df347fe645e
|
||||
F src/test_backup.c c129c91127e9b46e335715ae2e75756e25ba27de
|
||||
F src/test_btree.c 47cd771250f09cdc6e12dda5bc71bc0b3abc96e2
|
||||
F src/test_config.c 25a4128c2dc9e1dbebafcb7e8c61d45f09f7fbc3
|
||||
F src/test_config.c 2794d55f27c7faa6c8203b15e634e7103953ddcc
|
||||
F src/test_demovfs.c 938d0f595f8bd310076e1c06cf7885a01ce7ce01
|
||||
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
|
||||
F src/test_func.c cbdec5cededa0761daedde5baf06004a9bf416b5
|
||||
@ -220,8 +220,8 @@ F src/test_intarray.c d879bbf8e4ce085ab966d1f3c896a7c8b4f5fc99
|
||||
F src/test_intarray.h 489edb9068bb926583445cb02589344961054207
|
||||
F src/test_journal.c 785edd54f963aefb3c1628124170a56697c68c70
|
||||
F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e
|
||||
F src/test_malloc.c fd6188b1501c0010fb4241ddc9f0d5ac402c688d
|
||||
F src/test_multiplex.c fdabd793ee7a9642c5a8a470def2347144c46d05
|
||||
F src/test_malloc.c 7ca7be34e0e09ef0ed6619544552ed95732e41f6
|
||||
F src/test_multiplex.c 8e67617b80b532315293761970589581745a52a0
|
||||
F src/test_multiplex.h e99c571bc4968b7a9363b661481f3934bfead61d
|
||||
F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e
|
||||
F src/test_onefile.c 40cf9e212a377a6511469384a64b01e6e34b2eec
|
||||
@ -236,7 +236,7 @@ F src/test_superlock.c 2b97936ca127d13962c3605dbc9a4ef269c424cd
|
||||
F src/test_syscall.c 162c4ec0137a549c009bb9ecab550527743cfc5d
|
||||
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
|
||||
F src/test_thread.c 361ae0a0f1cbf5a28ad0388a258b104017a370c0
|
||||
F src/test_vfs.c 2ed8853c1e51ac6f9ea091f7ce4e0d618bba8b86
|
||||
F src/test_vfs.c 0ac5b2e3da61bc385c1017890687c359746be2fd
|
||||
F src/test_vfstrace.c 2265c9895f350c8d3c39b079998fbe7481505cc1
|
||||
F src/test_wholenumber.c 6129adfbe7c7444f2e60cc785927f3aa74e12290
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
@ -244,25 +244,26 @@ F src/tokenize.c 604607d6813e9551cf5189d899e0a25c12681080
|
||||
F src/trigger.c 144cc18bb701f3286484aae4292a9531f09278c8
|
||||
F src/update.c f66b651c15e42875f36501ec39a968e836ee5586
|
||||
F src/utf.c d83650c3ea08f7407bd9d0839d9885241c209c60
|
||||
F src/util.c 465fe10aabf0ca7d7826a156dab919b0b65c525a
|
||||
F src/util.c 0f33bbbdfcc4a2d8cf20c3b2a16ffc3b57c58a70
|
||||
F src/vacuum.c 05513dca036a1e7848fe18d5ed1265ac0b32365e
|
||||
F src/vdbe.c fa5bfc0c820706a1f78042b134a0f7a388ca9a3e
|
||||
F src/vdbe.c af2e9d0ffd3e111140bc51769f6995834be69e11
|
||||
F src/vdbe.h 44fd57aeed86da0cd31206626c13cdde0e72cc0e
|
||||
F src/vdbeInt.h b95de01246c15499c700ae00cfda0de25c01358a
|
||||
F src/vdbeapi.c 8051038f7674c708f4515ab189fc3ea929e09a4c
|
||||
F src/vdbeaux.c cc95d80b899b75829cb93d260d3f14125a5c26ad
|
||||
F src/vdbeaux.c be135f46ee48b5726fb59ca41224475c1dbe8f8b
|
||||
F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562
|
||||
F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b
|
||||
F src/vdbetrace.c 5d0dc3d5fd54878cc8d6d28eb41deb8d5885b114
|
||||
F src/vtab.c 1491acb3e0a67eafe69134fb65bfa0b7b7e82342
|
||||
F src/wal.c 7334009b396285b658a95a3b6bc6d2b016a1f794
|
||||
F src/wal.h 7a5fbb00114b7f2cd40c7e1003d4c41ce9d26840
|
||||
F src/vtab.c 48dcef8bc757c2e7b488f68b5ddebb1650da2450
|
||||
F src/wal.c de27c34c8016c00be348fc6bed588816557ceb66
|
||||
F src/wal.h 66b40bd91bc29a5be1c88ddd1f5ade8f3f48728a
|
||||
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
|
||||
F src/where.c 55403ce19c506be6a321c7f129aff693d6103db5
|
||||
F test/8_3_names.test b93687beebd17f6ebf812405a6833bae5d1f4199
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
|
||||
F test/all.test 51756962d522e474338e9b2ebb26e7364d4aa125
|
||||
F test/alter.test 4e47fb9ea59348b88fce4e8bb49de530128b104c
|
||||
F test/alter.test a3f570072b53d7c0fe463bab3f5affa8e113c487
|
||||
F test/alter2.test 75f731508f1bf27ba09a6075c66cd02216ba464b
|
||||
F test/alter3.test 8677e48d95536f7a6ed86a1a774744dadcc22b07
|
||||
F test/alter4.test 1e5dd6b951e9f65ca66422edff02e56df82dd403
|
||||
@ -322,7 +323,7 @@ F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
|
||||
F test/capi3c.test bea67403a5e37a4b33230ee4723e315a2ffb31e7
|
||||
F test/capi3d.test cd36571f014f34bdc4421967f6453cbb597d5d16
|
||||
F test/capi3e.test f7408dda65c92b9056199fdc180f893015f83dde
|
||||
F test/cast.test 166951664a0b0a2e0f8fb5997a152490c6363932
|
||||
F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3
|
||||
F test/check.test db2b29d557544347d28e25b8406f5d5ecc3d1bc3
|
||||
F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91
|
||||
F test/collate1.test e3eaa48c21e150814be1a7b852d2a8af24458d04
|
||||
@ -389,6 +390,7 @@ F test/e_resolve.test dcce9308fb13b934ce29591105d031d3e14fbba6
|
||||
F test/e_select.test bf385ae3aa0f014c4933ae66fd3e1302138493eb
|
||||
F test/e_select2.test 5c3d3da19c7b3e90ae444579db2b70098599ab92
|
||||
F test/e_update.test 963d6876064e65f318d1c93aaed36a02b9b389bf
|
||||
F test/e_uri.test 9ce11319fb9b271bf7392027f913f7830e93e7a7
|
||||
F test/e_vacuum.test 6c09c2af7f2f140518f371c5342100118f779dcf
|
||||
F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
|
||||
F test/enc2.test 6d91a5286f59add0cfcbb2d0da913b76f2242398
|
||||
@ -400,7 +402,7 @@ F test/exclusive.test 53e1841b422e554cecf0160f937c473d6d0e3062
|
||||
F test/exclusive2.test 343d55130c12c67b8bf10407acec043a6c26c86b
|
||||
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
|
||||
F test/exists.test 5e2d64b4eb5a9d08876599bdae2e1213d2d12e2a
|
||||
F test/expr.test 19e8ac40313e2282a47b586d11c4892040990d3a
|
||||
F test/expr.test 67c9fd6f8f829e239dc8b0f4a08a73c08b09196d
|
||||
F test/fallocate.test 43dc34b8c24be6baffadc3b4401ee15710ce83c6
|
||||
F test/filectrl.test 97003734290887566e01dded09dc9e99cb937e9e
|
||||
F test/filefmt.test f178cfc29501a14565954c961b226e61877dd32c
|
||||
@ -467,7 +469,7 @@ F test/fts3b.test e93bbb653e52afde110ad53bbd793f14fe7a8984
|
||||
F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958
|
||||
F test/fts3comp1.test a0f5b16a2df44dd0b15751787130af2183167c0c
|
||||
F test/fts3conf.test 8e65ea56f88ced6cdd2252bdddb1a8327ae5af7e
|
||||
F test/fts3corrupt.test 7890cc202406858386ddf390a879dcf80bc10abf
|
||||
F test/fts3corrupt.test 7b0f91780ca36118d73324ec803187208ad33b32
|
||||
F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba
|
||||
F test/fts3cov.test e0fb00d8b715ddae4a94c305992dfc3ef70353d7
|
||||
F test/fts3d.test 95fb3c862cbc4297c93fceb9a635543744e9ef52
|
||||
@ -598,10 +600,10 @@ F test/misc5.test 45b2e3ed5f79af2b4f38ae362eaf4c49674575bd
|
||||
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
|
||||
F test/misc7.test 29032efcd3d826fbd409e2a7af873e7939f4a4e3
|
||||
F test/misuse.test 30b3a458e5a70c31e74c291937b6c82204c59f33
|
||||
F test/multiplex.test a88f3e2c16e567e72be7296195c59fbdd6a8d3d4
|
||||
F test/multiplex.test 7a8a50c8ed72dfcf4db9ebae977f7a63184639d8
|
||||
F test/mutex1.test 78b2b9bb320e51d156c4efdb71b99b051e7a4b41
|
||||
F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
|
||||
F test/nan.test a44e04df1486fcfb02d32468cbcd3c8e1e433723
|
||||
F test/nan.test dc212a22b36109fd1ae37154292444ef249c5ec2
|
||||
F test/notify1.test 8433bc74bd952fb8a6e3f8d7a4c2b28dfd69e310
|
||||
F test/notify2.test 195a467e021f74197be2c4fb02d6dee644b8d8db
|
||||
F test/notify3.test d60923e186e0900f4812a845fcdfd8eea096e33a
|
||||
@ -609,7 +611,7 @@ F test/notnull.test cc7c78340328e6112a13c3e311a9ab3127114347
|
||||
F test/null.test a8b09b8ed87852742343b33441a9240022108993
|
||||
F test/openv2.test af02ed0a9cbc0d2a61b8f35171d4d117e588e4ec
|
||||
F test/oserror.test 498d8337e9d15543eb7b004fef8594bf204ff43c
|
||||
F test/pager1.test d8672fd0af5f4f9b99b06283d00f01547809bebe
|
||||
F test/pager1.test 8baf4470b29511503abcaf1f17d16b16462e4d54
|
||||
F test/pager2.test 745b911dde3d1f24ae0870bd433dfa83d7c658c1
|
||||
F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
|
||||
F test/pagerfault.test 9de4d3e0c59970b4c6cb8dac511fa242f335d8a7
|
||||
@ -700,7 +702,7 @@ F test/tclsqlite.test 1ce9b6340d6d412420634e129a2e3722c651056a
|
||||
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
|
||||
F test/temptable.test f42121a0d29a62f00f93274464164177ab1cc24a
|
||||
F test/temptrigger.test b0273db072ce5f37cf19140ceb1f0d524bbe9f05
|
||||
F test/tester.tcl cf301cdb35f20378b086849acd26a4574187183f
|
||||
F test/tester.tcl 1949b4af9701daaca189fd5d53a6e48173c162af
|
||||
F test/thread001.test a3e6a7254d1cb057836cb3145b60c10bf5b7e60f
|
||||
F test/thread002.test afd20095e6e845b405df4f2c920cb93301ca69db
|
||||
F test/thread003.test b824d4f52b870ae39fc5bae4d8070eca73085dca
|
||||
@ -714,6 +716,7 @@ F test/threadtest2.c ace893054fa134af3fc8d6e7cfecddb8e3acefb9
|
||||
F test/threadtest3.c 0ed13e09690f6204d7455fac3b0e8ece490f6eef
|
||||
F test/tkt-02a8e81d44.test 58494de77be2cf249228ada3f313fa399821c6ab
|
||||
F test/tkt-26ff0c2d1e.test 888324e751512972c6e0d1a09df740d8f5aaf660
|
||||
F test/tkt-2d1a5c67d.test 39d2368072315923021700a216379fcf23ac3a5c
|
||||
F test/tkt-2ea2425d34.test 1cf13e6f75d149b3209a0cb32927a82d3d79fb28
|
||||
F test/tkt-31338dca7e.test 5741cd48de500347a437ba1be58c8335e83c5a5e
|
||||
F test/tkt-313723c356.test c47f8a9330523e6f35698bf4489bcb29609b53ac
|
||||
@ -812,13 +815,13 @@ F test/tkt3793.test 754b73f0e6a9349c70dc57e522cf3247272ecd5d
|
||||
F test/tkt3810.test 90fa0635dfa7da9680c8cd3513350a49b3a8ae12
|
||||
F test/tkt3824.test 150aa00bb6220672e5f0eb14dc8eaa36750425f0
|
||||
F test/tkt3832.test 2300d10d57562b89875b72148338ac3e14f8847d
|
||||
F test/tkt3838.test f956f0719b5f805b12dd1dbf19f19d298bacebc3
|
||||
F test/tkt3838.test d8490365a1c473d214f7878007e543410cbb715f
|
||||
F test/tkt3841.test 4659845bc53f809a5932c61c6ce8c5bb9d6b947f
|
||||
F test/tkt3871.test 43ecbc8d90dc83908e2a454aef345acc9d160c6f
|
||||
F test/tkt3879.test 2ad5bef2c87e9991ce941e054c31abe26ef7fb90
|
||||
F test/tkt3911.test 74cd324f3ba653040cc6d94cc4857b290d12d633
|
||||
F test/tkt3918.test e6cdf6bfcfe9ba939d86a4238a9dc55d6eec5d42
|
||||
F test/tkt3922.test 022ace32c049e3964f68492c12eb803e8e4856d8
|
||||
F test/tkt3922.test f26be40ab4fe6c00795629bd2006d96e270d9b1a
|
||||
F test/tkt3929.test 75a862e45bcb39e9a7944c89b92afa531304afca
|
||||
F test/tkt3935.test e15261fedb9e30a4305a311da614a5d8e693c767
|
||||
F test/tkt3992.test f3e7d548ac26f763b47bc0f750da3d03c81071da
|
||||
@ -851,6 +854,7 @@ F test/unique.test 083c7fff74695bcc27a71d75699deba3595bc9c2
|
||||
F test/unixexcl.test 9d80a54d86d2261f660758928959368ffc36151e
|
||||
F test/unordered.test e81169ce2a8f31b2c6b66af691887e1376ab3ced
|
||||
F test/update.test 8bc86fd7ef1a00014f76dc6a6a7c974df4aef172
|
||||
F test/uri.test 2d08a6f77bf93ca925743a65802c4aa23aaaf373
|
||||
F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
|
||||
F test/vacuum.test 29b60e8cc9e573b39676df6c4a75fe9e02d04a09
|
||||
F test/vacuum2.test 91a84c9b08adfc4472097d2e8deb0150214e0e76
|
||||
@ -882,6 +886,7 @@ F test/wal3.test 5c396cc22497244d627306f4c1d360167353f8dd
|
||||
F test/wal4.test 3404b048fa5e10605facaf70384e6d2943412e30
|
||||
F test/wal5.test 1bbfaa316dc2a1d0d1fac3f4500c38a90055a41b
|
||||
F test/wal6.test 07aa31ca8892d0527f2c5c5a9a2a87aa421dfaa8
|
||||
F test/wal7.test 09bc8de3d11949571d6f7a4188b308059cec27e5
|
||||
F test/wal_common.tcl a98f17fba96206122eff624db0ab13ec377be4fe
|
||||
F test/walbak.test 4df1c7369da0301caeb9a48fa45997fd592380e4
|
||||
F test/walbig.test e882bc1d014afffbfa2b6ba36e0f07d30a633ad0
|
||||
@ -944,7 +949,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
|
||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||
P b91b4c31fe311b292044c9c747feba294ffce25c 930be6a1bdec8c150caafd790973f7a401fc1970
|
||||
R 13217a0634732c3fc1250bf1a2936d3d
|
||||
P 6883580e6c8973010a42d1d2c5bde04c6b2f4eb7 67bf1c9a888b0d84d252d6c4c754c2c51994d208
|
||||
R f15f9213bb9ad0f88efa9254eb2387a3
|
||||
U drh
|
||||
Z f29377c78641e183f6acae5b288b38b3
|
||||
Z 1a1886a9d9151866e45101a5d0e49b24
|
||||
|
@ -1 +1 @@
|
||||
6883580e6c8973010a42d1d2c5bde04c6b2f4eb7
|
||||
5b1b536cf828850d0e8ac2ab08e8696082715877
|
18
src/attach.c
18
src/attach.c
@ -70,8 +70,12 @@ static void attachFunc(
|
||||
sqlite3 *db = sqlite3_context_db_handle(context);
|
||||
const char *zName;
|
||||
const char *zFile;
|
||||
char *zPath = 0;
|
||||
char *zErr = 0;
|
||||
unsigned int flags;
|
||||
Db *aNew;
|
||||
char *zErrDyn = 0;
|
||||
sqlite3_vfs *pVfs;
|
||||
|
||||
UNUSED_PARAMETER(NotUsed);
|
||||
|
||||
@ -124,8 +128,18 @@ static void attachFunc(
|
||||
** it to obtain the database schema. At this point the schema may
|
||||
** or may not be initialised.
|
||||
*/
|
||||
rc = sqlite3BtreeOpen(zFile, db, &aNew->pBt, 0,
|
||||
db->openFlags | SQLITE_OPEN_MAIN_DB);
|
||||
flags = db->openFlags;
|
||||
rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr);
|
||||
if( rc!=SQLITE_OK ){
|
||||
if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
|
||||
sqlite3_result_error(context, zErr, -1);
|
||||
sqlite3_free(zErr);
|
||||
return;
|
||||
}
|
||||
assert( pVfs );
|
||||
flags |= SQLITE_OPEN_MAIN_DB;
|
||||
rc = sqlite3BtreeOpen(pVfs, zPath, db, &aNew->pBt, 0, flags);
|
||||
sqlite3_free( zPath );
|
||||
db->nDb++;
|
||||
if( rc==SQLITE_CONSTRAINT ){
|
||||
rc = SQLITE_ERROR;
|
||||
|
10
src/btree.c
10
src/btree.c
@ -788,6 +788,7 @@ static void ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent, int *pRC){
|
||||
*pRC = SQLITE_CORRUPT_BKPT;
|
||||
goto ptrmap_exit;
|
||||
}
|
||||
assert( offset <= (int)pBt->usableSize-5 );
|
||||
pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage);
|
||||
|
||||
if( eType!=pPtrmap[offset] || get4byte(&pPtrmap[offset+1])!=parent ){
|
||||
@ -827,6 +828,11 @@ static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){
|
||||
pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage);
|
||||
|
||||
offset = PTRMAP_PTROFFSET(iPtrmap, key);
|
||||
if( offset<0 ){
|
||||
sqlite3PagerUnref(pDbPage);
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
assert( offset <= (int)pBt->usableSize-5 );
|
||||
assert( pEType!=0 );
|
||||
*pEType = pPtrmap[offset];
|
||||
if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]);
|
||||
@ -1688,13 +1694,13 @@ static int btreeInvokeBusyHandler(void *pArg){
|
||||
** to problems with locking.
|
||||
*/
|
||||
int sqlite3BtreeOpen(
|
||||
sqlite3_vfs *pVfs, /* VFS to use for this b-tree */
|
||||
const char *zFilename, /* Name of the file containing the BTree database */
|
||||
sqlite3 *db, /* Associated database handle */
|
||||
Btree **ppBtree, /* Pointer to new Btree object written here */
|
||||
int flags, /* Options */
|
||||
int vfsFlags /* Flags passed through to sqlite3_vfs.xOpen() */
|
||||
){
|
||||
sqlite3_vfs *pVfs; /* The VFS to use for this btree */
|
||||
BtShared *pBt = 0; /* Shared part of btree structure */
|
||||
Btree *p; /* Handle to return */
|
||||
sqlite3_mutex *mutexOpen = 0; /* Prevents a race condition. Ticket #3537 */
|
||||
@ -1716,6 +1722,7 @@ int sqlite3BtreeOpen(
|
||||
#endif
|
||||
|
||||
assert( db!=0 );
|
||||
assert( pVfs!=0 );
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
assert( (flags&0xff)==flags ); /* flags fit in 8 bits */
|
||||
|
||||
@ -1734,7 +1741,6 @@ int sqlite3BtreeOpen(
|
||||
if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (isMemdb || isTempDb) ){
|
||||
vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB;
|
||||
}
|
||||
pVfs = db->pVfs;
|
||||
p = sqlite3MallocZero(sizeof(Btree));
|
||||
if( !p ){
|
||||
return SQLITE_NOMEM;
|
||||
|
@ -42,6 +42,7 @@ typedef struct BtShared BtShared;
|
||||
|
||||
|
||||
int sqlite3BtreeOpen(
|
||||
sqlite3_vfs *pVfs, /* VFS to use with this b-tree */
|
||||
const char *zFilename, /* Name of database file to open */
|
||||
sqlite3 *db, /* Associated database connection */
|
||||
Btree **ppBtree, /* Return open Btree* here */
|
||||
|
@ -3443,7 +3443,7 @@ int sqlite3OpenTempDatabase(Parse *pParse){
|
||||
SQLITE_OPEN_DELETEONCLOSE |
|
||||
SQLITE_OPEN_TEMP_DB;
|
||||
|
||||
rc = sqlite3BtreeOpen(0, db, &pBt, 0, flags);
|
||||
rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pBt, 0, flags);
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3ErrorMsg(pParse, "unable to open a temporary database "
|
||||
"file for storing temporary tables");
|
||||
|
@ -129,7 +129,9 @@ const unsigned char sqlite3CtypeMap[256] = {
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef SQLITE_USE_URI
|
||||
# define SQLITE_USE_URI 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The following singleton contains the global configuration for
|
||||
@ -139,6 +141,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
|
||||
SQLITE_DEFAULT_MEMSTATUS, /* bMemstat */
|
||||
1, /* bCoreMutex */
|
||||
SQLITE_THREADSAFE==1, /* bFullMutex */
|
||||
SQLITE_USE_URI, /* bOpenUri */
|
||||
0x7ffffffe, /* mxStrlen */
|
||||
100, /* szLookaside */
|
||||
500, /* nLookaside */
|
||||
|
292
src/main.c
292
src/main.c
@ -426,6 +426,11 @@ int sqlite3_config(int op, ...){
|
||||
break;
|
||||
}
|
||||
|
||||
case SQLITE_CONFIG_URI: {
|
||||
sqlite3GlobalConfig.bOpenUri = va_arg(ap, int);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
rc = SQLITE_ERROR;
|
||||
break;
|
||||
@ -1806,6 +1811,236 @@ int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){
|
||||
return oldLimit; /* IMP: R-53341-35419 */
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is used to parse both URIs and non-URI filenames passed by the
|
||||
** user to API functions sqlite3_open() or sqlite3_open_v2(), and for database
|
||||
** URIs specified as part of ATTACH statements.
|
||||
**
|
||||
** The first argument to this function is the name of the VFS to use (or
|
||||
** a NULL to signify the default VFS) if the URI does not contain a "vfs=xxx"
|
||||
** query parameter. The second argument contains the URI (or non-URI filename)
|
||||
** itself. When this function is called the *pFlags variable should contain
|
||||
** the default flags to open the database handle with. The value stored in
|
||||
** *pFlags may be updated before returning if the URI filename contains
|
||||
** "cache=xxx" or "mode=xxx" query parameters.
|
||||
**
|
||||
** If successful, SQLITE_OK is returned. In this case *ppVfs is set to point to
|
||||
** the VFS that should be used to open the database file. *pzFile is set to
|
||||
** point to a buffer containing the name of the file to open. It is the
|
||||
** responsibility of the caller to eventually call sqlite3_free() to release
|
||||
** this buffer.
|
||||
**
|
||||
** If an error occurs, then an SQLite error code is returned and *pzErrMsg
|
||||
** may be set to point to a buffer containing an English language error
|
||||
** message. It is the responsibility of the caller to eventually release
|
||||
** this buffer by calling sqlite3_free().
|
||||
*/
|
||||
int sqlite3ParseUri(
|
||||
const char *zDefaultVfs, /* VFS to use if no "vfs=xxx" query option */
|
||||
const char *zUri, /* Nul-terminated URI to parse */
|
||||
unsigned int *pFlags, /* IN/OUT: SQLITE_OPEN_XXX flags */
|
||||
sqlite3_vfs **ppVfs, /* OUT: VFS to use */
|
||||
char **pzFile, /* OUT: Filename component of URI */
|
||||
char **pzErrMsg /* OUT: Error message (if rc!=SQLITE_OK) */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
unsigned int flags = *pFlags;
|
||||
const char *zVfs = zDefaultVfs;
|
||||
char *zFile;
|
||||
char c;
|
||||
int nUri = sqlite3Strlen30(zUri);
|
||||
|
||||
assert( *pzErrMsg==0 );
|
||||
|
||||
if( ((flags & SQLITE_OPEN_URI) || sqlite3GlobalConfig.bOpenUri)
|
||||
&& nUri>=5 && memcmp(zUri, "file:", 5)==0
|
||||
){
|
||||
char *zOpt;
|
||||
int eState; /* Parser state when parsing URI */
|
||||
int iIn; /* Input character index */
|
||||
int iOut = 0; /* Output character index */
|
||||
int nByte = nUri+2; /* Bytes of space to allocate */
|
||||
|
||||
/* Make sure the SQLITE_OPEN_URI flag is set to indicate to the VFS xOpen
|
||||
** method that there may be extra parameters following the file-name. */
|
||||
flags |= SQLITE_OPEN_URI;
|
||||
|
||||
for(iIn=0; iIn<nUri; iIn++) nByte += (zUri[iIn]=='&');
|
||||
zFile = sqlite3_malloc(nByte);
|
||||
if( !zFile ) return SQLITE_NOMEM;
|
||||
|
||||
/* Discard the scheme and authority segments of the URI. */
|
||||
if( zUri[5]=='/' && zUri[6]=='/' ){
|
||||
iIn = 7;
|
||||
while( zUri[iIn] && zUri[iIn]!='/' ) iIn++;
|
||||
|
||||
if( iIn!=7 && (iIn!=16 || memcmp("localhost", &zUri[7], 9)) ){
|
||||
*pzErrMsg = sqlite3_mprintf("invalid uri authority: %.*s",
|
||||
iIn-7, &zUri[7]);
|
||||
rc = SQLITE_ERROR;
|
||||
goto parse_uri_out;
|
||||
}
|
||||
}else{
|
||||
iIn = 5;
|
||||
}
|
||||
|
||||
/* Copy the filename and any query parameters into the zFile buffer.
|
||||
** Decode %HH escape codes along the way.
|
||||
**
|
||||
** Within this loop, variable eState may be set to 0, 1 or 2, depending
|
||||
** on the parsing context. As follows:
|
||||
**
|
||||
** 0: Parsing file-name.
|
||||
** 1: Parsing name section of a name=value query parameter.
|
||||
** 2: Parsing value section of a name=value query parameter.
|
||||
*/
|
||||
eState = 0;
|
||||
while( (c = zUri[iIn])!=0 && c!='#' ){
|
||||
iIn++;
|
||||
if( c=='%'
|
||||
&& sqlite3Isxdigit(zUri[iIn])
|
||||
&& sqlite3Isxdigit(zUri[iIn+1])
|
||||
){
|
||||
int octet = (sqlite3HexToInt(zUri[iIn++]) << 4);
|
||||
octet += sqlite3HexToInt(zUri[iIn++]);
|
||||
|
||||
assert( octet>=0 && octet<256 );
|
||||
if( octet==0 ){
|
||||
/* This branch is taken when "%00" appears within the URI. In this
|
||||
** case we ignore all text in the remainder of the path, name or
|
||||
** value currently being parsed. So ignore the current character
|
||||
** and skip to the next "?", "=" or "&", as appropriate. */
|
||||
while( (c = zUri[iIn])!=0 && c!='#'
|
||||
&& (eState!=0 || c!='?')
|
||||
&& (eState!=1 || (c!='=' && c!='&'))
|
||||
&& (eState!=2 || c!='&')
|
||||
){
|
||||
iIn++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
c = octet;
|
||||
}else if( eState==1 && (c=='&' || c=='=') ){
|
||||
if( zFile[iOut-1]==0 ){
|
||||
/* An empty option name. Ignore this option altogether. */
|
||||
while( zUri[iIn] && zUri[iIn]!='#' && zUri[iIn-1]!='&' ) iIn++;
|
||||
continue;
|
||||
}
|
||||
if( c=='&' ){
|
||||
zFile[iOut++] = '\0';
|
||||
}else{
|
||||
eState = 2;
|
||||
}
|
||||
c = 0;
|
||||
}else if( (eState==0 && c=='?') || (eState==2 && c=='&') ){
|
||||
c = 0;
|
||||
eState = 1;
|
||||
}
|
||||
zFile[iOut++] = c;
|
||||
}
|
||||
if( eState==1 ) zFile[iOut++] = '\0';
|
||||
zFile[iOut++] = '\0';
|
||||
zFile[iOut++] = '\0';
|
||||
|
||||
/* Check if there were any options specified that should be interpreted
|
||||
** here. Options that are interpreted here include "vfs" and those that
|
||||
** correspond to flags that may be passed to the sqlite3_open_v2()
|
||||
** method. */
|
||||
zOpt = &zFile[sqlite3Strlen30(zFile)+1];
|
||||
while( zOpt[0] ){
|
||||
int nOpt = sqlite3Strlen30(zOpt);
|
||||
char *zVal = &zOpt[nOpt+1];
|
||||
int nVal = sqlite3Strlen30(zVal);
|
||||
|
||||
if( nOpt==3 && memcmp("vfs", zOpt, 3)==0 ){
|
||||
zVfs = zVal;
|
||||
}else{
|
||||
struct OpenMode {
|
||||
const char *z;
|
||||
int mode;
|
||||
} *aMode = 0;
|
||||
char *zModeType;
|
||||
int mask;
|
||||
int limit;
|
||||
|
||||
if( nOpt==5 && memcmp("cache", zOpt, 5)==0 ){
|
||||
static struct OpenMode aCacheMode[] = {
|
||||
{ "shared", SQLITE_OPEN_SHAREDCACHE },
|
||||
{ "private", SQLITE_OPEN_PRIVATECACHE },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
mask = SQLITE_OPEN_SHAREDCACHE|SQLITE_OPEN_PRIVATECACHE;
|
||||
aMode = aCacheMode;
|
||||
limit = mask;
|
||||
zModeType = "cache";
|
||||
}
|
||||
if( nOpt==4 && memcmp("mode", zOpt, 4)==0 ){
|
||||
static struct OpenMode aOpenMode[] = {
|
||||
{ "ro", SQLITE_OPEN_READONLY },
|
||||
{ "rw", SQLITE_OPEN_READWRITE },
|
||||
{ "rwc", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
mask = SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
|
||||
aMode = aOpenMode;
|
||||
limit = mask & flags;
|
||||
zModeType = "access";
|
||||
}
|
||||
|
||||
if( aMode ){
|
||||
int i;
|
||||
int mode = 0;
|
||||
for(i=0; aMode[i].z; i++){
|
||||
const char *z = aMode[i].z;
|
||||
if( nVal==sqlite3Strlen30(z) && 0==memcmp(zVal, z, nVal) ){
|
||||
mode = aMode[i].mode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( mode==0 ){
|
||||
*pzErrMsg = sqlite3_mprintf("no such %s mode: %s", zModeType, zVal);
|
||||
rc = SQLITE_ERROR;
|
||||
goto parse_uri_out;
|
||||
}
|
||||
if( mode>limit ){
|
||||
*pzErrMsg = sqlite3_mprintf("%s mode not allowed: %s",
|
||||
zModeType, zVal);
|
||||
rc = SQLITE_PERM;
|
||||
goto parse_uri_out;
|
||||
}
|
||||
flags = (flags & ~mask) | mode;
|
||||
}
|
||||
}
|
||||
|
||||
zOpt = &zVal[nVal+1];
|
||||
}
|
||||
|
||||
}else{
|
||||
zFile = sqlite3_malloc(nUri+2);
|
||||
if( !zFile ) return SQLITE_NOMEM;
|
||||
memcpy(zFile, zUri, nUri);
|
||||
zFile[nUri] = '\0';
|
||||
zFile[nUri+1] = '\0';
|
||||
}
|
||||
|
||||
*ppVfs = sqlite3_vfs_find(zVfs);
|
||||
if( *ppVfs==0 ){
|
||||
*pzErrMsg = sqlite3_mprintf("no such vfs: %s", zVfs);
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
parse_uri_out:
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_free(zFile);
|
||||
zFile = 0;
|
||||
}
|
||||
*pFlags = flags;
|
||||
*pzFile = zFile;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** This routine does the work of opening a database on behalf of
|
||||
** sqlite3_open() and sqlite3_open16(). The database filename "zFilename"
|
||||
@ -1814,12 +2049,14 @@ int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){
|
||||
static int openDatabase(
|
||||
const char *zFilename, /* Database filename UTF-8 encoded */
|
||||
sqlite3 **ppDb, /* OUT: Returned database handle */
|
||||
unsigned flags, /* Operational flags */
|
||||
unsigned int flags, /* Operational flags */
|
||||
const char *zVfs /* Name of the VFS to use */
|
||||
){
|
||||
sqlite3 *db;
|
||||
int rc;
|
||||
int isThreadsafe;
|
||||
sqlite3 *db; /* Store allocated handle here */
|
||||
int rc; /* Return code */
|
||||
int isThreadsafe; /* True for threadsafe connections */
|
||||
char *zOpen = 0; /* Filename argument to pass to BtreeOpen() */
|
||||
char *zErrMsg = 0; /* Error message from sqlite3ParseUri() */
|
||||
|
||||
*ppDb = 0;
|
||||
#ifndef SQLITE_OMIT_AUTOINIT
|
||||
@ -1843,7 +2080,7 @@ static int openDatabase(
|
||||
testcase( (1<<(flags&7))==0x02 ); /* READONLY */
|
||||
testcase( (1<<(flags&7))==0x04 ); /* READWRITE */
|
||||
testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */
|
||||
if( ((1<<(flags&7)) & 0x46)==0 ) return SQLITE_MISUSE;
|
||||
if( ((1<<(flags&7)) & 0x46)==0 ) return SQLITE_MISUSE_BKPT;
|
||||
|
||||
if( sqlite3GlobalConfig.bCoreMutex==0 ){
|
||||
isThreadsafe = 0;
|
||||
@ -1924,13 +2161,6 @@ static int openDatabase(
|
||||
sqlite3HashInit(&db->aModule);
|
||||
#endif
|
||||
|
||||
db->pVfs = sqlite3_vfs_find(zVfs);
|
||||
if( !db->pVfs ){
|
||||
rc = SQLITE_ERROR;
|
||||
sqlite3Error(db, rc, "no such vfs: %s", zVfs);
|
||||
goto opendb_out;
|
||||
}
|
||||
|
||||
/* 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.
|
||||
@ -1953,9 +2183,18 @@ static int openDatabase(
|
||||
createCollation(db, "NOCASE", SQLITE_UTF8, SQLITE_COLL_NOCASE, 0,
|
||||
nocaseCollatingFunc, 0);
|
||||
|
||||
/* Open the backend database driver */
|
||||
/* Parse the filename/URI argument. */
|
||||
db->openFlags = flags;
|
||||
rc = sqlite3BtreeOpen(zFilename, db, &db->aDb[0].pBt, 0,
|
||||
rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg);
|
||||
if( rc!=SQLITE_OK ){
|
||||
if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
|
||||
sqlite3Error(db, rc, zErrMsg ? "%s" : 0, zErrMsg);
|
||||
sqlite3_free(zErrMsg);
|
||||
goto opendb_out;
|
||||
}
|
||||
|
||||
/* Open the backend database driver */
|
||||
rc = sqlite3BtreeOpen(db->pVfs, zOpen, db, &db->aDb[0].pBt, 0,
|
||||
flags | SQLITE_OPEN_MAIN_DB);
|
||||
if( rc!=SQLITE_OK ){
|
||||
if( rc==SQLITE_IOERR_NOMEM ){
|
||||
@ -2048,6 +2287,7 @@ static int openDatabase(
|
||||
sqlite3_wal_autocheckpoint(db, SQLITE_DEFAULT_WAL_AUTOCHECKPOINT);
|
||||
|
||||
opendb_out:
|
||||
sqlite3_free(zOpen);
|
||||
if( db ){
|
||||
assert( db->mutex!=0 || isThreadsafe==0 || sqlite3GlobalConfig.bFullMutex==0 );
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
@ -2079,7 +2319,7 @@ int sqlite3_open_v2(
|
||||
int flags, /* Flags */
|
||||
const char *zVfs /* Name of VFS module to use */
|
||||
){
|
||||
return openDatabase(filename, ppDb, flags, zVfs);
|
||||
return openDatabase(filename, ppDb, (unsigned int)flags, zVfs);
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
@ -2689,3 +2929,25 @@ int sqlite3_test_control(int op, ...){
|
||||
#endif /* SQLITE_OMIT_BUILTIN_TEST */
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** This is a utility routine, useful to VFS implementations, that checks
|
||||
** to see if a database file was a URI that contained a specific query
|
||||
** parameter, and if so obtains the value of the query parameter.
|
||||
**
|
||||
** The zFilename argument is the filename pointer passed into the xOpen()
|
||||
** method of a VFS implementation. The zParam argument is the name of the
|
||||
** query parameter we seek. This routine returns the value of the zParam
|
||||
** parameter if it exists. If the parameter does not exist, this routine
|
||||
** returns a NULL pointer.
|
||||
*/
|
||||
const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam){
|
||||
zFilename += sqlite3Strlen30(zFilename) + 1;
|
||||
while( zFilename[0] ){
|
||||
int x = strcmp(zFilename, zParam);
|
||||
zFilename += sqlite3Strlen30(zFilename) + 1;
|
||||
if( x==0 ) return zFilename;
|
||||
zFilename += sqlite3Strlen30(zFilename) + 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -533,7 +533,7 @@ void *sqlite3Realloc(void *pOld, int nBytes){
|
||||
nDiff = nNew - nOld;
|
||||
if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >=
|
||||
mem0.alarmThreshold-nDiff ){
|
||||
sqlite3MallocAlarm(nNew-nOld);
|
||||
sqlite3MallocAlarm(nDiff);
|
||||
}
|
||||
assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) );
|
||||
assert( sqlite3MemdebugNoType(pOld, ~MEMTYPE_HEAP) );
|
||||
@ -544,7 +544,7 @@ void *sqlite3Realloc(void *pOld, int nBytes){
|
||||
}
|
||||
if( pNew ){
|
||||
nNew = sqlite3MallocSize(pNew);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nDiff);
|
||||
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
|
||||
}
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
}else{
|
||||
|
@ -3769,6 +3769,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
|
||||
(u32)sStat.st_ino, (u32)sStat.st_dev);
|
||||
#else
|
||||
sqlite3_snprintf(nShmFilename, zShmFilename, "%s-shm", pDbFd->zPath);
|
||||
sqlite3FileSuffix3(pDbFd->zPath, zShmFilename);
|
||||
#endif
|
||||
pShmNode->h = -1;
|
||||
pDbFd->pInode->pShmNode = pShmNode;
|
||||
@ -4802,6 +4803,11 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
|
||||
** corresponding database file and sets *pMode to this value. Whenever
|
||||
** possible, WAL and journal files are created using the same permissions
|
||||
** as the associated database file.
|
||||
**
|
||||
** If the SQLITE_ENABLE_8_3_NAMES option is enabled, then the
|
||||
** original filename is unavailable. But 8_3_NAMES is only used for
|
||||
** FAT filesystems and permissions do not matter there, so just use
|
||||
** the default permissions.
|
||||
*/
|
||||
static int findCreateFileMode(
|
||||
const char *zPath, /* Path of file (possibly) being created */
|
||||
@ -4809,6 +4815,7 @@ static int findCreateFileMode(
|
||||
mode_t *pMode /* OUT: Permissions to open file with */
|
||||
){
|
||||
int rc = SQLITE_OK; /* Return Code */
|
||||
*pMode = SQLITE_DEFAULT_FILE_PERMISSIONS;
|
||||
if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
|
||||
char zDb[MAX_PATHNAME+1]; /* Database file path */
|
||||
int nDb; /* Number of valid bytes in zDb */
|
||||
@ -4820,15 +4827,15 @@ static int findCreateFileMode(
|
||||
**
|
||||
** "<path to db>-journal"
|
||||
** "<path to db>-wal"
|
||||
** "<path to db>-journal-NNNN"
|
||||
** "<path to db>-wal-NNNN"
|
||||
** "<path to db>-journalNN"
|
||||
** "<path to db>-walNN"
|
||||
**
|
||||
** where NNNN is a 4 digit decimal number. The NNNN naming schemes are
|
||||
** where NN is a 4 digit decimal number. The NN naming schemes are
|
||||
** used by the test_multiplex.c module.
|
||||
*/
|
||||
nDb = sqlite3Strlen30(zPath) - 1;
|
||||
while( nDb>0 && zPath[nDb]!='l' ) nDb--;
|
||||
nDb -= ((flags & SQLITE_OPEN_WAL) ? 3 : 7);
|
||||
while( nDb>0 && zPath[nDb]!='-' ) nDb--;
|
||||
if( nDb==0 ) return SQLITE_OK;
|
||||
memcpy(zDb, zPath, nDb);
|
||||
zDb[nDb] = '\0';
|
||||
|
||||
@ -4839,8 +4846,6 @@ static int findCreateFileMode(
|
||||
}
|
||||
}else if( flags & SQLITE_OPEN_DELETEONCLOSE ){
|
||||
*pMode = 0600;
|
||||
}else{
|
||||
*pMode = SQLITE_DEFAULT_FILE_PERMISSIONS;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
@ -1570,6 +1570,7 @@ static int winOpenSharedMemory(winFile *pDbFd){
|
||||
memset(pNew, 0, sizeof(*pNew));
|
||||
pNew->zFilename = (char*)&pNew[1];
|
||||
sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
|
||||
sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename);
|
||||
|
||||
/* Look to see if there is an existing winShmNode that can be used.
|
||||
** If no matching winShmNode currently exists, create a new one.
|
||||
@ -2465,6 +2466,13 @@ static int winFullPathname(
|
||||
void *zConverted;
|
||||
char *zOut;
|
||||
|
||||
/* If this path name begins with "/X:", where "X" is any alphabetic
|
||||
** character, discard the initial "/" from the pathname.
|
||||
*/
|
||||
if( zRelative[0]=='/' && sqlite3Isalpha(zRelative[1]) && zRelative[2]==':' ){
|
||||
zRelative++;
|
||||
}
|
||||
|
||||
/* It's odd to simulate an io-error here, but really this is just
|
||||
** using the io-error infrastructure to test that SQLite handles this
|
||||
** function failing. This function could fail if, for example, the
|
||||
|
30
src/pager.c
30
src/pager.c
@ -4299,6 +4299,8 @@ int sqlite3PagerOpen(
|
||||
int noReadlock = (flags & PAGER_NO_READLOCK)!=0; /* True to omit read-lock */
|
||||
int pcacheSize = sqlite3PcacheSize(); /* Bytes to allocate for PCache */
|
||||
u32 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE; /* Default page size */
|
||||
const char *zUri = 0; /* URI args to copy */
|
||||
int nUri = 0; /* Number of bytes of URI args at *zUri */
|
||||
|
||||
/* Figure out how much space is required for each journal file-handle
|
||||
** (there are two of them, the main journal and the sub-journal). This
|
||||
@ -4329,6 +4331,7 @@ int sqlite3PagerOpen(
|
||||
** leave both nPathname and zPathname set to 0.
|
||||
*/
|
||||
if( zFilename && zFilename[0] ){
|
||||
const char *z;
|
||||
nPathname = pVfs->mxPathname+1;
|
||||
zPathname = sqlite3Malloc(nPathname*2);
|
||||
if( zPathname==0 ){
|
||||
@ -4337,6 +4340,12 @@ int sqlite3PagerOpen(
|
||||
zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */
|
||||
rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname);
|
||||
nPathname = sqlite3Strlen30(zPathname);
|
||||
z = zUri = &zFilename[sqlite3Strlen30(zFilename)+1];
|
||||
while( *z ){
|
||||
z += sqlite3Strlen30(z)+1;
|
||||
z += sqlite3Strlen30(z)+1;
|
||||
}
|
||||
nUri = &z[1] - zUri;
|
||||
if( rc==SQLITE_OK && nPathname+8>pVfs->mxPathname ){
|
||||
/* This branch is taken when the journal path required by
|
||||
** the database being opened will be more than pVfs->mxPathname
|
||||
@ -4369,7 +4378,7 @@ int sqlite3PagerOpen(
|
||||
ROUND8(pcacheSize) + /* PCache object */
|
||||
ROUND8(pVfs->szOsFile) + /* The main db file */
|
||||
journalFileSize * 2 + /* The two journal files */
|
||||
nPathname + 1 + /* zFilename */
|
||||
nPathname + 1 + nUri + /* zFilename */
|
||||
nPathname + 8 + 1 /* zJournal */
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
+ nPathname + 4 + 1 /* zWal */
|
||||
@ -4391,14 +4400,17 @@ int sqlite3PagerOpen(
|
||||
/* Fill in the Pager.zFilename and Pager.zJournal buffers, if required. */
|
||||
if( zPathname ){
|
||||
assert( nPathname>0 );
|
||||
pPager->zJournal = (char*)(pPtr += nPathname + 1);
|
||||
pPager->zJournal = (char*)(pPtr += nPathname + 1 + nUri);
|
||||
memcpy(pPager->zFilename, zPathname, nPathname);
|
||||
memcpy(&pPager->zFilename[nPathname+1], zUri, nUri);
|
||||
memcpy(pPager->zJournal, zPathname, nPathname);
|
||||
memcpy(&pPager->zJournal[nPathname], "-journal", 8);
|
||||
sqlite3FileSuffix3(pPager->zFilename, pPager->zJournal);
|
||||
#ifndef SQLITE_OMIT_WAL
|
||||
pPager->zWal = &pPager->zJournal[nPathname+8+1];
|
||||
memcpy(pPager->zWal, zPathname, nPathname);
|
||||
memcpy(&pPager->zWal[nPathname], "-wal", 4);
|
||||
sqlite3FileSuffix3(pPager->zFilename, pPager->zWal);
|
||||
#endif
|
||||
sqlite3_free(zPathname);
|
||||
}
|
||||
@ -5735,11 +5747,21 @@ int sqlite3PagerCommitPhaseOne(
|
||||
}else{
|
||||
if( pagerUseWal(pPager) ){
|
||||
PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache);
|
||||
PgHdr *pPageOne = 0;
|
||||
if( pList==0 ){
|
||||
/* Must have at least one page for the WAL commit flag.
|
||||
** Ticket [2d1a5c67dfc2363e44f29d9bbd57f] 2011-05-18 */
|
||||
rc = sqlite3PagerGet(pPager, 1, &pPageOne);
|
||||
pList = pPageOne;
|
||||
pList->pDirty = 0;
|
||||
}
|
||||
assert( pList!=0 || rc!=SQLITE_OK );
|
||||
if( pList ){
|
||||
rc = pagerWalFrames(pPager, pList, pPager->dbSize, 1,
|
||||
(pPager->fullSync ? pPager->syncFlags : 0)
|
||||
);
|
||||
}
|
||||
sqlite3PagerUnref(pPageOne);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3PcacheCleanAll(pPager->pPCache);
|
||||
}
|
||||
@ -6597,6 +6619,7 @@ int sqlite3PagerOkToChangeJournalMode(Pager *pPager){
|
||||
i64 sqlite3PagerJournalSizeLimit(Pager *pPager, i64 iLimit){
|
||||
if( iLimit>=-1 ){
|
||||
pPager->journalSizeLimit = iLimit;
|
||||
sqlite3WalLimit(pPager->pWal, iLimit);
|
||||
}
|
||||
return pPager->journalSizeLimit;
|
||||
}
|
||||
@ -6688,7 +6711,8 @@ static int pagerOpenWal(Pager *pPager){
|
||||
*/
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3WalOpen(pPager->pVfs,
|
||||
pPager->fd, pPager->zWal, pPager->exclusiveMode, &pPager->pWal
|
||||
pPager->fd, pPager->zWal, pPager->exclusiveMode,
|
||||
pPager->journalSizeLimit, &pPager->pWal
|
||||
);
|
||||
}
|
||||
|
||||
|
10
src/pragma.c
10
src/pragma.c
@ -49,7 +49,7 @@ static u8 getSafetyLevel(const char *z){
|
||||
/*
|
||||
** Interpret the given string as a boolean value.
|
||||
*/
|
||||
static u8 getBoolean(const char *z){
|
||||
u8 sqlite3GetBoolean(const char *z){
|
||||
return getSafetyLevel(z)&1;
|
||||
}
|
||||
|
||||
@ -219,7 +219,7 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
|
||||
mask &= ~(SQLITE_ForeignKeys);
|
||||
}
|
||||
|
||||
if( getBoolean(zRight) ){
|
||||
if( sqlite3GetBoolean(zRight) ){
|
||||
db->flags |= mask;
|
||||
}else{
|
||||
db->flags &= ~mask;
|
||||
@ -433,7 +433,7 @@ void sqlite3Pragma(
|
||||
int b = -1;
|
||||
assert( pBt!=0 );
|
||||
if( zRight ){
|
||||
b = getBoolean(zRight);
|
||||
b = sqlite3GetBoolean(zRight);
|
||||
}
|
||||
if( pId2->n==0 && b>=0 ){
|
||||
int ii;
|
||||
@ -1033,7 +1033,7 @@ void sqlite3Pragma(
|
||||
#ifndef NDEBUG
|
||||
if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){
|
||||
if( zRight ){
|
||||
if( getBoolean(zRight) ){
|
||||
if( sqlite3GetBoolean(zRight) ){
|
||||
sqlite3ParserTrace(stderr, "parser: ");
|
||||
}else{
|
||||
sqlite3ParserTrace(0, 0);
|
||||
@ -1047,7 +1047,7 @@ void sqlite3Pragma(
|
||||
*/
|
||||
if( sqlite3StrICmp(zLeft, "case_sensitive_like")==0 ){
|
||||
if( zRight ){
|
||||
sqlite3RegisterLikeFunctions(db, getBoolean(zRight));
|
||||
sqlite3RegisterLikeFunctions(db, sqlite3GetBoolean(zRight));
|
||||
}
|
||||
}else
|
||||
|
||||
|
@ -2649,6 +2649,7 @@ static void main_init(struct callback_data *data) {
|
||||
data->mode = MODE_List;
|
||||
memcpy(data->separator,"|", 2);
|
||||
data->showHeader = 0;
|
||||
sqlite3_config(SQLITE_CONFIG_URI, 1);
|
||||
sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
|
||||
sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
|
||||
sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> ");
|
||||
@ -2663,6 +2664,11 @@ int main(int argc, char **argv){
|
||||
int i;
|
||||
int rc = 0;
|
||||
|
||||
if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){
|
||||
fprintf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
|
||||
sqlite3_sourceid(), SQLITE_SOURCE_ID);
|
||||
exit(1);
|
||||
}
|
||||
Argv0 = argv[0];
|
||||
main_init(&data);
|
||||
stdin_is_interactive = isatty(0);
|
||||
|
374
src/sqlite.h.in
374
src/sqlite.h.in
@ -453,14 +453,14 @@ int sqlite3_exec(
|
||||
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
|
||||
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
|
||||
#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
|
||||
#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
|
||||
|
||||
/*
|
||||
** CAPI3REF: Flags For File Open Operations
|
||||
**
|
||||
** These bit values are intended for use in the
|
||||
** 3rd parameter to the [sqlite3_open_v2()] interface and
|
||||
** in the 4th parameter to the xOpen method of the
|
||||
** [sqlite3_vfs] object.
|
||||
** in the 4th parameter to the [sqlite3_vfs.xOpen] method.
|
||||
*/
|
||||
#define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */
|
||||
#define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */
|
||||
@ -468,6 +468,7 @@ int sqlite3_exec(
|
||||
#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */
|
||||
#define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */
|
||||
#define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */
|
||||
#define SQLITE_OPEN_URI 0x00000040 /* Ok for sqlite3_open_v2() */
|
||||
#define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */
|
||||
#define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */
|
||||
#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */
|
||||
@ -578,17 +579,18 @@ struct sqlite3_file {
|
||||
/*
|
||||
** CAPI3REF: OS Interface File Virtual Methods Object
|
||||
**
|
||||
** Every file opened by the [sqlite3_vfs] xOpen method populates an
|
||||
** Every file opened by the [sqlite3_vfs.xOpen] method populates an
|
||||
** [sqlite3_file] object (or, more commonly, a subclass of the
|
||||
** [sqlite3_file] object) with a pointer to an instance of this object.
|
||||
** This object defines the methods used to perform various operations
|
||||
** against the open file represented by the [sqlite3_file] object.
|
||||
**
|
||||
** If the xOpen method sets the sqlite3_file.pMethods element
|
||||
** If the [sqlite3_vfs.xOpen] method sets the sqlite3_file.pMethods element
|
||||
** to a non-NULL pointer, then the sqlite3_io_methods.xClose method
|
||||
** may be invoked even if the xOpen reported that it failed. The
|
||||
** only way to prevent a call to xClose following a failed xOpen
|
||||
** is for the xOpen to set the sqlite3_file.pMethods element to NULL.
|
||||
** may be invoked even if the [sqlite3_vfs.xOpen] reported that it failed. The
|
||||
** only way to prevent a call to xClose following a failed [sqlite3_vfs.xOpen]
|
||||
** is for the [sqlite3_vfs.xOpen] to set the sqlite3_file.pMethods element
|
||||
** to NULL.
|
||||
**
|
||||
** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or
|
||||
** [SQLITE_SYNC_FULL]. The first choice is the normal fsync().
|
||||
@ -757,6 +759,7 @@ typedef struct sqlite3_mutex sqlite3_mutex;
|
||||
|
||||
/*
|
||||
** CAPI3REF: OS Interface Object
|
||||
** KEYWORDS: VFS VFSes
|
||||
**
|
||||
** An instance of the sqlite3_vfs object defines the interface between
|
||||
** the SQLite core and the underlying operating system. The "vfs"
|
||||
@ -789,6 +792,7 @@ typedef struct sqlite3_mutex sqlite3_mutex;
|
||||
** The zName field holds the name of the VFS module. The name must
|
||||
** be unique across all VFS modules.
|
||||
**
|
||||
** [[sqlite3_vfs.xOpen]]
|
||||
** ^SQLite guarantees that the zFilename parameter to xOpen
|
||||
** is either a NULL pointer or string obtained
|
||||
** from xFullPathname() with an optional suffix added.
|
||||
@ -866,6 +870,7 @@ typedef struct sqlite3_mutex sqlite3_mutex;
|
||||
** element will be valid after xOpen returns regardless of the success
|
||||
** or failure of the xOpen call.
|
||||
**
|
||||
** [[sqlite3_vfs.xAccess]]
|
||||
** ^The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS]
|
||||
** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to
|
||||
** test whether a file is readable and writable, or [SQLITE_ACCESS_READ]
|
||||
@ -1112,9 +1117,9 @@ int sqlite3_os_end(void);
|
||||
** implementation of an application-defined [sqlite3_os_init()].
|
||||
**
|
||||
** The first argument to sqlite3_config() is an integer
|
||||
** [SQLITE_CONFIG_SINGLETHREAD | configuration option] that determines
|
||||
** [configuration option] that determines
|
||||
** what property of SQLite is to be configured. Subsequent arguments
|
||||
** vary depending on the [SQLITE_CONFIG_SINGLETHREAD | configuration option]
|
||||
** vary depending on the [configuration option]
|
||||
** in the first argument.
|
||||
**
|
||||
** ^When a configuration option is set, sqlite3_config() returns [SQLITE_OK].
|
||||
@ -1224,6 +1229,7 @@ struct sqlite3_mem_methods {
|
||||
|
||||
/*
|
||||
** CAPI3REF: Configuration Options
|
||||
** KEYWORDS: {configuration option}
|
||||
**
|
||||
** These constants are the available integer configuration options that
|
||||
** can be passed as the first argument to the [sqlite3_config()] interface.
|
||||
@ -1236,7 +1242,7 @@ struct sqlite3_mem_methods {
|
||||
** is invoked.
|
||||
**
|
||||
** <dl>
|
||||
** <dt>SQLITE_CONFIG_SINGLETHREAD</dt>
|
||||
** [[SQLITE_CONFIG_SINGLETHREAD]] <dt>SQLITE_CONFIG_SINGLETHREAD</dt>
|
||||
** <dd>There are no arguments to this option. ^This option sets the
|
||||
** [threading mode] to Single-thread. In other words, it disables
|
||||
** all mutexing and puts SQLite into a mode where it can only be used
|
||||
@ -1247,7 +1253,7 @@ struct sqlite3_mem_methods {
|
||||
** [SQLITE_ERROR] if called with the SQLITE_CONFIG_SINGLETHREAD
|
||||
** configuration option.</dd>
|
||||
**
|
||||
** <dt>SQLITE_CONFIG_MULTITHREAD</dt>
|
||||
** [[SQLITE_CONFIG_MULTITHREAD]] <dt>SQLITE_CONFIG_MULTITHREAD</dt>
|
||||
** <dd>There are no arguments to this option. ^This option sets the
|
||||
** [threading mode] to Multi-thread. In other words, it disables
|
||||
** mutexing on [database connection] and [prepared statement] objects.
|
||||
@ -1261,7 +1267,7 @@ struct sqlite3_mem_methods {
|
||||
** [sqlite3_config()] will return [SQLITE_ERROR] if called with the
|
||||
** SQLITE_CONFIG_MULTITHREAD configuration option.</dd>
|
||||
**
|
||||
** <dt>SQLITE_CONFIG_SERIALIZED</dt>
|
||||
** [[SQLITE_CONFIG_SERIALIZED]] <dt>SQLITE_CONFIG_SERIALIZED</dt>
|
||||
** <dd>There are no arguments to this option. ^This option sets the
|
||||
** [threading mode] to Serialized. In other words, this option enables
|
||||
** all mutexes including the recursive
|
||||
@ -1277,7 +1283,7 @@ struct sqlite3_mem_methods {
|
||||
** [sqlite3_config()] will return [SQLITE_ERROR] if called with the
|
||||
** SQLITE_CONFIG_SERIALIZED configuration option.</dd>
|
||||
**
|
||||
** <dt>SQLITE_CONFIG_MALLOC</dt>
|
||||
** [[SQLITE_CONFIG_MALLOC]] <dt>SQLITE_CONFIG_MALLOC</dt>
|
||||
** <dd> ^(This option takes a single argument which is a pointer to an
|
||||
** instance of the [sqlite3_mem_methods] structure. The argument specifies
|
||||
** alternative low-level memory allocation routines to be used in place of
|
||||
@ -1285,7 +1291,7 @@ struct sqlite3_mem_methods {
|
||||
** its own private copy of the content of the [sqlite3_mem_methods] structure
|
||||
** before the [sqlite3_config()] call returns.</dd>
|
||||
**
|
||||
** <dt>SQLITE_CONFIG_GETMALLOC</dt>
|
||||
** [[SQLITE_CONFIG_GETMALLOC]] <dt>SQLITE_CONFIG_GETMALLOC</dt>
|
||||
** <dd> ^(This option takes a single argument which is a pointer to an
|
||||
** instance of the [sqlite3_mem_methods] structure. The [sqlite3_mem_methods]
|
||||
** structure is filled with the currently defined memory allocation routines.)^
|
||||
@ -1293,7 +1299,7 @@ struct sqlite3_mem_methods {
|
||||
** routines with a wrapper that simulations memory allocation failure or
|
||||
** tracks memory usage, for example. </dd>
|
||||
**
|
||||
** <dt>SQLITE_CONFIG_MEMSTATUS</dt>
|
||||
** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt>
|
||||
** <dd> ^This option takes single argument of type int, interpreted as a
|
||||
** boolean, which enables or disables the collection of memory allocation
|
||||
** statistics. ^(When memory allocation statistics are disabled, the
|
||||
@ -1309,7 +1315,7 @@ struct sqlite3_mem_methods {
|
||||
** allocation statistics are disabled by default.
|
||||
** </dd>
|
||||
**
|
||||
** <dt>SQLITE_CONFIG_SCRATCH</dt>
|
||||
** [[SQLITE_CONFIG_SCRATCH]] <dt>SQLITE_CONFIG_SCRATCH</dt>
|
||||
** <dd> ^This option specifies a static memory buffer that SQLite can use for
|
||||
** scratch memory. There are three arguments: A pointer an 8-byte
|
||||
** aligned memory buffer from which the scratch allocations will be
|
||||
@ -1325,7 +1331,7 @@ struct sqlite3_mem_methods {
|
||||
** scratch memory beyond what is provided by this configuration option, then
|
||||
** [sqlite3_malloc()] will be used to obtain the memory needed.</dd>
|
||||
**
|
||||
** <dt>SQLITE_CONFIG_PAGECACHE</dt>
|
||||
** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt>
|
||||
** <dd> ^This option specifies a static memory buffer that SQLite can use for
|
||||
** the database page cache with the default page cache implemenation.
|
||||
** This configuration should not be used if an application-define page
|
||||
@ -1346,7 +1352,7 @@ struct sqlite3_mem_methods {
|
||||
** be aligned to an 8-byte boundary or subsequent behavior of SQLite
|
||||
** will be undefined.</dd>
|
||||
**
|
||||
** <dt>SQLITE_CONFIG_HEAP</dt>
|
||||
** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt>
|
||||
** <dd> ^This option specifies a static memory buffer that SQLite will use
|
||||
** for all of its dynamic memory allocation needs beyond those provided
|
||||
** for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE].
|
||||
@ -1363,7 +1369,7 @@ struct sqlite3_mem_methods {
|
||||
** The minimum allocation size is capped at 2^12. Reasonable values
|
||||
** for the minimum allocation size are 2^5 through 2^8.</dd>
|
||||
**
|
||||
** <dt>SQLITE_CONFIG_MUTEX</dt>
|
||||
** [[SQLITE_CONFIG_MUTEX]] <dt>SQLITE_CONFIG_MUTEX</dt>
|
||||
** <dd> ^(This option takes a single argument which is a pointer to an
|
||||
** instance of the [sqlite3_mutex_methods] structure. The argument specifies
|
||||
** alternative low-level mutex routines to be used in place
|
||||
@ -1375,7 +1381,7 @@ struct sqlite3_mem_methods {
|
||||
** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will
|
||||
** return [SQLITE_ERROR].</dd>
|
||||
**
|
||||
** <dt>SQLITE_CONFIG_GETMUTEX</dt>
|
||||
** [[SQLITE_CONFIG_GETMUTEX]] <dt>SQLITE_CONFIG_GETMUTEX</dt>
|
||||
** <dd> ^(This option takes a single argument which is a pointer to an
|
||||
** instance of the [sqlite3_mutex_methods] structure. The
|
||||
** [sqlite3_mutex_methods]
|
||||
@ -1388,7 +1394,7 @@ struct sqlite3_mem_methods {
|
||||
** [sqlite3_config()] with the SQLITE_CONFIG_GETMUTEX configuration option will
|
||||
** return [SQLITE_ERROR].</dd>
|
||||
**
|
||||
** <dt>SQLITE_CONFIG_LOOKASIDE</dt>
|
||||
** [[SQLITE_CONFIG_LOOKASIDE]] <dt>SQLITE_CONFIG_LOOKASIDE</dt>
|
||||
** <dd> ^(This option takes two arguments that determine the default
|
||||
** memory allocation for the lookaside memory allocator on each
|
||||
** [database connection]. The first argument is the
|
||||
@ -1398,18 +1404,18 @@ struct sqlite3_mem_methods {
|
||||
** verb to [sqlite3_db_config()] can be used to change the lookaside
|
||||
** configuration on individual connections.)^ </dd>
|
||||
**
|
||||
** <dt>SQLITE_CONFIG_PCACHE</dt>
|
||||
** [[SQLITE_CONFIG_PCACHE]] <dt>SQLITE_CONFIG_PCACHE</dt>
|
||||
** <dd> ^(This option takes a single argument which is a pointer to
|
||||
** an [sqlite3_pcache_methods] object. This object specifies the interface
|
||||
** to a custom page cache implementation.)^ ^SQLite makes a copy of the
|
||||
** object and uses it for page cache memory allocations.</dd>
|
||||
**
|
||||
** <dt>SQLITE_CONFIG_GETPCACHE</dt>
|
||||
** [[SQLITE_CONFIG_GETPCACHE]] <dt>SQLITE_CONFIG_GETPCACHE</dt>
|
||||
** <dd> ^(This option takes a single argument which is a pointer to an
|
||||
** [sqlite3_pcache_methods] object. SQLite copies of the current
|
||||
** page cache implementation into that object.)^ </dd>
|
||||
**
|
||||
** <dt>SQLITE_CONFIG_LOG</dt>
|
||||
** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt>
|
||||
** <dd> ^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a
|
||||
** function with a call signature of void(*)(void*,int,const char*),
|
||||
** and a pointer to void. ^If the function pointer is not NULL, it is
|
||||
@ -1427,6 +1433,18 @@ struct sqlite3_mem_methods {
|
||||
** In a multi-threaded application, the application-defined logger
|
||||
** function must be threadsafe. </dd>
|
||||
**
|
||||
** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI
|
||||
** <dd> This option takes a single argument of type int. If non-zero, then
|
||||
** URI handling is globally enabled. If the parameter is zero, then URI handling
|
||||
** is globally disabled. If URI handling is globally enabled, all filenames
|
||||
** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or
|
||||
** specified as part of [ATTACH] commands are interpreted as URIs, regardless
|
||||
** of whether or not the [SQLITE_OPEN_URI] flag is set when the database
|
||||
** connection is opened. If it is globally disabled, filenames are
|
||||
** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the
|
||||
** database connection is opened. By default, URI handling is globally
|
||||
** disabled. The default value may be changed by compiling with the
|
||||
** [SQLITE_USE_URI] symbol defined.
|
||||
** </dl>
|
||||
*/
|
||||
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
|
||||
@ -1445,6 +1463,7 @@ struct sqlite3_mem_methods {
|
||||
#define SQLITE_CONFIG_PCACHE 14 /* sqlite3_pcache_methods* */
|
||||
#define SQLITE_CONFIG_GETPCACHE 15 /* sqlite3_pcache_methods* */
|
||||
#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */
|
||||
#define SQLITE_CONFIG_URI 17 /* int */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Database Connection Configuration Options
|
||||
@ -1530,13 +1549,17 @@ int sqlite3_extended_result_codes(sqlite3*, int onoff);
|
||||
**
|
||||
** ^This routine returns the [rowid] of the most recent
|
||||
** successful [INSERT] into the database from the [database connection]
|
||||
** in the first argument. ^If no successful [INSERT]s
|
||||
** in the first argument. ^As of SQLite version 3.7.7, this routines
|
||||
** records the last insert rowid of both ordinary tables and [virtual tables].
|
||||
** ^If no successful [INSERT]s
|
||||
** have ever occurred on that database connection, zero is returned.
|
||||
**
|
||||
** ^(If an [INSERT] occurs within a trigger, then the [rowid] of the inserted
|
||||
** row is returned by this routine as long as the trigger is running.
|
||||
** But once the trigger terminates, the value returned by this routine
|
||||
** reverts to the last value inserted before the trigger fired.)^
|
||||
** ^(If an [INSERT] occurs within a trigger or within a [virtual table]
|
||||
** method, then this routine will return the [rowid] of the inserted
|
||||
** row as long as the trigger or virtual table method is running.
|
||||
** But once the trigger or virtual table method ends, the value returned
|
||||
** by this routine reverts to what it was before the trigger or virtual
|
||||
** table method began.)^
|
||||
**
|
||||
** ^An [INSERT] that fails due to a constraint violation is not a
|
||||
** successful [INSERT] and does not change the value returned by this
|
||||
@ -2324,7 +2347,7 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
|
||||
/*
|
||||
** CAPI3REF: Opening A New Database Connection
|
||||
**
|
||||
** ^These routines open an SQLite database file whose name is given by the
|
||||
** ^These routines open an SQLite database file as specified by the
|
||||
** filename argument. ^The filename argument is interpreted as UTF-8 for
|
||||
** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte
|
||||
** order for sqlite3_open16(). ^(A [database connection] handle is usually
|
||||
@ -2351,7 +2374,7 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
|
||||
** sqlite3_open_v2() can take one of
|
||||
** the following three values, optionally combined with the
|
||||
** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE],
|
||||
** and/or [SQLITE_OPEN_PRIVATECACHE] flags:)^
|
||||
** [SQLITE_OPEN_PRIVATECACHE], and/or [SQLITE_OPEN_URI] flags:)^
|
||||
**
|
||||
** <dl>
|
||||
** ^(<dt>[SQLITE_OPEN_READONLY]</dt>
|
||||
@ -2370,9 +2393,8 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
|
||||
** </dl>
|
||||
**
|
||||
** If the 3rd parameter to sqlite3_open_v2() is not one of the
|
||||
** combinations shown above or one of the combinations shown above combined
|
||||
** with the [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX],
|
||||
** [SQLITE_OPEN_SHAREDCACHE] and/or [SQLITE_OPEN_PRIVATECACHE] flags,
|
||||
** combinations shown above optionally combined with other
|
||||
** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits]
|
||||
** then the behavior is undefined.
|
||||
**
|
||||
** ^If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection
|
||||
@ -2387,6 +2409,11 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
|
||||
** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not
|
||||
** participate in [shared cache mode] even if it is enabled.
|
||||
**
|
||||
** ^The fourth parameter to sqlite3_open_v2() is the name of the
|
||||
** [sqlite3_vfs] object that defines the operating system interface that
|
||||
** the new database connection should use. ^If the fourth parameter is
|
||||
** a NULL pointer then the default [sqlite3_vfs] object is used.
|
||||
**
|
||||
** ^If the filename is ":memory:", then a private, temporary in-memory database
|
||||
** is created for the connection. ^This in-memory database will vanish when
|
||||
** the database connection is closed. Future versions of SQLite might
|
||||
@ -2399,10 +2426,111 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
|
||||
** on-disk database will be created. ^This private database will be
|
||||
** automatically deleted as soon as the database connection is closed.
|
||||
**
|
||||
** ^The fourth parameter to sqlite3_open_v2() is the name of the
|
||||
** [sqlite3_vfs] object that defines the operating system interface that
|
||||
** the new database connection should use. ^If the fourth parameter is
|
||||
** a NULL pointer then the default [sqlite3_vfs] object is used.
|
||||
** [[URI filenames in sqlite3_open()]] <h3>URI Filenames</h3>
|
||||
**
|
||||
** ^If [URI filename] interpretation is enabled, and the filename argument
|
||||
** begins with "file:", then the filename is interpreted as a URI. ^URI
|
||||
** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is
|
||||
** is set in the fourth argument to sqlite3_open_v2(), or if it has
|
||||
** been enabled globally using the [SQLITE_CONFIG_URI] option with the
|
||||
** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option.
|
||||
** As of SQLite version 3.7.7, URI filename interpretation is turned off
|
||||
** by default, but future releases of SQLite might enable URI filename
|
||||
** intepretation by default. See "[URI filenames]" for additional
|
||||
** information.
|
||||
**
|
||||
** URI filenames are parsed according to RFC 3986. ^If the URI contains an
|
||||
** authority, then it must be either an empty string or the string
|
||||
** "localhost". ^If the authority is not an empty string or "localhost", an
|
||||
** error is returned to the caller. ^The fragment component of a URI, if
|
||||
** present, is ignored.
|
||||
**
|
||||
** ^SQLite uses the path component of the URI as the name of the disk file
|
||||
** which contains the database. ^If the path begins with a '/' character,
|
||||
** then it is interpreted as an absolute path. ^If the path does not begin
|
||||
** with a '/' (meaning that the authority section is omitted from the URI)
|
||||
** then the path is interpreted as a relative path.
|
||||
** ^On windows, the first component of an absolute path
|
||||
** is a drive specification (e.g. "C:").
|
||||
**
|
||||
** [[core URI query parameters]]
|
||||
** The query component of a URI may contain parameters that are interpreted
|
||||
** either by SQLite itself, or by a [VFS | custom VFS implementation].
|
||||
** SQLite interprets the following three query parameters:
|
||||
**
|
||||
** <ul>
|
||||
** <li> <b>vfs</b>: ^The "vfs" parameter may be used to specify the name of
|
||||
** a VFS object that provides the operating system interface that should
|
||||
** be used to access the database file on disk. ^If this option is set to
|
||||
** an empty string the default VFS object is used. ^Specifying an unknown
|
||||
** VFS is an error. ^If sqlite3_open_v2() is used and the vfs option is
|
||||
** present, then the VFS specified by the option takes precedence over
|
||||
** the value passed as the fourth parameter to sqlite3_open_v2().
|
||||
**
|
||||
** <li> <b>mode</b>: ^(The mode parameter may be set to either "ro", "rw" or
|
||||
** "rwc". Attempting to set it to any other value is an error)^.
|
||||
** ^If "ro" is specified, then the database is opened for read-only
|
||||
** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the
|
||||
** third argument to sqlite3_prepare_v2(). ^If the mode option is set to
|
||||
** "rw", then the database is opened for read-write (but not create)
|
||||
** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had
|
||||
** been set. ^Value "rwc" is equivalent to setting both
|
||||
** SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If sqlite3_open_v2() is
|
||||
** used, it is an error to specify a value for the mode parameter that is
|
||||
** less restrictive than that specified by the flags passed as the third
|
||||
** parameter.
|
||||
**
|
||||
** <li> <b>cache</b>: ^The cache parameter may be set to either "shared" or
|
||||
** "private". ^Setting it to "shared" is equivalent to setting the
|
||||
** SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to
|
||||
** sqlite3_open_v2(). ^Setting the cache parameter to "private" is
|
||||
** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
|
||||
** ^If sqlite3_open_v2() is used and the "cache" parameter is present in
|
||||
** a URI filename, its value overrides any behaviour requested by setting
|
||||
** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
|
||||
** </ul>
|
||||
**
|
||||
** ^Specifying an unknown parameter in the query component of a URI is not an
|
||||
** error. Future versions of SQLite might understand additional query
|
||||
** parameters. See "[query parameters with special meaning to SQLite]" for
|
||||
** additional information.
|
||||
**
|
||||
** [[URI filename examples]] <h3>URI filename examples</h3>
|
||||
**
|
||||
** <table border="1" align=center cellpadding=5>
|
||||
** <tr><th> URI filenames <th> Results
|
||||
** <tr><td> file:data.db <td>
|
||||
** Open the file "data.db" in the current directory.
|
||||
** <tr><td> file:/home/fred/data.db<br>
|
||||
** file:///home/fred/data.db <br>
|
||||
** file://localhost/home/fred/data.db <br> <td>
|
||||
** Open the database file "/home/fred/data.db".
|
||||
** <tr><td> file://darkstar/home/fred/data.db <td>
|
||||
** An error. "darkstar" is not a recognized authority.
|
||||
** <tr><td style="white-space:nowrap">
|
||||
** file:///C:/Documents%20and%20Settings/fred/Desktop/data.db
|
||||
** <td> Windows only: Open the file "data.db" on fred's desktop on drive
|
||||
** C:. Note that the %20 escaping in this example is not strictly
|
||||
** necessary - space characters can be used literally
|
||||
** in URI filenames.
|
||||
** <tr><td> file:data.db?mode=ro&cache=private <td>
|
||||
** Open file "data.db" in the current directory for read-only access.
|
||||
** Regardless of whether or not shared-cache mode is enabled by
|
||||
** default, use a private cache.
|
||||
** <tr><td> file:/home/fred/data.db?vfs=unix-nolock <td>
|
||||
** Open file "/home/fred/data.db". Use the special VFS "unix-nolock".
|
||||
** <tr><td> file:data.db?mode=readonly <td>
|
||||
** An error. "readonly" is not a valid option for the "mode" parameter.
|
||||
** </table>
|
||||
**
|
||||
** ^URI hexadecimal escape sequences (%HH) are supported within the path and
|
||||
** query components of a URI. A hexadecimal escape sequence consists of a
|
||||
** percent sign - "%" - followed by exactly two hexadecimal digits
|
||||
** specifying an octet value. ^Before the path or query components of a
|
||||
** URI filename are interpreted, they are encoded using UTF-8 and all
|
||||
** hexadecimal escape sequences replaced by a single byte containing the
|
||||
** corresponding octet. If this process generates an invalid UTF-8 encoding,
|
||||
** the results are undefined.
|
||||
**
|
||||
** <b>Note to Windows users:</b> The encoding used for the filename argument
|
||||
** of sqlite3_open() and sqlite3_open_v2() must be UTF-8, not whatever
|
||||
@ -2425,6 +2553,26 @@ int sqlite3_open_v2(
|
||||
const char *zVfs /* Name of VFS module to use */
|
||||
);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Obtain Values For URI Parameters
|
||||
**
|
||||
** This is a utility routine, useful to VFS implementations, that checks
|
||||
** to see if a database file was a URI that contained a specific query
|
||||
** parameter, and if so obtains the value of the query parameter.
|
||||
**
|
||||
** The zFilename argument is the filename pointer passed into the xOpen()
|
||||
** method of a VFS implementation. The zParam argument is the name of the
|
||||
** query parameter we seek. This routine returns the value of the zParam
|
||||
** parameter if it exists. If the parameter does not exist, this routine
|
||||
** returns a NULL pointer.
|
||||
**
|
||||
** If the zFilename argument to this function is not a pointer that SQLite
|
||||
** passed into the xOpen VFS method, then the behavior of this routine
|
||||
** is undefined and probably undesirable.
|
||||
*/
|
||||
const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
|
||||
|
||||
|
||||
/*
|
||||
** CAPI3REF: Error Codes And Messages
|
||||
**
|
||||
@ -2540,43 +2688,45 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
|
||||
** Additional information is available at [limits | Limits in SQLite].
|
||||
**
|
||||
** <dl>
|
||||
** ^(<dt>SQLITE_LIMIT_LENGTH</dt>
|
||||
** [[SQLITE_LIMIT_LENGTH]] ^(<dt>SQLITE_LIMIT_LENGTH</dt>
|
||||
** <dd>The maximum size of any string or BLOB or table row, in bytes.<dd>)^
|
||||
**
|
||||
** ^(<dt>SQLITE_LIMIT_SQL_LENGTH</dt>
|
||||
** [[SQLITE_LIMIT_SQL_LENGTH]] ^(<dt>SQLITE_LIMIT_SQL_LENGTH</dt>
|
||||
** <dd>The maximum length of an SQL statement, in bytes.</dd>)^
|
||||
**
|
||||
** ^(<dt>SQLITE_LIMIT_COLUMN</dt>
|
||||
** [[SQLITE_LIMIT_COLUMN]] ^(<dt>SQLITE_LIMIT_COLUMN</dt>
|
||||
** <dd>The maximum number of columns in a table definition or in the
|
||||
** result set of a [SELECT] or the maximum number of columns in an index
|
||||
** or in an ORDER BY or GROUP BY clause.</dd>)^
|
||||
**
|
||||
** ^(<dt>SQLITE_LIMIT_EXPR_DEPTH</dt>
|
||||
** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(<dt>SQLITE_LIMIT_EXPR_DEPTH</dt>
|
||||
** <dd>The maximum depth of the parse tree on any expression.</dd>)^
|
||||
**
|
||||
** ^(<dt>SQLITE_LIMIT_COMPOUND_SELECT</dt>
|
||||
** [[SQLITE_LIMIT_COMPOUND_SELECT]] ^(<dt>SQLITE_LIMIT_COMPOUND_SELECT</dt>
|
||||
** <dd>The maximum number of terms in a compound SELECT statement.</dd>)^
|
||||
**
|
||||
** ^(<dt>SQLITE_LIMIT_VDBE_OP</dt>
|
||||
** [[SQLITE_LIMIT_VDBE_OP]] ^(<dt>SQLITE_LIMIT_VDBE_OP</dt>
|
||||
** <dd>The maximum number of instructions in a virtual machine program
|
||||
** used to implement an SQL statement. This limit is not currently
|
||||
** enforced, though that might be added in some future release of
|
||||
** SQLite.</dd>)^
|
||||
**
|
||||
** ^(<dt>SQLITE_LIMIT_FUNCTION_ARG</dt>
|
||||
** [[SQLITE_LIMIT_FUNCTION_ARG]] ^(<dt>SQLITE_LIMIT_FUNCTION_ARG</dt>
|
||||
** <dd>The maximum number of arguments on a function.</dd>)^
|
||||
**
|
||||
** ^(<dt>SQLITE_LIMIT_ATTACHED</dt>
|
||||
** [[SQLITE_LIMIT_ATTACHED]] ^(<dt>SQLITE_LIMIT_ATTACHED</dt>
|
||||
** <dd>The maximum number of [ATTACH | attached databases].)^</dd>
|
||||
**
|
||||
** [[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]]
|
||||
** ^(<dt>SQLITE_LIMIT_LIKE_PATTERN_LENGTH</dt>
|
||||
** <dd>The maximum length of the pattern argument to the [LIKE] or
|
||||
** [GLOB] operators.</dd>)^
|
||||
**
|
||||
** [[SQLITE_LIMIT_VARIABLE_NUMBER]]
|
||||
** ^(<dt>SQLITE_LIMIT_VARIABLE_NUMBER</dt>
|
||||
** <dd>The maximum index number of any [parameter] in an SQL statement.)^
|
||||
**
|
||||
** ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt>
|
||||
** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt>
|
||||
** <dd>The maximum depth of recursion for triggers.</dd>)^
|
||||
** </dl>
|
||||
*/
|
||||
@ -4611,8 +4761,8 @@ struct sqlite3_module {
|
||||
void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
|
||||
void **ppArg);
|
||||
int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
|
||||
/* The methods above are in version 0 of the sqlite_module object. Those
|
||||
** below are for version 1 and greater. */
|
||||
/* The methods above are in version 1 of the sqlite_module object. Those
|
||||
** below are for version 2 and greater. */
|
||||
int (*xSavepoint)(sqlite3_vtab *pVTab, int);
|
||||
int (*xRelease)(sqlite3_vtab *pVTab, int);
|
||||
int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
|
||||
@ -5430,7 +5580,7 @@ int sqlite3_test_control(int op, ...);
|
||||
** about the performance of SQLite, and optionally to reset various
|
||||
** highwater marks. ^The first argument is an integer code for
|
||||
** the specific parameter to measure. ^(Recognized integer codes
|
||||
** are of the form [SQLITE_STATUS_MEMORY_USED | SQLITE_STATUS_...].)^
|
||||
** are of the form [status parameters | SQLITE_STATUS_...].)^
|
||||
** ^The current value of the parameter is returned into *pCurrent.
|
||||
** ^The highest recorded value is returned in *pHighwater. ^If the
|
||||
** resetFlag is true, then the highest record value is reset after
|
||||
@ -5457,12 +5607,13 @@ int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Status Parameters
|
||||
** KEYWORDS: {status parameters}
|
||||
**
|
||||
** These integer constants designate various run-time status parameters
|
||||
** that can be returned by [sqlite3_status()].
|
||||
**
|
||||
** <dl>
|
||||
** ^(<dt>SQLITE_STATUS_MEMORY_USED</dt>
|
||||
** [[SQLITE_STATUS_MEMORY_USED]] ^(<dt>SQLITE_STATUS_MEMORY_USED</dt>
|
||||
** <dd>This parameter is the current amount of memory checked out
|
||||
** using [sqlite3_malloc()], either directly or indirectly. The
|
||||
** figure includes calls made to [sqlite3_malloc()] by the application
|
||||
@ -5472,23 +5623,24 @@ int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
|
||||
** this parameter. The amount returned is the sum of the allocation
|
||||
** sizes as reported by the xSize method in [sqlite3_mem_methods].</dd>)^
|
||||
**
|
||||
** ^(<dt>SQLITE_STATUS_MALLOC_SIZE</dt>
|
||||
** [[SQLITE_STATUS_MALLOC_SIZE]] ^(<dt>SQLITE_STATUS_MALLOC_SIZE</dt>
|
||||
** <dd>This parameter records the largest memory allocation request
|
||||
** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their
|
||||
** internal equivalents). Only the value returned in the
|
||||
** *pHighwater parameter to [sqlite3_status()] is of interest.
|
||||
** The value written into the *pCurrent parameter is undefined.</dd>)^
|
||||
**
|
||||
** ^(<dt>SQLITE_STATUS_MALLOC_COUNT</dt>
|
||||
** [[SQLITE_STATUS_MALLOC_COUNT]] ^(<dt>SQLITE_STATUS_MALLOC_COUNT</dt>
|
||||
** <dd>This parameter records the number of separate memory allocations
|
||||
** currently checked out.</dd>)^
|
||||
**
|
||||
** ^(<dt>SQLITE_STATUS_PAGECACHE_USED</dt>
|
||||
** [[SQLITE_STATUS_PAGECACHE_USED]] ^(<dt>SQLITE_STATUS_PAGECACHE_USED</dt>
|
||||
** <dd>This parameter returns the number of pages used out of the
|
||||
** [pagecache memory allocator] that was configured using
|
||||
** [SQLITE_CONFIG_PAGECACHE]. The
|
||||
** value returned is in pages, not in bytes.</dd>)^
|
||||
**
|
||||
** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]]
|
||||
** ^(<dt>SQLITE_STATUS_PAGECACHE_OVERFLOW</dt>
|
||||
** <dd>This parameter returns the number of bytes of page cache
|
||||
** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE]
|
||||
@ -5498,13 +5650,13 @@ int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
|
||||
** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because
|
||||
** no space was left in the page cache.</dd>)^
|
||||
**
|
||||
** ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
|
||||
** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
|
||||
** <dd>This parameter records the largest memory allocation request
|
||||
** handed to [pagecache memory allocator]. Only the value returned in the
|
||||
** *pHighwater parameter to [sqlite3_status()] is of interest.
|
||||
** The value written into the *pCurrent parameter is undefined.</dd>)^
|
||||
**
|
||||
** ^(<dt>SQLITE_STATUS_SCRATCH_USED</dt>
|
||||
** [[SQLITE_STATUS_SCRATCH_USED]] ^(<dt>SQLITE_STATUS_SCRATCH_USED</dt>
|
||||
** <dd>This parameter returns the number of allocations used out of the
|
||||
** [scratch memory allocator] configured using
|
||||
** [SQLITE_CONFIG_SCRATCH]. The value returned is in allocations, not
|
||||
@ -5512,7 +5664,7 @@ int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
|
||||
** outstanding at time, this parameter also reports the number of threads
|
||||
** using scratch memory at the same time.</dd>)^
|
||||
**
|
||||
** ^(<dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt>
|
||||
** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^(<dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt>
|
||||
** <dd>This parameter returns the number of bytes of scratch memory
|
||||
** allocation which could not be satisfied by the [SQLITE_CONFIG_SCRATCH]
|
||||
** buffer and where forced to overflow to [sqlite3_malloc()]. The values
|
||||
@ -5522,13 +5674,13 @@ int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
|
||||
** slots were available.
|
||||
** </dd>)^
|
||||
**
|
||||
** ^(<dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
|
||||
** [[SQLITE_STATUS_SCRATCH_SIZE]] ^(<dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
|
||||
** <dd>This parameter records the largest memory allocation request
|
||||
** handed to [scratch memory allocator]. Only the value returned in the
|
||||
** *pHighwater parameter to [sqlite3_status()] is of interest.
|
||||
** The value written into the *pCurrent parameter is undefined.</dd>)^
|
||||
**
|
||||
** ^(<dt>SQLITE_STATUS_PARSER_STACK</dt>
|
||||
** [[SQLITE_STATUS_PARSER_STACK]] ^(<dt>SQLITE_STATUS_PARSER_STACK</dt>
|
||||
** <dd>This parameter records the deepest parser stack. It is only
|
||||
** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].</dd>)^
|
||||
** </dl>
|
||||
@ -5553,9 +5705,9 @@ int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
|
||||
** about a single [database connection]. ^The first argument is the
|
||||
** database connection object to be interrogated. ^The second argument
|
||||
** is an integer constant, taken from the set of
|
||||
** [SQLITE_DBSTATUS_LOOKASIDE_USED | SQLITE_DBSTATUS_*] macros, that
|
||||
** [SQLITE_DBSTATUS options], that
|
||||
** determines the parameter to interrogate. The set of
|
||||
** [SQLITE_DBSTATUS_LOOKASIDE_USED | SQLITE_DBSTATUS_*] macros is likely
|
||||
** [SQLITE_DBSTATUS options] is likely
|
||||
** to grow in future releases of SQLite.
|
||||
**
|
||||
** ^The current value of the requested parameter is written into *pCur
|
||||
@ -5572,6 +5724,7 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Status Parameters for database connections
|
||||
** KEYWORDS: {SQLITE_DBSTATUS options}
|
||||
**
|
||||
** These constants are the available integer "verbs" that can be passed as
|
||||
** the second argument to the [sqlite3_db_status()] interface.
|
||||
@ -5583,15 +5736,16 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
|
||||
** if a discontinued or unsupported verb is invoked.
|
||||
**
|
||||
** <dl>
|
||||
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt>
|
||||
** [[SQLITE_DBSTATUS_LOOKASIDE_USED]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt>
|
||||
** <dd>This parameter returns the number of lookaside memory slots currently
|
||||
** checked out.</dd>)^
|
||||
**
|
||||
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
|
||||
** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
|
||||
** <dd>This parameter returns the number malloc attempts that were
|
||||
** satisfied using lookaside memory. Only the high-water value is meaningful;
|
||||
** the current value is always zero.)^
|
||||
**
|
||||
** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]]
|
||||
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE</dt>
|
||||
** <dd>This parameter returns the number malloc attempts that might have
|
||||
** been satisfied using lookaside memory but failed due to the amount of
|
||||
@ -5599,6 +5753,7 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
|
||||
** Only the high-water value is meaningful;
|
||||
** the current value is always zero.)^
|
||||
**
|
||||
** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL]]
|
||||
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL</dt>
|
||||
** <dd>This parameter returns the number malloc attempts that might have
|
||||
** been satisfied using lookaside memory but failed due to all lookaside
|
||||
@ -5606,12 +5761,12 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
|
||||
** Only the high-water value is meaningful;
|
||||
** the current value is always zero.)^
|
||||
**
|
||||
** ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt>
|
||||
** [[SQLITE_DBSTATUS_CACHE_USED]] ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt>
|
||||
** <dd>This parameter returns the approximate number of of bytes of heap
|
||||
** memory used by all pager caches associated with the database connection.)^
|
||||
** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
|
||||
**
|
||||
** ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt>
|
||||
** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt>
|
||||
** <dd>This parameter returns the approximate number of of bytes of heap
|
||||
** memory used to store the schema for all databases associated
|
||||
** with the connection - main, temp, and any [ATTACH]-ed databases.)^
|
||||
@ -5620,7 +5775,7 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
|
||||
** [shared cache mode] being enabled.
|
||||
** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0.
|
||||
**
|
||||
** ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt>
|
||||
** [[SQLITE_DBSTATUS_STMT_USED]] ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt>
|
||||
** <dd>This parameter returns the approximate number of of bytes of heap
|
||||
** and lookaside memory used by all prepared statements associated with
|
||||
** the database connection.)^
|
||||
@ -5642,7 +5797,7 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
|
||||
** CAPI3REF: Prepared Statement Status
|
||||
**
|
||||
** ^(Each prepared statement maintains various
|
||||
** [SQLITE_STMTSTATUS_SORT | counters] that measure the number
|
||||
** [SQLITE_STMTSTATUS counters] that measure the number
|
||||
** of times it has performed specific operations.)^ These counters can
|
||||
** be used to monitor the performance characteristics of the prepared
|
||||
** statements. For example, if the number of table steps greatly exceeds
|
||||
@ -5653,7 +5808,7 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
|
||||
** ^(This interface is used to retrieve and reset counter values from
|
||||
** a [prepared statement]. The first argument is the prepared statement
|
||||
** object to be interrogated. The second argument
|
||||
** is an integer code for a specific [SQLITE_STMTSTATUS_SORT | counter]
|
||||
** is an integer code for a specific [SQLITE_STMTSTATUS counter]
|
||||
** to be interrogated.)^
|
||||
** ^The current value of the requested counter is returned.
|
||||
** ^If the resetFlg is true, then the counter is reset to zero after this
|
||||
@ -5665,24 +5820,25 @@ int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Status Parameters for prepared statements
|
||||
** KEYWORDS: {SQLITE_STMTSTATUS counter} {SQLITE_STMTSTATUS counters}
|
||||
**
|
||||
** These preprocessor macros define integer codes that name counter
|
||||
** values associated with the [sqlite3_stmt_status()] interface.
|
||||
** The meanings of the various counters are as follows:
|
||||
**
|
||||
** <dl>
|
||||
** <dt>SQLITE_STMTSTATUS_FULLSCAN_STEP</dt>
|
||||
** [[SQLITE_STMTSTATUS_FULLSCAN_STEP]] <dt>SQLITE_STMTSTATUS_FULLSCAN_STEP</dt>
|
||||
** <dd>^This is the number of times that SQLite has stepped forward in
|
||||
** a table as part of a full table scan. Large numbers for this counter
|
||||
** may indicate opportunities for performance improvement through
|
||||
** careful use of indices.</dd>
|
||||
**
|
||||
** <dt>SQLITE_STMTSTATUS_SORT</dt>
|
||||
** [[SQLITE_STMTSTATUS_SORT]] <dt>SQLITE_STMTSTATUS_SORT</dt>
|
||||
** <dd>^This is the number of sort operations that have occurred.
|
||||
** A non-zero value in this counter may indicate an opportunity to
|
||||
** improvement performance through careful use of indices.</dd>
|
||||
**
|
||||
** <dt>SQLITE_STMTSTATUS_AUTOINDEX</dt>
|
||||
** [[SQLITE_STMTSTATUS_AUTOINDEX]] <dt>SQLITE_STMTSTATUS_AUTOINDEX</dt>
|
||||
** <dd>^This is the number of rows inserted into transient indices that
|
||||
** were created automatically in order to help joins run faster.
|
||||
** A non-zero value in this counter may indicate an opportunity to
|
||||
@ -5733,6 +5889,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
|
||||
** the application may discard the parameter after the call to
|
||||
** [sqlite3_config()] returns.)^
|
||||
**
|
||||
** [[the xInit() page cache method]]
|
||||
** ^(The xInit() method is called once for each effective
|
||||
** call to [sqlite3_initialize()])^
|
||||
** (usually only once during the lifetime of the process). ^(The xInit()
|
||||
@ -5743,6 +5900,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
|
||||
** built-in default page cache is used instead of the application defined
|
||||
** page cache.)^
|
||||
**
|
||||
** [[the xShutdown() page cache method]]
|
||||
** ^The xShutdown() method is called by [sqlite3_shutdown()].
|
||||
** It can be used to clean up
|
||||
** any outstanding resources before process shutdown, if required.
|
||||
@ -5757,6 +5915,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
|
||||
** ^SQLite will never invoke xInit() more than once without an intervening
|
||||
** call to xShutdown().
|
||||
**
|
||||
** [[the xCreate() page cache methods]]
|
||||
** ^SQLite invokes the xCreate() method to construct a new cache instance.
|
||||
** SQLite will typically create one cache instance for each open database file,
|
||||
** though this is not guaranteed. ^The
|
||||
@ -5781,6 +5940,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
|
||||
** ^Hence, a cache created with bPurgeable false will
|
||||
** never contain any unpinned pages.
|
||||
**
|
||||
** [[the xCachesize() page cache method]]
|
||||
** ^(The xCachesize() method may be called at any time by SQLite to set the
|
||||
** suggested maximum cache-size (number of pages stored by) the cache
|
||||
** instance passed as the first argument. This is the value configured using
|
||||
@ -5788,9 +5948,11 @@ typedef struct sqlite3_pcache sqlite3_pcache;
|
||||
** parameter, the implementation is not required to do anything with this
|
||||
** value; it is advisory only.
|
||||
**
|
||||
** [[the xPagecount() page cache methods]]
|
||||
** The xPagecount() method must return the number of pages currently
|
||||
** stored in the cache, both pinned and unpinned.
|
||||
**
|
||||
** [[the xFetch() page cache methods]]
|
||||
** The xFetch() method locates a page in the cache and returns a pointer to
|
||||
** the page, or a NULL pointer.
|
||||
** A "page", in this context, means a buffer of szPage bytes aligned at an
|
||||
@ -5819,6 +5981,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
|
||||
** attempt to unpin one or more cache pages by spilling the content of
|
||||
** pinned pages to disk and synching the operating system disk cache.
|
||||
**
|
||||
** [[the xUnpin() page cache method]]
|
||||
** ^xUnpin() is called by SQLite with a pointer to a currently pinned page
|
||||
** as its second argument. If the third parameter, discard, is non-zero,
|
||||
** then the page must be evicted from the cache.
|
||||
@ -5831,6 +5994,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
|
||||
** call to xUnpin() unpins the page regardless of the number of prior calls
|
||||
** to xFetch().
|
||||
**
|
||||
** [[the xRekey() page cache methods]]
|
||||
** The xRekey() method is used to change the key value associated with the
|
||||
** page passed as the second argument. If the cache
|
||||
** previously contains an entry associated with newKey, it must be
|
||||
@ -5843,6 +6007,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
|
||||
** of these pages are pinned, they are implicitly unpinned, meaning that
|
||||
** they can be safely discarded.
|
||||
**
|
||||
** [[the xDestroy() page cache method]]
|
||||
** ^The xDestroy() method is used to delete a cache allocated by xCreate().
|
||||
** All resources associated with the specified cache should be freed. ^After
|
||||
** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*]
|
||||
@ -5905,7 +6070,7 @@ typedef struct sqlite3_backup sqlite3_backup;
|
||||
** There should be exactly one call to sqlite3_backup_finish() for each
|
||||
** successful call to sqlite3_backup_init().
|
||||
**
|
||||
** <b>sqlite3_backup_init()</b>
|
||||
** [[sqlite3_backup_init()]] <b>sqlite3_backup_init()</b>
|
||||
**
|
||||
** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the
|
||||
** [database connection] associated with the destination database
|
||||
@ -5932,7 +6097,7 @@ typedef struct sqlite3_backup sqlite3_backup;
|
||||
** sqlite3_backup_finish() functions to perform the specified backup
|
||||
** operation.
|
||||
**
|
||||
** <b>sqlite3_backup_step()</b>
|
||||
** [[sqlite3_backup_step()]] <b>sqlite3_backup_step()</b>
|
||||
**
|
||||
** ^Function sqlite3_backup_step(B,N) will copy up to N pages between
|
||||
** the source and destination databases specified by [sqlite3_backup] object B.
|
||||
@ -5989,7 +6154,7 @@ typedef struct sqlite3_backup sqlite3_backup;
|
||||
** by the backup operation, then the backup database is automatically
|
||||
** updated at the same time.
|
||||
**
|
||||
** <b>sqlite3_backup_finish()</b>
|
||||
** [[sqlite3_backup_finish()]] <b>sqlite3_backup_finish()</b>
|
||||
**
|
||||
** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the
|
||||
** application wishes to abandon the backup operation, the application
|
||||
@ -6012,7 +6177,8 @@ typedef struct sqlite3_backup sqlite3_backup;
|
||||
** is not a permanent error and does not affect the return value of
|
||||
** sqlite3_backup_finish().
|
||||
**
|
||||
** <b>sqlite3_backup_remaining(), sqlite3_backup_pagecount()</b>
|
||||
** [[sqlite3_backup__remaining()]] [[sqlite3_backup_pagecount()]]
|
||||
** <b>sqlite3_backup_remaining() and sqlite3_backup_pagecount()</b>
|
||||
**
|
||||
** ^Each call to sqlite3_backup_step() sets two values inside
|
||||
** the [sqlite3_backup] object: the number of pages still to be backed
|
||||
@ -6393,9 +6559,6 @@ int sqlite3_wal_checkpoint_v2(
|
||||
** [sqlite3_wal_checkpoint_v2()]. See the [sqlite3_wal_checkpoint_v2()]
|
||||
** documentation for additional information about the meaning and use of
|
||||
** each of these values.
|
||||
**
|
||||
** <dt>SQLITE_CONFIG_GETMUTEX</dt>
|
||||
** <dd> ^(This option takes a single argument which is a pointer to an
|
||||
*/
|
||||
#define SQLITE_CHECKPOINT_PASSIVE 0
|
||||
#define SQLITE_CHECKPOINT_FULL 1
|
||||
@ -6425,37 +6588,36 @@ int sqlite3_vtab_config(sqlite3*, int op, ...);
|
||||
** can use to customize and optimize their behavior.
|
||||
**
|
||||
** <dl>
|
||||
** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT
|
||||
** <dd>If the second argument to [sqlite3_vtab_config()] is
|
||||
** SQLITE_VTAB_CONSTRAINT_SUPPORT, then SQLite expects this function to
|
||||
** have been called with three arguments, the third of which being of
|
||||
** type 'int'. If the third argument is zero, then the virtual table
|
||||
** is indicating that it does not support constraints. In this case if
|
||||
** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], the entire
|
||||
** statement is rolled back as if [ON CONFLICT | OR ABORT] had been
|
||||
** specified as part of the users SQL statement, regardless of the actual
|
||||
** ON CONFLICT mode specified.
|
||||
** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT
|
||||
** <dd>Calls of the form
|
||||
** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported,
|
||||
** where X is an integer. If X is zero, then the [virtual table] whose
|
||||
** [xCreate] or [xConnect] method invoked [sqlite3_vtab_config()] does not
|
||||
** support constraints. In this configuration (which is the default) if
|
||||
** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire
|
||||
** statement is rolled back as if [ON CONFLICT | OR ABORT] had been
|
||||
** specified as part of the users SQL statement, regardless of the actual
|
||||
** ON CONFLICT mode specified.
|
||||
**
|
||||
** If the third argument passed is non-zero, then the virtual table
|
||||
** implementation must guarantee that if [xUpdate] returns
|
||||
** [SQLITE_CONSTRAINT], it does so before any modifications to internal
|
||||
** or persistent data structures have been made. If the [ON CONFLICT]
|
||||
** mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite is able to roll back
|
||||
** a statement or database transaction, and abandon or continue processing
|
||||
** the current SQL statement as appropriate. If the ON CONFLICT mode is
|
||||
** REPLACE and the [xUpdate] method returns [SQLITE_CONSTRAINT], SQLite
|
||||
** handles this as if the ON CONFLICT mode had been ABORT.
|
||||
** If X is non-zero, then the virtual table implementation guarantees
|
||||
** that if [xUpdate] returns [SQLITE_CONSTRAINT], it will do so before
|
||||
** any modifications to internal or persistent data structures have been made.
|
||||
** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite
|
||||
** is able to roll back a statement or database transaction, and abandon
|
||||
** or continue processing the current SQL statement as appropriate.
|
||||
** If the ON CONFLICT mode is REPLACE and the [xUpdate] method returns
|
||||
** [SQLITE_CONSTRAINT], SQLite handles this as if the ON CONFLICT mode
|
||||
** had been ABORT.
|
||||
**
|
||||
** Virtual table implementations that are required to handle OR REPLACE
|
||||
** must do so within the xUpdate method. If a call to the
|
||||
** [sqlite3_vtab_on_conflict()] function indicates that the current ON
|
||||
** CONFLICT policy is REPLACE, the virtual table implementation should
|
||||
** silently replace the appropriate rows within the xUpdate callback and
|
||||
** return SQLITE_OK. Or, if this is not possible, it may return
|
||||
** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT
|
||||
** constraint handling.
|
||||
** Virtual table implementations that are required to handle OR REPLACE
|
||||
** must do so within the [xUpdate] method. If a call to the
|
||||
** [sqlite3_vtab_on_conflict()] function indicates that the current ON
|
||||
** CONFLICT policy is REPLACE, the virtual table implementation should
|
||||
** silently replace the appropriate rows within the xUpdate callback and
|
||||
** return SQLITE_OK. Or, if this is not possible, it may return
|
||||
** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT
|
||||
** constraint handling.
|
||||
** </dl>
|
||||
**
|
||||
*/
|
||||
#define SQLITE_VTAB_CONSTRAINT_SUPPORT 1
|
||||
|
||||
|
@ -804,7 +804,7 @@ struct sqlite3 {
|
||||
int nDb; /* Number of backends currently in use */
|
||||
Db *aDb; /* All backends */
|
||||
int flags; /* Miscellaneous flags. See below */
|
||||
int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */
|
||||
unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */
|
||||
int errCode; /* Most recent error code (SQLITE_*) */
|
||||
int errMask; /* & result codes with this before returning */
|
||||
u8 autoCommit; /* The auto-commit flag. */
|
||||
@ -2432,6 +2432,7 @@ struct Sqlite3Config {
|
||||
int bMemstat; /* True to enable memory status */
|
||||
int bCoreMutex; /* True to enable core mutexing */
|
||||
int bFullMutex; /* True to enable full mutexing */
|
||||
int bOpenUri; /* True to interpret filenames as URIs */
|
||||
int mxStrlen; /* Maximum string length */
|
||||
int szLookaside; /* Default lookaside buffer size */
|
||||
int nLookaside; /* Default lookaside buffer count */
|
||||
@ -2681,6 +2682,8 @@ void sqlite3AddColumnType(Parse*,Token*);
|
||||
void sqlite3AddDefaultValue(Parse*,ExprSpan*);
|
||||
void sqlite3AddCollateType(Parse*, Token*);
|
||||
void sqlite3EndTable(Parse*,Token*,Token*,Select*);
|
||||
int sqlite3ParseUri(const char*,const char*,unsigned int*,
|
||||
sqlite3_vfs**,char**,char **);
|
||||
|
||||
Bitvec *sqlite3BitvecCreate(u32);
|
||||
int sqlite3BitvecTest(Bitvec*, u32);
|
||||
@ -2931,6 +2934,7 @@ char sqlite3ExprAffinity(Expr *pExpr);
|
||||
int sqlite3Atoi64(const char*, i64*, int, u8);
|
||||
void sqlite3Error(sqlite3*, int, const char*,...);
|
||||
void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
|
||||
u8 sqlite3HexToInt(int h);
|
||||
int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
|
||||
const char *sqlite3ErrStr(int);
|
||||
int sqlite3ReadSchema(Parse *pParse);
|
||||
@ -2946,6 +2950,12 @@ int sqlite3AddInt64(i64*,i64);
|
||||
int sqlite3SubInt64(i64*,i64);
|
||||
int sqlite3MulInt64(i64*,i64);
|
||||
int sqlite3AbsInt32(int);
|
||||
#ifdef SQLITE_ENABLE_8_3_NAMES
|
||||
void sqlite3FileSuffix3(const char*, char*);
|
||||
#else
|
||||
# define sqlite3FileSuffix3(X,Y)
|
||||
#endif
|
||||
u8 sqlite3GetBoolean(const char *z);
|
||||
|
||||
const void *sqlite3ValueText(sqlite3_value*, u8);
|
||||
int sqlite3ValueBytes(sqlite3_value*, u8);
|
||||
|
73
src/test1.c
73
src/test1.c
@ -163,6 +163,8 @@ const char *sqlite3TestErrorName(int rc){
|
||||
case SQLITE_IOERR_CHECKRESERVEDLOCK:
|
||||
zName = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break;
|
||||
case SQLITE_IOERR_LOCK: zName = "SQLITE_IOERR_LOCK"; break;
|
||||
case SQLITE_CORRUPT_VTAB: zName = "SQLITE_CORRUPT_VTAB"; break;
|
||||
zName = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break;
|
||||
default: zName = "SQLITE_Unknown"; break;
|
||||
}
|
||||
return zName;
|
||||
@ -3845,6 +3847,76 @@ static int test_open(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_open_v2 FILENAME FLAGS VFS
|
||||
*/
|
||||
static int test_open_v2(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
const char *zFilename;
|
||||
const char *zVfs;
|
||||
int flags = 0;
|
||||
sqlite3 *db;
|
||||
int rc;
|
||||
char zBuf[100];
|
||||
|
||||
int nFlag;
|
||||
Tcl_Obj **apFlag;
|
||||
int i;
|
||||
|
||||
if( objc!=4 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "FILENAME FLAGS VFS");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
zFilename = Tcl_GetString(objv[1]);
|
||||
zVfs = Tcl_GetString(objv[3]);
|
||||
if( zVfs[0]==0x00 ) zVfs = 0;
|
||||
|
||||
rc = Tcl_ListObjGetElements(interp, objv[2], &nFlag, &apFlag);
|
||||
if( rc!=TCL_OK ) return rc;
|
||||
for(i=0; i<nFlag; i++){
|
||||
int iFlag;
|
||||
struct OpenFlag {
|
||||
const char *zFlag;
|
||||
int flag;
|
||||
} aFlag[] = {
|
||||
{ "SQLITE_OPEN_READONLY", SQLITE_OPEN_READONLY },
|
||||
{ "SQLITE_OPEN_READWRITE", SQLITE_OPEN_READWRITE },
|
||||
{ "SQLITE_OPEN_CREATE", SQLITE_OPEN_CREATE },
|
||||
{ "SQLITE_OPEN_DELETEONCLOSE", SQLITE_OPEN_DELETEONCLOSE },
|
||||
{ "SQLITE_OPEN_EXCLUSIVE", SQLITE_OPEN_EXCLUSIVE },
|
||||
{ "SQLITE_OPEN_AUTOPROXY", SQLITE_OPEN_AUTOPROXY },
|
||||
{ "SQLITE_OPEN_MAIN_DB", SQLITE_OPEN_MAIN_DB },
|
||||
{ "SQLITE_OPEN_TEMP_DB", SQLITE_OPEN_TEMP_DB },
|
||||
{ "SQLITE_OPEN_TRANSIENT_DB", SQLITE_OPEN_TRANSIENT_DB },
|
||||
{ "SQLITE_OPEN_MAIN_JOURNAL", SQLITE_OPEN_MAIN_JOURNAL },
|
||||
{ "SQLITE_OPEN_TEMP_JOURNAL", SQLITE_OPEN_TEMP_JOURNAL },
|
||||
{ "SQLITE_OPEN_SUBJOURNAL", SQLITE_OPEN_SUBJOURNAL },
|
||||
{ "SQLITE_OPEN_MASTER_JOURNAL", SQLITE_OPEN_MASTER_JOURNAL },
|
||||
{ "SQLITE_OPEN_NOMUTEX", SQLITE_OPEN_NOMUTEX },
|
||||
{ "SQLITE_OPEN_FULLMUTEX", SQLITE_OPEN_FULLMUTEX },
|
||||
{ "SQLITE_OPEN_SHAREDCACHE", SQLITE_OPEN_SHAREDCACHE },
|
||||
{ "SQLITE_OPEN_PRIVATECACHE", SQLITE_OPEN_PRIVATECACHE },
|
||||
{ "SQLITE_OPEN_WAL", SQLITE_OPEN_WAL },
|
||||
{ "SQLITE_OPEN_URI", SQLITE_OPEN_URI },
|
||||
{ 0, 0 }
|
||||
};
|
||||
rc = Tcl_GetIndexFromObjStruct(interp, apFlag[i], aFlag, sizeof(aFlag[0]),
|
||||
"flag", 0, &iFlag
|
||||
);
|
||||
if( rc!=TCL_OK ) return rc;
|
||||
flags |= aFlag[iFlag].flag;
|
||||
}
|
||||
|
||||
rc = sqlite3_open_v2(zFilename, &db, flags, zVfs);
|
||||
if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
|
||||
Tcl_AppendResult(interp, zBuf, 0);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_open16 filename options
|
||||
*/
|
||||
@ -5593,6 +5665,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "sqlite3_errmsg16", test_errmsg16 ,0 },
|
||||
{ "sqlite3_open", test_open ,0 },
|
||||
{ "sqlite3_open16", test_open16 ,0 },
|
||||
{ "sqlite3_open_v2", test_open_v2 ,0 },
|
||||
{ "sqlite3_complete16", test_complete16 ,0 },
|
||||
|
||||
{ "sqlite3_prepare", test_prepare ,0 },
|
||||
|
@ -78,7 +78,7 @@ static int btree_open(
|
||||
sDb.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
|
||||
sqlite3_mutex_enter(sDb.mutex);
|
||||
}
|
||||
rc = sqlite3BtreeOpen(argv[1], &sDb, &pBt, 0,
|
||||
rc = sqlite3BtreeOpen(sDb.pVfs, argv[1], &sDb, &pBt, 0,
|
||||
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB);
|
||||
if( rc!=SQLITE_OK ){
|
||||
Tcl_AppendResult(interp, errorName(rc), 0);
|
||||
|
@ -73,6 +73,12 @@ static void set_options(Tcl_Interp *interp){
|
||||
Tcl_SetVar2(interp, "sqlite_options", "memdebug", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_8_3_NAMES
|
||||
Tcl_SetVar2(interp, "sqlite_options", "8_3_names", "1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
Tcl_SetVar2(interp, "sqlite_options", "8_3_names", "0", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_MEMSYS3
|
||||
Tcl_SetVar2(interp, "sqlite_options", "mem3", "1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
|
@ -1174,6 +1174,35 @@ static int test_config_error(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** tclcmd: sqlite3_config_uri BOOLEAN
|
||||
**
|
||||
** Invoke sqlite3_config() or sqlite3_db_config() with invalid
|
||||
** opcodes and verify that they return errors.
|
||||
*/
|
||||
static int test_config_uri(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
int rc;
|
||||
int bOpenUri;
|
||||
|
||||
if( objc!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( Tcl_GetBooleanFromObj(interp, objv[1], &bOpenUri) ){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
rc = sqlite3_config(SQLITE_CONFIG_URI, bOpenUri);
|
||||
Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage:
|
||||
**
|
||||
@ -1422,6 +1451,7 @@ int Sqlitetest_malloc_Init(Tcl_Interp *interp){
|
||||
{ "sqlite3_config_memstatus", test_config_memstatus ,0 },
|
||||
{ "sqlite3_config_lookaside", test_config_lookaside ,0 },
|
||||
{ "sqlite3_config_error", test_config_error ,0 },
|
||||
{ "sqlite3_config_uri", test_config_uri ,0 },
|
||||
{ "sqlite3_db_config_lookaside",test_db_config_lookaside ,0 },
|
||||
{ "sqlite3_dump_memsys3", test_dump_memsys3 ,3 },
|
||||
{ "sqlite3_dump_memsys5", test_dump_memsys3 ,5 },
|
||||
|
@ -185,13 +185,77 @@ static void multiplexLeave(void){ sqlite3_mutex_leave(gMultiplex.pMutex); }
|
||||
** than the actual length of the string. For very long strings (greater
|
||||
** than 1GiB) the value returned might be less than the true string length.
|
||||
*/
|
||||
int multiplexStrlen30(const char *z){
|
||||
static int multiplexStrlen30(const char *z){
|
||||
const char *z2 = z;
|
||||
if( z==0 ) return 0;
|
||||
while( *z2 ){ z2++; }
|
||||
return 0x3fffffff & (int)(z2 - z);
|
||||
}
|
||||
|
||||
/*
|
||||
** Create a temporary file name in zBuf. zBuf must be big enough to
|
||||
** hold at pOrigVfs->mxPathname characters. This function departs
|
||||
** from the traditional temporary name generation in the os_win
|
||||
** and os_unix VFS in several ways, but is necessary so that
|
||||
** the file name is known for temporary files (like those used
|
||||
** during vacuum.)
|
||||
**
|
||||
** N.B. This routine assumes your underlying VFS is ok with using
|
||||
** "/" as a directory seperator. This is the default for UNIXs
|
||||
** and is allowed (even mixed) for most versions of Windows.
|
||||
*/
|
||||
static int multiplexGetTempname(sqlite3_vfs *pOrigVfs, int nBuf, char *zBuf){
|
||||
static char zChars[] =
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"0123456789";
|
||||
int i,j;
|
||||
int attempts = 0;
|
||||
int exists = 0;
|
||||
int rc = SQLITE_ERROR;
|
||||
|
||||
/* Check that the output buffer is large enough for
|
||||
** pVfs->mxPathname characters.
|
||||
*/
|
||||
if( pOrigVfs->mxPathname <= nBuf ){
|
||||
char *zTmp = sqlite3_malloc(pOrigVfs->mxPathname);
|
||||
if( zTmp==0 ) return SQLITE_NOMEM;
|
||||
|
||||
/* sqlite3_temp_directory should always be less than
|
||||
** pVfs->mxPathname characters.
|
||||
*/
|
||||
sqlite3_snprintf(pOrigVfs->mxPathname,
|
||||
zTmp,
|
||||
"%s/",
|
||||
sqlite3_temp_directory ? sqlite3_temp_directory : ".");
|
||||
rc = pOrigVfs->xFullPathname(pOrigVfs, zTmp, nBuf, zBuf);
|
||||
sqlite3_free(zTmp);
|
||||
if( rc ) return rc;
|
||||
|
||||
/* Check that the output buffer is large enough for the temporary file
|
||||
** name.
|
||||
*/
|
||||
j = multiplexStrlen30(zBuf);
|
||||
if( (j + 8 + 1 + 3 + 1) <= nBuf ){
|
||||
/* Make 3 attempts to generate a unique name. */
|
||||
do {
|
||||
attempts++;
|
||||
sqlite3_randomness(8, &zBuf[j]);
|
||||
for(i=0; i<8; i++){
|
||||
zBuf[j+i] = (char)zChars[ ((unsigned char)zBuf[j+i])%(sizeof(zChars)-1) ];
|
||||
}
|
||||
memcpy(&zBuf[j+i], ".tmp", 5);
|
||||
rc = pOrigVfs->xAccess(pOrigVfs, zBuf, SQLITE_ACCESS_EXISTS, &exists);
|
||||
} while ( (rc==SQLITE_OK) && exists && (attempts<3) );
|
||||
if( rc==SQLITE_OK && exists ){
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Translate an sqlite3_file* that is really a multiplexGroup* into
|
||||
** the sqlite3_file* for the underlying original VFS.
|
||||
*/
|
||||
@ -295,12 +359,12 @@ static int multiplexOpen(
|
||||
int flags, /* Flags to control the opening */
|
||||
int *pOutFlags /* Flags showing results of opening */
|
||||
){
|
||||
int rc; /* Result code */
|
||||
int rc = SQLITE_OK; /* Result code */
|
||||
multiplexConn *pMultiplexOpen; /* The new multiplex file descriptor */
|
||||
multiplexGroup *pGroup; /* Corresponding multiplexGroup object */
|
||||
sqlite3_file *pSubOpen; /* Real file descriptor */
|
||||
sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */
|
||||
int nName = multiplexStrlen30(zName);
|
||||
int nName;
|
||||
int i;
|
||||
int sz;
|
||||
|
||||
@ -311,23 +375,39 @@ static int multiplexOpen(
|
||||
*/
|
||||
multiplexEnter();
|
||||
pMultiplexOpen = (multiplexConn*)pConn;
|
||||
/* allocate space for group */
|
||||
sz = sizeof(multiplexGroup) /* multiplexGroup */
|
||||
+ (sizeof(sqlite3_file *)*SQLITE_MULTIPLEX_MAX_CHUNKS) /* pReal[] */
|
||||
+ (pOrigVfs->szOsFile*SQLITE_MULTIPLEX_MAX_CHUNKS) /* *pReal */
|
||||
+ SQLITE_MULTIPLEX_MAX_CHUNKS /* bOpen[] */
|
||||
+ nName + 1; /* zName */
|
||||
|
||||
/* If the second argument to this function is NULL, generate a
|
||||
** temporary file name to use. This will be handled by the
|
||||
** original xOpen method. We just need to allocate space for
|
||||
** it.
|
||||
*/
|
||||
if( !zName ){
|
||||
rc = multiplexGetTempname(pOrigVfs, pOrigVfs->mxPathname, gMultiplex.zName);
|
||||
zName = gMultiplex.zName;
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
/* allocate space for group */
|
||||
nName = multiplexStrlen30(zName);
|
||||
sz = sizeof(multiplexGroup) /* multiplexGroup */
|
||||
+ (sizeof(sqlite3_file *)*SQLITE_MULTIPLEX_MAX_CHUNKS) /* pReal[] */
|
||||
+ (pOrigVfs->szOsFile*SQLITE_MULTIPLEX_MAX_CHUNKS) /* *pReal */
|
||||
+ SQLITE_MULTIPLEX_MAX_CHUNKS /* bOpen[] */
|
||||
+ nName + 1; /* zName */
|
||||
#ifndef SQLITE_MULTIPLEX_EXT_OVWR
|
||||
sz += SQLITE_MULTIPLEX_EXT_SZ;
|
||||
assert(nName+SQLITE_MULTIPLEX_EXT_SZ < pOrigVfs->mxPathname);
|
||||
sz += SQLITE_MULTIPLEX_EXT_SZ;
|
||||
assert(nName+SQLITE_MULTIPLEX_EXT_SZ < pOrigVfs->mxPathname);
|
||||
#else
|
||||
assert(nName >= SQLITE_MULTIPLEX_EXT_SZ);
|
||||
assert(nName < pOrigVfs->mxPathname);
|
||||
assert(nName >= SQLITE_MULTIPLEX_EXT_SZ);
|
||||
assert(nName < pOrigVfs->mxPathname);
|
||||
#endif
|
||||
pGroup = sqlite3_malloc( sz );
|
||||
if( pGroup==0 ){
|
||||
rc=SQLITE_NOMEM;
|
||||
}else{
|
||||
pGroup = sqlite3_malloc( sz );
|
||||
if( pGroup==0 ){
|
||||
rc=SQLITE_NOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
/* assign pointers to extra space allocated */
|
||||
char *p = (char *)&pGroup[1];
|
||||
pMultiplexOpen->pGroup = pGroup;
|
||||
@ -411,7 +491,7 @@ static int multiplexDelete(
|
||||
}
|
||||
rc2 = pOrigVfs->xAccess(pOrigVfs, gMultiplex.zName,
|
||||
SQLITE_ACCESS_EXISTS, &exists);
|
||||
if( rc2==SQLITE_OK && exists){
|
||||
if( rc2==SQLITE_OK && exists ){
|
||||
/* if it exists, delete it */
|
||||
rc2 = pOrigVfs->xDelete(pOrigVfs, gMultiplex.zName, syncDir);
|
||||
if( rc2!=SQLITE_OK ) rc = rc2;
|
||||
|
@ -114,20 +114,21 @@ struct Testvfs {
|
||||
** + Simulating IO errors, and
|
||||
** + Invoking the Tcl callback script.
|
||||
*/
|
||||
#define TESTVFS_SHMOPEN_MASK 0x00000001
|
||||
#define TESTVFS_SHMLOCK_MASK 0x00000010
|
||||
#define TESTVFS_SHMMAP_MASK 0x00000020
|
||||
#define TESTVFS_SHMBARRIER_MASK 0x00000040
|
||||
#define TESTVFS_SHMCLOSE_MASK 0x00000080
|
||||
#define TESTVFS_SHMOPEN_MASK 0x00000001
|
||||
#define TESTVFS_SHMLOCK_MASK 0x00000010
|
||||
#define TESTVFS_SHMMAP_MASK 0x00000020
|
||||
#define TESTVFS_SHMBARRIER_MASK 0x00000040
|
||||
#define TESTVFS_SHMCLOSE_MASK 0x00000080
|
||||
|
||||
#define TESTVFS_OPEN_MASK 0x00000100
|
||||
#define TESTVFS_SYNC_MASK 0x00000200
|
||||
#define TESTVFS_DELETE_MASK 0x00000400
|
||||
#define TESTVFS_CLOSE_MASK 0x00000800
|
||||
#define TESTVFS_WRITE_MASK 0x00001000
|
||||
#define TESTVFS_TRUNCATE_MASK 0x00002000
|
||||
#define TESTVFS_ACCESS_MASK 0x00004000
|
||||
#define TESTVFS_ALL_MASK 0x00007FFF
|
||||
#define TESTVFS_OPEN_MASK 0x00000100
|
||||
#define TESTVFS_SYNC_MASK 0x00000200
|
||||
#define TESTVFS_DELETE_MASK 0x00000400
|
||||
#define TESTVFS_CLOSE_MASK 0x00000800
|
||||
#define TESTVFS_WRITE_MASK 0x00001000
|
||||
#define TESTVFS_TRUNCATE_MASK 0x00002000
|
||||
#define TESTVFS_ACCESS_MASK 0x00004000
|
||||
#define TESTVFS_FULLPATHNAME_MASK 0x00008000
|
||||
#define TESTVFS_ALL_MASK 0x0001FFFF
|
||||
|
||||
|
||||
#define TESTVFS_MAX_PAGES 1024
|
||||
@ -545,7 +546,7 @@ static int tvfsOpen(
|
||||
|
||||
/* Evaluate the Tcl script:
|
||||
**
|
||||
** SCRIPT xOpen FILENAME
|
||||
** SCRIPT xOpen FILENAME KEY-VALUE-ARGS
|
||||
**
|
||||
** If the script returns an SQLite error code other than SQLITE_OK, an
|
||||
** error is returned to the caller. If it returns SQLITE_OK, the new
|
||||
@ -554,7 +555,19 @@ static int tvfsOpen(
|
||||
*/
|
||||
Tcl_ResetResult(p->interp);
|
||||
if( p->pScript && p->mask&TESTVFS_OPEN_MASK ){
|
||||
tvfsExecTcl(p, "xOpen", Tcl_NewStringObj(pFd->zFilename, -1), 0, 0);
|
||||
Tcl_Obj *pArg = Tcl_NewObj();
|
||||
Tcl_IncrRefCount(pArg);
|
||||
if( flags&SQLITE_OPEN_MAIN_DB ){
|
||||
const char *z = &zName[strlen(zName)+1];
|
||||
while( *z ){
|
||||
Tcl_ListObjAppendElement(0, pArg, Tcl_NewStringObj(z, -1));
|
||||
z += strlen(z) + 1;
|
||||
Tcl_ListObjAppendElement(0, pArg, Tcl_NewStringObj(z, -1));
|
||||
z += strlen(z) + 1;
|
||||
}
|
||||
}
|
||||
tvfsExecTcl(p, "xOpen", Tcl_NewStringObj(pFd->zFilename, -1), pArg, 0);
|
||||
Tcl_DecrRefCount(pArg);
|
||||
if( tvfsResultCode(p, &rc) ){
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
}else{
|
||||
@ -663,6 +676,14 @@ static int tvfsFullPathname(
|
||||
int nOut,
|
||||
char *zOut
|
||||
){
|
||||
Testvfs *p = (Testvfs *)pVfs->pAppData;
|
||||
if( p->pScript && p->mask&TESTVFS_FULLPATHNAME_MASK ){
|
||||
int rc;
|
||||
tvfsExecTcl(p, "xFullPathname", Tcl_NewStringObj(zPath, -1), 0, 0);
|
||||
if( tvfsResultCode(p, &rc) ){
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
}
|
||||
}
|
||||
return sqlite3OsFullPathname(PARENTVFS(pVfs), zPath, nOut, zOut);
|
||||
}
|
||||
|
||||
@ -1028,18 +1049,19 @@ static int testvfs_obj_cmd(
|
||||
char *zName;
|
||||
int mask;
|
||||
} vfsmethod [] = {
|
||||
{ "xShmOpen", TESTVFS_SHMOPEN_MASK },
|
||||
{ "xShmLock", TESTVFS_SHMLOCK_MASK },
|
||||
{ "xShmBarrier", TESTVFS_SHMBARRIER_MASK },
|
||||
{ "xShmUnmap", TESTVFS_SHMCLOSE_MASK },
|
||||
{ "xShmMap", TESTVFS_SHMMAP_MASK },
|
||||
{ "xSync", TESTVFS_SYNC_MASK },
|
||||
{ "xDelete", TESTVFS_DELETE_MASK },
|
||||
{ "xWrite", TESTVFS_WRITE_MASK },
|
||||
{ "xTruncate", TESTVFS_TRUNCATE_MASK },
|
||||
{ "xOpen", TESTVFS_OPEN_MASK },
|
||||
{ "xClose", TESTVFS_CLOSE_MASK },
|
||||
{ "xAccess", TESTVFS_ACCESS_MASK },
|
||||
{ "xShmOpen", TESTVFS_SHMOPEN_MASK },
|
||||
{ "xShmLock", TESTVFS_SHMLOCK_MASK },
|
||||
{ "xShmBarrier", TESTVFS_SHMBARRIER_MASK },
|
||||
{ "xShmUnmap", TESTVFS_SHMCLOSE_MASK },
|
||||
{ "xShmMap", TESTVFS_SHMMAP_MASK },
|
||||
{ "xSync", TESTVFS_SYNC_MASK },
|
||||
{ "xDelete", TESTVFS_DELETE_MASK },
|
||||
{ "xWrite", TESTVFS_WRITE_MASK },
|
||||
{ "xTruncate", TESTVFS_TRUNCATE_MASK },
|
||||
{ "xOpen", TESTVFS_OPEN_MASK },
|
||||
{ "xClose", TESTVFS_CLOSE_MASK },
|
||||
{ "xAccess", TESTVFS_ACCESS_MASK },
|
||||
{ "xFullPathname", TESTVFS_FULLPATHNAME_MASK },
|
||||
};
|
||||
Tcl_Obj **apElem = 0;
|
||||
int nElem = 0;
|
||||
|
32
src/util.c
32
src/util.c
@ -983,13 +983,12 @@ void sqlite3Put4byte(unsigned char *p, u32 v){
|
||||
|
||||
|
||||
|
||||
#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
|
||||
/*
|
||||
** Translate a single byte of Hex into an integer.
|
||||
** This routine only works if h really is a valid hexadecimal
|
||||
** character: 0..9a..fA..F
|
||||
*/
|
||||
static u8 hexToInt(int h){
|
||||
u8 sqlite3HexToInt(int h){
|
||||
assert( (h>='0' && h<='9') || (h>='a' && h<='f') || (h>='A' && h<='F') );
|
||||
#ifdef SQLITE_ASCII
|
||||
h += 9*(1&(h>>6));
|
||||
@ -999,7 +998,6 @@ static u8 hexToInt(int h){
|
||||
#endif
|
||||
return (u8)(h & 0xf);
|
||||
}
|
||||
#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */
|
||||
|
||||
#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
|
||||
/*
|
||||
@ -1016,7 +1014,7 @@ void *sqlite3HexToBlob(sqlite3 *db, const char *z, int n){
|
||||
n--;
|
||||
if( zBlob ){
|
||||
for(i=0; i<n; i+=2){
|
||||
zBlob[i/2] = (hexToInt(z[i])<<4) | hexToInt(z[i+1]);
|
||||
zBlob[i/2] = (sqlite3HexToInt(z[i])<<4) | sqlite3HexToInt(z[i+1]);
|
||||
}
|
||||
zBlob[i/2] = 0;
|
||||
}
|
||||
@ -1148,3 +1146,29 @@ int sqlite3AbsInt32(int x){
|
||||
if( x==(int)0x80000000 ) return 0x7fffffff;
|
||||
return -x;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_8_3_NAMES
|
||||
/*
|
||||
** If SQLITE_ENABLE_8_3_NAME is set at compile-time and if the database
|
||||
** filename in zBaseFilename is a URI with the "8_3_names=1" parameter and
|
||||
** if filename in z[] has a suffix (a.k.a. "extension") that is longer than
|
||||
** three characters, then shorten the suffix on z[] to be the last three
|
||||
** characters of the original suffix.
|
||||
**
|
||||
** Examples:
|
||||
**
|
||||
** test.db-journal => test.nal
|
||||
** test.db-wal => test.wal
|
||||
** test.db-shm => test.shm
|
||||
*/
|
||||
void sqlite3FileSuffix3(const char *zBaseFilename, char *z){
|
||||
const char *zOk;
|
||||
zOk = sqlite3_uri_parameter(zBaseFilename, "8_3_names");
|
||||
if( zOk && sqlite3GetBoolean(zOk) ){
|
||||
int i, sz;
|
||||
sz = sqlite3Strlen30(z);
|
||||
for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
|
||||
if( z[i]=='.' && ALWAYS(sz>i+4) ) memcpy(&z[i+1], &z[sz-3], 4);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
15
src/vdbe.c
15
src/vdbe.c
@ -574,6 +574,7 @@ int sqlite3VdbeExec(
|
||||
Mem *pOut = 0; /* Output operand */
|
||||
int iCompare = 0; /* Result of last OP_Compare operation */
|
||||
int *aPermute = 0; /* Permutation of columns for OP_Compare */
|
||||
i64 lastRowid = db->lastRowid; /* Saved value of the last insert ROWID */
|
||||
#ifdef VDBE_PROFILE
|
||||
u64 start; /* CPU clock count at start of opcode */
|
||||
int origPc; /* Program counter at start of opcode */
|
||||
@ -843,6 +844,7 @@ case OP_Halt: {
|
||||
p->nFrame--;
|
||||
sqlite3VdbeSetChanges(db, p->nChange);
|
||||
pc = sqlite3VdbeFrameRestore(pFrame);
|
||||
lastRowid = db->lastRowid;
|
||||
if( pOp->p2==OE_Ignore ){
|
||||
/* Instruction pc is the OP_Program that invoked the sub-program
|
||||
** currently being halted. If the p2 instruction of this OP_Halt
|
||||
@ -1403,7 +1405,9 @@ case OP_Function: {
|
||||
assert( pOp[-1].opcode==OP_CollSeq );
|
||||
ctx.pColl = pOp[-1].p4.pColl;
|
||||
}
|
||||
db->lastRowid = lastRowid;
|
||||
(*ctx.pFunc->xFunc)(&ctx, n, apVal); /* IMP: R-24505-23230 */
|
||||
lastRowid = db->lastRowid;
|
||||
if( db->mallocFailed ){
|
||||
/* Even though a malloc() has failed, the implementation of the
|
||||
** user function may have called an sqlite3_result_XXX() function
|
||||
@ -3159,7 +3163,7 @@ case OP_OpenEphemeral: {
|
||||
pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
|
||||
if( pCx==0 ) goto no_mem;
|
||||
pCx->nullRow = 1;
|
||||
rc = sqlite3BtreeOpen(0, db, &pCx->pBt,
|
||||
rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBt,
|
||||
BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3BtreeBeginTrans(pCx->pBt, 1);
|
||||
@ -3819,7 +3823,7 @@ case OP_NewRowid: { /* out2-prerelease */
|
||||
assert( pOp->p3==0 ); /* We cannot be in random rowid mode if this is
|
||||
** an AUTOINCREMENT table. */
|
||||
/* on the first attempt, simply do one more than previous */
|
||||
v = db->lastRowid;
|
||||
v = lastRowid;
|
||||
v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
|
||||
v++; /* ensure non-zero */
|
||||
cnt = 0;
|
||||
@ -3948,7 +3952,7 @@ case OP_InsertInt: {
|
||||
#endif
|
||||
|
||||
if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
|
||||
if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = iKey;
|
||||
if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = iKey;
|
||||
if( pData->flags & MEM_Null ){
|
||||
pData->z = 0;
|
||||
pData->n = 0;
|
||||
@ -5059,7 +5063,7 @@ case OP_Program: { /* jump */
|
||||
|
||||
p->nFrame++;
|
||||
pFrame->pParent = p->pFrame;
|
||||
pFrame->lastRowid = db->lastRowid;
|
||||
pFrame->lastRowid = lastRowid;
|
||||
pFrame->nChange = p->nChange;
|
||||
p->nChange = 0;
|
||||
p->pFrame = pFrame;
|
||||
@ -5866,7 +5870,7 @@ case OP_VUpdate: {
|
||||
importVtabErrMsg(p, pVtab);
|
||||
if( rc==SQLITE_OK && pOp->p1 ){
|
||||
assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) );
|
||||
db->lastRowid = rowid;
|
||||
db->lastRowid = lastRowid = rowid;
|
||||
}
|
||||
if( rc==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
|
||||
if( pOp->p5==OE_Ignore ){
|
||||
@ -6024,6 +6028,7 @@ vdbe_error_halt:
|
||||
** release the mutexes on btrees that were acquired at the
|
||||
** top. */
|
||||
vdbe_return:
|
||||
db->lastRowid = lastRowid;
|
||||
sqlite3VdbeLeave(p);
|
||||
return rc;
|
||||
|
||||
|
@ -1800,6 +1800,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
|
||||
if( !zMaster ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
sqlite3FileSuffix3(zMainFile, zMaster);
|
||||
rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res);
|
||||
}while( rc==SQLITE_OK && res );
|
||||
if( rc==SQLITE_OK ){
|
||||
|
@ -874,7 +874,7 @@ int sqlite3VtabSavepoint(sqlite3 *db, int op, int iSavepoint){
|
||||
int i;
|
||||
for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){
|
||||
const sqlite3_module *pMod = db->aVTrans[i]->pMod->pModule;
|
||||
if( pMod->iVersion>=1 ){
|
||||
if( pMod->iVersion>=2 ){
|
||||
int (*xMethod)(sqlite3_vtab *, int);
|
||||
switch( op ){
|
||||
case SAVEPOINT_BEGIN:
|
||||
@ -1001,7 +1001,7 @@ void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){
|
||||
*/
|
||||
int sqlite3_vtab_on_conflict(sqlite3 *db){
|
||||
static const unsigned char aMap[] = {
|
||||
SQLITE_ROLLBACK, SQLITE_IGNORE, SQLITE_ABORT, SQLITE_FAIL, SQLITE_REPLACE
|
||||
SQLITE_ROLLBACK, SQLITE_ABORT, SQLITE_FAIL, SQLITE_IGNORE, SQLITE_REPLACE
|
||||
};
|
||||
assert( OE_Rollback==1 && OE_Abort==2 && OE_Fail==3 );
|
||||
assert( OE_Ignore==4 && OE_Replace==5 );
|
||||
@ -1027,7 +1027,7 @@ int sqlite3_vtab_config(sqlite3 *db, int op, ...){
|
||||
if( !p ){
|
||||
rc = SQLITE_MISUSE_BKPT;
|
||||
}else{
|
||||
assert( (p->pTab->tabFlags & TF_Virtual)!=0 );
|
||||
assert( p->pTab==0 || (p->pTab->tabFlags & TF_Virtual)!=0 );
|
||||
p->pVTable->bConstraint = (u8)va_arg(ap, int);
|
||||
}
|
||||
break;
|
||||
|
26
src/wal.c
26
src/wal.c
@ -412,6 +412,7 @@ struct Wal {
|
||||
sqlite3_file *pDbFd; /* File handle for the database file */
|
||||
sqlite3_file *pWalFd; /* File handle for WAL file */
|
||||
u32 iCallback; /* Value to pass to log callback (or 0) */
|
||||
i64 mxWalSize; /* Truncate WAL to this size upon reset */
|
||||
int nWiData; /* Size of array apWiData */
|
||||
volatile u32 **apWiData; /* Pointer to wal-index content in memory */
|
||||
u32 szPage; /* Database page size */
|
||||
@ -1234,6 +1235,7 @@ int sqlite3WalOpen(
|
||||
sqlite3_file *pDbFd, /* The open database file */
|
||||
const char *zWalName, /* Name of the WAL file */
|
||||
int bNoShm, /* True to run in heap-memory mode */
|
||||
i64 mxWalSize, /* Truncate WAL to this size on reset */
|
||||
Wal **ppWal /* OUT: Allocated Wal handle */
|
||||
){
|
||||
int rc; /* Return Code */
|
||||
@ -1266,6 +1268,7 @@ int sqlite3WalOpen(
|
||||
pRet->pWalFd = (sqlite3_file *)&pRet[1];
|
||||
pRet->pDbFd = pDbFd;
|
||||
pRet->readLock = -1;
|
||||
pRet->mxWalSize = mxWalSize;
|
||||
pRet->zWalName = zWalName;
|
||||
pRet->exclusiveMode = (bNoShm ? WAL_HEAPMEMORY_MODE: WAL_NORMAL_MODE);
|
||||
|
||||
@ -1287,6 +1290,13 @@ int sqlite3WalOpen(
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Change the size to which the WAL file is trucated on each reset.
|
||||
*/
|
||||
void sqlite3WalLimit(Wal *pWal, i64 iLimit){
|
||||
if( pWal ) pWal->mxWalSize = iLimit;
|
||||
}
|
||||
|
||||
/*
|
||||
** Find the smallest page number out of all pages held in the WAL that
|
||||
** has not been returned by any prior invocation of this method on the
|
||||
@ -2522,6 +2532,22 @@ static int walRestartLog(Wal *pWal){
|
||||
*/
|
||||
int i; /* Loop counter */
|
||||
u32 *aSalt = pWal->hdr.aSalt; /* Big-endian salt values */
|
||||
|
||||
/* Limit the size of WAL file if the journal_size_limit PRAGMA is
|
||||
** set to a non-negative value. Log errors encountered
|
||||
** during the truncation attempt. */
|
||||
if( pWal->mxWalSize>=0 ){
|
||||
i64 sz;
|
||||
int rx;
|
||||
rx = sqlite3OsFileSize(pWal->pWalFd, &sz);
|
||||
if( rx==SQLITE_OK && (sz > pWal->mxWalSize) ){
|
||||
rx = sqlite3OsTruncate(pWal->pWalFd, pWal->mxWalSize);
|
||||
}
|
||||
if( rx ){
|
||||
sqlite3_log(rx, "cannot limit WAL size: %s", pWal->zWalName);
|
||||
}
|
||||
}
|
||||
|
||||
pWal->nCkpt++;
|
||||
pWal->hdr.mxFrame = 0;
|
||||
sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0]));
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#ifdef SQLITE_OMIT_WAL
|
||||
# define sqlite3WalOpen(x,y,z) 0
|
||||
# define sqlite3WalLimit(x,y)
|
||||
# define sqlite3WalClose(w,x,y,z) 0
|
||||
# define sqlite3WalBeginReadTransaction(y,z) 0
|
||||
# define sqlite3WalEndReadTransaction(z)
|
||||
@ -46,9 +47,12 @@
|
||||
typedef struct Wal Wal;
|
||||
|
||||
/* Open and close a connection to a write-ahead log. */
|
||||
int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *zName, int, Wal**);
|
||||
int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**);
|
||||
int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *);
|
||||
|
||||
/* Set the limiting size of a WAL file. */
|
||||
void sqlite3WalLimit(Wal*, i64);
|
||||
|
||||
/* Used by readers to open (lock) and close (unlock) a snapshot. A
|
||||
** snapshot is like a read-transaction. It is the state of the database
|
||||
** at an instant in time. sqlite3WalOpenSnapshot gets a read lock and
|
||||
|
197
test/8_3_names.test
Normal file
197
test/8_3_names.test
Normal file
@ -0,0 +1,197 @@
|
||||
# 2011 May 17
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# Test cases for the SQLITE_ENABLE_8_3_NAMES feature that forces all
|
||||
# filename extensions to be limited to 3 characters. Some embedded
|
||||
# systems need this to work around microsoft FAT patents, but this
|
||||
# feature should be disabled on most deployments.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !8_3_names {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_uri 1
|
||||
|
||||
do_test 8_3_names-1.0 {
|
||||
forcedelete test.db test.nal test.db-journal
|
||||
sqlite3 db test.db
|
||||
db eval {
|
||||
PRAGMA cache_size=10;
|
||||
CREATE TABLE t1(x);
|
||||
INSERT INTO t1 VALUES(randomblob(20000));
|
||||
BEGIN;
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1 VALUES(randomblob(15000));
|
||||
}
|
||||
file exists test.db-journal
|
||||
} 1
|
||||
do_test 8_3_names-1.1 {
|
||||
file exists test.nal
|
||||
} 0
|
||||
do_test 8_3_names-1.2 {
|
||||
db eval {
|
||||
ROLLBACK;
|
||||
SELECT length(x) FROM t1
|
||||
}
|
||||
} 20000
|
||||
|
||||
db close
|
||||
do_test 8_3_names-2.0 {
|
||||
forcedelete test.db test.nal test.db-journal
|
||||
sqlite3 db file:./test.db?8_3_names=1
|
||||
db eval {
|
||||
PRAGMA cache_size=10;
|
||||
CREATE TABLE t1(x);
|
||||
INSERT INTO t1 VALUES(randomblob(20000));
|
||||
BEGIN;
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1 VALUES(randomblob(15000));
|
||||
}
|
||||
file exists test.db-journal
|
||||
} 0
|
||||
do_test 8_3_names-2.1 {
|
||||
file exists test.nal
|
||||
} 1
|
||||
forcedelete test2.db test2.nal test2.db-journal
|
||||
file copy test.db test2.db
|
||||
file copy test.nal test2.nal
|
||||
do_test 8_3_names-2.2 {
|
||||
db eval {
|
||||
COMMIT;
|
||||
SELECT length(x) FROM t1
|
||||
}
|
||||
} 15000
|
||||
do_test 8_3_names-2.3 {
|
||||
sqlite3 db2 file:./test2.db?8_3_names=1
|
||||
db2 eval {
|
||||
PRAGMA integrity_check;
|
||||
SELECT length(x) FROM t1;
|
||||
}
|
||||
} {ok 20000}
|
||||
|
||||
db close
|
||||
do_test 8_3_names-3.0 {
|
||||
forcedelete test.db test.nal test.db-journal
|
||||
sqlite3 db file:./test.db?8_3_names=0
|
||||
db eval {
|
||||
PRAGMA cache_size=10;
|
||||
CREATE TABLE t1(x);
|
||||
INSERT INTO t1 VALUES(randomblob(20000));
|
||||
BEGIN;
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1 VALUES(randomblob(15000));
|
||||
}
|
||||
file exists test.db-journal
|
||||
} 1
|
||||
do_test 8_3_names-3.1 {
|
||||
file exists test.nal
|
||||
} 0
|
||||
forcedelete test2.db test2.nal test2.db-journal
|
||||
file copy test.db test2.db
|
||||
file copy test.db-journal test2.db-journal
|
||||
do_test 8_3_names-3.2 {
|
||||
db eval {
|
||||
COMMIT;
|
||||
SELECT length(x) FROM t1
|
||||
}
|
||||
} 15000
|
||||
do_test 8_3_names-3.3 {
|
||||
sqlite3 db2 file:./test2.db?8_3_names=0
|
||||
db2 eval {
|
||||
PRAGMA integrity_check;
|
||||
SELECT length(x) FROM t1;
|
||||
}
|
||||
} {ok 20000}
|
||||
|
||||
##########################################################################
|
||||
# Master journals.
|
||||
#
|
||||
db close
|
||||
forcedelete test.db test2.db
|
||||
do_test 8_3_names-4.0 {
|
||||
sqlite3 db file:./test.db?8_3_names=1
|
||||
db eval {
|
||||
CREATE TABLE t1(x);
|
||||
INSERT INTO t1 VALUES(1);
|
||||
ATTACH 'file:./test2.db?8_3_names=1' AS db2;
|
||||
CREATE TABLE db2.t2(y);
|
||||
INSERT INTO t2 VALUES(2);
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES(3);
|
||||
INSERT INTO t2 VALUES(4);
|
||||
COMMIT;
|
||||
SELECT * FROM t1, t2 ORDER BY x, y
|
||||
}
|
||||
} {1 2 1 4 3 2 3 4}
|
||||
|
||||
|
||||
##########################################################################
|
||||
# WAL mode.
|
||||
#
|
||||
ifcapable !wal {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
db close
|
||||
forcedelete test.db
|
||||
do_test 8_3_names-5.0 {
|
||||
sqlite3 db file:./test.db?8_3_names=1
|
||||
register_wholenumber_module db
|
||||
db eval {
|
||||
PRAGMA journal_mode=WAL;
|
||||
CREATE TABLE t1(x);
|
||||
CREATE VIRTUAL TABLE nums USING wholenumber;
|
||||
INSERT INTO t1 SELECT value FROM nums WHERE value BETWEEN 1 AND 1000;
|
||||
BEGIN;
|
||||
UPDATE t1 SET x=x*2;
|
||||
}
|
||||
sqlite3 db2 file:./test.db?8_3_names=1
|
||||
register_wholenumber_module db2
|
||||
db2 eval {
|
||||
BEGIN;
|
||||
SELECT sum(x) FROM t1;
|
||||
}
|
||||
} {500500}
|
||||
|
||||
do_test 8_3_names-5.1 {
|
||||
file exists test.db-wal
|
||||
} 0
|
||||
do_test 8_3_names-5.2 {
|
||||
file exists test.wal
|
||||
} 1
|
||||
do_test 8_3_names-5.3 {
|
||||
file exists test.db-shm
|
||||
} 0
|
||||
do_test 8_3_names-5.4 {
|
||||
file exists test.shm
|
||||
} 1
|
||||
|
||||
|
||||
do_test 8_3_names-5.5 {
|
||||
db eval {
|
||||
COMMIT;
|
||||
SELECT sum(x) FROM t1;
|
||||
}
|
||||
} {1001000}
|
||||
do_test 8_3_names-5.6 {
|
||||
db2 eval {
|
||||
SELECT sum(x) FROM t1;
|
||||
}
|
||||
} {500500}
|
||||
|
||||
|
||||
finish_test
|
@ -650,7 +650,7 @@ do_test alter-6.7 {
|
||||
# Ticket #1665: Make sure ALTER TABLE ADD COLUMN works on a table
|
||||
# that includes a COLLATE clause.
|
||||
#
|
||||
do_test alter-7.1 {
|
||||
do_realnum_test alter-7.1 {
|
||||
execsql {
|
||||
CREATE TABLE t1(a TEXT COLLATE BINARY);
|
||||
ALTER TABLE t1 ADD COLUMN b INTEGER COLLATE NOCASE;
|
||||
|
@ -234,7 +234,7 @@ do_test cast-3.1 {
|
||||
do_test cast-3.2 {
|
||||
execsql {SELECT CAST(9223372036854774800 AS numeric)}
|
||||
} 9223372036854774800
|
||||
do_test cast-3.3 {
|
||||
do_realnum_test cast-3.3 {
|
||||
execsql {SELECT CAST(9223372036854774800 AS real)}
|
||||
} 9.22337203685477e+18
|
||||
do_test cast-3.4 {
|
||||
@ -246,7 +246,7 @@ do_test cast-3.5 {
|
||||
do_test cast-3.6 {
|
||||
execsql {SELECT CAST(-9223372036854774800 AS numeric)}
|
||||
} -9223372036854774800
|
||||
do_test cast-3.7 {
|
||||
do_realnum_test cast-3.7 {
|
||||
execsql {SELECT CAST(-9223372036854774800 AS real)}
|
||||
} -9.22337203685477e+18
|
||||
do_test cast-3.8 {
|
||||
@ -258,7 +258,7 @@ do_test cast-3.11 {
|
||||
do_test cast-3.12 {
|
||||
execsql {SELECT CAST('9223372036854774800' AS numeric)}
|
||||
} 9223372036854774800
|
||||
do_test cast-3.13 {
|
||||
do_realnum_test cast-3.13 {
|
||||
execsql {SELECT CAST('9223372036854774800' AS real)}
|
||||
} 9.22337203685477e+18
|
||||
ifcapable long_double {
|
||||
@ -272,7 +272,7 @@ do_test cast-3.15 {
|
||||
do_test cast-3.16 {
|
||||
execsql {SELECT CAST('-9223372036854774800' AS numeric)}
|
||||
} -9223372036854774800
|
||||
do_test cast-3.17 {
|
||||
do_realnum_test cast-3.17 {
|
||||
execsql {SELECT CAST('-9223372036854774800' AS real)}
|
||||
} -9.22337203685477e+18
|
||||
ifcapable long_double {
|
||||
@ -287,7 +287,7 @@ if {[db eval {PRAGMA encoding}]=="UTF-8"} {
|
||||
do_test cast-3.22 {
|
||||
execsql {SELECT CAST(x'39323233333732303336383534373734383030' AS numeric)}
|
||||
} 9223372036854774800
|
||||
do_test cast-3.23 {
|
||||
do_realnum_test cast-3.23 {
|
||||
execsql {SELECT CAST(x'39323233333732303336383534373734383030' AS real)}
|
||||
} 9.22337203685477e+18
|
||||
ifcapable long_double {
|
||||
|
456
test/e_uri.test
Normal file
456
test/e_uri.test
Normal file
@ -0,0 +1,456 @@
|
||||
# 2011 May 06
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix e_uri
|
||||
|
||||
db close
|
||||
|
||||
proc parse_uri {uri} {
|
||||
testvfs tvfs2
|
||||
testvfs tvfs
|
||||
tvfs filter xOpen
|
||||
tvfs script parse_uri_open_cb
|
||||
|
||||
set ::uri_open [list]
|
||||
set DB [sqlite3_open_v2 $uri {
|
||||
SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_WAL
|
||||
} tvfs]
|
||||
sqlite3_close $DB
|
||||
tvfs delete
|
||||
tvfs2 delete
|
||||
|
||||
set ::uri_open
|
||||
}
|
||||
proc parse_uri_open_cb {method file arglist} {
|
||||
set ::uri_open [list $file $arglist]
|
||||
}
|
||||
|
||||
proc open_uri_error {uri} {
|
||||
set flags {SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_WAL}
|
||||
set DB [sqlite3_open_v2 $uri $flags ""]
|
||||
set e [sqlite3_errmsg $DB]
|
||||
sqlite3_close $DB
|
||||
set e
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-35840-33204 If URI filename interpretation is enabled,
|
||||
# and the filename argument begins with "file:", then the filename is
|
||||
# interpreted as a URI.
|
||||
#
|
||||
# EVIDENCE-OF: R-00067-59538 URI filename interpretation is enabled if
|
||||
# the SQLITE_OPEN_URI flag is is set in the fourth argument to
|
||||
# sqlite3_open_v2(), or if it has been enabled globally using the
|
||||
# SQLITE_CONFIG_URI option with the sqlite3_config() method.
|
||||
#
|
||||
if {$tcl_platform(platform) == "unix"} {
|
||||
set flags [list SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE]
|
||||
|
||||
# Tests with SQLITE_CONFIG_URI configured to false. URI intepretation is
|
||||
# only enabled if the SQLITE_OPEN_URI flag is specified.
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_uri 0
|
||||
do_test 1.1 {
|
||||
forcedelete file:test.db test.db
|
||||
set DB [sqlite3_open_v2 file:test.db [concat $flags SQLITE_OPEN_URI] ""]
|
||||
list [file exists file:test.db] [file exists test.db]
|
||||
} {0 1}
|
||||
do_test 1.2 {
|
||||
forcedelete file:test.db2 test.db2
|
||||
set STMT [sqlite3_prepare $DB "ATTACH 'file:test.db2' AS aux" -1 dummy]
|
||||
sqlite3_step $STMT
|
||||
sqlite3_finalize $STMT
|
||||
list [file exists file:test.db2] [file exists test.db2]
|
||||
} {0 1}
|
||||
sqlite3_close $DB
|
||||
do_test 1.3 {
|
||||
forcedelete file:test.db test.db
|
||||
set DB [sqlite3_open_v2 file:test.db [concat $flags] ""]
|
||||
list [file exists file:test.db] [file exists test.db]
|
||||
} {1 0}
|
||||
do_test 1.4 {
|
||||
forcedelete file:test.db2 test.db2
|
||||
set STMT [sqlite3_prepare $DB "ATTACH 'file:test.db2' AS aux" -1 dummy]
|
||||
sqlite3_step $STMT
|
||||
sqlite3_finalize $STMT
|
||||
list [file exists file:test.db2] [file exists test.db2]
|
||||
} {1 0}
|
||||
sqlite3_close $DB
|
||||
|
||||
# Tests with SQLITE_CONFIG_URI configured to true. URI intepretation is
|
||||
# enabled with or without SQLITE_OPEN_URI.
|
||||
#
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_uri 1
|
||||
do_test 1.5 {
|
||||
forcedelete file:test.db test.db
|
||||
set DB [sqlite3_open_v2 file:test.db [concat $flags SQLITE_OPEN_URI] ""]
|
||||
list [file exists file:test.db] [file exists test.db]
|
||||
} {0 1}
|
||||
do_test 1.6 {
|
||||
forcedelete file:test.db2 test.db2
|
||||
set STMT [sqlite3_prepare $DB "ATTACH 'file:test.db2' AS aux" -1 dummy]
|
||||
sqlite3_step $STMT
|
||||
sqlite3_finalize $STMT
|
||||
list [file exists file:test.db2] [file exists test.db2]
|
||||
} {0 1}
|
||||
sqlite3_close $DB
|
||||
do_test 1.7 {
|
||||
forcedelete file:test.db test.db
|
||||
set DB [sqlite3_open_v2 file:test.db [concat $flags] ""]
|
||||
list [file exists file:test.db] [file exists test.db]
|
||||
} {0 1}
|
||||
do_test 1.8 {
|
||||
forcedelete file:test.db2 test.db2
|
||||
set STMT [sqlite3_prepare $DB "ATTACH 'file:test.db2' AS aux" -1 dummy]
|
||||
sqlite3_step $STMT
|
||||
sqlite3_finalize $STMT
|
||||
list [file exists file:test.db2] [file exists test.db2]
|
||||
} {0 1}
|
||||
sqlite3_close $DB
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-17482-00398 If the authority is not an empty string or
|
||||
# "localhost", an error is returned to the caller.
|
||||
#
|
||||
if {$tcl_platform(platform) == "unix"} {
|
||||
set flags [list SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_URI]
|
||||
foreach {tn uri error} "
|
||||
1 {file://localhost[pwd]/test.db} {not an error}
|
||||
2 {file://[pwd]/test.db} {not an error}
|
||||
3 {file://x[pwd]/test.db} {invalid uri authority: x}
|
||||
4 {file://invalid[pwd]/test.db} {invalid uri authority: invalid}
|
||||
" {
|
||||
do_test 2.$tn {
|
||||
set DB [sqlite3_open_v2 $uri $flags ""]
|
||||
set e [sqlite3_errmsg $DB]
|
||||
sqlite3_close $DB
|
||||
set e
|
||||
} $error
|
||||
}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-43804-65312 The 'fragment' component of a URI, if
|
||||
# present, is always ignored.
|
||||
#
|
||||
# It is difficult to test that something is ignore correctly. So these tests
|
||||
# just show that adding a fragment does not interfere with the pathname or
|
||||
# parameters passed through to the VFS xOpen() methods.
|
||||
#
|
||||
if {$tcl_platform(platform) == "unix"} {
|
||||
foreach {tn uri parse} "
|
||||
1 {file:test.db#abc} {[pwd]/test.db {}}
|
||||
2 {file:test.db?a=b#abc} {[pwd]/test.db {a b}}
|
||||
3 {file:test.db?a=b#?c=d} {[pwd]/test.db {a b}}
|
||||
" {
|
||||
do_test 3.$tn { parse_uri $uri } $parse
|
||||
}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-00273-20588 SQLite uses the 'path' component of the URI
|
||||
# as the path to the database file to open.
|
||||
#
|
||||
# EVIDENCE-OF: R-28659-11035 If the path begins with a '/' character,
|
||||
# then it is interpreted as an absolute path.
|
||||
#
|
||||
# EVIDENCE-OF: R-39349-47203 If it does not begin with a '/', it is
|
||||
# interpreted as a relative path.
|
||||
#
|
||||
if {$tcl_platform(platform) == "unix"} {
|
||||
foreach {tn uri parse} "
|
||||
1 {file:test.db} {[pwd]/test.db {}}
|
||||
2 {file:/test.db} {/test.db {}}
|
||||
3 {file:///test.db} {/test.db {}}
|
||||
4 {file://localhost/test.db} {/test.db {}}
|
||||
5 {file:/a/b/c/test.db} {/a/b/c/test.db {}}
|
||||
" {
|
||||
do_test 4.$tn { parse_uri $uri } $parse
|
||||
}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-01612-30877 The "vfs" parameter may be used to specify
|
||||
# the name of a VFS object that provides the operating system interface
|
||||
# that should be used to access the database file on disk.
|
||||
#
|
||||
# The above is tested by cases 1.* below.
|
||||
#
|
||||
# EVIDENCE-OF: R-52293-58497 If this option is set to an empty string
|
||||
# the default VFS object is used.
|
||||
#
|
||||
# The above is tested by cases 2.* below.
|
||||
#
|
||||
# EVIDENCE-OF: R-31855-18665 If sqlite3_open_v2() is used and the vfs
|
||||
# option is present, then the VFS specified by the option takes
|
||||
# precedence over the value passed as the fourth parameter to
|
||||
# sqlite3_open_v2().
|
||||
#
|
||||
# The above is tested by cases 3.* below.
|
||||
#
|
||||
proc vfs_open_cb {name args} {
|
||||
set ::vfs $name
|
||||
}
|
||||
foreach {name default} {vfs1 0 vfs2 0 vfs3 1} {
|
||||
testvfs $name -default $default
|
||||
$name filter xOpen
|
||||
$name script [list vfs_open_cb $name]
|
||||
}
|
||||
foreach {tn uri defvfs vfs} {
|
||||
1.1 "file:test.db?vfs=vfs1" "" vfs1
|
||||
1.2 "file:test.db?vfs=vfs2" "" vfs2
|
||||
|
||||
2.1 "file:test.db" vfs1 vfs1
|
||||
2.2 "file:test.db?vfs=" vfs1 vfs3
|
||||
|
||||
3.1 "file:test.db?vfs=vfs1" vfs2 vfs1
|
||||
3.2 "file:test.db?vfs=vfs2" vfs1 vfs2
|
||||
3.3 "file:test.db?xvfs=vfs1" vfs2 vfs2
|
||||
3.4 "file:test.db?xvfs=vfs2" vfs1 vfs1
|
||||
} {
|
||||
do_test 5.$tn {
|
||||
set flags [list SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_URI]
|
||||
sqlite3_close [
|
||||
sqlite3_open_v2 $uri $flags $defvfs
|
||||
]
|
||||
set ::vfs
|
||||
} $vfs
|
||||
}
|
||||
vfs1 delete
|
||||
vfs2 delete
|
||||
vfs3 delete
|
||||
|
||||
# EVIDENCE-OF: R-48365-36308 Specifying an unknown VFS is an error.
|
||||
#
|
||||
set flags [list SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_URI]
|
||||
do_test 6.1 {
|
||||
set DB [sqlite3_open_v2 file:test.db?vfs=nosuchvfs $flags ""]
|
||||
set errmsg [sqlite3_errmsg $DB]
|
||||
sqlite3_close $DB
|
||||
set errmsg
|
||||
} {no such vfs: nosuchvfs}
|
||||
|
||||
|
||||
# EVIDENCE-OF: R-60479-64270 The mode parameter may be set to either
|
||||
# "ro", "rw" or "rwc". Attempting to set it to any other value is an
|
||||
# error
|
||||
#
|
||||
sqlite3 db test.db
|
||||
db close
|
||||
foreach {tn uri error} "
|
||||
1 {file:test.db?mode=ro} {not an error}
|
||||
2 {file:test.db?mode=rw} {not an error}
|
||||
3 {file:test.db?mode=rwc} {not an error}
|
||||
4 {file:test.db?mode=Ro} {no such access mode: Ro}
|
||||
5 {file:test.db?mode=Rw} {no such access mode: Rw}
|
||||
6 {file:test.db?mode=Rwc} {no such access mode: Rwc}
|
||||
" {
|
||||
do_test 7.$tn { open_uri_error $uri } $error
|
||||
}
|
||||
|
||||
|
||||
# EVIDENCE-OF: R-09651-31805 If "ro" is specified, then the database is
|
||||
# opened for read-only access, just as if the SQLITE_OPEN_READONLY flag
|
||||
# had been set in the third argument to sqlite3_prepare_v2().
|
||||
#
|
||||
# EVIDENCE-OF: R-40137-26050 If the mode option is set to "rw", then the
|
||||
# database is opened for read-write (but not create) access, as if
|
||||
# SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had been set.
|
||||
#
|
||||
# EVIDENCE-OF: R-26845-32976 Value "rwc" is equivalent to setting both
|
||||
# SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE.
|
||||
#
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_uri 1
|
||||
foreach {tn uri read write create} {
|
||||
1 {file:test.db?mode=ro} 1 0 0
|
||||
2 {file:test.db?mode=rw} 1 1 0
|
||||
3 {file:test.db?mode=rwc} 1 1 1
|
||||
} {
|
||||
set RES(c,0) {1 {unable to open database file}}
|
||||
set RES(c,1) {0 {}}
|
||||
set RES(w,0) {1 {attempt to write a readonly database}}
|
||||
set RES(w,1) {0 {}}
|
||||
set RES(r,0) {1 {this never happens}}
|
||||
set RES(r,1) {0 {a b}}
|
||||
|
||||
# Test CREATE access:
|
||||
forcedelete test.db
|
||||
do_test 8.$tn.c { list [catch { sqlite3 db $uri } msg] $msg } $RES(c,$create)
|
||||
catch { db close }
|
||||
|
||||
sqlite3 db test.db
|
||||
db eval { CREATE TABLE t1(a, b) ; INSERT INTO t1 VALUES('a', 'b') ;}
|
||||
db close
|
||||
|
||||
# Test READ access:
|
||||
do_test 8.$tn.r {
|
||||
sqlite3 db $uri
|
||||
catchsql { SELECT * FROM t1 }
|
||||
} $RES(r,$read)
|
||||
|
||||
# Test WRITE access:
|
||||
do_test 8.$tn.w {
|
||||
sqlite3 db $uri
|
||||
catchsql { INSERT INTO t1 VALUES(1, 2) }
|
||||
} $RES(w,$write)
|
||||
|
||||
catch {db close}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-56032-32287 If sqlite3_open_v2() is used, it is an
|
||||
# error to specify a value for the mode parameter that is less
|
||||
# restrictive than that specified by the flags passed as the third
|
||||
# parameter.
|
||||
#
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
db close
|
||||
foreach {tn uri flags error} {
|
||||
1 {file:test.db?mode=ro} ro {not an error}
|
||||
2 {file:test.db?mode=ro} rw {not an error}
|
||||
3 {file:test.db?mode=ro} rwc {not an error}
|
||||
|
||||
4 {file:test.db?mode=rw} ro {access mode not allowed: rw}
|
||||
5 {file:test.db?mode=rw} rw {not an error}
|
||||
6 {file:test.db?mode=rw} rwc {not an error}
|
||||
|
||||
7 {file:test.db?mode=rwc} ro {access mode not allowed: rwc}
|
||||
8 {file:test.db?mode=rwc} rw {access mode not allowed: rwc}
|
||||
9 {file:test.db?mode=rwc} rwc {not an error}
|
||||
} {
|
||||
set f(ro) [list SQLITE_OPEN_READONLY SQLITE_OPEN_URI]
|
||||
set f(rw) [list SQLITE_OPEN_READWRITE SQLITE_OPEN_URI]
|
||||
set f(rwc) [list SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_URI]
|
||||
|
||||
set DB [sqlite3_open_v2 $uri $f($flags) ""]
|
||||
set e [sqlite3_errmsg $DB]
|
||||
sqlite3_close $DB
|
||||
|
||||
do_test 9.$tn { set e } $error
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-23182-54295 The cache parameter may be set to either
|
||||
# "shared" or "private".
|
||||
sqlite3 db test.db
|
||||
db close
|
||||
foreach {tn uri error} "
|
||||
1 {file:test.db?cache=private} {not an error}
|
||||
2 {file:test.db?cache=shared} {not an error}
|
||||
3 {file:test.db?cache=yes} {no such cache mode: yes}
|
||||
4 {file:test.db?cache=} {no such cache mode: }
|
||||
" {
|
||||
do_test 10.$tn { open_uri_error $uri } $error
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-23027-03515 Setting it to "shared" is equivalent to
|
||||
# setting the SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed
|
||||
# to sqlite3_open_v2().
|
||||
#
|
||||
# EVIDENCE-OF: R-49793-28525 Setting the cache parameter to "private" is
|
||||
# equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
|
||||
#
|
||||
# EVIDENCE-OF: R-19510-48080 If sqlite3_open_v2() is used and the
|
||||
# "cache" parameter is present in a URI filename, its value overrides
|
||||
# any behaviour requested by setting SQLITE_OPEN_PRIVATECACHE or
|
||||
# SQLITE_OPEN_SHAREDCACHE flag.
|
||||
#
|
||||
set orig [sqlite3_enable_shared_cache]
|
||||
foreach {tn uri flags shared_default isshared} {
|
||||
1.1 "file:test.db" "" 0 0
|
||||
1.2 "file:test.db" "" 1 1
|
||||
1.3 "file:test.db" private 0 0
|
||||
1.4 "file:test.db" private 1 0
|
||||
1.5 "file:test.db" shared 0 1
|
||||
1.6 "file:test.db" shared 1 1
|
||||
|
||||
2.1 "file:test.db?cache=private" "" 0 0
|
||||
2.2 "file:test.db?cache=private" "" 1 0
|
||||
2.3 "file:test.db?cache=private" private 0 0
|
||||
2.4 "file:test.db?cache=private" private 1 0
|
||||
2.5 "file:test.db?cache=private" shared 0 0
|
||||
2.6 "file:test.db?cache=private" shared 1 0
|
||||
|
||||
3.1 "file:test.db?cache=shared" "" 0 1
|
||||
3.2 "file:test.db?cache=shared" "" 1 1
|
||||
3.3 "file:test.db?cache=shared" private 0 1
|
||||
3.4 "file:test.db?cache=shared" private 1 1
|
||||
3.5 "file:test.db?cache=shared" shared 0 1
|
||||
3.6 "file:test.db?cache=shared" shared 1 1
|
||||
} {
|
||||
forcedelete test.db
|
||||
sqlite3_enable_shared_cache 1
|
||||
sqlite3 db test.db
|
||||
sqlite3_enable_shared_cache 0
|
||||
|
||||
db eval {
|
||||
CREATE TABLE t1(x);
|
||||
INSERT INTO t1 VALUES('ok');
|
||||
}
|
||||
|
||||
unset -nocomplain f
|
||||
set f() {SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_URI}
|
||||
set f(shared) [concat $f() SQLITE_OPEN_SHAREDCACHE]
|
||||
set f(private) [concat $f() SQLITE_OPEN_PRIVATECACHE]
|
||||
|
||||
sqlite3_enable_shared_cache $shared_default
|
||||
set DB [sqlite3_open_v2 $uri $f($flags) ""]
|
||||
|
||||
set STMT [sqlite3_prepare $DB "SELECT * FROM t1" -1 dummy]
|
||||
|
||||
db eval {
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES('ko');
|
||||
}
|
||||
|
||||
sqlite3_step $STMT
|
||||
sqlite3_finalize $STMT
|
||||
|
||||
set RES(0) {not an error}
|
||||
set RES(1) {database table is locked: t1}
|
||||
|
||||
do_test 11.$tn { sqlite3_errmsg $DB } $RES($isshared)
|
||||
|
||||
sqlite3_close $DB
|
||||
db close
|
||||
}
|
||||
sqlite3_enable_shared_cache $orig
|
||||
|
||||
# EVIDENCE-OF: R-63472-46769 Specifying an unknown parameter in the
|
||||
# query component of a URI is not an error.
|
||||
#
|
||||
do_test 12.1 {
|
||||
parse_uri file://localhost/test.db?an=unknown¶meter=is&ok=
|
||||
} {/test.db {an unknown parameter is ok {}}}
|
||||
do_test 12.2 {
|
||||
parse_uri file://localhost/test.db?an&unknown¶meter&is&ok
|
||||
} {/test.db {an {} unknown {} parameter {} is {} ok {}}}
|
||||
|
||||
# EVIDENCE-OF: R-27458-04043 URI hexadecimal escape sequences (%HH) are
|
||||
# supported within the path and query components of a URI.
|
||||
#
|
||||
# EVIDENCE-OF: R-52765-50368 Before the path or query components of a
|
||||
# URI filename are interpreted, they are encoded using UTF-8 and all
|
||||
# hexadecimal escape sequences replaced by a single byte containing the
|
||||
# corresponding octet.
|
||||
#
|
||||
# The second of the two statements above is tested by creating a
|
||||
# multi-byte utf-8 character using a sequence of %HH escapes.
|
||||
#
|
||||
foreach {tn uri parse} "
|
||||
1 {file:/test.%64%62} {/test.db {}}
|
||||
2 {file:/test.db?%68%65%6c%6c%6f=%77%6f%72%6c%64} {/test.db {hello world}}
|
||||
3 {file:/%C3%BF.db} {/\xFF.db {}}
|
||||
" {
|
||||
do_test 13.$tn { parse_uri $uri } $parse
|
||||
}
|
||||
|
||||
finish_test
|
111
test/expr.test
111
test/expr.test
@ -32,6 +32,11 @@ proc test_expr {name settings expr result} {
|
||||
execsql {BEGIN; UPDATE test1 SET %s; SELECT %s FROM test1; ROLLBACK;}
|
||||
} $settings $expr] $result
|
||||
}
|
||||
proc test_realnum_expr {name settings expr result} {
|
||||
do_realnum_test $name [format {
|
||||
execsql {BEGIN; UPDATE test1 SET %s; SELECT %s FROM test1; ROLLBACK;}
|
||||
} $settings $expr] $result
|
||||
}
|
||||
|
||||
test_expr expr-1.1 {i1=10, i2=20} {i1+i2} 30
|
||||
test_expr expr-1.2 {i1=10, i2=20} {i1-i2} -10
|
||||
@ -164,7 +169,7 @@ ifcapable floatingpoint {
|
||||
}
|
||||
|
||||
if {[working_64bit_int]} {
|
||||
test_expr expr-1.106 {i1=0} {-9223372036854775808/-1} 9.22337203685478e+18
|
||||
test_realnum_expr expr-1.106 {i1=0} {-9223372036854775808/-1} 9.22337203685478e+18
|
||||
}
|
||||
|
||||
test_expr expr-1.107 {i1=0} {-9223372036854775808%-1} 0
|
||||
@ -203,100 +208,100 @@ test_expr expr-1.126 {i1=8, i2=8} \
|
||||
ifcapable floatingpoint {if {[working_64bit_int]} {
|
||||
test_expr expr-1.200\
|
||||
{i1=9223372036854775806, i2=1} {i1+i2} 9223372036854775807
|
||||
test_expr expr-1.201\
|
||||
test_realnum_expr expr-1.201\
|
||||
{i1=9223372036854775806, i2=2} {i1+i2} 9.22337203685478e+18
|
||||
test_expr expr-1.202\
|
||||
test_realnum_expr expr-1.202\
|
||||
{i1=9223372036854775806, i2=100000} {i1+i2} 9.22337203685488e+18
|
||||
test_expr expr-1.203\
|
||||
test_realnum_expr expr-1.203\
|
||||
{i1=9223372036854775807, i2=0} {i1+i2} 9223372036854775807
|
||||
test_expr expr-1.204\
|
||||
test_realnum_expr expr-1.204\
|
||||
{i1=9223372036854775807, i2=1} {i1+i2} 9.22337203685478e+18
|
||||
test_expr expr-1.205\
|
||||
test_realnum_expr expr-1.205\
|
||||
{i2=9223372036854775806, i1=1} {i1+i2} 9223372036854775807
|
||||
test_expr expr-1.206\
|
||||
test_realnum_expr expr-1.206\
|
||||
{i2=9223372036854775806, i1=2} {i1+i2} 9.22337203685478e+18
|
||||
test_expr expr-1.207\
|
||||
test_realnum_expr expr-1.207\
|
||||
{i2=9223372036854775806, i1=100000} {i1+i2} 9.22337203685488e+18
|
||||
test_expr expr-1.208\
|
||||
test_realnum_expr expr-1.208\
|
||||
{i2=9223372036854775807, i1=0} {i1+i2} 9223372036854775807
|
||||
test_expr expr-1.209\
|
||||
test_realnum_expr expr-1.209\
|
||||
{i2=9223372036854775807, i1=1} {i1+i2} 9.22337203685478e+18
|
||||
test_expr expr-1.210\
|
||||
test_realnum_expr expr-1.210\
|
||||
{i1=-9223372036854775807, i2=-1} {i1+i2} -9223372036854775808
|
||||
test_expr expr-1.211\
|
||||
test_realnum_expr expr-1.211\
|
||||
{i1=-9223372036854775807, i2=-2} {i1+i2} -9.22337203685478e+18
|
||||
test_expr expr-1.212\
|
||||
test_realnum_expr expr-1.212\
|
||||
{i1=-9223372036854775807, i2=-100000} {i1+i2} -9.22337203685488e+18
|
||||
test_expr expr-1.213\
|
||||
test_realnum_expr expr-1.213\
|
||||
{i1=-9223372036854775808, i2=0} {i1+i2} -9223372036854775808
|
||||
test_expr expr-1.214\
|
||||
test_realnum_expr expr-1.214\
|
||||
{i1=-9223372036854775808, i2=-1} {i1+i2} -9.22337203685478e+18
|
||||
test_expr expr-1.215\
|
||||
test_realnum_expr expr-1.215\
|
||||
{i2=-9223372036854775807, i1=-1} {i1+i2} -9223372036854775808
|
||||
test_expr expr-1.216\
|
||||
test_realnum_expr expr-1.216\
|
||||
{i2=-9223372036854775807, i1=-2} {i1+i2} -9.22337203685478e+18
|
||||
test_expr expr-1.217\
|
||||
test_realnum_expr expr-1.217\
|
||||
{i2=-9223372036854775807, i1=-100000} {i1+i2} -9.22337203685488e+18
|
||||
test_expr expr-1.218\
|
||||
test_realnum_expr expr-1.218\
|
||||
{i2=-9223372036854775808, i1=0} {i1+i2} -9223372036854775808
|
||||
test_expr expr-1.219\
|
||||
test_realnum_expr expr-1.219\
|
||||
{i2=-9223372036854775808, i1=-1} {i1+i2} -9.22337203685478e+18
|
||||
test_expr expr-1.220\
|
||||
test_realnum_expr expr-1.220\
|
||||
{i1=9223372036854775806, i2=-1} {i1-i2} 9223372036854775807
|
||||
test_expr expr-1.221\
|
||||
test_realnum_expr expr-1.221\
|
||||
{i1=9223372036854775806, i2=-2} {i1-i2} 9.22337203685478e+18
|
||||
test_expr expr-1.222\
|
||||
test_realnum_expr expr-1.222\
|
||||
{i1=9223372036854775806, i2=-100000} {i1-i2} 9.22337203685488e+18
|
||||
test_expr expr-1.223\
|
||||
test_realnum_expr expr-1.223\
|
||||
{i1=9223372036854775807, i2=0} {i1-i2} 9223372036854775807
|
||||
test_expr expr-1.224\
|
||||
test_realnum_expr expr-1.224\
|
||||
{i1=9223372036854775807, i2=-1} {i1-i2} 9.22337203685478e+18
|
||||
test_expr expr-1.225\
|
||||
test_realnum_expr expr-1.225\
|
||||
{i2=-9223372036854775806, i1=1} {i1-i2} 9223372036854775807
|
||||
test_expr expr-1.226\
|
||||
test_realnum_expr expr-1.226\
|
||||
{i2=-9223372036854775806, i1=2} {i1-i2} 9.22337203685478e+18
|
||||
test_expr expr-1.227\
|
||||
test_realnum_expr expr-1.227\
|
||||
{i2=-9223372036854775806, i1=100000} {i1-i2} 9.22337203685488e+18
|
||||
test_expr expr-1.228\
|
||||
test_realnum_expr expr-1.228\
|
||||
{i2=-9223372036854775807, i1=0} {i1-i2} 9223372036854775807
|
||||
test_expr expr-1.229\
|
||||
test_realnum_expr expr-1.229\
|
||||
{i2=-9223372036854775807, i1=1} {i1-i2} 9.22337203685478e+18
|
||||
test_expr expr-1.230\
|
||||
test_realnum_expr expr-1.230\
|
||||
{i1=-9223372036854775807, i2=1} {i1-i2} -9223372036854775808
|
||||
test_expr expr-1.231\
|
||||
test_realnum_expr expr-1.231\
|
||||
{i1=-9223372036854775807, i2=2} {i1-i2} -9.22337203685478e+18
|
||||
test_expr expr-1.232\
|
||||
test_realnum_expr expr-1.232\
|
||||
{i1=-9223372036854775807, i2=100000} {i1-i2} -9.22337203685488e+18
|
||||
test_expr expr-1.233\
|
||||
test_realnum_expr expr-1.233\
|
||||
{i1=-9223372036854775808, i2=0} {i1-i2} -9223372036854775808
|
||||
test_expr expr-1.234\
|
||||
test_realnum_expr expr-1.234\
|
||||
{i1=-9223372036854775808, i2=1} {i1-i2} -9.22337203685478e+18
|
||||
test_expr expr-1.235\
|
||||
test_realnum_expr expr-1.235\
|
||||
{i2=9223372036854775807, i1=-1} {i1-i2} -9223372036854775808
|
||||
test_expr expr-1.236\
|
||||
test_realnum_expr expr-1.236\
|
||||
{i2=9223372036854775807, i1=-2} {i1-i2} -9.22337203685478e+18
|
||||
test_expr expr-1.237\
|
||||
test_realnum_expr expr-1.237\
|
||||
{i2=9223372036854775807, i1=-100000} {i1-i2} -9.22337203685488e+18
|
||||
test_expr expr-1.238\
|
||||
test_realnum_expr expr-1.238\
|
||||
{i2=9223372036854775807, i1=0} {i1-i2} -9223372036854775807
|
||||
test_expr expr-1.239\
|
||||
test_realnum_expr expr-1.239\
|
||||
{i2=9223372036854775807, i1=-1} {i1-i2} -9223372036854775808
|
||||
|
||||
test_expr expr-1.250\
|
||||
test_realnum_expr expr-1.250\
|
||||
{i1=4294967296, i2=2147483648} {i1*i2} 9.22337203685478e+18
|
||||
test_expr expr-1.251\
|
||||
test_realnum_expr expr-1.251\
|
||||
{i1=4294967296, i2=2147483647} {i1*i2} 9223372032559808512
|
||||
test_expr expr-1.252\
|
||||
test_realnum_expr expr-1.252\
|
||||
{i1=-4294967296, i2=2147483648} {i1*i2} -9223372036854775808
|
||||
test_expr expr-1.253\
|
||||
test_realnum_expr expr-1.253\
|
||||
{i1=-4294967296, i2=2147483647} {i1*i2} -9223372032559808512
|
||||
test_expr expr-1.254\
|
||||
test_realnum_expr expr-1.254\
|
||||
{i1=4294967296, i2=-2147483648} {i1*i2} -9223372036854775808
|
||||
test_expr expr-1.255\
|
||||
test_realnum_expr expr-1.255\
|
||||
{i1=4294967296, i2=-2147483647} {i1*i2} -9223372032559808512
|
||||
test_expr expr-1.256\
|
||||
test_realnum_expr expr-1.256\
|
||||
{i1=-4294967296, i2=-2147483648} {i1*i2} 9.22337203685478e+18
|
||||
test_expr expr-1.257\
|
||||
test_realnum_expr expr-1.257\
|
||||
{i1=-4294967296, i2=-2147483647} {i1*i2} 9223372032559808512
|
||||
|
||||
}}
|
||||
@ -883,7 +888,7 @@ do_test expr-12.2 {
|
||||
} {1 {near ")": syntax error}}
|
||||
|
||||
ifcapable floatingpoint {
|
||||
do_test expr-13.1 {
|
||||
do_realnum_test expr-13.1 {
|
||||
execsql {
|
||||
SELECT 12345678901234567890;
|
||||
}
|
||||
@ -908,12 +913,12 @@ if {[working_64bit_int]} {
|
||||
# If the value is too large, use String->Float conversion.
|
||||
#
|
||||
ifcapable floatingpoint {
|
||||
do_test expr-13.4 {
|
||||
do_realnum_test expr-13.4 {
|
||||
execsql {
|
||||
SELECT 0+'9223372036854775808'
|
||||
}
|
||||
} {9.22337203685478e+18}
|
||||
do_test expr-13.5 {
|
||||
do_realnum_test expr-13.5 {
|
||||
execsql {
|
||||
SELECT '9223372036854775808'+0
|
||||
}
|
||||
@ -923,12 +928,12 @@ ifcapable floatingpoint {
|
||||
# Use String->float conversion if the value is explicitly a floating
|
||||
# point value.
|
||||
#
|
||||
do_test expr-13.6 {
|
||||
do_realnum_test expr-13.6 {
|
||||
execsql {
|
||||
SELECT 0+'9223372036854775807.0'
|
||||
}
|
||||
} {9.22337203685478e+18}
|
||||
do_test expr-13.7 {
|
||||
do_realnum_test expr-13.7 {
|
||||
execsql {
|
||||
SELECT '9223372036854775807.0'+0
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ do_test fts3corrupt-1.2 {
|
||||
do_catchsql_test 1.3 {
|
||||
INSERT INTO t1 VALUES('world');
|
||||
} {1 {database disk image is malformed}}
|
||||
do_test 1.3.1 { sqlite3_extended_errcode db } SQLITE_CORRUPT_VTAB
|
||||
do_execsql_test 1.4 {
|
||||
DROP TABLE t1;
|
||||
}
|
||||
@ -69,6 +70,7 @@ do_test fts3corrupt-2.1 {
|
||||
do_catchsql_test 2.2 {
|
||||
SELECT rowid FROM t1 WHERE t1 MATCH 'hello'
|
||||
} {1 {database disk image is malformed}}
|
||||
do_test 2.2.1 { sqlite3_extended_errcode db } SQLITE_CORRUPT_VTAB
|
||||
|
||||
do_execsql_test 3.0 {
|
||||
DROP TABLE t1;
|
||||
@ -86,6 +88,7 @@ do_test fts3corrupt-3.1 {
|
||||
do_catchsql_test 3.2 {
|
||||
SELECT rowid FROM t1 WHERE t1 MATCH 'world'
|
||||
} {1 {database disk image is malformed}}
|
||||
do_test 3.2.1 { sqlite3_extended_errcode db } SQLITE_CORRUPT_VTAB
|
||||
|
||||
|
||||
do_execsql_test 4.0 {
|
||||
@ -111,6 +114,7 @@ do_catchsql_test 4.2 {
|
||||
UPDATE t1_segdir SET root = X'FFFFFFFFFFFFFFFF';
|
||||
SELECT rowid FROM t1 WHERE t1 MATCH 'world';
|
||||
} {1 {database disk image is malformed}}
|
||||
do_test 4.2.1 { sqlite3_extended_errcode db } SQLITE_CORRUPT_VTAB
|
||||
|
||||
set blob [binary format cca*cca*cca*cca*cca*cca*cca*cca*cca*cca*a* \
|
||||
22 120 [string repeat a 120] \
|
||||
@ -130,6 +134,7 @@ do_catchsql_test 4.3 {
|
||||
UPDATE t1_segdir SET root = $blob;
|
||||
SELECT rowid FROM t1 WHERE t1 MATCH 'world';
|
||||
} {1 {database disk image is malformed}}
|
||||
do_test 4.3.1 { sqlite3_extended_errcode db } SQLITE_CORRUPT_VTAB
|
||||
|
||||
# Test a special kind of corruption, where the %_stat table contains
|
||||
# an invalid entry. At one point this could lead to a division-by-zero
|
||||
@ -152,10 +157,12 @@ do_catchsql_test 5.2 {
|
||||
UPDATE t1_stat SET value = X'0000';
|
||||
SELECT matchinfo(t1, 'nxa') FROM t1 WHERE t1 MATCH 't*';
|
||||
} {1 {database disk image is malformed}}
|
||||
do_test 5.2.1 { sqlite3_extended_errcode db } SQLITE_CORRUPT_VTAB
|
||||
do_catchsql_test 5.3 {
|
||||
UPDATE t1_stat SET value = NULL;
|
||||
SELECT matchinfo(t1, 'nxa') FROM t1 WHERE t1 MATCH 't*';
|
||||
} {1 {database disk image is malformed}}
|
||||
do_test 5.3.1 { sqlite3_extended_errcode db } SQLITE_CORRUPT_VTAB
|
||||
|
||||
|
||||
finish_test
|
||||
|
@ -567,5 +567,45 @@ if {0==[info exists ::G(perm:presql)] || $::G(perm:presql) == ""} {
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that you can vacuum a multiplex'ed DB.
|
||||
|
||||
ifcapable vacuum {
|
||||
|
||||
do_test multiplex-6.0.0 {
|
||||
multiplex_delete test.db
|
||||
sqlite3_multiplex_initialize "" 1
|
||||
sqlite3 db test.db
|
||||
multiplex_set db main 4096 16
|
||||
} {SQLITE_OK}
|
||||
|
||||
do_test multiplex-6.1.0 {
|
||||
execsql {
|
||||
PRAGMA page_size=1024;
|
||||
PRAGMA journal_mode=DELETE;
|
||||
PRAGMA auto_vacuum=OFF;
|
||||
}
|
||||
execsql {
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES(1, randomblob($g_chunk_size));
|
||||
INSERT INTO t1 VALUES(2, randomblob($g_chunk_size));
|
||||
}
|
||||
} {}
|
||||
do_test multiplex-6.2.1 { file size [multiplex_name test.db 0] } [list $g_chunk_size]
|
||||
do_test multiplex-6.2.2 { file size [multiplex_name test.db 1] } [list $g_chunk_size]
|
||||
|
||||
do_test multiplex-6.3.0 {
|
||||
execsql { VACUUM }
|
||||
} {}
|
||||
|
||||
do_test multiplex-6.99 {
|
||||
db close
|
||||
multiplex_delete test.db
|
||||
sqlite3_multiplex_shutdown
|
||||
} {SQLITE_OK}
|
||||
|
||||
}
|
||||
|
||||
|
||||
catch { sqlite3_multiplex_shutdown }
|
||||
finish_test
|
||||
|
@ -42,31 +42,31 @@ do_test nan-1.1.1 {
|
||||
db eval {SELECT x, typeof(x) FROM t1}
|
||||
} {{} null}
|
||||
if {$tcl_platform(platform) != "symbian"} {
|
||||
do_test nan-1.1.2 {
|
||||
do_realnum_test nan-1.1.2 {
|
||||
sqlite3_bind_double $::STMT 1 +Inf
|
||||
sqlite3_step $::STMT
|
||||
sqlite3_reset $::STMT
|
||||
db eval {SELECT x, typeof(x) FROM t1}
|
||||
} {{} null inf real}
|
||||
do_test nan-1.1.3 {
|
||||
do_realnum_test nan-1.1.3 {
|
||||
sqlite3_bind_double $::STMT 1 -Inf
|
||||
sqlite3_step $::STMT
|
||||
sqlite3_reset $::STMT
|
||||
db eval {SELECT x, typeof(x) FROM t1}
|
||||
} {{} null inf real -inf real}
|
||||
do_test nan-1.1.4 {
|
||||
do_realnum_test nan-1.1.4 {
|
||||
sqlite3_bind_double $::STMT 1 -NaN
|
||||
sqlite3_step $::STMT
|
||||
sqlite3_reset $::STMT
|
||||
db eval {SELECT x, typeof(x) FROM t1}
|
||||
} {{} null inf real -inf real {} null}
|
||||
do_test nan-1.1.5 {
|
||||
do_realnum_test nan-1.1.5 {
|
||||
sqlite3_bind_double $::STMT 1 NaN0
|
||||
sqlite3_step $::STMT
|
||||
sqlite3_reset $::STMT
|
||||
db eval {SELECT x, typeof(x) FROM t1}
|
||||
} {{} null inf real -inf real {} null {} null}
|
||||
do_test nan-1.1.6 {
|
||||
do_realnum_test nan-1.1.6 {
|
||||
sqlite3_bind_double $::STMT 1 -NaN0
|
||||
sqlite3_step $::STMT
|
||||
sqlite3_reset $::STMT
|
||||
@ -231,12 +231,12 @@ if {$tcl_platform(platform) != "symbian"} {
|
||||
# Do not run these tests on Symbian, as the Tcl port doesn't like to
|
||||
# convert from floating point value "-inf" to a string.
|
||||
#
|
||||
do_test nan-4.7 {
|
||||
do_realnum_test nan-4.7 {
|
||||
db eval {DELETE FROM t1}
|
||||
db eval "INSERT INTO t1 VALUES([string repeat 9 309].0)"
|
||||
db eval {SELECT x, typeof(x) FROM t1}
|
||||
} {inf real}
|
||||
do_test nan-4.8 {
|
||||
do_realnum_test nan-4.8 {
|
||||
db eval {DELETE FROM t1}
|
||||
db eval "INSERT INTO t1 VALUES(-[string repeat 9 309].0)"
|
||||
db eval {SELECT x, typeof(x) FROM t1}
|
||||
@ -313,7 +313,7 @@ do_test nan-4.18 {
|
||||
db eval {SELECT CAST(x AS text), typeof(x) FROM t1}
|
||||
} {-9.88131291682493e-324 real}
|
||||
|
||||
do_test nan-4.20 {
|
||||
do_realnum_test nan-4.20 {
|
||||
db eval {DELETE FROM t1}
|
||||
set big [string repeat 9 10000].0e-9000
|
||||
db eval "INSERT INTO t1 VALUES($big)"
|
||||
|
@ -1653,7 +1653,7 @@ for {set i 0} {$i<513} {incr i 3} {
|
||||
testvfs tv -default 1
|
||||
tv script xOpenCb
|
||||
tv filter xOpen
|
||||
proc xOpenCb {method filename} {
|
||||
proc xOpenCb {method filename args} {
|
||||
set ::file_len [string length $filename]
|
||||
}
|
||||
sqlite3 db test.db
|
||||
@ -2381,6 +2381,7 @@ do_test pager1-30.1 {
|
||||
# file can still be rolled back. This is required for backward compatibility -
|
||||
# versions of SQLite prior to 3.5.8 always set this field to zero.
|
||||
#
|
||||
if {$tcl_platform(platform)=="unix"} {
|
||||
do_test pager1-31.1 {
|
||||
faultsim_delete_and_reopen
|
||||
execsql {
|
||||
@ -2408,7 +2409,7 @@ do_test pager1-31.1 {
|
||||
sqlite3 db2 test.db2
|
||||
execsql { PRAGMA integrity_check } db2
|
||||
} {ok}
|
||||
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
@ -354,6 +354,15 @@ proc do_test {name cmd expected} {
|
||||
flush stdout
|
||||
}
|
||||
|
||||
proc realnum_normalize {r} {
|
||||
string map {1.#INF inf} [regsub -all {(e[+-])0+} $r {\1}]
|
||||
}
|
||||
proc do_realnum_test {name cmd expected} {
|
||||
uplevel [list do_test $name [
|
||||
subst -nocommands { realnum_normalize [ $cmd ] }
|
||||
] [realnum_normalize $expected]]
|
||||
}
|
||||
|
||||
proc fix_testname {varname} {
|
||||
upvar $varname testname
|
||||
if {[info exists ::testprefix]
|
||||
|
73
test/tkt-2d1a5c67d.test
Normal file
73
test/tkt-2d1a5c67d.test
Normal file
@ -0,0 +1,73 @@
|
||||
# 2011 May 19
|
||||
#
|
||||
# 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. Specifically,
|
||||
# it tests that ticket [2d1a5c67dfc2363e44f29d9bbd57f7331851390a] has
|
||||
# been resolved.
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
ifcapable !wal {finish_test; return}
|
||||
|
||||
for {set ii 1} {$ii<=10} {incr ii} {
|
||||
do_test tkt-2d1a5c67d.1.$ii {
|
||||
db close
|
||||
forcedelete test.db test.db-wal
|
||||
sqlite3 db test.db
|
||||
db eval "PRAGMA cache_size=$::ii"
|
||||
db eval {
|
||||
PRAGMA journal_mode=WAL;
|
||||
CREATE TABLE t1(a,b);
|
||||
CREATE INDEX t1b ON t1(b);
|
||||
CREATE TABLE t2(x,y UNIQUE);
|
||||
INSERT INTO t2 VALUES(3,4);
|
||||
BEGIN;
|
||||
INSERT INTO t1(a,b) VALUES(1,2);
|
||||
SELECT 'A', * FROM t2 WHERE y=4;
|
||||
SELECT 'B', * FROM t1;
|
||||
COMMIT;
|
||||
SELECT 'C', * FROM t1;
|
||||
}
|
||||
} {wal A 3 4 B 1 2 C 1 2}
|
||||
}
|
||||
|
||||
db close
|
||||
forcedelete test.db test.db-wal
|
||||
sqlite3 db test.db
|
||||
register_wholenumber_module db
|
||||
db eval {
|
||||
PRAGMA journal_mode=WAL;
|
||||
CREATE TABLE t1(a,b);
|
||||
CREATE INDEX t1b ON t1(b);
|
||||
CREATE TABLE t2(x,y);
|
||||
CREATE VIRTUAL TABLE nums USING wholenumber;
|
||||
INSERT INTO t2 SELECT value, randomblob(1000) FROM nums
|
||||
WHERE value BETWEEN 1 AND 1000;
|
||||
}
|
||||
|
||||
for {set ii 1} {$ii<=10} {incr ii} {
|
||||
do_test tkt-2d1a5c67d.2.$ii {
|
||||
db eval "PRAGMA cache_size=$::ii"
|
||||
db eval {
|
||||
DELETE FROM t1;
|
||||
BEGIN;
|
||||
INSERT INTO t1(a,b) VALUES(1,2);
|
||||
SELECT sum(length(y)) FROM t2;
|
||||
COMMIT;
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {1000000 1 2}
|
||||
}
|
||||
|
||||
finish_test
|
@ -25,7 +25,7 @@ ifcapable !altertable {
|
||||
return
|
||||
}
|
||||
|
||||
do_test tkt3838-1.1 {
|
||||
do_realnum_test tkt3838-1.1 {
|
||||
db eval {
|
||||
PRAGMA encoding=UTF16;
|
||||
CREATE TABLE t1(x);
|
||||
|
@ -36,21 +36,21 @@ if {[working_64bit_int]} {
|
||||
}
|
||||
} {-1 integer}
|
||||
}
|
||||
do_test tkt3922.2 {
|
||||
do_realnum_test tkt3922.2 {
|
||||
execsql {
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1 VALUES('-9223372036854775809');
|
||||
SELECT a, typeof(a) FROM t1;
|
||||
}
|
||||
} {-9.22337203685478e+18 real}
|
||||
do_test tkt3922.3 {
|
||||
do_realnum_test tkt3922.3 {
|
||||
execsql {
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1 VALUES('-9223372036854776832');
|
||||
SELECT a, typeof(a) FROM t1;
|
||||
}
|
||||
} {-9.22337203685478e+18 real}
|
||||
do_test tkt3922.4 {
|
||||
do_realnum_test tkt3922.4 {
|
||||
execsql {
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1 VALUES('-9223372036854776833');
|
||||
@ -78,7 +78,7 @@ if {[working_64bit_int]} {
|
||||
}
|
||||
} {1 integer}
|
||||
}
|
||||
do_test tkt3922.6 {
|
||||
do_realnum_test tkt3922.6 {
|
||||
execsql {
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1 VALUES('9223372036854775808');
|
||||
|
309
test/uri.test
Normal file
309
test/uri.test
Normal file
@ -0,0 +1,309 @@
|
||||
# 2011 April 22
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
# Test organization:
|
||||
#
|
||||
# 1.*: That file names are correctly extracted from URIs.
|
||||
# 2.*: That URI options (query parameters) are correctly extracted from URIs.
|
||||
# 3.*: That specifying an unknown VFS causes an error.
|
||||
# 4.*: Tests for specifying other options (other than "vfs").
|
||||
# 5.*: Test using a different VFS with an attached database.
|
||||
# 6.*: Test that authorities other than "" and localhost cause errors.
|
||||
# 7.*: Test that a read-write db can be attached to a read-only connection.
|
||||
#
|
||||
|
||||
set testprefix uri
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_uri 1
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that file names are correctly extracted from URIs.
|
||||
#
|
||||
foreach {tn uri file} {
|
||||
1 test.db test.db
|
||||
2 file:test.db test.db
|
||||
3 file://PWD/test.db test.db
|
||||
4 file:PWD/test.db test.db
|
||||
5 file:test.db?mork=1 test.db
|
||||
6 file:test.db?mork=1&tonglor=2 test.db
|
||||
7 file:test.db?mork=1#boris test.db
|
||||
8 file:test.db#boris test.db
|
||||
9 test.db#boris test.db#boris
|
||||
10 file:test%2Edb test.db
|
||||
11 file file
|
||||
12 http:test.db http:test.db
|
||||
13 file:test.db%00extra test.db
|
||||
14 file:test%00.db%00extra test
|
||||
|
||||
15 test.db?mork=1#boris test.db?mork=1#boris
|
||||
16 file://localhostPWD/test.db%3Fhello test.db?hello
|
||||
} {
|
||||
|
||||
if {$tcl_platform(platform)=="windows"} {
|
||||
if {$tn>14} break
|
||||
set uri [string map [list PWD /[pwd]] $uri]
|
||||
} else {
|
||||
set uri [string map [list PWD [pwd]] $uri]
|
||||
}
|
||||
|
||||
forcedelete $file
|
||||
do_test 1.$tn.1 { file exists $file } 0
|
||||
set DB [sqlite3_open $uri]
|
||||
do_test 1.$tn.2 { file exists $file } 1
|
||||
sqlite3_close $DB
|
||||
forcedelete $file
|
||||
|
||||
do_test 1.$tn.3 { file exists $file } 0
|
||||
sqlite3 db xxx.db
|
||||
catchsql { ATTACH $uri AS aux }
|
||||
do_test 1.$tn.4 { file exists $file } 1
|
||||
db close
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that URI query parameters are passed through to the VFS layer
|
||||
# correctly.
|
||||
#
|
||||
testvfs tvfs2
|
||||
testvfs tvfs -default 1
|
||||
tvfs filter xOpen
|
||||
tvfs script open_method
|
||||
proc open_method {method file arglist} {
|
||||
set ::arglist $arglist
|
||||
}
|
||||
foreach {tn uri kvlist} {
|
||||
1 file:test.db?hello=world {hello world}
|
||||
2 file:test.db?hello&world {hello {} world {}}
|
||||
3 file:test.db?hello=1&world=2&vfs=tvfs {hello 1 world 2 vfs tvfs}
|
||||
4 file:test.db?hello=1&world=2&vfs=tvfs2 {}
|
||||
5 file:test.db?%68%65%6C%6C%6F=%77%6F%72%6C%64 {hello world}
|
||||
6 file:test%00.db?hello%00extra=world%00ex {hello world}
|
||||
7 file:test%00.db?hello%00=world%00 {hello world}
|
||||
8 file:test%00.db?=world&xyz=abc {xyz abc}
|
||||
9 file:test.db?%00hello=world&xyz=abc {xyz abc}
|
||||
10 file:test.db?hello=%00world&xyz= {hello {} xyz {}}
|
||||
11 file:test.db?=#ravada {}
|
||||
12 file:test.db?&&&&&&&&hello=world&&&&&&& {hello world}
|
||||
|
||||
13 test.db?&&&&&&&&hello=world&&&&&&& {}
|
||||
14 http:test.db?hello&world {}
|
||||
} {
|
||||
|
||||
if {$tcl_platform(platform) == "windows" && $tn>12} {
|
||||
continue
|
||||
}
|
||||
|
||||
set ::arglist ""
|
||||
set DB [sqlite3_open $uri]
|
||||
do_test 2.$tn.1 { set ::arglist } $kvlist
|
||||
sqlite3_close $DB
|
||||
|
||||
sqlite3 db xxx.db
|
||||
set ::arglist ""
|
||||
execsql { ATTACH $uri AS aux }
|
||||
do_test 2.$tn.2 { set ::arglist } $kvlist
|
||||
db close
|
||||
}
|
||||
tvfs delete
|
||||
tvfs2 delete
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that specifying a non-existent VFS raises an error.
|
||||
#
|
||||
do_test 3.1 {
|
||||
list [catch { sqlite3 db "file:test.db?vfs=nosuchvfs" } msg] $msg
|
||||
} {1 {no such vfs: nosuchvfs}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test some of the other options (other than "vfs").
|
||||
#
|
||||
foreach {tn mode create_ok write_ok readonly_ok} {
|
||||
1 ro 0 0 1
|
||||
2 rw 0 1 0
|
||||
3 rwc 1 1 0
|
||||
} {
|
||||
catch { db close }
|
||||
forcedelete test.db
|
||||
|
||||
set A(1) {0 {}}
|
||||
set A(0) {1 {unable to open database file}}
|
||||
do_test 4.1.$tn.1 {
|
||||
list [catch {sqlite3 db "file:test.db?mode=$mode"} msg] $msg
|
||||
} $A($create_ok)
|
||||
|
||||
catch { db close }
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
db eval { CREATE TABLE t1(a, b) }
|
||||
db close
|
||||
|
||||
set A(1) {0 {}}
|
||||
set A(0) {1 {attempt to write a readonly database}}
|
||||
do_test 4.1.$tn.2 {
|
||||
sqlite3 db "file:test.db?mode=$mode"
|
||||
catchsql { INSERT INTO t1 VALUES(1, 2) }
|
||||
} $A($write_ok)
|
||||
|
||||
set A(1) {0 {}}
|
||||
set A(0) [list 1 "access mode not allowed: $mode"]
|
||||
do_test 4.1.$tn.3 {
|
||||
list [catch {sqlite3 db "file:test.db?mode=$mode" -readonly 1} msg] $msg
|
||||
} $A($readonly_ok)
|
||||
}
|
||||
|
||||
set orig [sqlite3_enable_shared_cache]
|
||||
foreach {tn options sc_default is_shared} {
|
||||
1 "" 1 1
|
||||
2 "cache=private" 1 0
|
||||
3 "cache=shared" 1 1
|
||||
4 "" 0 0
|
||||
5 "cache=private" 0 0
|
||||
6 "cache=shared" 0 1
|
||||
} {
|
||||
catch { db close }
|
||||
forcedelete test.db
|
||||
|
||||
sqlite3_enable_shared_cache 1
|
||||
sqlite3 db2 test.db
|
||||
db2 eval {CREATE TABLE t1(a, b)}
|
||||
|
||||
sqlite3_enable_shared_cache $sc_default
|
||||
sqlite3 db "file:test.db?$options"
|
||||
db eval {SELECT * FROM t1}
|
||||
|
||||
set A(1) {1 {database table is locked: t1}}
|
||||
set A(0) {0 {}}
|
||||
do_test 4.2.$tn {
|
||||
db2 eval {BEGIN; INSERT INTO t1 VALUES(1, 2);}
|
||||
catchsql { SELECT * FROM t1 }
|
||||
} $A($is_shared)
|
||||
|
||||
db2 close
|
||||
}
|
||||
|
||||
do_test 4.3.1 {
|
||||
list [catch {sqlite3 db "file:test.db?mode=rc"} msg] $msg
|
||||
} {1 {no such access mode: rc}}
|
||||
do_test 4.3.2 {
|
||||
list [catch {sqlite3 db "file:test.db?cache=public"} msg] $msg
|
||||
} {1 {no such cache mode: public}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that things work if an ATTACHed database uses a different VFS than
|
||||
# the main database. The important point is that for all operations
|
||||
# involving the ATTACHed database, the correct versions of the following
|
||||
# VFS are used for all operations involving the attached database.
|
||||
#
|
||||
# xOpen
|
||||
# xDelete
|
||||
# xAccess
|
||||
# xFullPathname
|
||||
#
|
||||
|
||||
# This block of code creates two VFS - "tvfs1" and "tvfs2". Each time one
|
||||
# of the above methods is called using "tvfs1", global variable ::T1(X) is
|
||||
# set, where X is the file-name the method is called on. Calls to the above
|
||||
# methods using "tvfs2" set entries in the global T2 array.
|
||||
#
|
||||
testvfs tvfs1
|
||||
tvfs1 filter {xOpen xDelete xAccess xFullPathname}
|
||||
tvfs1 script tvfs1_callback
|
||||
proc tvfs1_callback {method filename args} {
|
||||
set ::T1([file tail $filename]) 1
|
||||
}
|
||||
testvfs tvfs2
|
||||
tvfs2 filter {xOpen xDelete xAccess xFullPathname}
|
||||
tvfs2 script tvfs2_callback
|
||||
proc tvfs2_callback {method filename args} {
|
||||
set ::T2([file tail $filename]) 1
|
||||
}
|
||||
|
||||
catch {db close}
|
||||
eval forcedelete [glob test.db*]
|
||||
do_test 5.1.1 {
|
||||
sqlite3 db file:test.db1?vfs=tvfs1
|
||||
execsql {
|
||||
ATTACH 'file:test.db2?vfs=tvfs2' AS aux;
|
||||
PRAGMA main.journal_mode = PERSIST;
|
||||
PRAGMA aux.journal_mode = PERSIST;
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE TABLE aux.t2(a, b);
|
||||
PRAGMA main.journal_mode = WAL;
|
||||
PRAGMA aux.journal_mode = WAL;
|
||||
INSERT INTO t1 VALUES('x', 'y');
|
||||
INSERT INTO t2 VALUES('x', 'y');
|
||||
}
|
||||
lsort [array names ::T1]
|
||||
} {test.db1 test.db1-journal test.db1-wal}
|
||||
|
||||
do_test 5.1.2 {
|
||||
lsort [array names ::T2]
|
||||
} {test.db2 test.db2-journal test.db2-wal}
|
||||
|
||||
db close
|
||||
tvfs1 delete
|
||||
tvfs2 delete
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that only "" and "localhost" are acceptable as authorities.
|
||||
#
|
||||
catch {db close}
|
||||
foreach {tn uri res} {
|
||||
1 "file://localhost/PWD/test.db" {not an error}
|
||||
2 "file:///PWD/test.db" {not an error}
|
||||
3 "file:/PWD/test.db" {not an error}
|
||||
4 "file://l%6Fcalhost/PWD/test.db" {invalid uri authority: l%6Fcalhost}
|
||||
5 "file://lbcalhost/PWD/test.db" {invalid uri authority: lbcalhost}
|
||||
6 "file://x/PWD/test.db" {invalid uri authority: x}
|
||||
} {
|
||||
|
||||
if {$tcl_platform(platform)=="windows"} {
|
||||
set uri [string map [list PWD [string range [pwd] 3 end]] $uri]
|
||||
} else {
|
||||
set uri [string map [list PWD [string range [pwd] 1 end]] $uri]
|
||||
}
|
||||
|
||||
do_test 6.$tn {
|
||||
set DB [sqlite3_open $uri]
|
||||
sqlite3_errmsg $DB
|
||||
} $res
|
||||
catch { sqlite3_close $DB }
|
||||
}
|
||||
|
||||
forcedelete test.db test.db2
|
||||
do_test 7.1 {
|
||||
sqlite3 db test.db
|
||||
execsql {
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
ATTACH 'test.db2' AS aux;
|
||||
CREATE TABLE aux.t2(a, b);
|
||||
INSERT INTO t1 VALUES('a', 'b');
|
||||
}
|
||||
db close
|
||||
} {}
|
||||
do_test 7.2 {
|
||||
sqlite3 db file:test.db?mode=ro
|
||||
execsql { ATTACH 'file:test.db2?mode=rw' AS aux }
|
||||
} {}
|
||||
do_execsql_test 7.3 {
|
||||
INSERT INTO t2 VALUES('c', 'd')
|
||||
} {}
|
||||
do_catchsql_test 7.4 {
|
||||
INSERT INTO t1 VALUES(3, 4)
|
||||
} {1 {attempt to write a readonly database}}
|
||||
|
||||
finish_test
|
118
test/wal7.test
Normal file
118
test/wal7.test
Normal file
@ -0,0 +1,118 @@
|
||||
# 2011 May 16
|
||||
#
|
||||
# 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 file is testing the PRAGMA journal_size_limit when
|
||||
# in WAL mode.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !wal {finish_test ; return }
|
||||
|
||||
# Case 1: No size limit. Journal can get large.
|
||||
#
|
||||
do_test wal7-1.0 {
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
db eval {
|
||||
PRAGMA page_size=1024;
|
||||
PRAGMA journal_mode=WAL;
|
||||
PRAGMA wal_autocheckpoint=50; -- 50 pages
|
||||
CREATE TABLE t1(x, y UNIQUE);
|
||||
INSERT INTO t1 VALUES(1,2);
|
||||
INSERT INTO t1 VALUES(zeroblob(200000),4);
|
||||
CREATE TABLE t2(z);
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t2 SELECT x FROM t1;
|
||||
}
|
||||
expr {[file size test.db-wal]>50*1100}
|
||||
} 1
|
||||
do_test wal7-1.1 {
|
||||
db eval {PRAGMA wal_checkpoint}
|
||||
expr {[file size test.db-wal]>50*1100}
|
||||
} 1
|
||||
do_test wal7-1.2 {
|
||||
db eval {INSERT INTO t2 VALUES('hi');}
|
||||
expr {[file size test.db-wal]>50*1100}
|
||||
} 1
|
||||
|
||||
# Case 2: Size limit at half the autocheckpoint size.
|
||||
#
|
||||
do_test wal7-2.0 {
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
db eval {
|
||||
PRAGMA page_size=1024;
|
||||
PRAGMA journal_mode=WAL;
|
||||
PRAGMA wal_autocheckpoint=50; -- 50 pages
|
||||
PRAGMA journal_size_limit=25000;
|
||||
CREATE TABLE t1(x, y UNIQUE);
|
||||
INSERT INTO t1 VALUES(1,2);
|
||||
INSERT INTO t1 VALUES(zeroblob(200000),4);
|
||||
CREATE TABLE t2(z);
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t2 SELECT x FROM t1;
|
||||
}
|
||||
file size test.db-wal
|
||||
} 25000
|
||||
|
||||
|
||||
# Case 3: Size limit of zero.
|
||||
#
|
||||
do_test wal7-3.0 {
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
db eval {
|
||||
PRAGMA page_size=1024;
|
||||
PRAGMA journal_mode=WAL;
|
||||
PRAGMA wal_autocheckpoint=50; -- 50 pages
|
||||
PRAGMA journal_size_limit=0;
|
||||
CREATE TABLE t1(x, y UNIQUE);
|
||||
INSERT INTO t1 VALUES(1,2);
|
||||
INSERT INTO t1 VALUES(zeroblob(200000),4);
|
||||
CREATE TABLE t2(z);
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t2 SELECT x FROM t1;
|
||||
}
|
||||
set sz [file size test.db-wal]
|
||||
expr {$sz>0 && $sz<10000}
|
||||
} 1
|
||||
|
||||
|
||||
# Case 4: Size limit set before going WAL
|
||||
#
|
||||
do_test wal7-4.0 {
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
db eval {
|
||||
PRAGMA page_size=1024;
|
||||
PRAGMA journal_size_limit=25000;
|
||||
PRAGMA journal_mode=WAL;
|
||||
PRAGMA wal_autocheckpoint=50; -- 50 pages
|
||||
CREATE TABLE t1(x, y UNIQUE);
|
||||
INSERT INTO t1 VALUES(1,2);
|
||||
INSERT INTO t1 VALUES(zeroblob(200000),4);
|
||||
CREATE TABLE t2(z);
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t2 SELECT x FROM t1;
|
||||
}
|
||||
set sz [file size test.db-wal]
|
||||
} 25000
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
finish_test
|
Reference in New Issue
Block a user