mirror of https://github.com/sqlite/sqlite
Merge the pre-3.8.6 changes into the threads branch.
FossilOrigin-Name: a608fd1d52606a009c3acc7f1d184b86a7df3c82
This commit is contained in:
commit
83b25d32d7
|
@ -318,7 +318,7 @@ static int unicodeNext(
|
|||
){
|
||||
unicode_cursor *pCsr = (unicode_cursor *)pC;
|
||||
unicode_tokenizer *p = ((unicode_tokenizer *)pCsr->base.pTokenizer);
|
||||
int iCode;
|
||||
int iCode = 0;
|
||||
char *zOut;
|
||||
const unsigned char *z = &pCsr->aInput[pCsr->iOff];
|
||||
const unsigned char *zStart = z;
|
||||
|
|
|
@ -39,7 +39,7 @@ int sqlite3FtsUnicodeIsalnum(int c){
|
|||
** C. It is not possible to represent a range larger than 1023 codepoints
|
||||
** using this format.
|
||||
*/
|
||||
const static unsigned int aEntry[] = {
|
||||
static const unsigned int aEntry[] = {
|
||||
0x00000030, 0x0000E807, 0x00016C06, 0x0001EC2F, 0x0002AC07,
|
||||
0x0002D001, 0x0002D803, 0x0002EC01, 0x0002FC01, 0x00035C01,
|
||||
0x0003DC01, 0x000B0804, 0x000B480E, 0x000B9407, 0x000BB401,
|
||||
|
@ -131,7 +131,7 @@ int sqlite3FtsUnicodeIsalnum(int c){
|
|||
return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 );
|
||||
}else if( c<(1<<22) ){
|
||||
unsigned int key = (((unsigned int)c)<<10) | 0x000003FF;
|
||||
int iRes;
|
||||
int iRes = 0;
|
||||
int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
|
||||
int iLo = 0;
|
||||
while( iHi>=iLo ){
|
||||
|
@ -202,7 +202,7 @@ static int remove_diacritic(int c){
|
|||
}
|
||||
assert( key>=aDia[iRes] );
|
||||
return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
@ -160,7 +160,7 @@ proc print_rd {map} {
|
|||
}
|
||||
assert( key>=aDia[iRes] );
|
||||
return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);}
|
||||
puts "\};"
|
||||
puts "\}"
|
||||
}
|
||||
|
||||
proc print_isdiacritic {zFunc map} {
|
||||
|
@ -298,7 +298,7 @@ proc an_print_range_array {lRange} {
|
|||
** using this format.
|
||||
*/
|
||||
}]
|
||||
puts -nonewline " const static unsigned int aEntry\[\] = \{"
|
||||
puts -nonewline " static const unsigned int aEntry\[\] = \{"
|
||||
set i 0
|
||||
foreach range $lRange {
|
||||
foreach {iFirst nRange} $range {}
|
||||
|
@ -349,7 +349,7 @@ proc print_isalnum {zFunc lRange} {
|
|||
return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 );
|
||||
}else if( c<(1<<22) ){
|
||||
unsigned int key = (((unsigned int)c)<<10) | 0x000003FF;
|
||||
int iRes;
|
||||
int iRes = 0;
|
||||
int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
|
||||
int iLo = 0;
|
||||
while( iHi>=iLo ){
|
||||
|
@ -732,7 +732,7 @@ proc print_fileheader {} {
|
|||
*/
|
||||
}]
|
||||
puts ""
|
||||
puts "#if defined(SQLITE_ENABLE_FTS4_UNICODE61)"
|
||||
puts "#ifndef SQLITE_DISABLE_FTS3_UNICODE"
|
||||
puts "#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)"
|
||||
puts ""
|
||||
puts "#include <assert.h>"
|
||||
|
@ -808,4 +808,4 @@ if {$::generate_test_code} {
|
|||
}
|
||||
|
||||
puts "#endif /* defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) */"
|
||||
puts "#endif /* !defined(SQLITE_ENABLE_FTS4_UNICODE61) */"
|
||||
puts "#endif /* !defined(SQLITE_DISABLE_FTS3_UNICODE) */"
|
||||
|
|
|
@ -61,7 +61,6 @@ static void writefileFunc(
|
|||
){
|
||||
FILE *out;
|
||||
const char *z;
|
||||
int n;
|
||||
sqlite3_int64 rc;
|
||||
const char *zFile;
|
||||
|
||||
|
@ -71,11 +70,9 @@ static void writefileFunc(
|
|||
if( out==0 ) return;
|
||||
z = (const char*)sqlite3_value_blob(argv[1]);
|
||||
if( z==0 ){
|
||||
n = 0;
|
||||
rc = 0;
|
||||
}else{
|
||||
n = sqlite3_value_bytes(argv[1]);
|
||||
rc = fwrite(z, 1, n, out);
|
||||
rc = fwrite(z, 1, sqlite3_value_bytes(argv[1]), out);
|
||||
}
|
||||
fclose(out);
|
||||
sqlite3_result_int64(context, rc);
|
||||
|
|
65
manifest
65
manifest
|
@ -1,5 +1,5 @@
|
|||
C Merge\sall\srecent\schanges\sfrom\strunk.
|
||||
D 2014-08-06T02:03:35.291
|
||||
C Merge\sthe\spre-3.8.6\schanges\sinto\sthe\sthreads\sbranch.
|
||||
D 2014-08-14T14:02:48.852
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in cf57f673d77606ab0f2d9627ca52a9ba1464146a
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
|
@ -94,22 +94,22 @@ F ext/fts3/fts3_tokenize_vtab.c 011170fe9eba5ff062f1a31d3188e00267716706
|
|||
F ext/fts3/fts3_tokenizer.c bbdc731bc91338050675c6d1da9ab82147391e16
|
||||
F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
|
||||
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
|
||||
F ext/fts3/fts3_unicode.c e80eef8a11f2020dc9c1eb95c5b405b9012f2fbe
|
||||
F ext/fts3/fts3_unicode2.c c8adda75aad0c6c252ef3dd555f811f437485044
|
||||
F ext/fts3/fts3_unicode.c a93f5edc0aff44ef8b06d7cb55b52026541ca145
|
||||
F ext/fts3/fts3_unicode2.c c3d01968d497bd7001e7dc774ba75b372738c057
|
||||
F ext/fts3/fts3_write.c 8260388626516a7005d06a9dce94f9e55c6c2a41
|
||||
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
|
||||
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
|
||||
F ext/fts3/tool/fts3view.c 3986531f2fc0ceca0c89c31ec7d0589b6adb19d6
|
||||
F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c
|
||||
F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
|
||||
F ext/fts3/unicode/mkunicode.tcl dc6f268eb526710e2c6e496c372471d773d0c368
|
||||
F ext/fts3/unicode/mkunicode.tcl a2567f9d6ad6779879a2e394c120ad8718557e65
|
||||
F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43
|
||||
F ext/icu/icu.c d415ccf984defeb9df2c0e1afcfaa2f6dc05eacb
|
||||
F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
|
||||
F ext/misc/amatch.c 678056a4bfcd83c4e82dea81d37543cd1d6dbee1
|
||||
F ext/misc/closure.c 636024302cde41b2bf0c542f81c40c624cfb7012
|
||||
F ext/misc/compress.c 76e45655f4046e756064ab10c62e18f2eb846b9f
|
||||
F ext/misc/fileio.c beea82bb5055b6590cffe2d2e6d922905894f691
|
||||
F ext/misc/fileio.c d4171c815d6543a9edef8308aab2951413cd8d0f
|
||||
F ext/misc/fuzzer.c 136533c53cfce0957f0b48fa11dba27e21c5c01d
|
||||
F ext/misc/ieee754.c b0362167289170627659e84173f5d2e8fee8566e
|
||||
F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
|
||||
|
@ -179,17 +179,17 @@ F src/delete.c bcf8f72126cea80fc3d5bc5494cf19b3f8935aaf
|
|||
F src/expr.c f749009cf4a8534efb5e0d5cd7c9fb1fb0f2836c
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c 8545f3b36da47473e10800ea4fb0810fd4062514
|
||||
F src/func.c 3bc223ea36cd29a91c481485343d0ee4257ab8dc
|
||||
F src/func.c bbb724b74ed96ca42675a7274646a71dd52bcda7
|
||||
F src/global.c 77ec119d6f6453039c2820336af8e8f804f20acf
|
||||
F src/hash.c d139319967164f139c8d1bb8a11b14db9c4ba3cd
|
||||
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
|
||||
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
||||
F src/insert.c 991e4964e9295da3993e2c0f81c7faf642371848
|
||||
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
||||
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
|
||||
F src/legacy.c febc2a9e7ad6c1a6191c7b5b9170b325d263f343
|
||||
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
|
||||
F src/loadext.c 867c7b330b740c6c917af9956b13b81d0a048303
|
||||
F src/main.c 42ba5977d1c4324620b2ef2bc05b7bb28a2331e4
|
||||
F src/main.c 333a7134a4e08f7660c4e52390eda99c49493ba6
|
||||
F src/malloc.c 0203ebce9152c6a0e5de520140b8ba65187350be
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c c0c990fcaddff810ea277b4fb5d9138603dd5d4b
|
||||
|
@ -207,8 +207,8 @@ F src/os.c 1b147e4cf7cc39e618115c14a086aed44bc91ace
|
|||
F src/os.h 60d419395e32a8029fa380a80a3da2e9030f635e
|
||||
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
|
||||
F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
|
||||
F src/os_unix.c a7baf1b30f3c58ba20b813e01aab23b18ae44f85
|
||||
F src/os_win.c 9a7fda788394109131677a9fceee8d54820b6c16
|
||||
F src/os_unix.c bd7df3094a60915c148517504c76df4fca24e542
|
||||
F src/os_win.c 058cefbeb0f9713b7cc161c6d09e5a1770d26e11
|
||||
F src/os_win.h 057344a6720b4c8405d9bd98f58cb37a6ee46c25
|
||||
F src/pager.c f6bb1fa6cdf2062f2d8aec3e64db302bca519ab8
|
||||
F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428
|
||||
|
@ -220,12 +220,12 @@ F src/pragma.c d10ef67c4de79f78188b965b4b7988aff1d66f2e
|
|||
F src/prepare.c 677521ab7132615a8a26107a1d1c3132f44ae337
|
||||
F src/printf.c af06f66927919730f03479fed6ae9854f73419f4
|
||||
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
|
||||
F src/resolve.c 5fc110baeacf120a73fe34e103f052632ff11a02
|
||||
F src/resolve.c 0ea356d32a5e884add23d1b9b4e8736681dd5697
|
||||
F src/rowset.c a9c9aae3234b44a6d7c6f5a3cadf90dce1e627be
|
||||
F src/select.c c28f5165280ea7214285e4c53a23b257e1a06127
|
||||
F src/shell.c 05e9e7f667a6340643b647c4be0db15dd7627d92
|
||||
F src/sqlite.h.in 44b761ddf5362581617d08457f11ee582eb103a2
|
||||
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
||||
F src/select.c f8b0b6c43bee15f4e239ead1c9c9e3009e507e39
|
||||
F src/shell.c 26f8ef7f52b26644bb9098c62cee8694c17b3259
|
||||
F src/sqlite.h.in fef15a64d1358f5c365bd3f46f4c1915d5a5e5f0
|
||||
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
|
||||
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
||||
F src/sqliteInt.h b500ee46173fb510f8e10891a58bbf8e657bb3e6
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
|
@ -284,11 +284,11 @@ F src/update.c ea336ce7b8b3fc5e316ba8f082e6445babf81059
|
|||
F src/utf.c a0314e637768a030e6e84a957d0c4f6ba910cc05
|
||||
F src/util.c 3076bdd51cdbf60a6e2e57fada745be37133c73e
|
||||
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
|
||||
F src/vdbe.c 787d1b5178abaf44600702f6976a927d79ce3a92
|
||||
F src/vdbe.c aae4addde348f8a8d94a907f41c4524b7e2e0529
|
||||
F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8
|
||||
F src/vdbeInt.h 8870adf012235708f125f8cd1c988f487dc3eb6f
|
||||
F src/vdbeapi.c 24e40422382beb774daab11fe9fe9d37e8a04949
|
||||
F src/vdbeaux.c 3f1d2baa4a8cbdad33cb255a5f4fd1af7a414683
|
||||
F src/vdbeaux.c 142fdb31f6423fb3c66a7b0687dbf894a259b1cf
|
||||
F src/vdbeblob.c 9205ce9d3b064d9600f8418a897fc88b5687d9ac
|
||||
F src/vdbemem.c d90a1e8acf8b63dc9d14cbbea12bfec6cec31394
|
||||
F src/vdbesort.c b9a830685826c057cfd41993902a5afc6fe436e1
|
||||
|
@ -297,8 +297,8 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
|
|||
F src/wal.c 264df50a1b33124130b23180ded2e2c5663c652a
|
||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||
F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45
|
||||
F src/where.c ce1b9a3a2573033cd15e0882719db7f211f21cdd
|
||||
F src/whereInt.h 929c1349b5355fd44f22cee5c14d72b3329c58a6
|
||||
F src/where.c ab20f9c24a422ee8900831b343c3d1e5e7aca87b
|
||||
F src/whereInt.h 923820bee9726033a501a08d2fc69b9c1ee4feb3
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
|
||||
|
@ -443,11 +443,11 @@ F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2
|
|||
F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e
|
||||
F test/distinct.test 086e70c765f172e8974e9f83b9ac5ca03c154e77
|
||||
F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376
|
||||
F test/e_createtable.test ed82efcedc4b3656b27a5fcd12335cdb7e20eeee
|
||||
F test/e_createtable.test 181653f6f45e3adde73f8686600ce5ad7515466b
|
||||
F test/e_delete.test d5186e2f5478b659f16a2c8b66c09892823e542a
|
||||
F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412
|
||||
F test/e_dropview.test 0c9f7f60989164a70a67a9d9c26d1083bc808306
|
||||
F test/e_expr.test 5c71d183fbf519a4769fd2e2124afdc70b5b1f42
|
||||
F test/e_expr.test 8f5fdd7261e2d746813b0c6a1c0e34824ad3c5ad
|
||||
F test/e_fkey.test a1783fe1f759e1990e6a11adfcf0702dac4d0707
|
||||
F test/e_fts3.test 5c02288842e4f941896fd44afdef564dd5fc1459
|
||||
F test/e_insert.test 7b2fa9cd1456f83474d6c5d27db3abaeb8be2023
|
||||
|
@ -590,7 +590,7 @@ F test/fts4unicode.test 01ec3fe2a7c3cfff3b4c0581b83caa11b33efa36
|
|||
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
|
||||
F test/func.test ae97561957aba6ca9e3a7b8a13aac41830d701ef
|
||||
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
|
||||
F test/func3.test e82d16b13739f1a0c5efb20048583c79b767b625
|
||||
F test/func3.test d202a7606d23f90988a664e88e268aed1087c11c
|
||||
F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f
|
||||
F test/func5.test cdd224400bc3e48d891827cc913a57051a426fa4
|
||||
F test/fuzz-oss1.test 4912e528ec9cf2f42134456933659d371c9e0d74
|
||||
|
@ -614,7 +614,7 @@ F test/incrblob.test e81846d214f3637622620fbde7cd526781cfe328
|
|||
F test/incrblob2.test bf4d549aa4a466d7fbe3e3a3693d3861263d5600
|
||||
F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4
|
||||
F test/incrblob4.test f26502a5697893e5acea268c910f16478c2f0fab
|
||||
F test/incrblob_err.test d2562d2771ebffd4b3af89ef64c140dd44371597
|
||||
F test/incrblob_err.test af1f12ba60d220c9752073ff2bda2ad59e88960d
|
||||
F test/incrblobfault.test 280474078f6da9e732cd2a215d3d854969014b6e
|
||||
F test/incrvacuum.test d2a6ddf5e429720b5fe502766af747915ccf6c32
|
||||
F test/incrvacuum2.test 379eeb8740b0ef60c372c439ad4cbea20b34bb9b
|
||||
|
@ -677,7 +677,7 @@ F test/lock_common.tcl 0c270b121d40959fa2f3add382200c27045b3d95
|
|||
F test/lookaside.test 93f07bac140c5bb1d49f3892d2684decafdc7af2
|
||||
F test/main.test 39c4bb8a157f57298ed1659d6df89d9f35aaf2c8
|
||||
F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
|
||||
F test/malloc.test ada8ae15193ffc6415bf431a6db31d4ec507dbfe
|
||||
F test/malloc.test 96939d2d1a6f39667bbebe5bc27c6525f2ab614e
|
||||
F test/malloc3.test e3b32c724b5a124b57cb0ed177f675249ad0c66a
|
||||
F test/malloc4.test 957337613002b7058a85116493a262f679f3a261
|
||||
F test/malloc5.test fafce0aa9157060445cd1a56ad50fc79d82f28c3
|
||||
|
@ -697,7 +697,8 @@ F test/mallocH.test 79b65aed612c9b3ed2dcdaa727c85895fd1bfbdb
|
|||
F test/mallocI.test a88c2b9627c8506bf4703d8397420043a786cdb6
|
||||
F test/mallocJ.test b5d1839da331d96223e5f458856f8ffe1366f62e
|
||||
F test/mallocK.test 3cff7c0f64735f6883bacdd294e45a6ed5714817
|
||||
F test/malloc_common.tcl 58e54229c4132ef882a11fab6419ec4cd3073589
|
||||
F test/mallocL.test 252ddc7eb4fbf75364eab17b938816085ff1fc17
|
||||
F test/malloc_common.tcl 3663f9001ce3e29bbaa9677ffe15cd468e3ec7e3
|
||||
F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e
|
||||
F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f
|
||||
F test/memdb.test fcb5297b321b562084fc79d64d5a12a1cd2b639b
|
||||
|
@ -773,7 +774,7 @@ F test/rdonly.test dd30a4858d8e0fbad2304c2bd74a33d4df36412a
|
|||
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
|
||||
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
|
||||
F test/releasetest.mk 2eced2f9ae701fd0a29e714a241760503ccba25a
|
||||
F test/releasetest.tcl 06d289d8255794073a58d2850742f627924545ce
|
||||
F test/releasetest.tcl a0df0dfc5e3ee83ade87b9cc96db41b52d590b9e
|
||||
F test/resolver01.test 33abf37ff8335e6bf98f2b45a0af3e06996ccd9a
|
||||
F test/rollback.test e9504a009a202c3ed711da2e6879ff60c5a4669c
|
||||
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
|
||||
|
@ -1112,7 +1113,7 @@ F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
|
|||
F test/where7.test 5a4b0abc207d71da4deecd734ad8579e8dd40aa8
|
||||
F test/where8.test 806f1dcec4088be2b826b33f757fe6e17c3236a1
|
||||
F test/where8m.test da346596e19d54f0aba35ebade032a7c47d79739
|
||||
F test/where9.test 4f3eab951353a3ae164befc521c777dfa903e46c
|
||||
F test/where9.test 729c3ba9b47e8f9f1aab96bae7dad2a524f1d1a2
|
||||
F test/whereA.test 4d253178d135ec46d1671e440cd8f2b916aa6e6b
|
||||
F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5
|
||||
F test/whereC.test d6f4ecd4fa2d9429681a5b22a25d2bda8e86ab8a
|
||||
|
@ -1122,7 +1123,7 @@ F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7
|
|||
F test/whereG.test 69f5ec4b15760a8c860f80e2d55525669390aab3
|
||||
F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2
|
||||
F test/whereI.test 1d89199697919d4930be05a71e7fe620f114e622
|
||||
F test/whereJ.test 7dde28284d20f358b559ca592e294db03e1d7103
|
||||
F test/whereJ.test 35a40a50d0e13aa6b0de7cc5d4b204e5f9f9669f
|
||||
F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31
|
||||
F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
|
||||
F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
|
||||
|
@ -1190,7 +1191,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
|||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 655d8cfc752b3f5f63521a57f2155f8e14aaf7c4 717245d48714c08156c9b7636aaa6c3a402bad66
|
||||
R 522f9cbdadcee03fc45f476dbd20c9a7
|
||||
P a353a8515fb2eff86042d0c33e39772f4d04e0b3 13a2d90a2869c53b79754de39045bbbdbc7688e3
|
||||
R 64b417b620c9f6c58aeb23fe611b07d3
|
||||
U drh
|
||||
Z 56e08fa149f3ad8b1a6753df47adb03f
|
||||
Z b2ed58163bf8c58a60958e9dca71f3dd
|
||||
|
|
|
@ -1 +1 @@
|
|||
a353a8515fb2eff86042d0c33e39772f4d04e0b3
|
||||
a608fd1d52606a009c3acc7f1d184b86a7df3c82
|
|
@ -9,12 +9,9 @@
|
|||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** This file contains the C functions that implement various SQL
|
||||
** functions of SQLite.
|
||||
**
|
||||
** There is only one exported symbol in this file - the function
|
||||
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
|
||||
** All other code has file scope.
|
||||
** This file contains the C-language implementions for many of the SQL
|
||||
** functions of SQLite. (Some function, and in particular the date and
|
||||
** time functions, are implemented separately.)
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <stdlib.h>
|
||||
|
|
|
@ -96,6 +96,9 @@ int sqlite3_exec(
|
|||
}
|
||||
}
|
||||
if( xCallback(pArg, nCol, azVals, azCols) ){
|
||||
/* EVIDENCE-OF: R-38229-40159 If the callback function to
|
||||
** sqlite3_exec() returns non-zero, then sqlite3_exec() will
|
||||
** return SQLITE_ABORT. */
|
||||
rc = SQLITE_ABORT;
|
||||
sqlite3VdbeFinalize((Vdbe *)pStmt);
|
||||
pStmt = 0;
|
||||
|
|
|
@ -836,6 +836,8 @@ static int connectionIsBusy(sqlite3 *db){
|
|||
*/
|
||||
static int sqlite3Close(sqlite3 *db, int forceZombie){
|
||||
if( !db ){
|
||||
/* EVIDENCE-OF: R-63257-11740 Calling sqlite3_close() or
|
||||
** sqlite3_close_v2() with a NULL pointer argument is a harmless no-op. */
|
||||
return SQLITE_OK;
|
||||
}
|
||||
if( !sqlite3SafetyCheckSickOrOk(db) ){
|
||||
|
@ -1065,7 +1067,7 @@ void sqlite3RollbackAll(sqlite3 *db, int tripCode){
|
|||
** Return a static string containing the name corresponding to the error code
|
||||
** specified in the argument.
|
||||
*/
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
||||
#if (defined(SQLITE_DEBUG) && SQLITE_OS_WIN) || defined(SQLITE_TEST)
|
||||
const char *sqlite3ErrName(int rc){
|
||||
const char *zName = 0;
|
||||
int i, origRc = rc;
|
||||
|
@ -1100,7 +1102,6 @@ const char *sqlite3ErrName(int rc){
|
|||
case SQLITE_IOERR_UNLOCK: zName = "SQLITE_IOERR_UNLOCK"; break;
|
||||
case SQLITE_IOERR_RDLOCK: zName = "SQLITE_IOERR_RDLOCK"; break;
|
||||
case SQLITE_IOERR_DELETE: zName = "SQLITE_IOERR_DELETE"; break;
|
||||
case SQLITE_IOERR_BLOCKED: zName = "SQLITE_IOERR_BLOCKED"; break;
|
||||
case SQLITE_IOERR_NOMEM: zName = "SQLITE_IOERR_NOMEM"; break;
|
||||
case SQLITE_IOERR_ACCESS: zName = "SQLITE_IOERR_ACCESS"; break;
|
||||
case SQLITE_IOERR_CHECKRESERVEDLOCK:
|
||||
|
@ -2085,7 +2086,7 @@ static const int aHardLimit[] = {
|
|||
SQLITE_MAX_FUNCTION_ARG,
|
||||
SQLITE_MAX_ATTACHED,
|
||||
SQLITE_MAX_LIKE_PATTERN_LENGTH,
|
||||
SQLITE_MAX_VARIABLE_NUMBER,
|
||||
SQLITE_MAX_VARIABLE_NUMBER, /* IMP: R-38091-32352 */
|
||||
SQLITE_MAX_TRIGGER_DEPTH,
|
||||
};
|
||||
|
||||
|
|
|
@ -94,11 +94,10 @@
|
|||
#include <sys/time.h>
|
||||
#include <errno.h>
|
||||
#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
|
||||
#include <sys/mman.h>
|
||||
# include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
|
||||
#if SQLITE_ENABLE_LOCKING_STYLE
|
||||
#if SQLITE_ENABLE_LOCKING_STYLE || OS_VXWORKS
|
||||
# include <sys/ioctl.h>
|
||||
# if OS_VXWORKS
|
||||
# include <semaphore.h>
|
||||
|
@ -318,7 +317,11 @@ static int posixOpen(const char *zFile, int flags, int mode){
|
|||
** we are not running as root.
|
||||
*/
|
||||
static int posixFchown(int fd, uid_t uid, gid_t gid){
|
||||
#if OS_VXWORKS
|
||||
return 0;
|
||||
#else
|
||||
return geteuid() ? 0 : fchown(fd,uid,gid);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Forward reference */
|
||||
|
@ -374,7 +377,7 @@ static struct unix_syscall {
|
|||
{ "read", (sqlite3_syscall_ptr)read, 0 },
|
||||
#define osRead ((ssize_t(*)(int,void*,size_t))aSyscall[8].pCurrent)
|
||||
|
||||
#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
|
||||
#if defined(USE_PREAD) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
|
||||
{ "pread", (sqlite3_syscall_ptr)pread, 0 },
|
||||
#else
|
||||
{ "pread", (sqlite3_syscall_ptr)0, 0 },
|
||||
|
@ -391,7 +394,7 @@ static struct unix_syscall {
|
|||
{ "write", (sqlite3_syscall_ptr)write, 0 },
|
||||
#define osWrite ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent)
|
||||
|
||||
#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
|
||||
#if defined(USE_PREAD) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
|
||||
{ "pwrite", (sqlite3_syscall_ptr)pwrite, 0 },
|
||||
#else
|
||||
{ "pwrite", (sqlite3_syscall_ptr)0, 0 },
|
||||
|
@ -761,16 +764,6 @@ static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
|
|||
case EPERM:
|
||||
return SQLITE_PERM;
|
||||
|
||||
/* EDEADLK is only possible if a call to fcntl(F_SETLKW) is made. And
|
||||
** this module never makes such a call. And the code in SQLite itself
|
||||
** asserts that SQLITE_IOERR_BLOCKED is never returned. For these reasons
|
||||
** this case is also commented out. If the system does set errno to EDEADLK,
|
||||
** the default SQLITE_IOERR_XXX code will be returned. */
|
||||
#if 0
|
||||
case EDEADLK:
|
||||
return SQLITE_IOERR_BLOCKED;
|
||||
#endif
|
||||
|
||||
#if EOPNOTSUPP!=ENOTSUP
|
||||
case EOPNOTSUPP:
|
||||
/* something went terribly awry, unless during file system support
|
||||
|
@ -1303,9 +1296,13 @@ static int findInodeInfo(
|
|||
** Return TRUE if pFile has been renamed or unlinked since it was first opened.
|
||||
*/
|
||||
static int fileHasMoved(unixFile *pFile){
|
||||
#if OS_VXWORKS
|
||||
return pFile->pInode!=0 && pFile->pId!=pFile->pInode->fileId.pId;
|
||||
#else
|
||||
struct stat buf;
|
||||
return pFile->pInode!=0 &&
|
||||
(osStat(pFile->zPath, &buf)!=0 || buf.st_ino!=pFile->pInode->fileId.ino);
|
||||
(osStat(pFile->zPath, &buf)!=0 || buf.st_ino!=pFile->pInode->fileId.ino);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -2448,7 +2445,6 @@ static int semCheckReservedLock(sqlite3_file *id, int *pResOut) {
|
|||
/* Otherwise see if some other process holds it. */
|
||||
if( !reserved ){
|
||||
sem_t *pSem = pFile->pInode->pSem;
|
||||
struct stat statBuf;
|
||||
|
||||
if( sem_trywait(pSem)==-1 ){
|
||||
int tErrno = errno;
|
||||
|
@ -2501,7 +2497,6 @@ static int semCheckReservedLock(sqlite3_file *id, int *pResOut) {
|
|||
*/
|
||||
static int semLock(sqlite3_file *id, int eFileLock) {
|
||||
unixFile *pFile = (unixFile*)id;
|
||||
int fd;
|
||||
sem_t *pSem = pFile->pInode->pSem;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
|
@ -5888,7 +5883,11 @@ static int unixDelete(
|
|||
UNUSED_PARAMETER(NotUsed);
|
||||
SimulateIOError(return SQLITE_IOERR_DELETE);
|
||||
if( osUnlink(zPath)==(-1) ){
|
||||
if( errno==ENOENT ){
|
||||
if( errno==ENOENT
|
||||
#if OS_VXWORKS
|
||||
|| errno==0x380003
|
||||
#endif
|
||||
){
|
||||
rc = SQLITE_IOERR_DELETE_NOENT;
|
||||
}else{
|
||||
rc = unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
|
||||
|
|
210
src/os_win.c
210
src/os_win.c
|
@ -72,18 +72,14 @@
|
|||
#endif
|
||||
|
||||
/*
|
||||
** Check if the GetVersionEx[AW] functions should be considered deprecated
|
||||
** and avoid using them in that case. It should be noted here that if the
|
||||
** value of the SQLITE_WIN32_GETVERSIONEX pre-processor macro is zero
|
||||
** (whether via this block or via being manually specified), that implies
|
||||
** the underlying operating system will always be based on the Windows NT
|
||||
** Kernel.
|
||||
** Check to see if the GetVersionEx[AW] functions are deprecated on the
|
||||
** target system. GetVersionEx was first deprecated in Win8.1.
|
||||
*/
|
||||
#ifndef SQLITE_WIN32_GETVERSIONEX
|
||||
# if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WINBLUE
|
||||
# define SQLITE_WIN32_GETVERSIONEX 0
|
||||
# define SQLITE_WIN32_GETVERSIONEX 0 /* GetVersionEx() is deprecated */
|
||||
# else
|
||||
# define SQLITE_WIN32_GETVERSIONEX 1
|
||||
# define SQLITE_WIN32_GETVERSIONEX 1 /* GetVersionEx() is current */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
@ -155,7 +151,7 @@
|
|||
** [sometimes] not used by the code (e.g. via conditional compilation).
|
||||
*/
|
||||
#ifndef UNUSED_VARIABLE_VALUE
|
||||
# define UNUSED_VARIABLE_VALUE(x) (void)(x)
|
||||
# define UNUSED_VARIABLE_VALUE(x) (void)(x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -204,7 +200,7 @@ WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID);
|
|||
** Some Microsoft compilers lack this definition.
|
||||
*/
|
||||
#ifndef INVALID_FILE_ATTRIBUTES
|
||||
# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
|
||||
# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
|
||||
#endif
|
||||
|
||||
#ifndef FILE_FLAG_MASK
|
||||
|
@ -254,7 +250,7 @@ struct winFile {
|
|||
int szChunk; /* Chunk size configured by FCNTL_CHUNK_SIZE */
|
||||
#if SQLITE_OS_WINCE
|
||||
LPWSTR zDeleteOnClose; /* Name of file to delete when closing */
|
||||
HANDLE hMutex; /* Mutex used to control access to shared lock */
|
||||
HANDLE hMutex; /* Mutex used to control access to shared lock */
|
||||
HANDLE hShared; /* Shared memory segment used for locking */
|
||||
winceLock local; /* Locks obtained by this instance of winFile */
|
||||
winceLock *shared; /* Global shared lock memory for the file */
|
||||
|
@ -1043,10 +1039,21 @@ static struct win_syscall {
|
|||
#define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \
|
||||
LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[75].pCurrent)
|
||||
|
||||
/*
|
||||
** NOTE: On some sub-platforms, the InterlockedCompareExchange "function"
|
||||
** is really just a macro that uses a compiler intrinsic (e.g. x64).
|
||||
** So do not try to make this is into a redefinable interface.
|
||||
*/
|
||||
#if defined(InterlockedCompareExchange)
|
||||
{ "InterlockedCompareExchange", (SYSCALL)0, 0 },
|
||||
|
||||
#define osInterlockedCompareExchange InterlockedCompareExchange
|
||||
#else
|
||||
{ "InterlockedCompareExchange", (SYSCALL)InterlockedCompareExchange, 0 },
|
||||
|
||||
#define osInterlockedCompareExchange ((LONG(WINAPI*)(LONG volatile*, \
|
||||
LONG,LONG))aSyscall[76].pCurrent)
|
||||
#endif /* defined(InterlockedCompareExchange) */
|
||||
|
||||
}; /* End of the overrideable system calls */
|
||||
|
||||
|
@ -1313,20 +1320,29 @@ DWORD sqlite3Win32Wait(HANDLE hObject){
|
|||
** based on the NT kernel.
|
||||
*/
|
||||
int sqlite3_win32_is_nt(void){
|
||||
#if defined(SQLITE_WIN32_GETVERSIONEX) && SQLITE_WIN32_GETVERSIONEX
|
||||
if( osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0 ){
|
||||
#if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WIN8
|
||||
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
|
||||
defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WIN8
|
||||
OSVERSIONINFOW sInfo;
|
||||
sInfo.dwOSVersionInfoSize = sizeof(sInfo);
|
||||
osGetVersionExW(&sInfo);
|
||||
#else
|
||||
osInterlockedCompareExchange(&sqlite3_os_type,
|
||||
(sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);
|
||||
#elif defined(SQLITE_WIN32_HAS_ANSI)
|
||||
OSVERSIONINFOA sInfo;
|
||||
sInfo.dwOSVersionInfoSize = sizeof(sInfo);
|
||||
osGetVersionExA(&sInfo);
|
||||
#endif
|
||||
osInterlockedCompareExchange(&sqlite3_os_type,
|
||||
(sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);
|
||||
#endif
|
||||
}
|
||||
return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
|
||||
#elif SQLITE_TEST
|
||||
return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SQLITE_WIN32_MALLOC
|
||||
|
@ -1535,7 +1551,7 @@ void sqlite3MemSetDefault(void){
|
|||
#endif /* SQLITE_WIN32_MALLOC */
|
||||
|
||||
/*
|
||||
** Convert a UTF-8 string to Microsoft Unicode (UTF-16?).
|
||||
** Convert a UTF-8 string to Microsoft Unicode (UTF-16?).
|
||||
**
|
||||
** Space to hold the returned string is obtained from malloc.
|
||||
*/
|
||||
|
@ -1588,7 +1604,7 @@ static char *winUnicodeToUtf8(LPCWSTR zWideFilename){
|
|||
/*
|
||||
** Convert an ANSI string to Microsoft Unicode, based on the
|
||||
** current codepage settings for file apis.
|
||||
**
|
||||
**
|
||||
** Space to hold the returned string is obtained
|
||||
** from sqlite3_malloc.
|
||||
*/
|
||||
|
@ -1662,7 +1678,7 @@ char *sqlite3_win32_mbcs_to_utf8(const char *zFilename){
|
|||
}
|
||||
|
||||
/*
|
||||
** Convert UTF-8 to multibyte character string. Space to hold the
|
||||
** Convert UTF-8 to multibyte character string. Space to hold the
|
||||
** returned string is obtained from sqlite3_malloc().
|
||||
*/
|
||||
char *sqlite3_win32_utf8_to_mbcs(const char *zFilename){
|
||||
|
@ -1802,11 +1818,11 @@ static int winGetLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){
|
|||
**
|
||||
** This routine is invoked after an error occurs in an OS function.
|
||||
** It logs a message using sqlite3_log() containing the current value of
|
||||
** error code and, if possible, the human-readable equivalent from
|
||||
** error code and, if possible, the human-readable equivalent from
|
||||
** FormatMessage.
|
||||
**
|
||||
** The first argument passed to the macro should be the error code that
|
||||
** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
|
||||
** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
|
||||
** The two subsequent arguments should be the name of the OS function that
|
||||
** failed and the associated file-system path, if any.
|
||||
*/
|
||||
|
@ -1837,7 +1853,7 @@ static int winLogErrorAtLine(
|
|||
|
||||
/*
|
||||
** The number of times that a ReadFile(), WriteFile(), and DeleteFile()
|
||||
** will be retried following a locking error - probably caused by
|
||||
** will be retried following a locking error - probably caused by
|
||||
** antivirus software. Also the initial delay before the first retry.
|
||||
** The delay increases linearly with each retry.
|
||||
*/
|
||||
|
@ -1912,7 +1928,7 @@ static int winRetryIoerr(int *pnRetry, DWORD *pError){
|
|||
*/
|
||||
static void winLogIoerr(int nRetry){
|
||||
if( nRetry ){
|
||||
sqlite3_log(SQLITE_IOERR,
|
||||
sqlite3_log(SQLITE_IOERR,
|
||||
"delayed %dms for lock/sharing conflict",
|
||||
winIoerrRetryDelay*nRetry*(nRetry+1)/2
|
||||
);
|
||||
|
@ -2006,17 +2022,17 @@ static int winceCreateLock(const char *zFilename, winFile *pFile){
|
|||
|
||||
/* Acquire the mutex before continuing */
|
||||
winceMutexAcquire(pFile->hMutex);
|
||||
|
||||
/* Since the names of named mutexes, semaphores, file mappings etc are
|
||||
|
||||
/* Since the names of named mutexes, semaphores, file mappings etc are
|
||||
** case-sensitive, take advantage of that by uppercasing the mutex name
|
||||
** and using that as the shared filemapping name.
|
||||
*/
|
||||
osCharUpperW(zName);
|
||||
pFile->hShared = osCreateFileMappingW(INVALID_HANDLE_VALUE, NULL,
|
||||
PAGE_READWRITE, 0, sizeof(winceLock),
|
||||
zName);
|
||||
zName);
|
||||
|
||||
/* Set a flag that indicates we're the first to create the memory so it
|
||||
/* Set a flag that indicates we're the first to create the memory so it
|
||||
** must be zero-initialized */
|
||||
lastErrno = osGetLastError();
|
||||
if (lastErrno == ERROR_ALREADY_EXISTS){
|
||||
|
@ -2027,7 +2043,7 @@ static int winceCreateLock(const char *zFilename, winFile *pFile){
|
|||
|
||||
/* If we succeeded in making the shared memory handle, map it. */
|
||||
if( pFile->hShared ){
|
||||
pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared,
|
||||
pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared,
|
||||
FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock));
|
||||
/* If mapping failed, close the shared memory handle and erase it */
|
||||
if( !pFile->shared ){
|
||||
|
@ -2053,7 +2069,7 @@ static int winceCreateLock(const char *zFilename, winFile *pFile){
|
|||
pFile->hMutex = NULL;
|
||||
return SQLITE_IOERR;
|
||||
}
|
||||
|
||||
|
||||
/* Initialize the shared memory if we're supposed to */
|
||||
if( bInit ){
|
||||
memset(pFile->shared, 0, sizeof(winceLock));
|
||||
|
@ -2091,13 +2107,13 @@ static void winceDestroyLock(winFile *pFile){
|
|||
osCloseHandle(pFile->hShared);
|
||||
|
||||
/* Done with the mutex */
|
||||
winceMutexRelease(pFile->hMutex);
|
||||
winceMutexRelease(pFile->hMutex);
|
||||
osCloseHandle(pFile->hMutex);
|
||||
pFile->hMutex = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
** An implementation of the LockFile() API of Windows for CE
|
||||
*/
|
||||
static BOOL winceLockFile(
|
||||
|
@ -2308,8 +2324,8 @@ static BOOL winUnlockFile(
|
|||
#endif
|
||||
|
||||
/*
|
||||
** Move the current position of the file handle passed as the first
|
||||
** argument to offset iOffset within the file. If successful, return 0.
|
||||
** Move the current position of the file handle passed as the first
|
||||
** argument to offset iOffset within the file. If successful, return 0.
|
||||
** Otherwise, set pFile->lastErrno and return non-zero.
|
||||
*/
|
||||
static int winSeekFile(winFile *pFile, sqlite3_int64 iOffset){
|
||||
|
@ -2324,11 +2340,11 @@ static int winSeekFile(winFile *pFile, sqlite3_int64 iOffset){
|
|||
upperBits = (LONG)((iOffset>>32) & 0x7fffffff);
|
||||
lowerBits = (LONG)(iOffset & 0xffffffff);
|
||||
|
||||
/* API oddity: If successful, SetFilePointer() returns a dword
|
||||
/* API oddity: If successful, SetFilePointer() returns a dword
|
||||
** containing the lower 32-bits of the new file-offset. Or, if it fails,
|
||||
** it returns INVALID_SET_FILE_POINTER. However according to MSDN,
|
||||
** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine
|
||||
** whether an error has actually occurred, it is also necessary to call
|
||||
** it returns INVALID_SET_FILE_POINTER. However according to MSDN,
|
||||
** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine
|
||||
** whether an error has actually occurred, it is also necessary to call
|
||||
** GetLastError().
|
||||
*/
|
||||
dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
|
||||
|
@ -2411,7 +2427,7 @@ static int winClose(sqlite3_file *id){
|
|||
int cnt = 0;
|
||||
while(
|
||||
osDeleteFileW(pFile->zDeleteOnClose)==0
|
||||
&& osGetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff
|
||||
&& osGetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff
|
||||
&& cnt++ < WINCE_DELETION_ATTEMPTS
|
||||
){
|
||||
sqlite3_win32_sleep(100); /* Wait a little before trying again */
|
||||
|
@ -3259,7 +3275,7 @@ static int winDeviceCharacteristics(sqlite3_file *id){
|
|||
((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0);
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
** Windows will only let you create file view mappings
|
||||
** on allocation size granularity boundaries.
|
||||
** During sqlite3_os_init() we do a GetSystemInfo()
|
||||
|
@ -3271,11 +3287,11 @@ static SYSTEM_INFO winSysInfo;
|
|||
|
||||
/*
|
||||
** Helper functions to obtain and relinquish the global mutex. The
|
||||
** global mutex is used to protect the winLockInfo objects used by
|
||||
** global mutex is used to protect the winLockInfo objects used by
|
||||
** this file, all of which may be shared by multiple threads.
|
||||
**
|
||||
** Function winShmMutexHeld() is used to assert() that the global mutex
|
||||
** is held when required. This function is only used as part of assert()
|
||||
** Function winShmMutexHeld() is used to assert() that the global mutex
|
||||
** is held when required. This function is only used as part of assert()
|
||||
** statements. e.g.
|
||||
**
|
||||
** winShmEnterMutex()
|
||||
|
@ -3305,10 +3321,10 @@ static int winShmMutexHeld(void) {
|
|||
** this object or while reading or writing the following fields:
|
||||
**
|
||||
** nRef
|
||||
** pNext
|
||||
** pNext
|
||||
**
|
||||
** The following fields are read-only after the object is created:
|
||||
**
|
||||
**
|
||||
** fid
|
||||
** zFilename
|
||||
**
|
||||
|
@ -3404,7 +3420,7 @@ static int winShmSystemLock(
|
|||
if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
|
||||
rc = winLockFile(&pFile->hFile.h, dwFlags, ofst, 0, nByte, 0);
|
||||
}
|
||||
|
||||
|
||||
if( rc!= 0 ){
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
|
@ -3500,7 +3516,7 @@ static int winOpenSharedMemory(winFile *pDbFd){
|
|||
}
|
||||
pNew->zFilename = (char*)&pNew[1];
|
||||
sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
|
||||
sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename);
|
||||
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.
|
||||
|
@ -3537,7 +3553,7 @@ static int winOpenSharedMemory(winFile *pDbFd){
|
|||
}
|
||||
|
||||
/* Check to see if another process is holding the dead-man switch.
|
||||
** If not, truncate the file to zero length.
|
||||
** If not, truncate the file to zero length.
|
||||
*/
|
||||
if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){
|
||||
rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0);
|
||||
|
@ -3566,7 +3582,7 @@ static int winOpenSharedMemory(winFile *pDbFd){
|
|||
** the cover of the winShmEnterMutex() mutex and the pointer from the
|
||||
** new (struct winShm) object to the pShmNode has been set. All that is
|
||||
** left to do is to link the new object into the linked list starting
|
||||
** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
|
||||
** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
|
||||
** mutex.
|
||||
*/
|
||||
sqlite3_mutex_enter(pShmNode->mutex);
|
||||
|
@ -3586,7 +3602,7 @@ shm_open_err:
|
|||
}
|
||||
|
||||
/*
|
||||
** Close a connection to shared-memory. Delete the underlying
|
||||
** Close a connection to shared-memory. Delete the underlying
|
||||
** storage if deleteFlag is true.
|
||||
*/
|
||||
static int winShmUnmap(
|
||||
|
@ -3675,7 +3691,7 @@ static int winShmLock(
|
|||
if( rc==SQLITE_OK ){
|
||||
p->exclMask &= ~mask;
|
||||
p->sharedMask &= ~mask;
|
||||
}
|
||||
}
|
||||
}else if( flags & SQLITE_SHM_SHARED ){
|
||||
u16 allShared = 0; /* Union of locks held by connections other than "p" */
|
||||
|
||||
|
@ -3714,7 +3730,7 @@ static int winShmLock(
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Get the exclusive locks at the system level. Then if successful
|
||||
** also mark the local connection as being locked.
|
||||
*/
|
||||
|
@ -3734,7 +3750,7 @@ static int winShmLock(
|
|||
}
|
||||
|
||||
/*
|
||||
** Implement a memory barrier or memory fence on shared memory.
|
||||
** Implement a memory barrier or memory fence on shared memory.
|
||||
**
|
||||
** All loads and stores begun before the barrier must complete before
|
||||
** any load or store begun after the barrier.
|
||||
|
@ -3749,22 +3765,22 @@ static void winShmBarrier(
|
|||
}
|
||||
|
||||
/*
|
||||
** This function is called to obtain a pointer to region iRegion of the
|
||||
** shared-memory associated with the database file fd. Shared-memory regions
|
||||
** are numbered starting from zero. Each shared-memory region is szRegion
|
||||
** This function is called to obtain a pointer to region iRegion of the
|
||||
** shared-memory associated with the database file fd. Shared-memory regions
|
||||
** are numbered starting from zero. Each shared-memory region is szRegion
|
||||
** bytes in size.
|
||||
**
|
||||
** If an error occurs, an error code is returned and *pp is set to NULL.
|
||||
**
|
||||
** Otherwise, if the isWrite parameter is 0 and the requested shared-memory
|
||||
** region has not been allocated (by any client, including one running in a
|
||||
** separate process), then *pp is set to NULL and SQLITE_OK returned. If
|
||||
** isWrite is non-zero and the requested shared-memory region has not yet
|
||||
** separate process), then *pp is set to NULL and SQLITE_OK returned. If
|
||||
** isWrite is non-zero and the requested shared-memory region has not yet
|
||||
** been allocated, it is allocated by this function.
|
||||
**
|
||||
** If the shared-memory region has already been allocated or is allocated by
|
||||
** this call as described above, then it is mapped into this processes
|
||||
** address space (if it is not already), *pp is set to point to the mapped
|
||||
** this call as described above, then it is mapped into this processes
|
||||
** address space (if it is not already), *pp is set to point to the mapped
|
||||
** memory and SQLITE_OK returned.
|
||||
*/
|
||||
static int winShmMap(
|
||||
|
@ -3836,17 +3852,17 @@ static int winShmMap(
|
|||
while( pShmNode->nRegion<=iRegion ){
|
||||
HANDLE hMap = NULL; /* file-mapping handle */
|
||||
void *pMap = 0; /* Mapped memory region */
|
||||
|
||||
|
||||
#if SQLITE_OS_WINRT
|
||||
hMap = osCreateFileMappingFromApp(pShmNode->hFile.h,
|
||||
NULL, PAGE_READWRITE, nByte, NULL
|
||||
);
|
||||
#elif defined(SQLITE_WIN32_HAS_WIDE)
|
||||
hMap = osCreateFileMappingW(pShmNode->hFile.h,
|
||||
hMap = osCreateFileMappingW(pShmNode->hFile.h,
|
||||
NULL, PAGE_READWRITE, 0, nByte, NULL
|
||||
);
|
||||
#elif defined(SQLITE_WIN32_HAS_ANSI)
|
||||
hMap = osCreateFileMappingA(pShmNode->hFile.h,
|
||||
hMap = osCreateFileMappingA(pShmNode->hFile.h,
|
||||
NULL, PAGE_READWRITE, 0, nByte, NULL
|
||||
);
|
||||
#endif
|
||||
|
@ -3943,14 +3959,14 @@ static int winUnmapfile(winFile *pFile){
|
|||
|
||||
/*
|
||||
** Memory map or remap the file opened by file-descriptor pFd (if the file
|
||||
** is already mapped, the existing mapping is replaced by the new). Or, if
|
||||
** there already exists a mapping for this file, and there are still
|
||||
** is already mapped, the existing mapping is replaced by the new). Or, if
|
||||
** there already exists a mapping for this file, and there are still
|
||||
** outstanding xFetch() references to it, this function is a no-op.
|
||||
**
|
||||
** If parameter nByte is non-negative, then it is the requested size of
|
||||
** the mapping to create. Otherwise, if nByte is less than zero, then the
|
||||
** If parameter nByte is non-negative, then it is the requested size of
|
||||
** the mapping to create. Otherwise, if nByte is less than zero, then the
|
||||
** requested size is the size of the file on disk. The actual size of the
|
||||
** created mapping is either the requested size or the value configured
|
||||
** created mapping is either the requested size or the value configured
|
||||
** using SQLITE_FCNTL_MMAP_SIZE, whichever is smaller.
|
||||
**
|
||||
** SQLITE_OK is returned if no error occurs (even if the mapping is not
|
||||
|
@ -3979,7 +3995,7 @@ static int winMapfile(winFile *pFd, sqlite3_int64 nByte){
|
|||
nMap = pFd->mmapSizeMax;
|
||||
}
|
||||
nMap &= ~(sqlite3_int64)(winSysInfo.dwPageSize - 1);
|
||||
|
||||
|
||||
if( nMap==0 && pFd->mmapSize>0 ){
|
||||
winUnmapfile(pFd);
|
||||
}
|
||||
|
@ -4051,7 +4067,7 @@ static int winMapfile(winFile *pFd, sqlite3_int64 nByte){
|
|||
** Finally, if an error does occur, return an SQLite error code. The final
|
||||
** value of *pp is undefined in this case.
|
||||
**
|
||||
** If this function does return a pointer, the caller must eventually
|
||||
** If this function does return a pointer, the caller must eventually
|
||||
** release the reference by calling winUnfetch().
|
||||
*/
|
||||
static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
|
||||
|
@ -4086,20 +4102,20 @@ static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
|
|||
}
|
||||
|
||||
/*
|
||||
** If the third argument is non-NULL, then this function releases a
|
||||
** If the third argument is non-NULL, then this function releases a
|
||||
** reference obtained by an earlier call to winFetch(). The second
|
||||
** argument passed to this function must be the same as the corresponding
|
||||
** argument that was passed to the winFetch() invocation.
|
||||
** argument that was passed to the winFetch() invocation.
|
||||
**
|
||||
** Or, if the third argument is NULL, then this function is being called
|
||||
** to inform the VFS layer that, according to POSIX, any existing mapping
|
||||
** Or, if the third argument is NULL, then this function is being called
|
||||
** to inform the VFS layer that, according to POSIX, any existing mapping
|
||||
** may now be invalid and should be unmapped.
|
||||
*/
|
||||
static int winUnfetch(sqlite3_file *fd, i64 iOff, void *p){
|
||||
#if SQLITE_MAX_MMAP_SIZE>0
|
||||
winFile *pFd = (winFile*)fd; /* The underlying database file */
|
||||
|
||||
/* If p==0 (unmap the entire file) then there must be no outstanding
|
||||
/* If p==0 (unmap the entire file) then there must be no outstanding
|
||||
** xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
|
||||
** then there must be at least one outstanding. */
|
||||
assert( (p==0)==(pFd->nFetchOut==0) );
|
||||
|
@ -4245,7 +4261,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
|
|||
|
||||
/* 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.
|
||||
** function failing.
|
||||
*/
|
||||
SimulateIOError( return SQLITE_IOERR );
|
||||
|
||||
|
@ -4427,7 +4443,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
|
|||
}
|
||||
|
||||
/*
|
||||
** Check that the output buffer is large enough for the temporary file
|
||||
** Check that the output buffer is large enough for the temporary file
|
||||
** name in the following format:
|
||||
**
|
||||
** "<temporary_directory>/etilqs_XXXXXXXXXXXXXXX\0\0"
|
||||
|
@ -4530,8 +4546,8 @@ static int winOpen(
|
|||
|
||||
#ifndef NDEBUG
|
||||
int isOpenJournal = (isCreate && (
|
||||
eType==SQLITE_OPEN_MASTER_JOURNAL
|
||||
|| eType==SQLITE_OPEN_MAIN_JOURNAL
|
||||
eType==SQLITE_OPEN_MASTER_JOURNAL
|
||||
|| eType==SQLITE_OPEN_MAIN_JOURNAL
|
||||
|| eType==SQLITE_OPEN_WAL
|
||||
));
|
||||
#endif
|
||||
|
@ -4539,9 +4555,9 @@ static int winOpen(
|
|||
OSTRACE(("OPEN name=%s, pFile=%p, flags=%x, pOutFlags=%p\n",
|
||||
zUtf8Name, id, flags, pOutFlags));
|
||||
|
||||
/* Check the following statements are true:
|
||||
/* Check the following statements are true:
|
||||
**
|
||||
** (a) Exactly one of the READWRITE and READONLY flags must be set, and
|
||||
** (a) Exactly one of the READWRITE and READONLY flags must be set, and
|
||||
** (b) if CREATE is set, then READWRITE must also be set, and
|
||||
** (c) if EXCLUSIVE is set, then CREATE must also be set.
|
||||
** (d) if DELETEONCLOSE is set, then CREATE must also be set.
|
||||
|
@ -4551,7 +4567,7 @@ static int winOpen(
|
|||
assert(isExclusive==0 || isCreate);
|
||||
assert(isDelete==0 || isCreate);
|
||||
|
||||
/* The main DB, main journal, WAL file and master journal are never
|
||||
/* The main DB, main journal, WAL file and master journal are never
|
||||
** automatically deleted. Nor are they ever temporary files. */
|
||||
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
|
||||
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
|
||||
|
@ -4559,9 +4575,9 @@ static int winOpen(
|
|||
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
|
||||
|
||||
/* Assert that the upper layer has set one of the "file-type" flags. */
|
||||
assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
|
||||
|| eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
|
||||
|| eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL
|
||||
assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
|
||||
|| eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
|
||||
|| eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL
|
||||
|| eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
|
||||
);
|
||||
|
||||
|
@ -4576,8 +4592,8 @@ static int winOpen(
|
|||
}
|
||||
#endif
|
||||
|
||||
/* If the second argument to this function is NULL, generate a
|
||||
** temporary file name to use
|
||||
/* If the second argument to this function is NULL, generate a
|
||||
** temporary file name to use
|
||||
*/
|
||||
if( !zUtf8Name ){
|
||||
assert( isDelete && !isOpenJournal );
|
||||
|
@ -4617,8 +4633,8 @@ static int winOpen(
|
|||
dwDesiredAccess = GENERIC_READ;
|
||||
}
|
||||
|
||||
/* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is
|
||||
** created. SQLite doesn't use it to indicate "exclusive access"
|
||||
/* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is
|
||||
** created. SQLite doesn't use it to indicate "exclusive access"
|
||||
** as it is usually understood.
|
||||
*/
|
||||
if( isExclusive ){
|
||||
|
@ -4707,7 +4723,7 @@ static int winOpen(
|
|||
sqlite3_free(zConverted);
|
||||
sqlite3_free(zTmpname);
|
||||
if( isReadWrite && !isExclusive ){
|
||||
return winOpen(pVfs, zName, id,
|
||||
return winOpen(pVfs, zName, id,
|
||||
((flags|SQLITE_OPEN_READONLY) &
|
||||
~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)),
|
||||
pOutFlags);
|
||||
|
@ -4916,14 +4932,14 @@ static int winAccess(
|
|||
WIN32_FILE_ATTRIBUTE_DATA sAttrData;
|
||||
memset(&sAttrData, 0, sizeof(sAttrData));
|
||||
while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
|
||||
GetFileExInfoStandard,
|
||||
GetFileExInfoStandard,
|
||||
&sAttrData)) && winRetryIoerr(&cnt, &lastErrno) ){}
|
||||
if( rc ){
|
||||
/* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
|
||||
** as if it does not exist.
|
||||
*/
|
||||
if( flags==SQLITE_ACCESS_EXISTS
|
||||
&& sAttrData.nFileSizeHigh==0
|
||||
&& sAttrData.nFileSizeHigh==0
|
||||
&& sAttrData.nFileSizeLow==0 ){
|
||||
attr = INVALID_FILE_ATTRIBUTES;
|
||||
}else{
|
||||
|
@ -5022,7 +5038,7 @@ static int winFullPathname(
|
|||
int nFull, /* Size of output buffer in bytes */
|
||||
char *zFull /* Output buffer */
|
||||
){
|
||||
|
||||
|
||||
#if defined(__CYGWIN__)
|
||||
SimulateIOError( return SQLITE_ERROR );
|
||||
UNUSED_PARAMETER(nFull);
|
||||
|
@ -5335,12 +5351,12 @@ int sqlite3_current_time = 0; /* Fake system time in seconds since 1970. */
|
|||
** epoch of noon in Greenwich on November 24, 4714 B.C according to the
|
||||
** proleptic Gregorian calendar.
|
||||
**
|
||||
** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date
|
||||
** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date
|
||||
** cannot be found.
|
||||
*/
|
||||
static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
|
||||
/* FILETIME structure is a 64-bit value representing the number of
|
||||
100-nanosecond intervals since January 1, 1601 (= JD 2305813.5).
|
||||
/* FILETIME structure is a 64-bit value representing the number of
|
||||
100-nanosecond intervals since January 1, 1601 (= JD 2305813.5).
|
||||
*/
|
||||
FILETIME ft;
|
||||
static const sqlite3_int64 winFiletimeEpoch = 23058135*(sqlite3_int64)8640000;
|
||||
|
@ -5348,7 +5364,7 @@ static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
|
|||
static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
|
||||
#endif
|
||||
/* 2^32 - to avoid use of LL and warnings in gcc */
|
||||
static const sqlite3_int64 max32BitValue =
|
||||
static const sqlite3_int64 max32BitValue =
|
||||
(sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 +
|
||||
(sqlite3_int64)294967296;
|
||||
|
||||
|
@ -5364,7 +5380,7 @@ static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
|
|||
#endif
|
||||
|
||||
*piNow = winFiletimeEpoch +
|
||||
((((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) +
|
||||
((((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) +
|
||||
(sqlite3_int64)ft.dwLowDateTime)/(sqlite3_int64)10000;
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
|
@ -5501,10 +5517,10 @@ int sqlite3_os_init(void){
|
|||
sqlite3_vfs_register(&winLongPathVfs, 0);
|
||||
#endif
|
||||
|
||||
return SQLITE_OK;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
int sqlite3_os_end(void){
|
||||
int sqlite3_os_end(void){
|
||||
#if SQLITE_OS_WINRT
|
||||
if( sleepObj!=NULL ){
|
||||
osCloseHandle(sleepObj);
|
||||
|
|
|
@ -354,7 +354,7 @@ static int lookupName(
|
|||
}
|
||||
}
|
||||
if( iCol>=pTab->nCol && sqlite3IsRowid(zCol) && HasRowid(pTab) ){
|
||||
/* IMP: R-24309-18625 */
|
||||
/* IMP: R-51414-32910 */
|
||||
/* IMP: R-44911-55124 */
|
||||
iCol = -1;
|
||||
}
|
||||
|
@ -710,7 +710,11 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
|||
/* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is equivalent to
|
||||
** likelihood(X, 0.0625).
|
||||
** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is short-hand for
|
||||
** likelihood(X,0.0625). */
|
||||
** likelihood(X,0.0625).
|
||||
** EVIDENCE-OF: R-36850-34127 The likely(X) function is short-hand for
|
||||
** likelihood(X,0.9375).
|
||||
** EVIDENCE-OF: R-53436-40973 The likely(X) function is equivalent to
|
||||
** likelihood(X,0.9375). */
|
||||
/* TUNING: unlikely() probability is 0.0625. likely() is 0.9375 */
|
||||
pExpr->iTable = pDef->zName[0]=='u' ? 62 : 938;
|
||||
}
|
||||
|
|
|
@ -732,7 +732,7 @@ static void selectInnerLoop(
|
|||
sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ);
|
||||
sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
|
||||
}
|
||||
assert( sqlite3VdbeCurrentAddr(v)==iJump );
|
||||
assert( sqlite3VdbeCurrentAddr(v)==iJump || pParse->db->mallocFailed );
|
||||
sqlite3VdbeAddOp3(v, OP_Copy, regResult, regPrev, nResultCol-1);
|
||||
break;
|
||||
}
|
||||
|
|
10
src/shell.c
10
src/shell.c
|
@ -1694,7 +1694,6 @@ static void writefileFunc(
|
|||
){
|
||||
FILE *out;
|
||||
const char *z;
|
||||
int n;
|
||||
sqlite3_int64 rc;
|
||||
const char *zFile;
|
||||
|
||||
|
@ -1704,11 +1703,9 @@ static void writefileFunc(
|
|||
if( out==0 ) return;
|
||||
z = (const char*)sqlite3_value_blob(argv[1]);
|
||||
if( z==0 ){
|
||||
n = 0;
|
||||
rc = 0;
|
||||
}else{
|
||||
n = sqlite3_value_bytes(argv[1]);
|
||||
rc = fwrite(z, 1, n, out);
|
||||
rc = fwrite(z, 1, sqlite3_value_bytes(argv[1]), out);
|
||||
}
|
||||
fclose(out);
|
||||
sqlite3_result_int64(context, rc);
|
||||
|
@ -3126,7 +3123,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
|||
&& (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
|
||||
){
|
||||
char *zCmd;
|
||||
int i;
|
||||
int i, x;
|
||||
if( nArg<2 ){
|
||||
fprintf(stderr, "Usage: .system COMMAND\n");
|
||||
rc = 1;
|
||||
|
@ -3137,8 +3134,9 @@ static int do_meta_command(char *zLine, struct callback_data *p){
|
|||
zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
|
||||
zCmd, azArg[i]);
|
||||
}
|
||||
(void)system(zCmd);
|
||||
x = system(zCmd);
|
||||
sqlite3_free(zCmd);
|
||||
if( x ) fprintf(stderr, "System command returns %d\n", x);
|
||||
}else
|
||||
|
||||
if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
|
||||
|
|
|
@ -264,7 +264,7 @@ typedef sqlite_uint64 sqlite3_uint64;
|
|||
**
|
||||
** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors
|
||||
** for the [sqlite3] object.
|
||||
** ^Calls to sqlite3_close() and sqlite3_close_v2() return SQLITE_OK if
|
||||
** ^Calls to sqlite3_close() and sqlite3_close_v2() return [SQLITE_OK] if
|
||||
** the [sqlite3] object is successfully destroyed and all associated
|
||||
** resources are deallocated.
|
||||
**
|
||||
|
@ -272,7 +272,7 @@ typedef sqlite_uint64 sqlite3_uint64;
|
|||
** statements or unfinished sqlite3_backup objects then sqlite3_close()
|
||||
** will leave the database connection open and return [SQLITE_BUSY].
|
||||
** ^If sqlite3_close_v2() is called with unfinalized prepared statements
|
||||
** and unfinished sqlite3_backups, then the database connection becomes
|
||||
** and/or unfinished sqlite3_backups, then the database connection becomes
|
||||
** an unusable "zombie" which will automatically be deallocated when the
|
||||
** last prepared statement is finalized or the last sqlite3_backup is
|
||||
** finished. The sqlite3_close_v2() interface is intended for use with
|
||||
|
@ -285,7 +285,7 @@ typedef sqlite_uint64 sqlite3_uint64;
|
|||
** with the [sqlite3] object prior to attempting to close the object. ^If
|
||||
** sqlite3_close_v2() is called on a [database connection] that still has
|
||||
** outstanding [prepared statements], [BLOB handles], and/or
|
||||
** [sqlite3_backup] objects then it returns SQLITE_OK but the deallocation
|
||||
** [sqlite3_backup] objects then it returns [SQLITE_OK] and the deallocation
|
||||
** of resources is deferred until all [prepared statements], [BLOB handles],
|
||||
** and [sqlite3_backup] objects are also destroyed.
|
||||
**
|
||||
|
@ -381,16 +381,14 @@ int sqlite3_exec(
|
|||
|
||||
/*
|
||||
** CAPI3REF: Result Codes
|
||||
** KEYWORDS: SQLITE_OK {error code} {error codes}
|
||||
** KEYWORDS: {result code} {result codes}
|
||||
** KEYWORDS: {result code definitions}
|
||||
**
|
||||
** Many SQLite functions return an integer result code from the set shown
|
||||
** here in order to indicate success or failure.
|
||||
**
|
||||
** New error codes may be added in future versions of SQLite.
|
||||
**
|
||||
** See also: [SQLITE_IOERR_READ | extended result codes],
|
||||
** [sqlite3_vtab_on_conflict()] [SQLITE_ROLLBACK | result codes].
|
||||
** See also: [extended result code definitions]
|
||||
*/
|
||||
#define SQLITE_OK 0 /* Successful result */
|
||||
/* beginning-of-error-codes */
|
||||
|
@ -428,26 +426,19 @@ int sqlite3_exec(
|
|||
|
||||
/*
|
||||
** CAPI3REF: Extended Result Codes
|
||||
** KEYWORDS: {extended error code} {extended error codes}
|
||||
** KEYWORDS: {extended result code} {extended result codes}
|
||||
** KEYWORDS: {extended result code definitions}
|
||||
**
|
||||
** In its default configuration, SQLite API routines return one of 26 integer
|
||||
** [SQLITE_OK | result codes]. However, experience has shown that many of
|
||||
** In its default configuration, SQLite API routines return one of 30 integer
|
||||
** [result codes]. However, experience has shown that many of
|
||||
** these result codes are too coarse-grained. They do not provide as
|
||||
** much information about problems as programmers might like. In an effort to
|
||||
** address this, newer versions of SQLite (version 3.3.8 and later) include
|
||||
** support for additional result codes that provide more detailed information
|
||||
** about errors. The extended result codes are enabled or disabled
|
||||
** about errors. These [extended result codes] are enabled or disabled
|
||||
** on a per database connection basis using the
|
||||
** [sqlite3_extended_result_codes()] API.
|
||||
**
|
||||
** Some of the available extended result codes are listed here.
|
||||
** One may expect the number of extended result codes will increase
|
||||
** over time. Software that uses extended result codes should expect
|
||||
** to see new result codes in future releases of SQLite.
|
||||
**
|
||||
** The SQLITE_OK result code will never be extended. It will always
|
||||
** be exactly zero.
|
||||
** [sqlite3_extended_result_codes()] API. Or, the extended code for
|
||||
** the most recent error can be obtained using
|
||||
** [sqlite3_extended_errcode()].
|
||||
*/
|
||||
#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8))
|
||||
#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8))
|
||||
|
@ -680,7 +671,7 @@ struct sqlite3_file {
|
|||
** locking strategy (for example to use dot-file locks), to inquire
|
||||
** about the status of a lock, or to break stale locks. The SQLite
|
||||
** core reserves all opcodes less than 100 for its own use.
|
||||
** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available.
|
||||
** A [file control opcodes | list of opcodes] less than 100 is available.
|
||||
** Applications that define a custom xFileControl method should use opcodes
|
||||
** greater than 100 to avoid conflicts. VFS implementations should
|
||||
** return [SQLITE_NOTFOUND] for file control opcodes that they do not
|
||||
|
@ -753,6 +744,7 @@ struct sqlite3_io_methods {
|
|||
|
||||
/*
|
||||
** CAPI3REF: Standard File Control Opcodes
|
||||
** KEYWORDS: {file control opcodes} {file control opcode}
|
||||
**
|
||||
** These integer constants are opcodes for the xFileControl method
|
||||
** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
|
||||
|
@ -2051,7 +2043,7 @@ int sqlite3_complete16(const void *sql);
|
|||
** The sqlite3_busy_handler() interface is used to implement
|
||||
** [sqlite3_busy_timeout()] and [PRAGMA busy_timeout].
|
||||
**
|
||||
** ^If the busy callback is NULL, then [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]
|
||||
** ^If the busy callback is NULL, then [SQLITE_BUSY]
|
||||
** is returned immediately upon encountering the lock. ^If the busy callback
|
||||
** is not NULL, then the callback might be invoked with two arguments.
|
||||
**
|
||||
|
@ -2060,7 +2052,7 @@ int sqlite3_complete16(const void *sql);
|
|||
** the busy handler callback is the number of times that the busy handler has
|
||||
** been invoked for the same locking event. ^If the
|
||||
** busy callback returns 0, then no additional attempts are made to
|
||||
** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned
|
||||
** access the database and [SQLITE_BUSY] is returned
|
||||
** to the application.
|
||||
** ^If the callback returns non-zero, then another attempt
|
||||
** is made to access the database and the cycle repeats.
|
||||
|
@ -2068,7 +2060,7 @@ int sqlite3_complete16(const void *sql);
|
|||
** The presence of a busy handler does not guarantee that it will be invoked
|
||||
** when there is lock contention. ^If SQLite determines that invoking the busy
|
||||
** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY]
|
||||
** or [SQLITE_IOERR_BLOCKED] to the application instead of invoking the
|
||||
** to the application instead of invoking the
|
||||
** busy handler.
|
||||
** Consider a scenario where one process is holding a read lock that
|
||||
** it is trying to promote to a reserved lock and
|
||||
|
@ -2083,21 +2075,6 @@ int sqlite3_complete16(const void *sql);
|
|||
**
|
||||
** ^The default busy callback is NULL.
|
||||
**
|
||||
** ^The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED]
|
||||
** when SQLite is in the middle of a large transaction where all the
|
||||
** changes will not fit into the in-memory cache. SQLite will
|
||||
** already hold a RESERVED lock on the database file, but it needs
|
||||
** to promote this lock to EXCLUSIVE so that it can spill cache
|
||||
** pages into the database file without harm to concurrent
|
||||
** readers. ^If it is unable to promote the lock, then the in-memory
|
||||
** cache will be left in an inconsistent state and so the error
|
||||
** code is promoted from the relatively benign [SQLITE_BUSY] to
|
||||
** the more severe [SQLITE_IOERR_BLOCKED]. ^This error code promotion
|
||||
** forces an automatic rollback of the changes. See the
|
||||
** <a href="/cvstrac/wiki?p=CorruptionFollowingBusyError">
|
||||
** CorruptionFollowingBusyError</a> wiki page for a discussion of why
|
||||
** this is important.
|
||||
**
|
||||
** ^(There can only be a single busy handler defined for each
|
||||
** [database connection]. Setting a new busy handler clears any
|
||||
** previously set handler.)^ ^Note that calling [sqlite3_busy_timeout()]
|
||||
|
@ -2122,7 +2099,7 @@ int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
|
|||
** will sleep multiple times until at least "ms" milliseconds of sleeping
|
||||
** have accumulated. ^After at least "ms" milliseconds of sleeping,
|
||||
** the handler returns 0 which causes [sqlite3_step()] to return
|
||||
** [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED].
|
||||
** [SQLITE_BUSY].
|
||||
**
|
||||
** ^Calling this routine with an argument less than or equal to zero
|
||||
** turns off all busy handlers.
|
||||
|
@ -2534,8 +2511,8 @@ int sqlite3_set_authorizer(
|
|||
** [sqlite3_set_authorizer | authorizer documentation] for additional
|
||||
** information.
|
||||
**
|
||||
** Note that SQLITE_IGNORE is also used as a [SQLITE_ROLLBACK | return code]
|
||||
** from the [sqlite3_vtab_on_conflict()] interface.
|
||||
** Note that SQLITE_IGNORE is also used as a [conflict resolution mode]
|
||||
** returned from the [sqlite3_vtab_on_conflict()] interface.
|
||||
*/
|
||||
#define SQLITE_DENY 1 /* Abort the SQL statement with an error */
|
||||
#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */
|
||||
|
@ -7376,6 +7353,7 @@ int sqlite3_vtab_on_conflict(sqlite3 *);
|
|||
|
||||
/*
|
||||
** CAPI3REF: Conflict resolution modes
|
||||
** KEYWORDS: {conflict resolution mode}
|
||||
**
|
||||
** These constants are returned by [sqlite3_vtab_on_conflict()] to
|
||||
** inform a [virtual table] implementation what the [ON CONFLICT] mode
|
||||
|
|
|
@ -35,6 +35,14 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
|||
#pragma code_page(1252)
|
||||
#endif /* defined(_WIN32) */
|
||||
|
||||
/*
|
||||
* Icon
|
||||
*/
|
||||
|
||||
#define IDI_SQLITE 101
|
||||
|
||||
IDI_SQLITE ICON "..\\art\\sqlite370.ico"
|
||||
|
||||
/*
|
||||
* Version
|
||||
*/
|
||||
|
|
|
@ -3266,7 +3266,7 @@ case OP_ReopenIdx: {
|
|||
assert( pOp->p5==0 );
|
||||
assert( pOp->p4type==P4_KEYINFO );
|
||||
pCur = p->apCsr[pOp->p1];
|
||||
if( pCur && pCur->pgnoRoot==pOp->p2 ){
|
||||
if( pCur && pCur->pgnoRoot==(u32)pOp->p2 ){
|
||||
assert( pCur->iDb==pOp->p3 ); /* Guaranteed by the code generator */
|
||||
break;
|
||||
}
|
||||
|
@ -3553,7 +3553,7 @@ case OP_Close: {
|
|||
** the key and P2 is not zero, then jump to P2.
|
||||
**
|
||||
** This opcode leaves the cursor configured to move in forward order,
|
||||
** from the begining toward the end. In other words, the cursor is
|
||||
** from the beginning toward the end. In other words, the cursor is
|
||||
** configured to use Next, not Prev.
|
||||
**
|
||||
** See also: Found, NotFound, SeekLt, SeekGe, SeekLe
|
||||
|
@ -4571,7 +4571,7 @@ case OP_Sort: { /* jump */
|
|||
** to the following instruction.
|
||||
**
|
||||
** This opcode leaves the cursor configured to move in forward order,
|
||||
** from the begining toward the end. In other words, the cursor is
|
||||
** from the beginning toward the end. In other words, the cursor is
|
||||
** configured to use Next, not Prev.
|
||||
*/
|
||||
case OP_Rewind: { /* jump */
|
||||
|
|
|
@ -84,18 +84,35 @@ void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
|
|||
}
|
||||
|
||||
/*
|
||||
** Resize the Vdbe.aOp array so that it is at least one op larger than
|
||||
** it was.
|
||||
** Resize the Vdbe.aOp array so that it is at least nOp elements larger
|
||||
** than its current size. nOp is guaranteed to be less than or equal
|
||||
** to 1024/sizeof(Op).
|
||||
**
|
||||
** If an out-of-memory error occurs while resizing the array, return
|
||||
** SQLITE_NOMEM. In this case Vdbe.aOp and Vdbe.nOpAlloc remain
|
||||
** SQLITE_NOMEM. In this case Vdbe.aOp and Parse.nOpAlloc remain
|
||||
** unchanged (this is so that any opcodes already allocated can be
|
||||
** correctly deallocated along with the rest of the Vdbe).
|
||||
*/
|
||||
static int growOpArray(Vdbe *v){
|
||||
static int growOpArray(Vdbe *v, int nOp){
|
||||
VdbeOp *pNew;
|
||||
Parse *p = v->pParse;
|
||||
|
||||
/* The SQLITE_TEST_REALLOC_STRESS compile-time option is designed to force
|
||||
** more frequent reallocs and hence provide more opportunities for
|
||||
** simulated OOM faults. SQLITE_TEST_REALLOC_STRESS is generally used
|
||||
** during testing only. With SQLITE_TEST_REALLOC_STRESS grow the op array
|
||||
** by the minimum* amount required until the size reaches 512. Normal
|
||||
** operation (without SQLITE_TEST_REALLOC_STRESS) is to double the current
|
||||
** size of the op array or add 1KB of space, whichever is smaller. */
|
||||
#ifdef SQLITE_TEST_REALLOC_STRESS
|
||||
int nNew = (p->nOpAlloc>=512 ? p->nOpAlloc*2 : p->nOpAlloc+nOp);
|
||||
#else
|
||||
int nNew = (p->nOpAlloc ? p->nOpAlloc*2 : (int)(1024/sizeof(Op)));
|
||||
UNUSED_PARAMETER(nOp);
|
||||
#endif
|
||||
|
||||
assert( nOp<=(1024/sizeof(Op)) );
|
||||
assert( nNew>=(p->nOpAlloc+nOp) );
|
||||
pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op));
|
||||
if( pNew ){
|
||||
p->nOpAlloc = sqlite3DbMallocSize(p->db, pNew)/sizeof(Op);
|
||||
|
@ -139,7 +156,7 @@ int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
|
|||
assert( p->magic==VDBE_MAGIC_INIT );
|
||||
assert( op>0 && op<0xff );
|
||||
if( p->pParse->nOpAlloc<=i ){
|
||||
if( growOpArray(p) ){
|
||||
if( growOpArray(p, 1) ){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -541,7 +558,7 @@ VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg){
|
|||
int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp, int iLineno){
|
||||
int addr;
|
||||
assert( p->magic==VDBE_MAGIC_INIT );
|
||||
if( p->nOp + nOp > p->pParse->nOpAlloc && growOpArray(p) ){
|
||||
if( p->nOp + nOp > p->pParse->nOpAlloc && growOpArray(p, nOp) ){
|
||||
return 0;
|
||||
}
|
||||
addr = p->nOp;
|
||||
|
@ -726,7 +743,7 @@ void sqlite3VdbeLinkSubProgram(Vdbe *pVdbe, SubProgram *p){
|
|||
** Change the opcode at addr into OP_Noop
|
||||
*/
|
||||
void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
|
||||
if( p->aOp ){
|
||||
if( addr<p->nOp ){
|
||||
VdbeOp *pOp = &p->aOp[addr];
|
||||
sqlite3 *db = p->db;
|
||||
freeP4(db, pOp->p4type, pOp->p4.p);
|
||||
|
@ -2301,7 +2318,6 @@ int sqlite3VdbeHalt(Vdbe *p){
|
|||
|
||||
/* Check for one of the special errors */
|
||||
mrc = p->rc & 0xff;
|
||||
assert( p->rc!=SQLITE_IOERR_BLOCKED ); /* This error no longer exists */
|
||||
isSpecialError = mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR
|
||||
|| mrc==SQLITE_INTERRUPT || mrc==SQLITE_FULL;
|
||||
if( isSpecialError ){
|
||||
|
|
197
src/where.c
197
src/where.c
|
@ -5400,6 +5400,45 @@ static const char *wherePathName(WherePath *pPath, int nLoop, WhereLoop *pLast){
|
|||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Return the cost of sorting nRow rows, assuming that the keys have
|
||||
** nOrderby columns and that the first nSorted columns are already in
|
||||
** order.
|
||||
*/
|
||||
static LogEst whereSortingCost(
|
||||
WhereInfo *pWInfo,
|
||||
LogEst nRow,
|
||||
int nOrderBy,
|
||||
int nSorted
|
||||
){
|
||||
/* TUNING: Estimated cost of a full external sort, where N is
|
||||
** the number of rows to sort is:
|
||||
**
|
||||
** cost = (3.0 * N * log(N)).
|
||||
**
|
||||
** Or, if the order-by clause has X terms but only the last Y
|
||||
** terms are out of order, then block-sorting will reduce the
|
||||
** sorting cost to:
|
||||
**
|
||||
** cost = (3.0 * N * log(N)) * (Y/X)
|
||||
**
|
||||
** The (Y/X) term is implemented using stack variable rScale
|
||||
** below. */
|
||||
LogEst rScale, rSortCost;
|
||||
assert( nOrderBy>0 && 66==sqlite3LogEst(100) );
|
||||
rScale = sqlite3LogEst((nOrderBy-nSorted)*100/nOrderBy) - 66;
|
||||
rSortCost = nRow + estLog(nRow) + rScale + 16;
|
||||
|
||||
/* TUNING: The cost of implementing DISTINCT using a B-TREE is
|
||||
** similar but with a larger constant of proportionality.
|
||||
** Multiply by an additional factor of 3.0. */
|
||||
if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){
|
||||
rSortCost += 16;
|
||||
}
|
||||
|
||||
return rSortCost;
|
||||
}
|
||||
|
||||
/*
|
||||
** Given the list of WhereLoop objects at pWInfo->pLoops, this routine
|
||||
** attempts to find the lowest cost path that visits each WhereLoop
|
||||
|
@ -5421,9 +5460,8 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
|||
int ii, jj; /* Loop counters */
|
||||
int mxI = 0; /* Index of next entry to replace */
|
||||
int nOrderBy; /* Number of ORDER BY clause terms */
|
||||
LogEst rCost; /* Cost of a path */
|
||||
LogEst nOut; /* Number of outputs */
|
||||
LogEst mxCost = 0; /* Maximum cost of a set of paths */
|
||||
LogEst mxUnsorted = 0; /* Maximum unsorted cost of a set of path */
|
||||
int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */
|
||||
WherePath *aFrom; /* All nFrom paths at the previous level */
|
||||
WherePath *aTo; /* The nTo best paths at the current level */
|
||||
|
@ -5431,7 +5469,9 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
|||
WherePath *pTo; /* An element of aTo[] that we are working on */
|
||||
WhereLoop *pWLoop; /* One of the WhereLoop objects */
|
||||
WhereLoop **pX; /* Used to divy up the pSpace memory */
|
||||
LogEst *aSortCost = 0; /* Sorting and partial sorting costs */
|
||||
char *pSpace; /* Temporary memory used by this routine */
|
||||
int nSpace; /* Bytes of space allocated at pSpace */
|
||||
|
||||
pParse = pWInfo->pParse;
|
||||
db = pParse->db;
|
||||
|
@ -5441,11 +5481,23 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
|||
** For joins of 3 or more tables, track the 10 best paths */
|
||||
mxChoice = (nLoop<=1) ? 1 : (nLoop==2 ? 5 : 10);
|
||||
assert( nLoop<=pWInfo->pTabList->nSrc );
|
||||
WHERETRACE(0x002, ("---- begin solver\n"));
|
||||
WHERETRACE(0x002, ("---- begin solver. (nRowEst=%d)\n", nRowEst));
|
||||
|
||||
/* Allocate and initialize space for aTo and aFrom */
|
||||
ii = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2;
|
||||
pSpace = sqlite3DbMallocRaw(db, ii);
|
||||
/* If nRowEst is zero and there is an ORDER BY clause, ignore it. In this
|
||||
** case the purpose of this call is to estimate the number of rows returned
|
||||
** by the overall query. Once this estimate has been obtained, the caller
|
||||
** will invoke this function a second time, passing the estimate as the
|
||||
** nRowEst parameter. */
|
||||
if( pWInfo->pOrderBy==0 || nRowEst==0 ){
|
||||
nOrderBy = 0;
|
||||
}else{
|
||||
nOrderBy = pWInfo->pOrderBy->nExpr;
|
||||
}
|
||||
|
||||
/* Allocate and initialize space for aTo, aFrom and aSortCost[] */
|
||||
nSpace = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2;
|
||||
nSpace += sizeof(LogEst) * nOrderBy;
|
||||
pSpace = sqlite3DbMallocRaw(db, nSpace);
|
||||
if( pSpace==0 ) return SQLITE_NOMEM;
|
||||
aTo = (WherePath*)pSpace;
|
||||
aFrom = aTo+mxChoice;
|
||||
|
@ -5454,6 +5506,18 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
|||
for(ii=mxChoice*2, pFrom=aTo; ii>0; ii--, pFrom++, pX += nLoop){
|
||||
pFrom->aLoop = pX;
|
||||
}
|
||||
if( nOrderBy ){
|
||||
/* If there is an ORDER BY clause and it is not being ignored, set up
|
||||
** space for the aSortCost[] array. Each element of the aSortCost array
|
||||
** is either zero - meaning it has not yet been initialized - or the
|
||||
** cost of sorting nRowEst rows of data where the first X terms of
|
||||
** the ORDER BY clause are already in order, where X is the array
|
||||
** index. */
|
||||
aSortCost = (LogEst*)pX;
|
||||
memset(aSortCost, 0, sizeof(LogEst) * nOrderBy);
|
||||
}
|
||||
assert( aSortCost==0 || &pSpace[nSpace]==(char*)&aSortCost[nOrderBy] );
|
||||
assert( aSortCost!=0 || &pSpace[nSpace]==(char*)pX );
|
||||
|
||||
/* Seed the search with a single WherePath containing zero WhereLoops.
|
||||
**
|
||||
|
@ -5462,15 +5526,15 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
|||
** rows, then do not use the automatic index. */
|
||||
aFrom[0].nRow = MIN(pParse->nQueryLoop, 46); assert( 46==sqlite3LogEst(25) );
|
||||
nFrom = 1;
|
||||
|
||||
/* Precompute the cost of sorting the final result set, if the caller
|
||||
** to sqlite3WhereBegin() was concerned about sorting */
|
||||
if( pWInfo->pOrderBy==0 || nRowEst==0 ){
|
||||
aFrom[0].isOrdered = 0;
|
||||
nOrderBy = 0;
|
||||
}else{
|
||||
aFrom[0].isOrdered = nLoop>0 ? -1 : 1;
|
||||
nOrderBy = pWInfo->pOrderBy->nExpr;
|
||||
assert( aFrom[0].isOrdered==0 );
|
||||
if( nOrderBy ){
|
||||
/* If nLoop is zero, then there are no FROM terms in the query. Since
|
||||
** in this case the query may return a maximum of one row, the results
|
||||
** are already in the requested order. Set isOrdered to nOrderBy to
|
||||
** indicate this. Or, if nLoop is greater than zero, set isOrdered to
|
||||
** -1, indicating that the result set may or may not be ordered,
|
||||
** depending on the loops added to the current plan. */
|
||||
aFrom[0].isOrdered = nLoop>0 ? -1 : nOrderBy;
|
||||
}
|
||||
|
||||
/* Compute successively longer WherePaths using the previous generation
|
||||
|
@ -5480,66 +5544,71 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
|||
nTo = 0;
|
||||
for(ii=0, pFrom=aFrom; ii<nFrom; ii++, pFrom++){
|
||||
for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
|
||||
Bitmask maskNew;
|
||||
Bitmask revMask = 0;
|
||||
i8 isOrdered = pFrom->isOrdered;
|
||||
LogEst nOut; /* Rows visited by (pFrom+pWLoop) */
|
||||
LogEst rCost; /* Cost of path (pFrom+pWLoop) */
|
||||
LogEst rUnsorted; /* Unsorted cost of (pFrom+pWLoop) */
|
||||
i8 isOrdered = pFrom->isOrdered; /* isOrdered for (pFrom+pWLoop) */
|
||||
Bitmask maskNew; /* Mask of src visited by (..) */
|
||||
Bitmask revMask = 0; /* Mask of rev-order loops for (..) */
|
||||
|
||||
if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue;
|
||||
if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue;
|
||||
/* At this point, pWLoop is a candidate to be the next loop.
|
||||
** Compute its cost */
|
||||
rCost = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
|
||||
rCost = sqlite3LogEstAdd(rCost, pFrom->rCost);
|
||||
rUnsorted = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
|
||||
rUnsorted = sqlite3LogEstAdd(rUnsorted, pFrom->rUnsorted);
|
||||
nOut = pFrom->nRow + pWLoop->nOut;
|
||||
maskNew = pFrom->maskLoop | pWLoop->maskSelf;
|
||||
if( isOrdered<0 ){
|
||||
isOrdered = wherePathSatisfiesOrderBy(pWInfo,
|
||||
pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags,
|
||||
iLoop, pWLoop, &revMask);
|
||||
if( isOrdered>=0 && isOrdered<nOrderBy ){
|
||||
/* TUNING: Estimated cost of a full external sort, where N is
|
||||
** the number of rows to sort is:
|
||||
**
|
||||
** cost = (3.0 * N * log(N)).
|
||||
**
|
||||
** Or, if the order-by clause has X terms but only the last Y
|
||||
** terms are out of order, then block-sorting will reduce the
|
||||
** sorting cost to:
|
||||
**
|
||||
** cost = (3.0 * N * log(N)) * (Y/X)
|
||||
**
|
||||
** The (Y/X) term is implemented using stack variable rScale
|
||||
** below. */
|
||||
LogEst rScale, rSortCost;
|
||||
assert( nOrderBy>0 && 66==sqlite3LogEst(100) );
|
||||
rScale = sqlite3LogEst((nOrderBy-isOrdered)*100/nOrderBy) - 66;
|
||||
rSortCost = nRowEst + estLog(nRowEst) + rScale + 16;
|
||||
|
||||
/* TUNING: The cost of implementing DISTINCT using a B-TREE is
|
||||
** similar but with a larger constant of proportionality.
|
||||
** Multiply by an additional factor of 3.0. */
|
||||
if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){
|
||||
rSortCost += 16;
|
||||
}
|
||||
WHERETRACE(0x002,
|
||||
("---- sort cost=%-3d (%d/%d) increases cost %3d to %-3d\n",
|
||||
rSortCost, (nOrderBy-isOrdered), nOrderBy, rCost,
|
||||
sqlite3LogEstAdd(rCost,rSortCost)));
|
||||
rCost = sqlite3LogEstAdd(rCost, rSortCost);
|
||||
}
|
||||
}else{
|
||||
revMask = pFrom->revLoop;
|
||||
}
|
||||
/* Check to see if pWLoop should be added to the mxChoice best so far */
|
||||
if( isOrdered>=0 && isOrdered<nOrderBy ){
|
||||
if( aSortCost[isOrdered]==0 ){
|
||||
aSortCost[isOrdered] = whereSortingCost(
|
||||
pWInfo, nRowEst, nOrderBy, isOrdered
|
||||
);
|
||||
}
|
||||
rCost = sqlite3LogEstAdd(rUnsorted, aSortCost[isOrdered]);
|
||||
|
||||
WHERETRACE(0x002,
|
||||
("---- sort cost=%-3d (%d/%d) increases cost %3d to %-3d\n",
|
||||
aSortCost[isOrdered], (nOrderBy-isOrdered), nOrderBy,
|
||||
rUnsorted, rCost));
|
||||
}else{
|
||||
rCost = rUnsorted;
|
||||
}
|
||||
|
||||
/* Check to see if pWLoop should be added to the set of
|
||||
** mxChoice best-so-far paths.
|
||||
**
|
||||
** First look for an existing path among best-so-far paths
|
||||
** that covers the same set of loops and has the same isOrdered
|
||||
** setting as the current path candidate.
|
||||
**
|
||||
** The term "((pTo->isOrdered^isOrdered)&0x80)==0" is equivalent
|
||||
** to (pTo->isOrdered==(-1))==(isOrdered==(-1))" for the range
|
||||
** of legal values for isOrdered, -1..64.
|
||||
*/
|
||||
for(jj=0, pTo=aTo; jj<nTo; jj++, pTo++){
|
||||
if( pTo->maskLoop==maskNew
|
||||
&& ((pTo->isOrdered^isOrdered)&80)==0
|
||||
&& ((pTo->isOrdered^isOrdered)&0x80)==0
|
||||
){
|
||||
testcase( jj==nTo-1 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( jj>=nTo ){
|
||||
if( nTo>=mxChoice && rCost>=mxCost ){
|
||||
/* None of the existing best-so-far paths match the candidate. */
|
||||
if( nTo>=mxChoice
|
||||
&& (rCost>mxCost || (rCost==mxCost && rUnsorted>=mxUnsorted))
|
||||
){
|
||||
/* The current candidate is no better than any of the mxChoice
|
||||
** paths currently in the best-so-far buffer. So discard
|
||||
** this candidate as not viable. */
|
||||
#ifdef WHERETRACE_ENABLED /* 0x4 */
|
||||
if( sqlite3WhereTrace&0x4 ){
|
||||
sqlite3DebugPrintf("Skip %s cost=%-3d,%3d order=%c\n",
|
||||
|
@ -5549,7 +5618,8 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
|||
#endif
|
||||
continue;
|
||||
}
|
||||
/* Add a new Path to the aTo[] set */
|
||||
/* If we reach this points it means that the new candidate path
|
||||
** needs to be added to the set of best-so-far paths. */
|
||||
if( nTo<mxChoice ){
|
||||
/* Increase the size of the aTo set by one */
|
||||
jj = nTo++;
|
||||
|
@ -5566,7 +5636,11 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
|||
}
|
||||
#endif
|
||||
}else{
|
||||
if( pTo->rCost<=rCost ){
|
||||
/* Control reaches here if best-so-far path pTo=aTo[jj] covers the
|
||||
** same set of loops and has the sam isOrdered setting as the
|
||||
** candidate path. Check to see if the candidate should replace
|
||||
** pTo or if the candidate should be skipped */
|
||||
if( pTo->rCost<rCost || (pTo->rCost==rCost && pTo->nRow<=nOut) ){
|
||||
#ifdef WHERETRACE_ENABLED /* 0x4 */
|
||||
if( sqlite3WhereTrace&0x4 ){
|
||||
sqlite3DebugPrintf(
|
||||
|
@ -5578,11 +5652,13 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
|||
pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
|
||||
}
|
||||
#endif
|
||||
/* Discard the candidate path from further consideration */
|
||||
testcase( pTo->rCost==rCost );
|
||||
continue;
|
||||
}
|
||||
testcase( pTo->rCost==rCost+1 );
|
||||
/* A new and better score for a previously created equivalent path */
|
||||
/* Control reaches here if the candidate path is better than the
|
||||
** pTo path. Replace pTo with the candidate. */
|
||||
#ifdef WHERETRACE_ENABLED /* 0x4 */
|
||||
if( sqlite3WhereTrace&0x4 ){
|
||||
sqlite3DebugPrintf(
|
||||
|
@ -5600,15 +5676,20 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
|||
pTo->revLoop = revMask;
|
||||
pTo->nRow = nOut;
|
||||
pTo->rCost = rCost;
|
||||
pTo->rUnsorted = rUnsorted;
|
||||
pTo->isOrdered = isOrdered;
|
||||
memcpy(pTo->aLoop, pFrom->aLoop, sizeof(WhereLoop*)*iLoop);
|
||||
pTo->aLoop[iLoop] = pWLoop;
|
||||
if( nTo>=mxChoice ){
|
||||
mxI = 0;
|
||||
mxCost = aTo[0].rCost;
|
||||
mxUnsorted = aTo[0].nRow;
|
||||
for(jj=1, pTo=&aTo[1]; jj<mxChoice; jj++, pTo++){
|
||||
if( pTo->rCost>mxCost ){
|
||||
if( pTo->rCost>mxCost
|
||||
|| (pTo->rCost==mxCost && pTo->rUnsorted>mxUnsorted)
|
||||
){
|
||||
mxCost = pTo->rCost;
|
||||
mxUnsorted = pTo->rUnsorted;
|
||||
mxI = jj;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -183,6 +183,7 @@ struct WherePath {
|
|||
Bitmask revLoop; /* aLoop[]s that should be reversed for ORDER BY */
|
||||
LogEst nRow; /* Estimated number of rows generated by this path */
|
||||
LogEst rCost; /* Total cost of this path */
|
||||
LogEst rUnsorted; /* Total cost of this path ignoring sorting costs */
|
||||
i8 isOrdered; /* No. of ORDER BY terms satisfied. -1 for unknown */
|
||||
WhereLoop **aLoop; /* Array of WhereLoop objects implementing this path */
|
||||
};
|
||||
|
|
|
@ -1175,9 +1175,9 @@ do_createtable_tests 4.2 -repair {
|
|||
# EVIDENCE-OF: R-59124-61339 Each row in a table with a primary key must
|
||||
# have a unique combination of values in its primary key columns.
|
||||
#
|
||||
# EVIDENCE-OF: R-39102-06737 If an INSERT or UPDATE statement attempts
|
||||
# to modify the table content so that two or more rows feature identical
|
||||
# primary key values, it is a constraint violation.
|
||||
# EVIDENCE-OF: R-06471-16287 If an INSERT or UPDATE statement attempts
|
||||
# to modify the table content so that two or more rows have identical
|
||||
# primary key values, that is a constraint violation.
|
||||
#
|
||||
drop_all_tables
|
||||
do_execsql_test 4.3.0 {
|
||||
|
|
|
@ -450,7 +450,7 @@ do_execsql_test e_expr-10.3.4 { SELECT typeof('isn''t') } {text}
|
|||
# containing hexadecimal data and preceded by a single "x" or "X"
|
||||
# character.
|
||||
#
|
||||
# EVIDENCE-OF: R-39344-59787 For example: X'53514C697465'
|
||||
# EVIDENCE-OF: R-19836-11244 Example: X'53514C697465'
|
||||
#
|
||||
do_execsql_test e_expr-10.4.1 { SELECT typeof(X'0123456789ABCDEF') } blob
|
||||
do_execsql_test e_expr-10.4.2 { SELECT typeof(x'0123456789ABCDEF') } blob
|
||||
|
@ -1596,6 +1596,13 @@ do_expr_test e_expr-30.4.1 { CAST('' AS INTEGER) } integer 0
|
|||
do_expr_test e_expr-30.4.2 { CAST('not a number' AS INTEGER) } integer 0
|
||||
do_expr_test e_expr-30.4.3 { CAST('XXI' AS INTEGER) } integer 0
|
||||
|
||||
# EVIDENCE-OF: R-08980-53124 The CAST operator understands decimal
|
||||
# integers only — conversion of hexadecimal integers stops at
|
||||
# the "x" in the "0x" prefix of the hexadecimal integer string and thus
|
||||
# result of the CAST is always zero.
|
||||
do_expr_test e_expr-30.5.1 { CAST('0x1234' AS INTEGER) } integer 0
|
||||
do_expr_test e_expr-30.5.2 { CAST('0X1234' AS INTEGER) } integer 0
|
||||
|
||||
# EVIDENCE-OF: R-02752-50091 A cast of a REAL value into an INTEGER
|
||||
# results in the integer between the REAL value and zero that is closest
|
||||
# to the REAL value.
|
||||
|
|
|
@ -153,28 +153,38 @@ do_test func3-5.39 {
|
|||
db eval {EXPLAIN SELECT unlikely(min(1.0+'2.0',4*11))}
|
||||
} [db eval {EXPLAIN SELECT min(1.0+'2.0',4*11)}]
|
||||
|
||||
do_execsql_test func3-5.40 {
|
||||
|
||||
# EVIDENCE-OF: R-23735-03107 The likely(X) function returns the argument
|
||||
# X unchanged.
|
||||
#
|
||||
do_execsql_test func3-5.50 {
|
||||
SELECT likely(9223372036854775807);
|
||||
} {9223372036854775807}
|
||||
do_execsql_test func3-5.41 {
|
||||
do_execsql_test func3-5.51 {
|
||||
SELECT likely(-9223372036854775808);
|
||||
} {-9223372036854775808}
|
||||
do_execsql_test func3-5.42 {
|
||||
do_execsql_test func3-5.52 {
|
||||
SELECT likely(14.125);
|
||||
} {14.125}
|
||||
do_execsql_test func3-5.43 {
|
||||
do_execsql_test func3-5.53 {
|
||||
SELECT likely(NULL);
|
||||
} {{}}
|
||||
do_execsql_test func3-5.44 {
|
||||
do_execsql_test func3-5.54 {
|
||||
SELECT likely('test-string');
|
||||
} {test-string}
|
||||
do_execsql_test func3-5.45 {
|
||||
do_execsql_test func3-5.55 {
|
||||
SELECT quote(likely(x'010203000405'));
|
||||
} {X'010203000405'}
|
||||
do_test func3-5.49 {
|
||||
|
||||
# EVIDENCE-OF: R-43464-09689 The likely(X) function is a no-op that the
|
||||
# code generator optimizes away so that it consumes no CPU cycles at
|
||||
# run-time (that is, during calls to sqlite3_step()).
|
||||
#
|
||||
do_test func3-5.59 {
|
||||
db eval {EXPLAIN SELECT likely(min(1.0+'2.0',4*11))}
|
||||
} [db eval {EXPLAIN SELECT min(1.0+'2.0',4*11)}]
|
||||
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set ::testprefix incrblob_err
|
||||
|
||||
ifcapable {!incrblob || !memdebug || !tclvar} {
|
||||
finish_test
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set ::testprefix malloc
|
||||
|
||||
|
||||
# Only run these tests if memory debugging is turned on.
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
# 2014 August 12
|
||||
#
|
||||
# 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 test script is designed to show that the assert() fix at
|
||||
# [f1cb48f412] really is required.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/malloc_common.tcl
|
||||
set testprefix mallocL
|
||||
|
||||
do_test 1.0 {
|
||||
for {set i 0} {$i < 40} {incr i} {
|
||||
lappend cols "c$i"
|
||||
lappend vals $i
|
||||
}
|
||||
|
||||
execsql "CREATE TABLE t1([join $cols ,])"
|
||||
execsql "CREATE INDEX i1 ON t1([join $cols ,])"
|
||||
execsql "INSERT INTO t1 VALUES([join $vals ,])"
|
||||
} {}
|
||||
|
||||
for {set j 1} {$j < 40} {incr j} {
|
||||
set ::sql "SELECT DISTINCT [join [lrange $cols 0 $j] ,] FROM t1"
|
||||
do_faultsim_test 1.$j -faults oom* -body {
|
||||
execsql $::sql
|
||||
} -test {
|
||||
faultsim_test_result [list 0 [lrange $::vals 0 $::j]]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
|
@ -409,6 +409,7 @@ proc do_malloc_test {tn args} {
|
|||
|
||||
if {[string is integer $tn]} {
|
||||
set tn malloc-$tn
|
||||
catch { set tn $::testprefix-$tn }
|
||||
}
|
||||
if {[info exists ::mallocopts(-start)]} {
|
||||
set start $::mallocopts(-start)
|
||||
|
|
|
@ -176,6 +176,12 @@ array set ::Configs {
|
|||
-DSQLITE_DISABLE_FTS4_DEFERRED
|
||||
-DSQLITE_ENABLE_RTREE
|
||||
}
|
||||
|
||||
"No-lookaside" {
|
||||
-DSQLITE_TEST_REALLOC_STRESS=1
|
||||
-DSQLITE_OMIT_LOOKASIDE=1
|
||||
-DHAVE_USLEEP=1
|
||||
}
|
||||
}
|
||||
|
||||
array set ::Platforms {
|
||||
|
@ -188,6 +194,7 @@ array set ::Platforms {
|
|||
"Extra-Robustness" test
|
||||
"Device-Two" test
|
||||
"Ftrapv" test
|
||||
"No-lookaside" test
|
||||
"Default" "threadtest test"
|
||||
"Device-One" fulltest
|
||||
}
|
||||
|
|
|
@ -781,7 +781,12 @@ do_test where9-6.8.2 {
|
|||
OR (b NOT NULL AND c NOT NULL AND d IS NULL)
|
||||
}
|
||||
} {1 {no query solution}}
|
||||
|
||||
set solution_possible 0
|
||||
ifcapable stat4||stat3 {
|
||||
if {[permutation] != "no_optimization"} { set solution_possible 1 }
|
||||
}
|
||||
if $solution_possible {
|
||||
# When STAT3 is enabled, the "b NOT NULL" terms get translated
|
||||
# into b>NULL, which can be satified by the index t1b. It is a very
|
||||
# expensive way to do the query, but it works, and so a solution is possible.
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# This file implements a single regression test for a complex
|
||||
# This file implements regression tests for a complex
|
||||
# query planning case.
|
||||
#
|
||||
|
||||
|
@ -328,4 +328,48 @@ do_execsql_test whereJ-1.4 {
|
|||
GROUP BY aid;
|
||||
} {/B-TREE/}
|
||||
|
||||
############################################################################
|
||||
# Ensure that the sorting cost does not swamp the loop costs and cause
|
||||
# distinctions between individual loop costs to get lost, and hence for
|
||||
# sub-optimal loops to be chosen.
|
||||
#
|
||||
do_execsql_test whereJ-2.1 {
|
||||
CREATE TABLE tab(
|
||||
id INTEGER PRIMARY KEY,
|
||||
minChild INTEGER REFERENCES t1,
|
||||
maxChild INTEGER REFERENCES t1,
|
||||
x INTEGER
|
||||
);
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT t4.x
|
||||
FROM tab AS t0, tab AS t1, tab AS t2, tab AS t3, tab AS t4
|
||||
WHERE t0.id=0
|
||||
AND t1.id BETWEEN t0.minChild AND t0.maxChild
|
||||
AND t2.id BETWEEN t1.minChild AND t1.maxChild
|
||||
AND t3.id BETWEEN t2.minChild AND t2.maxChild
|
||||
AND t4.id BETWEEN t3.minChild AND t3.maxChild
|
||||
ORDER BY t4.x;
|
||||
} {~/SCAN/}
|
||||
do_execsql_test whereJ-2.2 {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT t4.x
|
||||
FROM tab AS t0a, tab AS t0b,
|
||||
tab AS t1a, tab AS t1b,
|
||||
tab AS t2a, tab AS t2b,
|
||||
tab AS t3a, tab AS t3b,
|
||||
tab AS t4
|
||||
WHERE 1
|
||||
AND t0a.id=1
|
||||
AND t1a.id BETWEEN t0a.minChild AND t0a.maxChild
|
||||
AND t2a.id BETWEEN t1a.minChild AND t1a.maxChild
|
||||
AND t3a.id BETWEEN t2a.minChild AND t2a.maxChild
|
||||
AND t0b.id=2
|
||||
AND t1b.id BETWEEN t0b.minChild AND t0b.maxChild
|
||||
AND t2b.id BETWEEN t1b.minChild AND t1b.maxChild
|
||||
AND t3b.id BETWEEN t2b.minChild AND t2b.maxChild
|
||||
AND t4.id BETWEEN t3a.minChild AND t3b.maxChild
|
||||
ORDER BY t4.x;
|
||||
} {~/SCAN/}
|
||||
|
||||
|
||||
finish_test
|
||||
|
|
Loading…
Reference in New Issue