mirror of https://github.com/sqlite/sqlite
Merge recent trunk changes.
FossilOrigin-Name: d9768de502e34da42f3ad955947c23da50f57bce
This commit is contained in:
commit
2c03652b45
|
@ -354,15 +354,17 @@ static void icuRegexpFunc(sqlite3_context *p, int nArg, sqlite3_value **apArg){
|
|||
** http://www.icu-project.org/userguide/posix.html#case_mappings
|
||||
*/
|
||||
static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
|
||||
const UChar *zInput;
|
||||
UChar *zOutput = 0;
|
||||
int nInput;
|
||||
int nOut;
|
||||
const UChar *zInput; /* Pointer to input string */
|
||||
UChar *zOutput = 0; /* Pointer to output buffer */
|
||||
int nInput; /* Size of utf-16 input string in bytes */
|
||||
int nOut; /* Size of output buffer in bytes */
|
||||
int cnt;
|
||||
int bToUpper; /* True for toupper(), false for tolower() */
|
||||
UErrorCode status;
|
||||
const char *zLocale = 0;
|
||||
|
||||
assert(nArg==1 || nArg==2);
|
||||
bToUpper = (sqlite3_user_data(p)!=0);
|
||||
if( nArg==2 ){
|
||||
zLocale = (const char *)sqlite3_value_text(apArg[1]);
|
||||
}
|
||||
|
@ -386,19 +388,23 @@ static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
|
|||
}
|
||||
zOutput = zNew;
|
||||
status = U_ZERO_ERROR;
|
||||
if( sqlite3_user_data(p) ){
|
||||
if( bToUpper ){
|
||||
nOut = 2*u_strToUpper(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
|
||||
}else{
|
||||
nOut = 2*u_strToLower(zOutput,nOut/2,zInput,nInput/2,zLocale,&status);
|
||||
}
|
||||
if( !U_SUCCESS(status) ){
|
||||
if( status==U_BUFFER_OVERFLOW_ERROR ) continue;
|
||||
icuFunctionError(p,
|
||||
sqlite3_user_data(p) ? "u_strToUpper" : "u_strToLower", status);
|
||||
return;
|
||||
|
||||
if( U_SUCCESS(status) ){
|
||||
sqlite3_result_text16(p, zOutput, nOut, xFree);
|
||||
}else if( status==U_BUFFER_OVERFLOW_ERROR ){
|
||||
assert( cnt==0 );
|
||||
continue;
|
||||
}else{
|
||||
icuFunctionError(p, bToUpper ? "u_strToUpper" : "u_strToLower", status);
|
||||
}
|
||||
return;
|
||||
}
|
||||
sqlite3_result_text16(p, zOutput, nOut, xFree);
|
||||
assert( 0 ); /* Unreachable */
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
42
manifest
42
manifest
|
@ -1,5 +1,5 @@
|
|||
C sqlite3PCachePerecentDirty()\sshould\sreturn\s0\sif\sthe\spcache\sis\sempty.
|
||||
D 2016-04-18T13:30:50.144
|
||||
C Merge\srecent\strunk\schanges.
|
||||
D 2016-04-18T13:36:17.439
|
||||
F Makefile.in eba680121821b8a60940a81454316f47a341487a
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc 71b8b16cf9393f68e2e2035486ca104872558836
|
||||
|
@ -201,7 +201,7 @@ F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093
|
|||
F ext/fts5/tool/mkfts5c.tcl d1c2a9ab8e0ec690a52316f33dd9b1d379942f45
|
||||
F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
|
||||
F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43
|
||||
F ext/icu/icu.c 4bdf4c5daedabcd8e6eb6e6a377657f7b978f9f7
|
||||
F ext/icu/icu.c 43df9d8ef2fae7a325100ebd713ab089dc829dd7
|
||||
F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
|
||||
F ext/misc/amatch.c 211108e201105e4bb0c076527b8cfd34330fc234
|
||||
F ext/misc/closure.c 0d2a038df8fbae7f19de42e7c7d71f2e4dc88704
|
||||
|
@ -355,15 +355,15 @@ F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
|
|||
F src/mutex_unix.c 27bb6cc49485ee46711a6580ab7b3f1402211d23
|
||||
F src/mutex_w32.c 5e6fe1c298fb5a8a15aaed4161d5759311431c17
|
||||
F src/notify.c 9711a7575036f0d3040ba61bc6e217f13a9888e7
|
||||
F src/os.c ca10edb445ad2c5fdc7285b49d72bcdf261fa23e
|
||||
F src/os.h 91ff889115ecd01f436d3611f7f5ea4dc12d92f1
|
||||
F src/os.c 4d83917f072ad958fba9235136fa2ed43df47905
|
||||
F src/os.h 8e976e59eb4ca1c0fca6d35ee803e38951cb0343
|
||||
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
|
||||
F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
|
||||
F src/os_unix.c bde4844f0849cab5924c6a81178f8500774ce76b
|
||||
F src/os_unix.c d0b41a47eb5f0dc00e423a1723aadeab0e78c85f
|
||||
F src/os_win.c b169437dff859e308b3726594094a2f8ca922941
|
||||
F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
|
||||
F src/pager.c 4d849ad718980d698157cd136a40dc91cbeff4d3
|
||||
F src/pager.h e1d38a2f14849e219df0f91f8323504d134c8a56
|
||||
F src/pager.h 329bdf078a4e0a3b35084534d58625d21fd03681
|
||||
F src/parse.y 10eb2f3fb62341291528c7984498054731f9d31e
|
||||
F src/pcache.c b3230ecfc7f797063fbe167f2845da363e8f07f8
|
||||
F src/pcache.h 60bc9893bfc0e16f8178fb5d8b6fcb8fab1d93c0
|
||||
|
@ -375,12 +375,12 @@ F src/printf.c 63e6fb12bbe702dd664dc3703776c090383a5a26
|
|||
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
|
||||
F src/resolve.c b8f7174e5f8c33c44ded3a25a973d0bb89228c20
|
||||
F src/rowset.c 9fe4b3ad7cc00944386bb600233d8f523de07a6e
|
||||
F src/select.c a07e6022e2b559f3c2ec80442472c5965fa7a3fc
|
||||
F src/shell.c aeaab68456010319cb71406cbaca05865b295154
|
||||
F src/select.c 30217121bdf6b587462150b8ee9e1467f7a6036b
|
||||
F src/shell.c 14ff7f660530a52b117d110ba3390b7b2eb719b6
|
||||
F src/sqlite.h.in 64eb70a3b309751bebf73a5552a51244f68f0ea5
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 98f72cbfe00169c39089115427d06ea05fe4b4a2
|
||||
F src/sqliteInt.h b3744b29555b83054f315f62d61b3a6558fa9e1c
|
||||
F src/sqliteInt.h 49cd2b5cd07cca7c462608540cb6dfa8ab03ba89
|
||||
F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247
|
||||
F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba
|
||||
F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9
|
||||
|
@ -402,14 +402,14 @@ F src/test_blob.c b2551a9b5573232db5f66f292307c37067937239
|
|||
F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f
|
||||
F src/test_config.c 7003f6f35134de6f19c6588f44783e43390ea277
|
||||
F src/test_demovfs.c 0de72c2c89551629f58486fde5734b7d90758852
|
||||
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
|
||||
F src/test_devsym.c 7e73009d5297b603c11c66d7c7d6723d4b5c73e1
|
||||
F src/test_fs.c f10f840ca4f8c72e4837908bd8347ac4bcab074b
|
||||
F src/test_func.c 37453d346cfcf118774efd5bf6187f7e6a7e3254
|
||||
F src/test_hexio.c abfdecb6fa58c354623978efceb088ca18e379cd
|
||||
F src/test_init.c 66b33120ffe9cd853b5a905ec850d51151337b32
|
||||
F src/test_intarray.c 870124b95ec4c645d4eb84f15efb7133528fb1a5
|
||||
F src/test_intarray.h 9dc57417fb65bc7835cc18548852cc08cc062202
|
||||
F src/test_journal.c 5360fbe1d1e4416ca36290562fd5a2e3f70f32aa
|
||||
F src/test_journal.c da540964c675fde39487da2bc664096af97190d8
|
||||
F src/test_loadext.c 337056bae59f80b9eb00ba82088b39d0f4fe6dfd
|
||||
F src/test_malloc.c 94c18e88d6df6d471a0d04ddb809f833d1739950
|
||||
F src/test_multiplex.c eafc567ebe162e36f17b5062285dfe90461cf8e9
|
||||
|
@ -425,10 +425,10 @@ F src/test_schema.c 2bdba21b82f601da69793e1f1d11bf481a79b091
|
|||
F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe
|
||||
F src/test_sqllog.c 0d138a8180a312bf996b37fa66da5c5799d4d57b
|
||||
F src/test_superlock.c 06797157176eb7085027d9dd278c0d7a105e3ec9
|
||||
F src/test_syscall.c 2e21ca7f7dc54a028f1967b63f1e76155c356f9b
|
||||
F src/test_syscall.c 4889d374f5a5856b7951f7a67c6401f7b938c6f5
|
||||
F src/test_tclvar.c d86412527da65468ee6fa1b8607c65d0af736bc4
|
||||
F src/test_thread.c af391ec03d23486dffbcc250b7e58e073f172af9
|
||||
F src/test_vfs.c 3b65d42e18b262805716bd96178c81da8f2d9283
|
||||
F src/test_vfs.c 4d02f38bfb8f7f273da7ba84bfe000f5babf206c
|
||||
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
|
||||
F src/test_windirent.c 8f5fada630348558d5745b334702f301da1ffc61
|
||||
F src/test_windirent.h b12055cab6227f7be10f5c19296f67c60cc5e2a5
|
||||
|
@ -448,15 +448,15 @@ F src/vdbeapi.c ba85b78fe08dc4a9ce747e62c89a2b4a4547e74c
|
|||
F src/vdbeaux.c ace1875da40b7185e604586768d5ac90de7e4f7f
|
||||
F src/vdbeblob.c c9f2f494b911c6fa34efd9803f0a10807da80f77
|
||||
F src/vdbemem.c 5cfef60e60e19cab6275d1b975bf4c791d575beb
|
||||
F src/vdbesort.c 307460bfa4de4d1c3901fcd42089159131e34062
|
||||
F src/vdbesort.c 0a8f98366ae794442e6d1ef71d9553226d885d19
|
||||
F src/vdbetrace.c f75c5455d8cf389ef86a8bfdfd3177e0e3692484
|
||||
F src/vtab.c 23b6cdfa996152d43b390504ed4a942c8caf3a00
|
||||
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c 4db22ed7e77bcf672b1a685d6ddeffba8d5be302
|
||||
F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c
|
||||
F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354
|
||||
F src/where.c 24ab561466d92d313747c04edb1a36a7af8663be
|
||||
F src/whereInt.h 93297d56edd137b7ea004490690fb6e2ce028a34
|
||||
F src/where.c bae50f2f18f9e8584549a77363858623b07e4915
|
||||
F src/whereInt.h 7de94b751f088fe3fdc8cc04a491376f0900a059
|
||||
F src/wherecode.c 8fdad9fbba723df1c1e8d07e7ea8507572040340
|
||||
F src/whereexpr.c eacc0e60d029a082b4fc0cc42ea98544add1319e
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
|
@ -1073,7 +1073,7 @@ F test/sort.test c2adc635c2564241fefec0b3a68391ef6868fd3b
|
|||
F test/sort2.test cc23b7c19d684657559e8a55b02f7fcee03851d0
|
||||
F test/sort3.test 1480ed7c4c157682542224e05e3b75faf4a149e5
|
||||
F test/sort4.test 5c34d9623a4ae5921d956dfa2b70e77ed0fc6e5c
|
||||
F test/sort5.test d3041ce3c475aa04142a959ae56ef6593f98a99f
|
||||
F test/sort5.test e47ec7a490b9b36787755874175d8f413a3883d9
|
||||
F test/sortfault.test d4ccf606a0c77498e2beb542764fd9394acb4d66
|
||||
F test/speed1.test f2974a91d79f58507ada01864c0e323093065452
|
||||
F test/speed1p.explain d841e650a04728b39e6740296b852dccdca9b2cb
|
||||
|
@ -1484,7 +1484,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
|||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P ae16310c4e9a9b7e94874bd912fc6a4324cfaa2b
|
||||
R 0620b8f840563243b73e6076ebdcd81f
|
||||
P 85f3d80eb7319754792eef76996b2c740a2b0073 3a7d72986fabe9434ff5bd02c93169314f072b23
|
||||
R 10404030b7871fd2cdace5bd8bb71227
|
||||
U drh
|
||||
Z 04d9a6e624a4591b3aa3f8ec5734f1ff
|
||||
Z 6da7b721a063bb7a65bebbe0704c9e5d
|
||||
|
|
|
@ -1 +1 @@
|
|||
85f3d80eb7319754792eef76996b2c740a2b0073
|
||||
d9768de502e34da42f3ad955947c23da50f57bce
|
12
src/os.c
12
src/os.c
|
@ -81,13 +81,11 @@ int sqlite3_memdebug_vfs_oom_test = 1;
|
|||
** of this would be completely automatic if SQLite were coded using
|
||||
** C++ instead of plain old C.
|
||||
*/
|
||||
int sqlite3OsClose(sqlite3_file *pId){
|
||||
int rc = SQLITE_OK;
|
||||
void sqlite3OsClose(sqlite3_file *pId){
|
||||
if( pId->pMethods ){
|
||||
rc = pId->pMethods->xClose(pId);
|
||||
pId->pMethods->xClose(pId);
|
||||
pId->pMethods = 0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){
|
||||
DO_OS_MALLOC_TEST(id);
|
||||
|
@ -305,12 +303,10 @@ int sqlite3OsOpenMalloc(
|
|||
}
|
||||
return rc;
|
||||
}
|
||||
int sqlite3OsCloseFree(sqlite3_file *pFile){
|
||||
int rc = SQLITE_OK;
|
||||
void sqlite3OsCloseFree(sqlite3_file *pFile){
|
||||
assert( pFile );
|
||||
rc = sqlite3OsClose(pFile);
|
||||
sqlite3OsClose(pFile);
|
||||
sqlite3_free(pFile);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
4
src/os.h
4
src/os.h
|
@ -160,7 +160,7 @@ int sqlite3OsInit(void);
|
|||
/*
|
||||
** Functions for accessing sqlite3_file methods
|
||||
*/
|
||||
int sqlite3OsClose(sqlite3_file*);
|
||||
void sqlite3OsClose(sqlite3_file*);
|
||||
int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset);
|
||||
int sqlite3OsWrite(sqlite3_file*, const void*, int amt, i64 offset);
|
||||
int sqlite3OsTruncate(sqlite3_file*, i64 size);
|
||||
|
@ -205,6 +205,6 @@ int sqlite3OsCurrentTimeInt64(sqlite3_vfs *, sqlite3_int64*);
|
|||
** sqlite3_malloc() to obtain space for the file-handle structure.
|
||||
*/
|
||||
int sqlite3OsOpenMalloc(sqlite3_vfs *, const char *, sqlite3_file **, int,int*);
|
||||
int sqlite3OsCloseFree(sqlite3_file *);
|
||||
void sqlite3OsCloseFree(sqlite3_file *);
|
||||
|
||||
#endif /* _SQLITE_OS_H_ */
|
||||
|
|
|
@ -405,7 +405,7 @@ static struct unix_syscall {
|
|||
#else
|
||||
{ "pread64", (sqlite3_syscall_ptr)0, 0 },
|
||||
#endif
|
||||
#define osPread64 ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[10].pCurrent)
|
||||
#define osPread64 ((ssize_t(*)(int,void*,size_t,off64_t))aSyscall[10].pCurrent)
|
||||
|
||||
{ "write", (sqlite3_syscall_ptr)write, 0 },
|
||||
#define osWrite ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent)
|
||||
|
@ -423,7 +423,7 @@ static struct unix_syscall {
|
|||
#else
|
||||
{ "pwrite64", (sqlite3_syscall_ptr)0, 0 },
|
||||
#endif
|
||||
#define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off_t))\
|
||||
#define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off64_t))\
|
||||
aSyscall[13].pCurrent)
|
||||
|
||||
{ "fchmod", (sqlite3_syscall_ptr)fchmod, 0 },
|
||||
|
|
11
src/pager.h
11
src/pager.h
|
@ -68,7 +68,11 @@ typedef struct PgHdr DbPage;
|
|||
#define PAGER_LOCKINGMODE_EXCLUSIVE 1
|
||||
|
||||
/*
|
||||
** Numeric constants that encode the journalmode.
|
||||
** Numeric constants that encode the journalmode.
|
||||
**
|
||||
** The numeric values encoded here (other than PAGER_JOURNALMODE_QUERY)
|
||||
** are exposed in the API via the "PRAGMA journal_mode" command and
|
||||
** therefore cannot be changed without a compatibility break.
|
||||
*/
|
||||
#define PAGER_JOURNALMODE_QUERY (-1) /* Query the value of journalmode */
|
||||
#define PAGER_JOURNALMODE_DELETE 0 /* Commit by deleting journal file */
|
||||
|
@ -86,6 +90,11 @@ typedef struct PgHdr DbPage;
|
|||
|
||||
/*
|
||||
** Flags for sqlite3PagerSetFlags()
|
||||
**
|
||||
** Value constraints (enforced via assert()):
|
||||
** PAGER_FULLFSYNC == SQLITE_FullFSync
|
||||
** PAGER_CKPT_FULLFSYNC == SQLITE_CkptFullFSync
|
||||
** PAGER_CACHE_SPILL == SQLITE_CacheSpill
|
||||
*/
|
||||
#define PAGER_SYNCHRONOUS_OFF 0x01 /* PRAGMA synchronous=OFF */
|
||||
#define PAGER_SYNCHRONOUS_NORMAL 0x02 /* PRAGMA synchronous=NORMAL */
|
||||
|
|
|
@ -3787,6 +3787,8 @@ static int pushDownWhereTerms(
|
|||
int nChng = 0;
|
||||
if( pWhere==0 ) return 0;
|
||||
if( (pSubq->selFlags & (SF_Aggregate|SF_Recursive))!=0 ){
|
||||
testcase( pSubq->selFlags & SF_Aggregate );
|
||||
testcase( pSubq->selFlags & SF_Recursive );
|
||||
return 0; /* restrictions (1) and (2) */
|
||||
}
|
||||
if( pSubq->pLimit!=0 ){
|
||||
|
@ -5092,6 +5094,13 @@ int sqlite3Select(
|
|||
** the sDistinct.isTnct is still set. Hence, isTnct represents the
|
||||
** original setting of the SF_Distinct flag, not the current setting */
|
||||
assert( sDistinct.isTnct );
|
||||
|
||||
#if SELECTTRACE_ENABLED
|
||||
if( sqlite3SelectTrace & 0x400 ){
|
||||
SELECTTRACE(0x400,pParse,p,("Transform DISTINCT into GROUP BY:\n"));
|
||||
sqlite3TreeViewSelect(0, p, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* If there is an ORDER BY clause, then create an ephemeral index to
|
||||
|
|
213
src/shell.c
213
src/shell.c
|
@ -1062,7 +1062,7 @@ static int shell_callback(
|
|||
}
|
||||
case MODE_Pretty: { /* .schema and .fullschema with --indent */
|
||||
char *z;
|
||||
int i,j;
|
||||
int j;
|
||||
int nParen = 0;
|
||||
char cEnd = 0;
|
||||
char c;
|
||||
|
@ -1089,8 +1089,7 @@ static int shell_callback(
|
|||
while( j>0 && IsSpace(z[j-1]) ){ j--; }
|
||||
z[j] = 0;
|
||||
if( strlen30(z)>=79 ){
|
||||
for(i=j=0; z[i]; i++){
|
||||
char c = z[i];
|
||||
for(i=j=0; (c = z[i])!=0; i++){
|
||||
if( c==cEnd ){
|
||||
cEnd = 0;
|
||||
}else if( c=='"' || c=='\'' || c=='`' ){
|
||||
|
@ -1734,7 +1733,7 @@ static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
|
|||
if( str_in_array(zOp, azGoto) && p2op<p->nIndent
|
||||
&& (abYield[p2op] || sqlite3_column_int(pSql, 2))
|
||||
){
|
||||
for(i=p2op+1; i<iOp; i++) p->aiIndent[i] += 2;
|
||||
for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1753,6 +1752,104 @@ static void explain_data_delete(ShellState *p){
|
|||
p->iIndent = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Disable and restore .wheretrace and .selecttrace settings.
|
||||
*/
|
||||
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
|
||||
extern int sqlite3SelectTrace;
|
||||
static int savedSelectTrace;
|
||||
#endif
|
||||
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
|
||||
extern int sqlite3WhereTrace;
|
||||
static int savedWhereTrace;
|
||||
#endif
|
||||
static void disable_debug_trace_modes(void){
|
||||
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
|
||||
savedSelectTrace = sqlite3SelectTrace;
|
||||
sqlite3SelectTrace = 0;
|
||||
#endif
|
||||
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
|
||||
savedWhereTrace = sqlite3WhereTrace;
|
||||
sqlite3WhereTrace = 0;
|
||||
#endif
|
||||
}
|
||||
static void restore_debug_trace_modes(void){
|
||||
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
|
||||
sqlite3SelectTrace = savedSelectTrace;
|
||||
#endif
|
||||
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
|
||||
sqlite3WhereTrace = savedWhereTrace;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Run a prepared statement
|
||||
*/
|
||||
static void exec_prepared_stmt(
|
||||
ShellState *pArg, /* Pointer to ShellState */
|
||||
sqlite3_stmt *pStmt, /* Statment to run */
|
||||
int (*xCallback)(void*,int,char**,char**,int*) /* Callback function */
|
||||
){
|
||||
int rc;
|
||||
|
||||
/* perform the first step. this will tell us if we
|
||||
** have a result set or not and how wide it is.
|
||||
*/
|
||||
rc = sqlite3_step(pStmt);
|
||||
/* if we have a result set... */
|
||||
if( SQLITE_ROW == rc ){
|
||||
/* if we have a callback... */
|
||||
if( xCallback ){
|
||||
/* allocate space for col name ptr, value ptr, and type */
|
||||
int nCol = sqlite3_column_count(pStmt);
|
||||
void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
|
||||
if( !pData ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
char **azCols = (char **)pData; /* Names of result columns */
|
||||
char **azVals = &azCols[nCol]; /* Results */
|
||||
int *aiTypes = (int *)&azVals[nCol]; /* Result types */
|
||||
int i, x;
|
||||
assert(sizeof(int) <= sizeof(char *));
|
||||
/* save off ptrs to column names */
|
||||
for(i=0; i<nCol; i++){
|
||||
azCols[i] = (char *)sqlite3_column_name(pStmt, i);
|
||||
}
|
||||
do{
|
||||
/* extract the data and data types */
|
||||
for(i=0; i<nCol; i++){
|
||||
aiTypes[i] = x = sqlite3_column_type(pStmt, i);
|
||||
if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){
|
||||
azVals[i] = "";
|
||||
}else{
|
||||
azVals[i] = (char*)sqlite3_column_text(pStmt, i);
|
||||
}
|
||||
if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
|
||||
rc = SQLITE_NOMEM;
|
||||
break; /* from for */
|
||||
}
|
||||
} /* end for */
|
||||
|
||||
/* if data and types extracted successfully... */
|
||||
if( SQLITE_ROW == rc ){
|
||||
/* call the supplied callback with the result row data */
|
||||
if( xCallback(pArg, nCol, azVals, azCols, aiTypes) ){
|
||||
rc = SQLITE_ABORT;
|
||||
}else{
|
||||
rc = sqlite3_step(pStmt);
|
||||
}
|
||||
}
|
||||
} while( SQLITE_ROW == rc );
|
||||
sqlite3_free(pData);
|
||||
}
|
||||
}else{
|
||||
do{
|
||||
rc = sqlite3_step(pStmt);
|
||||
} while( rc == SQLITE_ROW );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Execute a statement or set of statements. Print
|
||||
** any result rows/columns depending on the current mode
|
||||
|
@ -1780,6 +1877,7 @@ static int shell_exec(
|
|||
}
|
||||
|
||||
while( zSql[0] && (SQLITE_OK == rc) ){
|
||||
static const char *zStmtSql;
|
||||
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
|
||||
if( SQLITE_OK != rc ){
|
||||
if( pzErrMsg ){
|
||||
|
@ -1792,6 +1890,8 @@ static int shell_exec(
|
|||
while( IsSpace(zSql[0]) ) zSql++;
|
||||
continue;
|
||||
}
|
||||
zStmtSql = sqlite3_sql(pStmt);
|
||||
while( IsSpace(zStmtSql[0]) ) zStmtSql++;
|
||||
|
||||
/* save off the prepared statment handle and reset row count */
|
||||
if( pArg ){
|
||||
|
@ -1801,15 +1901,15 @@ static int shell_exec(
|
|||
|
||||
/* echo the sql statement if echo on */
|
||||
if( pArg && pArg->echoOn ){
|
||||
const char *zStmtSql = sqlite3_sql(pStmt);
|
||||
utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
|
||||
}
|
||||
|
||||
/* Show the EXPLAIN QUERY PLAN if .eqp is on */
|
||||
if( pArg && pArg->autoEQP ){
|
||||
if( pArg && pArg->autoEQP && sqlite3_strlike("EXPLAIN%",zStmtSql,0)!=0 ){
|
||||
sqlite3_stmt *pExplain;
|
||||
char *zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s",
|
||||
sqlite3_sql(pStmt));
|
||||
char *zEQP;
|
||||
disable_debug_trace_modes();
|
||||
zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql);
|
||||
rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
while( sqlite3_step(pExplain)==SQLITE_ROW ){
|
||||
|
@ -1821,13 +1921,27 @@ static int shell_exec(
|
|||
}
|
||||
sqlite3_finalize(pExplain);
|
||||
sqlite3_free(zEQP);
|
||||
if( pArg->autoEQP>=2 ){
|
||||
/* Also do an EXPLAIN for ".eqp full" mode */
|
||||
zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql);
|
||||
rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
pArg->cMode = MODE_Explain;
|
||||
explain_data_prepare(pArg, pExplain);
|
||||
exec_prepared_stmt(pArg, pExplain, xCallback);
|
||||
explain_data_delete(pArg);
|
||||
}
|
||||
sqlite3_finalize(pExplain);
|
||||
sqlite3_free(zEQP);
|
||||
}
|
||||
restore_debug_trace_modes();
|
||||
}
|
||||
|
||||
if( pArg ){
|
||||
pArg->cMode = pArg->mode;
|
||||
if( pArg->autoExplain
|
||||
&& sqlite3_column_count(pStmt)==8
|
||||
&& sqlite3_strlike("%EXPLAIN%", sqlite3_sql(pStmt),0)==0
|
||||
&& sqlite3_strlike("EXPLAIN%", zStmtSql,0)==0
|
||||
){
|
||||
pArg->cMode = MODE_Explain;
|
||||
}
|
||||
|
@ -1839,63 +1953,7 @@ static int shell_exec(
|
|||
}
|
||||
}
|
||||
|
||||
/* perform the first step. this will tell us if we
|
||||
** have a result set or not and how wide it is.
|
||||
*/
|
||||
rc = sqlite3_step(pStmt);
|
||||
/* if we have a result set... */
|
||||
if( SQLITE_ROW == rc ){
|
||||
/* if we have a callback... */
|
||||
if( xCallback ){
|
||||
/* allocate space for col name ptr, value ptr, and type */
|
||||
int nCol = sqlite3_column_count(pStmt);
|
||||
void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
|
||||
if( !pData ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
char **azCols = (char **)pData; /* Names of result columns */
|
||||
char **azVals = &azCols[nCol]; /* Results */
|
||||
int *aiTypes = (int *)&azVals[nCol]; /* Result types */
|
||||
int i, x;
|
||||
assert(sizeof(int) <= sizeof(char *));
|
||||
/* save off ptrs to column names */
|
||||
for(i=0; i<nCol; i++){
|
||||
azCols[i] = (char *)sqlite3_column_name(pStmt, i);
|
||||
}
|
||||
do{
|
||||
/* extract the data and data types */
|
||||
for(i=0; i<nCol; i++){
|
||||
aiTypes[i] = x = sqlite3_column_type(pStmt, i);
|
||||
if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){
|
||||
azVals[i] = "";
|
||||
}else{
|
||||
azVals[i] = (char*)sqlite3_column_text(pStmt, i);
|
||||
}
|
||||
if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
|
||||
rc = SQLITE_NOMEM;
|
||||
break; /* from for */
|
||||
}
|
||||
} /* end for */
|
||||
|
||||
/* if data and types extracted successfully... */
|
||||
if( SQLITE_ROW == rc ){
|
||||
/* call the supplied callback with the result row data */
|
||||
if( xCallback(pArg, nCol, azVals, azCols, aiTypes) ){
|
||||
rc = SQLITE_ABORT;
|
||||
}else{
|
||||
rc = sqlite3_step(pStmt);
|
||||
}
|
||||
}
|
||||
} while( SQLITE_ROW == rc );
|
||||
sqlite3_free(pData);
|
||||
}
|
||||
}else{
|
||||
do{
|
||||
rc = sqlite3_step(pStmt);
|
||||
} while( rc == SQLITE_ROW );
|
||||
}
|
||||
}
|
||||
|
||||
exec_prepared_stmt(pArg, pStmt, xCallback);
|
||||
explain_data_delete(pArg);
|
||||
|
||||
/* print usage stats if stats on */
|
||||
|
@ -2085,7 +2143,7 @@ static char zHelp[] =
|
|||
" If TABLE specified, only dump tables matching\n"
|
||||
" LIKE pattern TABLE.\n"
|
||||
".echo on|off Turn command echo on or off\n"
|
||||
".eqp on|off Enable or disable automatic EXPLAIN QUERY PLAN\n"
|
||||
".eqp on|off|full Enable or disable automatic EXPLAIN QUERY PLAN\n"
|
||||
".exit Exit this program\n"
|
||||
".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic\n"
|
||||
".fullschema ?--indent? Show schema and the content of sqlite_stat tables\n"
|
||||
|
@ -3255,9 +3313,13 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||
|
||||
if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
|
||||
if( nArg==2 ){
|
||||
p->autoEQP = booleanValue(azArg[1]);
|
||||
if( strcmp(azArg[1],"full")==0 ){
|
||||
p->autoEQP = 2;
|
||||
}else{
|
||||
p->autoEQP = booleanValue(azArg[1]);
|
||||
}
|
||||
}else{
|
||||
raw_printf(stderr, "Usage: .eqp on|off\n");
|
||||
raw_printf(stderr, "Usage: .eqp on|off|full\n");
|
||||
rc = 1;
|
||||
}
|
||||
}else
|
||||
|
@ -4018,7 +4080,6 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||
|
||||
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
|
||||
if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
|
||||
extern int sqlite3SelectTrace;
|
||||
sqlite3SelectTrace = integerValue(azArg[1]);
|
||||
}else
|
||||
#endif
|
||||
|
@ -4278,17 +4339,18 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||
}else
|
||||
|
||||
if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
|
||||
static const char *azBool[] = { "off", "on", "full", "unk" };
|
||||
int i;
|
||||
if( nArg!=1 ){
|
||||
raw_printf(stderr, "Usage: .show\n");
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
utf8_printf(p->out, "%12.12s: %s\n","echo", p->echoOn ? "on" : "off");
|
||||
utf8_printf(p->out, "%12.12s: %s\n","eqp", p->autoEQP ? "on" : "off");
|
||||
utf8_printf(p->out, "%12.12s: %s\n","echo", azBool[p->echoOn!=0]);
|
||||
utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
|
||||
utf8_printf(p->out, "%12.12s: %s\n","explain",
|
||||
p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");
|
||||
utf8_printf(p->out,"%12.12s: %s\n","headers", p->showHeader ? "on" : "off");
|
||||
utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]);
|
||||
utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]);
|
||||
utf8_printf(p->out, "%12.12s: ", "nullvalue");
|
||||
output_c_string(p->out, p->nullValue);
|
||||
|
@ -4301,7 +4363,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||
utf8_printf(p->out,"%12.12s: ", "rowseparator");
|
||||
output_c_string(p->out, p->rowSeparator);
|
||||
raw_printf(p->out, "\n");
|
||||
utf8_printf(p->out, "%12.12s: %s\n","stats", p->statsOn ? "on" : "off");
|
||||
utf8_printf(p->out, "%12.12s: %s\n","stats", azBool[p->statsOn!=0]);
|
||||
utf8_printf(p->out, "%12.12s: ", "width");
|
||||
for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
|
||||
raw_printf(p->out, "%d ", p->colWidth[i]);
|
||||
|
@ -4716,7 +4778,6 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||
|
||||
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
|
||||
if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
|
||||
extern int sqlite3WhereTrace;
|
||||
sqlite3WhereTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff;
|
||||
}else
|
||||
#endif
|
||||
|
@ -5384,6 +5445,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
|||
data.echoOn = 1;
|
||||
}else if( strcmp(z,"-eqp")==0 ){
|
||||
data.autoEQP = 1;
|
||||
}else if( strcmp(z,"-eqpfull")==0 ){
|
||||
data.autoEQP = 2;
|
||||
}else if( strcmp(z,"-stats")==0 ){
|
||||
data.statsOn = 1;
|
||||
}else if( strcmp(z,"-scanstats")==0 ){
|
||||
|
|
|
@ -1350,6 +1350,11 @@ struct sqlite3 {
|
|||
|
||||
/*
|
||||
** Possible values for the sqlite3.flags.
|
||||
**
|
||||
** Value constraints (enforced via assert()):
|
||||
** SQLITE_FullFSync == PAGER_FULLFSYNC
|
||||
** SQLITE_CkptFullFSync == PAGER_CKPT_FULLFSYNC
|
||||
** SQLITE_CacheSpill == PAGER_CACHE_SPILL
|
||||
*/
|
||||
#define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */
|
||||
#define SQLITE_InternChanges 0x00000002 /* Uncommitted Hash table changes */
|
||||
|
@ -1484,6 +1489,13 @@ struct FuncDestructor {
|
|||
** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. And
|
||||
** SQLITE_FUNC_CONSTANT must be the same as SQLITE_DETERMINISTIC. There
|
||||
** are assert() statements in the code to verify this.
|
||||
**
|
||||
** Value constraints (enforced via assert()):
|
||||
** SQLITE_FUNC_MINMAX == NC_MinMaxAgg == SF_MinMaxAgg
|
||||
** SQLITE_FUNC_LENGTH == OPFLAG_LENGTHARG
|
||||
** SQLITE_FUNC_TYPEOF == OPFLAG_TYPEOFARG
|
||||
** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API
|
||||
** SQLITE_FUNC_ENCMASK depends on SQLITE_UTF* macros in the API
|
||||
*/
|
||||
#define SQLITE_FUNC_ENCMASK 0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */
|
||||
#define SQLITE_FUNC_LIKE 0x0004 /* Candidate for the LIKE optimization */
|
||||
|
@ -2483,6 +2495,9 @@ struct SrcList {
|
|||
/*
|
||||
** Flags appropriate for the wctrlFlags parameter of sqlite3WhereBegin()
|
||||
** and the WhereInfo.wctrlFlags member.
|
||||
**
|
||||
** Value constraints (enforced via assert()):
|
||||
** WHERE_USE_LIMIT == SF_FixedLimit
|
||||
*/
|
||||
#define WHERE_ORDERBY_NORMAL 0x0000 /* No-op */
|
||||
#define WHERE_ORDERBY_MIN 0x0001 /* ORDER BY processing for min() func */
|
||||
|
@ -2543,15 +2558,16 @@ struct NameContext {
|
|||
/*
|
||||
** Allowed values for the NameContext, ncFlags field.
|
||||
**
|
||||
** Note: NC_MinMaxAgg must have the same value as SF_MinMaxAgg and
|
||||
** SQLITE_FUNC_MINMAX.
|
||||
** Value constraints (all checked via assert()):
|
||||
** NC_HasAgg == SF_HasAgg
|
||||
** NC_MinMaxAgg == SF_MinMaxAgg == SQLITE_FUNC_MINMAX
|
||||
**
|
||||
*/
|
||||
#define NC_AllowAgg 0x0001 /* Aggregate functions are allowed here */
|
||||
#define NC_HasAgg 0x0002 /* One or more aggregate functions seen */
|
||||
#define NC_PartIdx 0x0002 /* True if resolving a partial index WHERE */
|
||||
#define NC_IsCheck 0x0004 /* True if resolving names in a CHECK constraint */
|
||||
#define NC_InAggFunc 0x0008 /* True if analyzing arguments to an agg func */
|
||||
#define NC_PartIdx 0x0010 /* True if resolving a partial index WHERE */
|
||||
#define NC_HasAgg 0x0010 /* One or more aggregate functions seen */
|
||||
#define NC_IdxExpr 0x0020 /* True if resolving columns of CREATE INDEX */
|
||||
#define NC_MinMaxAgg 0x1000 /* min/max aggregates seen. See note above */
|
||||
|
||||
|
@ -2600,24 +2616,30 @@ struct Select {
|
|||
/*
|
||||
** Allowed values for Select.selFlags. The "SF" prefix stands for
|
||||
** "Select Flag".
|
||||
**
|
||||
** Value constraints (all checked via assert())
|
||||
** SF_HasAgg == NC_HasAgg
|
||||
** SF_MinMaxAgg == NC_MinMaxAgg == SQLITE_FUNC_MINMAX
|
||||
** SF_FixedLimit == WHERE_USE_LIMIT
|
||||
*/
|
||||
#define SF_Distinct 0x00001 /* Output should be DISTINCT */
|
||||
#define SF_All 0x00002 /* Includes the ALL keyword */
|
||||
#define SF_Resolved 0x00004 /* Identifiers have been resolved */
|
||||
#define SF_Aggregate 0x00008 /* Contains aggregate functions */
|
||||
#define SF_UsesEphemeral 0x00010 /* Uses the OpenEphemeral opcode */
|
||||
#define SF_Expanded 0x00020 /* sqlite3SelectExpand() called on this */
|
||||
#define SF_HasTypeInfo 0x00040 /* FROM subqueries have Table metadata */
|
||||
#define SF_Compound 0x00080 /* Part of a compound query */
|
||||
#define SF_Values 0x00100 /* Synthesized from VALUES clause */
|
||||
#define SF_MultiValue 0x00200 /* Single VALUES term with multiple rows */
|
||||
#define SF_NestedFrom 0x00400 /* Part of a parenthesized FROM clause */
|
||||
#define SF_MaybeConvert 0x00800 /* Need convertCompoundSelectToSubquery() */
|
||||
#define SF_Aggregate 0x00008 /* Contains agg functions or a GROUP BY */
|
||||
#define SF_HasAgg 0x00010 /* Contains aggregate functions */
|
||||
#define SF_UsesEphemeral 0x00020 /* Uses the OpenEphemeral opcode */
|
||||
#define SF_Expanded 0x00040 /* sqlite3SelectExpand() called on this */
|
||||
#define SF_HasTypeInfo 0x00080 /* FROM subqueries have Table metadata */
|
||||
#define SF_Compound 0x00100 /* Part of a compound query */
|
||||
#define SF_Values 0x00200 /* Synthesized from VALUES clause */
|
||||
#define SF_MultiValue 0x00400 /* Single VALUES term with multiple rows */
|
||||
#define SF_NestedFrom 0x00800 /* Part of a parenthesized FROM clause */
|
||||
#define SF_MinMaxAgg 0x01000 /* Aggregate containing min() or max() */
|
||||
#define SF_Recursive 0x02000 /* The recursive part of a recursive CTE */
|
||||
#define SF_FixedLimit 0x04000 /* nSelectRow set by a constant LIMIT */
|
||||
#define SF_Converted 0x08000 /* By convertCompoundSelectToSubquery() */
|
||||
#define SF_IncludeHidden 0x10000 /* Include hidden columns in output */
|
||||
#define SF_MaybeConvert 0x08000 /* Need convertCompoundSelectToSubquery() */
|
||||
#define SF_Converted 0x10000 /* By convertCompoundSelectToSubquery() */
|
||||
#define SF_IncludeHidden 0x20000 /* Include hidden columns in output */
|
||||
|
||||
|
||||
/*
|
||||
|
@ -2928,6 +2950,15 @@ struct AuthContext {
|
|||
|
||||
/*
|
||||
** Bitfield flags for P5 value in various opcodes.
|
||||
**
|
||||
** Value constraints (enforced via assert()):
|
||||
** OPFLAG_LENGTHARG == SQLITE_FUNC_LENGTH
|
||||
** OPFLAG_TYPEOFARG == SQLITE_FUNC_TYPEOF
|
||||
** OPFLAG_BULKCSR == BTREE_BULKLOAD
|
||||
** OPFLAG_SEEKEQ == BTREE_SEEK_EQ
|
||||
** OPFLAG_FORDELETE == BTREE_FORDELETE
|
||||
** OPFLAG_SAVEPOSITION == BTREE_SAVEPOSITION
|
||||
** OPFLAG_AUXDELETE == BTREE_AUXDELETE
|
||||
*/
|
||||
#define OPFLAG_NCHANGE 0x01 /* OP_Insert: Set to update db->nChange */
|
||||
/* Also used in P2 (not P5) of OP_Delete */
|
||||
|
|
|
@ -133,7 +133,8 @@ struct DevsymGlobal g = {0, 0, 512};
|
|||
*/
|
||||
static int devsymClose(sqlite3_file *pFile){
|
||||
devsym_file *p = (devsym_file *)pFile;
|
||||
return sqlite3OsClose(p->pReal);
|
||||
sqlite3OsClose(p->pReal);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -256,7 +256,8 @@ static int jtClose(sqlite3_file *pFile){
|
|||
*pp = p->pNext;
|
||||
}
|
||||
leaveJtMutex();
|
||||
return sqlite3OsClose(p->pReal);
|
||||
sqlite3OsClose(p->pReal);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -108,10 +108,13 @@ static int ts_ftruncate(int fd, off_t n);
|
|||
static int ts_fcntl(int fd, int cmd, ... );
|
||||
static int ts_read(int fd, void *aBuf, size_t nBuf);
|
||||
static int ts_pread(int fd, void *aBuf, size_t nBuf, off_t off);
|
||||
static int ts_pread64(int fd, void *aBuf, size_t nBuf, off_t off);
|
||||
/* Note: pread64() and pwrite64() actually use off64_t as the type on their
|
||||
** last parameter. But that datatype is not defined on many systems
|
||||
** (ex: Mac, OpenBSD). So substitute a likely equivalent: sqlite3_uint64 */
|
||||
static int ts_pread64(int fd, void *aBuf, size_t nBuf, sqlite3_uint64 off);
|
||||
static int ts_write(int fd, const void *aBuf, size_t nBuf);
|
||||
static int ts_pwrite(int fd, const void *aBuf, size_t nBuf, off_t off);
|
||||
static int ts_pwrite64(int fd, const void *aBuf, size_t nBuf, off_t off);
|
||||
static int ts_pwrite64(int fd, const void *aBuf, size_t nBuf, sqlite3_uint64 off);
|
||||
static int ts_fchmod(int fd, mode_t mode);
|
||||
static int ts_fallocate(int fd, off_t off, off_t len);
|
||||
static void *ts_mmap(void *, size_t, int, int, int, off_t);
|
||||
|
@ -155,11 +158,11 @@ struct TestSyscallArray {
|
|||
#define orig_fcntl ((int(*)(int,int,...))aSyscall[7].xOrig)
|
||||
#define orig_read ((ssize_t(*)(int,void*,size_t))aSyscall[8].xOrig)
|
||||
#define orig_pread ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[9].xOrig)
|
||||
#define orig_pread64 ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[10].xOrig)
|
||||
#define orig_pread64 ((ssize_t(*)(int,void*,size_t,sqlite3_uint64))aSyscall[10].xOrig)
|
||||
#define orig_write ((ssize_t(*)(int,const void*,size_t))aSyscall[11].xOrig)
|
||||
#define orig_pwrite ((ssize_t(*)(int,const void*,size_t,off_t))\
|
||||
aSyscall[12].xOrig)
|
||||
#define orig_pwrite64 ((ssize_t(*)(int,const void*,size_t,off_t))\
|
||||
#define orig_pwrite64 ((ssize_t(*)(int,const void*,size_t,sqlite3_uint64))\
|
||||
aSyscall[13].xOrig)
|
||||
#define orig_fchmod ((int(*)(int,mode_t))aSyscall[14].xOrig)
|
||||
#define orig_fallocate ((int(*)(int,off_t,off_t))aSyscall[15].xOrig)
|
||||
|
@ -326,7 +329,7 @@ static int ts_pread(int fd, void *aBuf, size_t nBuf, off_t off){
|
|||
/*
|
||||
** A wrapper around pread64().
|
||||
*/
|
||||
static int ts_pread64(int fd, void *aBuf, size_t nBuf, off_t off){
|
||||
static int ts_pread64(int fd, void *aBuf, size_t nBuf, sqlite3_uint64 off){
|
||||
if( tsIsFailErrno("pread64") ){
|
||||
return -1;
|
||||
}
|
||||
|
@ -357,7 +360,7 @@ static int ts_pwrite(int fd, const void *aBuf, size_t nBuf, off_t off){
|
|||
/*
|
||||
** A wrapper around pwrite64().
|
||||
*/
|
||||
static int ts_pwrite64(int fd, const void *aBuf, size_t nBuf, off_t off){
|
||||
static int ts_pwrite64(int fd, const void *aBuf, size_t nBuf, sqlite3_uint64 off){
|
||||
if( tsIsFailErrno("pwrite64") ){
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -306,7 +306,6 @@ static void tvfsExecTcl(
|
|||
** Close an tvfs-file.
|
||||
*/
|
||||
static int tvfsClose(sqlite3_file *pFile){
|
||||
int rc;
|
||||
TestvfsFile *pTestfile = (TestvfsFile *)pFile;
|
||||
TestvfsFd *pFd = pTestfile->pFd;
|
||||
Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
|
||||
|
@ -324,10 +323,10 @@ static int tvfsClose(sqlite3_file *pFile){
|
|||
if( pFile->pMethods ){
|
||||
ckfree((char *)pFile->pMethods);
|
||||
}
|
||||
rc = sqlite3OsClose(pFd->pReal);
|
||||
sqlite3OsClose(pFd->pReal);
|
||||
ckfree((char *)pFd);
|
||||
pTestfile->pFd = 0;
|
||||
return rc;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -931,7 +931,6 @@ int sqlite3VdbeSorterInit(
|
|||
){
|
||||
int pgsz; /* Page size of main database */
|
||||
int i; /* Used to iterate through aTask[] */
|
||||
int mxCache; /* Cache size */
|
||||
VdbeSorter *pSorter; /* The new sorter */
|
||||
KeyInfo *pKeyInfo; /* Copy of pCsr->pKeyInfo with db==0 */
|
||||
int szKeyInfo; /* Size of pCsr->pKeyInfo in bytes */
|
||||
|
@ -988,11 +987,20 @@ int sqlite3VdbeSorterInit(
|
|||
}
|
||||
|
||||
if( !sqlite3TempInMemory(db) ){
|
||||
i64 mxCache; /* Cache size in bytes*/
|
||||
u32 szPma = sqlite3GlobalConfig.szPma;
|
||||
pSorter->mnPmaSize = szPma * pgsz;
|
||||
|
||||
mxCache = db->aDb[0].pSchema->cache_size;
|
||||
if( mxCache<(int)szPma ) mxCache = (int)szPma;
|
||||
pSorter->mxPmaSize = MIN((i64)mxCache*pgsz, SQLITE_MAX_PMASZ);
|
||||
if( mxCache<0 ){
|
||||
/* A negative cache-size value C indicates that the cache is abs(C)
|
||||
** KiB in size. */
|
||||
mxCache = mxCache * -1024;
|
||||
}else{
|
||||
mxCache = mxCache * pgsz;
|
||||
}
|
||||
mxCache = MIN(mxCache, SQLITE_MAX_PMASZ);
|
||||
pSorter->mxPmaSize = MAX(pSorter->mnPmaSize, (int)mxCache);
|
||||
|
||||
/* EVIDENCE-OF: R-26747-61719 When the application provides any amount of
|
||||
** scratch memory using SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary
|
||||
|
|
30
src/where.c
30
src/where.c
|
@ -3881,9 +3881,9 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
|||
&& nRowEst
|
||||
){
|
||||
Bitmask notUsed;
|
||||
int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pResultSet, pFrom,
|
||||
int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pDistinctSet, pFrom,
|
||||
WHERE_DISTINCTBY, nLoop-1, pFrom->aLoop[nLoop-1], ¬Used);
|
||||
if( rc==pWInfo->pResultSet->nExpr ){
|
||||
if( rc==pWInfo->pDistinctSet->nExpr ){
|
||||
pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
|
||||
}
|
||||
}
|
||||
|
@ -4098,14 +4098,14 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
|
|||
** used.
|
||||
*/
|
||||
WhereInfo *sqlite3WhereBegin(
|
||||
Parse *pParse, /* The parser context */
|
||||
SrcList *pTabList, /* FROM clause: A list of all tables to be scanned */
|
||||
Expr *pWhere, /* The WHERE clause */
|
||||
ExprList *pOrderBy, /* An ORDER BY (or GROUP BY) clause, or NULL */
|
||||
ExprList *pResultSet, /* Result set of the query */
|
||||
u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */
|
||||
int iAuxArg /* If WHERE_ONETABLE_ONLY is set, index cursor number,
|
||||
** If WHERE_USE_LIMIT, then the limit amount */
|
||||
Parse *pParse, /* The parser context */
|
||||
SrcList *pTabList, /* FROM clause: A list of all tables to be scanned */
|
||||
Expr *pWhere, /* The WHERE clause */
|
||||
ExprList *pOrderBy, /* An ORDER BY (or GROUP BY) clause, or NULL */
|
||||
ExprList *pDistinctSet, /* Try not to output two rows that duplicate these */
|
||||
u16 wctrlFlags, /* The WHERE_* flags defined in sqliteInt.h */
|
||||
int iAuxArg /* If WHERE_ONETABLE_ONLY is set, index cursor number
|
||||
** If WHERE_USE_LIMIT, then the limit amount */
|
||||
){
|
||||
int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */
|
||||
int nTabList; /* Number of elements in pTabList */
|
||||
|
@ -4180,7 +4180,7 @@ WhereInfo *sqlite3WhereBegin(
|
|||
pWInfo->pParse = pParse;
|
||||
pWInfo->pTabList = pTabList;
|
||||
pWInfo->pOrderBy = pOrderBy;
|
||||
pWInfo->pResultSet = pResultSet;
|
||||
pWInfo->pDistinctSet = pDistinctSet;
|
||||
pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(v);
|
||||
pWInfo->wctrlFlags = wctrlFlags;
|
||||
pWInfo->iLimit = iAuxArg;
|
||||
|
@ -4253,13 +4253,13 @@ WhereInfo *sqlite3WhereBegin(
|
|||
if( db->mallocFailed ) goto whereBeginError;
|
||||
|
||||
if( wctrlFlags & WHERE_WANT_DISTINCT ){
|
||||
if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){
|
||||
if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pDistinctSet) ){
|
||||
/* The DISTINCT marking is pointless. Ignore it. */
|
||||
pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
|
||||
}else if( pOrderBy==0 ){
|
||||
/* Try to ORDER BY the result set to make distinct processing easier */
|
||||
pWInfo->wctrlFlags |= WHERE_DISTINCTBY;
|
||||
pWInfo->pOrderBy = pResultSet;
|
||||
pWInfo->pOrderBy = pDistinctSet;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4338,10 +4338,10 @@ WhereInfo *sqlite3WhereBegin(
|
|||
#endif
|
||||
/* Attempt to omit tables from the join that do not effect the result */
|
||||
if( pWInfo->nLevel>=2
|
||||
&& pResultSet!=0
|
||||
&& pDistinctSet!=0
|
||||
&& OptimizationEnabled(db, SQLITE_OmitNoopJoin)
|
||||
){
|
||||
Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pResultSet);
|
||||
Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pDistinctSet);
|
||||
if( sWLB.pOrderBy ){
|
||||
tabUsed |= sqlite3WhereExprListUsage(pMaskSet, sWLB.pOrderBy);
|
||||
}
|
||||
|
|
|
@ -408,7 +408,7 @@ struct WhereInfo {
|
|||
Parse *pParse; /* Parsing and code generating context */
|
||||
SrcList *pTabList; /* List of tables in the join */
|
||||
ExprList *pOrderBy; /* The ORDER BY clause or NULL */
|
||||
ExprList *pResultSet; /* Result set. DISTINCT operates on these */
|
||||
ExprList *pDistinctSet; /* DISTINCT over all these values */
|
||||
WhereLoop *pLoops; /* List of all WhereLoop objects */
|
||||
Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
|
||||
LogEst nRowOut; /* Estimated number of output rows */
|
||||
|
@ -492,6 +492,14 @@ void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereClause*);
|
|||
** operators that are of interest to the query planner. An
|
||||
** OR-ed combination of these values can be used when searching for
|
||||
** particular WhereTerms within a WhereClause.
|
||||
**
|
||||
** Value constraints:
|
||||
** WO_EQ == SQLITE_INDEX_CONSTRAINT_EQ
|
||||
** WO_LT == SQLITE_INDEX_CONSTRAINT_LT
|
||||
** WO_LE == SQLITE_INDEX_CONSTRAINT_LE
|
||||
** WO_GT == SQLITE_INDEX_CONSTRAINT_GT
|
||||
** WO_GE == SQLITE_INDEX_CONSTRAINT_GE
|
||||
** WO_MATCH == SQLITE_INDEX_CONSTRAINT_MATCH
|
||||
*/
|
||||
#define WO_IN 0x0001
|
||||
#define WO_EQ 0x0002
|
||||
|
|
|
@ -41,4 +41,76 @@ do_execsql_test 1.2 {
|
|||
|
||||
db close
|
||||
tvfs delete
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that the PMA size is determined correctly. The PMA size should be
|
||||
# roughly the same amount of memory allocated to the main pager cache, or
|
||||
# 250 pages if this is larger.
|
||||
#
|
||||
testvfs tvfs
|
||||
tvfs script tv_callback
|
||||
tvfs filter {xOpen xWrite}
|
||||
|
||||
proc tv_callback {method args} {
|
||||
global iTemp
|
||||
global F
|
||||
switch $method {
|
||||
xOpen {
|
||||
if {[lindex $args 0]==""} { return "temp[incr iTemp]" }
|
||||
return "SQLITE_OK"
|
||||
}
|
||||
|
||||
xWrite {
|
||||
foreach {filename id off amt} $args {}
|
||||
if {[info exists F($id)]==0 || $F($id)<($off + $amt)} {
|
||||
set F($id) [expr $off+$amt]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
catch { db close }
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db -vfs tvfs
|
||||
execsql { CREATE TABLE t1(x) }
|
||||
|
||||
# Each iteration of the following loop attempts to sort 10001 records
|
||||
# each a bit over 100 bytes in size. In total a little more than 1MiB
|
||||
# of data.
|
||||
#
|
||||
breakpoint
|
||||
foreach {tn pgsz cachesz bTemp} {
|
||||
2 1024 1000 1
|
||||
|
||||
1 4096 1000 0
|
||||
2 1024 1000 1
|
||||
|
||||
3 4096 -1000 1
|
||||
4 1024 -1000 1
|
||||
|
||||
5 4096 -9000 0
|
||||
6 1024 -9000 0
|
||||
} {
|
||||
do_execsql_test 2.$tn.0 "
|
||||
PRAGMA page_size = $pgsz;
|
||||
VACUUM;
|
||||
PRAGMA cache_size = $cachesz;
|
||||
"
|
||||
|
||||
do_test 2.$tn.1 {
|
||||
set ::iTemp 0
|
||||
catch { array unset F }
|
||||
execsql {
|
||||
WITH x(i, j) AS (
|
||||
SELECT 1, randomblob(100)
|
||||
UNION ALL
|
||||
SELECT i+1, randomblob(100) FROM x WHERE i<10000
|
||||
)
|
||||
SELECT * FROM x ORDER BY j;
|
||||
}
|
||||
expr {[array names F]!=""}
|
||||
} $bTemp
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
|
Loading…
Reference in New Issue