Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d90ecb5d6e | |||
| 3a32690a55 | |||
| 09768559b6 | |||
| adea051707 | |||
| 64b76c0ed4 | |||
| 1d09f4d018 | |||
| d87299cece | |||
| ed0a614c21 | |||
| d844e0a1c4 | |||
| 744581d3d6 | |||
| 9486178f39 | |||
| c24f53635c | |||
| b202a452ad | |||
| 91981fe74e | |||
| af3824d5fa | |||
| 581bf002ce | |||
| 7f9a1ff3f2 | |||
| 3fc7a34efc | |||
| 4c11a5251a | |||
| 5b480ead99 | |||
| d921533954 | |||
| 052f0a95d0 | |||
| 21bdfe5884 | |||
| 48e899a86e | |||
| ad2689fe4e | |||
| 7659ce22c5 | |||
| 3467698000 | |||
| 51f652de10 | |||
| 82bf13796a | |||
| 539085ddf5 | |||
| 4821b15dca | |||
| fa079680f1 | |||
| bcf3df0192 | |||
| 1ff9a7bc8d | |||
| 5ff513c16e | |||
| 6bb8ce6375 | |||
| e318f10ce2 | |||
| 91cee17d83 |
@@ -683,6 +683,7 @@ other than that, the order of directives in Lemon is arbitrary.</p>
|
||||
<li><tt><a href='#pifdef'>%endif</a></tt>
|
||||
<li><tt><a href='#extraarg'>%extra_argument</a></tt>
|
||||
<li><tt><a href='#pfallback'>%fallback</a></tt>
|
||||
<li><tt><a href='#reallc'>%free</a></tt>
|
||||
<li><tt><a href='#pifdef'>%if</a></tt>
|
||||
<li><tt><a href='#pifdef'>%ifdef</a></tt>
|
||||
<li><tt><a href='#pifdef'>%ifndef</a></tt>
|
||||
@@ -693,6 +694,7 @@ other than that, the order of directives in Lemon is arbitrary.</p>
|
||||
<li><tt><a href='#parse_accept'>%parse_accept</a></tt>
|
||||
<li><tt><a href='#parse_failure'>%parse_failure</a></tt>
|
||||
<li><tt><a href='#pright'>%right</a></tt>
|
||||
<li><tt><a href='#reallc'>%realloc</a></tt>
|
||||
<li><tt><a href='#stack_overflow'>%stack_overflow</a></tt>
|
||||
<li><tt><a href='#stack_size'>%stack_size</a></tt>
|
||||
<li><tt><a href='#start_symbol'>%start_symbol</a></tt>
|
||||
@@ -1200,6 +1202,21 @@ match any input token.</p>
|
||||
the wildcard token and some other token, the other token is always used.
|
||||
The wildcard token is only matched if there are no alternatives.</p>
|
||||
|
||||
<a id='reallc'></a>
|
||||
<h4>4.4.26 The <tt>%realloc</tt> and <tt>%free</tt> directives</h4>
|
||||
|
||||
<p>The <tt>%realloc</tt> and <tt>%free</tt> directives defines function
|
||||
that allocate and free heap memory. The signatures of these functions
|
||||
should be the same as the realloc() and free() functions from the standard
|
||||
C library.
|
||||
|
||||
<p>If both of these functions are defined
|
||||
then these functions are used to allocate and free
|
||||
memory for supplemental parser stack space, if the initial
|
||||
parse stack space is exceeded. The initial parser stack size
|
||||
is specified by either <tt>%stack_size</tt> or the
|
||||
-DYYSTACKDEPTH compile-time flag.
|
||||
|
||||
<a id='errors'></a>
|
||||
<h2>5.0 Error Processing</h2>
|
||||
|
||||
@@ -1224,6 +1241,7 @@ to begin parsing a new file. This is what will happen at the very
|
||||
first syntax error, of course, if there are no instances of the
|
||||
"error" non-terminal in your grammar.</p>
|
||||
|
||||
|
||||
<a id='history'></a>
|
||||
<h2>6.0 History of Lemon</h2>
|
||||
|
||||
|
||||
+7
-5
@@ -4014,22 +4014,24 @@ static int fts3IntegrityMethod(
|
||||
char **pzErr /* Write error message here */
|
||||
){
|
||||
Fts3Table *p = (Fts3Table*)pVtab;
|
||||
int rc;
|
||||
int rc = SQLITE_OK;
|
||||
int bOk = 0;
|
||||
|
||||
UNUSED_PARAMETER(isQuick);
|
||||
rc = sqlite3Fts3IntegrityCheck(p, &bOk);
|
||||
assert( rc!=SQLITE_CORRUPT_VTAB || bOk==0 );
|
||||
if( rc!=SQLITE_OK && rc!=SQLITE_CORRUPT_VTAB ){
|
||||
assert( rc!=SQLITE_CORRUPT_VTAB );
|
||||
if( rc==SQLITE_ERROR || (rc&0xFF)==SQLITE_CORRUPT ){
|
||||
*pzErr = sqlite3_mprintf("unable to validate the inverted index for"
|
||||
" FTS%d table %s.%s: %s",
|
||||
p->bFts4 ? 4 : 3, zSchema, zTabname, sqlite3_errstr(rc));
|
||||
}else if( bOk==0 ){
|
||||
if( *pzErr ) rc = SQLITE_OK;
|
||||
}else if( rc==SQLITE_OK && bOk==0 ){
|
||||
*pzErr = sqlite3_mprintf("malformed inverted index for FTS%d table %s.%s",
|
||||
p->bFts4 ? 4 : 3, zSchema, zTabname);
|
||||
if( *pzErr==0 ) rc = SQLITE_NOMEM;
|
||||
}
|
||||
sqlite3Fts3SegmentsClose(p);
|
||||
return SQLITE_OK;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -5372,7 +5372,12 @@ int sqlite3Fts3IntegrityCheck(Fts3Table *p, int *pbOk){
|
||||
sqlite3_finalize(pStmt);
|
||||
}
|
||||
|
||||
*pbOk = (rc==SQLITE_OK && cksum1==cksum2);
|
||||
if( rc==SQLITE_CORRUPT_VTAB ){
|
||||
rc = SQLITE_OK;
|
||||
*pbOk = 0;
|
||||
}else{
|
||||
*pbOk = (rc==SQLITE_OK && cksum1==cksum2);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@@ -2979,6 +2979,7 @@ static int fts5IntegrityMethod(
|
||||
if( (rc&0xff)==SQLITE_CORRUPT ){
|
||||
*pzErr = sqlite3_mprintf("malformed inverted index for FTS5 table %s.%s",
|
||||
zSchema, zTabname);
|
||||
rc = (*pzErr) ? SQLITE_OK : SQLITE_NOMEM;
|
||||
}else if( rc!=SQLITE_OK ){
|
||||
*pzErr = sqlite3_mprintf("unable to validate the inverted index for"
|
||||
" FTS5 table %s.%s: %s",
|
||||
@@ -2986,7 +2987,7 @@ static int fts5IntegrityMethod(
|
||||
}
|
||||
sqlite3Fts5IndexCloseReader(pTab->p.pIndex);
|
||||
|
||||
return SQLITE_OK;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int fts5Init(sqlite3 *db){
|
||||
|
||||
@@ -57,7 +57,6 @@ foreach_detail_mode $testprefix {
|
||||
|
||||
} ;# foreach_detail_mode...
|
||||
|
||||
|
||||
do_execsql_test 4.0 {
|
||||
CREATE VIRTUAL TABLE x2 USING fts5(a);
|
||||
INSERT INTO x2(x2, rank) VALUES('crisismerge', 2);
|
||||
@@ -80,5 +79,18 @@ do_faultsim_test 4 -faults oom-* -prep {
|
||||
faultsim_test_result {0 {}} {1 SQLITE_NOMEM}
|
||||
}
|
||||
|
||||
set TMPDBERROR {1 {unable to open a temporary database file for storing temporary tables}}
|
||||
|
||||
do_faultsim_test 5 -faults oom-t* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
execsql { PRAGMA temp_store = memory }
|
||||
} -body {
|
||||
execsql { PRAGMA integrity_check }
|
||||
} -test {
|
||||
if {[string match {*error code=7*} $testresult]==0} {
|
||||
faultsim_test_result {0 ok} {1 SQLITE_NOMEM} $::TMPDBERROR
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -174,11 +174,17 @@ const Rx = newObj({
|
||||
squiggly: /[{}]/
|
||||
});
|
||||
|
||||
|
||||
|
||||
const Util = newObj({
|
||||
toss,
|
||||
|
||||
unlink: function(fn){
|
||||
return 0==sqlite3.wasm.sqlite3_wasm_vfs_unlink(0,fn);
|
||||
unlink: function f(fn){
|
||||
if(!f.unlink){
|
||||
f.unlink = sqlite3.wasm.xWrap('sqlite3__wasm_vfs_unlink','int',
|
||||
['*','string']);
|
||||
}
|
||||
return 0==f.unlink(0,fn);
|
||||
},
|
||||
|
||||
argvToString: (list)=>{
|
||||
@@ -197,7 +203,7 @@ const Util = newObj({
|
||||
|
||||
utf8Encode: (str)=>__utf8Encoder.encode(str),
|
||||
|
||||
strglob: sqlite3.wasm.xWrap('sqlite3_wasm_SQLTester_strglob','int',
|
||||
strglob: sqlite3.wasm.xWrap('sqlite3__wasm_SQLTester_strglob','int',
|
||||
['string','string'])
|
||||
})/*Util*/;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
C Simplification\sof\sthe\serror\sreporting\slogic.
|
||||
D 2024-01-22T20:49:47.506
|
||||
C Have\s"PRAGMA\squick_check"\scompare\sthe\snumber\sof\sentries\sin\stables\sand\sindexes.
|
||||
D 2024-02-02T16:51:24.901
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
@@ -40,7 +40,7 @@ F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
|
||||
F doc/compile-for-windows.md 50b27d77be96195c66031a3181cb8684ed822327ea834e07f9c014213e5e3bcf
|
||||
F doc/json-enhancements.md e356fc834781f1f1aa22ee300027a270b2c960122468499bf347bb123ce1ea4f
|
||||
F doc/jsonb.md 5fab4b8613aa9153fbeb6259297bd4697988af8b3d23900deba588fa7841456b
|
||||
F doc/lemon.html 44a53a1d2b42d7751f7b2f478efb23c978e258d794bfd172442307a755b9fa44
|
||||
F doc/lemon.html 8b266ff711d2ec7f867c3dca37634963f48a630329908cc282beebfa8c708706
|
||||
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
|
||||
F doc/testrunner.md 8d36ec692cf4994bb66d84a4645b9afa1ce9d47dc12cbf8d437c5a5fb6ddeedb
|
||||
F doc/trusted-schema.md 33625008620e879c7bcfbbfa079587612c434fa094d338b08242288d358c3e8a
|
||||
@@ -63,7 +63,7 @@ F ext/fts3/README.content b9078d0843a094d86af0d48dffbff13c906702b4c3558012e67b9c
|
||||
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
|
||||
F ext/fts3/README.tokenizers b92bdeb8b46503f0dd301d364efc5ef59ef9fa8e2758b8e742f39fa93a2e422d
|
||||
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
|
||||
F ext/fts3/fts3.c fd64a588471ce00b19da08acb0d6f904277a21ac1d15141d5913c83591afa027
|
||||
F ext/fts3/fts3.c c922380b62bd15bce953dae3350337acbd0fff07c10cdc805819409791eb480a
|
||||
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
||||
F ext/fts3/fts3Int.h 968f7d7cae541a6926146e9fd3fb2b2ccbd3845b7890a8ed03de0c06ac776682
|
||||
F ext/fts3/fts3_aux.c 7eab82a9cf0830f6551ba3abfdbe73ed39e322a4d3940ee82fbf723674ecd9f3
|
||||
@@ -81,7 +81,7 @@ F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
|
||||
F ext/fts3/fts3_tokenizer1.c c1de4ae28356ad98ccb8b2e3388a7fdcce7607b5523738c9afb6275dab765154
|
||||
F ext/fts3/fts3_unicode.c de426ff05c1c2e7bce161cf6b706638419c3a1d9c2667de9cb9dc0458c18e226
|
||||
F ext/fts3/fts3_unicode2.c 416eb7e1e81142703520d284b768ca2751d40e31fa912cae24ba74860532bf0f
|
||||
F ext/fts3/fts3_write.c c2d7a8dfb6e7a00c6c88ce626785cf4c50ed18eba34b5fbd53cacd60af96d0f2
|
||||
F ext/fts3/fts3_write.c 81cd8f7e8003e427a1801e04842776b731af26dd93af206e4e66ea5ae319cad1
|
||||
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
|
||||
F ext/fts3/tool/fts3cov.sh c331d006359456cf6f8f953e37f2b9c7d568f3863f00bb5f7eb87fea4ac01b73
|
||||
F ext/fts3/tool/fts3view.c 413c346399159df81f86c4928b7c4a455caab73bfbc8cd68f950f632e5751674
|
||||
@@ -98,7 +98,7 @@ F ext/fts5/fts5_config.c 8072a207034b51ae9b7694121d1b5715c794e94b275e088f70ae532
|
||||
F ext/fts5/fts5_expr.c e91156ebdcc08d837f4f324168f69f3c0d7fdef0e521fd561efb48ef3297b696
|
||||
F ext/fts5/fts5_hash.c adda4272be401566a6e0ba1acbe70ee5cb97fce944bc2e04dc707152a0ec91b1
|
||||
F ext/fts5/fts5_index.c bb1965c3965f6fe5f64160bf1c0694a9684a790a783f293a76da1d38d319b258
|
||||
F ext/fts5/fts5_main.c cd56ed9619e9bc55ae603ecafd5965c3684bb4c1de7dd00893c307ddf98afe88
|
||||
F ext/fts5/fts5_main.c d68bd9533d5a638b7f6fae61c3cb0a15257dcdcccedaf3d0b3c9f55940c85048
|
||||
F ext/fts5/fts5_storage.c f9e31b0d155e9b2c92d5d3a09ad7a56b937fbf1c7f962e10f4ca6281349f3934
|
||||
F ext/fts5/fts5_tcl.c cf0fd0dbe64ec272491b749e0d594f563cda03336aeb60900129e6d18b0aefb8
|
||||
F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee
|
||||
@@ -163,7 +163,7 @@ F ext/fts5/test/fts5fault4.test 87a10d0caee57da587c7588b0c8d25d2930197399b4812ad
|
||||
F ext/fts5/test/fts5fault5.test a336e4e11847de24c9497f80cce18e00bb3fab7fb11f97d04eb9af898900a762
|
||||
F ext/fts5/test/fts5fault6.test a0fc0a8f99e4b16500c31dfc7e38e1defe0f1693ac47650517ac7b723b1956f8
|
||||
F ext/fts5/test/fts5fault7.test 0acbec416edb24b8881f154e99c31e9ccf73f539cfcd164090be139e9e97ed4c
|
||||
F ext/fts5/test/fts5fault8.test 318238659d35f82ad215ecb57ca4c87486ea85d45dbeedaee42f148ff5105ee2
|
||||
F ext/fts5/test/fts5fault8.test 9353fe6a2a993c3231e09c49b0f4a12c8d306319555ff2ca6672b5b86fe9b0dd
|
||||
F ext/fts5/test/fts5fault9.test 098e6b894bbdf9b2192f994a30f4043673fb3f338b6b8ab1624c704422f39119
|
||||
F ext/fts5/test/fts5faultA.test be4487576bff8c22cee6597d1893b312f306504a8c6ccd3c53ca85af12290c8c
|
||||
F ext/fts5/test/fts5faultB.test d606bdb8e81aaeb6f41de3fc9fc7ae315733f0903fbff05cf54f5b045b729ab5
|
||||
@@ -579,7 +579,7 @@ F ext/wasm/GNUmakefile 867c903a27fa0d53a3bf1b01d8c7bb713456f87e0939c3cac9f07faa6
|
||||
F ext/wasm/README-dist.txt 6382cb9548076fca472fb3330bbdba3a55c1ea0b180ff9253f084f07ff383576
|
||||
F ext/wasm/README.md a8a2962c3aebdf8d2104a9102e336c5554e78fc6072746e5daf9c61514e7d193
|
||||
F ext/wasm/SQLTester/GNUmakefile e0794f676d55819951bbfae45cc5e8d7818dc460492dc317ce7f0d2eca15caff
|
||||
F ext/wasm/SQLTester/SQLTester.mjs ec2f6ba63a0f2f0562941a0fb8e46b7dc55589711513f1952349785966edfe50
|
||||
F ext/wasm/SQLTester/SQLTester.mjs ce765c0ad7d57f93553d12ef4dca574deb00300134a26d472daacab49031e1fb
|
||||
F ext/wasm/SQLTester/SQLTester.run.mjs c72b7fe2072d05992f7a3d8c6a1d34e95712513ceabe40849784e24e41c84638
|
||||
F ext/wasm/SQLTester/index.html 3f8a016df0776be76605abf20e815ecaafbe055abac0e1fe5ea080e7846b760d
|
||||
F ext/wasm/SQLTester/touint8array.c 2d5ece04ec1393a6a60c4bf96385bda5e1a10ad49f3038b96460fc5e5aa7e536
|
||||
@@ -677,9 +677,9 @@ F src/auth.c 19b7ccacae3dfba23fc6f1d0af68134fa216e9040e53b0681b4715445ea030b4
|
||||
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
|
||||
F src/bitvec.c 9eac5f42c11914d5ef00a75605bb205e934f435c579687f985f1f8b0995c8645
|
||||
F src/btmutex.c 79a43670447eacc651519a429f6ece9fd638563cf95b469d6891185ddae2b522
|
||||
F src/btree.c dee25e097b749275333b55d64a5ffc079249576f8e88a2ee476468cf67510f4b
|
||||
F src/btree.h 03e3356f5208bcab8eed4e094240fdac4a7f9f5ddf5e91045ce589f67d47c240
|
||||
F src/btreeInt.h 3e2589726c4f105e653461814f65857465da68be1fac688de340c43b873f4062
|
||||
F src/btree.c d49ecac72d677faa9ef604ea67248847acb1599579204c4f3b108b2ee1ca7037
|
||||
F src/btree.h 55066f513eb095db935169dab1dc2f7c7a747ef223c533f5d4ad4dfed346cbd0
|
||||
F src/btreeInt.h 98aadb6dcb77b012cab2574d6a728fad56b337fc946839b9898c4b4c969e30b6
|
||||
F src/build.c 05c9eb387638982092988d2ef4c00a91b0c29baa1b85923f082ce0cf2903ea7e
|
||||
F src/callback.c db3a45e376deff6a16c0058163fe0ae2b73a2945f3f408ca32cf74960b28d490
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
@@ -698,11 +698,11 @@ F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
|
||||
F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
|
||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c 3f0a94082d978bbdd33c38fefea15346c6c6bffb70bc645a71dc0f1f87dd3276
|
||||
F src/json.c 99f2825b44327811bdf47808e57077388b83bcc6a253c1269d13fd1b3237138d
|
||||
F src/json.c e4e5f70b602c1dc9592b798166697bedeb84c61ffe857c9302ded54d5024603d
|
||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||
F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
|
||||
F src/main.c 438b95162acfa17b7d218f586f5bde11d6ae82bcf030c9611fc537556870ad6b
|
||||
F src/malloc.c f016922435dc7d1f1f5083a03338a3e91f8c67ce2c5bdcfa4cdef62e612f5fcc
|
||||
F src/malloc.c c31472af77e3421d993b69c93f07890277afd94247da4290e1b290ffc0d1f404
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
|
||||
F src/mem2.c c8bfc9446fd0798bddd495eb5d9dbafa7d4b7287d8c22d50a83ac9daa26d8a75
|
||||
@@ -722,16 +722,16 @@ F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
|
||||
F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e06
|
||||
F src/os_kv.c 4d39e1f1c180b11162c6dc4aa8ad34053873a639bac6baae23272fc03349986a
|
||||
F src/os_setup.h 6011ad7af5db4e05155f385eb3a9b4470688de6f65d6166b8956e58a3d872107
|
||||
F src/os_unix.c 5dc41030cd5dfd99b907976b1725a4ed695566405d33744e4824c3d6aff245a3
|
||||
F src/os_win.c 4a50a154aeebc66a1f8fb79c1ff6dd5fe3d005556533361e0d460d41cb6a45a8
|
||||
F src/os_unix.c fa9b81b642e60e77ffaf98bd1a2e5fde16c1c2317614ec178bf3bd5864772356
|
||||
F src/os_win.c 6ff43bac175bd9ed79e7c0f96840b139f2f51d01689a638fd05128becf94908a
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c ff60e98138d2499082ac6230f01ac508aba545315debccfca2fd6042f5f10fcd
|
||||
F src/pager.h 4b1140d691860de0be1347474c51fee07d5420bd7f802d38cbab8ea4ab9f538a
|
||||
F src/parse.y 020d80386eb216ec9520549106353c517d2bbc89be28752ffdca649a9eaf56ec
|
||||
F src/parse.y bfd6da46fc895cd8237400ff485d04ab0b32e47eb56de20982bb7f53e56c1f42
|
||||
F src/pcache.c 040b165f30622a21b7a9a77c6f2e4877a32fb7f22d4c7f0d2a6fa6833a156a75
|
||||
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
|
||||
F src/pcache1.c 602acb23c471bb8d557a6f0083cc2be641d6cafcafa19e481eba7ef4c9ca0f00
|
||||
F src/pragma.c b5b4cff830575e6188cd56a295a57448d2b9dbc53f0dae58e22b97354cda3781
|
||||
F src/pragma.c cf46ab7d7d4c9ea53edfff52412215538b1ac96e52718b3e1279458e26b6f26e
|
||||
F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
|
||||
F src/prepare.c 371f6115cb69286ebc12c6f2d7511279c2e47d9f54f475d46a554d687a3b312c
|
||||
F src/printf.c 18fbdf028345c8fbe6044f5f5bfda5a10d48d6287afef088cc21b0ca57985640
|
||||
@@ -739,11 +739,11 @@ F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
|
||||
F src/resolve.c 0ed10ebb70d15dcf3f1882051931ccfaf9c3f4debe67dbd114047d9e2adb9523
|
||||
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
|
||||
F src/select.c f1a81ff4f8e9e76c224e2ab3a4baa799add0db22158c7fcede65d8cc4a6fa2da
|
||||
F src/shell.c.in 5ea8c6b0057bfe3bcdff31949fe72aa231ae429047c421ea1b168af6825a4890
|
||||
F src/shell.c.in c6cb773b7703d76677529de19d1c40584520701966422c33da3e9334498a7099
|
||||
F src/sqlite.h.in 61a60b4ea04db8ead15e1579b20b64cb56e9f55d52c5f9f9694de630110593a3
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
|
||||
F src/sqliteInt.h 03e64e4a973f56035772421e94be7bf092ceceeb3dc91a74a2147030a822c392
|
||||
F src/sqliteInt.h 5013ac1f5642df4c0b76314f507f4c7b6f8efee0e1d7c2e93bf8b445ceea29bb
|
||||
F src/sqliteLimit.h 6878ab64bdeb8c24a1d762d45635e34b96da21132179023338c93f820eee6728
|
||||
F src/status.c cb11f8589a6912af2da3bb1ec509a94dd8ef27df4d4c1a97e0bcf2309ece972b
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
@@ -808,14 +808,14 @@ F src/upsert.c fa125a8d3410ce9a97b02cb50f7ae68a2476c405c76aa692d3acf6b8586e9242
|
||||
F src/utf.c f23165685a67b4caf8ec08fb274cb3f319103decfb2a980b7cfd55d18dfa855e
|
||||
F src/util.c 078f040366d5bd5f47658d045f901c768c1c636c6eaea121f3a1cbd63c3edb5b
|
||||
F src/vacuum.c 604fcdaebe76f3497c855afcbf91b8fa5046b32de3045bab89cc008d68e40104
|
||||
F src/vdbe.c 92910d536e0b77505599cd6ae5d9d449e4a5d31ada61da4c0bb84f6ccb2c3189
|
||||
F src/vdbe.h 88e19a982df9027ec1c177c793d1a5d34dc23d8f06e3b2d997f43688b05ee0eb
|
||||
F src/vdbe.c c91a1555921f1573ef267210c8a5eeb91d28d83a1059d43a9a850c52a9bf6e39
|
||||
F src/vdbe.h c2d78d15112c3fc5ab87f5e8e0b75d2db1c624409de2e858c3d1aafb1650bb4f
|
||||
F src/vdbeInt.h 949669dfd8a41550d27dcb905b494f2ccde9a2e6c1b0b04daa1227e2e74c2b2c
|
||||
F src/vdbeapi.c 8f57d60c89da0b60e6d4e272358c511f6bae4e24330bdb11f8b42f986d1bf21b
|
||||
F src/vdbeaux.c c5a471b34e9c4cfc0295a3e10734fd197670ffaebcb742f284c8e17e8026ceea
|
||||
F src/vdbeblob.c 13f9287b55b6356b4b1845410382d6bede203ceb29ef69388a4a3d007ffacbe5
|
||||
F src/vdbemem.c 3e37dab421b74e9ce55c1e88fbc7bc6fead590b5ab258bc684f8b70abb1d6e71
|
||||
F src/vdbesort.c 237840ca1947511fa59bd4e18b9eeae93f2af2468c34d2427b059f896230a547
|
||||
F src/vdbemem.c 6f1728ea70d9523cc446567d3bf1cca3f26515d15160dd9f540fc549cdfbe2a6
|
||||
F src/vdbesort.c 00c1fb15171205063556c2f1cf454e24c0b41c1effb0c876b850dce91f21bc64
|
||||
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
|
||||
F src/vdbevtab.c 2143db7db0ceed69b21422581f434baffc507a08d831565193a7a02882a1b6a7
|
||||
F src/vtab.c 11948e105f56e84099ca17f1f434b1944539ea84de26d0d767eadfbc670ce1ea
|
||||
@@ -823,7 +823,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c 887fc4ca3f020ebb2e376f222069570834ac63bf50111ef0cbf3ae417048ed89
|
||||
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
|
||||
F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2
|
||||
F src/where.c 217fe82a26c0fb6a3c7fd01865d821e752f9c01fb72f114af3f0b77ce234d1fb
|
||||
F src/where.c 0a6492afeb75f8d2a50e26b993eb78e9623b142e637cd3f2cdb85e896931d51d
|
||||
F src/whereInt.h 82a13766f13d1a53b05387c2e60726289ef26404bc7b9b1f7770204d97357fb8
|
||||
F src/wherecode.c 5d77db30a2a3dd532492ae882de114edba2fae672622056b1c7fd61f5917a8f1
|
||||
F src/whereexpr.c dc5096eca5ed503999be3bdee8a90c51361289a678d396a220912e9cb73b3c00
|
||||
@@ -998,7 +998,7 @@ F test/corrupt9.test 730a3db08d4ab9aa43392ea30d9c2b4879cbff85
|
||||
F test/corruptA.test 112f4b2ae0b95ebf3ea63718642fb969a93acea557ace3a307234d19c245989b
|
||||
F test/corruptB.test 73a8d6c0b9833697ecf16b63e3c5c05c945b5dec
|
||||
F test/corruptC.test 9cf32275dae3ca33f645afe5d1d3f5ba5ac2af2b0833dfb5282f9dccb6fb81bb
|
||||
F test/corruptD.test a828c788535946a372a56a750b242cd96287cd823657abe5a73c5e51b91bdd28
|
||||
F test/corruptD.test 614320aa519f6bf6c7dd2f581f9513ff7b6826954180cca1a606d0e25ea084a3
|
||||
F test/corruptE.test 4143791f2dfb443aec5b7fabfa5821e6063eccc3b49b06f212c2f014715fd476
|
||||
F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4
|
||||
F test/corruptG.test adf79b669cbfd19e28c8191a610d083ae53a6d51
|
||||
@@ -1056,7 +1056,7 @@ F test/descidx3.test 953c831df7ea219c73826dfbf2f6ee02d95040725aa88ccb4fa43d1a199
|
||||
F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e
|
||||
F test/distinct.test 691c9e850b0d0b56b66e7e235453198cb4cf0760e324b7403d3c5abbeab0a014
|
||||
F test/distinct2.test bb71cc7b5e58e895787f9910a788c254f679928d324732d063fe9bc202ecbe71
|
||||
F test/distinctagg.test ad2b4cf1483cd4cf24867dfafbfa0abb61184d92085fcc9784cea0592b278d64
|
||||
F test/distinctagg.test 40d7169ae5846caaf62c6e307d2ca3c333daf9b6f7cde888956a339a97afe85f
|
||||
F test/e_blobbytes.test 4c01dfe4f12087b92b20705a3fdfded45dc4ed16d5a211fed4e1d2786ba68a52
|
||||
F test/e_blobclose.test 692fc02a058476c2222a63d97e3f3b2b809c1842e5525ded7f854d540ac2e075
|
||||
F test/e_blobopen.test 29f6055ee453b8e679fe9570c4d3acfedbef821622c5dad16875148c5952ef50
|
||||
@@ -1070,7 +1070,7 @@ F test/e_expr.test b950818a48269506d75a41c819003bd77a0893bc4a4f2fdee191bc74109c1
|
||||
F test/e_fkey.test feeba6238aeff9d809fb6236b351da8df4ae9bda89e088e54526b31a0cbfeec5
|
||||
F test/e_fts3.test 17ba7c373aba4d4f5696ba147ee23fd1a1ef70782af050e03e262ca187c5ee07
|
||||
F test/e_insert.test f02f7f17852b2163732c6611d193f84fc67bc641fb4882c77a464076e5eba80e
|
||||
F test/e_reindex.test 2b0e29344497d9a8a999453a003cb476b6b1d2eef2d6c120f83c2d3a429f3164
|
||||
F test/e_reindex.test 027bb13d2c7e9e865886eed6349f126a273f8037899b636bf5fb53c7fc815921
|
||||
F test/e_resolve.test a61751c368b109db73df0f20fc75fb47e166b1d8
|
||||
F test/e_select.test 327a15f14068bbd6f647cedc67210f8680fcb2f05e481a0a855fccd2abfa1292
|
||||
F test/e_select2.test aceb80ab927d46fba5ce7586ebabf23e2bb0604f
|
||||
@@ -1168,7 +1168,7 @@ F test/fts3expr5.test a5b9a053becbdb8e973fbf4d6d3abaabeb42d511d1848bd57931f3e0a1
|
||||
F test/fts3f.test 8c438d5e1cab526b0021988fb1dc70cf3597b006a33ffd6c955ee89929077fe3
|
||||
F test/fts3fault.test f4e1342acfe6d216a001490e8cd52afac1f9ffe4a11bbcdcb296129a45c5df45
|
||||
F test/fts3fault2.test 7b2741e5095367238380b0fcdb837f36c24484c7a5f353659b387df63cf039ec
|
||||
F test/fts3fault3.test 4a39a1618546776255dc1de306213b600aef87eca589ca8428a70c00fd11961b
|
||||
F test/fts3fault3.test ccdd2292dd2d4e21e30fc5f4c8e064f79e516087eec5ff57ab6bc4f6a7714097
|
||||
F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641
|
||||
F test/fts3fuzz001.test c78afcd8ad712ea0b8d2ed50851a8aab3bc9dc52c64a536291e07112f519357c
|
||||
F test/fts3integrity.test 0c6fe7353d7b24d78862f4272ee9df4da2f32b3ff30fa3396945cda8119580a8
|
||||
@@ -1342,9 +1342,10 @@ F test/json103.test 53df87f83a4e5fa0c0a56eb29ff6c94055c6eb919f33316d62161a888011
|
||||
F test/json104.test 1b844a70cddcfa2e4cd81a5db0657b2e61e7f00868310f24f56a9ba0114348c1
|
||||
F test/json105.test 043838b56e68f3252a0dcf5be1689016f6f3f05056f8dcfcdc9d074f4d932988
|
||||
F test/json106.test 1d46a9294e2ced35c7f87cebbcb9626d01abab04f1969d7ded7b6f6a1d9be0f2
|
||||
F test/json501.test ab168a12eb6eb14d479f8c1cdae3ac062fd5a4679f17f976e96f1af518408330
|
||||
F test/json107.test 59054e815c8f6b67d634d44ace421cf975828fb5651c4460aa66015c8e19d562
|
||||
F test/json501.test b95e2d14988b682a5cadf079dd6162f0f85fb74cd59c6b1f1624110104a974eb
|
||||
F test/json502.test 84634d3dbb521d2814e43624025b760c6198456c8197bbec6c977c0236648f5b
|
||||
F test/jsonb01.test cace70765b36a36aec9a85a41ea65667d3bbf647d4400ddc3ac76f8fe7d94f90
|
||||
F test/jsonb01.test f4cdfb4cf5a0c940091b17675ed9583f45add0c938f07d65b0de0e19d3a9a101
|
||||
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
|
||||
F test/kvtest.c 6e0228409ea7ca0497dad503fbd109badb5e59545d131014b6aaac68b56f484a
|
||||
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
|
||||
@@ -1412,16 +1413,17 @@ F test/misc1.test 8d138a4926ab90617c1aa29ce26e7785ae2b83a4d3a195d543b7374e05589d
|
||||
F test/misc2.test 71e746af479119386ac2ed7ab7d81d99970e75b49ffd3e8efffee100b4b5f350
|
||||
F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d
|
||||
F test/misc4.test 10cd6addb2fa9093df4751a1b92b50440175dd5468a6ec84d0386e78f087db0e
|
||||
F test/misc5.test c4aeaa0fa28faa08f2485309c38db4719e6cd1364215d5687a5b96d340a3fa58
|
||||
F test/misc5.test 027cf0ac10314ea534173f335a33bb4059907ddabbac2c16786766d6f26c8923
|
||||
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
|
||||
F test/misc7.test d912f3d45c2989191b797504a220ca225d6be80b21acad22ba0d35f4a9ee4579
|
||||
F test/misc8.test 4db9f8be59834cea08c87e9658014080efa02678ef54a088f84fa5647e81fee0
|
||||
F test/misuse.test 9e7f78402005e833af71dcab32d048003869eca5abcaccc985d4f8dc1d86bcc7
|
||||
F test/mjournal.test 28a08d5cb5fb5b5702a46e19176e45e964e0800d1f894677169e79f34030e152
|
||||
F test/mmap1.test 5c1f768828094b0dd94e55ae7f10489a1ded74772682be2c4c78679d0acaf7ef
|
||||
F test/mmap1.test 18de3fd7b70a777af6004ca2feecfcdd3d0be17fa04058e808baf530c94b1a1d
|
||||
F test/mmap2.test 9d6dd9ddb4ad2379f29cc78f38ce1e63ed418022
|
||||
F test/mmap3.test b3c297e78e6a8520aafcc1a8f140535594c9086e
|
||||
F test/mmap4.test 2e2b4e32555b58da15176e6fe750f17c9dcf7f93
|
||||
F test/mmapcorrupt.test 0d89724591f22a376019f3df60d075b838dd2ba6dae6effb0be465c49cf86d4a
|
||||
F test/mmapfault.test d4c9eff9cd8c2dc14bc43e71e042f175b0a26fe3
|
||||
F test/mmapwarm.test 2272005969cd17a910077bd5082f70bc1fefad9a875afec7fc9af483898ecaf3
|
||||
F test/multiplex.test d74c034e52805f6de8cc5432cef8c9eb774bb64ec29b83a22effc8ca4dac1f08
|
||||
@@ -1479,10 +1481,10 @@ F test/pendingrace.test 6aa33756b950c4529f79c4f3817a9a1e4025bd0d9961571a05c0279b
|
||||
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
|
||||
F test/permutations.test f7caf8dd5c7b1da74842a48df116f7f193399c656d4ffc805cd0d9658568c675
|
||||
F test/pg_common.tcl 3b27542224db1e713ae387459b5d117c836a5f6e328846922993b6d2b7640d9f
|
||||
F test/pragma.test 57a36226218c03cfb381019fe43234b2cefbd8a1f12825514f906a17ccf7991e
|
||||
F test/pragma.test 6e0bb3277d7293328a0cec417b967db62beb1700ae8e4e3cdb52be585705cbdd
|
||||
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
|
||||
F test/pragma3.test 92a46bbea12322dd94a404f49edcfbfc913a2c98115f0d030a7459bb4712ef31
|
||||
F test/pragma4.test ca5e4dfc46adfe490f75d73734f70349d95a199e6510973899e502eef2c8b1f8
|
||||
F test/pragma4.test 9559cf5173864bf47c0431873d158fbeb72f920a59905b1f46069d8543eccdab
|
||||
F test/pragma5.test 7b33fc43e2e41abf17f35fb73f71b49671a380ea92a6c94b6ce530a25f8d9102
|
||||
F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8
|
||||
F test/prefixes.test b524a1c44bffec225b9aec98bd728480352aa8532ac4c15771fb85e8beef65d9
|
||||
@@ -2070,8 +2072,8 @@ F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a
|
||||
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
|
||||
F tool/index_usage.c f62a0c701b2c7ff2f3e21d206f093c123f222dbf07136a10ffd1ca15a5c706c5
|
||||
F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f
|
||||
F tool/lemon.c 19e368bc8e97ff4071115119a7911ca3b0c56eba7926d8ada8b4a86fcc69a176
|
||||
F tool/lempar.c 57478ea48420da05faa873c6d1616321caa5464644588c97fbe8e0ea04450748
|
||||
F tool/lemon.c db6c77d899f565ab42217d924e5daee5b267724433c7747fb6d3329b3c919fa1
|
||||
F tool/lempar.c e6b649778e5c027c8365ff01d7ef39297cd7285fa1f881cce31792689541e79f
|
||||
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
|
||||
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
|
||||
F tool/logest.c c34e5944318415de513d29a6098df247a9618c96d83c38d4abd88641fe46e669
|
||||
@@ -2159,8 +2161,11 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 0a834bd81122b6e9c34c8253f9e45d53dab3274be28df60968366fa42237617b
|
||||
R 55b4daf0d623afe21abf6d430f07654f
|
||||
U drh
|
||||
Z 28de270bfc8a17f68f447b4061913785
|
||||
P 62010ba488f65aec3c6bd17b05f64c5b3e885dee4221e6016c4eb1053e19284d
|
||||
R f7f56a51df263c734cbee718d29c6a34
|
||||
T *branch * quick-check-counts
|
||||
T *sym-quick-check-counts *
|
||||
T -sym-trunk *
|
||||
U dan
|
||||
Z 3682eb48d291ba0b263b9d8bf9a6accb
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
59eb9d29e796886db17a578b64e75fd2797aebf969cbeeda70ecf2fda378c98f
|
||||
cc294c041b4c7a044ff344989f872415ced5263a0b654112371b2da7c852a688
|
||||
+68
-8
@@ -151,8 +151,47 @@ int corruptPageError(int lineno, MemPage *p){
|
||||
# define SQLITE_CORRUPT_PAGE(pMemPage) SQLITE_CORRUPT_PGNO(pMemPage->pgno)
|
||||
#endif
|
||||
|
||||
/* Default value for SHARED_LOCK_TRACE macro if shared-cache is disabled
|
||||
** or if the lock tracking is disabled. This is always the value for
|
||||
** release builds.
|
||||
*/
|
||||
#define SHARED_LOCK_TRACE(X,MSG,TAB,TYPE) /*no-op*/
|
||||
|
||||
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||
|
||||
#if 0
|
||||
/* ^---- Change to 1 and recompile to enable shared-lock tracing
|
||||
** for debugging purposes.
|
||||
**
|
||||
** Print all shared-cache locks on a BtShared. Debugging use only.
|
||||
*/
|
||||
static void sharedLockTrace(
|
||||
BtShared *pBt,
|
||||
const char *zMsg,
|
||||
int iRoot,
|
||||
int eLockType
|
||||
){
|
||||
BtLock *pLock;
|
||||
if( iRoot>0 ){
|
||||
printf("%s-%p %u%s:", zMsg, pBt, iRoot, eLockType==READ_LOCK?"R":"W");
|
||||
}else{
|
||||
printf("%s-%p:", zMsg, pBt);
|
||||
}
|
||||
for(pLock=pBt->pLock; pLock; pLock=pLock->pNext){
|
||||
printf(" %p/%u%s", pLock->pBtree, pLock->iTable,
|
||||
pLock->eLock==READ_LOCK ? "R" : "W");
|
||||
while( pLock->pNext && pLock->pBtree==pLock->pNext->pBtree ){
|
||||
pLock = pLock->pNext;
|
||||
printf(",%u%s", pLock->iTable, pLock->eLock==READ_LOCK ? "R" : "W");
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
#undef SHARED_LOCK_TRACE
|
||||
#define SHARED_LOCK_TRACE(X,MSG,TAB,TYPE) sharedLockTrace(X,MSG,TAB,TYPE)
|
||||
#endif /* Shared-lock tracing */
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
**** This function is only used as part of an assert() statement. ***
|
||||
@@ -229,6 +268,8 @@ static int hasSharedCacheTableLock(
|
||||
iTab = iRoot;
|
||||
}
|
||||
|
||||
SHARED_LOCK_TRACE(pBtree->pBt,"hasLock",iRoot,eLockType);
|
||||
|
||||
/* Search for the required lock. Either a write-lock on root-page iTab, a
|
||||
** write-lock on the schema table, or (if the client is reading) a
|
||||
** read-lock on iTab will suffice. Return 1 if any of these are found. */
|
||||
@@ -362,6 +403,8 @@ static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){
|
||||
BtLock *pLock = 0;
|
||||
BtLock *pIter;
|
||||
|
||||
SHARED_LOCK_TRACE(pBt,"setLock", iTable, eLock);
|
||||
|
||||
assert( sqlite3BtreeHoldsMutex(p) );
|
||||
assert( eLock==READ_LOCK || eLock==WRITE_LOCK );
|
||||
assert( p->db!=0 );
|
||||
@@ -429,6 +472,8 @@ static void clearAllSharedCacheTableLocks(Btree *p){
|
||||
assert( p->sharable || 0==*ppIter );
|
||||
assert( p->inTrans>0 );
|
||||
|
||||
SHARED_LOCK_TRACE(pBt, "clearAllLocks", 0, 0);
|
||||
|
||||
while( *ppIter ){
|
||||
BtLock *pLock = *ppIter;
|
||||
assert( (pBt->btsFlags & BTS_EXCLUSIVE)==0 || pBt->pWriter==pLock->pBtree );
|
||||
@@ -467,6 +512,9 @@ static void clearAllSharedCacheTableLocks(Btree *p){
|
||||
*/
|
||||
static void downgradeAllSharedCacheTableLocks(Btree *p){
|
||||
BtShared *pBt = p->pBt;
|
||||
|
||||
SHARED_LOCK_TRACE(pBt, "downgradeLocks", 0, 0);
|
||||
|
||||
if( pBt->pWriter==p ){
|
||||
BtLock *pLock;
|
||||
pBt->pWriter = 0;
|
||||
@@ -6280,7 +6328,10 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur){
|
||||
}
|
||||
|
||||
pPage = pCur->pPage;
|
||||
assert( pPage->isInit );
|
||||
if( sqlite3FaultSim(412) ) pPage->isInit = 0;
|
||||
if( !pPage->isInit ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
if( !pPage->leaf ){
|
||||
int idx = pCur->ix;
|
||||
rc = moveToChild(pCur, get4byte(findCell(pPage, idx)));
|
||||
@@ -10740,6 +10791,9 @@ static int checkTreePage(
|
||||
** number of cells on the page. */
|
||||
nCell = get2byte(&data[hdr+3]);
|
||||
assert( pPage->nCell==nCell );
|
||||
if( pPage->leaf || pPage->intKey==0 ){
|
||||
pCheck->nRow += nCell;
|
||||
}
|
||||
|
||||
/* EVIDENCE-OF: R-23882-45353 The cell pointer array of a b-tree page
|
||||
** immediately follows the b-tree page header. */
|
||||
@@ -10950,6 +11004,7 @@ int sqlite3BtreeIntegrityCheck(
|
||||
sqlite3 *db, /* Database connection that is running the check */
|
||||
Btree *p, /* The btree to be checked */
|
||||
Pgno *aRoot, /* An array of root pages numbers for individual trees */
|
||||
Mem *aCnt, /* Memory cells to write counts for each tree to */
|
||||
int nRoot, /* Number of entries in aRoot[] */
|
||||
int mxErr, /* Stop reporting errors after this many */
|
||||
int *pnErr, /* OUT: Write number of errors seen to this variable */
|
||||
@@ -11036,15 +11091,20 @@ int sqlite3BtreeIntegrityCheck(
|
||||
testcase( pBt->db->flags & SQLITE_CellSizeCk );
|
||||
pBt->db->flags &= ~(u64)SQLITE_CellSizeCk;
|
||||
for(i=0; (int)i<nRoot && sCheck.mxErr; i++){
|
||||
i64 notUsed;
|
||||
if( aRoot[i]==0 ) continue;
|
||||
sCheck.nRow = 0;
|
||||
if( aRoot[i] && sCheck.mxErr ){
|
||||
i64 notUsed;
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
if( pBt->autoVacuum && aRoot[i]>1 && !bPartial ){
|
||||
checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0);
|
||||
}
|
||||
if( pBt->autoVacuum && aRoot[i]>1 && !bPartial ){
|
||||
checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0);
|
||||
}
|
||||
#endif
|
||||
sCheck.v0 = aRoot[i];
|
||||
checkTreePage(&sCheck, aRoot[i], ¬Used, LARGEST_INT64);
|
||||
sCheck.v0 = aRoot[i];
|
||||
checkTreePage(&sCheck, aRoot[i], ¬Used, LARGEST_INT64);
|
||||
}
|
||||
if( aCnt ){
|
||||
sqlite3MemSetArrayInt64(aCnt, i, sCheck.nRow);
|
||||
}
|
||||
}
|
||||
pBt->db->flags = savedDbFlags;
|
||||
|
||||
|
||||
@@ -331,6 +331,7 @@ int sqlite3BtreeIntegrityCheck(
|
||||
sqlite3 *db, /* Database connection that is running the check */
|
||||
Btree *p, /* The btree to be checked */
|
||||
Pgno *aRoot, /* An array of root pages numbers for individual trees */
|
||||
sqlite3_value *aCnt, /* OUT: entry counts for each btree in aRoot[] */
|
||||
int nRoot, /* Number of entries in aRoot[] */
|
||||
int mxErr, /* Stop reporting errors after this many */
|
||||
int *pnErr, /* OUT: Write number of errors seen to this variable */
|
||||
|
||||
@@ -707,6 +707,7 @@ struct IntegrityCk {
|
||||
StrAccum errMsg; /* Accumulate the error message text here */
|
||||
u32 *heap; /* Min-heap used for analyzing cell coverage */
|
||||
sqlite3 *db; /* Database connection running the check */
|
||||
i64 nRow; /* Number of rows visited in current tree */
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
+88
-57
@@ -621,6 +621,40 @@ static void jsonAppendSeparator(JsonString *p){
|
||||
jsonAppendChar(p, ',');
|
||||
}
|
||||
|
||||
/* c is a control character. Append the canonical JSON representation
|
||||
** of that control character to p.
|
||||
**
|
||||
** This routine assumes that the output buffer has already been enlarged
|
||||
** sufficiently to hold the worst-case encoding plus a nul terminator.
|
||||
*/
|
||||
static void jsonAppendControlChar(JsonString *p, u8 c){
|
||||
static const char aSpecial[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
assert( sizeof(aSpecial)==32 );
|
||||
assert( aSpecial['\b']=='b' );
|
||||
assert( aSpecial['\f']=='f' );
|
||||
assert( aSpecial['\n']=='n' );
|
||||
assert( aSpecial['\r']=='r' );
|
||||
assert( aSpecial['\t']=='t' );
|
||||
assert( c>=0 && c<sizeof(aSpecial) );
|
||||
assert( p->nUsed+7 <= p->nAlloc );
|
||||
if( aSpecial[c] ){
|
||||
p->zBuf[p->nUsed] = '\\';
|
||||
p->zBuf[p->nUsed+1] = aSpecial[c];
|
||||
p->nUsed += 2;
|
||||
}else{
|
||||
p->zBuf[p->nUsed] = '\\';
|
||||
p->zBuf[p->nUsed+1] = 'u';
|
||||
p->zBuf[p->nUsed+2] = '0';
|
||||
p->zBuf[p->nUsed+3] = '0';
|
||||
p->zBuf[p->nUsed+4] = "0123456789abcdef"[c>>4];
|
||||
p->zBuf[p->nUsed+5] = "0123456789abcdef"[c&0xf];
|
||||
p->nUsed += 6;
|
||||
}
|
||||
}
|
||||
|
||||
/* Append the N-byte string in zIn to the end of the JsonString string
|
||||
** under construction. Enclose the string in double-quotes ("...") and
|
||||
** escape any double-quotes or backslash characters contained within the
|
||||
@@ -680,35 +714,14 @@ static void jsonAppendString(JsonString *p, const char *zIn, u32 N){
|
||||
}
|
||||
c = z[0];
|
||||
if( c=='"' || c=='\\' ){
|
||||
json_simple_escape:
|
||||
if( (p->nUsed+N+3 > p->nAlloc) && jsonStringGrow(p,N+3)!=0 ) return;
|
||||
p->zBuf[p->nUsed++] = '\\';
|
||||
p->zBuf[p->nUsed++] = c;
|
||||
}else if( c=='\'' ){
|
||||
p->zBuf[p->nUsed++] = c;
|
||||
}else{
|
||||
static const char aSpecial[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
assert( sizeof(aSpecial)==32 );
|
||||
assert( aSpecial['\b']=='b' );
|
||||
assert( aSpecial['\f']=='f' );
|
||||
assert( aSpecial['\n']=='n' );
|
||||
assert( aSpecial['\r']=='r' );
|
||||
assert( aSpecial['\t']=='t' );
|
||||
assert( c>=0 && c<sizeof(aSpecial) );
|
||||
if( aSpecial[c] ){
|
||||
c = aSpecial[c];
|
||||
goto json_simple_escape;
|
||||
}
|
||||
if( (p->nUsed+N+7 > p->nAlloc) && jsonStringGrow(p,N+7)!=0 ) return;
|
||||
p->zBuf[p->nUsed++] = '\\';
|
||||
p->zBuf[p->nUsed++] = 'u';
|
||||
p->zBuf[p->nUsed++] = '0';
|
||||
p->zBuf[p->nUsed++] = '0';
|
||||
p->zBuf[p->nUsed++] = "0123456789abcdef"[c>>4];
|
||||
p->zBuf[p->nUsed++] = "0123456789abcdef"[c&0xf];
|
||||
jsonAppendControlChar(p, c);
|
||||
}
|
||||
z++;
|
||||
N--;
|
||||
@@ -1409,7 +1422,10 @@ static u32 jsonbValidityCheck(
|
||||
if( !jsonIsOk[z[j]] && z[j]!='\'' ){
|
||||
if( z[j]=='"' ){
|
||||
if( x==JSONB_TEXTJ ) return j+1;
|
||||
}else if( z[j]!='\\' || j+1>=k ){
|
||||
}else if( z[j]<=0x1f ){
|
||||
/* Control characters in JSON5 string literals are ok */
|
||||
if( x==JSONB_TEXTJ ) return j+1;
|
||||
}else if( NEVER(z[j]!='\\') || j+1>=k ){
|
||||
return j+1;
|
||||
}else if( strchr("\"\\/bfnrt",z[j+1])!=0 ){
|
||||
j++;
|
||||
@@ -1703,9 +1719,14 @@ json_parse_restart:
|
||||
return -1;
|
||||
}
|
||||
}else if( c<=0x1f ){
|
||||
/* Control characters are not allowed in strings */
|
||||
pParse->iErr = j;
|
||||
return -1;
|
||||
if( c==0 ){
|
||||
pParse->iErr = j;
|
||||
return -1;
|
||||
}
|
||||
/* Control characters are not allowed in canonical JSON string
|
||||
** literals, but are allowed in JSON5 string literals. */
|
||||
opcode = JSONB_TEXT5;
|
||||
pParse->hasNonstd = 1;
|
||||
}else if( c=='"' ){
|
||||
opcode = JSONB_TEXT5;
|
||||
}
|
||||
@@ -2073,8 +2094,8 @@ static u32 jsonbPayloadSize(const JsonParse *pParse, u32 i, u32 *pSz){
|
||||
(pParse->aBlob[i+7]<<8) + pParse->aBlob[i+8];
|
||||
n = 9;
|
||||
}
|
||||
if( i+sz+n > pParse->nBlob
|
||||
&& i+sz+n > pParse->nBlob-pParse->delta
|
||||
if( (i64)i+sz+n > pParse->nBlob
|
||||
&& (i64)i+sz+n > pParse->nBlob-pParse->delta
|
||||
){
|
||||
sz = 0;
|
||||
n = 0;
|
||||
@@ -2124,6 +2145,7 @@ static u32 jsonTranslateBlobToText(
|
||||
}
|
||||
case JSONB_INT:
|
||||
case JSONB_FLOAT: {
|
||||
if( sz==0 ) goto malformed_jsonb;
|
||||
jsonAppendRaw(pOut, (const char*)&pParse->aBlob[i+n], sz);
|
||||
break;
|
||||
}
|
||||
@@ -2132,6 +2154,7 @@ static u32 jsonTranslateBlobToText(
|
||||
sqlite3_uint64 u = 0;
|
||||
const char *zIn = (const char*)&pParse->aBlob[i+n];
|
||||
int bOverflow = 0;
|
||||
if( sz==0 ) goto malformed_jsonb;
|
||||
if( zIn[0]=='-' ){
|
||||
jsonAppendChar(pOut, '-');
|
||||
k++;
|
||||
@@ -2154,6 +2177,7 @@ static u32 jsonTranslateBlobToText(
|
||||
case JSONB_FLOAT5: { /* Float literal missing digits beside "." */
|
||||
u32 k = 0;
|
||||
const char *zIn = (const char*)&pParse->aBlob[i+n];
|
||||
if( sz==0 ) goto malformed_jsonb;
|
||||
if( zIn[0]=='-' ){
|
||||
jsonAppendChar(pOut, '-');
|
||||
k++;
|
||||
@@ -2183,7 +2207,7 @@ static u32 jsonTranslateBlobToText(
|
||||
zIn = (const char*)&pParse->aBlob[i+n];
|
||||
jsonAppendChar(pOut, '"');
|
||||
while( sz2>0 ){
|
||||
for(k=0; k<sz2 && zIn[k]!='\\' && zIn[k]!='"'; k++){}
|
||||
for(k=0; k<sz2 && (jsonIsOk[(u8)zIn[k]] || zIn[k]=='\''); k++){}
|
||||
if( k>0 ){
|
||||
jsonAppendRawNZ(pOut, zIn, k);
|
||||
if( k>=sz2 ){
|
||||
@@ -2198,6 +2222,13 @@ static u32 jsonTranslateBlobToText(
|
||||
sz2--;
|
||||
continue;
|
||||
}
|
||||
if( zIn[0]<=0x1f ){
|
||||
if( pOut->nUsed+7>pOut->nAlloc && jsonStringGrow(pOut,7) ) break;
|
||||
jsonAppendControlChar(pOut, zIn[0]);
|
||||
zIn++;
|
||||
sz2--;
|
||||
continue;
|
||||
}
|
||||
assert( zIn[0]=='\\' );
|
||||
assert( sz2>=1 );
|
||||
if( sz2<2 ){
|
||||
@@ -2267,10 +2298,11 @@ static u32 jsonTranslateBlobToText(
|
||||
jsonAppendChar(pOut, '[');
|
||||
j = i+n;
|
||||
iEnd = j+sz;
|
||||
while( j<iEnd ){
|
||||
while( j<iEnd && pOut->eErr==0 ){
|
||||
j = jsonTranslateBlobToText(pParse, j, pOut);
|
||||
jsonAppendChar(pOut, ',');
|
||||
}
|
||||
if( j>iEnd ) pOut->eErr |= JSTRING_MALFORMED;
|
||||
if( sz>0 ) jsonStringTrimOneChar(pOut);
|
||||
jsonAppendChar(pOut, ']');
|
||||
break;
|
||||
@@ -2280,17 +2312,18 @@ static u32 jsonTranslateBlobToText(
|
||||
jsonAppendChar(pOut, '{');
|
||||
j = i+n;
|
||||
iEnd = j+sz;
|
||||
while( j<iEnd ){
|
||||
while( j<iEnd && pOut->eErr==0 ){
|
||||
j = jsonTranslateBlobToText(pParse, j, pOut);
|
||||
jsonAppendChar(pOut, (x++ & 1) ? ',' : ':');
|
||||
}
|
||||
if( x & 1 ) pOut->eErr |= JSTRING_MALFORMED;
|
||||
if( (x & 1)!=0 || j>iEnd ) pOut->eErr |= JSTRING_MALFORMED;
|
||||
if( sz>0 ) jsonStringTrimOneChar(pOut);
|
||||
jsonAppendChar(pOut, '}');
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
malformed_jsonb:
|
||||
pOut->eErr |= JSTRING_MALFORMED;
|
||||
break;
|
||||
}
|
||||
@@ -3311,20 +3344,18 @@ rebuild_from_cache:
|
||||
}
|
||||
return p;
|
||||
}
|
||||
#if defined(SQLITE_JSON_BLOB_INPUT_BUG_COMPATIBLE)
|
||||
/* If the input is a BLOB that is not JSONB, fall through into trying
|
||||
** to process that BLOB as if it where text. This goes against all
|
||||
** historical documentation about how the SQLite JSON functions are
|
||||
** suppose to work. Nevertheless, many SQLite implementations prior to
|
||||
** version 3.45.0 contained a bug such that they did behave this way
|
||||
** and some applications came to depend upon this buggy behavior. The
|
||||
** SQLITE_JSON_BLOB_INPUT_BUG_COMPATIBLE compile-time option provides
|
||||
** a mechanism for those applications to continue working even after
|
||||
** the bug was fixed. See
|
||||
** https://sqlite.org/forum/forumpost/012136abd5292b8d */
|
||||
#else
|
||||
goto json_pfa_malformed;
|
||||
#endif
|
||||
/* If the blob is not valid JSONB, fall through into trying to cast
|
||||
** the blob into text which is then interpreted as JSON. (tag-20240123-a)
|
||||
**
|
||||
** This goes against all historical documentation about how the SQLite
|
||||
** JSON functions were suppose to work. From the beginning, blob was
|
||||
** reserved for expansion and a blob value should have raised an error.
|
||||
** But it did not, due to a bug. And many applications came to depend
|
||||
** upon this buggy behavior, espeically when using the CLI and reading
|
||||
** JSON text using readfile(), which returns a blob. For this reason
|
||||
** we will continue to support the bug moving forward.
|
||||
** See for example https://sqlite.org/forum/forumpost/012136abd5292b8d
|
||||
*/
|
||||
}
|
||||
p->zJson = (char*)sqlite3_value_text(pArg);
|
||||
p->nJson = sqlite3_value_bytes(pArg);
|
||||
@@ -3549,11 +3580,12 @@ static void jsonParseFunc(
|
||||
if( p==0 ) return;
|
||||
if( argc==1 ){
|
||||
jsonDebugPrintBlob(p, 0, p->nBlob, 0, &out);
|
||||
sqlite3_result_text64(ctx, out.zText, out.nChar, SQLITE_DYNAMIC, SQLITE_UTF8);
|
||||
sqlite3_result_text64(ctx,out.zText,out.nChar,SQLITE_TRANSIENT,SQLITE_UTF8);
|
||||
}else{
|
||||
jsonShowParse(p);
|
||||
}
|
||||
jsonParseFree(p);
|
||||
sqlite3_str_reset(&out);
|
||||
}
|
||||
#endif /* SQLITE_DEBUG */
|
||||
|
||||
@@ -4300,12 +4332,12 @@ static void jsonValidFunc(
|
||||
return;
|
||||
}
|
||||
case SQLITE_BLOB: {
|
||||
if( (flags & 0x0c)!=0 && jsonFuncArgMightBeBinary(argv[0]) ){
|
||||
if( jsonFuncArgMightBeBinary(argv[0]) ){
|
||||
if( flags & 0x04 ){
|
||||
/* Superficial checking only - accomplished by the
|
||||
** jsonFuncArgMightBeBinary() call above. */
|
||||
res = 1;
|
||||
}else{
|
||||
}else if( flags & 0x08 ){
|
||||
/* Strict checking. Check by translating BLOB->TEXT->BLOB. If
|
||||
** no errors occur, call that a "strict check". */
|
||||
JsonParse px;
|
||||
@@ -4316,8 +4348,11 @@ static void jsonValidFunc(
|
||||
iErr = jsonbValidityCheck(&px, 0, px.nBlob, 1);
|
||||
res = iErr==0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
/* Fall through into interpreting the input as text. See note
|
||||
** above at tag-20240123-a. */
|
||||
/* no break */ deliberate_fall_through
|
||||
}
|
||||
default: {
|
||||
JsonParse px;
|
||||
@@ -5053,13 +5088,9 @@ static int jsonEachFilter(
|
||||
memset(&p->sParse, 0, sizeof(p->sParse));
|
||||
p->sParse.nJPRef = 1;
|
||||
p->sParse.db = p->db;
|
||||
if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
|
||||
if( jsonFuncArgMightBeBinary(argv[0]) ){
|
||||
p->sParse.nBlob = sqlite3_value_bytes(argv[0]);
|
||||
p->sParse.aBlob = (u8*)sqlite3_value_blob(argv[0]);
|
||||
}else{
|
||||
goto json_each_malformed_input;
|
||||
}
|
||||
if( jsonFuncArgMightBeBinary(argv[0]) ){
|
||||
p->sParse.nBlob = sqlite3_value_bytes(argv[0]);
|
||||
p->sParse.aBlob = (u8*)sqlite3_value_blob(argv[0]);
|
||||
}else{
|
||||
p->sParse.zJson = (char*)sqlite3_value_text(argv[0]);
|
||||
p->sParse.nJson = sqlite3_value_bytes(argv[0]);
|
||||
|
||||
@@ -221,6 +221,24 @@ static void sqlite3MallocAlarm(int nByte){
|
||||
sqlite3_mutex_enter(mem0.mutex);
|
||||
}
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
** This routine is called whenever an out-of-memory condition is seen,
|
||||
** It's only purpose to to serve as a breakpoint for gdb or similar
|
||||
** code debuggers when working on out-of-memory conditions, for example
|
||||
** caused by PRAGMA hard_heap_limit=N.
|
||||
*/
|
||||
static SQLITE_NOINLINE void test_oom_breakpoint(void){
|
||||
static u64 nOomFault = 0;
|
||||
nOomFault++;
|
||||
/* The assert() is never reached in a human lifetime. It is here mostly
|
||||
** to prevent code optimizers from optimizing out this function. */
|
||||
assert( (nOomFault>>32) < 0xffffffff );
|
||||
}
|
||||
#else
|
||||
# define test_oom_breakpoint(X) /* No-op for production builds */
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Do a memory allocation with statistics and alarms. Assume the
|
||||
** lock is already held.
|
||||
@@ -247,6 +265,7 @@ static void mallocWithAlarm(int n, void **pp){
|
||||
if( mem0.hardLimit ){
|
||||
nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
|
||||
if( nUsed >= mem0.hardLimit - nFull ){
|
||||
test_oom_breakpoint();
|
||||
*pp = 0;
|
||||
return;
|
||||
}
|
||||
@@ -535,6 +554,7 @@ void *sqlite3Realloc(void *pOld, u64 nBytes){
|
||||
sqlite3MallocAlarm(nDiff);
|
||||
if( mem0.hardLimit>0 && nUsed >= mem0.hardLimit - nDiff ){
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
test_oom_breakpoint();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
+6
-1
@@ -5441,11 +5441,16 @@ static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
|
||||
|
||||
#if SQLITE_MAX_MMAP_SIZE>0
|
||||
if( pFd->mmapSizeMax>0 ){
|
||||
/* Ensure that there is always at least a 256 byte buffer of addressable
|
||||
** memory following the returned page. If the database is corrupt,
|
||||
** SQLite may overread the page slightly (in practice only a few bytes,
|
||||
** but 256 is safe, round, number). */
|
||||
const int nEofBuffer = 256;
|
||||
if( pFd->pMapRegion==0 ){
|
||||
int rc = unixMapfile(pFd, -1);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
}
|
||||
if( pFd->mmapSize >= iOff+nAmt ){
|
||||
if( pFd->mmapSize >= (iOff+nAmt+nEofBuffer) ){
|
||||
*pp = &((u8 *)pFd->pMapRegion)[iOff];
|
||||
pFd->nFetchOut++;
|
||||
}
|
||||
|
||||
+6
-1
@@ -4521,6 +4521,11 @@ static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
|
||||
|
||||
#if SQLITE_MAX_MMAP_SIZE>0
|
||||
if( pFd->mmapSizeMax>0 ){
|
||||
/* Ensure that there is always at least a 256 byte buffer of addressable
|
||||
** memory following the returned page. If the database is corrupt,
|
||||
** SQLite may overread the page slightly (in practice only a few bytes,
|
||||
** but 256 is safe, round, number). */
|
||||
const int nEofBuffer = 256;
|
||||
if( pFd->pMapRegion==0 ){
|
||||
int rc = winMapfile(pFd, -1);
|
||||
if( rc!=SQLITE_OK ){
|
||||
@@ -4529,7 +4534,7 @@ static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
if( pFd->mmapSize >= iOff+nAmt ){
|
||||
if( pFd->mmapSize >= (iOff+nAmt+nEofBuffer) ){
|
||||
assert( pFd->pMapRegion!=0 );
|
||||
*pp = &((u8 *)pFd->pMapRegion)[iOff];
|
||||
pFd->nFetchOut++;
|
||||
|
||||
+13
-1
@@ -21,6 +21,10 @@
|
||||
*/
|
||||
}
|
||||
|
||||
// Function used to enlarge the parser stack, if needed
|
||||
%realloc parserStackRealloc
|
||||
%free sqlite3_free
|
||||
|
||||
// All token codes are small integers with #defines that begin with "TK_"
|
||||
%token_prefix TK_
|
||||
|
||||
@@ -45,7 +49,7 @@
|
||||
}
|
||||
}
|
||||
%stack_overflow {
|
||||
sqlite3ErrorMsg(pParse, "parser stack overflow");
|
||||
sqlite3OomFault(pParse->db);
|
||||
}
|
||||
|
||||
// The name of the generated procedure that implements the parser
|
||||
@@ -547,6 +551,14 @@ cmd ::= select(X). {
|
||||
}
|
||||
return pSelect;
|
||||
}
|
||||
|
||||
/* Memory allocator for parser stack resizing. This is a thin wrapper around
|
||||
** sqlite3_realloc() that includes a call to sqlite3FaultSim() to facilitate
|
||||
** testing.
|
||||
*/
|
||||
static void *parserStackRealloc(void *pOld, sqlite3_uint64 newSize){
|
||||
return sqlite3FaultSim(700) ? 0 : sqlite3_realloc(pOld, newSize);
|
||||
}
|
||||
}
|
||||
|
||||
%ifndef SQLITE_OMIT_CTE
|
||||
|
||||
+69
-44
@@ -1692,7 +1692,6 @@ void sqlite3Pragma(
|
||||
Hash *pTbls; /* Set of all tables in the schema */
|
||||
int *aRoot; /* Array of root page numbers of all btrees */
|
||||
int cnt = 0; /* Number of entries in aRoot[] */
|
||||
int mxIdx = 0; /* Maximum number of indexes for any table */
|
||||
|
||||
if( OMIT_TEMPDB && i==1 ) continue;
|
||||
if( iDb>=0 && i!=iDb ) continue;
|
||||
@@ -1714,7 +1713,6 @@ void sqlite3Pragma(
|
||||
if( pObjTab && pObjTab!=pTab ) continue;
|
||||
if( HasRowid(pTab) ) cnt++;
|
||||
for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ cnt++; }
|
||||
if( nIdx>mxIdx ) mxIdx = nIdx;
|
||||
}
|
||||
if( cnt==0 ) continue;
|
||||
if( pObjTab ) cnt++;
|
||||
@@ -1734,11 +1732,11 @@ void sqlite3Pragma(
|
||||
aRoot[0] = cnt;
|
||||
|
||||
/* Make sure sufficient number of registers have been allocated */
|
||||
sqlite3TouchRegister(pParse, 8+mxIdx);
|
||||
sqlite3TouchRegister(pParse, 8+cnt);
|
||||
sqlite3ClearTempRegCache(pParse);
|
||||
|
||||
/* Do the b-tree integrity checks */
|
||||
sqlite3VdbeAddOp4(v, OP_IntegrityCk, 2, cnt, 1, (char*)aRoot,P4_INTARRAY);
|
||||
sqlite3VdbeAddOp4(v, OP_IntegrityCk, 1, cnt, 8, (char*)aRoot,P4_INTARRAY);
|
||||
sqlite3VdbeChangeP5(v, (u8)i);
|
||||
addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
|
||||
@@ -1748,6 +1746,36 @@ void sqlite3Pragma(
|
||||
integrityCheckResultRow(v);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
|
||||
/* Check that the indexes all have the right number of rows */
|
||||
cnt = pObjTab ? 1 : 0;
|
||||
sqlite3VdbeLoadString(v, 2, "wrong # of entries in index ");
|
||||
for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
|
||||
int iTab = 0;
|
||||
Table *pTab = sqliteHashData(x);
|
||||
Index *pIdx;
|
||||
if( pObjTab && pObjTab!=pTab ) continue;
|
||||
if( HasRowid(pTab) ){
|
||||
iTab = cnt++;
|
||||
}else{
|
||||
iTab = cnt;
|
||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
if( IsPrimaryKeyIndex(pIdx) ) break;
|
||||
iTab++;
|
||||
}
|
||||
}
|
||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
if( pIdx->pPartIdxWhere==0 ){
|
||||
addr = sqlite3VdbeAddOp3(v, OP_Eq, 8+cnt, 0, 8+iTab);
|
||||
VdbeCoverage(v);
|
||||
sqlite3VdbeLoadString(v, 4, pIdx->zName);
|
||||
sqlite3VdbeAddOp3(v, OP_Concat, 4, 2, 3);
|
||||
integrityCheckResultRow(v);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure all the indices are constructed correctly.
|
||||
*/
|
||||
for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
|
||||
@@ -1762,31 +1790,7 @@ void sqlite3Pragma(
|
||||
int mxCol; /* Maximum non-virtual column number */
|
||||
|
||||
if( pObjTab && pObjTab!=pTab ) continue;
|
||||
if( !IsOrdinaryTable(pTab) ){
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
sqlite3_vtab *pVTab;
|
||||
int a1;
|
||||
if( !IsVirtual(pTab) ) continue;
|
||||
if( pTab->nCol<=0 ){
|
||||
const char *zMod = pTab->u.vtab.azArg[0];
|
||||
if( sqlite3HashFind(&db->aModule, zMod)==0 ) continue;
|
||||
}
|
||||
sqlite3ViewGetColumnNames(pParse, pTab);
|
||||
if( pTab->u.vtab.p==0 ) continue;
|
||||
pVTab = pTab->u.vtab.p->pVtab;
|
||||
if( NEVER(pVTab==0) ) continue;
|
||||
if( NEVER(pVTab->pModule==0) ) continue;
|
||||
if( pVTab->pModule->iVersion<4 ) continue;
|
||||
if( pVTab->pModule->xIntegrity==0 ) continue;
|
||||
sqlite3VdbeAddOp3(v, OP_VCheck, i, 3, isQuick);
|
||||
pTab->nTabRef++;
|
||||
sqlite3VdbeAppendP4(v, pTab, P4_TABLEREF);
|
||||
a1 = sqlite3VdbeAddOp1(v, OP_IsNull, 3); VdbeCoverage(v);
|
||||
integrityCheckResultRow(v);
|
||||
sqlite3VdbeJumpHere(v, a1);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
if( !IsOrdinaryTable(pTab) ) continue;
|
||||
if( isQuick || HasRowid(pTab) ){
|
||||
pPk = 0;
|
||||
r2 = 0;
|
||||
@@ -2094,23 +2098,44 @@ void sqlite3Pragma(
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v);
|
||||
sqlite3VdbeJumpHere(v, loopTop-1);
|
||||
if( !isQuick ){
|
||||
sqlite3VdbeLoadString(v, 2, "wrong # of entries in index ");
|
||||
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
|
||||
if( pPk==pIdx ) continue;
|
||||
sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3);
|
||||
addr = sqlite3VdbeAddOp3(v, OP_Eq, 8+j, 0, 3); VdbeCoverage(v);
|
||||
sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
|
||||
sqlite3VdbeLoadString(v, 4, pIdx->zName);
|
||||
sqlite3VdbeAddOp3(v, OP_Concat, 4, 2, 3);
|
||||
integrityCheckResultRow(v);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
}
|
||||
if( pPk ){
|
||||
sqlite3ReleaseTempRange(pParse, r2, pPk->nKeyCol);
|
||||
}
|
||||
if( pPk ){
|
||||
assert( !isQuick );
|
||||
sqlite3ReleaseTempRange(pParse, r2, pPk->nKeyCol);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
/* Second pass to invoke the xIntegrity method on all virtual
|
||||
** tables.
|
||||
*/
|
||||
for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
|
||||
Table *pTab = sqliteHashData(x);
|
||||
sqlite3_vtab *pVTab;
|
||||
int a1;
|
||||
if( pObjTab && pObjTab!=pTab ) continue;
|
||||
if( IsOrdinaryTable(pTab) ) continue;
|
||||
if( !IsVirtual(pTab) ) continue;
|
||||
if( pTab->nCol<=0 ){
|
||||
const char *zMod = pTab->u.vtab.azArg[0];
|
||||
if( sqlite3HashFind(&db->aModule, zMod)==0 ) continue;
|
||||
}
|
||||
sqlite3ViewGetColumnNames(pParse, pTab);
|
||||
if( pTab->u.vtab.p==0 ) continue;
|
||||
pVTab = pTab->u.vtab.p->pVtab;
|
||||
if( NEVER(pVTab==0) ) continue;
|
||||
if( NEVER(pVTab->pModule==0) ) continue;
|
||||
if( pVTab->pModule->iVersion<4 ) continue;
|
||||
if( pVTab->pModule->xIntegrity==0 ) continue;
|
||||
sqlite3VdbeAddOp3(v, OP_VCheck, i, 3, isQuick);
|
||||
pTab->nTabRef++;
|
||||
sqlite3VdbeAppendP4(v, pTab, P4_TABLEREF);
|
||||
a1 = sqlite3VdbeAddOp1(v, OP_IsNull, 3); VdbeCoverage(v);
|
||||
integrityCheckResultRow(v);
|
||||
sqlite3VdbeJumpHere(v, a1);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
{
|
||||
static const int iLn = VDBE_OFFSET_LINENO(2);
|
||||
|
||||
+1
-1
@@ -11926,7 +11926,7 @@ static void usage(int showDetail){
|
||||
}else{
|
||||
eputz("Use the -help option for additional information\n");
|
||||
}
|
||||
exit(1);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+1
-1
@@ -886,7 +886,7 @@ typedef INT16_TYPE LogEst;
|
||||
# define SQLITE_PTRSIZE __SIZEOF_POINTER__
|
||||
# elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \
|
||||
defined(_M_ARM) || defined(__arm__) || defined(__x86) || \
|
||||
(defined(__APPLE__) && defined(__POWERPC__)) || \
|
||||
(defined(__APPLE__) && defined(__ppc__)) || \
|
||||
(defined(__TOS_AIX__) && !defined(__64BIT__))
|
||||
# define SQLITE_PTRSIZE 4
|
||||
# else
|
||||
|
||||
+9
-9
@@ -7096,11 +7096,11 @@ case OP_DropTrigger: {
|
||||
/* Opcode: IntegrityCk P1 P2 P3 P4 P5
|
||||
**
|
||||
** Do an analysis of the currently open database. Store in
|
||||
** register P1 the text of an error message describing any problems.
|
||||
** If no problems are found, store a NULL in register P1.
|
||||
** register (P1+1) the text of an error message describing any problems.
|
||||
** If no problems are found, store a NULL in register (P1+1).
|
||||
**
|
||||
** The register P3 contains one less than the maximum number of allowed errors.
|
||||
** At most reg(P3) errors will be reported.
|
||||
** The register (P1) contains one less than the maximum number of allowed
|
||||
** errors. At most reg(P1) errors will be reported.
|
||||
** In other words, the analysis stops as soon as reg(P1) errors are
|
||||
** seen. Reg(P1) is updated with the number of errors remaining.
|
||||
**
|
||||
@@ -7124,15 +7124,15 @@ case OP_IntegrityCk: {
|
||||
aRoot = pOp->p4.ai;
|
||||
assert( nRoot>0 );
|
||||
assert( aRoot[0]==(Pgno)nRoot );
|
||||
assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
|
||||
pnErr = &aMem[pOp->p3];
|
||||
assert( pOp->p1>0 && (pOp->p1+1)<=(p->nMem+1 - p->nCursor) );
|
||||
pnErr = &aMem[pOp->p1];
|
||||
assert( (pnErr->flags & MEM_Int)!=0 );
|
||||
assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 );
|
||||
pIn1 = &aMem[pOp->p1];
|
||||
pIn1 = &aMem[pOp->p1+1];
|
||||
assert( pOp->p5<db->nDb );
|
||||
assert( DbMaskTest(p->btreeMask, pOp->p5) );
|
||||
rc = sqlite3BtreeIntegrityCheck(db, db->aDb[pOp->p5].pBt, &aRoot[1], nRoot,
|
||||
(int)pnErr->u.i+1, &nErr, &z);
|
||||
rc = sqlite3BtreeIntegrityCheck(db, db->aDb[pOp->p5].pBt, &aRoot[1],
|
||||
&aMem[pOp->p3], nRoot, (int)pnErr->u.i+1, &nErr, &z);
|
||||
sqlite3VdbeMemSetNull(pIn1);
|
||||
if( nErr==0 ){
|
||||
assert( z==0 );
|
||||
|
||||
@@ -296,6 +296,8 @@ RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);
|
||||
void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
|
||||
int sqlite3VdbeHasSubProgram(Vdbe*);
|
||||
|
||||
void sqlite3MemSetArrayInt64(sqlite3_value *aMem, int iIdx, i64 val);
|
||||
|
||||
int sqlite3NotPureFunc(sqlite3_context*);
|
||||
#ifdef SQLITE_ENABLE_BYTECODE_VTAB
|
||||
int sqlite3VdbeBytecodeVtabInit(sqlite3*);
|
||||
|
||||
@@ -943,6 +943,11 @@ void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){
|
||||
}
|
||||
}
|
||||
|
||||
void sqlite3MemSetArrayInt64(sqlite3_value *aMem, int iIdx, i64 val){
|
||||
aMem[iIdx].u.i = val;
|
||||
aMem[iIdx].flags = MEM_Int;
|
||||
}
|
||||
|
||||
/* A no-op destructor */
|
||||
void sqlite3NoopDestructor(void *p){ UNUSED_PARAMETER(p); }
|
||||
|
||||
|
||||
+1
-1
@@ -1290,7 +1290,7 @@ static void vdbeSorterExtendFile(sqlite3 *db, sqlite3_file *pFd, i64 nByte){
|
||||
sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_CHUNK_SIZE, &chunksize);
|
||||
sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_SIZE_HINT, &nByte);
|
||||
sqlite3OsFetch(pFd, 0, (int)nByte, &p);
|
||||
if( p ) sqlite3OsUnfetch(pFd, 0, p);
|
||||
if( NEVER(p) ) sqlite3OsUnfetch(pFd, 0, p);
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
+10
-6
@@ -3362,7 +3362,9 @@ static int indexMightHelpWithOrderBy(
|
||||
for(ii=0; ii<pOB->nExpr; ii++){
|
||||
Expr *pExpr = sqlite3ExprSkipCollateAndLikely(pOB->a[ii].pExpr);
|
||||
if( NEVER(pExpr==0) ) continue;
|
||||
if( pExpr->op==TK_COLUMN && pExpr->iTable==iCursor ){
|
||||
if( (pExpr->op==TK_COLUMN || pExpr->op==TK_AGG_COLUMN)
|
||||
&& pExpr->iTable==iCursor
|
||||
){
|
||||
if( pExpr->iColumn<0 ) return 1;
|
||||
for(jj=0; jj<pIndex->nKeyCol; jj++){
|
||||
if( pExpr->iColumn==pIndex->aiColumn[jj] ) return 1;
|
||||
@@ -5462,10 +5464,9 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
if( pFrom->isOrdered==pWInfo->pOrderBy->nExpr ){
|
||||
pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
|
||||
}
|
||||
if( pWInfo->pSelect->pOrderBy
|
||||
&& pWInfo->nOBSat > pWInfo->pSelect->pOrderBy->nExpr ){
|
||||
pWInfo->nOBSat = pWInfo->pSelect->pOrderBy->nExpr;
|
||||
}
|
||||
/* vvv--- See check-in [12ad822d9b827777] on 2023-03-16 ---vvv */
|
||||
assert( pWInfo->pSelect->pOrderBy==0
|
||||
|| pWInfo->nOBSat <= pWInfo->pSelect->pOrderBy->nExpr );
|
||||
}else{
|
||||
pWInfo->revMask = pFrom->revLoop;
|
||||
if( pWInfo->nOBSat<=0 ){
|
||||
@@ -6056,7 +6057,10 @@ WhereInfo *sqlite3WhereBegin(
|
||||
|
||||
/* An ORDER/GROUP BY clause of more than 63 terms cannot be optimized */
|
||||
testcase( pOrderBy && pOrderBy->nExpr==BMS-1 );
|
||||
if( pOrderBy && pOrderBy->nExpr>=BMS ) pOrderBy = 0;
|
||||
if( pOrderBy && pOrderBy->nExpr>=BMS ){
|
||||
pOrderBy = 0;
|
||||
wctrlFlags &= ~WHERE_WANT_DISTINCT;
|
||||
}
|
||||
|
||||
/* The number of tables in the FROM clause is limited by the number of
|
||||
** bits in a Bitmask
|
||||
|
||||
+1
-1
@@ -113,7 +113,7 @@ do_test corruptD-1.1.1 {
|
||||
hexio_write test.db [expr 1024+1] FFFF
|
||||
catchsql { PRAGMA quick_check }
|
||||
} {0 {{*** in database main ***
|
||||
Tree 2 page 2: free space corruption}}}
|
||||
Tree 2 page 2: free space corruption} {wrong # of entries in index i1}}}
|
||||
do_test corruptD-1.1.2 {
|
||||
incr_change_counter
|
||||
hexio_write test.db [expr 1024+1] [hexio_render_int32 1021]
|
||||
|
||||
@@ -95,7 +95,7 @@ foreach {tn use_eph sql res} {
|
||||
7 0 "SELECT count(DISTINCT a) FROM t2, t1" 5
|
||||
8 1 "SELECT count(DISTINCT a+b) FROM t1, t2, t2, t2" 6
|
||||
9 0 "SELECT count(DISTINCT c) FROM t1 WHERE c=2" 1
|
||||
10 1 "SELECT count(DISTINCT t1.rowid) FROM t1, t2" 10
|
||||
10 0 "SELECT count(DISTINCT t1.rowid) FROM t1, t2" 10
|
||||
} {
|
||||
do_test 3.$tn.1 {
|
||||
set prg [db eval "EXPLAIN $sql"]
|
||||
@@ -148,6 +148,10 @@ do_execsql_test 3.0 {
|
||||
CREATE TABLE t3(x, y, z);
|
||||
INSERT INTO t3 VALUES(1,1,1);
|
||||
INSERT INTO t3 VALUES(2,2,2);
|
||||
|
||||
CREATE TABLE t4(a);
|
||||
CREATE INDEX t4a ON t4(a);
|
||||
INSERT INTO t4 VALUES(1), (2), (2), (3), (1);
|
||||
}
|
||||
|
||||
foreach {tn use_eph sql res} {
|
||||
@@ -158,6 +162,9 @@ foreach {tn use_eph sql res} {
|
||||
4 0 "SELECT count(DISTINCT f) FROM t2 GROUP BY d, e" {1 2 2 3}
|
||||
5 1 "SELECT count(DISTINCT f) FROM t2 GROUP BY d" {2 3}
|
||||
6 0 "SELECT count(DISTINCT f) FROM t2 WHERE d IS 1 GROUP BY e" {1 2 2}
|
||||
|
||||
7 0 "SELECT count(DISTINCT a) FROM t1" {4}
|
||||
8 0 "SELECT count(DISTINCT a) FROM t4" {3}
|
||||
} {
|
||||
do_test 4.$tn.1 {
|
||||
set prg [db eval "EXPLAIN $sql"]
|
||||
|
||||
+3
-3
@@ -73,12 +73,12 @@ sqlite3 db test.db
|
||||
do_execsql_test e_reindex-1.3 {
|
||||
PRAGMA integrity_check;
|
||||
} [list \
|
||||
{wrong # of entries in index i2} \
|
||||
{wrong # of entries in index i1} \
|
||||
{row 3 missing from index i2} \
|
||||
{row 3 missing from index i1} \
|
||||
{row 4 missing from index i2} \
|
||||
{row 4 missing from index i1} \
|
||||
{wrong # of entries in index i2} \
|
||||
{wrong # of entries in index i1}
|
||||
{row 4 missing from index i1}
|
||||
]
|
||||
|
||||
do_execsql_test e_reindex-1.4 {
|
||||
|
||||
@@ -50,5 +50,33 @@ do_faultsim_test 1 -faults oom* -prep {
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
BEGIN;
|
||||
CREATE VIRTUAL TABLE t1 USING fts3(a);
|
||||
WITH s(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50
|
||||
)
|
||||
INSERT INTO t1 SELECT 'abc def ghi jkl mno pqr' FROM s;
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
faultsim_save_and_close
|
||||
do_faultsim_test 2 -faults oom-t* -prep {
|
||||
faultsim_restore_and_reopen
|
||||
execsql {
|
||||
BEGIN;
|
||||
CREATE TABLE x1(a PRIMARY KEY);
|
||||
}
|
||||
} -body {
|
||||
execsql {
|
||||
PRAGMA integrity_check;
|
||||
}
|
||||
} -test {
|
||||
faultsim_test_result {0 ok} $::TMPDBERROR
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
# 2024-01-23
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# Legacy JSON bug: If the input is a BLOB that when cast into TEXT looks
|
||||
# like valid JSON, then treat it as valid JSON.
|
||||
#
|
||||
# The original intent of the JSON functions was to raise an error on any
|
||||
# BLOB input. That intent was clearly documented, but the code failed to
|
||||
# to implement it. Subsequently, many applications began to depend on the
|
||||
# incorrect behavior, especially apps that used readfile() to read JSON
|
||||
# content, since readfile() returns a BLOB. So we need to support the
|
||||
# bug moving forward.
|
||||
#
|
||||
# The tests in this fail verify that the original buggy behavior is
|
||||
# preserved.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix json107
|
||||
|
||||
if {[db one {PRAGMA encoding}]!="UTF-8"} {
|
||||
# These tests only work for a UTF-8 encoding.
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
SELECT json_valid( CAST('{"a":1}' AS BLOB) );
|
||||
} 1
|
||||
do_execsql_test 1.1.1 {
|
||||
SELECT json_valid( CAST('{"a":1}' AS BLOB), 1);
|
||||
} 1
|
||||
do_execsql_test 1.1.2 {
|
||||
SELECT json_valid( CAST('{"a":1}' AS BLOB), 2);
|
||||
} 1
|
||||
do_execsql_test 1.1.4 {
|
||||
SELECT json_valid( CAST('{"a":1}' AS BLOB), 4);
|
||||
} 0
|
||||
do_execsql_test 1.1.8 {
|
||||
SELECT json_valid( CAST('{"a":1}' AS BLOB), 8);
|
||||
} 0
|
||||
|
||||
do_execsql_test 1.2.1 {
|
||||
SELECT CAST('{"a":123}' AS blob) -> 'a';
|
||||
} 123
|
||||
do_execsql_test 1.2.2 {
|
||||
SELECT CAST('{"a":123}' AS blob) ->> 'a';
|
||||
} 123
|
||||
do_execsql_test 1.2.3 {
|
||||
SELECT json_extract(CAST('{"a":123}' AS blob), '$.a');
|
||||
} 123
|
||||
do_execsql_test 1.3 {
|
||||
SELECT json_insert(CAST('{"a":123}' AS blob),'$.b',456);
|
||||
} {{{"a":123,"b":456}}}
|
||||
do_execsql_test 1.4 {
|
||||
SELECT json_remove(CAST('{"a":123,"b":456}' AS blob),'$.a');
|
||||
} {{{"b":456}}}
|
||||
do_execsql_test 1.5 {
|
||||
SELECT json_set(CAST('{"a":123,"b":456}' AS blob),'$.a',789);
|
||||
} {{{"a":789,"b":456}}}
|
||||
do_execsql_test 1.6 {
|
||||
SELECT json_replace(CAST('{"a":123,"b":456}' AS blob),'$.a',789);
|
||||
} {{{"a":789,"b":456}}}
|
||||
do_execsql_test 1.7 {
|
||||
SELECT json_type(CAST('{"a":123,"b":456}' AS blob));
|
||||
} object
|
||||
do_execsql_test 1.8 {
|
||||
SELECT json(CAST('{"a":123,"b":456}' AS blob));
|
||||
} {{{"a":123,"b":456}}}
|
||||
|
||||
ifcapable vtab {
|
||||
do_execsql_test 2.1 {
|
||||
SELECT key, value FROM json_tree( CAST('{"a":123,"b":456}' AS blob) )
|
||||
WHERE atom;
|
||||
} {a 123 b 456}
|
||||
}
|
||||
finish_test
|
||||
@@ -306,4 +306,31 @@ do_execsql_test 13.1 {
|
||||
SELECT json('{x:''a "b" c''}');
|
||||
} {{{"x":"a \"b\" c"}}}
|
||||
|
||||
# 2024-01-31
|
||||
# Allow control characters within JSON5 string literals.
|
||||
#
|
||||
for {set c 1} {$c<=0x1f} {incr c} {
|
||||
do_execsql_test 14.$c.1 {
|
||||
SELECT json_valid('"abc' || char($c) || 'xyz"');
|
||||
} {0}
|
||||
do_execsql_test 14.$c.2 {
|
||||
SELECT json_valid('"abc' || char($c) || 'xyz"', 2);
|
||||
} {1}
|
||||
switch $c {
|
||||
8 {set e "\\b"}
|
||||
9 {set e "\\t"}
|
||||
10 {set e "\\n"}
|
||||
12 {set e "\\f"}
|
||||
13 {set e "\\r"}
|
||||
default {set e [format "\\u00%02x" $c]}
|
||||
}
|
||||
do_execsql_test 14.$c.3 {
|
||||
SELECT json('{label:"abc' || char($c) || 'xyz"}');
|
||||
} "{{\"label\":\"abc${e}xyz\"}}"
|
||||
do_execsql_test 14.$c.4 {
|
||||
SELECT jsonb('{label:"abc' || char($c) || 'xyz"}') -> '$';
|
||||
} "{{\"label\":\"abc${e}xyz\"}}"
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -46,4 +46,8 @@ foreach {id path res} {
|
||||
} $res
|
||||
}
|
||||
|
||||
do_catchsql_test jsonb01-2.0 {
|
||||
SELECT x'8ce6ffffffff171333' -> '$';
|
||||
} {1 {malformed JSON}}
|
||||
|
||||
finish_test
|
||||
|
||||
+18
-6
@@ -569,11 +569,11 @@ ifcapable subquery&&compound {
|
||||
}
|
||||
|
||||
# Overflow the lemon parser stack by providing an overly complex
|
||||
# expression. Make sure that the overflow is detected and reported.
|
||||
# expression. Make sure that the overflow is detected and the
|
||||
# stack is grown automatically such that the application calling
|
||||
# SQLite never notices.
|
||||
#
|
||||
# This test fails when building with -DYYSTACKDEPTH=0
|
||||
#
|
||||
do_test misc5-7.1 {
|
||||
do_test misc5-7.1.1 {
|
||||
execsql {CREATE TABLE t1(x)}
|
||||
set sql "INSERT INTO t1 VALUES("
|
||||
set tail ""
|
||||
@@ -581,9 +581,21 @@ do_test misc5-7.1 {
|
||||
append sql "(1+"
|
||||
append tail ")"
|
||||
}
|
||||
append sql 2$tail
|
||||
append sql "0$tail); SELECT * FROM t1;"
|
||||
catchsql $sql
|
||||
} {1 {parser stack overflow}}
|
||||
} {0 200}
|
||||
do_test misc5-7.1.2 {
|
||||
execsql {DELETE FROM t1}
|
||||
set sql "INSERT INTO t1 VALUES("
|
||||
set tail ""
|
||||
for {set i 0} {$i<900} {incr i} {
|
||||
append sql "(1+"
|
||||
append tail ")"
|
||||
}
|
||||
append sql "0$tail); SELECT * FROM t1;"
|
||||
catchsql $sql
|
||||
} {0 900}
|
||||
|
||||
|
||||
# Parser stack overflow is silently ignored when it occurs while parsing the
|
||||
# schema and PRAGMA writable_schema is turned on.
|
||||
|
||||
+8
-8
@@ -45,18 +45,18 @@ proc register_rblob_code {dbname seed} {
|
||||
}
|
||||
|
||||
|
||||
# For cases 1.1 and 1.4, the number of pages read using xRead() is 4 on
|
||||
# unix and 9 on windows. The difference is that windows only ever maps
|
||||
# For cases 1.1 and 1.4, the number of pages read using xRead() is 8 on
|
||||
# unix and 12 on windows. The difference is that windows only ever maps
|
||||
# an integer number of OS pages (i.e. creates mappings that are a multiple
|
||||
# of 4KB in size). Whereas on unix any sized mapping may be created.
|
||||
#
|
||||
foreach {t mmap_size nRead c2init} {
|
||||
1.1 { PRAGMA mmap_size = 67108864 } /[49]/ {PRAGMA mmap_size = 0}
|
||||
1.2 { PRAGMA mmap_size = 53248 } 150 {PRAGMA mmap_size = 0}
|
||||
1.3 { PRAGMA mmap_size = 0 } 344 {PRAGMA mmap_size = 0}
|
||||
1.4 { PRAGMA mmap_size = 67108864 } /[49]/ {PRAGMA mmap_size = 67108864 }
|
||||
1.5 { PRAGMA mmap_size = 53248 } 150 {PRAGMA mmap_size = 67108864 }
|
||||
1.6 { PRAGMA mmap_size = 0 } 344 {PRAGMA mmap_size = 67108864 }
|
||||
1.1 { PRAGMA mmap_size = 67108864 } /8|12/ {PRAGMA mmap_size = 0}
|
||||
1.2 { PRAGMA mmap_size = 53248 } /15[34]/ {PRAGMA mmap_size = 0}
|
||||
1.3 { PRAGMA mmap_size = 0 } 344 {PRAGMA mmap_size = 0}
|
||||
1.4 { PRAGMA mmap_size = 67108864 } /12|8/ {PRAGMA mmap_size = 67108864 }
|
||||
1.5 { PRAGMA mmap_size = 53248 } /15[34]/ {PRAGMA mmap_size = 67108864 }
|
||||
1.6 { PRAGMA mmap_size = 0 } 344 {PRAGMA mmap_size = 67108864 }
|
||||
} {
|
||||
|
||||
do_multiclient_test tn {
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
# 2024 January 23
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# Test special cases of corrupt database handling in mmap-mode.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix mmapcorrupt
|
||||
|
||||
database_may_be_corrupt
|
||||
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_lookaside 0 0
|
||||
sqlite3_initialize
|
||||
|
||||
reset_db
|
||||
do_execsql_test 1.0 {
|
||||
PRAGMA page_size = 16384;
|
||||
CREATE TABLE tn1(a PRIMARY KEY) WITHOUT ROWID;
|
||||
CREATE TABLE t0(a PRIMARY KEY) WITHOUT ROWID;
|
||||
CREATE TABLE t1(a PRIMARY KEY) WITHOUT ROWID;
|
||||
INSERT INTO t1 VALUES('B');
|
||||
}
|
||||
db close
|
||||
|
||||
set sz [file size test.db]
|
||||
hexio_write test.db [expr $sz-3] 800380
|
||||
|
||||
sqlite3 db test.db
|
||||
do_execsql_test 2.1 {
|
||||
PRAGMA mmap_size = 1000000;
|
||||
SELECT sql FROM sqlite_schema LIMIT 1;
|
||||
SELECT * FROM t0;
|
||||
} {1000000 {CREATE TABLE tn1(a PRIMARY KEY) WITHOUT ROWID}}
|
||||
|
||||
do_execsql_test 2.2 {
|
||||
INSERT INTO t0 SELECT * FROM t1;
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
+16
-16
@@ -372,27 +372,27 @@ ifcapable attach {
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
execsql {PRAGMA integrity_check}
|
||||
} {{row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2}}
|
||||
} {{wrong # of entries in index i2} {row 1 missing from index i2} {row 2 missing from index i2}}
|
||||
do_test pragma-3.3 {
|
||||
execsql {PRAGMA integrity_check=1}
|
||||
} {{row 1 missing from index i2}}
|
||||
} {{wrong # of entries in index i2}}
|
||||
do_test pragma-3.4 {
|
||||
execsql {
|
||||
ATTACH DATABASE 'test.db' AS t2;
|
||||
PRAGMA integrity_check
|
||||
}
|
||||
} {{row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2}}
|
||||
} {{wrong # of entries in index i2} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2} {row 1 missing from index i2} {row 2 missing from index i2}}
|
||||
do_test pragma-3.5 {
|
||||
execsql {
|
||||
PRAGMA integrity_check=4
|
||||
}
|
||||
} {{row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2} {row 1 missing from index i2}}
|
||||
} {{wrong # of entries in index i2} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2}}
|
||||
do_catchsql_test pragma-3.6 {
|
||||
PRAGMA integrity_check=xyz
|
||||
} {1 {no such table: xyz}}
|
||||
do_catchsql_test pragma-3.6b {
|
||||
PRAGMA integrity_check=t2
|
||||
} {0 {{row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2}}}
|
||||
} {0 {{wrong # of entries in index i2} {row 1 missing from index i2} {row 2 missing from index i2}}}
|
||||
do_catchsql_test pragma-3.6c {
|
||||
PRAGMA integrity_check=sqlite_schema
|
||||
} {0 ok}
|
||||
@@ -400,7 +400,7 @@ ifcapable attach {
|
||||
execsql {
|
||||
PRAGMA integrity_check=0
|
||||
}
|
||||
} {{row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2}}
|
||||
} {{wrong # of entries in index i2} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2} {row 1 missing from index i2} {row 2 missing from index i2}}
|
||||
|
||||
# Add additional corruption by appending unused pages to the end of
|
||||
# the database file testerr.db
|
||||
@@ -435,10 +435,10 @@ ifcapable attach {
|
||||
} {{*** in database t2 ***
|
||||
Page 4: never used
|
||||
Page 5: never used
|
||||
Page 6: never used} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2}}
|
||||
Page 6: never used} {wrong # of entries in index i2} {row 1 missing from index i2} {row 2 missing from index i2}}
|
||||
do_execsql_test pragma-3.9b {
|
||||
PRAGMA t2.integrity_check=t2;
|
||||
} {{row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2}}
|
||||
} {{wrong # of entries in index i2} {row 1 missing from index i2} {row 2 missing from index i2}}
|
||||
do_execsql_test pragma-3.9c {
|
||||
PRAGMA t2.integrity_check=sqlite_schema;
|
||||
} {ok}
|
||||
@@ -455,7 +455,7 @@ Page 4: never used}}
|
||||
} {{*** in database t2 ***
|
||||
Page 4: never used
|
||||
Page 5: never used
|
||||
Page 6: never used} {row 1 missing from index i2} {row 2 missing from index i2}}
|
||||
Page 6: never used} {wrong # of entries in index i2} {row 1 missing from index i2}}
|
||||
do_test pragma-3.12 {
|
||||
execsql {
|
||||
PRAGMA integrity_check=4
|
||||
@@ -463,7 +463,7 @@ Page 6: never used} {row 1 missing from index i2} {row 2 missing from index i2}}
|
||||
} {{*** in database t2 ***
|
||||
Page 4: never used
|
||||
Page 5: never used
|
||||
Page 6: never used} {row 1 missing from index i2}}
|
||||
Page 6: never used} {wrong # of entries in index i2}}
|
||||
do_test pragma-3.13 {
|
||||
execsql {
|
||||
PRAGMA integrity_check=3
|
||||
@@ -487,10 +487,10 @@ Page 5: never used}}
|
||||
} {{*** in database t2 ***
|
||||
Page 4: never used
|
||||
Page 5: never used
|
||||
Page 6: never used} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2} {*** in database t3 ***
|
||||
Page 6: never used} {wrong # of entries in index i2} {row 1 missing from index i2} {row 2 missing from index i2} {*** in database t3 ***
|
||||
Page 4: never used
|
||||
Page 5: never used
|
||||
Page 6: never used} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2}}
|
||||
Page 6: never used} {wrong # of entries in index i2} {row 1 missing from index i2} {row 2 missing from index i2}}
|
||||
do_test pragma-3.16 {
|
||||
execsql {
|
||||
PRAGMA integrity_check(10)
|
||||
@@ -498,10 +498,10 @@ Page 6: never used} {row 1 missing from index i2} {row 2 missing from index i2}
|
||||
} {{*** in database t2 ***
|
||||
Page 4: never used
|
||||
Page 5: never used
|
||||
Page 6: never used} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2} {*** in database t3 ***
|
||||
Page 6: never used} {wrong # of entries in index i2} {row 1 missing from index i2} {row 2 missing from index i2} {*** in database t3 ***
|
||||
Page 4: never used
|
||||
Page 5: never used
|
||||
Page 6: never used} {row 1 missing from index i2}}
|
||||
Page 6: never used} {wrong # of entries in index i2}}
|
||||
do_test pragma-3.17 {
|
||||
execsql {
|
||||
PRAGMA integrity_check=8
|
||||
@@ -509,7 +509,7 @@ Page 6: never used} {row 1 missing from index i2}}
|
||||
} {{*** in database t2 ***
|
||||
Page 4: never used
|
||||
Page 5: never used
|
||||
Page 6: never used} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2} {*** in database t3 ***
|
||||
Page 6: never used} {wrong # of entries in index i2} {row 1 missing from index i2} {row 2 missing from index i2} {*** in database t3 ***
|
||||
Page 4: never used
|
||||
Page 5: never used}}
|
||||
do_test pragma-3.18 {
|
||||
@@ -519,7 +519,7 @@ Page 5: never used}}
|
||||
} {{*** in database t2 ***
|
||||
Page 4: never used
|
||||
Page 5: never used
|
||||
Page 6: never used} {row 1 missing from index i2}}
|
||||
Page 6: never used} {wrong # of entries in index i2}}
|
||||
}
|
||||
do_test pragma-3.19 {
|
||||
catch {db close}
|
||||
|
||||
+1
-1
@@ -97,7 +97,7 @@ do_test pragma4-2.100 {
|
||||
}
|
||||
string map {\[ x \] x \173 {} \175 {}} \
|
||||
[db eval {EXPLAIN PRAGMA integrity_check}]
|
||||
} {/ IntegrityCk 2 2 1 x[0-9]+,1x /}
|
||||
} {/ IntegrityCk 1 2 8 x[0-9]+,1x /}
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
|
||||
+40
-1
@@ -418,6 +418,8 @@ struct lemon {
|
||||
char *filename; /* Name of the input file */
|
||||
char *outname; /* Name of the current output file */
|
||||
char *tokenprefix; /* A prefix added to token names in the .h file */
|
||||
char *reallocFunc; /* Function to use to allocate stack space */
|
||||
char *freeFunc; /* Function to use to free stack space */
|
||||
int nconflict; /* Number of parsing conflicts */
|
||||
int nactiontab; /* Number of entries in the yy_action[] table */
|
||||
int nlookaheadtab; /* Number of entries in yy_lookahead[] */
|
||||
@@ -2531,6 +2533,12 @@ static void parseonetoken(struct pstate *psp)
|
||||
}else if( strcmp(x,"default_type")==0 ){
|
||||
psp->declargslot = &(psp->gp->vartype);
|
||||
psp->insertLineMacro = 0;
|
||||
}else if( strcmp(x,"realloc")==0 ){
|
||||
psp->declargslot = &(psp->gp->reallocFunc);
|
||||
psp->insertLineMacro = 0;
|
||||
}else if( strcmp(x,"free")==0 ){
|
||||
psp->declargslot = &(psp->gp->freeFunc);
|
||||
psp->insertLineMacro = 0;
|
||||
}else if( strcmp(x,"stack_size")==0 ){
|
||||
psp->declargslot = &(psp->gp->stacksize);
|
||||
psp->insertLineMacro = 0;
|
||||
@@ -4309,7 +4317,7 @@ void ReportTable(
|
||||
struct action *ap;
|
||||
struct rule *rp;
|
||||
struct acttab *pActtab;
|
||||
int i, j, n, sz;
|
||||
int i, j, n, sz, mn, mx;
|
||||
int nLookAhead;
|
||||
int szActionType; /* sizeof(YYACTIONTYPE) */
|
||||
int szCodeType; /* sizeof(YYCODETYPE) */
|
||||
@@ -4501,6 +4509,21 @@ void ReportTable(
|
||||
fprintf(out,"#define %sARG_FETCH\n",name); lineno++;
|
||||
fprintf(out,"#define %sARG_STORE\n",name); lineno++;
|
||||
}
|
||||
if( lemp->reallocFunc ){
|
||||
fprintf(out,"#define YYREALLOC %s\n", lemp->reallocFunc); lineno++;
|
||||
}else{
|
||||
fprintf(out,"#define YYREALLOC realloc\n"); lineno++;
|
||||
}
|
||||
if( lemp->freeFunc ){
|
||||
fprintf(out,"#define YYFREE %s\n", lemp->freeFunc); lineno++;
|
||||
}else{
|
||||
fprintf(out,"#define YYFREE free\n"); lineno++;
|
||||
}
|
||||
if( lemp->reallocFunc && lemp->freeFunc ){
|
||||
fprintf(out,"#define YYDYNSTACK 1\n"); lineno++;
|
||||
}else{
|
||||
fprintf(out,"#define YYDYNSTACK 0\n"); lineno++;
|
||||
}
|
||||
if( lemp->ctx && lemp->ctx[0] ){
|
||||
i = lemonStrlen(lemp->ctx);
|
||||
while( i>=1 && ISSPACE(lemp->ctx[i-1]) ) i--;
|
||||
@@ -4624,6 +4647,22 @@ void ReportTable(
|
||||
fprintf(out,"#define YY_MIN_REDUCE %d\n", lemp->minReduce); lineno++;
|
||||
i = lemp->minReduce + lemp->nrule;
|
||||
fprintf(out,"#define YY_MAX_REDUCE %d\n", i-1); lineno++;
|
||||
|
||||
/* Minimum and maximum token values that have a destructor */
|
||||
mn = mx = 0;
|
||||
for(i=0; i<lemp->nsymbol; i++){
|
||||
struct symbol *sp = lemp->symbols[i];
|
||||
|
||||
if( sp && sp->type!=TERMINAL && sp->destructor ){
|
||||
if( mn==0 || sp->index<mn ) mn = sp->index;
|
||||
if( sp->index>mx ) mx = sp->index;
|
||||
}
|
||||
}
|
||||
if( lemp->tokendest ) mn = 0;
|
||||
if( lemp->vardest ) mx = lemp->nsymbol-1;
|
||||
fprintf(out,"#define YY_MIN_DSTRCTR %d\n", mn); lineno++;
|
||||
fprintf(out,"#define YY_MAX_DSTRCTR %d\n", mx); lineno++;
|
||||
|
||||
tplt_xfer(lemp->name,in,out,&lineno);
|
||||
|
||||
/* Now output the action table and its associates:
|
||||
|
||||
+75
-57
@@ -67,6 +67,9 @@
|
||||
** ParseARG_STORE Code to store %extra_argument into yypParser
|
||||
** ParseARG_FETCH Code to extract %extra_argument from yypParser
|
||||
** ParseCTX_* As ParseARG_ except for %extra_context
|
||||
** YYREALLOC Name of the realloc() function to use
|
||||
** YYFREE Name of the free() function to use
|
||||
** YYDYNSTACK True if stack space should be extended on heap
|
||||
** YYERRORSYMBOL is the code number of the error symbol. If not
|
||||
** defined, then do no error processing.
|
||||
** YYNSTATE the combined number of states.
|
||||
@@ -80,6 +83,8 @@
|
||||
** YY_NO_ACTION The yy_action[] code for no-op
|
||||
** YY_MIN_REDUCE Minimum value for reduce actions
|
||||
** YY_MAX_REDUCE Maximum value for reduce actions
|
||||
** YY_MIN_DSTRCTR Minimum symbol value that has a destructor
|
||||
** YY_MAX_DSTRCTR Maximum symbol value that has a destructor
|
||||
*/
|
||||
#ifndef INTERFACE
|
||||
# define INTERFACE 1
|
||||
@@ -101,6 +106,22 @@
|
||||
# define yytestcase(X)
|
||||
#endif
|
||||
|
||||
/* Macro to determine if stack space has the ability to grow using
|
||||
** heap memory.
|
||||
*/
|
||||
#if YYSTACKDEPTH<=0 || YYDYNSTACK
|
||||
# define YYGROWABLESTACK 1
|
||||
#else
|
||||
# define YYGROWABLESTACK 0
|
||||
#endif
|
||||
|
||||
/* Guarantee a minimum number of initial stack slots.
|
||||
*/
|
||||
#if YYSTACKDEPTH<=0
|
||||
# undef YYSTACKDEPTH
|
||||
# define YYSTACKDEPTH 2 /* Need a minimum stack size */
|
||||
#endif
|
||||
|
||||
|
||||
/* Next are the tables used to determine what action to take based on the
|
||||
** current state and lookahead token. These tables are used to implement
|
||||
@@ -212,14 +233,9 @@ struct yyParser {
|
||||
#endif
|
||||
ParseARG_SDECL /* A place to hold %extra_argument */
|
||||
ParseCTX_SDECL /* A place to hold %extra_context */
|
||||
#if YYSTACKDEPTH<=0
|
||||
int yystksz; /* Current side of the stack */
|
||||
yyStackEntry *yystack; /* The parser's stack */
|
||||
yyStackEntry yystk0; /* First stack entry */
|
||||
#else
|
||||
yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */
|
||||
yyStackEntry *yystackEnd; /* Last entry in the stack */
|
||||
#endif
|
||||
yyStackEntry *yystackEnd; /* Last entry in the stack */
|
||||
yyStackEntry *yystack; /* The parser stack */
|
||||
yyStackEntry yystk0[YYSTACKDEPTH]; /* Initial stack space */
|
||||
};
|
||||
typedef struct yyParser yyParser;
|
||||
|
||||
@@ -273,37 +289,45 @@ static const char *const yyRuleName[] = {
|
||||
#endif /* NDEBUG */
|
||||
|
||||
|
||||
#if YYSTACKDEPTH<=0
|
||||
#if YYGROWABLESTACK
|
||||
/*
|
||||
** Try to increase the size of the parser stack. Return the number
|
||||
** of errors. Return 0 on success.
|
||||
*/
|
||||
static int yyGrowStack(yyParser *p){
|
||||
int oldSize = 1 + (int)(p->yystackEnd - p->yystack);
|
||||
int newSize;
|
||||
int idx;
|
||||
yyStackEntry *pNew;
|
||||
|
||||
newSize = p->yystksz*2 + 100;
|
||||
idx = p->yytos ? (int)(p->yytos - p->yystack) : 0;
|
||||
if( p->yystack==&p->yystk0 ){
|
||||
pNew = malloc(newSize*sizeof(pNew[0]));
|
||||
if( pNew ) pNew[0] = p->yystk0;
|
||||
newSize = oldSize*2 + 100;
|
||||
idx = (int)(p->yytos - p->yystack);
|
||||
if( p->yystack==p->yystk0 ){
|
||||
pNew = YYREALLOC(0, newSize*sizeof(pNew[0]));
|
||||
if( pNew==0 ) return 1;
|
||||
memcpy(pNew, p->yystack, oldSize*sizeof(pNew[0]));
|
||||
}else{
|
||||
pNew = realloc(p->yystack, newSize*sizeof(pNew[0]));
|
||||
pNew = YYREALLOC(p->yystack, newSize*sizeof(pNew[0]));
|
||||
if( pNew==0 ) return 1;
|
||||
}
|
||||
if( pNew ){
|
||||
p->yystack = pNew;
|
||||
p->yytos = &p->yystack[idx];
|
||||
p->yystack = pNew;
|
||||
p->yytos = &p->yystack[idx];
|
||||
#ifndef NDEBUG
|
||||
if( yyTraceFILE ){
|
||||
fprintf(yyTraceFILE,"%sStack grows from %d to %d entries.\n",
|
||||
yyTracePrompt, p->yystksz, newSize);
|
||||
}
|
||||
#endif
|
||||
p->yystksz = newSize;
|
||||
if( yyTraceFILE ){
|
||||
fprintf(yyTraceFILE,"%sStack grows from %d to %d entries.\n",
|
||||
yyTracePrompt, oldSize, newSize);
|
||||
}
|
||||
return pNew==0;
|
||||
#endif
|
||||
p->yystackEnd = &p->yystack[newSize-1];
|
||||
return 0;
|
||||
}
|
||||
#endif /* YYGROWABLESTACK */
|
||||
|
||||
#if !YYGROWABLESTACK
|
||||
/* For builds that do no have a growable stack, yyGrowStack always
|
||||
** returns an error.
|
||||
*/
|
||||
# define yyGrowStack(X) 1
|
||||
#endif
|
||||
|
||||
/* Datatype of the argument to the memory allocated passed as the
|
||||
@@ -323,24 +347,14 @@ void ParseInit(void *yypRawParser ParseCTX_PDECL){
|
||||
#ifdef YYTRACKMAXSTACKDEPTH
|
||||
yypParser->yyhwm = 0;
|
||||
#endif
|
||||
#if YYSTACKDEPTH<=0
|
||||
yypParser->yytos = NULL;
|
||||
yypParser->yystack = NULL;
|
||||
yypParser->yystksz = 0;
|
||||
if( yyGrowStack(yypParser) ){
|
||||
yypParser->yystack = &yypParser->yystk0;
|
||||
yypParser->yystksz = 1;
|
||||
}
|
||||
#endif
|
||||
yypParser->yystack = yypParser->yystk0;
|
||||
yypParser->yystackEnd = &yypParser->yystack[YYSTACKDEPTH-1];
|
||||
#ifndef YYNOERRORRECOVERY
|
||||
yypParser->yyerrcnt = -1;
|
||||
#endif
|
||||
yypParser->yytos = yypParser->yystack;
|
||||
yypParser->yystack[0].stateno = 0;
|
||||
yypParser->yystack[0].major = 0;
|
||||
#if YYSTACKDEPTH>0
|
||||
yypParser->yystackEnd = &yypParser->yystack[YYSTACKDEPTH-1];
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef Parse_ENGINEALWAYSONSTACK
|
||||
@@ -426,9 +440,26 @@ static void yy_pop_parser_stack(yyParser *pParser){
|
||||
*/
|
||||
void ParseFinalize(void *p){
|
||||
yyParser *pParser = (yyParser*)p;
|
||||
while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser);
|
||||
#if YYSTACKDEPTH<=0
|
||||
if( pParser->yystack!=&pParser->yystk0 ) free(pParser->yystack);
|
||||
|
||||
/* In-lined version of calling yy_pop_parser_stack() for each
|
||||
** element left in the stack */
|
||||
yyStackEntry *yytos = pParser->yytos;
|
||||
while( yytos>pParser->yystack ){
|
||||
#ifndef NDEBUG
|
||||
if( yyTraceFILE ){
|
||||
fprintf(yyTraceFILE,"%sPopping %s\n",
|
||||
yyTracePrompt,
|
||||
yyTokenName[yytos->major]);
|
||||
}
|
||||
#endif
|
||||
if( yytos->major>=YY_MIN_DSTRCTR ){
|
||||
yy_destructor(pParser, yytos->major, &yytos->minor);
|
||||
}
|
||||
yytos--;
|
||||
}
|
||||
|
||||
#if YYGROWABLESTACK
|
||||
if( pParser->yystack!=pParser->yystk0 ) YYFREE(pParser->yystack);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -654,25 +685,19 @@ static void yy_shift(
|
||||
assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack) );
|
||||
}
|
||||
#endif
|
||||
#if YYSTACKDEPTH>0
|
||||
if( yypParser->yytos>yypParser->yystackEnd ){
|
||||
yypParser->yytos--;
|
||||
yyStackOverflow(yypParser);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz] ){
|
||||
yytos = yypParser->yytos;
|
||||
if( yytos>yypParser->yystackEnd ){
|
||||
if( yyGrowStack(yypParser) ){
|
||||
yypParser->yytos--;
|
||||
yyStackOverflow(yypParser);
|
||||
return;
|
||||
}
|
||||
yytos = yypParser->yytos;
|
||||
assert( yytos <= yypParser->yystackEnd );
|
||||
}
|
||||
#endif
|
||||
if( yyNewState > YY_MAX_SHIFT ){
|
||||
yyNewState += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE;
|
||||
}
|
||||
yytos = yypParser->yytos;
|
||||
yytos->stateno = yyNewState;
|
||||
yytos->major = yyMajor;
|
||||
yytos->minor.yy0 = yyMinor;
|
||||
@@ -911,19 +936,12 @@ void Parse(
|
||||
(int)(yypParser->yytos - yypParser->yystack));
|
||||
}
|
||||
#endif
|
||||
#if YYSTACKDEPTH>0
|
||||
if( yypParser->yytos>=yypParser->yystackEnd ){
|
||||
yyStackOverflow(yypParser);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz-1] ){
|
||||
if( yyGrowStack(yypParser) ){
|
||||
yyStackOverflow(yypParser);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
yyact = yy_reduce(yypParser,yyruleno,yymajor,yyminor ParseCTX_PARAM);
|
||||
}else if( yyact <= YY_MAX_SHIFTREDUCE ){
|
||||
|
||||
Reference in New Issue
Block a user