Compare commits
67 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f14c59bb11 | |||
| 39065c60b3 | |||
| 591909c344 | |||
| 2c8fb926da | |||
| b7580e84a8 | |||
| e674bf1648 | |||
| ae6cd72318 | |||
| ded340e4fc | |||
| 6918095d81 | |||
| 526b17db13 | |||
| d4ddcbc121 | |||
| 92298637ca | |||
| 780573510b | |||
| 619a111e05 | |||
| 88d702e6bd | |||
| d83e2831b7 | |||
| 6cbbdb08f8 | |||
| c6e956f038 | |||
| 94701b048a | |||
| 45143e9d31 | |||
| 9a64586864 | |||
| 9e7804dfd4 | |||
| 672073a41b | |||
| 40a3cabe68 | |||
| b468ce1256 | |||
| 9c739e26da | |||
| 2ec18a3cce | |||
| ea82b37302 | |||
| fe647dc9ee | |||
| 4f4bf7747a | |||
| 008d64c23a | |||
| f783893b8d | |||
| 4edfdd38fb | |||
| a2306712f2 | |||
| 923cadb1ae | |||
| 1ffd247c0c | |||
| 658873bdb3 | |||
| 82c4f9b407 | |||
| 5f02ab0976 | |||
| b11b0efde6 | |||
| eeab2c63a9 | |||
| 56cb04efc8 | |||
| 5fa605142f | |||
| 25ada07ab4 | |||
| 4307690b5c | |||
| 606f2344e9 | |||
| b3d903ebe5 | |||
| 5995e292e6 | |||
| 14e067455e | |||
| 073664de88 | |||
| 00452196d8 | |||
| bbe031f9f1 | |||
| b0870486aa | |||
| c5b41ac8ee | |||
| f1aabd6b78 | |||
| 0dd5cdaea5 | |||
| 07d694c750 | |||
| 3e24a34324 | |||
| f5ed7ad63e | |||
| e4d38707ea | |||
| c056e4b257 | |||
| 74a043607e | |||
| 982215a2c5 | |||
| 55a46c9b0e | |||
| b230a52892 | |||
| 36b80349b7 | |||
| 97bae794c2 |
+7
-6
@@ -240,12 +240,13 @@ static int icuNext(
|
||||
** The set of routines that implement the simple tokenizer
|
||||
*/
|
||||
static const sqlite3_tokenizer_module icuTokenizerModule = {
|
||||
0, /* iVersion */
|
||||
icuCreate, /* xCreate */
|
||||
icuDestroy, /* xCreate */
|
||||
icuOpen, /* xOpen */
|
||||
icuClose, /* xClose */
|
||||
icuNext, /* xNext */
|
||||
0, /* iVersion */
|
||||
icuCreate, /* xCreate */
|
||||
icuDestroy, /* xCreate */
|
||||
icuOpen, /* xOpen */
|
||||
icuClose, /* xClose */
|
||||
icuNext, /* xNext */
|
||||
0, /* xLanguageid */
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
+1
-1
@@ -83,7 +83,6 @@ static int icuLikeCompare(
|
||||
/* Read (and consume) the next character from the input pattern. */
|
||||
UChar32 uPattern;
|
||||
U8_NEXT_UNSAFE(zPattern, iPattern, uPattern);
|
||||
assert(uPattern!=0);
|
||||
|
||||
/* There are now 4 possibilities:
|
||||
**
|
||||
@@ -422,6 +421,7 @@ static void icuLoadCollation(
|
||||
int rc; /* Return code from sqlite3_create_collation_x() */
|
||||
|
||||
assert(nArg==2);
|
||||
(void)nArg; /* Unused parameter */
|
||||
zLocale = (const char *)sqlite3_value_text(apArg[0]);
|
||||
zName = (const char *)sqlite3_value_text(apArg[1]);
|
||||
|
||||
|
||||
+32
-6
@@ -2655,6 +2655,31 @@ static int spellfix1Rowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is called by the xUpdate() method. It returns a string
|
||||
** containing the conflict mode that xUpdate() should use for the current
|
||||
** operation. One of: "ROLLBACK", "IGNORE", "ABORT" or "REPLACE".
|
||||
*/
|
||||
static const char *spellfix1GetConflict(sqlite3 *db){
|
||||
static const char *azConflict[] = {
|
||||
/* Note: Instead of "FAIL" - "ABORT". */
|
||||
"ROLLBACK", "IGNORE", "ABORT", "ABORT", "REPLACE"
|
||||
};
|
||||
int eConflict = sqlite3_vtab_on_conflict(db);
|
||||
|
||||
assert( eConflict==SQLITE_ROLLBACK || eConflict==SQLITE_IGNORE
|
||||
|| eConflict==SQLITE_FAIL || eConflict==SQLITE_ABORT
|
||||
|| eConflict==SQLITE_REPLACE
|
||||
);
|
||||
assert( SQLITE_ROLLBACK==1 );
|
||||
assert( SQLITE_IGNORE==2 );
|
||||
assert( SQLITE_FAIL==3 );
|
||||
assert( SQLITE_ABORT==4 );
|
||||
assert( SQLITE_REPLACE==5 );
|
||||
|
||||
return azConflict[eConflict-1];
|
||||
}
|
||||
|
||||
/*
|
||||
** The xUpdate() method.
|
||||
*/
|
||||
@@ -2686,6 +2711,7 @@ static int spellfix1Update(
|
||||
char *zK1, *zK2;
|
||||
int i;
|
||||
char c;
|
||||
const char *zConflict = spellfix1GetConflict(db);
|
||||
|
||||
if( zWord==0 ){
|
||||
/* Inserts of the form: INSERT INTO table(command) VALUES('xyzzy');
|
||||
@@ -2746,10 +2772,10 @@ static int spellfix1Update(
|
||||
}else{
|
||||
newRowid = sqlite3_value_int64(argv[1]);
|
||||
spellfix1DbExec(&rc, db,
|
||||
"INSERT INTO \"%w\".\"%w_vocab\"(id,rank,langid,word,k1,k2) "
|
||||
"VALUES(%lld,%d,%d,%Q,%Q,%Q)",
|
||||
p->zDbName, p->zTableName,
|
||||
newRowid, iRank, iLang, zWord, zK1, zK2
|
||||
"INSERT OR %s INTO \"%w\".\"%w_vocab\"(id,rank,langid,word,k1,k2) "
|
||||
"VALUES(%lld,%d,%d,%Q,%Q,%Q)",
|
||||
zConflict, p->zDbName, p->zTableName,
|
||||
newRowid, iRank, iLang, zWord, zK1, zK2
|
||||
);
|
||||
}
|
||||
*pRowid = sqlite3_last_insert_rowid(db);
|
||||
@@ -2757,9 +2783,9 @@ static int spellfix1Update(
|
||||
rowid = sqlite3_value_int64(argv[0]);
|
||||
newRowid = *pRowid = sqlite3_value_int64(argv[1]);
|
||||
spellfix1DbExec(&rc, db,
|
||||
"UPDATE \"%w\".\"%w_vocab\" SET id=%lld, rank=%d, langid=%d,"
|
||||
"UPDATE OR %s \"%w\".\"%w_vocab\" SET id=%lld, rank=%d, langid=%d,"
|
||||
" word=%Q, k1=%Q, k2=%Q WHERE id=%lld",
|
||||
p->zDbName, p->zTableName, newRowid, iRank, iLang,
|
||||
zConflict, p->zDbName, p->zTableName, newRowid, iRank, iLang,
|
||||
zWord, zK1, zK2, rowid
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
C Merge\strunk\sfixes.
|
||||
D 2015-06-11T17:58:27.864
|
||||
C Cache\sthe\smost\srecently\ssqlite3_context\sused\sby\sOP_Function\sand\sreuse\sit\son\nsubsequent\scalls,\sif\sappropriate.\sThis\sgives\sa\snoticable\sperformance\sboost.
|
||||
D 2015-06-26T13:31:02.230
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 1063c58075b7400d93326b0eb332b48a54f53025
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@@ -85,7 +85,7 @@ F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1
|
||||
F ext/fts3/fts3_expr.c 71c063da9c2a4167fb54aec089dd5ef33a58c9cb
|
||||
F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60
|
||||
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
|
||||
F ext/fts3/fts3_icu.c e319e108661147bcca8dd511cd562f33a1ba81b5
|
||||
F ext/fts3/fts3_icu.c deb46f7020d87ea7a14a433fb7a7f4bef42a9652
|
||||
F ext/fts3/fts3_porter.c 3565faf04b626cddf85f03825e86056a4562c009
|
||||
F ext/fts3/fts3_snippet.c 68ae118b0f834ea53d2b89e4087fc0f0b8c4ee4e
|
||||
F ext/fts3/fts3_term.c 88c55a6fa1a51ab494e33dced0401a6c28791fd7
|
||||
@@ -104,7 +104,7 @@ F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c
|
||||
F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
|
||||
F ext/fts3/unicode/mkunicode.tcl a2567f9d6ad6779879a2e394c120ad8718557e65
|
||||
F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43
|
||||
F ext/icu/icu.c d415ccf984defeb9df2c0e1afcfaa2f6dc05eacb
|
||||
F ext/icu/icu.c b2732aef0b076e4276d9b39b5a33cec7a05e1413
|
||||
F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
|
||||
F ext/misc/amatch.c 27b9b601fb1453084e18a3432ea0240d7af8decb
|
||||
F ext/misc/closure.c 636024302cde41b2bf0c542f81c40c624cfb7012
|
||||
@@ -118,7 +118,7 @@ F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63
|
||||
F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc
|
||||
F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a
|
||||
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
|
||||
F ext/misc/spellfix.c 25810dda37fc904b0772a13efd8ca072fb09e355
|
||||
F ext/misc/spellfix.c de9181ec188294dd2a1087b329ca55cfaa76a29d
|
||||
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
|
||||
F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
|
||||
F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e
|
||||
@@ -192,20 +192,20 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
|
||||
F src/backup.c ff743689c4d6c5cb55ad42ed9d174b2b3e71f1e3
|
||||
F src/bitvec.c 5eb7958c3bf65210211cbcfc44eff86d0ded7c9d
|
||||
F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
|
||||
F src/btree.c 5166c27883c24768c2f7f53479714f03ef34c612
|
||||
F src/btree.c 40e98c10725c2cec5429068e21c17924f4bf06cc
|
||||
F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1
|
||||
F src/btreeInt.h 973a22a6fd61350b454ad614832b1f0a5e25a1e4
|
||||
F src/build.c 6770b74ccb51cb485e81057c625f77455d5ddc06
|
||||
F src/btreeInt.h fdd1aff02fb2a63812bd95716e7f579fc3759107
|
||||
F src/build.c b3f15255d5b16e42dafeaa638fd4f8a47c94ed70
|
||||
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
|
||||
F src/complete.c a5cf5b4b56390cfb7b8636e8f7ddef90258dd575
|
||||
F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b
|
||||
F src/date.c e4d50b3283696836ec1036b695ead9a19e37a5ac
|
||||
F src/dbstat.c f402e77e25089c6003d0c60b3233b9b3947d599a
|
||||
F src/delete.c 81fc0453b0e95275bef8c2091636fcafc7229e91
|
||||
F src/expr.c 710c764c1974b15a0e56b004ff9f5e6ceab3a854
|
||||
F src/delete.c 8857a6f27560718f65d43bdbec86c967ae1f8dfa
|
||||
F src/expr.c 32c836d9fa22c25371039febf074849dcefb3de9
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c 6c5a2dbf8333303b033a2219e18ce8a9f99981c2
|
||||
F src/func.c 5b8b8e77a0fb644eaf8947d413804622e32692b6
|
||||
F src/fkey.c c9b63a217d86582c22121699a47f22f524608869
|
||||
F src/func.c a98ea5880dc50e9ca6dd6f57079a37b9cfcdecf1
|
||||
F src/global.c 4f77cadbc5427d00139ba43d0f3979804cbb700e
|
||||
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
|
||||
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
|
||||
@@ -214,8 +214,8 @@ F src/insert.c b5f8b35a1b7924020e48cade5b2b5017bca7906b
|
||||
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
||||
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
|
||||
F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770
|
||||
F src/loadext.c 29255bbe1cfb2ce9bbff2526a5ecfddcb49b9271
|
||||
F src/main.c 3a610587018485d9a12e38899dd8b8129b04d836
|
||||
F src/loadext.c e722f4b832f923744788365df5fb8515c0bc8a47
|
||||
F src/main.c c0061a4f8ba86f957534be93b7026dab324f12c2
|
||||
F src/malloc.c 908c780fdddd472163c2d1b1820ae4081f01ad20
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c abe6ee469b6c5a35c7f22bfeb9c9bac664a1c987
|
||||
@@ -224,7 +224,7 @@ F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534
|
||||
F src/mem5.c 61eeb90134f9a5be6c2e68d8daae7628b25953fb
|
||||
F src/memjournal.c 3eb2c0b51adbd869cb6a44780323f05fa904dc85
|
||||
F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495
|
||||
F src/mutex.c 19bf9acba69ca2f367c3761080f8a9f0cf4670a8
|
||||
F src/mutex.c 529e95739f815300a33c73fd8a7d6bdf0c24bd18
|
||||
F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85
|
||||
F src/mutex_noop.c 529bab0743c3321c940f32c3464de494fd38cfa9
|
||||
F src/mutex_unix.c 5cf676464bd19e0a866297515d146e8bf1669dfb
|
||||
@@ -240,22 +240,22 @@ F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
|
||||
F src/pager.c 9bc918a009285f96ec6dac62dd764c7063552455
|
||||
F src/pager.h c3476e7c89cdf1c6914e50a11f3714e30b4e0a77
|
||||
F src/parse.y 6d60dda8f8d418b6dc034f1fbccd816c459983a8
|
||||
F src/pcache.c 10539fb959849ad6efff80050541cab3d25089d4
|
||||
F src/pcache.c d8b19632706dd6b81b03d0c5fd1e6bab8c13d0b9
|
||||
F src/pcache.h b44658c9c932d203510279439d891a2a83e12ba8
|
||||
F src/pcache1.c 69d137620a305f814398bd29a0c998038c0695e9
|
||||
F src/pcache1.c 8e3799b33c41d517d86444d4abefc80d4f02adca
|
||||
F src/pragma.c c1f4d012ea9f6b1ce52d341b2cd0ad72d560afd7
|
||||
F src/pragma.h b8632d7cdda7b25323fa580e3e558a4f0d4502cc
|
||||
F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1
|
||||
F src/printf.c db11b5960105ee661dcac690f2ae6276e49bf251
|
||||
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
|
||||
F src/resolve.c 84c571794e3ee5806274d95158a4c0177c6c4708
|
||||
F src/resolve.c 2d47554370de8de6dd5be060cef9559eec315005
|
||||
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
|
||||
F src/select.c ecd8562e686b968511abbad6d6810fa30fda2952
|
||||
F src/shell.c 07dda7cd692911d2f22269953418d049f2e2c0ee
|
||||
F src/sqlite.h.in d165beeceb6b40af60f352a4d4e37e02d9af7df0
|
||||
F src/select.c 9baeda79f93cfd180d471273a2f9c82c682a37a2
|
||||
F src/shell.c 8af3cced094aebb5f57a8ad739b9dafc7867eed7
|
||||
F src/sqlite.h.in 76d2f5637eb795b6300d9dd3c3ec3632ffafd721
|
||||
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
|
||||
F src/sqlite3ext.h 2ebeb634e751a61a6f0eebfa0f4669f46a42f6cd
|
||||
F src/sqliteInt.h e389c788cd9f0af14528dfcddefc9ccece17d385
|
||||
F src/sqlite3ext.h be1a718b7d2ce40ceba725ae92c8eb5f18003066
|
||||
F src/sqliteInt.h d5df694bc33870e77fb08f389d12309597fe3059
|
||||
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
|
||||
F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
|
||||
F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
|
||||
@@ -306,20 +306,20 @@ F src/test_vfs.c 3b65d42e18b262805716bd96178c81da8f2d9283
|
||||
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c 6bbcc9fe50c917864d48287b4792d46d6e873481
|
||||
F src/tokenize.c baa0e550dfa76a8d781732a7bfb1f0aa094942f2
|
||||
F src/treeview.c 84aa2d2ed26627ccc8dd3a2becfa18dc86ee4607
|
||||
F src/tokenize.c 57cb3720f53f84d811def2069c2b169b6be539a5
|
||||
F src/treeview.c c84b1a8ebc7f1d00cd76ce4958eeb3ae1021beed
|
||||
F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f
|
||||
F src/update.c 831a657bcfffcb44b25f3551909efcf4977e57c5
|
||||
F src/update.c 487747b328b7216bb7f6af0695d6937d5c9e605f
|
||||
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
|
||||
F src/util.c a6431c92803b975b7322724a7b433e538d243539
|
||||
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
|
||||
F src/vdbe.c 0a6a1df5c31415a0e974e74e7bd412616889453d
|
||||
F src/vdbe.h 7e538ecf47dccb307ea2d087c3ddc2dd8d70e79d
|
||||
F src/vdbeInt.h f0ccddac48583d5f762dc554a9f79e85ea8807e0
|
||||
F src/vdbe.c 592957316d7bced599384e7897f6ee7728af5a61
|
||||
F src/vdbe.h 90048aea1910f9df93e6044592bd4a466dc9c5e7
|
||||
F src/vdbeInt.h 20295e482121d13437f69985f77db211cdc8bac1
|
||||
F src/vdbeapi.c 6a0d7757987018ff6b1b81bc5293219cd26bb299
|
||||
F src/vdbeaux.c 46f9bc4b32866082eb87a36b461e487a0bbdbe8e
|
||||
F src/vdbeaux.c 4c82d6f686f72ea7d266d26d528a171b728626f7
|
||||
F src/vdbeblob.c 4f2e8e075d238392df98c5e03a64342465b03f90
|
||||
F src/vdbemem.c 67b302dc6df64b4d6785881c5d22bd4f9b17739d
|
||||
F src/vdbemem.c ae38a0d35ae71cf604381a887c170466ba518090
|
||||
F src/vdbesort.c f5009e7a35e3065635d8918b9a31f498a499976b
|
||||
F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0
|
||||
F src/vtab.c c535e80259ebe616467181a83a4263555b97c694
|
||||
@@ -327,9 +327,9 @@ F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
|
||||
F src/wal.c ce2cb2d06faab54d1bce3e739bec79e063dd9113
|
||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||
F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
|
||||
F src/where.c aa26f4b0a3ad9c586f3315cb499d2dc813e14f01
|
||||
F src/where.c 909eba3b6db984eb2adfbca9de2c237ee7056adb
|
||||
F src/whereInt.h 5f87e3c4b0551747d119730dfebddd3c54f04047
|
||||
F src/wherecode.c 3f3152ecf4224413bd0491ea4210883b85fe95d1
|
||||
F src/wherecode.c 0669481cabaf5caf934b6bb825df15bc57f60d40
|
||||
F src/whereexpr.c 9ce1c9cfedbf80c93c7d899497025ec8256ce652
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
|
||||
@@ -457,7 +457,7 @@ F test/corruptE.test 193b4ca4e927e77c1d5f4f56203ddc998432a7ee
|
||||
F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4
|
||||
F test/corruptG.test 1ab3bf97ee7bdba70e0ff3ba2320657df55d1804
|
||||
F test/corruptH.test 5dd4fa98c6c1ed33b178f9e8a48c4fdd3cfc9067
|
||||
F test/corruptI.test ddf8c7146db0bc6080eedced67453b4cc69b5340
|
||||
F test/corruptI.test f2b10e4fec2a4315bca2b936ffa52ccbffac3422
|
||||
F test/corruptJ.test 9e29e7a81ee3b6ac50f77ea7a9e2f3fa03f32d91
|
||||
F test/cost.test 19d314526616ce4473eb4e4e450fcb94499ce318
|
||||
F test/count.test cb2e0f934c6eb33670044520748d2ecccd46259c
|
||||
@@ -517,7 +517,7 @@ F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
|
||||
F test/enc2.test 83437a79ba1545a55fb549309175c683fb334473
|
||||
F test/enc3.test 90683ad0e6ea587b9d5542ca93568af9a9858c40
|
||||
F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020
|
||||
F test/eqp.test bd139ceea2ebc6ebb01c50f55f7c6f79473af6e5
|
||||
F test/eqp.test 85873fa5816c48915c82c4e74cb5c35a5b48160f
|
||||
F test/errmsg.test f31592a594b44ee121371d25ddd5d63497bb3401
|
||||
F test/eval.test a64c9105d6ff163df7cf09d6ac29cdad5922078c
|
||||
F test/exclusive.test c7ebbc756eacf544c108b15eed64d7d4e5f86b75
|
||||
@@ -644,7 +644,7 @@ F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
|
||||
F test/fts4merge3.test aab02a09f50fe6baaddc2e159c3eabc116d45fc7
|
||||
F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b
|
||||
F test/fts4noti.test 524807f0c36d49deea7920cdd4cd687408b58849
|
||||
F test/fts4unicode.test 01ec3fe2a7c3cfff3b4c0581b83caa11b33efa36
|
||||
F test/fts4unicode.test 27378af76394542cf490cf001d8d1505fe55f6a9
|
||||
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
|
||||
F test/func.test ae97561957aba6ca9e3a7b8a13aac41830d701ef
|
||||
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
|
||||
@@ -657,10 +657,10 @@ F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
|
||||
F test/fuzz3.test efd384b896c647b61a2c1848ba70d42aad60a7b3
|
||||
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
|
||||
F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26
|
||||
F test/fuzzcheck.c a60f926e3fa86c8d33908406d75eec868c22b9ca
|
||||
F test/fuzzdata1.db b60254eeb6bc11474071b883059662a73c48da7f
|
||||
F test/fuzzcheck.c b973b06b500e6fc052d7059257cdf70df1f3a986
|
||||
F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664
|
||||
F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973
|
||||
F test/fuzzdata3.db a6e9bf75b8bfad0b7e60e57038908f4237b9c5d2
|
||||
F test/fuzzdata3.db 1d6044c33a114007f02b6e6846f1fa232f607bfd
|
||||
F test/fuzzer1.test d4c52aaf3ef923da293a2653cfab33d02f718a36
|
||||
F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
|
||||
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
|
||||
@@ -668,7 +668,7 @@ F test/hexlit.test 1d312fa816dfd3650a3bb488093bc09a0c927f67
|
||||
F test/hook.test 162d7cef7a2d2b04839fe14402934e6a1b79442f
|
||||
F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4
|
||||
F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8
|
||||
F test/in.test b52fa96bcf6cebc5c8829c822315d0f87af9c6c2
|
||||
F test/in.test 61a24ae38d4b64ec69f06ccdf022992f68a98176
|
||||
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
|
||||
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
|
||||
F test/in4.test d2b38cba404bc4320f4fe1b595b3d163f212c068
|
||||
@@ -745,7 +745,7 @@ F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
|
||||
F test/malloc.test 21c213365f2cca95ab2d7dc078dc8525f96065f8
|
||||
F test/malloc3.test e3b32c724b5a124b57cb0ed177f675249ad0c66a
|
||||
F test/malloc4.test 957337613002b7058a85116493a262f679f3a261
|
||||
F test/malloc5.test 79182b8bffd6d62f77b1a5a8ba8e6bf0e5053b8e
|
||||
F test/malloc5.test e9a9116f80ab6b7a9ca258876c6f3dedb08cb08b
|
||||
F test/malloc6.test 2f039d9821927eacae43e1831f815e157659a151
|
||||
F test/malloc7.test 7c68a32942858bc715284856c5507446bba88c3a
|
||||
F test/malloc8.test 9b7a3f8cb9cf0b12fff566e80a980b1767bd961d
|
||||
@@ -875,7 +875,7 @@ F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054
|
||||
F test/select4.test 6d5bc6d178a367e8b48fa1c1d3ea12cae9c2d650
|
||||
F test/select5.test e758b8ef94f69b111df4cb819008856655dcd535
|
||||
F test/select6.test 39eac4a5c03650b2b473c532882273283ee8b7a0
|
||||
F test/select7.test 7fd2ef598cfabb6b9ff6ac13973b91d0527df49d
|
||||
F test/select7.test 71f06cd37cb6f65bb08ba1ccf8e2f5818c09329f
|
||||
F test/select8.test 8c8f5ae43894c891efc5755ed905467d1d67ad5d
|
||||
F test/select9.test aebc2bb0c3bc44606125033cbcaac2c8d1f33a95
|
||||
F test/selectA.test e452bdb975f488ea46d091382a9185b5853ed2c7
|
||||
@@ -928,8 +928,8 @@ F test/speed3.test d32043614c08c53eafdc80f33191d5bd9b920523
|
||||
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
|
||||
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
|
||||
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
|
||||
F test/speedtest1.c 9f1b745c24886cced3f70ffc666300152a39013c
|
||||
F test/spellfix.test 24f676831acddd2f4056a598fd731a72c6311f49
|
||||
F test/speedtest1.c f42fd04a34a0c1dc289cbe536ef62d706227a736
|
||||
F test/spellfix.test 0597065ff57042df1f138e6a2611ae19c2698135
|
||||
F test/sqldiff1.test 8f6bc7c6a5b3585d350d779c6078869ba402f8f5
|
||||
F test/sqllimits1.test e05786eaed7950ff6a2d00031d001d8a26131e68
|
||||
F test/stat.test 8de91498c99f5298b303f70f1d1f3b9557af91bf
|
||||
@@ -943,7 +943,7 @@ F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2
|
||||
F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85
|
||||
F test/syscall.test d2fdaad713f103ac611fe7ef9b724c7b69f8149c
|
||||
F test/sysfault.test fa776e60bf46bdd3ae69f0b73e46ee3977a58ae6
|
||||
F test/table.test bd841e8df69b99172ce9c7d53587463913d711ca
|
||||
F test/table.test 33bf0d1fd07f304582695184b8e6feb017303816
|
||||
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
|
||||
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
|
||||
F test/tclsqlite.test 7fb866443c7deceed22b63948ccd6f76b52ad054
|
||||
@@ -1209,7 +1209,7 @@ F test/whereC.test cae295158703cb3fc23bf1a108a9ab730efff0f6
|
||||
F test/whereD.test 9eba1f9b18e5b19a0b0bcaae5e8c037260195f2b
|
||||
F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f
|
||||
F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7
|
||||
F test/whereG.test 69f5ec4b15760a8c860f80e2d55525669390aab3
|
||||
F test/whereG.test dde4c52a97385a55be6a7cd46be8373f0cf35501
|
||||
F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2
|
||||
F test/whereI.test 1d89199697919d4930be05a71e7fe620f114e622
|
||||
F test/whereJ.test 55a3221706a7ab706293f17cc8f96da563bf0767
|
||||
@@ -1284,9 +1284,12 @@ F tool/varint.c 5d94cb5003db9dbbcbcc5df08d66f16071aee003
|
||||
F tool/vdbe-compress.tcl 5926c71f9c12d2ab73ef35c29376e756eb68361c
|
||||
F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
||||
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 0e23a079bd648f9778c857ec51e39acfd30a4040 afc6db9b105f32110112b877f06091757888a5f2
|
||||
R 66f6090af762e2af727925054063787e
|
||||
P 015302f15e46a087ec92f3644c6741600dbf4306
|
||||
R 7832174f14c22d1eacdad67bafdfeaa7
|
||||
T *branch * function-ctx-cache
|
||||
T *sym-function-ctx-cache *
|
||||
T -sym-trunk *
|
||||
U drh
|
||||
Z 15f99ba3f20685296cbae74ff03f5eca
|
||||
Z e48fb4a345ac7f54e42bdc087583de4b
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
1df8cbbea66f303029737752f37cf2a6db98fcd4
|
||||
2f31bdd1b2186659f57a705ecf0eaf590471c374
|
||||
+514
-281
File diff suppressed because it is too large
Load Diff
+4
-1
@@ -231,6 +231,7 @@
|
||||
/* Forward declarations */
|
||||
typedef struct MemPage MemPage;
|
||||
typedef struct BtLock BtLock;
|
||||
typedef struct CellInfo CellInfo;
|
||||
|
||||
/*
|
||||
** This is a magic string that appears at the beginning of every
|
||||
@@ -295,6 +296,8 @@ struct MemPage {
|
||||
u8 *aDataEnd; /* One byte past the end of usable data */
|
||||
u8 *aCellIdx; /* The cell index area */
|
||||
DbPage *pDbPage; /* Pager page handle */
|
||||
u16 (*xCellSize)(MemPage*,u8*); /* cellSizePtr method */
|
||||
void (*xParseCell)(MemPage*,u8*,CellInfo*); /* btreeParseCell method */
|
||||
Pgno pgno; /* Page number for this page */
|
||||
};
|
||||
|
||||
@@ -350,6 +353,7 @@ struct Btree {
|
||||
u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */
|
||||
u8 sharable; /* True if we can share pBt with another db */
|
||||
u8 locked; /* True if db currently has pBt locked */
|
||||
u8 hasIncrblobCur; /* True if there are one or more Incrblob cursors */
|
||||
int wantToLock; /* Number of nested calls to sqlite3BtreeEnter() */
|
||||
int nBackup; /* Number of backup operations reading this btree */
|
||||
u32 iDataVersion; /* Combines with pBt->pPager->iDataVersion */
|
||||
@@ -460,7 +464,6 @@ struct BtShared {
|
||||
** about a cell. The parseCellPtr() function fills in this structure
|
||||
** based on information extract from the raw disk page.
|
||||
*/
|
||||
typedef struct CellInfo CellInfo;
|
||||
struct CellInfo {
|
||||
i64 nKey; /* The key for INTKEY tables, or nPayload otherwise */
|
||||
u8 *pPayload; /* Pointer to the start of payload */
|
||||
|
||||
+2
-1
@@ -976,7 +976,7 @@ void sqlite3StartTable(
|
||||
int j1;
|
||||
int fileFormat;
|
||||
int reg1, reg2, reg3;
|
||||
sqlite3BeginWriteOperation(pParse, 0, iDb);
|
||||
sqlite3BeginWriteOperation(pParse, 1, iDb);
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
if( isVirtual ){
|
||||
@@ -1924,6 +1924,7 @@ void sqlite3EndTable(
|
||||
regRec = ++pParse->nMem;
|
||||
regRowid = ++pParse->nMem;
|
||||
assert(pParse->nTab==1);
|
||||
sqlite3MayAbort(pParse);
|
||||
sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, pParse->regRoot, iDb);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_P2ISREG);
|
||||
pParse->nTab = 2;
|
||||
|
||||
+1
-1
@@ -397,7 +397,7 @@ void sqlite3DeleteFrom(
|
||||
/* Construct a query to find the rowid or primary key for every row
|
||||
** to be deleted, based on the WHERE clause.
|
||||
*/
|
||||
pWInfo = sqlite3WhereBegin(pParse, 0, pTabList, pWhere, 0, 0,
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0,
|
||||
WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK,
|
||||
iTabCur+1);
|
||||
if( pWInfo==0 ) goto delete_from_cleanup;
|
||||
|
||||
+3
-18
@@ -2208,17 +2208,6 @@ static void sqlite3ExprCodeIN(
|
||||
}
|
||||
#endif /* SQLITE_OMIT_SUBQUERY */
|
||||
|
||||
/*
|
||||
** Duplicate an 8-byte value
|
||||
*/
|
||||
static char *dup8bytes(Vdbe *v, const char *in){
|
||||
char *out = sqlite3DbMallocRaw(sqlite3VdbeDb(v), 8);
|
||||
if( out ){
|
||||
memcpy(out, in, 8);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
/*
|
||||
** Generate an instruction that will put the floating point
|
||||
@@ -2231,12 +2220,10 @@ static char *dup8bytes(Vdbe *v, const char *in){
|
||||
static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){
|
||||
if( ALWAYS(z!=0) ){
|
||||
double value;
|
||||
char *zV;
|
||||
sqlite3AtoF(z, &value, sqlite3Strlen30(z), SQLITE_UTF8);
|
||||
assert( !sqlite3IsNaN(value) ); /* The new AtoF never returns NaN */
|
||||
if( negateFlag ) value = -value;
|
||||
zV = dup8bytes(v, (char*)&value);
|
||||
sqlite3VdbeAddOp4(v, OP_Real, 0, iMem, 0, zV, P4_REAL);
|
||||
sqlite3VdbeAddOp4Dup8(v, OP_Real, 0, iMem, 0, (u8*)&value, P4_REAL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -2262,10 +2249,8 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
|
||||
assert( z!=0 );
|
||||
c = sqlite3DecOrHexToI64(z, &value);
|
||||
if( c==0 || (c==2 && negFlag) ){
|
||||
char *zV;
|
||||
if( negFlag ){ value = c==2 ? SMALLEST_INT64 : -value; }
|
||||
zV = dup8bytes(v, (char*)&value);
|
||||
sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64);
|
||||
sqlite3VdbeAddOp4Dup8(v, OP_Int64, 0, iMem, 0, (u8*)&value, P4_INT64);
|
||||
}else{
|
||||
#ifdef SQLITE_OMIT_FLOATING_POINT
|
||||
sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z);
|
||||
@@ -2870,7 +2855,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
*/
|
||||
if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){
|
||||
assert( nFarg>=1 );
|
||||
sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target);
|
||||
inReg = sqlite3ExprCodeTarget(pParse, pFarg->a[0].pExpr, target);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -631,7 +631,7 @@ static void fkScanChildren(
|
||||
/* Create VDBE to loop through the entries in pSrc that match the WHERE
|
||||
** clause. For each row found, increment either the deferred or immediate
|
||||
** foreign key constraint counter. */
|
||||
pWInfo = sqlite3WhereBegin(pParse, 0, pSrc, pWhere, 0, 0, 0, 0);
|
||||
pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
|
||||
if( pWInfo ){
|
||||
sqlite3WhereEnd(pWInfo);
|
||||
|
||||
+10
-13
@@ -575,17 +575,15 @@ struct compareInfo {
|
||||
|
||||
/*
|
||||
** For LIKE and GLOB matching on EBCDIC machines, assume that every
|
||||
** character is exactly one byte in size. Also, all characters are
|
||||
** able to participate in upper-case-to-lower-case mappings in EBCDIC
|
||||
** whereas only characters less than 0x80 do in ASCII.
|
||||
** character is exactly one byte in size. Also, provde the Utf8Read()
|
||||
** macro for fast reading of the next character in the common case where
|
||||
** the next character is ASCII.
|
||||
*/
|
||||
#if defined(SQLITE_EBCDIC)
|
||||
# define sqlite3Utf8Read(A) (*((*A)++))
|
||||
# define GlobUpperToLower(A) A = sqlite3UpperToLower[A]
|
||||
# define GlobUpperToLowerAscii(A) A = sqlite3UpperToLower[A]
|
||||
# define Utf8Read(A) (*(A++))
|
||||
#else
|
||||
# define GlobUpperToLower(A) if( A<=0x7f ){ A = sqlite3UpperToLower[A]; }
|
||||
# define GlobUpperToLowerAscii(A) A = sqlite3UpperToLower[A]
|
||||
# define Utf8Read(A) (A[0]<0x80?*(A++):sqlite3Utf8Read(&A))
|
||||
#endif
|
||||
|
||||
static const struct compareInfo globInfo = { '*', '?', '[', 0 };
|
||||
@@ -627,7 +625,7 @@ static const struct compareInfo likeInfoAlt = { '%', '_', 0, 0 };
|
||||
** Ec Where E is the "esc" character and c is any other
|
||||
** character, including '%', '_', and esc, match exactly c.
|
||||
**
|
||||
** The comments through this routine usually assume glob matching.
|
||||
** The comments within this routine usually assume glob matching.
|
||||
**
|
||||
** This routine is usually quick, but can be N**2 in the worst case.
|
||||
*/
|
||||
@@ -651,13 +649,12 @@ static int patternCompare(
|
||||
*/
|
||||
matchOther = esc ? esc : pInfo->matchSet;
|
||||
|
||||
while( (c = sqlite3Utf8Read(&zPattern))!=0 ){
|
||||
while( (c = Utf8Read(zPattern))!=0 ){
|
||||
if( c==matchAll ){ /* Match "*" */
|
||||
/* Skip over multiple "*" characters in the pattern. If there
|
||||
** are also "?" characters, skip those as well, but consume a
|
||||
** single character of the input string for each "?" skipped */
|
||||
while( (c=sqlite3Utf8Read(&zPattern)) == matchAll
|
||||
|| c == matchOne ){
|
||||
while( (c=Utf8Read(zPattern)) == matchAll || c == matchOne ){
|
||||
if( c==matchOne && sqlite3Utf8Read(&zString)==0 ){
|
||||
return 0;
|
||||
}
|
||||
@@ -702,7 +699,7 @@ static int patternCompare(
|
||||
if( patternCompare(zPattern,zString,pInfo,esc) ) return 1;
|
||||
}
|
||||
}else{
|
||||
while( (c2 = sqlite3Utf8Read(&zString))!=0 ){
|
||||
while( (c2 = Utf8Read(zString))!=0 ){
|
||||
if( c2!=c ) continue;
|
||||
if( patternCompare(zPattern,zString,pInfo,esc) ) return 1;
|
||||
}
|
||||
@@ -748,7 +745,7 @@ static int patternCompare(
|
||||
continue;
|
||||
}
|
||||
}
|
||||
c2 = sqlite3Utf8Read(&zString);
|
||||
c2 = Utf8Read(zString);
|
||||
if( c==c2 ) continue;
|
||||
if( noCase && c<0x80 && c2<0x80 && sqlite3Tolower(c)==sqlite3Tolower(c2) ){
|
||||
continue;
|
||||
|
||||
+4
-1
@@ -402,7 +402,10 @@ static const sqlite3_api_routines sqlite3Apis = {
|
||||
sqlite3_reset_auto_extension,
|
||||
sqlite3_result_blob64,
|
||||
sqlite3_result_text64,
|
||||
sqlite3_strglob
|
||||
sqlite3_strglob,
|
||||
/* Version 3.8.11 and later */
|
||||
(sqlite3_value*(*)(const sqlite3_value*))sqlite3_value_dup,
|
||||
sqlite3_value_free
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
+5
-1
@@ -2082,9 +2082,11 @@ int sqlite3TempInMemory(const sqlite3 *db){
|
||||
return ( db->temp_store!=1 );
|
||||
#endif
|
||||
#if SQLITE_TEMP_STORE==3
|
||||
UNUSED_PARAMETER(db);
|
||||
return 1;
|
||||
#endif
|
||||
#if SQLITE_TEMP_STORE<1 || SQLITE_TEMP_STORE>3
|
||||
UNUSED_PARAMETER(db);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
@@ -3356,7 +3358,9 @@ int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){
|
||||
*/
|
||||
int sqlite3_test_control(int op, ...){
|
||||
int rc = 0;
|
||||
#ifndef SQLITE_OMIT_BUILTIN_TEST
|
||||
#ifdef SQLITE_OMIT_BUILTIN_TEST
|
||||
UNUSED_PARAMETER(op);
|
||||
#else
|
||||
va_list ap;
|
||||
va_start(ap, op);
|
||||
switch( op ){
|
||||
|
||||
+8
-3
@@ -45,9 +45,14 @@ int sqlite3MutexInit(void){
|
||||
}else{
|
||||
pFrom = sqlite3NoopMutex();
|
||||
}
|
||||
memcpy(pTo, pFrom, offsetof(sqlite3_mutex_methods, xMutexAlloc));
|
||||
memcpy(&pTo->xMutexFree, &pFrom->xMutexFree,
|
||||
sizeof(*pTo) - offsetof(sqlite3_mutex_methods, xMutexFree));
|
||||
pTo->xMutexInit = pFrom->xMutexInit;
|
||||
pTo->xMutexEnd = pFrom->xMutexEnd;
|
||||
pTo->xMutexFree = pFrom->xMutexFree;
|
||||
pTo->xMutexEnter = pFrom->xMutexEnter;
|
||||
pTo->xMutexTry = pFrom->xMutexTry;
|
||||
pTo->xMutexLeave = pFrom->xMutexLeave;
|
||||
pTo->xMutexHeld = pFrom->xMutexHeld;
|
||||
pTo->xMutexNotheld = pFrom->xMutexNotheld;
|
||||
pTo->xMutexAlloc = pFrom->xMutexAlloc;
|
||||
}
|
||||
rc = sqlite3GlobalConfig.mutex.xMutexInit();
|
||||
|
||||
+8
-14
@@ -28,7 +28,6 @@ struct PCache {
|
||||
int (*xStress)(void*,PgHdr*); /* Call to try make a page clean */
|
||||
void *pStress; /* Argument to xStress */
|
||||
sqlite3_pcache *pCache; /* Pluggable cache module */
|
||||
PgHdr *pPage1; /* Reference to page 1 */
|
||||
};
|
||||
|
||||
/********************************** Linked List Management ********************/
|
||||
@@ -106,9 +105,6 @@ static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){
|
||||
*/
|
||||
static void pcacheUnpin(PgHdr *p){
|
||||
if( p->pCache->bPurgeable ){
|
||||
if( p->pgno==1 ){
|
||||
p->pCache->pPage1 = 0;
|
||||
}
|
||||
sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 0);
|
||||
}
|
||||
}
|
||||
@@ -201,7 +197,6 @@ int sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
|
||||
sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
|
||||
}
|
||||
pCache->pCache = pNew;
|
||||
pCache->pPage1 = 0;
|
||||
pCache->szPage = szPage;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
@@ -359,9 +354,6 @@ PgHdr *sqlite3PcacheFetchFinish(
|
||||
pCache->nRef++;
|
||||
}
|
||||
pPgHdr->nRef++;
|
||||
if( pgno==1 ){
|
||||
pCache->pPage1 = pPgHdr;
|
||||
}
|
||||
return pPgHdr;
|
||||
}
|
||||
|
||||
@@ -402,9 +394,6 @@ void sqlite3PcacheDrop(PgHdr *p){
|
||||
pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE);
|
||||
}
|
||||
p->pCache->nRef--;
|
||||
if( p->pgno==1 ){
|
||||
p->pCache->pPage1 = 0;
|
||||
}
|
||||
sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 1);
|
||||
}
|
||||
|
||||
@@ -495,9 +484,14 @@ void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){
|
||||
sqlite3PcacheMakeClean(p);
|
||||
}
|
||||
}
|
||||
if( pgno==0 && pCache->pPage1 ){
|
||||
memset(pCache->pPage1->pData, 0, pCache->szPage);
|
||||
pgno = 1;
|
||||
if( pgno==0 && pCache->nRef ){
|
||||
sqlite3_pcache_page *pPage1;
|
||||
pPage1 = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache,1,0);
|
||||
if( ALWAYS(pPage1) ){ /* Page 1 is always available in cache, because
|
||||
** pCache->nRef>0 */
|
||||
memset(pPage1->pBuf, 0, pCache->szPage);
|
||||
pgno = 1;
|
||||
}
|
||||
}
|
||||
sqlite3GlobalConfig.pcache2.xTruncate(pCache->pCache, pgno+1);
|
||||
}
|
||||
|
||||
+72
-24
@@ -148,8 +148,15 @@ static SQLITE_WSD struct PCacheGlobal {
|
||||
/*
|
||||
** Macros to enter and leave the PCache LRU mutex.
|
||||
*/
|
||||
#define pcache1EnterMutex(X) sqlite3_mutex_enter((X)->mutex)
|
||||
#define pcache1LeaveMutex(X) sqlite3_mutex_leave((X)->mutex)
|
||||
#if !defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) || SQLITE_THREADSAFE==0
|
||||
# define pcache1EnterMutex(X) assert((X)->mutex==0)
|
||||
# define pcache1LeaveMutex(X) assert((X)->mutex==0)
|
||||
# define PCACHE1_MIGHT_USE_GROUP_MUTEX 0
|
||||
#else
|
||||
# define pcache1EnterMutex(X) sqlite3_mutex_enter((X)->mutex)
|
||||
# define pcache1LeaveMutex(X) sqlite3_mutex_leave((X)->mutex)
|
||||
# define PCACHE1_MIGHT_USE_GROUP_MUTEX 1
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
/******** Page Allocation/SQLITE_CONFIG_PCACHE Related Functions **************/
|
||||
@@ -425,31 +432,30 @@ static void pcache1ResizeHash(PCache1 *p){
|
||||
**
|
||||
** The PGroup mutex must be held when this function is called.
|
||||
*/
|
||||
static void pcache1PinPage(PgHdr1 *pPage){
|
||||
static PgHdr1 *pcache1PinPage(PgHdr1 *pPage){
|
||||
PCache1 *pCache;
|
||||
PGroup *pGroup;
|
||||
|
||||
assert( pPage!=0 );
|
||||
assert( pPage->isPinned==0 );
|
||||
pCache = pPage->pCache;
|
||||
pGroup = pCache->pGroup;
|
||||
assert( pPage->pLruNext || pPage==pGroup->pLruTail );
|
||||
assert( pPage->pLruPrev || pPage==pGroup->pLruHead );
|
||||
assert( sqlite3_mutex_held(pGroup->mutex) );
|
||||
assert( pPage->pLruNext || pPage==pCache->pGroup->pLruTail );
|
||||
assert( pPage->pLruPrev || pPage==pCache->pGroup->pLruHead );
|
||||
assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
|
||||
if( pPage->pLruPrev ){
|
||||
pPage->pLruPrev->pLruNext = pPage->pLruNext;
|
||||
}else{
|
||||
pGroup->pLruHead = pPage->pLruNext;
|
||||
pCache->pGroup->pLruHead = pPage->pLruNext;
|
||||
}
|
||||
if( pPage->pLruNext ){
|
||||
pPage->pLruNext->pLruPrev = pPage->pLruPrev;
|
||||
}else{
|
||||
pGroup->pLruTail = pPage->pLruPrev;
|
||||
pCache->pGroup->pLruTail = pPage->pLruPrev;
|
||||
}
|
||||
pPage->pLruNext = 0;
|
||||
pPage->pLruPrev = 0;
|
||||
pPage->isPinned = 1;
|
||||
pCache->nRecyclable--;
|
||||
return pPage;
|
||||
}
|
||||
|
||||
|
||||
@@ -530,10 +536,12 @@ static int pcache1Init(void *NotUsed){
|
||||
UNUSED_PARAMETER(NotUsed);
|
||||
assert( pcache1.isInit==0 );
|
||||
memset(&pcache1, 0, sizeof(pcache1));
|
||||
#if SQLITE_THREADSAFE
|
||||
if( sqlite3GlobalConfig.bCoreMutex ){
|
||||
pcache1.grp.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU);
|
||||
pcache1.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PMEM);
|
||||
}
|
||||
#endif
|
||||
pcache1.grp.mxPinned = 10;
|
||||
pcache1.isInit = 1;
|
||||
return SQLITE_OK;
|
||||
@@ -729,9 +737,9 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
|
||||
** attempt to allocate a new one.
|
||||
*/
|
||||
if( !pPage ){
|
||||
if( createFlag==1 ) sqlite3BeginBenignMalloc();
|
||||
if( createFlag==1 ){ sqlite3BeginBenignMalloc(); }
|
||||
pPage = pcache1AllocPage(pCache);
|
||||
if( createFlag==1 ) sqlite3EndBenignMalloc();
|
||||
if( createFlag==1 ){ sqlite3EndBenignMalloc(); }
|
||||
}
|
||||
|
||||
if( pPage ){
|
||||
@@ -805,8 +813,13 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
|
||||
** proceed to step 5.
|
||||
**
|
||||
** 5. Otherwise, allocate and return a new page buffer.
|
||||
**
|
||||
** There are two versions of this routine. pcache1FetchWithMutex() is
|
||||
** the general case. pcache1FetchNoMutex() is a faster implementation for
|
||||
** the common case where pGroup->mutex is NULL. The pcache1Fetch() wrapper
|
||||
** invokes the appropriate routine.
|
||||
*/
|
||||
static sqlite3_pcache_page *pcache1Fetch(
|
||||
static PgHdr1 *pcache1FetchNoMutex(
|
||||
sqlite3_pcache *p,
|
||||
unsigned int iKey,
|
||||
int createFlag
|
||||
@@ -814,28 +827,63 @@ static sqlite3_pcache_page *pcache1Fetch(
|
||||
PCache1 *pCache = (PCache1 *)p;
|
||||
PgHdr1 *pPage = 0;
|
||||
|
||||
assert( offsetof(PgHdr1,page)==0 );
|
||||
assert( pCache->bPurgeable || createFlag!=1 );
|
||||
assert( pCache->bPurgeable || pCache->nMin==0 );
|
||||
assert( pCache->bPurgeable==0 || pCache->nMin==10 );
|
||||
assert( pCache->nMin==0 || pCache->bPurgeable );
|
||||
assert( pCache->nHash>0 );
|
||||
pcache1EnterMutex(pCache->pGroup);
|
||||
|
||||
/* Step 1: Search the hash table for an existing entry. */
|
||||
pPage = pCache->apHash[iKey % pCache->nHash];
|
||||
while( pPage && pPage->iKey!=iKey ){ pPage = pPage->pNext; }
|
||||
|
||||
/* Step 2: Abort if no existing page is found and createFlag is 0 */
|
||||
if( pPage ){
|
||||
if( !pPage->isPinned ) pcache1PinPage(pPage);
|
||||
if( !pPage->isPinned ){
|
||||
return pcache1PinPage(pPage);
|
||||
}else{
|
||||
return pPage;
|
||||
}
|
||||
}else if( createFlag ){
|
||||
/* Steps 3, 4, and 5 implemented by this subroutine */
|
||||
pPage = pcache1FetchStage2(pCache, iKey, createFlag);
|
||||
return pcache1FetchStage2(pCache, iKey, createFlag);
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#if PCACHE1_MIGHT_USE_GROUP_MUTEX
|
||||
static PgHdr1 *pcache1FetchWithMutex(
|
||||
sqlite3_pcache *p,
|
||||
unsigned int iKey,
|
||||
int createFlag
|
||||
){
|
||||
PCache1 *pCache = (PCache1 *)p;
|
||||
PgHdr1 *pPage;
|
||||
|
||||
pcache1EnterMutex(pCache->pGroup);
|
||||
pPage = pcache1FetchNoMutex(p, iKey, createFlag);
|
||||
assert( pPage==0 || pCache->iMaxKey>=iKey );
|
||||
pcache1LeaveMutex(pCache->pGroup);
|
||||
return (sqlite3_pcache_page*)pPage;
|
||||
return pPage;
|
||||
}
|
||||
#endif
|
||||
static sqlite3_pcache_page *pcache1Fetch(
|
||||
sqlite3_pcache *p,
|
||||
unsigned int iKey,
|
||||
int createFlag
|
||||
){
|
||||
#if PCACHE1_MIGHT_USE_GROUP_MUTEX || defined(SQLITE_DEBUG)
|
||||
PCache1 *pCache = (PCache1 *)p;
|
||||
#endif
|
||||
|
||||
assert( offsetof(PgHdr1,page)==0 );
|
||||
assert( pCache->bPurgeable || createFlag!=1 );
|
||||
assert( pCache->bPurgeable || pCache->nMin==0 );
|
||||
assert( pCache->bPurgeable==0 || pCache->nMin==10 );
|
||||
assert( pCache->nMin==0 || pCache->bPurgeable );
|
||||
assert( pCache->nHash>0 );
|
||||
#if PCACHE1_MIGHT_USE_GROUP_MUTEX
|
||||
if( pCache->pGroup->mutex ){
|
||||
return (sqlite3_pcache_page*)pcache1FetchWithMutex(p, iKey, createFlag);
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
return (sqlite3_pcache_page*)pcache1FetchNoMutex(p, iKey, createFlag);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1331,6 +1331,13 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
|
||||
}
|
||||
}
|
||||
|
||||
/* If this is part of a compound SELECT, check that it has the right
|
||||
** number of expressions in the select list. */
|
||||
if( p->pNext && p->pEList->nExpr!=p->pNext->pEList->nExpr ){
|
||||
sqlite3SelectWrongNumTermsError(pParse, p->pNext);
|
||||
return WRC_Abort;
|
||||
}
|
||||
|
||||
/* Advance to the next term of the compound
|
||||
*/
|
||||
p = p->pPrior;
|
||||
|
||||
+124
-140
@@ -366,6 +366,12 @@ static void setJoinExpr(Expr *p, int iTable){
|
||||
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
|
||||
ExprSetVVAProperty(p, EP_NoReduce);
|
||||
p->iRightJoinTable = (i16)iTable;
|
||||
if( p->op==TK_FUNCTION && p->x.pList ){
|
||||
int i;
|
||||
for(i=0; i<p->x.pList->nExpr; i++){
|
||||
setJoinExpr(p->x.pList->a[i].pExpr, iTable);
|
||||
}
|
||||
}
|
||||
setJoinExpr(p->pLeft, iTable);
|
||||
p = p->pRight;
|
||||
}
|
||||
@@ -1386,10 +1392,13 @@ static const char *columnTypeImpl(
|
||||
** of the SELECT statement. Return the declaration type and origin
|
||||
** data for the result-set column of the sub-select.
|
||||
*/
|
||||
if( iCol>=0 && iCol<pS->pEList->nExpr ){
|
||||
if( iCol>=0 && ALWAYS(iCol<pS->pEList->nExpr) ){
|
||||
/* If iCol is less than zero, then the expression requests the
|
||||
** rowid of the sub-select or view. This expression is legal (see
|
||||
** test case misc2.2.2) - it always evaluates to NULL.
|
||||
**
|
||||
** The ALWAYS() is because iCol>=pS->pEList->nExpr will have been
|
||||
** caught already by name resolution.
|
||||
*/
|
||||
NameContext sNC;
|
||||
Expr *p = pS->pEList->a[iCol].pExpr;
|
||||
@@ -1868,7 +1877,10 @@ static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){
|
||||
pRet = 0;
|
||||
}
|
||||
assert( iCol>=0 );
|
||||
if( pRet==0 && iCol<p->pEList->nExpr ){
|
||||
/* iCol must be less than p->pEList->nExpr. Otherwise an error would
|
||||
** have been thrown during name resolution and we would not have gotten
|
||||
** this far */
|
||||
if( pRet==0 && ALWAYS(iCol<p->pEList->nExpr) ){
|
||||
pRet = sqlite3ExprCollSeq(pParse, p->pEList->a[iCol].pExpr);
|
||||
}
|
||||
return pRet;
|
||||
@@ -2087,7 +2099,7 @@ static int multiSelectOrderBy(
|
||||
** Error message for when two or more terms of a compound select have different
|
||||
** size result sets.
|
||||
*/
|
||||
static void selectWrongNumTermsError(Parse *pParse, Select *p){
|
||||
void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p){
|
||||
if( p->selFlags & SF_Values ){
|
||||
sqlite3ErrorMsg(pParse, "all VALUES must have the same number of terms");
|
||||
}else{
|
||||
@@ -2113,7 +2125,6 @@ static int multiSelectValues(
|
||||
SelectDest *pDest /* What to do with query results */
|
||||
){
|
||||
Select *pPrior;
|
||||
int nExpr = p->pEList->nExpr;
|
||||
int nRow = 1;
|
||||
int rc = 0;
|
||||
assert( p->selFlags & SF_MultiValue );
|
||||
@@ -2122,10 +2133,7 @@ static int multiSelectValues(
|
||||
assert( p->op==TK_ALL || (p->op==TK_SELECT && p->pPrior==0) );
|
||||
assert( p->pLimit==0 );
|
||||
assert( p->pOffset==0 );
|
||||
if( p->pEList->nExpr!=nExpr ){
|
||||
selectWrongNumTermsError(pParse, p);
|
||||
return 1;
|
||||
}
|
||||
assert( p->pNext==0 || p->pEList->nExpr==p->pNext->pEList->nExpr );
|
||||
if( p->pPrior==0 ) break;
|
||||
assert( p->pPrior->pNext==p );
|
||||
p = p->pPrior;
|
||||
@@ -2234,11 +2242,7 @@ static int multiSelect(
|
||||
** in their result sets.
|
||||
*/
|
||||
assert( p->pEList && pPrior->pEList );
|
||||
if( p->pEList->nExpr!=pPrior->pEList->nExpr ){
|
||||
selectWrongNumTermsError(pParse, p);
|
||||
rc = 1;
|
||||
goto multi_select_end;
|
||||
}
|
||||
assert( p->pEList->nExpr==pPrior->pEList->nExpr );
|
||||
|
||||
#ifndef SQLITE_OMIT_CTE
|
||||
if( p->selFlags & SF_Recursive ){
|
||||
@@ -2857,9 +2861,7 @@ static int multiSelectOrderBy(
|
||||
struct ExprList_item *pItem;
|
||||
for(i=0, pItem=pOrderBy->a; i<nOrderBy; i++, pItem++){
|
||||
assert( pItem->u.x.iOrderByCol>0 );
|
||||
/* assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr ) is also true
|
||||
** but only for well-formed SELECT statements. */
|
||||
testcase( pItem->u.x.iOrderByCol > p->pEList->nExpr );
|
||||
assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr );
|
||||
aPermute[i] = pItem->u.x.iOrderByCol - 1;
|
||||
}
|
||||
pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1);
|
||||
@@ -3429,10 +3431,10 @@ static int flattenSubquery(
|
||||
testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct );
|
||||
testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate );
|
||||
assert( pSub->pSrc!=0 );
|
||||
assert( pSub->pEList->nExpr==pSub1->pEList->nExpr );
|
||||
if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0
|
||||
|| (pSub1->pPrior && pSub1->op!=TK_ALL)
|
||||
|| pSub1->pSrc->nSrc<1
|
||||
|| pSub->pEList->nExpr!=pSub1->pEList->nExpr
|
||||
){
|
||||
return 0;
|
||||
}
|
||||
@@ -3788,121 +3790,6 @@ static int pushDownWhereTerms(
|
||||
}
|
||||
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
|
||||
|
||||
/*
|
||||
** Generate code for all sub-queries in the FROM clause
|
||||
*/
|
||||
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
|
||||
void sqlite3ManifestSubqueries(
|
||||
Parse *pParse, /* Parsing context */
|
||||
Select *p, /* SELECT statement being generated */
|
||||
SrcList *pTabList /* The FROM clause */
|
||||
){
|
||||
int i;
|
||||
sqlite3 *db = pParse->db;
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
for(i=0; i<pTabList->nSrc; i++){
|
||||
struct SrcList_item *pItem = &pTabList->a[i];
|
||||
SelectDest dest;
|
||||
Select *pSub = pItem->pSelect;
|
||||
if( pSub==0 ) continue;
|
||||
|
||||
/* Sometimes the code for a subquery will be generated more than
|
||||
** once, if the subquery is part of the WHERE clause in a LEFT JOIN,
|
||||
** for example. In that case, do not regenerate the code to manifest
|
||||
** a view or the co-routine to implement a view. The first instance
|
||||
** is sufficient, though the subroutine to manifest the view does need
|
||||
** to be invoked again. */
|
||||
if( pItem->addrFillSub ){
|
||||
if( pItem->viaCoroutine==0 ){
|
||||
sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Increment Parse.nHeight by the height of the largest expression
|
||||
** tree referred to by this, the parent select. The child select
|
||||
** may contain expression trees of at most
|
||||
** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit
|
||||
** more conservative than necessary, but much easier than enforcing
|
||||
** an exact limit.
|
||||
*/
|
||||
pParse->nHeight += sqlite3SelectExprHeight(p);
|
||||
|
||||
/* Make copies of constant WHERE-clause terms in the outer query down
|
||||
** inside the subquery. This can help the subquery to run more efficiently.
|
||||
*/
|
||||
if( (pItem->jointype & JT_OUTER)==0
|
||||
&& pushDownWhereTerms(db, pSub, p->pWhere, pItem->iCursor)
|
||||
){
|
||||
#if SELECTTRACE_ENABLED
|
||||
if( sqlite3SelectTrace & 0x100 ){
|
||||
SELECTTRACE(0x100,pParse,p,("After WHERE-clause push-down:\n"));
|
||||
sqlite3TreeViewSelect(0, p, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Generate code to implement the subquery
|
||||
*/
|
||||
if( pTabList->nSrc==1
|
||||
&& (p->selFlags & SF_All)==0
|
||||
&& OptimizationEnabled(db, SQLITE_SubqCoroutine)
|
||||
){
|
||||
/* Implement a co-routine that will return a single row of the result
|
||||
** set on each invocation.
|
||||
*/
|
||||
int addrTop = sqlite3VdbeCurrentAddr(v)+1;
|
||||
pItem->regReturn = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop);
|
||||
VdbeComment((v, "%s", pItem->pTab->zName));
|
||||
pItem->addrFillSub = addrTop;
|
||||
sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
|
||||
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
|
||||
sqlite3Select(pParse, pSub, &dest);
|
||||
pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
|
||||
pItem->viaCoroutine = 1;
|
||||
pItem->regResult = dest.iSdst;
|
||||
sqlite3VdbeAddOp1(v, OP_EndCoroutine, pItem->regReturn);
|
||||
sqlite3VdbeJumpHere(v, addrTop-1);
|
||||
sqlite3ClearTempRegCache(pParse);
|
||||
}else{
|
||||
/* Generate a subroutine that will fill an ephemeral table with
|
||||
** the content of this subquery. pItem->addrFillSub will point
|
||||
** to the address of the generated subroutine. pItem->regReturn
|
||||
** is a register allocated to hold the subroutine return address
|
||||
*/
|
||||
int topAddr;
|
||||
int onceAddr = 0;
|
||||
int retAddr;
|
||||
assert( pItem->addrFillSub==0 );
|
||||
pItem->regReturn = ++pParse->nMem;
|
||||
topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
|
||||
pItem->addrFillSub = topAddr+1;
|
||||
if( pItem->isCorrelated==0 ){
|
||||
/* If the subquery is not correlated and if we are not inside of
|
||||
** a trigger, then we only need to compute the value of the subquery
|
||||
** once. */
|
||||
onceAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v);
|
||||
VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName));
|
||||
}else{
|
||||
VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName));
|
||||
}
|
||||
sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
|
||||
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
|
||||
sqlite3Select(pParse, pSub, &dest);
|
||||
pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
|
||||
if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
|
||||
retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
|
||||
VdbeComment((v, "end %s", pItem->pTab->zName));
|
||||
sqlite3VdbeChangeP1(v, topAddr, retAddr);
|
||||
sqlite3ClearTempRegCache(pParse);
|
||||
}
|
||||
if( db->mallocFailed ) break;
|
||||
pParse->nHeight -= sqlite3SelectExprHeight(p);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Based on the contents of the AggInfo structure indicated by the first
|
||||
** argument, this function checks if the following are true:
|
||||
@@ -4999,13 +4886,110 @@ int sqlite3Select(
|
||||
}
|
||||
#endif
|
||||
|
||||
if( !OptimizationEnabled(db, SQLITE_LateSubquery) ){
|
||||
/* Manifest the subqueries. This needs to be done before calling
|
||||
** sqlite3WhereBegin() so that the Table.nRowLogEst value can be set
|
||||
** correctly for the subqueries. */
|
||||
sqlite3ManifestSubqueries(pParse, p, pTabList);
|
||||
/* Generate code for all sub-queries in the FROM clause
|
||||
*/
|
||||
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
|
||||
for(i=0; i<pTabList->nSrc; i++){
|
||||
struct SrcList_item *pItem = &pTabList->a[i];
|
||||
SelectDest dest;
|
||||
Select *pSub = pItem->pSelect;
|
||||
if( pSub==0 ) continue;
|
||||
|
||||
/* Sometimes the code for a subquery will be generated more than
|
||||
** once, if the subquery is part of the WHERE clause in a LEFT JOIN,
|
||||
** for example. In that case, do not regenerate the code to manifest
|
||||
** a view or the co-routine to implement a view. The first instance
|
||||
** is sufficient, though the subroutine to manifest the view does need
|
||||
** to be invoked again. */
|
||||
if( pItem->addrFillSub ){
|
||||
if( pItem->viaCoroutine==0 ){
|
||||
sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Increment Parse.nHeight by the height of the largest expression
|
||||
** tree referred to by this, the parent select. The child select
|
||||
** may contain expression trees of at most
|
||||
** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit
|
||||
** more conservative than necessary, but much easier than enforcing
|
||||
** an exact limit.
|
||||
*/
|
||||
pParse->nHeight += sqlite3SelectExprHeight(p);
|
||||
|
||||
/* Make copies of constant WHERE-clause terms in the outer query down
|
||||
** inside the subquery. This can help the subquery to run more efficiently.
|
||||
*/
|
||||
if( (pItem->jointype & JT_OUTER)==0
|
||||
&& pushDownWhereTerms(db, pSub, p->pWhere, pItem->iCursor)
|
||||
){
|
||||
#if SELECTTRACE_ENABLED
|
||||
if( sqlite3SelectTrace & 0x100 ){
|
||||
SELECTTRACE(0x100,pParse,p,("After WHERE-clause push-down:\n"));
|
||||
sqlite3TreeViewSelect(0, p, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Generate code to implement the subquery
|
||||
*/
|
||||
if( pTabList->nSrc==1
|
||||
&& (p->selFlags & SF_All)==0
|
||||
&& OptimizationEnabled(db, SQLITE_SubqCoroutine)
|
||||
){
|
||||
/* Implement a co-routine that will return a single row of the result
|
||||
** set on each invocation.
|
||||
*/
|
||||
int addrTop = sqlite3VdbeCurrentAddr(v)+1;
|
||||
pItem->regReturn = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop);
|
||||
VdbeComment((v, "%s", pItem->pTab->zName));
|
||||
pItem->addrFillSub = addrTop;
|
||||
sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
|
||||
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
|
||||
sqlite3Select(pParse, pSub, &dest);
|
||||
pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
|
||||
pItem->viaCoroutine = 1;
|
||||
pItem->regResult = dest.iSdst;
|
||||
sqlite3VdbeAddOp1(v, OP_EndCoroutine, pItem->regReturn);
|
||||
sqlite3VdbeJumpHere(v, addrTop-1);
|
||||
sqlite3ClearTempRegCache(pParse);
|
||||
}else{
|
||||
/* Generate a subroutine that will fill an ephemeral table with
|
||||
** the content of this subquery. pItem->addrFillSub will point
|
||||
** to the address of the generated subroutine. pItem->regReturn
|
||||
** is a register allocated to hold the subroutine return address
|
||||
*/
|
||||
int topAddr;
|
||||
int onceAddr = 0;
|
||||
int retAddr;
|
||||
assert( pItem->addrFillSub==0 );
|
||||
pItem->regReturn = ++pParse->nMem;
|
||||
topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
|
||||
pItem->addrFillSub = topAddr+1;
|
||||
if( pItem->isCorrelated==0 ){
|
||||
/* If the subquery is not correlated and if we are not inside of
|
||||
** a trigger, then we only need to compute the value of the subquery
|
||||
** once. */
|
||||
onceAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v);
|
||||
VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName));
|
||||
}else{
|
||||
VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName));
|
||||
}
|
||||
sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
|
||||
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
|
||||
sqlite3Select(pParse, pSub, &dest);
|
||||
pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
|
||||
if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
|
||||
retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
|
||||
VdbeComment((v, "end %s", pItem->pTab->zName));
|
||||
sqlite3VdbeChangeP1(v, topAddr, retAddr);
|
||||
sqlite3ClearTempRegCache(pParse);
|
||||
}
|
||||
if( db->mallocFailed ) goto select_end;
|
||||
pParse->nHeight -= sqlite3SelectExprHeight(p);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Various elements of the SELECT copied into local variables for
|
||||
** convenience */
|
||||
@@ -5104,7 +5088,7 @@ int sqlite3Select(
|
||||
u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0);
|
||||
|
||||
/* Begin the database scan. */
|
||||
pWInfo = sqlite3WhereBegin(pParse, p, pTabList, pWhere, sSort.pOrderBy,
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, sSort.pOrderBy,
|
||||
p->pEList, wctrlFlags, 0);
|
||||
if( pWInfo==0 ) goto select_end;
|
||||
if( sqlite3WhereOutputRowCount(pWInfo) < p->nSelectRow ){
|
||||
@@ -5260,7 +5244,7 @@ int sqlite3Select(
|
||||
** in the right order to begin with.
|
||||
*/
|
||||
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
|
||||
pWInfo = sqlite3WhereBegin(pParse, p, pTabList, pWhere, pGroupBy, 0,
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0,
|
||||
WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0), 0
|
||||
);
|
||||
if( pWInfo==0 ) goto select_end;
|
||||
@@ -5555,7 +5539,7 @@ int sqlite3Select(
|
||||
** of output.
|
||||
*/
|
||||
resetAccumulator(pParse, &sAggInfo);
|
||||
pWInfo = sqlite3WhereBegin(pParse,p,pTabList, pWhere, pMinMax,0,flag,0);
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMax,0,flag,0);
|
||||
if( pWInfo==0 ){
|
||||
sqlite3ExprListDelete(db, pDel);
|
||||
goto select_end;
|
||||
|
||||
+32
-30
@@ -101,28 +101,26 @@
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
# include <io.h>
|
||||
# include <fcntl.h>
|
||||
#define isatty(h) _isatty(h)
|
||||
#ifndef access
|
||||
# define access(f,m) _access((f),(m))
|
||||
#endif
|
||||
#undef popen
|
||||
#define popen _popen
|
||||
#undef pclose
|
||||
#define pclose _pclose
|
||||
# define isatty(h) _isatty(h)
|
||||
# ifndef access
|
||||
# define access(f,m) _access((f),(m))
|
||||
# endif
|
||||
# undef popen
|
||||
# define popen _popen
|
||||
# undef pclose
|
||||
# define pclose _pclose
|
||||
#else
|
||||
/* Make sure isatty() has a prototype.
|
||||
*/
|
||||
extern int isatty(int);
|
||||
|
||||
#if !defined(__RTP__) && !defined(_WRS_KERNEL)
|
||||
/* popen and pclose are not C89 functions and so are sometimes omitted from
|
||||
** the <stdio.h> header */
|
||||
extern FILE *popen(const char*,const char*);
|
||||
extern int pclose(FILE*);
|
||||
#else
|
||||
# define SQLITE_OMIT_POPEN 1
|
||||
#endif
|
||||
/* Make sure isatty() has a prototype. */
|
||||
extern int isatty(int);
|
||||
|
||||
# if !defined(__RTP__) && !defined(_WRS_KERNEL)
|
||||
/* popen and pclose are not C89 functions and so are
|
||||
** sometimes omitted from the <stdio.h> header */
|
||||
extern FILE *popen(const char*,const char*);
|
||||
extern int pclose(FILE*);
|
||||
# else
|
||||
# define SQLITE_OMIT_POPEN 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32_WCE)
|
||||
@@ -1331,7 +1329,10 @@ static void display_scanstats(
|
||||
sqlite3 *db, /* Database to query */
|
||||
ShellState *pArg /* Pointer to ShellState */
|
||||
){
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
UNUSED_PARAMETER(db);
|
||||
UNUSED_PARAMETER(pArg);
|
||||
#else
|
||||
int i, k, n, mx;
|
||||
fprintf(pArg->out, "-------- scanstats --------\n");
|
||||
mx = 0;
|
||||
@@ -1866,6 +1867,7 @@ static void readfileFunc(
|
||||
long nIn;
|
||||
void *pBuf;
|
||||
|
||||
UNUSED_PARAMETER(argc);
|
||||
zName = (const char*)sqlite3_value_text(argv[0]);
|
||||
if( zName==0 ) return;
|
||||
in = fopen(zName, "rb");
|
||||
@@ -1898,6 +1900,7 @@ static void writefileFunc(
|
||||
sqlite3_int64 rc;
|
||||
const char *zFile;
|
||||
|
||||
UNUSED_PARAMETER(argc);
|
||||
zFile = (const char*)sqlite3_value_text(argv[0]);
|
||||
if( zFile==0 ) return;
|
||||
out = fopen(zFile, "wb");
|
||||
@@ -2577,7 +2580,7 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
|
||||
fprintf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
|
||||
fprintf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
|
||||
fprintf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
|
||||
for(i=0; i<sizeof(aField)/sizeof(aField[0]); i++){
|
||||
for(i=0; i<ArraySize(aField); i++){
|
||||
int ofst = aField[i].ofst;
|
||||
unsigned int val = get4byteInt(aHdr + ofst);
|
||||
fprintf(p->out, "%-20s %u", aField[i].zName, val);
|
||||
@@ -2597,7 +2600,7 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
|
||||
}else{
|
||||
zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_master", zDb);
|
||||
}
|
||||
for(i=0; i<sizeof(aQuery)/sizeof(aQuery[0]); i++){
|
||||
for(i=0; i<ArraySize(aQuery); i++){
|
||||
char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
|
||||
int val = db_int(p, zSql);
|
||||
sqlite3_free(zSql);
|
||||
@@ -3228,7 +3231,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
int i, n2;
|
||||
open_db(p, 0);
|
||||
if( nArg==1 ){
|
||||
for(i=0; i<sizeof(aLimit)/sizeof(aLimit[0]); i++){
|
||||
for(i=0; i<ArraySize(aLimit); i++){
|
||||
printf("%20s %d\n", aLimit[i].zLimitName,
|
||||
sqlite3_limit(p->db, aLimit[i].limitCode, -1));
|
||||
}
|
||||
@@ -3239,7 +3242,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
}else{
|
||||
int iLimit = -1;
|
||||
n2 = strlen30(azArg[1]);
|
||||
for(i=0; i<sizeof(aLimit)/sizeof(aLimit[0]); i++){
|
||||
for(i=0; i<ArraySize(aLimit); i++){
|
||||
if( sqlite3_strnicmp(aLimit[i].zLimitName, azArg[1], n2)==0 ){
|
||||
if( iLimit<0 ){
|
||||
iLimit = i;
|
||||
@@ -3349,9 +3352,8 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
const char *zSavedFilename = p->zDbFilename;
|
||||
char *zNewFilename = 0;
|
||||
p->db = 0;
|
||||
if( nArg>=2 ){
|
||||
p->zDbFilename = zNewFilename = sqlite3_mprintf("%s", azArg[1]);
|
||||
}
|
||||
if( nArg>=2 ) zNewFilename = sqlite3_mprintf("%s", azArg[1]);
|
||||
p->zDbFilename = zNewFilename;
|
||||
open_db(p, 1);
|
||||
if( p->db!=0 ){
|
||||
sqlite3_close(savedDb);
|
||||
@@ -3815,7 +3817,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
/* convert testctrl text option to value. allow any unique prefix
|
||||
** of the option name, or a numerical value. */
|
||||
n2 = strlen30(azArg[1]);
|
||||
for(i=0; i<(int)(sizeof(aCtrl)/sizeof(aCtrl[0])); i++){
|
||||
for(i=0; i<ArraySize(aCtrl); i++){
|
||||
if( strncmp(azArg[1], aCtrl[i].zCtrlName, n2)==0 ){
|
||||
if( testctrl<0 ){
|
||||
testctrl = aCtrl[i].ctrlCode;
|
||||
@@ -4792,7 +4794,7 @@ int SQLITE_CDECL main(int argc, char **argv){
|
||||
sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
|
||||
}
|
||||
}
|
||||
if( zHistory ) shell_read_history(zHistory);
|
||||
if( zHistory ){ shell_read_history(zHistory); }
|
||||
rc = process_input(&data, 0);
|
||||
if( zHistory ){
|
||||
shell_stifle_history(100);
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@
|
||||
**
|
||||
** The official C-language API documentation for SQLite is derived
|
||||
** from comments in this file. This file is the authoritative source
|
||||
** on how SQLite interfaces are suppose to operate.
|
||||
** on how SQLite interfaces are supposed to operate.
|
||||
**
|
||||
** The name of this file under configuration management is "sqlite.h.in".
|
||||
** The makefile makes some minor changes to this file (such as inserting
|
||||
|
||||
+2
-1
@@ -267,7 +267,8 @@ struct sqlite3_api_routines {
|
||||
void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64,
|
||||
void(*)(void*), unsigned char);
|
||||
int (*strglob)(const char*,const char*);
|
||||
sqlite3_value (*value_dup)(const sqlite3_value*);
|
||||
/* Version 3.8.11 and later */
|
||||
sqlite3_value *(*value_dup)(const sqlite3_value*);
|
||||
void (*value_free)(sqlite3_value*);
|
||||
};
|
||||
|
||||
|
||||
+10
-4
@@ -1273,7 +1273,6 @@ struct sqlite3 {
|
||||
#define SQLITE_Transitive 0x0200 /* Transitive constraints */
|
||||
#define SQLITE_OmitNoopJoin 0x0400 /* Omit unused tables in joins */
|
||||
#define SQLITE_Stat34 0x0800 /* Use STAT3 or STAT4 data */
|
||||
#define SQLITE_LateSubquery 0x1000 /* Plan main Q before rendering subQ */
|
||||
#define SQLITE_AllOpts 0xffff /* All optimizations */
|
||||
|
||||
/*
|
||||
@@ -3067,7 +3066,9 @@ int sqlite3CantopenError(int);
|
||||
# define sqlite3Isxdigit(x) isxdigit((unsigned char)(x))
|
||||
# define sqlite3Tolower(x) tolower((unsigned char)(x))
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
|
||||
int sqlite3IsIdChar(u8);
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Internal function prototypes
|
||||
@@ -3095,7 +3096,9 @@ void sqlite3ScratchFree(void*);
|
||||
void *sqlite3PageMalloc(int);
|
||||
void sqlite3PageFree(void*);
|
||||
void sqlite3MemSetDefault(void);
|
||||
#ifndef SQLITE_OMIT_BUILTIN_TEST
|
||||
void sqlite3BenignMallocHooks(void (*)(void), void (*)(void));
|
||||
#endif
|
||||
int sqlite3HeapNearlyFull(void);
|
||||
|
||||
/*
|
||||
@@ -3239,7 +3242,9 @@ int sqlite3BitvecSet(Bitvec*, u32);
|
||||
void sqlite3BitvecClear(Bitvec*, u32, void*);
|
||||
void sqlite3BitvecDestroy(Bitvec*);
|
||||
u32 sqlite3BitvecSize(Bitvec*);
|
||||
#ifndef SQLITE_OMIT_BUILTIN_TEST
|
||||
int sqlite3BitvecBuiltinTest(int,int*);
|
||||
#endif
|
||||
|
||||
RowSet *sqlite3RowSetInit(sqlite3*, void*, unsigned int);
|
||||
void sqlite3RowSetClear(RowSet*);
|
||||
@@ -3286,7 +3291,6 @@ Index *sqlite3AllocateIndexObject(sqlite3*,i16,int,char**);
|
||||
Index *sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
|
||||
Expr*, int, int);
|
||||
void sqlite3DropIndex(Parse*, SrcList*, int);
|
||||
void sqlite3ManifestSubqueries(Parse*, Select*, SrcList*);
|
||||
int sqlite3Select(Parse*, Select*, SelectDest*);
|
||||
Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
|
||||
Expr*,ExprList*,u16,Expr*,Expr*);
|
||||
@@ -3299,8 +3303,7 @@ Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,Expr*,char*);
|
||||
#endif
|
||||
void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
|
||||
void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
|
||||
WhereInfo *sqlite3WhereBegin(Parse*,Select*,SrcList*,Expr*,ExprList*,
|
||||
ExprList*,u16,int);
|
||||
WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int);
|
||||
void sqlite3WhereEnd(WhereInfo*);
|
||||
u64 sqlite3WhereOutputRowCount(WhereInfo*);
|
||||
int sqlite3WhereIsDistinct(WhereInfo*);
|
||||
@@ -3346,8 +3349,10 @@ void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
|
||||
void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
|
||||
int sqlite3FunctionUsesThisSrc(Expr*, SrcList*);
|
||||
Vdbe *sqlite3GetVdbe(Parse*);
|
||||
#ifndef SQLITE_OMIT_BUILTIN_TEST
|
||||
void sqlite3PrngSaveState(void);
|
||||
void sqlite3PrngRestoreState(void);
|
||||
#endif
|
||||
void sqlite3RollbackAll(sqlite3*,int);
|
||||
void sqlite3CodeVerifySchema(Parse*, int);
|
||||
void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb);
|
||||
@@ -3565,6 +3570,7 @@ void sqlite3NestedParse(Parse*, const char*, ...);
|
||||
void sqlite3ExpirePreparedStatements(sqlite3*);
|
||||
int sqlite3CodeSubselect(Parse *, Expr *, int, int);
|
||||
void sqlite3SelectPrep(Parse*, Select*, NameContext*);
|
||||
void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p);
|
||||
int sqlite3MatchSpanName(const char*, const char*, const char*, const char*);
|
||||
int sqlite3ResolveExprNames(NameContext*, Expr*);
|
||||
void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
|
||||
|
||||
@@ -102,7 +102,11 @@ const char sqlite3IsEbcdicIdChar[] = {
|
||||
};
|
||||
#define IdChar(C) (((c=C)>=0x42 && sqlite3IsEbcdicIdChar[c-0x40]))
|
||||
#endif
|
||||
|
||||
/* Make the IdChar function accessible from ctime.c */
|
||||
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
|
||||
int sqlite3IsIdChar(u8 c){ return IdChar(c); }
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
|
||||
+13
-7
@@ -178,25 +178,31 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
|
||||
void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
|
||||
const char *zBinOp = 0; /* Binary operator */
|
||||
const char *zUniOp = 0; /* Unary operator */
|
||||
char zFlgs[30];
|
||||
pView = sqlite3TreeViewPush(pView, moreToFollow);
|
||||
if( pExpr==0 ){
|
||||
sqlite3TreeViewLine(pView, "nil");
|
||||
sqlite3TreeViewPop(pView);
|
||||
return;
|
||||
}
|
||||
if( pExpr->flags ){
|
||||
sqlite3_snprintf(sizeof(zFlgs),zFlgs," flags=0x%x",pExpr->flags);
|
||||
}else{
|
||||
zFlgs[0] = 0;
|
||||
}
|
||||
switch( pExpr->op ){
|
||||
case TK_AGG_COLUMN: {
|
||||
sqlite3TreeViewLine(pView, "AGG{%d:%d}",
|
||||
pExpr->iTable, pExpr->iColumn);
|
||||
sqlite3TreeViewLine(pView, "AGG{%d:%d}%s",
|
||||
pExpr->iTable, pExpr->iColumn, zFlgs);
|
||||
break;
|
||||
}
|
||||
case TK_COLUMN: {
|
||||
if( pExpr->iTable<0 ){
|
||||
/* This only happens when coding check constraints */
|
||||
sqlite3TreeViewLine(pView, "COLUMN(%d)", pExpr->iColumn);
|
||||
sqlite3TreeViewLine(pView, "COLUMN(%d)%s", pExpr->iColumn, zFlgs);
|
||||
}else{
|
||||
sqlite3TreeViewLine(pView, "{%d:%d}",
|
||||
pExpr->iTable, pExpr->iColumn);
|
||||
sqlite3TreeViewLine(pView, "{%d:%d}%s",
|
||||
pExpr->iTable, pExpr->iColumn, zFlgs);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -389,11 +395,11 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
|
||||
}
|
||||
}
|
||||
if( zBinOp ){
|
||||
sqlite3TreeViewLine(pView, "%s", zBinOp);
|
||||
sqlite3TreeViewLine(pView, "%s%s", zBinOp, zFlgs);
|
||||
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
|
||||
sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
|
||||
}else if( zUniOp ){
|
||||
sqlite3TreeViewLine(pView, "%s", zUniOp);
|
||||
sqlite3TreeViewLine(pView, "%s%s", zUniOp, zFlgs);
|
||||
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
|
||||
}
|
||||
sqlite3TreeViewPop(pView);
|
||||
|
||||
+2
-2
@@ -347,7 +347,7 @@ void sqlite3Update(
|
||||
if( HasRowid(pTab) ){
|
||||
sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid);
|
||||
pWInfo = sqlite3WhereBegin(
|
||||
pParse, 0, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED, iIdxCur
|
||||
pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED, iIdxCur
|
||||
);
|
||||
if( pWInfo==0 ) goto update_cleanup;
|
||||
okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
|
||||
@@ -376,7 +376,7 @@ void sqlite3Update(
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, iPk);
|
||||
addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk);
|
||||
sqlite3VdbeSetP4KeyInfo(pParse, pPk);
|
||||
pWInfo = sqlite3WhereBegin(pParse, 0, pTabList, pWhere, 0, 0,
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0,
|
||||
WHERE_ONEPASS_DESIRED, iIdxCur);
|
||||
if( pWInfo==0 ) goto update_cleanup;
|
||||
okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
|
||||
|
||||
+66
-38
@@ -562,6 +562,9 @@ int sqlite3VdbeExec(
|
||||
#ifdef VDBE_PROFILE
|
||||
u64 start; /* CPU clock count at start of opcode */
|
||||
#endif
|
||||
Op *pCtxOp = 0; /* Opcode for which ctx is initialized */
|
||||
sqlite3_context ctx; /* Function call context */
|
||||
|
||||
/*** INSERT STACK UNION HERE ***/
|
||||
|
||||
assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */
|
||||
@@ -582,13 +585,9 @@ int sqlite3VdbeExec(
|
||||
sqlite3VdbeIOTraceSql(p);
|
||||
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
|
||||
if( db->xProgress ){
|
||||
u32 iPrior = p->aCounter[SQLITE_STMTSTATUS_VM_STEP];
|
||||
assert( 0 < db->nProgressOps );
|
||||
nProgressLimit = (unsigned)p->aCounter[SQLITE_STMTSTATUS_VM_STEP];
|
||||
if( nProgressLimit==0 ){
|
||||
nProgressLimit = db->nProgressOps;
|
||||
}else{
|
||||
nProgressLimit %= (unsigned)db->nProgressOps;
|
||||
}
|
||||
nProgressLimit = db->nProgressOps - (iPrior % db->nProgressOps);
|
||||
}
|
||||
#endif
|
||||
#ifdef SQLITE_DEBUG
|
||||
@@ -947,6 +946,7 @@ case OP_Halt: {
|
||||
aOp = p->aOp;
|
||||
aMem = p->aMem;
|
||||
pOp = &aOp[pcx];
|
||||
pCtxOp = 0;
|
||||
break;
|
||||
}
|
||||
p->rc = pOp->p1;
|
||||
@@ -1570,35 +1570,39 @@ case OP_CollSeq: {
|
||||
case OP_Function: {
|
||||
int i;
|
||||
Mem *pArg;
|
||||
sqlite3_context ctx;
|
||||
sqlite3_value **apVal;
|
||||
int n;
|
||||
|
||||
n = pOp->p5;
|
||||
apVal = p->apArg;
|
||||
assert( apVal || n==0 );
|
||||
assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
|
||||
ctx.pOut = &aMem[pOp->p3];
|
||||
memAboutToChange(p, ctx.pOut);
|
||||
if( pOp!=pCtxOp ){
|
||||
apVal = p->apArg;
|
||||
assert( apVal || n==0 );
|
||||
assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
|
||||
ctx.pOut = &aMem[pOp->p3];
|
||||
|
||||
assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) );
|
||||
assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
|
||||
pArg = &aMem[pOp->p2];
|
||||
for(i=0; i<n; i++, pArg++){
|
||||
assert( memIsValid(pArg) );
|
||||
apVal[i] = pArg;
|
||||
Deephemeralize(pArg);
|
||||
REGISTER_TRACE(pOp->p2+i, pArg);
|
||||
assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) );
|
||||
assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
|
||||
pArg = &aMem[pOp->p2];
|
||||
for(i=0; i<n; i++, pArg++){
|
||||
apVal[i] = pArg;
|
||||
}
|
||||
assert( pOp->p4type==P4_FUNCDEF );
|
||||
ctx.pFunc = pOp->p4.pFunc;
|
||||
ctx.iOp = (int)(pOp - aOp);
|
||||
ctx.pVdbe = p;
|
||||
pCtxOp = pOp;
|
||||
}
|
||||
|
||||
assert( pOp->p4type==P4_FUNCDEF );
|
||||
ctx.pFunc = pOp->p4.pFunc;
|
||||
ctx.iOp = (int)(pOp - aOp);
|
||||
ctx.pVdbe = p;
|
||||
#ifdef SQLITE_DEBUG
|
||||
for(i=0; i<n; i++){
|
||||
assert( memIsValid(p->apArg[i]) );
|
||||
REGISTER_TRACE(pOp->p2+i, p->apArg[i]);
|
||||
}
|
||||
#endif
|
||||
memAboutToChange(p, ctx.pOut);
|
||||
MemSetTypeFlag(ctx.pOut, MEM_Null);
|
||||
ctx.fErrorOrAux = 0;
|
||||
db->lastRowid = lastRowid;
|
||||
(*ctx.pFunc->xFunc)(&ctx, n, apVal); /* IMP: R-24505-23230 */
|
||||
(*ctx.pFunc->xFunc)(&ctx, n, p->apArg); /* IMP: R-24505-23230 */
|
||||
lastRowid = db->lastRowid; /* Remember rowid changes made by xFunc */
|
||||
|
||||
/* If the function returned an error, throw an exception */
|
||||
@@ -3511,6 +3515,26 @@ case OP_Close: {
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
|
||||
/* Opcode: ColumnsUsed P1 * * P4 *
|
||||
**
|
||||
** This opcode (which only exists if SQLite was compiled with
|
||||
** SQLITE_ENABLE_COLUMN_USED_MASK) identifies which columns of the
|
||||
** table or index for cursor P1 are used. P4 is a 64-bit integer
|
||||
** (P4_INT64) in which the first 63 bits are one for each of the
|
||||
** first 63 columns of the table or index that are actually used
|
||||
** by the cursor. The high-order bit is set if any column after
|
||||
** the 64th is used.
|
||||
*/
|
||||
case OP_ColumnsUsed: {
|
||||
VdbeCursor *pC;
|
||||
pC = p->apCsr[pOp->p1];
|
||||
assert( pC->pCursor );
|
||||
pC->maskUsed = *(u64*)pOp->p4.pI64;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Opcode: SeekGE P1 P2 P3 P4 *
|
||||
** Synopsis: key=r[P3@P4]
|
||||
**
|
||||
@@ -5488,6 +5512,7 @@ case OP_Program: { /* jump */
|
||||
p->nCursor = (u16)pFrame->nChildCsr;
|
||||
p->apCsr = (VdbeCursor **)&aMem[p->nMem+1];
|
||||
p->aOp = aOp = pProgram->aOp;
|
||||
pCtxOp = 0;
|
||||
p->nOp = pProgram->nOp;
|
||||
p->aOnceFlag = (u8 *)&p->apCsr[p->nCursor];
|
||||
p->nOnceFlag = pProgram->nOnce;
|
||||
@@ -5698,12 +5723,13 @@ case OP_AggStep: {
|
||||
Mem *pMem;
|
||||
Mem *pRec;
|
||||
Mem t;
|
||||
sqlite3_context ctx;
|
||||
sqlite3_context actx;
|
||||
sqlite3_value **apVal;
|
||||
|
||||
n = pOp->p5;
|
||||
assert( n>=0 );
|
||||
pRec = &aMem[pOp->p2];
|
||||
pCtxOp = 0;
|
||||
apVal = p->apArg;
|
||||
assert( apVal || n==0 );
|
||||
for(i=0; i<n; i++, pRec++){
|
||||
@@ -5711,22 +5737,22 @@ case OP_AggStep: {
|
||||
apVal[i] = pRec;
|
||||
memAboutToChange(p, pRec);
|
||||
}
|
||||
ctx.pFunc = pOp->p4.pFunc;
|
||||
actx.pFunc = pOp->p4.pFunc;
|
||||
assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
|
||||
ctx.pMem = pMem = &aMem[pOp->p3];
|
||||
actx.pMem = pMem = &aMem[pOp->p3];
|
||||
pMem->n++;
|
||||
sqlite3VdbeMemInit(&t, db, MEM_Null);
|
||||
ctx.pOut = &t;
|
||||
ctx.isError = 0;
|
||||
ctx.pVdbe = p;
|
||||
ctx.iOp = (int)(pOp - aOp);
|
||||
ctx.skipFlag = 0;
|
||||
(ctx.pFunc->xStep)(&ctx, n, apVal); /* IMP: R-24505-23230 */
|
||||
if( ctx.isError ){
|
||||
actx.pOut = &t;
|
||||
actx.isError = 0;
|
||||
actx.pVdbe = p;
|
||||
actx.iOp = (int)(pOp - aOp);
|
||||
actx.skipFlag = 0;
|
||||
(actx.pFunc->xStep)(&actx, n, apVal); /* IMP: R-24505-23230 */
|
||||
if( actx.isError ){
|
||||
sqlite3VdbeError(p, "%s", sqlite3_value_text(&t));
|
||||
rc = ctx.isError;
|
||||
rc = actx.isError;
|
||||
}
|
||||
if( ctx.skipFlag ){
|
||||
if( actx.skipFlag ){
|
||||
assert( pOp[-1].opcode==OP_CollSeq );
|
||||
i = pOp[-1].p1;
|
||||
if( i ) sqlite3VdbeMemSetInt64(&aMem[i], 1);
|
||||
@@ -6156,6 +6182,7 @@ case OP_VFilter: { /* jump */
|
||||
for(i = 0; i<nArg; i++){
|
||||
apArg[i] = &pArgc[i+1];
|
||||
}
|
||||
pCtxOp = 0;
|
||||
rc = pModule->xFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg);
|
||||
sqlite3VtabImportErrmsg(p, pVtab);
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -6339,6 +6366,7 @@ case OP_VUpdate: {
|
||||
if( ALWAYS(pModule->xUpdate) ){
|
||||
u8 vtabOnConflict = db->vtabOnConflict;
|
||||
apArg = p->apArg;
|
||||
pCtxOp = 0;
|
||||
pX = &aMem[pOp->p3];
|
||||
for(i=0; i<nArg; i++){
|
||||
assert( memIsValid(pX) );
|
||||
|
||||
@@ -169,6 +169,7 @@ int sqlite3VdbeAddOp1(Vdbe*,int,int);
|
||||
int sqlite3VdbeAddOp2(Vdbe*,int,int,int);
|
||||
int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int);
|
||||
int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int);
|
||||
int sqlite3VdbeAddOp4Dup8(Vdbe*,int,int,int,int,const u8*,int);
|
||||
int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
|
||||
int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp, int iLineno);
|
||||
void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
|
||||
|
||||
@@ -83,6 +83,9 @@ struct VdbeCursor {
|
||||
i64 seqCount; /* Sequence counter */
|
||||
i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
|
||||
VdbeSorter *pSorter; /* Sorter object for OP_SorterOpen cursors */
|
||||
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
|
||||
u64 maskUsed; /* Mask of columns used by this cursor */
|
||||
#endif
|
||||
|
||||
/* Cached information about the header for the data record that the
|
||||
** cursor is currently pointing to. Only valid if cacheStatus matches
|
||||
|
||||
+29
-3
@@ -233,6 +233,23 @@ int sqlite3VdbeAddOp4(
|
||||
return addr;
|
||||
}
|
||||
|
||||
/*
|
||||
** Add an opcode that includes the p4 value with a P4_INT64 type.
|
||||
*/
|
||||
int sqlite3VdbeAddOp4Dup8(
|
||||
Vdbe *p, /* Add the opcode to this VM */
|
||||
int op, /* The new opcode */
|
||||
int p1, /* The P1 operand */
|
||||
int p2, /* The P2 operand */
|
||||
int p3, /* The P3 operand */
|
||||
const u8 *zP4, /* The P4 operand */
|
||||
int p4type /* P4 operand type */
|
||||
){
|
||||
char *p4copy = sqlite3DbMallocRaw(sqlite3VdbeDb(p), 8);
|
||||
if( p4copy ) memcpy(p4copy, zP4, 8);
|
||||
return sqlite3VdbeAddOp4(p, op, p1, p2, p3, p4copy, p4type);
|
||||
}
|
||||
|
||||
/*
|
||||
** Add an OP_ParseSchema opcode. This routine is broken out from
|
||||
** sqlite3VdbeAddOp4() since it needs to also needs to mark all btrees
|
||||
@@ -397,6 +414,7 @@ static Op *opIterNext(VdbeOpIter *p){
|
||||
** * OP_VUpdate
|
||||
** * OP_VRename
|
||||
** * OP_FkCounter with P2==0 (immediate foreign key constraint)
|
||||
** * OP_CreateTable and OP_InitCoroutine (for CREATE TABLE AS SELECT ...)
|
||||
**
|
||||
** Then check that the value of Parse.mayAbort is true if an
|
||||
** ABORT may be thrown, or false otherwise. Return true if it does
|
||||
@@ -408,6 +426,8 @@ static Op *opIterNext(VdbeOpIter *p){
|
||||
int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
|
||||
int hasAbort = 0;
|
||||
int hasFkCounter = 0;
|
||||
int hasCreateTable = 0;
|
||||
int hasInitCoroutine = 0;
|
||||
Op *pOp;
|
||||
VdbeOpIter sIter;
|
||||
memset(&sIter, 0, sizeof(sIter));
|
||||
@@ -422,6 +442,8 @@ int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
|
||||
hasAbort = 1;
|
||||
break;
|
||||
}
|
||||
if( opcode==OP_CreateTable ) hasCreateTable = 1;
|
||||
if( opcode==OP_InitCoroutine ) hasInitCoroutine = 1;
|
||||
#ifndef SQLITE_OMIT_FOREIGN_KEY
|
||||
if( opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1 ){
|
||||
hasFkCounter = 1;
|
||||
@@ -435,7 +457,8 @@ int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
|
||||
** through all opcodes and hasAbort may be set incorrectly. Return
|
||||
** true for this case to prevent the assert() in the callers frame
|
||||
** from failing. */
|
||||
return ( v->db->mallocFailed || hasAbort==mayAbort || hasFkCounter );
|
||||
return ( v->db->mallocFailed || hasAbort==mayAbort || hasFkCounter
|
||||
|| (hasCreateTable && hasInitCoroutine) );
|
||||
}
|
||||
#endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */
|
||||
|
||||
@@ -1218,12 +1241,11 @@ void sqlite3VdbeEnter(Vdbe *p){
|
||||
/*
|
||||
** Unlock all of the btrees previously locked by a call to sqlite3VdbeEnter().
|
||||
*/
|
||||
void sqlite3VdbeLeave(Vdbe *p){
|
||||
static SQLITE_NOINLINE void vdbeLeave(Vdbe *p){
|
||||
int i;
|
||||
sqlite3 *db;
|
||||
Db *aDb;
|
||||
int nDb;
|
||||
if( DbMaskAllZero(p->lockMask) ) return; /* The common case */
|
||||
db = p->db;
|
||||
aDb = db->aDb;
|
||||
nDb = db->nDb;
|
||||
@@ -1233,6 +1255,10 @@ void sqlite3VdbeLeave(Vdbe *p){
|
||||
}
|
||||
}
|
||||
}
|
||||
void sqlite3VdbeLeave(Vdbe *p){
|
||||
if( DbMaskAllZero(p->lockMask) ) return; /* The common case */
|
||||
vdbeLeave(p);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
|
||||
|
||||
+46
-21
@@ -777,10 +777,15 @@ void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){
|
||||
** pFrom->z is used, then pTo->z points to the same thing as pFrom->z
|
||||
** and flags gets srcType (either MEM_Ephem or MEM_Static).
|
||||
*/
|
||||
static SQLITE_NOINLINE void vdbeClrCopy(Mem *pTo, const Mem *pFrom, int eType){
|
||||
vdbeMemClearExternAndSetNull(pTo);
|
||||
assert( !VdbeMemDynamic(pTo) );
|
||||
sqlite3VdbeMemShallowCopy(pTo, pFrom, eType);
|
||||
}
|
||||
void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
|
||||
assert( (pFrom->flags & MEM_RowSet)==0 );
|
||||
assert( pTo->db==pFrom->db );
|
||||
if( VdbeMemDynamic(pTo) ) vdbeMemClearExternAndSetNull(pTo);
|
||||
if( VdbeMemDynamic(pTo) ){ vdbeClrCopy(pTo,pFrom,srcType); return; }
|
||||
memcpy(pTo, pFrom, MEMCELLSIZE);
|
||||
if( (pFrom->flags&MEM_Static)==0 ){
|
||||
pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem);
|
||||
@@ -946,6 +951,32 @@ int sqlite3VdbeMemSetStr(
|
||||
** If this routine fails for any reason (malloc returns NULL or unable
|
||||
** to read from the disk) then the pMem is left in an inconsistent state.
|
||||
*/
|
||||
static SQLITE_NOINLINE int vdbeMemFromBtreeResize(
|
||||
BtCursor *pCur, /* Cursor pointing at record to retrieve. */
|
||||
u32 offset, /* Offset from the start of data to return bytes from. */
|
||||
u32 amt, /* Number of bytes to return. */
|
||||
int key, /* If true, retrieve from the btree key, not data. */
|
||||
Mem *pMem /* OUT: Return data in this Mem structure. */
|
||||
){
|
||||
int rc;
|
||||
pMem->flags = MEM_Null;
|
||||
if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+2)) ){
|
||||
if( key ){
|
||||
rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z);
|
||||
}else{
|
||||
rc = sqlite3BtreeData(pCur, offset, amt, pMem->z);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
pMem->z[amt] = 0;
|
||||
pMem->z[amt+1] = 0;
|
||||
pMem->flags = MEM_Blob|MEM_Term;
|
||||
pMem->n = (int)amt;
|
||||
}else{
|
||||
sqlite3VdbeMemRelease(pMem);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
int sqlite3VdbeMemFromBtree(
|
||||
BtCursor *pCur, /* Cursor pointing at record to retrieve. */
|
||||
u32 offset, /* Offset from the start of data to return bytes from. */
|
||||
@@ -975,22 +1006,7 @@ int sqlite3VdbeMemFromBtree(
|
||||
pMem->flags = MEM_Blob|MEM_Ephem;
|
||||
pMem->n = (int)amt;
|
||||
}else{
|
||||
pMem->flags = MEM_Null;
|
||||
if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+2)) ){
|
||||
if( key ){
|
||||
rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z);
|
||||
}else{
|
||||
rc = sqlite3BtreeData(pCur, offset, amt, pMem->z);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
pMem->z[amt] = 0;
|
||||
pMem->z[amt+1] = 0;
|
||||
pMem->flags = MEM_Blob|MEM_Term;
|
||||
pMem->n = (int)amt;
|
||||
}else{
|
||||
sqlite3VdbeMemRelease(pMem);
|
||||
}
|
||||
}
|
||||
rc = vdbeMemFromBtreeResize(pCur, offset, amt, key, pMem);
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -1678,17 +1694,26 @@ void sqlite3ValueFree(sqlite3_value *v){
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the number of bytes in the sqlite3_value object assuming
|
||||
** that it uses the encoding "enc"
|
||||
** The sqlite3ValueBytes() routine returns the number of bytes in the
|
||||
** sqlite3_value object assuming that it uses the encoding "enc".
|
||||
** The valueBytes() routine is a helper function.
|
||||
*/
|
||||
static SQLITE_NOINLINE int valueBytes(sqlite3_value *pVal, u8 enc){
|
||||
return valueToText(pVal, enc)!=0 ? pVal->n : 0;
|
||||
}
|
||||
int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){
|
||||
Mem *p = (Mem*)pVal;
|
||||
if( (p->flags & MEM_Blob)!=0 || sqlite3ValueText(pVal, enc) ){
|
||||
assert( (p->flags & MEM_Null)==0 || (p->flags & (MEM_Str|MEM_Blob))==0 );
|
||||
if( (p->flags & MEM_Str)!=0 && pVal->enc==enc ){
|
||||
return p->n;
|
||||
}
|
||||
if( (p->flags & MEM_Blob)!=0 ){
|
||||
if( p->flags & MEM_Zero ){
|
||||
return p->n + p->u.nZero;
|
||||
}else{
|
||||
return p->n;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
if( p->flags & MEM_Null ) return 0;
|
||||
return valueBytes(pVal, enc);
|
||||
}
|
||||
|
||||
+22
-15
@@ -2555,16 +2555,15 @@ static int whereLoopAddBtree(
|
||||
/* TUNING: One-time cost for computing the automatic index is
|
||||
** estimated to be X*N*log2(N) where N is the number of rows in
|
||||
** the table being indexed and where X is 7 (LogEst=28) for normal
|
||||
** tables or 0.3333 (LogEst=-16) for views and subqueries. The value
|
||||
** tables or 1.375 (LogEst=4) for views and subqueries. The value
|
||||
** of X is smaller for views and subqueries so that the query planner
|
||||
** will be more aggressive about generating automatic indexes for
|
||||
** those objects, since there is no opportunity to add schema
|
||||
** indexes on subqueries and views. */
|
||||
pNew->rSetup = rLogSize + rSize - 16;
|
||||
pNew->rSetup = rLogSize + rSize + 4;
|
||||
if( pTab->pSelect==0 && (pTab->tabFlags & TF_Ephemeral)==0 ){
|
||||
pNew->rSetup += 44;
|
||||
pNew->rSetup += 24;
|
||||
}
|
||||
if( pNew->rSetup<1 ) pNew->rSetup = 1;
|
||||
ApplyCostMultiplier(pNew->rSetup, pTab->costMult);
|
||||
/* TUNING: Each index lookup yields 20 rows in the table. This
|
||||
** is more than the usual guess of 10 rows, since we have no way
|
||||
@@ -3897,7 +3896,6 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
|
||||
*/
|
||||
WhereInfo *sqlite3WhereBegin(
|
||||
Parse *pParse, /* The parser context */
|
||||
Select *pSelect, /* SELECT stmt that owns this WHERE. Might be NULL */
|
||||
SrcList *pTabList, /* FROM clause: A list of all tables to be scanned */
|
||||
Expr *pWhere, /* The WHERE clause */
|
||||
ExprList *pOrderBy, /* An ORDER BY (or GROUP BY) clause, or NULL */
|
||||
@@ -4172,16 +4170,6 @@ WhereInfo *sqlite3WhereBegin(
|
||||
}
|
||||
}
|
||||
|
||||
/* If this WHERE clause is part of a SELECT statement, then there
|
||||
** might be subqueries in the FROM clause that need to be manifested.
|
||||
** This works mostly - except the Table.nRowLogEst value is not set
|
||||
** correctly for the subquery, resulting in a bad plan in some cases.
|
||||
*/
|
||||
if( OptimizationEnabled(db, SQLITE_LateSubquery) && pSelect!=0 ){
|
||||
sqlite3ManifestSubqueries(pParse, pSelect, pTabList);
|
||||
if( db->mallocFailed ) goto whereBeginError;
|
||||
}
|
||||
|
||||
/* Open all tables in the pTabList and any indices selected for
|
||||
** searching those tables.
|
||||
*/
|
||||
@@ -4225,6 +4213,10 @@ WhereInfo *sqlite3WhereBegin(
|
||||
SQLITE_INT_TO_PTR(n), P4_INT32);
|
||||
assert( n<=pTab->nCol );
|
||||
}
|
||||
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
|
||||
sqlite3VdbeAddOp4Dup8(v, OP_ColumnsUsed, pTabItem->iCursor, 0, 0,
|
||||
(const u8*)&pTabItem->colUsed, P4_INT64);
|
||||
#endif
|
||||
}else{
|
||||
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
|
||||
}
|
||||
@@ -4270,6 +4262,21 @@ WhereInfo *sqlite3WhereBegin(
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ); /* Hint to COMDB2 */
|
||||
}
|
||||
VdbeComment((v, "%s", pIx->zName));
|
||||
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
|
||||
{
|
||||
u64 colUsed = 0;
|
||||
int ii, jj;
|
||||
for(ii=0; ii<pIx->nColumn; ii++){
|
||||
jj = pIx->aiColumn[ii];
|
||||
if( jj<0 ) continue;
|
||||
if( jj>63 ) jj = 63;
|
||||
if( (pTabItem->colUsed & MASKBIT(jj))==0 ) continue;
|
||||
colUsed |= ((u64)1)<<(ii<63 ? ii : 63);
|
||||
}
|
||||
sqlite3VdbeAddOp4Dup8(v, OP_ColumnsUsed, iIndexCur, 0, 0,
|
||||
(u8*)&colUsed, P4_INT64);
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_COLUMN_USED_MASK */
|
||||
}
|
||||
}
|
||||
if( iDb>=0 ) sqlite3CodeVerifySchema(pParse, iDb);
|
||||
|
||||
+1
-1
@@ -1265,7 +1265,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
}
|
||||
/* Loop through table entries that match term pOrTerm. */
|
||||
WHERETRACE(0xffff, ("Subplan for OR-clause:\n"));
|
||||
pSubWInfo = sqlite3WhereBegin(pParse, 0, pOrTab, pOrExpr, 0, 0,
|
||||
pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
|
||||
wctrlFlags, iCovCur);
|
||||
assert( pSubWInfo || pParse->nErr || db->mallocFailed );
|
||||
if( pSubWInfo ){
|
||||
|
||||
+1
-1
@@ -204,7 +204,7 @@ do_execsql_test 6.0 {
|
||||
} {}
|
||||
do_test 6.1 {
|
||||
db close
|
||||
hexio_write test.db 616 EAFFFFFF0202
|
||||
hexio_write test.db 616 8FFFFFFF7F02
|
||||
sqlite3 db test.db
|
||||
breakpoint
|
||||
execsql { DELETE FROM t1 WHERE rowid=2 }
|
||||
|
||||
+10
-10
@@ -81,31 +81,31 @@ do_eqp_test 1.6 {
|
||||
do_eqp_test 1.7 {
|
||||
SELECT * FROM t3 JOIN (SELECT 1)
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t3}
|
||||
0 1 1 {SCAN SUBQUERY 1}
|
||||
0 0 1 {SCAN SUBQUERY 1}
|
||||
0 1 0 {SCAN TABLE t3}
|
||||
}
|
||||
do_eqp_test 1.8 {
|
||||
SELECT * FROM t3 JOIN (SELECT 1 UNION SELECT 2)
|
||||
} {
|
||||
1 0 0 {COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (UNION)}
|
||||
0 0 0 {SCAN TABLE t3}
|
||||
0 1 1 {SCAN SUBQUERY 1}
|
||||
0 0 1 {SCAN SUBQUERY 1}
|
||||
0 1 0 {SCAN TABLE t3}
|
||||
}
|
||||
do_eqp_test 1.9 {
|
||||
SELECT * FROM t3 JOIN (SELECT 1 EXCEPT SELECT a FROM t3 LIMIT 17)
|
||||
} {
|
||||
3 0 0 {SCAN TABLE t3}
|
||||
1 0 0 {COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (EXCEPT)}
|
||||
0 0 0 {SCAN TABLE t3}
|
||||
0 1 1 {SCAN SUBQUERY 1}
|
||||
0 0 1 {SCAN SUBQUERY 1}
|
||||
0 1 0 {SCAN TABLE t3}
|
||||
}
|
||||
do_eqp_test 1.10 {
|
||||
SELECT * FROM t3 JOIN (SELECT 1 INTERSECT SELECT a FROM t3 LIMIT 17)
|
||||
} {
|
||||
3 0 0 {SCAN TABLE t3}
|
||||
1 0 0 {COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (INTERSECT)}
|
||||
0 0 0 {SCAN TABLE t3}
|
||||
0 1 1 {SCAN SUBQUERY 1}
|
||||
0 0 1 {SCAN SUBQUERY 1}
|
||||
0 1 0 {SCAN TABLE t3}
|
||||
}
|
||||
|
||||
do_eqp_test 1.11 {
|
||||
@@ -113,8 +113,8 @@ do_eqp_test 1.11 {
|
||||
} {
|
||||
3 0 0 {SCAN TABLE t3}
|
||||
1 0 0 {COMPOUND SUBQUERIES 2 AND 3 (UNION ALL)}
|
||||
0 0 0 {SCAN TABLE t3}
|
||||
0 1 1 {SCAN SUBQUERY 1}
|
||||
0 0 1 {SCAN SUBQUERY 1}
|
||||
0 1 0 {SCAN TABLE t3}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
+12
-2
@@ -362,11 +362,17 @@ ifcapable icu { lappend tokenizers icu }
|
||||
# Some tests to check that the tokenizers can both identify white-space
|
||||
# codepoints. All codepoints tested below are of type "Zs" in the
|
||||
# UnicodeData.txt file.
|
||||
#
|
||||
# Note that codepoint 6158 has changed from Zs to Cf in recent versions
|
||||
# of UnicodeData.txt. So take that into account for the "icu" tests.
|
||||
#
|
||||
foreach T $tokenizers {
|
||||
do_isspace_test 6.$T.1 $T 32
|
||||
do_isspace_test 6.$T.2 $T 160
|
||||
do_isspace_test 6.$T.3 $T 5760
|
||||
do_isspace_test 6.$T.4 $T 6158
|
||||
if {$T!="icu"} {
|
||||
do_isspace_test 6.$T.4 $T 6158
|
||||
}
|
||||
do_isspace_test 6.$T.5 $T 8192
|
||||
do_isspace_test 6.$T.6 $T 8193
|
||||
do_isspace_test 6.$T.7 $T 8194
|
||||
@@ -382,7 +388,11 @@ foreach T $tokenizers {
|
||||
do_isspace_test 6.$T.17 $T 8287
|
||||
do_isspace_test 6.$T.18 $T 12288
|
||||
|
||||
do_isspace_test 6.$T.19 $T {32 160 5760 6158}
|
||||
if {$T!="icu"} {
|
||||
do_isspace_test 6.$T.19 $T {32 160 5760 6158}
|
||||
} else {
|
||||
do_isspace_test 6.$T.19 $T {32 160 5760 8192}
|
||||
}
|
||||
do_isspace_test 6.$T.20 $T {8192 8193 8194 8195}
|
||||
do_isspace_test 6.$T.21 $T {8196 8197 8198 8199}
|
||||
do_isspace_test 6.$T.22 $T {8200 8201 8202 8239}
|
||||
|
||||
+154
-11
@@ -10,8 +10,8 @@
|
||||
**
|
||||
*************************************************************************
|
||||
**
|
||||
** This is a utility program designed to aid running regressions tests
|
||||
** on SQLite library using data from an external fuzzer, such as American
|
||||
** This is a utility program designed to aid running regressions tests on
|
||||
** the SQLite library using data from an external fuzzer, such as American
|
||||
** Fuzzy Lop (AFL) (http://lcamtuf.coredump.cx/afl/).
|
||||
**
|
||||
** This program reads content from an SQLite database file with the following
|
||||
@@ -25,16 +25,44 @@
|
||||
** sqlid INTEGER PRIMARY KEY, -- SQL script id
|
||||
** sqltext TEXT -- Text of SQL statements to run
|
||||
** );
|
||||
** CREATE TABLE IF NOT EXISTS readme(
|
||||
** msg TEXT -- Human-readable description of this test collection
|
||||
** );
|
||||
**
|
||||
** For each database file in the DB table, the SQL text in the XSQL table
|
||||
** is run against that database. This program is looking for crashes,
|
||||
** assertion faults, and/or memory leaks. No attempt is made to verify
|
||||
** the output. The assumption is that either all of the database files
|
||||
** or all of the SQL statements are malformed inputs, generated by a fuzzer,
|
||||
** that need to be checked to make sure they do not present a security risk.
|
||||
** is run against that database. All README.MSG values are printed prior
|
||||
** to the start of the test (unless the --quiet option is used). If the
|
||||
** DB table is empty, then all entries in XSQL are run against an empty
|
||||
** in-memory database.
|
||||
**
|
||||
** This program is looking for crashes, assertion faults, and/or memory leaks.
|
||||
** No attempt is made to verify the output. The assumption is that either all
|
||||
** of the database files or all of the SQL statements are malformed inputs,
|
||||
** generated by a fuzzer, that need to be checked to make sure they do not
|
||||
** present a security risk.
|
||||
**
|
||||
** This program also includes some command-line options to help with
|
||||
** creation and maintenance of the source content database.
|
||||
** creation and maintenance of the source content database. The command
|
||||
**
|
||||
** ./fuzzcheck database.db --load-sql FILE...
|
||||
**
|
||||
** Loads all FILE... arguments into the XSQL table. The --load-db option
|
||||
** works the same but loads the files into the DB table. The -m option can
|
||||
** be used to initialize the README table. The "database.db" file is created
|
||||
** if it does not previously exist. Example:
|
||||
**
|
||||
** ./fuzzcheck new.db --load-sql *.sql
|
||||
** ./fuzzcheck new.db --load-db *.db
|
||||
** ./fuzzcheck new.db -m 'New test cases'
|
||||
**
|
||||
** The three commands above will create the "new.db" file and initialize all
|
||||
** tables. Then do "./fuzzcheck new.db" to run the tests.
|
||||
**
|
||||
** DEBUGGING HINTS:
|
||||
**
|
||||
** If fuzzcheck does crash, it can be run in the debugger and the content
|
||||
** of the global variable g.zTextName[] will identify the specific XSQL and
|
||||
** DB values that were running when the crash occurred.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -43,6 +71,11 @@
|
||||
#include <ctype.h>
|
||||
#include "sqlite3.h"
|
||||
|
||||
#ifdef __unix__
|
||||
# include <signal.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Files in the virtual file system.
|
||||
*/
|
||||
@@ -111,6 +144,43 @@ static void fatalError(const char *zFormat, ...){
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
** Timeout handler
|
||||
*/
|
||||
#ifdef __unix__
|
||||
static void timeoutHandler(int NotUsed){
|
||||
(void)NotUsed;
|
||||
fatalError("timeout\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Set the an alarm to go off after N seconds. Disable the alarm
|
||||
** if N==0
|
||||
*/
|
||||
static void setAlarm(int N){
|
||||
#ifdef __unix__
|
||||
alarm(N);
|
||||
#else
|
||||
(void)N;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
|
||||
/*
|
||||
** This an SQL progress handler. After an SQL statement has run for
|
||||
** many steps, we want to interrupt it. This guards against infinite
|
||||
** loops from recursive common table expressions.
|
||||
**
|
||||
** *pVdbeLimitFlag is true if the --limit-vdbe command-line option is used.
|
||||
** In that case, hitting the progress handler is a fatal error.
|
||||
*/
|
||||
static int progressHandler(void *pVdbeLimitFlag){
|
||||
if( *(int*)pVdbeLimitFlag ) fatalError("too many VDBE cycles");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Reallocate memory. Show and error and quit if unable.
|
||||
*/
|
||||
@@ -587,6 +657,31 @@ static void runSql(sqlite3 *db, const char *zSql, unsigned runFlags){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Rebuild the database file.
|
||||
**
|
||||
** (1) Remove duplicate entries
|
||||
** (2) Put all entries in order
|
||||
** (3) Vacuum
|
||||
*/
|
||||
static void rebuild_database(sqlite3 *db){
|
||||
int rc;
|
||||
rc = sqlite3_exec(db,
|
||||
"BEGIN;\n"
|
||||
"CREATE TEMP TABLE dbx AS SELECT DISTINCT dbcontent FROM db;\n"
|
||||
"DELETE FROM db;\n"
|
||||
"INSERT INTO db(dbid, dbcontent) SELECT NULL, dbcontent FROM dbx ORDER BY 2;\n"
|
||||
"DROP TABLE dbx;\n"
|
||||
"CREATE TEMP TABLE sx AS SELECT DISTINCT sqltext FROM xsql;\n"
|
||||
"DELETE FROM xsql;\n"
|
||||
"INSERT INTO xsql(sqlid,sqltext) SELECT NULL, sqltext FROM sx ORDER BY 2;\n"
|
||||
"DROP TABLE sx;\n"
|
||||
"COMMIT;\n"
|
||||
"PRAGMA page_size=1024;\n"
|
||||
"VACUUM;\n", 0, 0, 0);
|
||||
if( rc ) fatalError("cannot rebuild: %s", sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
/*
|
||||
** Print sketchy documentation for this utility program
|
||||
*/
|
||||
@@ -598,15 +693,18 @@ static void showHelp(void){
|
||||
"Options:\n"
|
||||
" --cell-size-check Set the PRAGMA cell_size_check=ON\n"
|
||||
" --dbid N Use only the database where dbid=N\n"
|
||||
" --help Show this help text\n"
|
||||
" --help Show this help text\n"
|
||||
" -q Reduced output\n"
|
||||
" --quiet Reduced output\n"
|
||||
" --limit-vdbe Panic if an sync SQL runs for more than 100,000 cycles\n"
|
||||
" --load-sql ARGS... Load SQL scripts fro files into SOURCE-DB\n"
|
||||
" --load-db ARGS... Load template databases from files into SOURCE_DB\n"
|
||||
" -m TEXT Add a description to the database\n"
|
||||
" --native-vfs Use the native VFS for initially empty database files\n"
|
||||
" --rebuild Rebuild and vacuum the database file\n"
|
||||
" --result-trace Show the results of each SQL command\n"
|
||||
" --sqlid N Use only SQL where sqlid=N\n"
|
||||
" --timeline N Abort if any single test case needs more than N seconds\n"
|
||||
" -v Increased output\n"
|
||||
" --verbose Increased output\n"
|
||||
);
|
||||
@@ -627,6 +725,9 @@ int main(int argc, char **argv){
|
||||
int onlySqlid = -1; /* --sqlid */
|
||||
int onlyDbid = -1; /* --dbid */
|
||||
int nativeFlag = 0; /* --native-vfs */
|
||||
int rebuildFlag = 0; /* --rebuild */
|
||||
int vdbeLimitFlag = 0; /* --limit-vdbe */
|
||||
int timeoutTest = 0; /* undocumented --timeout-test flag */
|
||||
int runFlags = 0; /* Flags sent to runSql() */
|
||||
char *zMsg = 0; /* Add this message */
|
||||
int nSrcDb = 0; /* Number of source databases */
|
||||
@@ -636,8 +737,13 @@ int main(int argc, char **argv){
|
||||
char *zDbName = ""; /* Appreviated name of a source database */
|
||||
const char *zFailCode = 0; /* Value of the TEST_FAILURE environment variable */
|
||||
int cellSzCkFlag = 0; /* --cell-size-check */
|
||||
int sqlFuzz = 0; /* True for SQL fuzz testing. False for DB fuzz */
|
||||
int iTimeout = 120; /* Default 120-second timeout */
|
||||
|
||||
iBegin = timeOfDay();
|
||||
#ifdef __unix__
|
||||
signal(SIGALRM, timeoutHandler);
|
||||
#endif
|
||||
g.zArgv0 = argv[0];
|
||||
zFailCode = getenv("TEST_FAILURE");
|
||||
for(i=1; i<argc; i++){
|
||||
@@ -656,6 +762,9 @@ int main(int argc, char **argv){
|
||||
showHelp();
|
||||
return 0;
|
||||
}else
|
||||
if( strcmp(z,"limit-vdbe")==0 ){
|
||||
vdbeLimitFlag = 1;
|
||||
}else
|
||||
if( strcmp(z,"load-sql")==0 ){
|
||||
zInsSql = "INSERT INTO xsql(sqltext) VALUES(CAST(readfile(?1) AS text))";
|
||||
iFirstInsArg = i+1;
|
||||
@@ -677,6 +786,9 @@ int main(int argc, char **argv){
|
||||
quietFlag = 1;
|
||||
verboseFlag = 0;
|
||||
}else
|
||||
if( strcmp(z,"rebuild")==0 ){
|
||||
rebuildFlag = 1;
|
||||
}else
|
||||
if( strcmp(z,"result-trace")==0 ){
|
||||
runFlags |= SQL_OUTPUT;
|
||||
}else
|
||||
@@ -684,6 +796,16 @@ int main(int argc, char **argv){
|
||||
if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
|
||||
onlySqlid = atoi(argv[++i]);
|
||||
}else
|
||||
if( strcmp(z,"timeout")==0 ){
|
||||
if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
|
||||
iTimeout = atoi(argv[++i]);
|
||||
}else
|
||||
if( strcmp(z,"timeout-test")==0 ){
|
||||
timeoutTest = 1;
|
||||
#ifndef __unix__
|
||||
fatalError("timeout is not available on non-unix systems");
|
||||
#endif
|
||||
}else
|
||||
if( strcmp(z,"verbose")==0 || strcmp(z,"v")==0 ){
|
||||
quietFlag = 0;
|
||||
verboseFlag = 1;
|
||||
@@ -715,7 +837,7 @@ int main(int argc, char **argv){
|
||||
fatalError("cannot open source database %s - %s",
|
||||
azSrcDb[iSrcDb], sqlite3_errmsg(db));
|
||||
}
|
||||
rc = sqlite3_exec(db,
|
||||
rc = sqlite3_exec(db,
|
||||
"CREATE TABLE IF NOT EXISTS db(\n"
|
||||
" dbid INTEGER PRIMARY KEY, -- database id\n"
|
||||
" dbcontent BLOB -- database disk file image\n"
|
||||
@@ -753,6 +875,7 @@ int main(int argc, char **argv){
|
||||
sqlite3_finalize(pStmt);
|
||||
rc = sqlite3_exec(db, "COMMIT", 0, 0, 0);
|
||||
if( rc ) fatalError("cannot commit the transaction: %s", sqlite3_errmsg(db));
|
||||
rebuild_database(db);
|
||||
sqlite3_close(db);
|
||||
return 0;
|
||||
}
|
||||
@@ -771,6 +894,7 @@ int main(int argc, char **argv){
|
||||
g.pFirstDb->id = 1;
|
||||
g.pFirstDb->seq = 0;
|
||||
g.nDb = 1;
|
||||
sqlFuzz = 1;
|
||||
}
|
||||
|
||||
/* Print the description, if there is one */
|
||||
@@ -786,6 +910,16 @@ int main(int argc, char **argv){
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
}
|
||||
|
||||
/* Rebuild the database, if requested */
|
||||
if( rebuildFlag ){
|
||||
if( !quietFlag ){
|
||||
printf("%s: rebuilding... ", zDbName);
|
||||
fflush(stdout);
|
||||
}
|
||||
rebuild_database(db);
|
||||
if( !quietFlag ) printf("done\n");
|
||||
}
|
||||
|
||||
/* Close the source database. Verify that no SQLite memory allocations are
|
||||
** outstanding.
|
||||
@@ -831,7 +965,16 @@ int main(int argc, char **argv){
|
||||
rc = sqlite3_open_v2("main.db", &db, openFlags, zVfs);
|
||||
if( rc ) fatalError("cannot open inmem database");
|
||||
if( cellSzCkFlag ) runSql(db, "PRAGMA cell_size_check=ON", runFlags);
|
||||
runSql(db, (char*)pSql->a, runFlags);
|
||||
setAlarm(iTimeout);
|
||||
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
|
||||
if( sqlFuzz || vdbeLimitFlag ){
|
||||
sqlite3_progress_handler(db, 100000, progressHandler, &vdbeLimitFlag);
|
||||
}
|
||||
#endif
|
||||
do{
|
||||
runSql(db, (char*)pSql->a, runFlags);
|
||||
}while( timeoutTest );
|
||||
setAlarm(0);
|
||||
sqlite3_close(db);
|
||||
if( sqlite3_memory_used()>0 ) fatalError("memory leak");
|
||||
reformatVfs();
|
||||
|
||||
Binary file not shown.
Binary file not shown.
+17
-3
@@ -450,28 +450,42 @@ do_test in-12.10 {
|
||||
SELECT a FROM t3 UNION ALL SELECT a, b FROM t2
|
||||
);
|
||||
}
|
||||
} {1 {only a single result allowed for a SELECT that is part of an expression}}
|
||||
} {1 {SELECTs to the left and right of UNION ALL do not have the same number of result columns}}
|
||||
do_test in-12.11 {
|
||||
catchsql {
|
||||
SELECT * FROM t2 WHERE a IN (
|
||||
SELECT a FROM t3 UNION SELECT a, b FROM t2
|
||||
);
|
||||
}
|
||||
} {1 {only a single result allowed for a SELECT that is part of an expression}}
|
||||
} {1 {SELECTs to the left and right of UNION do not have the same number of result columns}}
|
||||
do_test in-12.12 {
|
||||
catchsql {
|
||||
SELECT * FROM t2 WHERE a IN (
|
||||
SELECT a FROM t3 EXCEPT SELECT a, b FROM t2
|
||||
);
|
||||
}
|
||||
} {1 {only a single result allowed for a SELECT that is part of an expression}}
|
||||
} {1 {SELECTs to the left and right of EXCEPT do not have the same number of result columns}}
|
||||
do_test in-12.13 {
|
||||
catchsql {
|
||||
SELECT * FROM t2 WHERE a IN (
|
||||
SELECT a FROM t3 INTERSECT SELECT a, b FROM t2
|
||||
);
|
||||
}
|
||||
} {1 {SELECTs to the left and right of INTERSECT do not have the same number of result columns}}
|
||||
do_test in-12.14 {
|
||||
catchsql {
|
||||
SELECT * FROM t2 WHERE a IN (
|
||||
SELECT a, b FROM t3 UNION ALL SELECT a, b FROM t2
|
||||
);
|
||||
}
|
||||
} {1 {only a single result allowed for a SELECT that is part of an expression}}
|
||||
do_test in-12.15 {
|
||||
catchsql {
|
||||
SELECT * FROM t2 WHERE a IN (
|
||||
SELECT a, b FROM t3 UNION ALL SELECT a FROM t2
|
||||
);
|
||||
}
|
||||
} {1 {SELECTs to the left and right of UNION ALL do not have the same number of result columns}}
|
||||
}; #ifcapable compound
|
||||
|
||||
|
||||
|
||||
+2
-2
@@ -189,8 +189,8 @@ do_test malloc5-3.1 {
|
||||
BEGIN;
|
||||
SELECT * FROM def;
|
||||
} db2
|
||||
sqlite3_release_memory
|
||||
} [expr $::pgalloc * 2]
|
||||
value_in_range [expr $::pgalloc*2] 0.99 [sqlite3_release_memory]
|
||||
} [value_in_range [expr $::pgalloc * 2] 0.99]
|
||||
do_test malloc5-3.2 {
|
||||
concat \
|
||||
[execsql {SELECT * FROM abc; COMMIT}] \
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix select7
|
||||
|
||||
ifcapable compound {
|
||||
|
||||
@@ -201,4 +202,23 @@ do_test select7-7.7 {
|
||||
}
|
||||
} {text 123}
|
||||
|
||||
do_execsql_test 8.0 {
|
||||
CREATE TABLE t01(x, y);
|
||||
CREATE TABLE t02(x, y);
|
||||
}
|
||||
|
||||
do_catchsql_test 8.1 {
|
||||
SELECT * FROM (
|
||||
SELECT * FROM t01 UNION SELECT x FROM t02
|
||||
) WHERE y=1
|
||||
} {1 {SELECTs to the left and right of UNION do not have the same number of result columns}}
|
||||
|
||||
do_catchsql_test 8.2 {
|
||||
CREATE VIEW v0 as SELECT x, y FROM t01 UNION SELECT x FROM t02;
|
||||
EXPLAIN QUERY PLAN SELECT * FROM v0 WHERE x='0' OR y;
|
||||
} {1 {SELECTs to the left and right of UNION do not have the same number of result columns}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
+18
-2
@@ -43,6 +43,9 @@ static const char zHelp[] =
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#if SQLITE_VERSION_NUMBER<3005000
|
||||
# define sqlite3_int64 sqlite_int64
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_OTA
|
||||
# include "sqlite3ota.h"
|
||||
#endif
|
||||
@@ -143,6 +146,9 @@ static int integerValue(const char *zArg){
|
||||
|
||||
/* Return the current wall-clock time, in milliseconds */
|
||||
sqlite3_int64 speedtest1_timestamp(void){
|
||||
#if SQLITE_VERSION_NUMBER<3005000
|
||||
return 0;
|
||||
#else
|
||||
static sqlite3_vfs *clockVfs = 0;
|
||||
sqlite3_int64 t;
|
||||
if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
|
||||
@@ -157,6 +163,7 @@ sqlite3_int64 speedtest1_timestamp(void){
|
||||
t = (sqlite3_int64)(r*86400000.0);
|
||||
}
|
||||
return t;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return a pseudo-random unsigned integer */
|
||||
@@ -306,7 +313,7 @@ static void printSql(const char *zSql){
|
||||
if( g.bExplain ) printf("EXPLAIN ");
|
||||
printf("%.*s;\n", n, zSql);
|
||||
if( g.bExplain
|
||||
#if SQLITE_VERSION_NUMBER>=3007010
|
||||
#if SQLITE_VERSION_NUMBER>=3007017
|
||||
&& ( sqlite3_strglob("CREATE *", zSql)==0
|
||||
|| sqlite3_strglob("DROP *", zSql)==0
|
||||
|| sqlite3_strglob("ALTER *", zSql)==0
|
||||
@@ -374,12 +381,15 @@ void speedtest1_run(void){
|
||||
}
|
||||
}
|
||||
}
|
||||
#if SQLITE_VERSION_NUMBER>=3006001
|
||||
if( g.bReprepare ){
|
||||
sqlite3_stmt *pNew;
|
||||
sqlite3_prepare_v2(g.db, sqlite3_sql(g.pStmt), -1, &pNew, 0);
|
||||
sqlite3_finalize(g.pStmt);
|
||||
g.pStmt = pNew;
|
||||
}else{
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
sqlite3_reset(g.pStmt);
|
||||
}
|
||||
}
|
||||
@@ -1273,6 +1283,7 @@ int main(int argc, char **argv){
|
||||
fatal_error(zHelp, argv[0]);
|
||||
}
|
||||
#endif
|
||||
#if SQLITE_VERSION_NUMBER>=3006001
|
||||
if( nHeap>0 ){
|
||||
pHeap = malloc( nHeap );
|
||||
if( pHeap==0 ) fatal_error("cannot allocate %d-byte heap\n", nHeap);
|
||||
@@ -1296,16 +1307,19 @@ int main(int argc, char **argv){
|
||||
if( nLook>0 ){
|
||||
sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Open the database and the input file */
|
||||
if( sqlite3_open(zDbName, &g.db) ){
|
||||
fatal_error("Cannot open database file: %s\n", zDbName);
|
||||
}
|
||||
#if SQLITE_VERSION_NUMBER>=3006001
|
||||
if( nLook>0 && szLook>0 ){
|
||||
pLook = malloc( nLook*szLook );
|
||||
rc = sqlite3_db_config(g.db, SQLITE_DBCONFIG_LOOKASIDE, pLook, szLook,nLook);
|
||||
if( rc ) fatal_error("lookaside configuration failed: %d\n", rc);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set database connection options */
|
||||
sqlite3_create_function(g.db, "random", 0, SQLITE_UTF8, 0, randomFunc, 0, 0);
|
||||
@@ -1387,6 +1401,7 @@ int main(int argc, char **argv){
|
||||
|
||||
sqlite3_close(g.db);
|
||||
|
||||
#if SQLITE_VERSION_NUMBER>=3006001
|
||||
/* Global memory usage statistics printed after the database connection
|
||||
** has closed. Memory usage should be zero at this point. */
|
||||
if( showStats ){
|
||||
@@ -1407,6 +1422,7 @@ int main(int argc, char **argv){
|
||||
sqlite3_status(SQLITE_STATUS_SCRATCH_SIZE, &iCur, &iHi, 0);
|
||||
printf("-- Largest Scratch Allocation: %d bytes\n", iHi);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Release memory */
|
||||
free( pLook );
|
||||
|
||||
@@ -283,7 +283,124 @@ ifcapable trace {
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that the spellfix1 table supports conflict handling (OR REPLACE
|
||||
# and so on).
|
||||
#
|
||||
do_execsql_test 7.1 {
|
||||
CREATE VIRTUAL TABLE t4 USING spellfix1;
|
||||
PRAGMA table_info = t4;
|
||||
} {
|
||||
0 word {} 0 {} 0
|
||||
1 rank {} 0 {} 0
|
||||
2 distance {} 0 {} 0
|
||||
3 langid {} 0 {} 0
|
||||
4 score {} 0 {} 0
|
||||
5 matchlen {} 0 {} 0
|
||||
}
|
||||
|
||||
do_execsql_test 7.2.1 {
|
||||
INSERT INTO t4(rowid, word) VALUES(1, 'Archilles');
|
||||
INSERT INTO t4(rowid, word) VALUES(2, 'Pluto');
|
||||
INSERT INTO t4(rowid, word) VALUES(3, 'Atrides');
|
||||
INSERT OR REPLACE INTO t4(rowid, word) VALUES(2, 'Apollo');
|
||||
SELECT rowid, word FROM t4;
|
||||
} {
|
||||
1 Archilles 2 Apollo 3 Atrides
|
||||
}
|
||||
do_catchsql_test 7.2.2 {
|
||||
INSERT OR ABORT INTO t4(rowid, word) VALUES(1, 'Leto');
|
||||
} {1 {constraint failed}}
|
||||
do_catchsql_test 7.2.3 {
|
||||
INSERT OR ROLLBACK INTO t4(rowid, word) VALUES(3, 'Zeus');
|
||||
} {1 {constraint failed}}
|
||||
do_catchsql_test 7.2.4 {
|
||||
INSERT OR FAIL INTO t4(rowid, word) VALUES(3, 'Zeus');
|
||||
} {1 {constraint failed}}
|
||||
do_execsql_test 7.2.5 {
|
||||
INSERT OR IGNORE INTO t4(rowid, word) VALUES(3, 'Zeus');
|
||||
SELECT rowid, word FROM t4;
|
||||
} {
|
||||
1 Archilles 2 Apollo 3 Atrides
|
||||
}
|
||||
|
||||
do_execsql_test 7.3.1 {
|
||||
UPDATE OR REPLACE t4 SET rowid=3 WHERE rowid=1;
|
||||
SELECT rowid, word FROM t4;
|
||||
} {2 Apollo 3 Archilles}
|
||||
do_catchsql_test 7.3.2 {
|
||||
UPDATE OR ABORT t4 SET rowid=3 WHERE rowid=2;
|
||||
} {1 {constraint failed}}
|
||||
do_catchsql_test 7.3.3 {
|
||||
UPDATE OR ROLLBACK t4 SET rowid=3 WHERE rowid=2;
|
||||
} {1 {constraint failed}}
|
||||
do_catchsql_test 7.3.4 {
|
||||
UPDATE OR FAIL t4 SET rowid=3 WHERE rowid=2;
|
||||
} {1 {constraint failed}}
|
||||
do_execsql_test 7.3.5 {
|
||||
UPDATE OR IGNORE t4 SET rowid=3 WHERE rowid=2;
|
||||
SELECT rowid, word FROM t4;
|
||||
} {2 Apollo 3 Archilles}
|
||||
|
||||
do_execsql_test 7.4.1 {
|
||||
DELETE FROM t4;
|
||||
INSERT INTO t4(rowid, word) VALUES(10, 'Agamemnon');
|
||||
INSERT INTO t4(rowid, word) VALUES(20, 'Patroclus');
|
||||
INSERT INTO t4(rowid, word) VALUES(30, 'Chryses');
|
||||
|
||||
CREATE TABLE t5(i, w);
|
||||
INSERT INTO t5 VALUES(5, 'Poseidon');
|
||||
INSERT INTO t5 VALUES(20, 'Chronos');
|
||||
INSERT INTO t5 VALUES(30, 'Hera');
|
||||
}
|
||||
|
||||
db_save_and_close
|
||||
foreach {tn conflict err bRollback res} {
|
||||
0 "" {1 {constraint failed}} 0
|
||||
{10 Agamemnon 20 Patroclus 30 Chryses}
|
||||
1 "OR REPLACE" {0 {}} 0
|
||||
{5 Poseidon 10 Agamemnon 20 Chronos 30 Hera}
|
||||
2 "OR ABORT" {1 {constraint failed}} 0
|
||||
{10 Agamemnon 20 Patroclus 30 Chryses}
|
||||
3 "OR ROLLBACK" {1 {constraint failed}} 1
|
||||
{10 Agamemnon 20 Patroclus 30 Chryses}
|
||||
5 "OR IGNORE" {0 {}} 0
|
||||
{5 Poseidon 10 Agamemnon 20 Patroclus 30 Chryses}
|
||||
} {
|
||||
db_restore_and_reopen
|
||||
load_static_extension db spellfix nextchar
|
||||
|
||||
execsql BEGIN
|
||||
set sql "INSERT $conflict INTO t4(rowid, word) SELECT i, w FROM t5"
|
||||
do_catchsql_test 7.4.2.$tn.1 $sql $err
|
||||
do_execsql_test 7.4.2.$tn.2 { SELECT rowid, word FROM t4 } $res
|
||||
|
||||
do_test 7.4.2.$tn.3 { sqlite3_get_autocommit db } $bRollback
|
||||
catchsql ROLLBACK
|
||||
}
|
||||
|
||||
foreach {tn conflict err bRollback res} {
|
||||
0 "" {1 {constraint failed}} 0
|
||||
{10 Agamemnon 20 Patroclus 30 Chryses}
|
||||
1 "OR REPLACE" {0 {}} 0
|
||||
{15 Agamemnon 45 Chryses}
|
||||
2 "OR ABORT" {1 {constraint failed}} 0
|
||||
{10 Agamemnon 20 Patroclus 30 Chryses}
|
||||
3 "OR ROLLBACK" {1 {constraint failed}} 1
|
||||
{10 Agamemnon 20 Patroclus 30 Chryses}
|
||||
5 "OR IGNORE" {0 {}} 0
|
||||
{15 Agamemnon 20 Patroclus 45 Chryses}
|
||||
} {
|
||||
db_restore_and_reopen
|
||||
load_static_extension db spellfix nextchar
|
||||
|
||||
execsql BEGIN
|
||||
set sql "UPDATE $conflict t4 SET rowid=rowid + (rowid/2)"
|
||||
do_catchsql_test 7.5.2.$tn.1 $sql $err
|
||||
do_execsql_test 7.5.2.$tn.2 { SELECT rowid, word FROM t4 } $res
|
||||
do_test 7.5.2.$tn.3 { sqlite3_get_autocommit db } $bRollback
|
||||
catchsql ROLLBACK
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -808,4 +808,20 @@ do_execsql_test table-17.1 {
|
||||
SELECT p, q, '|' FROM t3 ORDER BY p;
|
||||
} {1 1 | 2 2 |}
|
||||
|
||||
# 2015-06-16
|
||||
# Ticket [https://www.sqlite.org/src/tktview/873cae2b6e25b1991ce5e9b782f9cd0409b96063]
|
||||
# Make sure a CREATE TABLE AS statement correctly rolls back partial changes to the
|
||||
# sqlite_master table when the SELECT on the right-hand side aborts.
|
||||
#
|
||||
do_catchsql_test table-18.1 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
BEGIN;
|
||||
CREATE TABLE t1 AS SELECT zeroblob(2e20);
|
||||
} {1 {string or blob too big}}
|
||||
do_execsql_test table-18.2 {
|
||||
COMMIT;
|
||||
PRAGMA integrity_check;
|
||||
} {ok}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -230,4 +230,41 @@ do_eqp_test 5.3.3 {
|
||||
SELECT * FROM t1 WHERE likely(a=?)
|
||||
} {0 0 0 {SCAN TABLE t1}}
|
||||
|
||||
# 2015-06-18
|
||||
# Ticket [https://www.sqlite.org/see/tktview/472f0742a1868fb58862bc588ed70]
|
||||
#
|
||||
do_execsql_test 6.0 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(i int, x, y, z);
|
||||
INSERT INTO t1 VALUES (1,1,1,1), (2,2,2,2), (3,3,3,3), (4,4,4,4);
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t2(i int, bool char);
|
||||
INSERT INTO t2 VALUES(1,'T'), (2,'F');
|
||||
SELECT count(*) FROM t1 LEFT JOIN t2 ON t1.i=t2.i AND bool='T';
|
||||
SELECT count(*) FROM t1 LEFT JOIN t2 ON likely(t1.i=t2.i) AND bool='T';
|
||||
} {4 4}
|
||||
|
||||
# 2015-06-20
|
||||
# Crash discovered by AFL
|
||||
#
|
||||
do_execsql_test 7.0 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(a, b, PRIMARY KEY(a,b));
|
||||
INSERT INTO t1 VALUES(9,1),(1,2);
|
||||
DROP TABLE IF EXISTS t2;
|
||||
CREATE TABLE t2(x, y, PRIMARY KEY(x,y));
|
||||
INSERT INTO t2 VALUES(3,3),(4,4);
|
||||
SELECT likely(a), x FROM t1, t2 ORDER BY 1, 2;
|
||||
} {1 3 1 4 9 3 9 4}
|
||||
do_execsql_test 7.1 {
|
||||
SELECT unlikely(a), x FROM t1, t2 ORDER BY 1, 2;
|
||||
} {1 3 1 4 9 3 9 4}
|
||||
do_execsql_test 7.2 {
|
||||
SELECT likelihood(a,0.5), x FROM t1, t2 ORDER BY 1, 2;
|
||||
} {1 3 1 4 9 3 9 4}
|
||||
do_execsql_test 7.3 {
|
||||
SELECT coalesce(a,a), x FROM t1, t2 ORDER BY 1, 2;
|
||||
} {1 3 1 4 9 3 9 4}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -9,6 +9,28 @@ echo '********** No optimizations. Includes FTS4 and RTREE *********'
|
||||
gcc -c -Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long -std=c89 \
|
||||
-ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE \
|
||||
sqlite3.c
|
||||
echo '********** Android configuration ******************************'
|
||||
gcc -c \
|
||||
-DHAVE_USLEEP=1 \
|
||||
-DSQLITE_HAVE_ISNAN \
|
||||
-DSQLITE_DEFAULT_JOURNAL_SIZE_LIMIT=1048576 \
|
||||
-DSQLITE_THREADSAFE=2 \
|
||||
-DSQLITE_TEMP_STORE=3 \
|
||||
-DSQLITE_POWERSAFE_OVERWRITE=1 \
|
||||
-DSQLITE_DEFAULT_FILE_FORMAT=4 \
|
||||
-DSQLITE_DEFAULT_AUTOVACUUM=1 \
|
||||
-DSQLITE_ENABLE_MEMORY_MANAGEMENT=1 \
|
||||
-DSQLITE_ENABLE_FTS3 \
|
||||
-DSQLITE_ENABLE_FTS3_BACKWARDS \
|
||||
-DSQLITE_ENABLE_FTS4 \
|
||||
-DSQLITE_OMIT_BUILTIN_TEST \
|
||||
-DSQLITE_OMIT_COMPILEOPTION_DIAGS \
|
||||
-DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
-DSQLITE_DEFAULT_FILE_PERMISSIONS=0600 \
|
||||
-DSQLITE_ENABLE_ICU \
|
||||
-DUSE_PREAD64 \
|
||||
-Wshadow -Wall -Wextra \
|
||||
-Os sqlite3.c shell.c
|
||||
echo '********** No optimizations. ENABLE_STAT4. THREADSAFE=0 *******'
|
||||
gcc -c -Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long -std=c89 \
|
||||
-ansi -DSQLITE_ENABLE_STAT4 -DSQLITE_THREADSAFE=0 \
|
||||
|
||||
Reference in New Issue
Block a user