From 2fc865c1153d739208657ea652f74426bf20f678 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 16 Dec 2017 20:20:37 +0000 Subject: [PATCH 01/40] Add an experimental location(X) SQL function that attempt to return the location of the payload within the database for the record that contains column X. location(X) returns NULL if X is not an ordinary table column or if SQLite cannot figure out the location because it is using a covering index. FossilOrigin-Name: 51be9558164301c5dd4df23ab8b3e67de0b522f8d36f79f3d84d45d3dc2a83a4 --- manifest | 29 ++++++++++++++++------------- manifest.uuid | 2 +- src/btree.c | 13 +++++++++++++ src/btree.h | 1 + src/expr.c | 15 ++++++++++++--- src/func.c | 2 ++ src/sqliteInt.h | 1 + src/vdbe.c | 20 ++++++++++++++++++++ test/func6.test | 36 ++++++++++++++++++++++++++++++++++++ 9 files changed, 102 insertions(+), 17 deletions(-) create mode 100644 test/func6.test diff --git a/manifest b/manifest index c3b80112dd..8e46d8e601 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\ssqlite3_vtab_collation()\sfunction,\swhich\sallows\san\sxBestIndex\scallback\nto\sdetermine\sthe\scollation\ssequence\sthat\sSQLite\swill\suse\sfor\sa\scomparison.\sAnd\nthe\sSQLITE_DBCONFIG_FULL_EQP\sconfiguration\soption,\swhich\senhances\sthe\soutput\nof\s"EXPLAIN\sQUERY\sPLAN"\sso\sthat\sit\sincludes\sstatements\srun\sby\striggers.\sAnd\nthe\scode\sfor\sthe\ssqlite3_expert\sextension\sand\scommand\sline\sapplication. -D 2017-12-16T19:36:52.802 +C Add\san\sexperimental\slocation(X)\sSQL\sfunction\sthat\sattempt\sto\sreturn\sthe\nlocation\sof\sthe\spayload\swithin\sthe\sdatabase\sfor\sthe\srecord\sthat\scontains\ncolumn\sX.\s\slocation(X)\sreturns\sNULL\sif\sX\sis\snot\san\sordinary\stable\scolumn\sor\nif\sSQLite\scannot\sfigure\sout\sthe\slocation\sbecause\sit\sis\susing\sa\scovering\sindex. +D 2017-12-16T20:20:37.221 F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69 @@ -420,8 +420,8 @@ F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73 F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca -F src/btree.c b83a6b03f160528020bb965f0c3a40af5286cd4923c3870fd218177f03a120a7 -F src/btree.h 32ef5d3f25dc70ef1ee9cecf84a023c21378f06a57cd701d2e866e141b150f09 +F src/btree.c 6fba32ea06e9be55849dd486e88df6c467bf69cf306d38ca3c3a8df34e6499e9 +F src/btree.h e9d22d0475b37422cc2db53f4336cc814645dcca8634bc4aae25ed52d043ef53 F src/btreeInt.h 55b702efce17e5d1941865464227d3802cfc9c7c832fac81d4c94dced47a71fc F src/build.c 87b68e3b45559ec404b12f095f0ba5f06f91a6dd2d21bd8443e41d8ac2e67196 F src/callback.c fe677cb5f5abb02f7a772a62a98c2f516426081df68856e8f2d5f950929b966a @@ -431,10 +431,10 @@ F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957 F src/dbpage.c 8db4c97f630e7d83f884ea75caf1ffd0988c160e9d530194d93721c80821e0f6 F src/dbstat.c 7a4ba8518b6369ef3600c49cf9c918ad979acba610b2aebef1b656d649b96720 F src/delete.c 74667ad914ac143731a444a1bacf29ceb18f6eded8a0dd17aafae80baa07f8bb -F src/expr.c fe11b91bb65b869143bd42023427c4429778ae42c0a0db7762f68f75b347a958 +F src/expr.c 261d1eb0954a7813d512d8edafd6db26736a3dcb650785652a6234d5ddb394aa F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c d617daf66b5515e2b42c1405b2b4984c30ca50fb705ab164271a9bf66c69e331 -F src/func.c 0fb9a2d678d3c8aba89b46468b309cd7e8fa9806a369a30aa89024660845bb13 +F src/func.c a23ea9b8869ca47e20a273985013b36a2294788fde5abe1a610be4bb90c8e6e8 F src/global.c ac3094f1dc59fbeb919aef7cc0cc827a8459d1fb1adb7972ef75bd9e0c10b75b F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4 @@ -483,7 +483,7 @@ F src/shell.c.in 6ffed0c589f5aff180789a8c8abf5b2d3e2eea7470c86b30e797887cb0c9d0e F src/sqlite.h.in 95afbec6e623843d702e727765efc833586fecc688867f41f87be7db3ff1fa62 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34 -F src/sqliteInt.h 4d6580ab911e9bc36447ef05bf4d2aab929dde161ac117c7de6220eef06d6175 +F src/sqliteInt.h 3aca12018eb1528f9bc7af4a9ea141759f2487ff42b9f9f688210d09742dfe1e F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 9737ed017279a9e0c5da748701c3c7bf1e8ae0dae459aad20dd64fcff97a7e35 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -547,7 +547,7 @@ F src/update.c 961bd1265d4d1e5cd65c9a54fa5122fb7aefcb003fcf2de0c092fceb7e58972c F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c d01fa6f45bfad3b65fb2490513aa2e0676412c61b4b094340b513cf72c3704a4 F src/vacuum.c 90839322fd5f00df9617eb21b68beda9b6e2a2937576b0d65985e4aeb1c53739 -F src/vdbe.c 3393b508d9ad084ffce232a7c53e375ef5ac99b50b685c5131fcdfce97a9d534 +F src/vdbe.c beed55b540e01e9be3b87b0d3aa491b41d933bd391ca4d8470882f77e1090871 F src/vdbe.h d50cadf12bcf9fb99117ef392ce1ea283aa429270481426b6e8b0280c101fd97 F src/vdbeInt.h 1fe00770144c12c4913128f35262d11527ef3284561baaab59b947a41c08d0d9 F src/vdbeapi.c 9c670ca0dcc1cd86373aa353b747b26fe531ca5cd4331690c611d1f03842e2a1 @@ -917,6 +917,7 @@ F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f F test/func3.test d202a7606d23f90988a664e88e268aed1087c11c F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f F test/func5.test cdd224400bc3e48d891827cc913a57051a426fa4 +F test/func6.test 5d4b0526f5013db07e2f6de43df42d990500f636fa32258cfac0c87113a1c1ce F test/fuzz-oss1.test e58330d01cbbd8215ee636b17a03fe220b37dbfa F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1 F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1 @@ -1687,8 +1688,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 64487d658cb3b6c8c67f1e198c70813c963de52599f3ea974bdc2aa432e74de9 d5b597b52a1213cdf382d96f4df3535727be0852b25bafd12bbef54da946c5f2 -R 864c298149f75794a8b0c88eee2c8573 -T +closed d5b597b52a1213cdf382d96f4df3535727be0852b25bafd12bbef54da946c5f2 -U dan -Z 532f71905753147684a848f63aad67ba +P 4c782c950204c09c1d8f857c39c4cf476539ec4e7eee6fd86419d47cf0f8b9e0 +R c224d72a40caf69fa2477f10805805e4 +T *branch * location-function +T *sym-location-function * +T -sym-trunk * +U drh +Z 078a2a780a60eba456bb0addd6858536 diff --git a/manifest.uuid b/manifest.uuid index 7b68239262..e971cdd459 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4c782c950204c09c1d8f857c39c4cf476539ec4e7eee6fd86419d47cf0f8b9e0 \ No newline at end of file +51be9558164301c5dd4df23ab8b3e67de0b522f8d36f79f3d84d45d3dc2a83a4 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 0fa00a2e12..d17cbde846 100644 --- a/src/btree.c +++ b/src/btree.c @@ -4432,6 +4432,19 @@ i64 sqlite3BtreeIntegerKey(BtCursor *pCur){ return pCur->info.nKey; } +/* +** Return the offset into the database file for the start of the +** payload to which the cursor is pointing. +*/ +i64 sqlite3BtreeLocation(BtCursor *pCur){ + assert( cursorHoldsMutex(pCur) ); + assert( pCur->eState==CURSOR_VALID ); + assert( pCur->curIntKey ); + getCellInfo(pCur); + return (i64)pCur->pBt->pageSize*(i64)pCur->pPage->pgno + + (i64)(pCur->info.pPayload - pCur->pPage->aData); +} + /* ** Return the number of bytes of payload for the entry that pCur is ** currently pointing to. For table btrees, this will be the amount diff --git a/src/btree.h b/src/btree.h index e2c271cdc5..43c0b9a8a4 100644 --- a/src/btree.h +++ b/src/btree.h @@ -291,6 +291,7 @@ int sqlite3BtreeNext(BtCursor*, int flags); int sqlite3BtreeEof(BtCursor*); int sqlite3BtreePrevious(BtCursor*, int flags); i64 sqlite3BtreeIntegerKey(BtCursor*); +i64 sqlite3BtreeLocation(BtCursor*); int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*); const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt); u32 sqlite3BtreePayloadSize(BtCursor*); diff --git a/src/expr.c b/src/expr.c index 524e539349..b7c64d3c11 100644 --- a/src/expr.c +++ b/src/expr.c @@ -3871,9 +3871,18 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ if( !pColl ) pColl = db->pDfltColl; sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ); } - sqlite3VdbeAddOp4(v, pParse->iSelfTab ? OP_PureFunc0 : OP_Function0, - constMask, r1, target, (char*)pDef, P4_FUNCDEF); - sqlite3VdbeChangeP5(v, (u8)nFarg); + if( pDef->funcFlags & SQLITE_FUNC_LOCATION ){ + Expr *pArg = pFarg->a[0].pExpr; + if( pArg->op==TK_COLUMN ){ + sqlite3VdbeAddOp2(v, OP_Location, pArg->iTable, target); + }else{ + sqlite3VdbeAddOp2(v, OP_Null, 0, target); + } + }else{ + sqlite3VdbeAddOp4(v, pParse->iSelfTab ? OP_PureFunc0 : OP_Function0, + constMask, r1, target, (char*)pDef, P4_FUNCDEF); + sqlite3VdbeChangeP5(v, (u8)nFarg); + } if( nFarg && constMask==0 ){ sqlite3ReleaseTempRange(pParse, r1, nFarg); } diff --git a/src/func.c b/src/func.c index 7528fa8b4d..f81c4865d8 100644 --- a/src/func.c +++ b/src/func.c @@ -1799,6 +1799,8 @@ void sqlite3RegisterBuiltinFunctions(void){ #ifdef SQLITE_DEBUG FUNCTION2(affinity, 1, 0, 0, noopFunc, SQLITE_FUNC_AFFINITY), #endif + FUNCTION2(location, 1, 0, 0, noopFunc, SQLITE_FUNC_LOCATION| + SQLITE_FUNC_TYPEOF), FUNCTION(ltrim, 1, 1, 0, trimFunc ), FUNCTION(ltrim, 2, 1, 0, trimFunc ), FUNCTION(rtrim, 1, 2, 0, trimFunc ), diff --git a/src/sqliteInt.h b/src/sqliteInt.h index efe823a654..f85682a393 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1630,6 +1630,7 @@ struct FuncDestructor { #define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a ** single query - might change over time */ #define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */ +#define SQLITE_FUNC_LOCATION 0x8000 /* Built-in location() function */ /* ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are diff --git a/src/vdbe.c b/src/vdbe.c index cfe18a9d1e..74cf82c4c1 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2349,6 +2349,26 @@ case OP_IfNullRow: { /* jump */ break; } +/* Opcode: Location P1 P2 * * * +** Synopsis: r[P2] = location(P1) +** +** Store in register r[P2] the location in the database file that is the +** start of the payload for the record at which that cursor P1 is currently +** pointing. +*/ +case OP_Location: { /* out2 */ + VdbeCursor *pC; /* The VDBE cursor */ + assert( pOp->p1>=0 && pOp->p1nCursor ); + pC = p->apCsr[pOp->p1]; + pOut = out2Prerelease(p, pOp); + if( pC==0 || pC->eCurType!=CURTYPE_BTREE ){ + pOut->flags = MEM_Null; + }else{ + pOut->u.i = sqlite3BtreeLocation(pC->uc.pCursor); + } + break; +} + /* Opcode: Column P1 P2 P3 P4 P5 ** Synopsis: r[P3]=PX ** diff --git a/test/func6.test b/test/func6.test new file mode 100644 index 0000000000..5350aeaa7b --- /dev/null +++ b/test/func6.test @@ -0,0 +1,36 @@ +# 2017-12-16 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#************************************************************************* +# +# Test cases for the location() function. +# +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +do_execsql_test func6-100 { + CREATE TABLE t1(a,b,c,d); + WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100) + INSERT INTO t1(a,b,c,d) SELECT printf('abc%03x',x), x, 1000-x, NULL FROM c; +} +do_execsql_test func6-110 { + SELECT a, typeof(location(a)) FROM t1 ORDER BY rowid LIMIT 2; +} {abc001 integer abc002 integer} +do_execsql_test func6-120 { + SELECT a, typeof(location(+a)) FROM t1 ORDER BY rowid LIMIT 2; +} {abc001 null abc002 null} +do_execsql_test func6-130 { + CREATE INDEX t1a ON t1(a); + SELECT a, typeof(location(a)) FROM t1 ORDER BY a LIMIT 2; +} {abc001 null abc002 null} +do_execsql_test func6-140 { + SELECT a, typeof(location(a)) FROM t1 NOT INDEXED ORDER BY a LIMIT 2; +} {abc001 integer abc002 integer} + +finish_test From 1be266ba089bf463f1b0a5ea2839b7a1341d91ab Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 24 Dec 2017 00:18:47 +0000 Subject: [PATCH 02/40] Remove the ExprSpan object. Instead, keep track of the test of subphrases in the parse using the "scanpt" non-terminal. FossilOrigin-Name: 3eab7bdc44e0878b83dc86f27058a40c2ffafeacadc566f03693f6dc7e40a504 --- manifest | 21 +-- manifest.uuid | 2 +- src/build.c | 23 ++- src/expr.c | 11 +- src/parse.y | 408 ++++++++++++++++++++---------------------------- src/sqliteInt.h | 16 +- 6 files changed, 207 insertions(+), 274 deletions(-) diff --git a/manifest b/manifest index f187cc0290..3cc840deb1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Simplification\sto\sthe\serror\shandling\slogic\sin\sthe\sextension\sloader. -D 2017-12-23T14:39:36.160 +C Remove\sthe\sExprSpan\sobject.\sInstead,\skeep\strack\sof\sthe\stest\sof\ssubphrases\sin\nthe\sparse\susing\sthe\s"scanpt"\snon-terminal. +D 2017-12-24T00:18:47.740 F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69 @@ -423,7 +423,7 @@ F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca F src/btree.c b83a6b03f160528020bb965f0c3a40af5286cd4923c3870fd218177f03a120a7 F src/btree.h 32ef5d3f25dc70ef1ee9cecf84a023c21378f06a57cd701d2e866e141b150f09 F src/btreeInt.h 55b702efce17e5d1941865464227d3802cfc9c7c832fac81d4c94dced47a71fc -F src/build.c ed567f088edbc305dad33a6b14e08f8216a3860f6bad1d180450d5a5414bf346 +F src/build.c d3d2feeeee9c6b41a0bc7a00e4803724780f29f27ef16633b6e32aa0901c7994 F src/callback.c fe677cb5f5abb02f7a772a62a98c2f516426081df68856e8f2d5f950929b966a F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c ff1be3eed7bdd75aaca61ca8dc848f7c9f850ef2fb9cb56f2734e922a098f9c0 @@ -431,7 +431,7 @@ F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957 F src/dbpage.c 8db4c97f630e7d83f884ea75caf1ffd0988c160e9d530194d93721c80821e0f6 F src/dbstat.c 7a4ba8518b6369ef3600c49cf9c918ad979acba610b2aebef1b656d649b96720 F src/delete.c 74667ad914ac143731a444a1bacf29ceb18f6eded8a0dd17aafae80baa07f8bb -F src/expr.c fe11b91bb65b869143bd42023427c4429778ae42c0a0db7762f68f75b347a958 +F src/expr.c 04188faa71b86bff3a1de46d92f41b9ec2b18fa1bbbdbf683cfff657fe803f3d F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c d617daf66b5515e2b42c1405b2b4984c30ca50fb705ab164271a9bf66c69e331 F src/func.c 0fb9a2d678d3c8aba89b46468b309cd7e8fa9806a369a30aa89024660845bb13 @@ -467,7 +467,7 @@ F src/os_win.c 0a4afa35cc8e812000df3ea2f64b476131b39e29e75d8007d0504726e4761de4 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c 07cf850241667874fcce9d7d924c814305e499b26c804322e2261247b5921903 F src/pager.h 581698f2177e8bd4008fe4760898ce20b6133d1df22139b9101b5155f900df7a -F src/parse.y d79001da275bfe344b409006b85e81e486a0f6afc3762fdf0944f000f4aa0111 +F src/parse.y 1e29222ba074fea8d84438098e00812071d4cfd34c8620f34accab7cd523a276 F src/pcache.c 7ae91a4557a43d77d449accbfdc68846e6516f8e2eda46e8bbe4536fb669b201 F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170 F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880 @@ -483,7 +483,7 @@ F src/shell.c.in 339169a3d1307b5566ebe9ce15832d03439206106724c78cc3d9125a7b85179 F src/sqlite.h.in 2126192945019d4cdce335cb236b440a05ec75c93e4cd94c9c6d6e7fcc654cc4 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34 -F src/sqliteInt.h 003b78433baae4e5c997f99f2f9cf98d90754f256baeacb32f8189569a48251f +F src/sqliteInt.h 124be5e9bacd2a356ba17875bbaddf5f25aa1ba8a292233210ba8141ecc58316 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 9737ed017279a9e0c5da748701c3c7bf1e8ae0dae459aad20dd64fcff97a7e35 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -1687,7 +1687,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 05fee1a21ea398f1e4d6f1cf361657eff25ed6cd8f85ab398262dcfd30da57e9 -R 7fbfe3e61eca395fa5baf5f121a4d2ad +P 07c773148d8db185fa54991df09298b64f4fef28879e6c9395759265e8183977 +R 1cdf837f203b6ea58ba0352a2b260bed +T *branch * span-refactor +T *sym-span-refactor * +T -sym-trunk * U drh -Z d82d9c01768cefc5beb206b92e1398bf +Z 03a6ffebedfd10412e429ce17606ec66 diff --git a/manifest.uuid b/manifest.uuid index 8454418cd5..512e591247 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -07c773148d8db185fa54991df09298b64f4fef28879e6c9395759265e8183977 \ No newline at end of file +3eab7bdc44e0878b83dc86f27058a40c2ffafeacadc566f03693f6dc7e40a504 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 01d8972415..edf300628b 100644 --- a/src/build.c +++ b/src/build.c @@ -1221,34 +1221,41 @@ char sqlite3AffinityType(const char *zIn, u8 *pszEst){ ** This routine is called by the parser while in the middle of ** parsing a CREATE TABLE statement. */ -void sqlite3AddDefaultValue(Parse *pParse, ExprSpan *pSpan){ +void sqlite3AddDefaultValue( + Parse *pParse, /* Parsing context */ + Expr *pExpr, /* The parsed expression of the default value */ + const char *zStart, /* Start of the default value text */ + const char *zEnd /* First character past end of defaut value text */ +){ Table *p; Column *pCol; sqlite3 *db = pParse->db; p = pParse->pNewTable; if( p!=0 ){ pCol = &(p->aCol[p->nCol-1]); - if( !sqlite3ExprIsConstantOrFunction(pSpan->pExpr, db->init.busy) ){ + if( !sqlite3ExprIsConstantOrFunction(pExpr, db->init.busy) ){ sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant", pCol->zName); }else{ /* A copy of pExpr is used instead of the original, as pExpr contains - ** tokens that point to volatile memory. The 'span' of the expression - ** is required by pragma table_info. + ** tokens that point to volatile memory. */ Expr x; + int n; sqlite3ExprDelete(db, pCol->pDflt); memset(&x, 0, sizeof(x)); x.op = TK_SPAN; - x.u.zToken = sqlite3DbStrNDup(db, (char*)pSpan->zStart, - (int)(pSpan->zEnd - pSpan->zStart)); - x.pLeft = pSpan->pExpr; + while( sqlite3Isspace(zStart[0]) ) zStart++; + n = (int)(zEnd - zStart); + while( n>0 && sqlite3Isspace(zStart[n-1]) ) n--; + x.u.zToken = sqlite3DbStrNDup(db, zStart, n); + x.pLeft = pExpr; x.flags = EP_Skip; pCol->pDflt = sqlite3ExprDup(db, &x, EXPRDUP_REDUCE); sqlite3DbFree(db, x.u.zToken); } } - sqlite3ExprDelete(db, pSpan->pExpr); + sqlite3ExprDelete(db, pExpr); } /* diff --git a/src/expr.c b/src/expr.c index 524e539349..129c1299bf 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1654,17 +1654,20 @@ void sqlite3ExprListSetName( void sqlite3ExprListSetSpan( Parse *pParse, /* Parsing context */ ExprList *pList, /* List to which to add the span. */ - ExprSpan *pSpan /* The span to be added */ + const char *zStart, /* Start of the span */ + const char *zEnd /* End of the span */ ){ sqlite3 *db = pParse->db; assert( pList!=0 || db->mallocFailed!=0 ); if( pList ){ struct ExprList_item *pItem = &pList->a[pList->nExpr-1]; + int n; assert( pList->nExpr>0 ); - assert( db->mallocFailed || pItem->pExpr==pSpan->pExpr ); sqlite3DbFree(db, pItem->zSpan); - pItem->zSpan = sqlite3DbStrNDup(db, (char*)pSpan->zStart, - (int)(pSpan->zEnd - pSpan->zStart)); + while( sqlite3Isspace(zStart[0]) ) zStart++; + n = (int)(zEnd - zStart); + while( n>0 && sqlite3Isspace(zStart[n-1]) ) n--; + pItem->zSpan = sqlite3DbStrNDup(db, zStart, n); } } diff --git a/src/parse.y b/src/parse.y index 0867d1e0c8..d59426409c 100644 --- a/src/parse.y +++ b/src/parse.y @@ -273,26 +273,47 @@ typename(A) ::= typename(A) ids(Y). {A.n=Y.n+(int)(Y.z-A.z);} signed ::= plus_num. signed ::= minus_num. +// The scanpt non-terminal takes a value which is a pointer to the +// input text just past the last token that has been shifted into +// the parser. By surrounding some phrase in the grammar with two +// scanpt non-terminals, we can capture the input text for that phrase. +// For example: +// +// something ::= .... scanpt(A) phrase scanpt(Z). +// +// The text that is parsed as "phrase" is a string starting at A +// and containing (int)(Z-A) characters. There might be some extra +// whitespace on either end of the text, but that can be removed in +// post-processing, if needed. +// +%type scanpt {const char*} +scanpt(A) ::= . { + if( yyLookahead!=YYNOCODE ){ + A = yyLookaheadToken.z; + }else{ + A = pParse->sLastToken.z + pParse->sLastToken.n; + } +} + // "carglist" is a list of additional constraints that come after the // column name and column type in a CREATE TABLE statement. // carglist ::= carglist ccons. carglist ::= . ccons ::= CONSTRAINT nm(X). {pParse->constraintName = X;} -ccons ::= DEFAULT term(X). {sqlite3AddDefaultValue(pParse,&X);} -ccons ::= DEFAULT LP expr(X) RP. {sqlite3AddDefaultValue(pParse,&X);} -ccons ::= DEFAULT PLUS term(X). {sqlite3AddDefaultValue(pParse,&X);} -ccons ::= DEFAULT MINUS(A) term(X). { - ExprSpan v; - v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, X.pExpr, 0); - v.zStart = A.z; - v.zEnd = X.zEnd; - sqlite3AddDefaultValue(pParse,&v); +ccons ::= DEFAULT scanpt(A) term(X) scanpt(Z). + {sqlite3AddDefaultValue(pParse,X,A,Z);} +ccons ::= DEFAULT LP(A) expr(X) RP(Z). + {sqlite3AddDefaultValue(pParse,X,A.z+1,Z.z);} +ccons ::= DEFAULT PLUS(A) term(X) scanpt(Z). + {sqlite3AddDefaultValue(pParse,X,A.z,Z);} +ccons ::= DEFAULT MINUS(A) term(X) scanpt(Z). { + Expr *p = sqlite3PExpr(pParse, TK_UMINUS, X, 0); + sqlite3AddDefaultValue(pParse,p,A.z,Z); } -ccons ::= DEFAULT id(X). { - ExprSpan v; - spanExpr(&v, pParse, TK_STRING, X); - sqlite3AddDefaultValue(pParse,&v); +ccons ::= DEFAULT scanpt id(X). { + Expr *p = tokenExpr(pParse, TK_STRING, X); + sqlite3AddDefaultValue(pParse,p,X.z,X.z+X.n); } // In addition to the type name, we also care about the primary key and @@ -304,7 +325,7 @@ ccons ::= PRIMARY KEY sortorder(Z) onconf(R) autoinc(I). {sqlite3AddPrimaryKey(pParse,0,R,I,Z);} ccons ::= UNIQUE onconf(R). {sqlite3CreateIndex(pParse,0,0,0,0,R,0,0,0,0, SQLITE_IDXTYPE_UNIQUE);} -ccons ::= CHECK LP expr(X) RP. {sqlite3AddCheckConstraint(pParse,X.pExpr);} +ccons ::= CHECK LP expr(X) RP. {sqlite3AddCheckConstraint(pParse,X);} ccons ::= REFERENCES nm(T) eidlist_opt(TA) refargs(R). {sqlite3CreateForeignKey(pParse,0,&T,TA,R);} ccons ::= defer_subclause(D). {sqlite3DeferForeignKey(pParse,D);} @@ -355,7 +376,7 @@ tcons ::= UNIQUE LP sortlist(X) RP onconf(R). {sqlite3CreateIndex(pParse,0,0,0,X,R,0,0,0,0, SQLITE_IDXTYPE_UNIQUE);} tcons ::= CHECK LP expr(E) RP onconf. - {sqlite3AddCheckConstraint(pParse,E.pExpr);} + {sqlite3AddCheckConstraint(pParse,E);} tcons ::= FOREIGN KEY LP eidlist(FA) RP REFERENCES nm(T) eidlist_opt(TA) refargs(R) defer_subclause_opt(D). { sqlite3CreateForeignKey(pParse, FA, &T, TA, R); @@ -549,16 +570,16 @@ distinct(A) ::= . {A = 0;} %destructor sclp {sqlite3ExprListDelete(pParse->db, $$);} sclp(A) ::= selcollist(A) COMMA. sclp(A) ::= . {A = 0;} -selcollist(A) ::= sclp(A) expr(X) as(Y). { - A = sqlite3ExprListAppend(pParse, A, X.pExpr); +selcollist(A) ::= sclp(A) scanpt(B) expr(X) scanpt(Z) as(Y). { + A = sqlite3ExprListAppend(pParse, A, X); if( Y.n>0 ) sqlite3ExprListSetName(pParse, A, &Y, 1); - sqlite3ExprListSetSpan(pParse,A,&X); + sqlite3ExprListSetSpan(pParse,A,B,Z); } selcollist(A) ::= sclp(A) STAR. { Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0); A = sqlite3ExprListAppend(pParse, A, p); } -selcollist(A) ::= sclp(A) nm(X) DOT STAR. { +selcollist(A) ::= sclp(A) scanpt nm(X) DOT STAR. { Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0); Expr *pLeft = sqlite3ExprAlloc(pParse->db, TK_ID, &X, 1); Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight); @@ -656,7 +677,7 @@ joinop(X) ::= JOIN_KW(A) nm(B) nm(C) JOIN. %type on_opt {Expr*} %destructor on_opt {sqlite3ExprDelete(pParse->db, $$);} -on_opt(N) ::= ON expr(E). {N = E.pExpr;} +on_opt(N) ::= ON expr(E). {N = E;} on_opt(N) ::= . {N = 0;} // Note that this block abuses the Token type just a little. If there is @@ -693,11 +714,11 @@ using_opt(U) ::= . {U = 0;} orderby_opt(A) ::= . {A = 0;} orderby_opt(A) ::= ORDER BY sortlist(X). {A = X;} sortlist(A) ::= sortlist(A) COMMA expr(Y) sortorder(Z). { - A = sqlite3ExprListAppend(pParse,A,Y.pExpr); + A = sqlite3ExprListAppend(pParse,A,Y); sqlite3ExprListSetSortOrder(A,Z); } sortlist(A) ::= expr(Y) sortorder(Z). { - A = sqlite3ExprListAppend(pParse,0,Y.pExpr); /*A-overwrites-Y*/ + A = sqlite3ExprListAppend(pParse,0,Y); /*A-overwrites-Y*/ sqlite3ExprListSetSortOrder(A,Z); } @@ -715,7 +736,7 @@ groupby_opt(A) ::= GROUP BY nexprlist(X). {A = X;} %type having_opt {Expr*} %destructor having_opt {sqlite3ExprDelete(pParse->db, $$);} having_opt(A) ::= . {A = 0;} -having_opt(A) ::= HAVING expr(X). {A = X.pExpr;} +having_opt(A) ::= HAVING expr(X). {A = X;} %type limit_opt {Expr*} @@ -729,11 +750,11 @@ having_opt(A) ::= HAVING expr(X). {A = X.pExpr;} //%destructor limit_opt {sqlite3ExprDelete(pParse->db, $$);} limit_opt(A) ::= . {A = 0;} limit_opt(A) ::= LIMIT expr(X). - {A = sqlite3PExpr(pParse,TK_LIMIT,X.pExpr,0);} + {A = sqlite3PExpr(pParse,TK_LIMIT,X,0);} limit_opt(A) ::= LIMIT expr(X) OFFSET expr(Y). - {A = sqlite3PExpr(pParse,TK_LIMIT,X.pExpr,Y.pExpr);} + {A = sqlite3PExpr(pParse,TK_LIMIT,X,Y);} limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y). - {A = sqlite3PExpr(pParse,TK_LIMIT,Y.pExpr,X.pExpr);} + {A = sqlite3PExpr(pParse,TK_LIMIT,Y,X);} /////////////////////////// The DELETE statement ///////////////////////////// // @@ -757,7 +778,7 @@ cmd ::= with(C) DELETE FROM fullname(X) indexed_opt(I) where_opt(W). { %destructor where_opt {sqlite3ExprDelete(pParse->db, $$);} where_opt(A) ::= . {A = 0;} -where_opt(A) ::= WHERE expr(X). {A = X.pExpr;} +where_opt(A) ::= WHERE expr(X). {A = X;} ////////////////////////// The UPDATE command //////////////////////////////// // @@ -784,18 +805,18 @@ cmd ::= with(C) UPDATE orconf(R) fullname(X) indexed_opt(I) SET setlist(Y) %destructor setlist {sqlite3ExprListDelete(pParse->db, $$);} setlist(A) ::= setlist(A) COMMA nm(X) EQ expr(Y). { - A = sqlite3ExprListAppend(pParse, A, Y.pExpr); + A = sqlite3ExprListAppend(pParse, A, Y); sqlite3ExprListSetName(pParse, A, &X, 1); } setlist(A) ::= setlist(A) COMMA LP idlist(X) RP EQ expr(Y). { - A = sqlite3ExprListAppendVector(pParse, A, X, Y.pExpr); + A = sqlite3ExprListAppendVector(pParse, A, X, Y); } setlist(A) ::= nm(X) EQ expr(Y). { - A = sqlite3ExprListAppend(pParse, 0, Y.pExpr); + A = sqlite3ExprListAppend(pParse, 0, Y); sqlite3ExprListSetName(pParse, A, &X, 1); } setlist(A) ::= LP idlist(X) RP EQ expr(Y). { - A = sqlite3ExprListAppendVector(pParse, 0, X, Y.pExpr); + A = sqlite3ExprListAppendVector(pParse, 0, X, Y); } ////////////////////////// The INSERT command ///////////////////////////////// @@ -829,26 +850,18 @@ idlist(A) ::= nm(Y). /////////////////////////// Expression Processing ///////////////////////////// // -%type expr {ExprSpan} -%destructor expr {sqlite3ExprDelete(pParse->db, $$.pExpr);} -%type term {ExprSpan} -%destructor term {sqlite3ExprDelete(pParse->db, $$.pExpr);} +%type expr {Expr*} +%destructor expr {sqlite3ExprDelete(pParse->db, $$);} +%type term {Expr*} +%destructor term {sqlite3ExprDelete(pParse->db, $$);} %include { - /* This is a utility routine used to set the ExprSpan.zStart and - ** ExprSpan.zEnd values of pOut so that the span covers the complete - ** range of text beginning with pStart and going to the end of pEnd. - */ - static void spanSet(ExprSpan *pOut, Token *pStart, Token *pEnd){ - pOut->zStart = pStart->z; - pOut->zEnd = &pEnd->z[pEnd->n]; - } /* Construct a new Expr object from a single identifier. Use the ** new Expr to populate pOut. Set the span of pOut to be the identifier ** that created the expression. */ - static void spanExpr(ExprSpan *pOut, Parse *pParse, int op, Token t){ + static Expr *tokenExpr(Parse *pParse, int op, Token t){ Expr *p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr)+t.n+1); if( p ){ memset(p, 0, sizeof(Expr)); @@ -866,136 +879,98 @@ idlist(A) ::= nm(Y). p->nHeight = 1; #endif } - pOut->pExpr = p; - pOut->zStart = t.z; - pOut->zEnd = &t.z[t.n]; + return p; } } expr(A) ::= term(A). -expr(A) ::= LP(B) expr(X) RP(E). - {spanSet(&A,&B,&E); /*A-overwrites-B*/ A.pExpr = X.pExpr;} -expr(A) ::= id(X). {spanExpr(&A,pParse,TK_ID,X); /*A-overwrites-X*/} -expr(A) ::= JOIN_KW(X). {spanExpr(&A,pParse,TK_ID,X); /*A-overwrites-X*/} +expr(A) ::= LP expr(X) RP. {A = X;} +expr(A) ::= id(X). {A=tokenExpr(pParse,TK_ID,X); /*A-overwrites-X*/} +expr(A) ::= JOIN_KW(X). {A=tokenExpr(pParse,TK_ID,X); /*A-overwrites-X*/} expr(A) ::= nm(X) DOT nm(Y). { Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &X, 1); Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &Y, 1); - spanSet(&A,&X,&Y); /*A-overwrites-X*/ - A.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2); + A = sqlite3PExpr(pParse, TK_DOT, temp1, temp2); } expr(A) ::= nm(X) DOT nm(Y) DOT nm(Z). { Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &X, 1); Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &Y, 1); Expr *temp3 = sqlite3ExprAlloc(pParse->db, TK_ID, &Z, 1); Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3); - spanSet(&A,&X,&Z); /*A-overwrites-X*/ - A.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4); + A = sqlite3PExpr(pParse, TK_DOT, temp1, temp4); } -term(A) ::= NULL|FLOAT|BLOB(X). {spanExpr(&A,pParse,@X,X); /*A-overwrites-X*/} -term(A) ::= STRING(X). {spanExpr(&A,pParse,@X,X); /*A-overwrites-X*/} +term(A) ::= NULL|FLOAT|BLOB(X). {A=tokenExpr(pParse,@X,X); /*A-overwrites-X*/} +term(A) ::= STRING(X). {A=tokenExpr(pParse,@X,X); /*A-overwrites-X*/} term(A) ::= INTEGER(X). { - A.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &X, 1); - A.zStart = X.z; - A.zEnd = X.z + X.n; + A = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &X, 1); } expr(A) ::= VARIABLE(X). { if( !(X.z[0]=='#' && sqlite3Isdigit(X.z[1])) ){ u32 n = X.n; - spanExpr(&A, pParse, TK_VARIABLE, X); - sqlite3ExprAssignVarNumber(pParse, A.pExpr, n); + A = tokenExpr(pParse, TK_VARIABLE, X); + sqlite3ExprAssignVarNumber(pParse, A, n); }else{ /* When doing a nested parse, one can include terms in an expression ** that look like this: #1 #2 ... These terms refer to registers ** in the virtual machine. #N is the N-th register. */ Token t = X; /*A-overwrites-X*/ assert( t.n>=2 ); - spanSet(&A, &t, &t); if( pParse->nested==0 ){ sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t); - A.pExpr = 0; + A = 0; }else{ - A.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0); - if( A.pExpr ) sqlite3GetInt32(&t.z[1], &A.pExpr->iTable); + A = sqlite3PExpr(pParse, TK_REGISTER, 0, 0); + if( A ) sqlite3GetInt32(&t.z[1], &A->iTable); } } } expr(A) ::= expr(A) COLLATE ids(C). { - A.pExpr = sqlite3ExprAddCollateToken(pParse, A.pExpr, &C, 1); - A.zEnd = &C.z[C.n]; + A = sqlite3ExprAddCollateToken(pParse, A, &C, 1); } %ifndef SQLITE_OMIT_CAST -expr(A) ::= CAST(X) LP expr(E) AS typetoken(T) RP(Y). { - spanSet(&A,&X,&Y); /*A-overwrites-X*/ - A.pExpr = sqlite3ExprAlloc(pParse->db, TK_CAST, &T, 1); - sqlite3ExprAttachSubtrees(pParse->db, A.pExpr, E.pExpr, 0); +expr(A) ::= CAST LP expr(E) AS typetoken(T) RP. { + A = sqlite3ExprAlloc(pParse->db, TK_CAST, &T, 1); + sqlite3ExprAttachSubtrees(pParse->db, A, E, 0); } %endif SQLITE_OMIT_CAST -expr(A) ::= id(X) LP distinct(D) exprlist(Y) RP(E). { +expr(A) ::= id(X) LP distinct(D) exprlist(Y) RP. { if( Y && Y->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ sqlite3ErrorMsg(pParse, "too many arguments on function %T", &X); } - A.pExpr = sqlite3ExprFunction(pParse, Y, &X); - spanSet(&A,&X,&E); - if( D==SF_Distinct && A.pExpr ){ - A.pExpr->flags |= EP_Distinct; + A = sqlite3ExprFunction(pParse, Y, &X); + if( D==SF_Distinct && A ){ + A->flags |= EP_Distinct; } } -expr(A) ::= id(X) LP STAR RP(E). { - A.pExpr = sqlite3ExprFunction(pParse, 0, &X); - spanSet(&A,&X,&E); +expr(A) ::= id(X) LP STAR RP. { + A = sqlite3ExprFunction(pParse, 0, &X); } term(A) ::= CTIME_KW(OP). { - A.pExpr = sqlite3ExprFunction(pParse, 0, &OP); - spanSet(&A, &OP, &OP); + A = sqlite3ExprFunction(pParse, 0, &OP); } -%include { - /* This routine constructs a binary expression node out of two ExprSpan - ** objects and uses the result to populate a new ExprSpan object. - */ - static void spanBinaryExpr( - Parse *pParse, /* The parsing context. Errors accumulate here */ - int op, /* The binary operation */ - ExprSpan *pLeft, /* The left operand, and output */ - ExprSpan *pRight /* The right operand */ - ){ - pLeft->pExpr = sqlite3PExpr(pParse, op, pLeft->pExpr, pRight->pExpr); - pLeft->zEnd = pRight->zEnd; - } - - /* If doNot is true, then add a TK_NOT Expr-node wrapper around the - ** outside of *ppExpr. - */ - static void exprNot(Parse *pParse, int doNot, ExprSpan *pSpan){ - if( doNot ){ - pSpan->pExpr = sqlite3PExpr(pParse, TK_NOT, pSpan->pExpr, 0); - } - } -} - -expr(A) ::= LP(L) nexprlist(X) COMMA expr(Y) RP(R). { - ExprList *pList = sqlite3ExprListAppend(pParse, X, Y.pExpr); - A.pExpr = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); - if( A.pExpr ){ - A.pExpr->x.pList = pList; - spanSet(&A, &L, &R); +expr(A) ::= LP nexprlist(X) COMMA expr(Y) RP. { + ExprList *pList = sqlite3ExprListAppend(pParse, X, Y); + A = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); + if( A ){ + A->x.pList = pList; }else{ sqlite3ExprListDelete(pParse->db, pList); } } -expr(A) ::= expr(A) AND(OP) expr(Y). {spanBinaryExpr(pParse,@OP,&A,&Y);} -expr(A) ::= expr(A) OR(OP) expr(Y). {spanBinaryExpr(pParse,@OP,&A,&Y);} +expr(A) ::= expr(A) AND(OP) expr(Y). {A=sqlite3PExpr(pParse,@OP,A,Y);} +expr(A) ::= expr(A) OR(OP) expr(Y). {A=sqlite3PExpr(pParse,@OP,A,Y);} expr(A) ::= expr(A) LT|GT|GE|LE(OP) expr(Y). - {spanBinaryExpr(pParse,@OP,&A,&Y);} -expr(A) ::= expr(A) EQ|NE(OP) expr(Y). {spanBinaryExpr(pParse,@OP,&A,&Y);} + {A=sqlite3PExpr(pParse,@OP,A,Y);} +expr(A) ::= expr(A) EQ|NE(OP) expr(Y). {A=sqlite3PExpr(pParse,@OP,A,Y);} expr(A) ::= expr(A) BITAND|BITOR|LSHIFT|RSHIFT(OP) expr(Y). - {spanBinaryExpr(pParse,@OP,&A,&Y);} + {A=sqlite3PExpr(pParse,@OP,A,Y);} expr(A) ::= expr(A) PLUS|MINUS(OP) expr(Y). - {spanBinaryExpr(pParse,@OP,&A,&Y);} + {A=sqlite3PExpr(pParse,@OP,A,Y);} expr(A) ::= expr(A) STAR|SLASH|REM(OP) expr(Y). - {spanBinaryExpr(pParse,@OP,&A,&Y);} -expr(A) ::= expr(A) CONCAT(OP) expr(Y). {spanBinaryExpr(pParse,@OP,&A,&Y);} + {A=sqlite3PExpr(pParse,@OP,A,Y);} +expr(A) ::= expr(A) CONCAT(OP) expr(Y). {A=sqlite3PExpr(pParse,@OP,A,Y);} %type likeop {Token} likeop(A) ::= LIKE_KW|MATCH(A). likeop(A) ::= NOT LIKE_KW|MATCH(X). {A=X; A.n|=0x80000000; /*A-overwrite-X*/} @@ -1003,42 +978,26 @@ expr(A) ::= expr(A) likeop(OP) expr(Y). [LIKE_KW] { ExprList *pList; int bNot = OP.n & 0x80000000; OP.n &= 0x7fffffff; - pList = sqlite3ExprListAppend(pParse,0, Y.pExpr); - pList = sqlite3ExprListAppend(pParse,pList, A.pExpr); - A.pExpr = sqlite3ExprFunction(pParse, pList, &OP); - exprNot(pParse, bNot, &A); - A.zEnd = Y.zEnd; - if( A.pExpr ) A.pExpr->flags |= EP_InfixFunc; + pList = sqlite3ExprListAppend(pParse,0, Y); + pList = sqlite3ExprListAppend(pParse,pList, A); + A = sqlite3ExprFunction(pParse, pList, &OP); + if( bNot ) A = sqlite3PExpr(pParse, TK_NOT, A, 0); + if( A ) A->flags |= EP_InfixFunc; } expr(A) ::= expr(A) likeop(OP) expr(Y) ESCAPE expr(E). [LIKE_KW] { ExprList *pList; int bNot = OP.n & 0x80000000; OP.n &= 0x7fffffff; - pList = sqlite3ExprListAppend(pParse,0, Y.pExpr); - pList = sqlite3ExprListAppend(pParse,pList, A.pExpr); - pList = sqlite3ExprListAppend(pParse,pList, E.pExpr); - A.pExpr = sqlite3ExprFunction(pParse, pList, &OP); - exprNot(pParse, bNot, &A); - A.zEnd = E.zEnd; - if( A.pExpr ) A.pExpr->flags |= EP_InfixFunc; + pList = sqlite3ExprListAppend(pParse,0, Y); + pList = sqlite3ExprListAppend(pParse,pList, A); + pList = sqlite3ExprListAppend(pParse,pList, E); + A = sqlite3ExprFunction(pParse, pList, &OP); + if( bNot ) A = sqlite3PExpr(pParse, TK_NOT, A, 0); + if( A ) A->flags |= EP_InfixFunc; } -%include { - /* Construct an expression node for a unary postfix operator - */ - static void spanUnaryPostfix( - Parse *pParse, /* Parsing context to record errors */ - int op, /* The operator */ - ExprSpan *pOperand, /* The operand, and output */ - Token *pPostOp /* The operand token for setting the span */ - ){ - pOperand->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0); - pOperand->zEnd = &pPostOp->z[pPostOp->n]; - } -} - -expr(A) ::= expr(A) ISNULL|NOTNULL(E). {spanUnaryPostfix(pParse,@E,&A,&E);} -expr(A) ::= expr(A) NOT NULL(E). {spanUnaryPostfix(pParse,TK_NOTNULL,&A,&E);} +expr(A) ::= expr(A) ISNULL|NOTNULL(E). {A = sqlite3PExpr(pParse,@E,A,0);} +expr(A) ::= expr(A) NOT NULL. {A = sqlite3PExpr(pParse,TK_NOTNULL,A,0);} %include { /* A routine to convert a binary TK_IS or TK_ISNOT expression into a @@ -1060,61 +1019,42 @@ expr(A) ::= expr(A) NOT NULL(E). {spanUnaryPostfix(pParse,TK_NOTNULL,&A,&E);} // is any other expression, code as TK_IS or TK_ISNOT. // expr(A) ::= expr(A) IS expr(Y). { - spanBinaryExpr(pParse,TK_IS,&A,&Y); - binaryToUnaryIfNull(pParse, Y.pExpr, A.pExpr, TK_ISNULL); + A = sqlite3PExpr(pParse,TK_IS,A,Y); + binaryToUnaryIfNull(pParse, Y, A, TK_ISNULL); } expr(A) ::= expr(A) IS NOT expr(Y). { - spanBinaryExpr(pParse,TK_ISNOT,&A,&Y); - binaryToUnaryIfNull(pParse, Y.pExpr, A.pExpr, TK_NOTNULL); + A = sqlite3PExpr(pParse,TK_ISNOT,A,Y); + binaryToUnaryIfNull(pParse, Y, A, TK_NOTNULL); } -%include { - /* Construct an expression node for a unary prefix operator - */ - static void spanUnaryPrefix( - ExprSpan *pOut, /* Write the new expression node here */ - Parse *pParse, /* Parsing context to record errors */ - int op, /* The operator */ - ExprSpan *pOperand, /* The operand */ - Token *pPreOp /* The operand token for setting the span */ - ){ - pOut->zStart = pPreOp->z; - pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0); - pOut->zEnd = pOperand->zEnd; - } -} - - - expr(A) ::= NOT(B) expr(X). - {spanUnaryPrefix(&A,pParse,@B,&X,&B);/*A-overwrites-B*/} + {A = sqlite3PExpr(pParse, @B, X, 0);/*A-overwrites-B*/} expr(A) ::= BITNOT(B) expr(X). - {spanUnaryPrefix(&A,pParse,@B,&X,&B);/*A-overwrites-B*/} -expr(A) ::= MINUS(B) expr(X). [BITNOT] - {spanUnaryPrefix(&A,pParse,TK_UMINUS,&X,&B);/*A-overwrites-B*/} -expr(A) ::= PLUS(B) expr(X). [BITNOT] - {spanUnaryPrefix(&A,pParse,TK_UPLUS,&X,&B);/*A-overwrites-B*/} + {A = sqlite3PExpr(pParse, @B, X, 0);/*A-overwrites-B*/} +expr(A) ::= MINUS expr(X). [BITNOT] + {A = sqlite3PExpr(pParse, TK_UMINUS, X, 0);} +expr(A) ::= PLUS expr(X). [BITNOT] + {A = sqlite3PExpr(pParse, TK_UPLUS, X, 0);} %type between_op {int} between_op(A) ::= BETWEEN. {A = 0;} between_op(A) ::= NOT BETWEEN. {A = 1;} expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] { - ExprList *pList = sqlite3ExprListAppend(pParse,0, X.pExpr); - pList = sqlite3ExprListAppend(pParse,pList, Y.pExpr); - A.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, A.pExpr, 0); - if( A.pExpr ){ - A.pExpr->x.pList = pList; + ExprList *pList = sqlite3ExprListAppend(pParse,0, X); + pList = sqlite3ExprListAppend(pParse,pList, Y); + A = sqlite3PExpr(pParse, TK_BETWEEN, A, 0); + if( A ){ + A->x.pList = pList; }else{ sqlite3ExprListDelete(pParse->db, pList); } - exprNot(pParse, N, &A); - A.zEnd = Y.zEnd; + if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0); } %ifndef SQLITE_OMIT_SUBQUERY %type in_op {int} in_op(A) ::= IN. {A = 0;} in_op(A) ::= NOT IN. {A = 1;} - expr(A) ::= expr(A) in_op(N) LP exprlist(Y) RP(E). [IN] { + expr(A) ::= expr(A) in_op(N) LP exprlist(Y) RP. [IN] { if( Y==0 ){ /* Expressions of the form ** @@ -1124,8 +1064,8 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] { ** simplify to constants 0 (false) and 1 (true), respectively, ** regardless of the value of expr1. */ - sqlite3ExprDelete(pParse->db, A.pExpr); - A.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[N],1); + sqlite3ExprDelete(pParse->db, A); + A = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[N],1); }else if( Y->nExpr==1 ){ /* Expressions of the form: ** @@ -1152,54 +1092,48 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] { pRHS->flags &= ~EP_Collate; pRHS->flags |= EP_Generic; } - A.pExpr = sqlite3PExpr(pParse, N ? TK_NE : TK_EQ, A.pExpr, pRHS); + A = sqlite3PExpr(pParse, N ? TK_NE : TK_EQ, A, pRHS); }else{ - A.pExpr = sqlite3PExpr(pParse, TK_IN, A.pExpr, 0); - if( A.pExpr ){ - A.pExpr->x.pList = Y; - sqlite3ExprSetHeightAndFlags(pParse, A.pExpr); + A = sqlite3PExpr(pParse, TK_IN, A, 0); + if( A ){ + A->x.pList = Y; + sqlite3ExprSetHeightAndFlags(pParse, A); }else{ sqlite3ExprListDelete(pParse->db, Y); } - exprNot(pParse, N, &A); + if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0); } - A.zEnd = &E.z[E.n]; } - expr(A) ::= LP(B) select(X) RP(E). { - spanSet(&A,&B,&E); /*A-overwrites-B*/ - A.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0); - sqlite3PExprAddSelect(pParse, A.pExpr, X); + expr(A) ::= LP select(X) RP. { + A = sqlite3PExpr(pParse, TK_SELECT, 0, 0); + sqlite3PExprAddSelect(pParse, A, X); } - expr(A) ::= expr(A) in_op(N) LP select(Y) RP(E). [IN] { - A.pExpr = sqlite3PExpr(pParse, TK_IN, A.pExpr, 0); - sqlite3PExprAddSelect(pParse, A.pExpr, Y); - exprNot(pParse, N, &A); - A.zEnd = &E.z[E.n]; + expr(A) ::= expr(A) in_op(N) LP select(Y) RP. [IN] { + A = sqlite3PExpr(pParse, TK_IN, A, 0); + sqlite3PExprAddSelect(pParse, A, Y); + if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0); } expr(A) ::= expr(A) in_op(N) nm(Y) dbnm(Z) paren_exprlist(E). [IN] { SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&Y,&Z); Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0); if( E ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, E); - A.pExpr = sqlite3PExpr(pParse, TK_IN, A.pExpr, 0); - sqlite3PExprAddSelect(pParse, A.pExpr, pSelect); - exprNot(pParse, N, &A); - A.zEnd = Z.z ? &Z.z[Z.n] : &Y.z[Y.n]; + A = sqlite3PExpr(pParse, TK_IN, A, 0); + sqlite3PExprAddSelect(pParse, A, pSelect); + if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0); } - expr(A) ::= EXISTS(B) LP select(Y) RP(E). { + expr(A) ::= EXISTS LP select(Y) RP. { Expr *p; - spanSet(&A,&B,&E); /*A-overwrites-B*/ - p = A.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0); + p = A = sqlite3PExpr(pParse, TK_EXISTS, 0, 0); sqlite3PExprAddSelect(pParse, p, Y); } %endif SQLITE_OMIT_SUBQUERY /* CASE expressions */ -expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). { - spanSet(&A,&C,&E); /*A-overwrites-C*/ - A.pExpr = sqlite3PExpr(pParse, TK_CASE, X, 0); - if( A.pExpr ){ - A.pExpr->x.pList = Z ? sqlite3ExprListAppend(pParse,Y,Z) : Y; - sqlite3ExprSetHeightAndFlags(pParse, A.pExpr); +expr(A) ::= CASE case_operand(X) case_exprlist(Y) case_else(Z) END. { + A = sqlite3PExpr(pParse, TK_CASE, X, 0); + if( A ){ + A->x.pList = Z ? sqlite3ExprListAppend(pParse,Y,Z) : Y; + sqlite3ExprSetHeightAndFlags(pParse, A); }else{ sqlite3ExprListDelete(pParse->db, Y); sqlite3ExprDelete(pParse->db, Z); @@ -1208,20 +1142,20 @@ expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). { %type case_exprlist {ExprList*} %destructor case_exprlist {sqlite3ExprListDelete(pParse->db, $$);} case_exprlist(A) ::= case_exprlist(A) WHEN expr(Y) THEN expr(Z). { - A = sqlite3ExprListAppend(pParse,A, Y.pExpr); - A = sqlite3ExprListAppend(pParse,A, Z.pExpr); + A = sqlite3ExprListAppend(pParse,A, Y); + A = sqlite3ExprListAppend(pParse,A, Z); } case_exprlist(A) ::= WHEN expr(Y) THEN expr(Z). { - A = sqlite3ExprListAppend(pParse,0, Y.pExpr); - A = sqlite3ExprListAppend(pParse,A, Z.pExpr); + A = sqlite3ExprListAppend(pParse,0, Y); + A = sqlite3ExprListAppend(pParse,A, Z); } %type case_else {Expr*} %destructor case_else {sqlite3ExprDelete(pParse->db, $$);} -case_else(A) ::= ELSE expr(X). {A = X.pExpr;} +case_else(A) ::= ELSE expr(X). {A = X;} case_else(A) ::= . {A = 0;} %type case_operand {Expr*} %destructor case_operand {sqlite3ExprDelete(pParse->db, $$);} -case_operand(A) ::= expr(X). {A = X.pExpr; /*A-overwrites-X*/} +case_operand(A) ::= expr(X). {A = X; /*A-overwrites-X*/} case_operand(A) ::= . {A = 0;} %type exprlist {ExprList*} @@ -1232,9 +1166,9 @@ case_operand(A) ::= . {A = 0;} exprlist(A) ::= nexprlist(A). exprlist(A) ::= . {A = 0;} nexprlist(A) ::= nexprlist(A) COMMA expr(Y). - {A = sqlite3ExprListAppend(pParse,A,Y.pExpr);} + {A = sqlite3ExprListAppend(pParse,A,Y);} nexprlist(A) ::= expr(Y). - {A = sqlite3ExprListAppend(pParse,0,Y.pExpr); /*A-overwrites-Y*/} + {A = sqlite3ExprListAppend(pParse,0,Y); /*A-overwrites-Y*/} %ifndef SQLITE_OMIT_SUBQUERY /* A paren_exprlist is an optional expression list contained inside @@ -1388,7 +1322,7 @@ foreach_clause ::= FOR EACH ROW. %type when_clause {Expr*} %destructor when_clause {sqlite3ExprDelete(pParse->db, $$);} when_clause(A) ::= . { A = 0; } -when_clause(A) ::= WHEN expr(X). { A = X.pExpr; } +when_clause(A) ::= WHEN expr(X). { A = X; } %type trigger_cmd_list {TriggerStep*} %destructor trigger_cmd_list {sqlite3DeleteTriggerStep(pParse->db, $$);} @@ -1453,18 +1387,16 @@ trigger_cmd(A) ::= select(X). {A = sqlite3TriggerSelectStep(pParse->db, X); /*A-overwrites-X*/} // The special RAISE expression that may occur in trigger programs -expr(A) ::= RAISE(X) LP IGNORE RP(Y). { - spanSet(&A,&X,&Y); /*A-overwrites-X*/ - A.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0); - if( A.pExpr ){ - A.pExpr->affinity = OE_Ignore; +expr(A) ::= RAISE LP IGNORE RP. { + A = sqlite3PExpr(pParse, TK_RAISE, 0, 0); + if( A ){ + A->affinity = OE_Ignore; } } -expr(A) ::= RAISE(X) LP raisetype(T) COMMA nm(Z) RP(Y). { - spanSet(&A,&X,&Y); /*A-overwrites-X*/ - A.pExpr = sqlite3ExprAlloc(pParse->db, TK_RAISE, &Z, 1); - if( A.pExpr ) { - A.pExpr->affinity = (char)T; +expr(A) ::= RAISE LP raisetype(T) COMMA nm(Z) RP. { + A = sqlite3ExprAlloc(pParse->db, TK_RAISE, &Z, 1); + if( A ) { + A->affinity = (char)T; } } %endif !SQLITE_OMIT_TRIGGER @@ -1485,16 +1417,16 @@ cmd ::= DROP TRIGGER ifexists(NOERR) fullname(X). { //////////////////////// ATTACH DATABASE file AS name ///////////////////////// %ifndef SQLITE_OMIT_ATTACH cmd ::= ATTACH database_kw_opt expr(F) AS expr(D) key_opt(K). { - sqlite3Attach(pParse, F.pExpr, D.pExpr, K); + sqlite3Attach(pParse, F, D, K); } cmd ::= DETACH database_kw_opt expr(D). { - sqlite3Detach(pParse, D.pExpr); + sqlite3Detach(pParse, D); } %type key_opt {Expr*} %destructor key_opt {sqlite3ExprDelete(pParse->db, $$);} key_opt(A) ::= . { A = 0; } -key_opt(A) ::= KEY expr(X). { A = X.pExpr; } +key_opt(A) ::= KEY expr(X). { A = X; } database_kw_opt ::= DATABASE. database_kw_opt ::= . diff --git a/src/sqliteInt.h b/src/sqliteInt.h index b0c4711b03..93099ca1d3 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1063,7 +1063,6 @@ typedef struct Db Db; typedef struct Schema Schema; typedef struct Expr Expr; typedef struct ExprList ExprList; -typedef struct ExprSpan ExprSpan; typedef struct FKey FKey; typedef struct FuncDestructor FuncDestructor; typedef struct FuncDef FuncDef; @@ -2504,17 +2503,6 @@ struct ExprList { } a[1]; /* One slot for each expression in the list */ }; -/* -** An instance of this structure is used by the parser to record both -** the parse tree for an expression and the span of input text for an -** expression. -*/ -struct ExprSpan { - Expr *pExpr; /* The expression parse tree */ - const char *zStart; /* First character of input text */ - const char *zEnd; /* One character past the end of input text */ -}; - /* ** An instance of this structure can hold a simple list of identifiers, ** such as the list "a,b,c" in the following statements: @@ -3663,7 +3651,7 @@ ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*); void sqlite3ExprListSetSortOrder(ExprList*,int); void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int); -void sqlite3ExprListSetSpan(Parse*,ExprList*,ExprSpan*); +void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*); void sqlite3ExprListDelete(sqlite3*, ExprList*); u32 sqlite3ExprListFlags(const ExprList*); int sqlite3Init(sqlite3*, char**); @@ -3693,7 +3681,7 @@ void sqlite3AddColumn(Parse*,Token*,Token*); void sqlite3AddNotNull(Parse*, int); void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int); void sqlite3AddCheckConstraint(Parse*, Expr*); -void sqlite3AddDefaultValue(Parse*,ExprSpan*); +void sqlite3AddDefaultValue(Parse*,Expr*,const char*,const char*); void sqlite3AddCollateType(Parse*, Token*); void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*); int sqlite3ParseUri(const char*,const char*,unsigned int*, From ec64c6cfd2ecdc4d14032f8608833e2a0e11a1d2 Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 24 Dec 2017 14:14:21 +0000 Subject: [PATCH 03/40] Improved parser tracing output. FossilOrigin-Name: c4951833c2b976223c2393d82fd2606068c71cd19612ca9df4e26debab980e32 --- manifest | 15 ++++++--------- manifest.uuid | 2 +- tool/lempar.c | 36 +++++++++++++++++++++++++----------- 3 files changed, 32 insertions(+), 21 deletions(-) diff --git a/manifest b/manifest index 3cc840deb1..8e6b14968f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sthe\sExprSpan\sobject.\sInstead,\skeep\strack\sof\sthe\stest\sof\ssubphrases\sin\nthe\sparse\susing\sthe\s"scanpt"\snon-terminal. -D 2017-12-24T00:18:47.740 +C Improved\sparser\stracing\soutput. +D 2017-12-24T14:14:21.392 F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69 @@ -1609,7 +1609,7 @@ F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f F tool/lemon.c e6056373044d55296d21f81467dba7632bbb81dc49af072b3f0e76338771497e -F tool/lempar.c 967ebf585cd09b11b89d255d213865109a9c4ff075680d22580a2826de288c89 +F tool/lempar.c a427c2375df118fa52e69174ffbbf9e26878096f0a109df6b77062d6032afe18 F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca @@ -1687,10 +1687,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 07c773148d8db185fa54991df09298b64f4fef28879e6c9395759265e8183977 -R 1cdf837f203b6ea58ba0352a2b260bed -T *branch * span-refactor -T *sym-span-refactor * -T -sym-trunk * +P 3eab7bdc44e0878b83dc86f27058a40c2ffafeacadc566f03693f6dc7e40a504 +R 35c7a29b183ac93da1a9be4e6a82bb63 U drh -Z 03a6ffebedfd10412e429ce17606ec66 +Z 121e81b010860ccafac66f3ea34cc3c9 diff --git a/manifest.uuid b/manifest.uuid index 512e591247..519f079775 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3eab7bdc44e0878b83dc86f27058a40c2ffafeacadc566f03693f6dc7e40a504 \ No newline at end of file +c4951833c2b976223c2393d82fd2606068c71cd19612ca9df4e26debab980e32 \ No newline at end of file diff --git a/tool/lempar.c b/tool/lempar.c index da81ddd4bc..89c1c80f70 100644 --- a/tool/lempar.c +++ b/tool/lempar.c @@ -578,20 +578,21 @@ static void yyStackOverflow(yyParser *yypParser){ ** Print tracing information for a SHIFT action */ #ifndef NDEBUG -static void yyTraceShift(yyParser *yypParser, int yyNewState){ +static void yyTraceShift(yyParser *yypParser, int yyNewState, const char *zTag){ if( yyTraceFILE ){ if( yyNewStateyytos->major], + fprintf(yyTraceFILE,"%s%s '%s', go to state %d\n", + yyTracePrompt, zTag, yyTokenName[yypParser->yytos->major], yyNewState); }else{ - fprintf(yyTraceFILE,"%sShift '%s'\n", - yyTracePrompt,yyTokenName[yypParser->yytos->major]); + fprintf(yyTraceFILE,"%s%s '%s', pending reduce %d\n", + yyTracePrompt, zTag, yyTokenName[yypParser->yytos->major], + yyNewState - YY_MIN_REDUCE); } } } #else -# define yyTraceShift(X,Y) +# define yyTraceShift(X,Y,Z) #endif /* @@ -633,7 +634,7 @@ static void yy_shift( yytos->stateno = (YYACTIONTYPE)yyNewState; yytos->major = (YYCODETYPE)yyMajor; yytos->minor.yy0 = yyMinor; - yyTraceShift(yypParser, yyNewState); + yyTraceShift(yypParser, yyNewState, "Shift"); } /* The following table contains information about every rule that @@ -673,8 +674,14 @@ static void yy_reduce( #ifndef NDEBUG if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ yysize = yyRuleInfo[yyruleno].nrhs; - fprintf(yyTraceFILE, "%sReduce [%s], go to state %d.\n", yyTracePrompt, - yyRuleName[yyruleno], yymsp[yysize].stateno); + if( yysize ){ + fprintf(yyTraceFILE, "%sReduce %d [%s], go to state %d.\n", + yyTracePrompt, + yyruleno, yyRuleName[yyruleno], yymsp[yysize].stateno); + }else{ + fprintf(yyTraceFILE, "%sReduce %d [%s].\n", + yyTracePrompt, yyruleno, yyRuleName[yyruleno]); + } } #endif /* NDEBUG */ @@ -737,7 +744,7 @@ static void yy_reduce( yypParser->yytos = yymsp; yymsp->stateno = (YYACTIONTYPE)yyact; yymsp->major = (YYCODETYPE)yygoto; - yyTraceShift(yypParser, yyact); + yyTraceShift(yypParser, yyact, "... then shift"); } } @@ -848,7 +855,14 @@ void Parse( #ifndef NDEBUG if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sInput '%s'\n",yyTracePrompt,yyTokenName[yymajor]); + int stateno = yypParser->yytos->stateno; + if( stateno < YY_MIN_REDUCE ){ + fprintf(yyTraceFILE,"%sInput '%s' in state %d\n", + yyTracePrompt,yyTokenName[yymajor],stateno); + }else{ + fprintf(yyTraceFILE,"%sInput '%s' with pending reduce %d\n", + yyTracePrompt,yyTokenName[yymajor],stateno-YY_MIN_REDUCE); + } } #endif From d3f5d6110b21b04acbe860f6a6d6242f6ed9fab4 Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 24 Dec 2017 17:01:54 +0000 Subject: [PATCH 04/40] Grammar changes: the sclp non-terminal should always be followed by a scanpt. FossilOrigin-Name: 74a0181fc016fb0b7934188cfcc2ec26c689f0d33cc42453875f4392b7240d3a --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/parse.y | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 8e6b14968f..bc08e70fd1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\sparser\stracing\soutput. -D 2017-12-24T14:14:21.392 +C Grammar\schanges:\s\sthe\ssclp\snon-terminal\sshould\salways\sbe\sfollowed\sby\sa\sscanpt. +D 2017-12-24T17:01:54.828 F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69 @@ -467,7 +467,7 @@ F src/os_win.c 0a4afa35cc8e812000df3ea2f64b476131b39e29e75d8007d0504726e4761de4 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c 07cf850241667874fcce9d7d924c814305e499b26c804322e2261247b5921903 F src/pager.h 581698f2177e8bd4008fe4760898ce20b6133d1df22139b9101b5155f900df7a -F src/parse.y 1e29222ba074fea8d84438098e00812071d4cfd34c8620f34accab7cd523a276 +F src/parse.y 2b0653fd44534d941ff5289f372fedfc213e78c4698e28334d073cf4cfd146f2 F src/pcache.c 7ae91a4557a43d77d449accbfdc68846e6516f8e2eda46e8bbe4536fb669b201 F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170 F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880 @@ -1687,7 +1687,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 3eab7bdc44e0878b83dc86f27058a40c2ffafeacadc566f03693f6dc7e40a504 -R 35c7a29b183ac93da1a9be4e6a82bb63 +P c4951833c2b976223c2393d82fd2606068c71cd19612ca9df4e26debab980e32 +R bc2b2a8774f331c7775262d09dd60c38 U drh -Z 121e81b010860ccafac66f3ea34cc3c9 +Z a70d3a97910b6c52f1408e750f661b18 diff --git a/manifest.uuid b/manifest.uuid index 519f079775..b5e2fe7f2b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c4951833c2b976223c2393d82fd2606068c71cd19612ca9df4e26debab980e32 \ No newline at end of file +74a0181fc016fb0b7934188cfcc2ec26c689f0d33cc42453875f4392b7240d3a \ No newline at end of file diff --git a/src/parse.y b/src/parse.y index d59426409c..fe2251db4b 100644 --- a/src/parse.y +++ b/src/parse.y @@ -575,7 +575,7 @@ selcollist(A) ::= sclp(A) scanpt(B) expr(X) scanpt(Z) as(Y). { if( Y.n>0 ) sqlite3ExprListSetName(pParse, A, &Y, 1); sqlite3ExprListSetSpan(pParse,A,B,Z); } -selcollist(A) ::= sclp(A) STAR. { +selcollist(A) ::= sclp(A) scanpt STAR. { Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0); A = sqlite3ExprListAppend(pParse, A, p); } From e58f74f680f97f382db35215b22203b3b10abb30 Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 24 Dec 2017 17:06:41 +0000 Subject: [PATCH 05/40] Improved parser tracing output. FossilOrigin-Name: 25be5750545b7b0ed9e1a1baca31611b354519688f875aa1590b21bb6ff42f1b --- manifest | 16 ++++++++++------ manifest.uuid | 2 +- tool/lempar.c | 36 +++++++++++++++++++++++++----------- 3 files changed, 36 insertions(+), 18 deletions(-) diff --git a/manifest b/manifest index f187cc0290..07c293333d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Simplification\sto\sthe\serror\shandling\slogic\sin\sthe\sextension\sloader. -D 2017-12-23T14:39:36.160 +C Improved\sparser\stracing\soutput. +D 2017-12-24T17:06:41.289 F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69 @@ -1609,7 +1609,7 @@ F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f F tool/lemon.c e6056373044d55296d21f81467dba7632bbb81dc49af072b3f0e76338771497e -F tool/lempar.c 967ebf585cd09b11b89d255d213865109a9c4ff075680d22580a2826de288c89 +F tool/lempar.c a427c2375df118fa52e69174ffbbf9e26878096f0a109df6b77062d6032afe18 F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca @@ -1687,7 +1687,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 05fee1a21ea398f1e4d6f1cf361657eff25ed6cd8f85ab398262dcfd30da57e9 -R 7fbfe3e61eca395fa5baf5f121a4d2ad +P 07c773148d8db185fa54991df09298b64f4fef28879e6c9395759265e8183977 +Q +c4951833c2b976223c2393d82fd2606068c71cd19612ca9df4e26debab980e32 +R 3f4f31cde41f94adafa8015552d0561b +T *branch * lemon-improvements +T *sym-lemon-improvements * +T -sym-trunk * U drh -Z d82d9c01768cefc5beb206b92e1398bf +Z 3f6d9f274761457d9d7dcc3ca6c0270c diff --git a/manifest.uuid b/manifest.uuid index 8454418cd5..bdf982cb88 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -07c773148d8db185fa54991df09298b64f4fef28879e6c9395759265e8183977 \ No newline at end of file +25be5750545b7b0ed9e1a1baca31611b354519688f875aa1590b21bb6ff42f1b \ No newline at end of file diff --git a/tool/lempar.c b/tool/lempar.c index da81ddd4bc..89c1c80f70 100644 --- a/tool/lempar.c +++ b/tool/lempar.c @@ -578,20 +578,21 @@ static void yyStackOverflow(yyParser *yypParser){ ** Print tracing information for a SHIFT action */ #ifndef NDEBUG -static void yyTraceShift(yyParser *yypParser, int yyNewState){ +static void yyTraceShift(yyParser *yypParser, int yyNewState, const char *zTag){ if( yyTraceFILE ){ if( yyNewStateyytos->major], + fprintf(yyTraceFILE,"%s%s '%s', go to state %d\n", + yyTracePrompt, zTag, yyTokenName[yypParser->yytos->major], yyNewState); }else{ - fprintf(yyTraceFILE,"%sShift '%s'\n", - yyTracePrompt,yyTokenName[yypParser->yytos->major]); + fprintf(yyTraceFILE,"%s%s '%s', pending reduce %d\n", + yyTracePrompt, zTag, yyTokenName[yypParser->yytos->major], + yyNewState - YY_MIN_REDUCE); } } } #else -# define yyTraceShift(X,Y) +# define yyTraceShift(X,Y,Z) #endif /* @@ -633,7 +634,7 @@ static void yy_shift( yytos->stateno = (YYACTIONTYPE)yyNewState; yytos->major = (YYCODETYPE)yyMajor; yytos->minor.yy0 = yyMinor; - yyTraceShift(yypParser, yyNewState); + yyTraceShift(yypParser, yyNewState, "Shift"); } /* The following table contains information about every rule that @@ -673,8 +674,14 @@ static void yy_reduce( #ifndef NDEBUG if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ yysize = yyRuleInfo[yyruleno].nrhs; - fprintf(yyTraceFILE, "%sReduce [%s], go to state %d.\n", yyTracePrompt, - yyRuleName[yyruleno], yymsp[yysize].stateno); + if( yysize ){ + fprintf(yyTraceFILE, "%sReduce %d [%s], go to state %d.\n", + yyTracePrompt, + yyruleno, yyRuleName[yyruleno], yymsp[yysize].stateno); + }else{ + fprintf(yyTraceFILE, "%sReduce %d [%s].\n", + yyTracePrompt, yyruleno, yyRuleName[yyruleno]); + } } #endif /* NDEBUG */ @@ -737,7 +744,7 @@ static void yy_reduce( yypParser->yytos = yymsp; yymsp->stateno = (YYACTIONTYPE)yyact; yymsp->major = (YYCODETYPE)yygoto; - yyTraceShift(yypParser, yyact); + yyTraceShift(yypParser, yyact, "... then shift"); } } @@ -848,7 +855,14 @@ void Parse( #ifndef NDEBUG if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sInput '%s'\n",yyTracePrompt,yyTokenName[yymajor]); + int stateno = yypParser->yytos->stateno; + if( stateno < YY_MIN_REDUCE ){ + fprintf(yyTraceFILE,"%sInput '%s' in state %d\n", + yyTracePrompt,yyTokenName[yymajor],stateno); + }else{ + fprintf(yyTraceFILE,"%sInput '%s' with pending reduce %d\n", + yyTracePrompt,yyTokenName[yymajor],stateno-YY_MIN_REDUCE); + } } #endif From 512795dfeae9dd816eefda3eee3222aedcd6d2b5 Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 24 Dec 2017 18:56:28 +0000 Subject: [PATCH 06/40] Fix a NULL pointer dereference after a syntax error that can occur as a result of check-in [6b2ff26c25bb9da3] yesterday. This problem was discovered by the OSSFuzz. FossilOrigin-Name: d49afb8f9804e96662d1e3cadc4c6643908706d848a53d5ed019919c98f2ccba --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/build.c | 1 + test/colname.test | 10 ++++++++++ 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index f187cc0290..1c622c1102 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Simplification\sto\sthe\serror\shandling\slogic\sin\sthe\sextension\sloader. -D 2017-12-23T14:39:36.160 +C Fix\sa\sNULL\spointer\sdereference\safter\sa\ssyntax\serror\sthat\scan\soccur\sas\sa\nresult\sof\scheck-in\s[6b2ff26c25bb9da3]\syesterday.\s\sThis\sproblem\swas\ndiscovered\sby\sthe\sOSSFuzz. +D 2017-12-24T18:56:28.786 F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69 @@ -423,7 +423,7 @@ F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca F src/btree.c b83a6b03f160528020bb965f0c3a40af5286cd4923c3870fd218177f03a120a7 F src/btree.h 32ef5d3f25dc70ef1ee9cecf84a023c21378f06a57cd701d2e866e141b150f09 F src/btreeInt.h 55b702efce17e5d1941865464227d3802cfc9c7c832fac81d4c94dced47a71fc -F src/build.c ed567f088edbc305dad33a6b14e08f8216a3860f6bad1d180450d5a5414bf346 +F src/build.c ab5bdf955c85bcd56acbf310a48bbd50b4b92079efa40d997a7e4246f8e03741 F src/callback.c fe677cb5f5abb02f7a772a62a98c2f516426081df68856e8f2d5f950929b966a F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c ff1be3eed7bdd75aaca61ca8dc848f7c9f850ef2fb9cb56f2734e922a098f9c0 @@ -682,7 +682,7 @@ F test/collate9.test 3adcc799229545940df2f25308dd1ad65869145a F test/collateA.test b8218ab90d1fa5c59dcf156efabb1b2599c580d6 F test/collateB.test 1e68906951b846570f29f20102ed91d29e634854ee47454d725f2151ecac0b95 F test/colmeta.test 2c765ea61ee37bc43bbe6d6047f89004e6508eb1 -F test/colname.test a7ecb8f1d6d8b30a6cf8fa84a2cd6f6e91cad8296376fabe485cf93cd5eb6229 +F test/colname.test 36da785927822ecd0de979459e27e9be63f458dd08d3edde41af3af37a337d58 F test/conflict.test 029faa2d81a0d1cafb5f88614beb663d972c01db F test/conflict2.test bb0b94cf7196c64a3cbd815c66d3ee98c2fecd9c F test/conflict3.test a83db76a6c3503b2fa057c7bfb08c318d8a422202d8bc5b86226e078e5b49ff9 @@ -1687,7 +1687,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 05fee1a21ea398f1e4d6f1cf361657eff25ed6cd8f85ab398262dcfd30da57e9 -R 7fbfe3e61eca395fa5baf5f121a4d2ad +P 07c773148d8db185fa54991df09298b64f4fef28879e6c9395759265e8183977 +R 2e4222d820aa06549d33319e9e33c627 U drh -Z d82d9c01768cefc5beb206b92e1398bf +Z 67298e45eb2d4d992f0cdf5678deffdf diff --git a/manifest.uuid b/manifest.uuid index 8454418cd5..d58d2c0dd5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -07c773148d8db185fa54991df09298b64f4fef28879e6c9395759265e8183977 \ No newline at end of file +d49afb8f9804e96662d1e3cadc4c6643908706d848a53d5ed019919c98f2ccba \ No newline at end of file diff --git a/src/build.c b/src/build.c index 01d8972415..390dae5d3b 100644 --- a/src/build.c +++ b/src/build.c @@ -1965,6 +1965,7 @@ void sqlite3EndTable( pParse->nTab = 2; addrTop = sqlite3VdbeCurrentAddr(v) + 1; sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop); + if( pParse->nErr ) return; pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect); if( pSelTab==0 ) return; assert( p->aCol==0 ); diff --git a/test/colname.test b/test/colname.test index 5a40286773..cacf91e4e3 100644 --- a/test/colname.test +++ b/test/colname.test @@ -398,6 +398,16 @@ do_execsql_test colname-9.320 { SELECT name FROM pragma_table_info('t2'); } {Bbb} +# Issue detected by clusterfuzz on 2017-12-24 (Christmas Eve) +# caused by check-in https://sqlite.org/src/info/6b2ff26c25 +# +# Prior to being fixed, the following CREATE TABLE was dereferencing +# a NULL pointer and segfaulting. +# +do_catchsql_test colname-9.400 { + CREATE TABLE t4 AS SELECT #0; +} {1 {near "#0": syntax error}} + # Make sure the quotation marks get removed from the column names # when constructing a new table from an aggregate SELECT. From 5c8241b8750ce919b4151761a1d721af58bfbf7b Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 24 Dec 2017 23:38:10 +0000 Subject: [PATCH 07/40] In the LEMON-generated parser, rearrange the meanings of integer action codes so that reduce actions occur last. This means that the most common case (reduce actions) can be recognized with a single comparison operation, thus speeding up the main parser loop, slightly. FossilOrigin-Name: 7bfe7a360261ac7227840db49487c2f0fe338a2f1b868fcaada1e04a8d2b8f7a --- manifest | 18 ++++----- manifest.uuid | 2 +- tool/lemon.c | 100 ++++++++++++++++++++++++++++++++------------------ tool/lempar.c | 16 ++++---- 4 files changed, 81 insertions(+), 55 deletions(-) diff --git a/manifest b/manifest index 07c293333d..d8e37c9644 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\sparser\stracing\soutput. -D 2017-12-24T17:06:41.289 +C In\sthe\sLEMON-generated\sparser,\srearrange\sthe\smeanings\sof\sinteger\saction\scodes\nso\sthat\sreduce\sactions\soccur\slast.\s\sThis\smeans\sthat\sthe\smost\scommon\scase\n(reduce\sactions)\scan\sbe\srecognized\swith\sa\ssingle\scomparison\soperation,\sthus\nspeeding\sup\sthe\smain\sparser\sloop,\sslightly. +D 2017-12-24T23:38:10.370 F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69 @@ -1608,8 +1608,8 @@ F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4 F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f -F tool/lemon.c e6056373044d55296d21f81467dba7632bbb81dc49af072b3f0e76338771497e -F tool/lempar.c a427c2375df118fa52e69174ffbbf9e26878096f0a109df6b77062d6032afe18 +F tool/lemon.c 7c6919d98e459c0f8a3673be64b03425553733dba01c12939b2fadc30e4e2804 +F tool/lempar.c c8dd4dcf0bca9d7c27c62f7df12882c30db749cd9bb83d6f71796b9fabb94f6c F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca @@ -1687,11 +1687,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 07c773148d8db185fa54991df09298b64f4fef28879e6c9395759265e8183977 -Q +c4951833c2b976223c2393d82fd2606068c71cd19612ca9df4e26debab980e32 -R 3f4f31cde41f94adafa8015552d0561b -T *branch * lemon-improvements -T *sym-lemon-improvements * -T -sym-trunk * +P 25be5750545b7b0ed9e1a1baca31611b354519688f875aa1590b21bb6ff42f1b +R 02413a9b8686f5cb855fd9a72c28a347 U drh -Z 3f6d9f274761457d9d7dcc3ca6c0270c +Z a4798d5b361261f3f5c39967bad11abf diff --git a/manifest.uuid b/manifest.uuid index bdf982cb88..d4db86c744 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -25be5750545b7b0ed9e1a1baca31611b354519688f875aa1590b21bb6ff42f1b \ No newline at end of file +7bfe7a360261ac7227840db49487c2f0fe338a2f1b868fcaada1e04a8d2b8f7a \ No newline at end of file diff --git a/tool/lemon.c b/tool/lemon.c index acc5450c99..33ef43d1b1 100644 --- a/tool/lemon.c +++ b/tool/lemon.c @@ -384,6 +384,12 @@ struct lemon { int nrule; /* Number of rules */ int nsymbol; /* Number of terminal and nonterminal symbols */ int nterminal; /* Number of terminal symbols */ + int minShiftReduce; /* Minimum shift-reduce action value */ + int errAction; /* Error action value */ + int accAction; /* Accept action value */ + int noAction; /* No-op action value */ + int minReduce; /* Minimum reduce action */ + int maxAction; /* Maximum action value of any kind */ struct symbol **symbols; /* Sorted array of pointers to symbols */ int errorcnt; /* Number of errors */ struct symbol *errsym; /* The error symbol */ @@ -3020,6 +3026,27 @@ PRIVATE FILE *file_open( return fp; } +/* Print the text of a rule +*/ +void rule_print(FILE *out, struct rule *rp){ + int i, j; + fprintf(out, "%s",rp->lhs->name); + /* if( rp->lhsalias ) fprintf(out,"(%s)",rp->lhsalias); */ + fprintf(out," ::="); + for(i=0; inrhs; i++){ + struct symbol *sp = rp->rhs[i]; + if( sp->type==MULTITERMINAL ){ + fprintf(out," %s", sp->subsym[0]->name); + for(j=1; jnsubsym; j++){ + fprintf(out,"|%s", sp->subsym[j]->name); + } + }else{ + fprintf(out," %s", sp->name); + } + /* if( rp->rhsalias[i] ) fprintf(out,"(%s)",rp->rhsalias[i]); */ + } +} + /* Duplicate the input file without comments and without actions ** on rules */ void Reprint(struct lemon *lemp) @@ -3047,21 +3074,7 @@ void Reprint(struct lemon *lemp) printf("\n"); } for(rp=lemp->rule; rp; rp=rp->next){ - printf("%s",rp->lhs->name); - /* if( rp->lhsalias ) printf("(%s)",rp->lhsalias); */ - printf(" ::="); - for(i=0; inrhs; i++){ - sp = rp->rhs[i]; - if( sp->type==MULTITERMINAL ){ - printf(" %s", sp->subsym[0]->name); - for(j=1; jnsubsym; j++){ - printf("|%s", sp->subsym[j]->name); - } - }else{ - printf(" %s", sp->name); - } - /* if( rp->rhsalias[i] ) printf("(%s)",rp->rhsalias[i]); */ - } + rule_print(stdout, rp); printf("."); if( rp->precsym ) printf(" [%s]",rp->precsym->name); /* if( rp->code ) printf("\n %s",rp->code); */ @@ -3321,16 +3334,19 @@ PRIVATE int compute_action(struct lemon *lemp, struct action *ap) switch( ap->type ){ case SHIFT: act = ap->x.stp->statenum; break; case SHIFTREDUCE: { - act = ap->x.rp->iRule + lemp->nstate; /* Since a SHIFT is inherient after a prior REDUCE, convert any ** SHIFTREDUCE action with a nonterminal on the LHS into a simple ** REDUCE action: */ - if( ap->sp->index>=lemp->nterminal ) act += lemp->nrule; + if( ap->sp->index>=lemp->nterminal ){ + act = lemp->minReduce + ap->x.rp->iRule; + }else{ + act = lemp->minShiftReduce + ap->x.rp->iRule; + } break; } - case REDUCE: act = ap->x.rp->iRule + lemp->nstate+lemp->nrule; break; - case ERROR: act = lemp->nstate + lemp->nrule*2; break; - case ACCEPT: act = lemp->nstate + lemp->nrule*2 + 1; break; + case REDUCE: act = lemp->minReduce + ap->x.rp->iRule; break; + case ERROR: act = lemp->errAction; break; + case ACCEPT: act = lemp->accAction; break; default: act = -1; break; } return act; @@ -4038,6 +4054,13 @@ void ReportTable( int mnNtOfst, mxNtOfst; struct axset *ax; + lemp->minShiftReduce = lemp->nstate; + lemp->errAction = lemp->minShiftReduce + lemp->nrule; + lemp->accAction = lemp->errAction + 1; + lemp->noAction = lemp->accAction + 1; + lemp->minReduce = lemp->noAction + 1; + lemp->maxAction = lemp->minReduce + lemp->nrule; + in = tplt_open(lemp); if( in==0 ) return; out = file_open(lemp,".c","wb"); @@ -4076,7 +4099,7 @@ void ReportTable( minimum_size_type(0, lemp->nsymbol+1, &szCodeType)); lineno++; fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol+1); lineno++; fprintf(out,"#define YYACTIONTYPE %s\n", - minimum_size_type(0,lemp->nstate+lemp->nrule*2+5,&szActionType)); lineno++; + minimum_size_type(0,lemp->maxAction,&szActionType)); lineno++; if( lemp->wildcard ){ fprintf(out,"#define YYWILDCARD %d\n", lemp->wildcard->index); lineno++; @@ -4201,15 +4224,16 @@ void ReportTable( fprintf(out,"#define YYNSTATE %d\n",lemp->nxstate); lineno++; fprintf(out,"#define YYNRULE %d\n",lemp->nrule); lineno++; fprintf(out,"#define YY_MAX_SHIFT %d\n",lemp->nxstate-1); lineno++; - fprintf(out,"#define YY_MIN_SHIFTREDUCE %d\n",lemp->nstate); lineno++; - i = lemp->nstate + lemp->nrule; + i = lemp->minShiftReduce; + fprintf(out,"#define YY_MIN_SHIFTREDUCE %d\n",i); lineno++; + i += lemp->nrule; fprintf(out,"#define YY_MAX_SHIFTREDUCE %d\n", i-1); lineno++; - fprintf(out,"#define YY_MIN_REDUCE %d\n", i); lineno++; - i = lemp->nstate + lemp->nrule*2; + fprintf(out,"#define YY_ERROR_ACTION %d\n", lemp->errAction); lineno++; + fprintf(out,"#define YY_ACCEPT_ACTION %d\n", lemp->accAction); lineno++; + fprintf(out,"#define YY_NO_ACTION %d\n", lemp->noAction); lineno++; + 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++; - fprintf(out,"#define YY_ERROR_ACTION %d\n", i); lineno++; - fprintf(out,"#define YY_ACCEPT_ACTION %d\n", i+1); lineno++; - fprintf(out,"#define YY_NO_ACTION %d\n", i+2); lineno++; tplt_xfer(lemp->name,in,out,&lineno); /* Now output the action table and its associates: @@ -4231,7 +4255,7 @@ void ReportTable( fprintf(out,"static const YYACTIONTYPE yy_action[] = {\n"); lineno++; for(i=j=0; instate + lemp->nrule + 2; + if( action<0 ) action = lemp->noAction; if( j==0 ) fprintf(out," /* %5d */ ", i); fprintf(out, " %4d,", action); if( j==9 || i==n-1 ){ @@ -4320,7 +4344,11 @@ void ReportTable( for(i=j=0; isorted[i]; if( j==0 ) fprintf(out," /* %5d */ ", i); - fprintf(out, " %4d,", stp->iDfltReduce+lemp->nstate+lemp->nrule); + if( stp->iDfltReduce<0 ){ + fprintf(out, " %4d,", lemp->errAction); + }else{ + fprintf(out, " %4d,", stp->iDfltReduce + lemp->minReduce); + } if( j==9 || i==n-1 ){ fprintf(out, "\n"); lineno++; j = 0; @@ -4401,7 +4429,7 @@ void ReportTable( if( sp==0 || sp->type==TERMINAL || sp->index<=0 || sp->destructor!=0 ) continue; if( once ){ - fprintf(out, " /* Default NON-TERMINAL Destructor */\n"); lineno++; + fprintf(out, " /* Default NON-TERMINAL Destructor */\n");lineno++; once = 0; } fprintf(out," case %d: /* %s */\n", sp->index, sp->name); lineno++; @@ -4444,8 +4472,10 @@ void ReportTable( ** Note: This code depends on the fact that rules are number ** sequentually beginning with 0. */ - for(rp=lemp->rule; rp; rp=rp->next){ - fprintf(out," { %d, %d },\n",rp->lhs->index,-rp->nrhs); lineno++; + for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){ + fprintf(out," { %4d, %4d }, /* (%d) ",rp->lhs->index,-rp->nrhs,i); + rule_print(out, rp); + fprintf(out," */\n"); lineno++; } tplt_xfer(lemp->name,in,out,&lineno); @@ -4711,7 +4741,7 @@ void ResortStates(struct lemon *lemp) for(i=0; instate; i++){ stp = lemp->sorted[i]; stp->nTknAct = stp->nNtAct = 0; - stp->iDfltReduce = lemp->nrule; /* Init dflt action to "syntax error" */ + stp->iDfltReduce = -1; /* Init dflt action to "syntax error" */ stp->iTknOfst = NO_OFFSET; stp->iNtOfst = NO_OFFSET; for(ap=stp->ap; ap; ap=ap->next){ @@ -4723,7 +4753,7 @@ void ResortStates(struct lemon *lemp) stp->nNtAct++; }else{ assert( stp->autoReduce==0 || stp->pDfltReduce==ap->x.rp ); - stp->iDfltReduce = iAction - lemp->nstate - lemp->nrule; + stp->iDfltReduce = iAction; } } } diff --git a/tool/lempar.c b/tool/lempar.c index 89c1c80f70..7d25175ca7 100644 --- a/tool/lempar.c +++ b/tool/lempar.c @@ -75,11 +75,11 @@ ** YY_MAX_SHIFT Maximum value for shift actions ** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions ** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions -** YY_MIN_REDUCE Minimum value for reduce actions -** YY_MAX_REDUCE Maximum value for reduce actions ** YY_ERROR_ACTION The yy_action[] code for syntax error ** YY_ACCEPT_ACTION The yy_action[] code for accept ** 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 */ #ifndef INTERFACE # define INTERFACE 1 @@ -115,9 +115,6 @@ ** N between YY_MIN_SHIFTREDUCE Shift to an arbitrary state then ** and YY_MAX_SHIFTREDUCE reduce by rule N-YY_MIN_SHIFTREDUCE. ** -** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE -** and YY_MAX_REDUCE -** ** N == YY_ERROR_ACTION A syntax error has occurred. ** ** N == YY_ACCEPT_ACTION The parser accepts its input. @@ -125,6 +122,9 @@ ** N == YY_NO_ACTION No such action. Denotes unused ** slots in the yy_action[] table. ** +** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE +** and YY_MAX_REDUCE +** ** The action table is constructed as a single large table named yy_action[]. ** Given state S and lookahead X, the action is computed as either: ** @@ -868,14 +868,14 @@ void Parse( do{ yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor); - if( yyact <= YY_MAX_SHIFTREDUCE ){ + if( yyact >= YY_MIN_REDUCE ){ + yy_reduce(yypParser,yyact-YY_MIN_REDUCE,yymajor,yyminor); + }else if( yyact <= YY_MAX_SHIFTREDUCE ){ yy_shift(yypParser,yyact,yymajor,yyminor); #ifndef YYNOERRORRECOVERY yypParser->yyerrcnt--; #endif yymajor = YYNOCODE; - }else if( yyact <= YY_MAX_REDUCE ){ - yy_reduce(yypParser,yyact-YY_MIN_REDUCE,yymajor,yyminor); }else{ assert( yyact == YY_ERROR_ACTION ); yyminorunion.yy0 = yyminor; From ef53a9f0af73a66d8844fb2b58c669213677530e Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 25 Dec 2017 00:10:05 +0000 Subject: [PATCH 08/40] In the LEMON-generated parser, avoid unnecessary tests for the acceptance state. FossilOrigin-Name: fdbb35c54f2b6cb65d04ac295f207ff3e69360e0558348c77eb5e62691807046 --- manifest | 12 ++++++------ manifest.uuid | 2 +- tool/lempar.c | 21 ++++++++++----------- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/manifest b/manifest index d8e37c9644..f8d8364cbb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\sLEMON-generated\sparser,\srearrange\sthe\smeanings\sof\sinteger\saction\scodes\nso\sthat\sreduce\sactions\soccur\slast.\s\sThis\smeans\sthat\sthe\smost\scommon\scase\n(reduce\sactions)\scan\sbe\srecognized\swith\sa\ssingle\scomparison\soperation,\sthus\nspeeding\sup\sthe\smain\sparser\sloop,\sslightly. -D 2017-12-24T23:38:10.370 +C In\sthe\sLEMON-generated\sparser,\savoid\sunnecessary\stests\sfor\sthe\sacceptance\nstate. +D 2017-12-25T00:10:05.418 F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69 @@ -1609,7 +1609,7 @@ F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f F tool/lemon.c 7c6919d98e459c0f8a3673be64b03425553733dba01c12939b2fadc30e4e2804 -F tool/lempar.c c8dd4dcf0bca9d7c27c62f7df12882c30db749cd9bb83d6f71796b9fabb94f6c +F tool/lempar.c 8062f219b4ce349853cb3ab3ebd3ab44466604235347457d703a9f4252e76dd5 F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca @@ -1687,7 +1687,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 25be5750545b7b0ed9e1a1baca31611b354519688f875aa1590b21bb6ff42f1b -R 02413a9b8686f5cb855fd9a72c28a347 +P 7bfe7a360261ac7227840db49487c2f0fe338a2f1b868fcaada1e04a8d2b8f7a +R 904d9f58d13471f5c0ad3064ead9b812 U drh -Z a4798d5b361261f3f5c39967bad11abf +Z c00f50853c78fa733a13b33ab92ee708 diff --git a/manifest.uuid b/manifest.uuid index d4db86c744..e026b0ddc4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7bfe7a360261ac7227840db49487c2f0fe338a2f1b868fcaada1e04a8d2b8f7a \ No newline at end of file +fdbb35c54f2b6cb65d04ac295f207ff3e69360e0558348c77eb5e62691807046 \ No newline at end of file diff --git a/tool/lempar.c b/tool/lempar.c index 7d25175ca7..6c6ca77dde 100644 --- a/tool/lempar.c +++ b/tool/lempar.c @@ -472,7 +472,7 @@ static unsigned int yy_find_shift_action( int i; int stateno = pParser->yytos->stateno; - if( stateno>=YY_MIN_REDUCE ) return stateno; + if( stateno>YY_MAX_SHIFT ) return stateno; assert( stateno <= YY_SHIFT_COUNT ); do{ i = yy_shift_ofst[stateno]; @@ -736,16 +736,11 @@ static void yy_reduce( /* It is not possible for a REDUCE to be followed by an error */ assert( yyact!=YY_ERROR_ACTION ); - if( yyact==YY_ACCEPT_ACTION ){ - yypParser->yytos += yysize; - yy_accept(yypParser); - }else{ - yymsp += yysize+1; - yypParser->yytos = yymsp; - yymsp->stateno = (YYACTIONTYPE)yyact; - yymsp->major = (YYCODETYPE)yygoto; - yyTraceShift(yypParser, yyact, "... then shift"); - } + yymsp += yysize+1; + yypParser->yytos = yymsp; + yymsp->stateno = (YYACTIONTYPE)yyact; + yymsp->major = (YYCODETYPE)yygoto; + yyTraceShift(yypParser, yyact, "... then shift"); } /* @@ -876,6 +871,10 @@ void Parse( yypParser->yyerrcnt--; #endif yymajor = YYNOCODE; + }else if( yyact==YY_ACCEPT_ACTION ){ + yypParser->yytos--; + yy_accept(yypParser); + return; }else{ assert( yyact == YY_ERROR_ACTION ); yyminorunion.yy0 = yyminor; From 3a9d6c7156e33c63f03f12be8e2168c8d0aa7d2b Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 25 Dec 2017 04:15:38 +0000 Subject: [PATCH 09/40] Enhance LEMON so that it generates the action table in such a way that no range check is needed on the lookahead table to verify that the next input token is valid. This makes the lookahead table slightly larger (about 120 bytes) but helps the parser to run faster. FossilOrigin-Name: 7eb0198d0102e97e4b7ad9e359d95985e55e09c510ea4b360265ac8feb9ed814 --- manifest | 14 +++++------ manifest.uuid | 2 +- tool/lemon.c | 65 +++++++++++++++++++++++++++++++++++++-------------- tool/lempar.c | 16 ++++--------- 4 files changed, 61 insertions(+), 36 deletions(-) diff --git a/manifest b/manifest index f8d8364cbb..d9f3940ae0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\sLEMON-generated\sparser,\savoid\sunnecessary\stests\sfor\sthe\sacceptance\nstate. -D 2017-12-25T00:10:05.418 +C Enhance\sLEMON\sso\sthat\sit\sgenerates\sthe\saction\stable\sin\ssuch\sa\sway\sthat\sno\nrange\scheck\sis\sneeded\son\sthe\slookahead\stable\sto\sverify\sthat\sthe\snext\sinput\ntoken\sis\svalid.\s\sThis\smakes\sthe\slookahead\stable\sslightly\slarger\s(about\s120\nbytes)\sbut\shelps\sthe\sparser\sto\srun\sfaster. +D 2017-12-25T04:15:38.668 F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69 @@ -1608,8 +1608,8 @@ F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4 F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f -F tool/lemon.c 7c6919d98e459c0f8a3673be64b03425553733dba01c12939b2fadc30e4e2804 -F tool/lempar.c 8062f219b4ce349853cb3ab3ebd3ab44466604235347457d703a9f4252e76dd5 +F tool/lemon.c c8d7ce4fe7a90f7fa6a5985452aa926fcf25376cf90095c9d06c432ab0bebdbc +F tool/lempar.c 427ee280f3c3781e82bbee21f428bc8ae18ab245d4f66d65da46b598ded81648 F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca @@ -1687,7 +1687,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 7bfe7a360261ac7227840db49487c2f0fe338a2f1b868fcaada1e04a8d2b8f7a -R 904d9f58d13471f5c0ad3064ead9b812 +P fdbb35c54f2b6cb65d04ac295f207ff3e69360e0558348c77eb5e62691807046 +R f14cbf100834d359550a23c924f7ebaa U drh -Z c00f50853c78fa733a13b33ab92ee708 +Z bb1d7d0db816330a6f1e2b8011c2819b diff --git a/manifest.uuid b/manifest.uuid index e026b0ddc4..b69ed5a1cc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fdbb35c54f2b6cb65d04ac295f207ff3e69360e0558348c77eb5e62691807046 \ No newline at end of file +7eb0198d0102e97e4b7ad9e359d95985e55e09c510ea4b360265ac8feb9ed814 \ No newline at end of file diff --git a/tool/lemon.c b/tool/lemon.c index 33ef43d1b1..96dc756d1b 100644 --- a/tool/lemon.c +++ b/tool/lemon.c @@ -413,6 +413,7 @@ struct lemon { char *tokenprefix; /* A prefix added to token names in the .h file */ int nconflict; /* Number of parsing conflicts */ int nactiontab; /* Number of entries in the yy_action[] table */ + int nlookaheadtab; /* Number of entries in yy_lookahead[] */ int tablesize; /* Total table size of all tables in bytes */ int basisflag; /* Print only basis configurations */ int has_fallback; /* True if any %fallback is seen in the grammar */ @@ -589,10 +590,12 @@ struct acttab { int mxLookahead; /* Maximum aLookahead[].lookahead */ int nLookahead; /* Used slots in aLookahead[] */ int nLookaheadAlloc; /* Slots allocated in aLookahead[] */ + int nterminal; /* Number of terminal symbols */ + int nsymbol; /* total number of symbols */ }; /* Return the number of entries in the yy_action table */ -#define acttab_size(X) ((X)->nAction) +#define acttab_lookahead_size(X) ((X)->nAction) /* The value for the N-th entry in yy_action */ #define acttab_yyaction(X,N) ((X)->aAction[N].action) @@ -608,13 +611,15 @@ void acttab_free(acttab *p){ } /* Allocate a new acttab structure */ -acttab *acttab_alloc(void){ +acttab *acttab_alloc(int nsymbol, int nterminal){ acttab *p = (acttab *) calloc( 1, sizeof(*p) ); if( p==0 ){ fprintf(stderr,"Unable to allocate memory for a new acttab."); exit(1); } memset(p, 0, sizeof(*p)); + p->nsymbol = nsymbol; + p->nterminal = nterminal; return p; } @@ -655,16 +660,24 @@ void acttab_action(acttab *p, int lookahead, int action){ ** to an empty set in preparation for a new round of acttab_action() calls. ** ** Return the offset into the action table of the new transaction. +** +** If the makeItSafe parameter is true, then the offset is chosen so that +** it is impossible to overread the yy_lookaside[] table regardless of +** the lookaside token. This is done for the terminal symbols, as they +** come from external inputs and can contain syntax errors. When makeItSafe +** is false, there is more flexibility in selecting offsets, resulting in +** a smaller table. For non-terminal symbols, which are never syntax errors, +** makeItSafe can be false. */ -int acttab_insert(acttab *p){ - int i, j, k, n; +int acttab_insert(acttab *p, int makeItSafe){ + int i, j, k, n, end; assert( p->nLookahead>0 ); /* Make sure we have enough space to hold the expanded action table ** in the worst case. The worst case occurs if the transaction set ** must be appended to the current action table */ - n = p->mxLookahead + 1; + n = p->nsymbol + 1; if( p->nAction + n >= p->nActionAlloc ){ int oldAlloc = p->nActionAlloc; p->nActionAlloc = p->nAction + n + p->nActionAlloc + 20; @@ -686,7 +699,8 @@ int acttab_insert(acttab *p){ ** ** i is the index in p->aAction[] where p->mnLookahead is inserted. */ - for(i=p->nAction-1; i>=0; i--){ + end = makeItSafe ? p->mnLookahead : 0; + for(i=p->nAction-1; i>=end; i--){ if( p->aAction[i].lookahead==p->mnLookahead ){ /* All lookaheads and actions in the aLookahead[] transaction ** must match against the candidate aAction[i] entry. */ @@ -716,12 +730,13 @@ int acttab_insert(acttab *p){ ** an empty offset in the aAction[] table in which we can add the ** aLookahead[] transaction. */ - if( i<0 ){ + if( inAction, which means the ** transaction will be appended. */ - for(i=0; inActionAlloc - p->mxLookahead; i++){ + i = makeItSafe ? p->mnLookahead : 0; + for(; inActionAlloc - p->mxLookahead; i++){ if( p->aAction[i].lookahead<0 ){ for(j=0; jnLookahead; j++){ k = p->aLookahead[j].lookahead - p->mnLookahead + i; @@ -739,11 +754,19 @@ int acttab_insert(acttab *p){ } } /* Insert transaction set at index i. */ +#if 0 + printf("Acttab:"); + for(j=0; jnLookahead; j++){ + printf(" %d", p->aLookahead[j].lookahead); + } + printf(" inserted at %d\n", i); +#endif for(j=0; jnLookahead; j++){ k = p->aLookahead[j].lookahead - p->mnLookahead + i; p->aAction[k] = p->aLookahead[j]; if( k>=p->nAction ) p->nAction = k+1; } + if( makeItSafe && i+p->nterminal>p->nAction ) p->nAction = i+p->nterminal; p->nLookahead = 0; /* Return the offset that is added to the lookahead in order to get the @@ -751,6 +774,16 @@ int acttab_insert(acttab *p){ return i - p->mnLookahead; } +/* +** Return the size of the action table without the trailing syntax error +** entries. +*/ +int acttab_action_size(acttab *p){ + int n = p->nAction; + while( n>0 && p->aAction[n-1].lookahead<0 ){ n--; } + return n; +} + /********************** From the file "build.c" *****************************/ /* ** Routines to construction the finite state machine for the LEMON @@ -1724,6 +1757,7 @@ int main(int argc, char **argv) stats_line("states", lem.nxstate); stats_line("conflicts", lem.nconflict); stats_line("action table entries", lem.nactiontab); + stats_line("lookahead table entries", lem.nlookaheadtab); stats_line("total table size (bytes)", lem.tablesize); } if( lem.nconflict > 0 ){ @@ -4167,7 +4201,7 @@ void ReportTable( ** of placing the largest action sets first */ for(i=0; inxstate*2; i++) ax[i].iOrder = i; qsort(ax, lemp->nxstate*2, sizeof(ax[0]), axset_compare); - pActtab = acttab_alloc(); + pActtab = acttab_alloc(lemp->nsymbol, lemp->nterminal); for(i=0; inxstate*2 && ax[i].nAction>0; i++){ stp = ax[i].stp; if( ax[i].isTkn ){ @@ -4178,7 +4212,7 @@ void ReportTable( if( action<0 ) continue; acttab_action(pActtab, ap->sp->index, action); } - stp->iTknOfst = acttab_insert(pActtab); + stp->iTknOfst = acttab_insert(pActtab, 1); if( stp->iTknOfstiTknOfst; if( stp->iTknOfst>mxTknOfst ) mxTknOfst = stp->iTknOfst; }else{ @@ -4190,7 +4224,7 @@ void ReportTable( if( action<0 ) continue; acttab_action(pActtab, ap->sp->index, action); } - stp->iNtOfst = acttab_insert(pActtab); + stp->iNtOfst = acttab_insert(pActtab, 0); if( stp->iNtOfstiNtOfst; if( stp->iNtOfst>mxNtOfst ) mxNtOfst = stp->iNtOfst; } @@ -4249,7 +4283,7 @@ void ReportTable( */ /* Output the yy_action table */ - lemp->nactiontab = n = acttab_size(pActtab); + lemp->nactiontab = n = acttab_action_size(pActtab); lemp->tablesize += n*szActionType; fprintf(out,"#define YY_ACTTAB_COUNT (%d)\n", n); lineno++; fprintf(out,"static const YYACTIONTYPE yy_action[] = {\n"); lineno++; @@ -4268,6 +4302,7 @@ void ReportTable( fprintf(out, "};\n"); lineno++; /* Output the yy_lookahead table */ + lemp->nlookaheadtab = n = acttab_lookahead_size(pActtab); lemp->tablesize += n*szCodeType; fprintf(out,"static const YYCODETYPE yy_lookahead[] = {\n"); lineno++; for(i=j=0; inxstate; while( n>0 && lemp->sorted[n-1]->iTknOfst==NO_OFFSET ) n--; - fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", lemp->nactiontab); lineno++; fprintf(out, "#define YY_SHIFT_COUNT (%d)\n", n-1); lineno++; fprintf(out, "#define YY_SHIFT_MIN (%d)\n", mnTknOfst); lineno++; fprintf(out, "#define YY_SHIFT_MAX (%d)\n", mxTknOfst); lineno++; @@ -4312,7 +4346,6 @@ void ReportTable( fprintf(out, "};\n"); lineno++; /* Output the yy_reduce_ofst[] table */ - fprintf(out, "#define YY_REDUCE_USE_DFLT (%d)\n", mnNtOfst-1); lineno++; n = lemp->nxstate; while( n>0 && lemp->sorted[n-1]->iNtOfst==NO_OFFSET ) n--; fprintf(out, "#define YY_REDUCE_COUNT (%d)\n", n-1); lineno++; @@ -4382,10 +4415,8 @@ void ReportTable( */ for(i=0; insymbol; i++){ lemon_sprintf(line,"\"%s\",",lemp->symbols[i]->name); - fprintf(out," %-15s",line); - if( (i&3)==3 ){ fprintf(out,"\n"); lineno++; } + fprintf(out," /* %4d */ \"%s\",\n",i, lemp->symbols[i]->name); lineno++; } - if( (i&3)!=0 ){ fprintf(out,"\n"); lineno++; } tplt_xfer(lemp->name,in,out,&lineno); /* Generate a table containing a text string that describes every diff --git a/tool/lempar.c b/tool/lempar.c index 6c6ca77dde..7ceaaa6207 100644 --- a/tool/lempar.c +++ b/tool/lempar.c @@ -131,19 +131,13 @@ ** (A) N = yy_action[ yy_shift_ofst[S] + X ] ** (B) N = yy_default[S] ** -** The (A) formula is preferred. The B formula is used instead if: -** (1) The yy_shift_ofst[S]+X value is out of range, or -** (2) yy_lookahead[yy_shift_ofst[S]+X] is not equal to X, or -** (3) yy_shift_ofst[S] equal YY_SHIFT_USE_DFLT. -** (Implementation note: YY_SHIFT_USE_DFLT is chosen so that -** YY_SHIFT_USE_DFLT+X will be out of range for all possible lookaheads X. -** Hence only tests (1) and (2) need to be evaluated.) +** The (A) formula is preferred. The B formula is used instead if +** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X. ** ** The formulas above are for computing the action when the lookahead is ** a terminal symbol. If the lookahead is a non-terminal (as occurs after ** a reduce action) then the yy_reduce_ofst[] array is used in place of -** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of -** YY_SHIFT_USE_DFLT. +** the yy_shift_ofst[] array. ** ** The following are the tables generated in this section: ** @@ -478,7 +472,8 @@ static unsigned int yy_find_shift_action( i = yy_shift_ofst[stateno]; assert( iLookAhead!=YYNOCODE ); i += iLookAhead; - if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ + assert( i>=0 && i Date: Mon, 25 Dec 2017 13:43:54 +0000 Subject: [PATCH 10/40] Fix an assertion fault on a syntax error input caused by check-in [6b2ff26c25bb9da3]. Problem discovered by OSSFuzz. FossilOrigin-Name: 90d6e4f10d3055a776d24854c442a2a68e726af8fc382cdb6241a834082e4c4c --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/build.c | 1 + test/colname.test | 11 ++++++++++- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 1c622c1102..d9715194d3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sNULL\spointer\sdereference\safter\sa\ssyntax\serror\sthat\scan\soccur\sas\sa\nresult\sof\scheck-in\s[6b2ff26c25bb9da3]\syesterday.\s\sThis\sproblem\swas\ndiscovered\sby\sthe\sOSSFuzz. -D 2017-12-24T18:56:28.786 +C Fix\san\sassertion\sfault\son\sa\ssyntax\serror\sinput\scaused\sby\scheck-in\n[6b2ff26c25bb9da3].\s\sProblem\sdiscovered\sby\sOSSFuzz. +D 2017-12-25T13:43:54.974 F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69 @@ -423,7 +423,7 @@ F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca F src/btree.c b83a6b03f160528020bb965f0c3a40af5286cd4923c3870fd218177f03a120a7 F src/btree.h 32ef5d3f25dc70ef1ee9cecf84a023c21378f06a57cd701d2e866e141b150f09 F src/btreeInt.h 55b702efce17e5d1941865464227d3802cfc9c7c832fac81d4c94dced47a71fc -F src/build.c ab5bdf955c85bcd56acbf310a48bbd50b4b92079efa40d997a7e4246f8e03741 +F src/build.c 6ab114a9a4717622df3745d26f2c55e9113f356441a8f76fa2b1d7e1f2472c20 F src/callback.c fe677cb5f5abb02f7a772a62a98c2f516426081df68856e8f2d5f950929b966a F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c ff1be3eed7bdd75aaca61ca8dc848f7c9f850ef2fb9cb56f2734e922a098f9c0 @@ -682,7 +682,7 @@ F test/collate9.test 3adcc799229545940df2f25308dd1ad65869145a F test/collateA.test b8218ab90d1fa5c59dcf156efabb1b2599c580d6 F test/collateB.test 1e68906951b846570f29f20102ed91d29e634854ee47454d725f2151ecac0b95 F test/colmeta.test 2c765ea61ee37bc43bbe6d6047f89004e6508eb1 -F test/colname.test 36da785927822ecd0de979459e27e9be63f458dd08d3edde41af3af37a337d58 +F test/colname.test 101aa39392a1f6883278f588836a3ab99178f8103f78032433400475cc05109f F test/conflict.test 029faa2d81a0d1cafb5f88614beb663d972c01db F test/conflict2.test bb0b94cf7196c64a3cbd815c66d3ee98c2fecd9c F test/conflict3.test a83db76a6c3503b2fa057c7bfb08c318d8a422202d8bc5b86226e078e5b49ff9 @@ -1687,7 +1687,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 07c773148d8db185fa54991df09298b64f4fef28879e6c9395759265e8183977 -R 2e4222d820aa06549d33319e9e33c627 +P d49afb8f9804e96662d1e3cadc4c6643908706d848a53d5ed019919c98f2ccba +R 22dc7c511444b2944fcb40dc7656150e U drh -Z 67298e45eb2d4d992f0cdf5678deffdf +Z df3951acae9acd7f479ba37833a7cfe6 diff --git a/manifest.uuid b/manifest.uuid index d58d2c0dd5..55584bef0a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d49afb8f9804e96662d1e3cadc4c6643908706d848a53d5ed019919c98f2ccba \ No newline at end of file +90d6e4f10d3055a776d24854c442a2a68e726af8fc382cdb6241a834082e4c4c \ No newline at end of file diff --git a/src/build.c b/src/build.c index 390dae5d3b..ae2a92c79b 100644 --- a/src/build.c +++ b/src/build.c @@ -1976,6 +1976,7 @@ void sqlite3EndTable( sqlite3DeleteTable(db, pSelTab); sqlite3SelectDestInit(&dest, SRT_Coroutine, regYield); sqlite3Select(pParse, pSelect, &dest); + if( pParse->nErr ) return; sqlite3VdbeEndCoroutine(v, regYield); sqlite3VdbeJumpHere(v, addrTop - 1); addrInsLoop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); diff --git a/test/colname.test b/test/colname.test index cacf91e4e3..358ea77e07 100644 --- a/test/colname.test +++ b/test/colname.test @@ -398,7 +398,7 @@ do_execsql_test colname-9.320 { SELECT name FROM pragma_table_info('t2'); } {Bbb} -# Issue detected by clusterfuzz on 2017-12-24 (Christmas Eve) +# Issue detected by OSSFuzz on 2017-12-24 (Christmas Eve) # caused by check-in https://sqlite.org/src/info/6b2ff26c25 # # Prior to being fixed, the following CREATE TABLE was dereferencing @@ -408,6 +408,15 @@ do_catchsql_test colname-9.400 { CREATE TABLE t4 AS SELECT #0; } {1 {near "#0": syntax error}} +# Issue detected by OSSFuzz on 2017-12-25 (Christmas Day) +# also caused by check-in https://sqlite.org/src/info/6b2ff26c25 +# +# Prior to being fixed, the following CREATE TABLE caused an +# assertion fault. +# +do_catchsql_test colname-9.410 { + CREATE TABLE t5 AS SELECT RAISE(abort,a); +} {1 {RAISE() may only be used within a trigger-program}} # Make sure the quotation marks get removed from the column names # when constructing a new table from an aggregate SELECT. From f6c37dbc8c9ae15689f91e1d9c1e43e7b8737120 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 26 Dec 2017 14:30:44 +0000 Subject: [PATCH 11/40] Add options to speedtest1.c and speed-check.sh for testing performance of floating-point computatations. FossilOrigin-Name: ebfea8728fec955b1d74b1d0a3de498fd1a32e8b39572a8fdab606ed87b169b4 --- manifest | 17 +++++----- manifest.uuid | 2 +- test/speedtest1.c | 76 +++++++++++++++++++++++++++++++++++++++++++-- tool/speed-check.sh | 6 ++++ 4 files changed, 90 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index d9715194d3..aa2114d805 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\san\sassertion\sfault\son\sa\ssyntax\serror\sinput\scaused\sby\scheck-in\n[6b2ff26c25bb9da3].\s\sProblem\sdiscovered\sby\sOSSFuzz. -D 2017-12-25T13:43:54.974 +C Add\soptions\sto\sspeedtest1.c\sand\sspeed-check.sh\sfor\stesting\sperformance\sof\nfloating-point\scomputatations. +D 2017-12-26T14:30:44.117 F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69 @@ -1248,7 +1248,7 @@ F test/speed3.test 694affeb9100526007436334cf7d08f3d74b85ef F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715 F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b -F test/speedtest1.c e44c5fccddcfe916c3bf7fe2f87dcc4b4fd66a0d923eb83515f311212670f267 +F test/speedtest1.c a5faf4cbe5769eee4b721b3875cb3f12520a9b99d9026b1063b47c39603375b8 F test/spellfix.test f9c1f431e2c096c8775fec032952320c0e4700db F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3 F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33 @@ -1647,7 +1647,7 @@ F tool/showstat4.c 0682ebea7abf4d3657f53c4a243f2e7eab48eab344ed36a94bb75dcd19a5c F tool/showwal.c ad9d768f96ca6199ad3a8c9562d679680bd032dd01204ea3e5ea6fb931d81847 F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe F tool/spaceanal.tcl 4bfd19aad7eb3ce0372ef0255f58035e0bba4ff5e9acfd763a10c6fb365c8dec -F tool/speed-check.sh a97ae367e9172a706101901e7caef48f1a14fc8a49053b25e79f6a67296b3412 +F tool/speed-check.sh 9ae425da8819e54e780cf494fc6d8175dfb16e109ae3214a45a5c9bb2b74e2c4 F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355 F tool/speedtest16.c ecb6542862151c3e6509bbc00509b234562ae81e F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff @@ -1687,7 +1687,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P d49afb8f9804e96662d1e3cadc4c6643908706d848a53d5ed019919c98f2ccba -R 22dc7c511444b2944fcb40dc7656150e -U drh -Z df3951acae9acd7f479ba37833a7cfe6 +P 90d6e4f10d3055a776d24854c442a2a68e726af8fc382cdb6241a834082e4c4c +Q +b3c6105181d22c8a53f5bf662e3d182bba962ee8afd1ad972ebd10094b20fc17 +R c2447707ab323a591ab8e05be0f0cae9 +U dan +Z 1002781326ca68c114cfc46396055176 diff --git a/manifest.uuid b/manifest.uuid index 55584bef0a..aaa3417a9c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -90d6e4f10d3055a776d24854c442a2a68e726af8fc382cdb6241a834082e4c4c \ No newline at end of file +ebfea8728fec955b1d74b1d0a3de498fd1a32e8b39572a8fdab606ed87b169b4 \ No newline at end of file diff --git a/test/speedtest1.c b/test/speedtest1.c index b92801a208..9342da79bf 100644 --- a/test/speedtest1.c +++ b/test/speedtest1.c @@ -32,7 +32,7 @@ static const char zHelp[] = " --size N Relative test size. Default=100\n" " --stats Show statistics at the end\n" " --temp N N from 0 to 9. 0: no temp table. 9: all temp tables\n" - " --testset T Run test-set T (main, cte, rtree, orm, debug)\n" + " --testset T Run test-set T (main, cte, rtree, orm, fp, debug)\n" " --trace Turn on SQL tracing\n" " --threads N Use up to N threads for sorting\n" " --utf16be Set text encoding to UTF-16BE\n" @@ -1120,7 +1120,77 @@ void testset_cte(void){ ); speedtest1_run(); speedtest1_end_test(); +} +/* +** Compute a pseudo-random floating point ascii number. +*/ +void speedtest1_random_ascii_fp(char *zFP){ + int x = speedtest1_random(); + int y = speedtest1_random(); + int z; + z = y%10; + if( z<0 ) z = -z; + y /= 10; + sqlite3_snprintf(100,zFP,"%d.%de%d",y,z,x%200); +} + +/* +** A testset for floating-point numbers. +*/ +void testset_fp(void){ + int n; + int i; + char zFP1[100]; + char zFP2[100]; + + n = g.szTest*5000; + speedtest1_begin_test(100, "Fill a table with %d FP values", n*2); + speedtest1_exec("BEGIN"); + speedtest1_exec("CREATE%s TABLE t1(a REAL %s, b REAL %s);", + isTemp(1), g.zNN, g.zNN); + speedtest1_prepare("INSERT INTO t1 VALUES(?1,?2); -- %d times", n); + for(i=1; i<=n; i++){ + speedtest1_random_ascii_fp(zFP1); + speedtest1_random_ascii_fp(zFP2); + sqlite3_bind_text(g.pStmt, 1, zFP1, -1, SQLITE_STATIC); + sqlite3_bind_text(g.pStmt, 2, zFP2, -1, SQLITE_STATIC); + speedtest1_run(); + } + speedtest1_exec("COMMIT"); + speedtest1_end_test(); + + n = g.szTest/25 + 2; + speedtest1_begin_test(110, "%d range queries", n); + speedtest1_prepare("SELECT sum(b) FROM t1 WHERE a BETWEEN ?1 AND ?2"); + for(i=1; i<=n; i++){ + speedtest1_random_ascii_fp(zFP1); + speedtest1_random_ascii_fp(zFP2); + sqlite3_bind_text(g.pStmt, 1, zFP1, -1, SQLITE_STATIC); + sqlite3_bind_text(g.pStmt, 2, zFP2, -1, SQLITE_STATIC); + speedtest1_run(); + } + speedtest1_end_test(); + + speedtest1_begin_test(120, "CREATE INDEX three times"); + speedtest1_exec("BEGIN;"); + speedtest1_exec("CREATE INDEX t1a ON t1(a);"); + speedtest1_exec("CREATE INDEX t1b ON t1(b);"); + speedtest1_exec("CREATE INDEX t1ab ON t1(a,b);"); + speedtest1_exec("COMMIT;"); + speedtest1_end_test(); + + n = g.szTest/3 + 2; + speedtest1_begin_test(130, "%d indexed range queries", n); + speedtest1_prepare("SELECT sum(b) FROM t1 WHERE a BETWEEN ?1 AND ?2"); + for(i=1; i<=n; i++){ + speedtest1_random_ascii_fp(zFP1); + speedtest1_random_ascii_fp(zFP2); + sqlite3_bind_text(g.pStmt, 1, zFP1, -1, SQLITE_STATIC); + sqlite3_bind_text(g.pStmt, 2, zFP2, -1, SQLITE_STATIC); + speedtest1_run(); + } + speedtest1_end_test(); } #ifdef SQLITE_ENABLE_RTREE @@ -1873,6 +1943,8 @@ int main(int argc, char **argv){ testset_orm(); }else if( strcmp(zTSet,"cte")==0 ){ testset_cte(); + }else if( strcmp(zTSet,"fp")==0 ){ + testset_fp(); }else if( strcmp(zTSet,"rtree")==0 ){ #ifdef SQLITE_ENABLE_RTREE testset_rtree(6, 147); @@ -1881,7 +1953,7 @@ int main(int argc, char **argv){ "the R-Tree tests\n"); #endif }else{ - fatal_error("unknown testset: \"%s\"\nChoices: main debug1 cte rtree\n", + fatal_error("unknown testset: \"%s\"\nChoices: main debug1 cte rtree fp\n", zTSet); } speedtest1_final(); diff --git a/tool/speed-check.sh b/tool/speed-check.sh index 2cda5c8078..6cc3018981 100644 --- a/tool/speed-check.sh +++ b/tool/speed-check.sh @@ -117,6 +117,12 @@ while test "$1" != ""; do --orm) SPEEDTEST_OPTS="$SPEEDTEST_OPTS --testset orm" ;; + --cte) + SPEEDTEST_OPTS="$SPEEDTEST_OPTS --testset cte" + ;; + --fp) + SPEEDTEST_OPTS="$SPEEDTEST_OPTS --testset fp" + ;; -*) CC_OPTS="$CC_OPTS $1" ;; From c8f44d245c5034c8f96361026a49b748ac02a700 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 26 Dec 2017 14:32:25 +0000 Subject: [PATCH 12/40] Fix crashes that could occur if SQL NULL values were passed to the built-in FTS5 snippet function. Edit: breaks amalgamation builds. FossilOrigin-Name: 6a790b67a0a5c698526db16ea262b13ecdd1b6ca74e80bdccfcad88ddbdc933a --- ext/fts5/fts5_aux.c | 16 +++++++++++++--- ext/fts5/test/fts5af.test | 10 ++++++++++ manifest | 16 ++++++++-------- manifest.uuid | 2 +- 4 files changed, 32 insertions(+), 12 deletions(-) diff --git a/ext/fts5/fts5_aux.c b/ext/fts5/fts5_aux.c index 219ea6fff8..594b981dda 100644 --- a/ext/fts5/fts5_aux.c +++ b/ext/fts5/fts5_aux.c @@ -358,6 +358,16 @@ static int fts5SnippetScore( return rc; } +/* +** Return the value in pVal interpreted as utf-8 text. Except, if pVal +** contains a NULL value, return a pointer to a static string zero +** bytes in length instead of a NULL pointer. +*/ +static const char *fts5ValueToText(sqlite3_value *pVal){ + const char *zRet = (const char*)sqlite3_value_text(pVal); + return zRet ? zRet : ""; +} + /* ** Implementation of snippet() function. */ @@ -393,9 +403,9 @@ static void fts5SnippetFunction( nCol = pApi->xColumnCount(pFts); memset(&ctx, 0, sizeof(HighlightContext)); iCol = sqlite3_value_int(apVal[0]); - ctx.zOpen = (const char*)sqlite3_value_text(apVal[1]); - ctx.zClose = (const char*)sqlite3_value_text(apVal[2]); - zEllips = (const char*)sqlite3_value_text(apVal[3]); + ctx.zOpen = fts5ValueToText(apVal[1]); + ctx.zClose = fts5ValueToText(apVal[2]); + zEllips = fts5ValueToText(apVal[3]); nToken = sqlite3_value_int(apVal[4]); iBestCol = (iCol>=0 ? iCol : 0); diff --git a/ext/fts5/test/fts5af.test b/ext/fts5/test/fts5af.test index fa4ebd2955..86c8f753fa 100644 --- a/ext/fts5/test/fts5af.test +++ b/ext/fts5/test/fts5af.test @@ -175,6 +175,16 @@ do_execsql_test 5.1 { SELECT snippet(p1, 0, '[', ']', '...', 6) FROM p1('x'); } {{[x] a a a a a...}} +do_execsql_test 5.2 { + SELECT snippet(p1, 0, '[', ']', NULL, 6) FROM p1('x'); +} {{[x] a a a a a}} +do_execsql_test 5.3 { + SELECT snippet(p1, 0, NULL, ']', '...', 6) FROM p1('x'); +} {{x] a a a a a...}} +do_execsql_test 5.4 { + SELECT snippet(p1, 0, '[', NULL, '...', 6) FROM p1('x'); +} {{[x a a a a a...}} + } ;# foreach_detail_mode finish_test diff --git a/manifest b/manifest index aa2114d805..f3f08454e9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\soptions\sto\sspeedtest1.c\sand\sspeed-check.sh\sfor\stesting\sperformance\sof\nfloating-point\scomputatations. -D 2017-12-26T14:30:44.117 +C Fix\scrashes\sthat\scould\soccur\sif\sSQL\sNULL\svalues\swere\spassed\sto\sthe\sbuilt-in\nFTS5\ssnippet\sfunction.\sEdit:\sbreaks\samalgamation\sbuilds. +D 2017-12-26T14:32:25.807 F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69 @@ -106,7 +106,7 @@ F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95 F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0 F ext/fts5/fts5.h 62f3e33ceeb9a428db139f9c012186b371da1cc7 F ext/fts5/fts5Int.h eda28e3a0a5d87c412e8355fe35da875b04cb389908c8eb0d867ad662adbc491 -F ext/fts5/fts5_aux.c 67acf8d51723cf28ffc3828210ba662df4b8d267 +F ext/fts5/fts5_aux.c ca666a3bbe07c5a3bbe9fffaea19c935a1efaf337333e28bad7bdd1971ffd093 F ext/fts5/fts5_buffer.c 1dd1ec0446b3acfc2d7d407eb894762a461613e2695273f48e449bfd13e973ff F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857 F ext/fts5/fts5_expr.c 01048018d21524e2c302b063ff5c3cdcf546e03297215e577205d85b47499deb @@ -129,7 +129,7 @@ F ext/fts5/test/fts5ab.test 9205c839332c908aaad2b01ab8670ece8b161e8f2ec8a9fabf18 F ext/fts5/test/fts5ac.test a7aa7e1fefc6e1918aa4d3111d5c44a09177168e962c5fd2cca9620de8a7ed6d F ext/fts5/test/fts5ad.test e8cf959dfcd57c8e46d6f5f25665686f3b6627130a9a981371dafdf6482790de F ext/fts5/test/fts5ae.test 1142d16d9cc193894dc13cc8f9c7a8a21411ac61b5567a878514df6f9f0d7bb7 -F ext/fts5/test/fts5af.test aa635947bda31ac87fbe99483eef4d9a8571f58ad89c75dfb63312a35688eceb +F ext/fts5/test/fts5af.test 724247405b13f8f06cc6ce464dc4f152dc5dd4e86b12c2099685d8f19747bf7b F ext/fts5/test/fts5ag.test 7816f25a0707578f08145ab539fc0ca025f8951e788b28a6a18a06b2099469dd F ext/fts5/test/fts5ah.test 27b5a33bfd0363ca8a4dc659e6e2a5df3dea1c3c5b04bc51ca6aeb1277bd9b21 F ext/fts5/test/fts5ai.test d837c42249c0d8ad1a2912270e22cf2f303790a611f85c0be3a58e42a3696e3d @@ -1687,8 +1687,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 90d6e4f10d3055a776d24854c442a2a68e726af8fc382cdb6241a834082e4c4c -Q +b3c6105181d22c8a53f5bf662e3d182bba962ee8afd1ad972ebd10094b20fc17 -R c2447707ab323a591ab8e05be0f0cae9 +P ebfea8728fec955b1d74b1d0a3de498fd1a32e8b39572a8fdab606ed87b169b4 +Q +553a3ad32498ddda920216cd44a376a439a58fbb326d2d3800528867db1ffa9d +R 742f62796704fae3ae9dc15618c72290 U dan -Z 1002781326ca68c114cfc46396055176 +Z ecb93df9cf8c6f4bd1c8f7a6ca97d753 diff --git a/manifest.uuid b/manifest.uuid index aaa3417a9c..9c54144fee 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ebfea8728fec955b1d74b1d0a3de498fd1a32e8b39572a8fdab606ed87b169b4 \ No newline at end of file +6a790b67a0a5c698526db16ea262b13ecdd1b6ca74e80bdccfcad88ddbdc933a \ No newline at end of file From 02a43f6defda835b5baaaee274923f1b80d31ceb Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 26 Dec 2017 14:46:20 +0000 Subject: [PATCH 13/40] Faster and smaller implementation of sqlite3AtoF() based on a suggestion from Cezary H. Noweta. FossilOrigin-Name: fd2e0e7a770c2ce9355068aad1024c3d2861c104fd3be304a91c55ca742155fa --- manifest | 15 +++++++-------- manifest.uuid | 2 +- src/util.c | 26 ++++++++++++++++++++------ 3 files changed, 28 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index f3f08454e9..3d3fdb11e9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\scrashes\sthat\scould\soccur\sif\sSQL\sNULL\svalues\swere\spassed\sto\sthe\sbuilt-in\nFTS5\ssnippet\sfunction.\sEdit:\sbreaks\samalgamation\sbuilds. -D 2017-12-26T14:32:25.807 +C Faster\sand\ssmaller\simplementation\sof\ssqlite3AtoF()\sbased\son\sa\ssuggestion\nfrom\sCezary\sH.\sNoweta. +D 2017-12-26T14:46:20.800 F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69 @@ -545,7 +545,7 @@ F src/treeview.c eae35972ff44f67064de2eaf35f04afe94e7aea3271a8b3bcebb3f954880fec F src/trigger.c 775053eecf6b73062e243404b56f5064446254d5cce17d8704d5cdffd72a546a F src/update.c 961bd1265d4d1e5cd65c9a54fa5122fb7aefcb003fcf2de0c092fceb7e58972c F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 -F src/util.c d01fa6f45bfad3b65fb2490513aa2e0676412c61b4b094340b513cf72c3704a4 +F src/util.c 7315e97a8dc2c8e19ca64196c652cf0a65d13fd0a211b2cec082062372dc6261 F src/vacuum.c 90839322fd5f00df9617eb21b68beda9b6e2a2937576b0d65985e4aeb1c53739 F src/vdbe.c 3393b508d9ad084ffce232a7c53e375ef5ac99b50b685c5131fcdfce97a9d534 F src/vdbe.h d50cadf12bcf9fb99117ef392ce1ea283aa429270481426b6e8b0280c101fd97 @@ -1687,8 +1687,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P ebfea8728fec955b1d74b1d0a3de498fd1a32e8b39572a8fdab606ed87b169b4 -Q +553a3ad32498ddda920216cd44a376a439a58fbb326d2d3800528867db1ffa9d -R 742f62796704fae3ae9dc15618c72290 -U dan -Z ecb93df9cf8c6f4bd1c8f7a6ca97d753 +P 6a790b67a0a5c698526db16ea262b13ecdd1b6ca74e80bdccfcad88ddbdc933a +R c3240df89b3aa2504611bdd745085460 +U drh +Z 3dc20c6e2c72c6078d443025934f152b diff --git a/manifest.uuid b/manifest.uuid index 9c54144fee..bdfe92339c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6a790b67a0a5c698526db16ea262b13ecdd1b6ca74e80bdccfcad88ddbdc933a \ No newline at end of file +fd2e0e7a770c2ce9355068aad1024c3d2861c104fd3be304a91c55ca742155fa \ No newline at end of file diff --git a/src/util.c b/src/util.c index a4dbe8fdaf..75de4b3b30 100644 --- a/src/util.c +++ b/src/util.c @@ -320,6 +320,24 @@ int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){ return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b]; } +/* +** Compute 10 to the E-th power. Examples: E==1 results in 10. +** E==2 results in 100. E==50 results in 1.0e50. +** +** This routine only works for values of E between 1 and 341. +*/ +static LONGDOUBLE_TYPE sqlite3Pow10(int E){ + LONGDOUBLE_TYPE x = 10.0; + LONGDOUBLE_TYPE r = 1.0; + while(1){ + if( E & 1 ) r *= x; + E >>= 1; + if( E==0 ) break; + x *= x; + } + return r; +} + /* ** The string z[] is an text representation of a real number. ** Convert this string to a double and write it into *pResult. @@ -475,11 +493,10 @@ do_atof_calc: if( e==0 ){ /*OPTIMIZATION-IF-TRUE*/ result = (double)s; }else{ - LONGDOUBLE_TYPE scale = 1.0; /* attempt to handle extremely small/large numbers better */ if( e>307 ){ /*OPTIMIZATION-IF-TRUE*/ if( e<342 ){ /*OPTIMIZATION-IF-TRUE*/ - while( e%308 ) { scale *= 1.0e+1; e -= 1; } + LONGDOUBLE_TYPE scale = sqlite3Pow10(e-308); if( esign<0 ){ result = s / scale; result /= 1.0e+308; @@ -499,10 +516,7 @@ do_atof_calc: } } }else{ - /* 1.0e+22 is the largest power of 10 than can be - ** represented exactly. */ - while( e%22 ) { scale *= 1.0e+1; e -= 1; } - while( e>0 ) { scale *= 1.0e+22; e -= 22; } + LONGDOUBLE_TYPE scale = sqlite3Pow10(e); if( esign<0 ){ result = s / scale; }else{ From 0d9de99c5cbc065fa0243f1a23ab79081e05fea4 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 26 Dec 2017 18:04:23 +0000 Subject: [PATCH 14/40] Add support for measuring and reporting coverage of the parser state machine using the SQLITE_TESTCTRL_PARSER_COVERAGE test-control. FossilOrigin-Name: 1253a872dbf48656d4efd588ab61223a5ac550d9b2b932249d6ba585276ba573 --- manifest | 22 +++++++++++----------- manifest.uuid | 2 +- src/main.c | 16 ++++++++++++++++ src/shell.c.in | 11 +++++++++++ src/sqlite.h.in | 3 ++- src/sqliteInt.h | 3 +++ tool/lemon.c | 1 + tool/lempar.c | 37 +++++++++++++++++++++++++++++++++++-- 8 files changed, 80 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index d9f3940ae0..7f1e56cfbd 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sLEMON\sso\sthat\sit\sgenerates\sthe\saction\stable\sin\ssuch\sa\sway\sthat\sno\nrange\scheck\sis\sneeded\son\sthe\slookahead\stable\sto\sverify\sthat\sthe\snext\sinput\ntoken\sis\svalid.\s\sThis\smakes\sthe\slookahead\stable\sslightly\slarger\s(about\s120\nbytes)\sbut\shelps\sthe\sparser\sto\srun\sfaster. -D 2017-12-25T04:15:38.668 +C Add\ssupport\sfor\smeasuring\sand\sreporting\scoverage\sof\sthe\sparser\sstate\smachine\nusing\sthe\sSQLITE_TESTCTRL_PARSER_COVERAGE\stest-control. +D 2017-12-26T18:04:23.951 F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69 @@ -443,7 +443,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/insert.c cb67cc56ef2ddd13e6944b2c0dd08a920bcd9503230adef8b9928d338097c722 F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e F src/loadext.c 55bcc3c741059a1056859e8adaf133aa179e22be12215c0936b2f354ef71209b -F src/main.c 7ce55fa3c0bf669944de309ebab1655ed06ec67869adb0372c7a1062e461c448 +F src/main.c 690c4134f944cbd5b71d59dd6e61ce4131f6a50ab774f38108e57d07d79cf876 F src/malloc.c a02c9e69bc76bee0f639416b947a946412890b606301454727feadcb313536d6 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de @@ -479,11 +479,11 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c bbee7e31d369a18a2f4836644769882e9c5d40ef4a3af911db06410b65cb3730 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c 8b22abe193e4d8243befa2038e4ae2405802fed1c446e5e502d11f652e09ba74 -F src/shell.c.in 339169a3d1307b5566ebe9ce15832d03439206106724c78cc3d9125a7b851795 -F src/sqlite.h.in 2126192945019d4cdce335cb236b440a05ec75c93e4cd94c9c6d6e7fcc654cc4 +F src/shell.c.in f3ec8f90dd698ea98781a90642c91eacbc24f4e55bb551c7b2762000d3ef55dc +F src/sqlite.h.in b4dc75265ed04b98e2184011a7dd0054ce2137ff84867a6be8b4f3bdfbc03d30 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34 -F src/sqliteInt.h 003b78433baae4e5c997f99f2f9cf98d90754f256baeacb32f8189569a48251f +F src/sqliteInt.h 26bf7cc7aaa6a6eb3d3c0581f9ef5523da01babb8de1d796793d5165fea95958 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 9737ed017279a9e0c5da748701c3c7bf1e8ae0dae459aad20dd64fcff97a7e35 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -1608,8 +1608,8 @@ F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4 F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f -F tool/lemon.c c8d7ce4fe7a90f7fa6a5985452aa926fcf25376cf90095c9d06c432ab0bebdbc -F tool/lempar.c 427ee280f3c3781e82bbee21f428bc8ae18ab245d4f66d65da46b598ded81648 +F tool/lemon.c d92031adf63377ff5055441c9d26a41a03378e8cac8dbcc1cd6ef7190f51aa6a +F tool/lempar.c 2a688bf343f21c25908cf082d0d707f45bc4416eea8550787809da4025c3d7c6 F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca @@ -1687,7 +1687,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P fdbb35c54f2b6cb65d04ac295f207ff3e69360e0558348c77eb5e62691807046 -R f14cbf100834d359550a23c924f7ebaa +P 7eb0198d0102e97e4b7ad9e359d95985e55e09c510ea4b360265ac8feb9ed814 +R e80238b7e2c8eabf5efe2bfae85580fc U drh -Z bb1d7d0db816330a6f1e2b8011c2819b +Z d5a5596d3c74652b6ba118722fb4ea75 diff --git a/manifest.uuid b/manifest.uuid index b69ed5a1cc..dce691ea27 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7eb0198d0102e97e4b7ad9e359d95985e55e09c510ea4b360265ac8feb9ed814 \ No newline at end of file +1253a872dbf48656d4efd588ab61223a5ac550d9b2b932249d6ba585276ba573 \ No newline at end of file diff --git a/src/main.c b/src/main.c index 32ce1889f6..3c8035c120 100644 --- a/src/main.c +++ b/src/main.c @@ -3911,6 +3911,22 @@ int sqlite3_test_control(int op, ...){ sqlite3_mutex_leave(db->mutex); break; } + +#if defined(YYCOVERAGE) + /* sqlite3_test_control(SQLITE_TESTCTRL_PARSER_COVERAGE, FILE *out) + ** + ** This test control (only available when SQLite is compiled with + ** -DYYCOVERAGE) writes a report onto "out" that shows all + ** state/lookahead combinations in the parser state machine + ** which are never exercised. If any state is missed, make the + ** return code SQLITE_ERROR. + */ + case SQLITE_TESTCTRL_PARSER_COVERAGE: { + FILE *out = va_arg(ap, FILE*); + if( sqlite3ParserCoverage(out) ) rc = SQLITE_ERROR; + break; + } +#endif /* defined(YYCOVERAGE) */ } va_end(ap); #endif /* SQLITE_UNTESTABLE */ diff --git a/src/shell.c.in b/src/shell.c.in index 13b1fcde39..155ca708a5 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -6108,6 +6108,9 @@ static int do_meta_command(char *zLine, ShellState *p){ { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" }, { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" }, { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" }, +#ifdef YYCOVERAGE + { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE, "" }, +#endif { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " }, { "prng_reset", SQLITE_TESTCTRL_PRNG_RESET, "" }, { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" }, @@ -6233,6 +6236,14 @@ static int do_meta_command(char *zLine, ShellState *p){ isOk = 3; } break; + +#ifdef YYCOVERAGE + case SQLITE_TESTCTRL_PARSER_COVERAGE: + if( nArg==2 ){ + sqlite3_test_control(testctrl, p->out); + isOk = 3; + } +#endif } } if( isOk==0 && iCtrl>=0 ){ diff --git a/src/sqlite.h.in b/src/sqlite.h.in index f161eea6f2..7e5fccdae6 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -7042,7 +7042,8 @@ int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_ISINIT 23 #define SQLITE_TESTCTRL_SORTER_MMAP 24 #define SQLITE_TESTCTRL_IMPOSTER 25 -#define SQLITE_TESTCTRL_LAST 25 /* Largest TESTCTRL */ +#define SQLITE_TESTCTRL_PARSER_COVERAGE 26 +#define SQLITE_TESTCTRL_LAST 26 /* Largest TESTCTRL */ /* ** CAPI3REF: SQLite Runtime Status diff --git a/src/sqliteInt.h b/src/sqliteInt.h index b0c4711b03..074d363d48 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -4348,6 +4348,9 @@ void sqlite3Put4byte(u8*, u32); #ifdef SQLITE_DEBUG void sqlite3ParserTrace(FILE*, char *); #endif +#if defined(YYCOVERAGE) + int sqlite3ParserCoverage(FILE*); +#endif /* ** If the SQLITE_ENABLE IOTRACE exists then the global variable diff --git a/tool/lemon.c b/tool/lemon.c index 96dc756d1b..111082c72a 100644 --- a/tool/lemon.c +++ b/tool/lemon.c @@ -4257,6 +4257,7 @@ void ReportTable( ** been computed */ fprintf(out,"#define YYNSTATE %d\n",lemp->nxstate); lineno++; fprintf(out,"#define YYNRULE %d\n",lemp->nrule); lineno++; + fprintf(out,"#define YYNTOKEN %d\n",lemp->nterminal); lineno++; fprintf(out,"#define YY_MAX_SHIFT %d\n",lemp->nxstate-1); lineno++; i = lemp->minShiftReduce; fprintf(out,"#define YY_MIN_SHIFTREDUCE %d\n",i); lineno++; diff --git a/tool/lempar.c b/tool/lempar.c index 7ceaaa6207..29dc15d03d 100644 --- a/tool/lempar.c +++ b/tool/lempar.c @@ -72,6 +72,7 @@ ** defined, then do no error processing. ** YYNSTATE the combined number of states. ** YYNRULE the number of rules in the grammar +** YYNTOKEN Number of terminal symbols ** YY_MAX_SHIFT Maximum value for shift actions ** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions ** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions @@ -253,13 +254,13 @@ void ParseTrace(FILE *TraceFILE, char *zTracePrompt){ } #endif /* NDEBUG */ -#ifndef NDEBUG +#if defined(YYCOVERAGE) || !defined(NDEBUG) /* For tracing shifts, the names of all terminals and nonterminals ** are required. The following table supplies these names */ static const char *const yyTokenName[] = { %% }; -#endif /* NDEBUG */ +#endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */ #ifndef NDEBUG /* For tracing reduce actions, the names of all rules are required. @@ -455,6 +456,35 @@ int ParseStackPeak(void *p){ } #endif +/* This array of booleans keeps track of the parser statement +** coverage. The element yycoverage[X][Y] is set when the parser +** is in state X and has a lookahead token Y. In a well-tested +** systems, every element of this matrix should end up being set. +*/ +#if defined(YYCOVERAGE) +static unsigned char yycoverage[YYNSTATE][YYNTOKEN]; +#endif + +/* +** Write into out a description of every state/lookahead combination that +** has not previously been seen by the parser. Return the number of +** missed state/lookahead combinations. +*/ +#if defined(YYCOVERAGE) +int ParseCoverage(FILE *out){ + int i, j; + int nMissed = 0; + for(i=0; iYY_MAX_SHIFT ) return stateno; assert( stateno <= YY_SHIFT_COUNT ); +#if defined(YYCOVERAGE) + yycoverage[stateno][iLookAhead] = 1; +#endif do{ i = yy_shift_ofst[stateno]; assert( iLookAhead!=YYNOCODE ); From 22716cbb0baa9b07231b033247a7cae0f1ae0c3a Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 26 Dec 2017 18:32:06 +0000 Subject: [PATCH 15/40] Change the lemon-parser coverage report format to report all state/lookahead pairs and indicate on each whether it is hit or missed. FossilOrigin-Name: 86e30fc284c740b55f75884b67988fe837b28878f586f6ec8850ecf80164e700 --- manifest | 12 ++++++------ manifest.uuid | 2 +- tool/lempar.c | 8 +++++--- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 9adf601335..ffec829b50 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sbug\sfixes\sfrom\strunk. -D 2017-12-26T18:14:53.001 +C Change\sthe\slemon-parser\scoverage\sreport\sformat\sto\sreport\sall\sstate/lookahead\npairs\sand\sindicate\son\seach\swhether\sit\sis\shit\sor\smissed. +D 2017-12-26T18:32:06.041 F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69 @@ -1609,7 +1609,7 @@ F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f F tool/lemon.c d92031adf63377ff5055441c9d26a41a03378e8cac8dbcc1cd6ef7190f51aa6a -F tool/lempar.c 2a688bf343f21c25908cf082d0d707f45bc4416eea8550787809da4025c3d7c6 +F tool/lempar.c 64e760f7cc21ea7e73513b062a86a3c478dfd1ed41fe9837a6f49958cdb61e03 F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca @@ -1687,7 +1687,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 1253a872dbf48656d4efd588ab61223a5ac550d9b2b932249d6ba585276ba573 fd2e0e7a770c2ce9355068aad1024c3d2861c104fd3be304a91c55ca742155fa -R 2e2b89187d0becf4c2715a566c5e3287 +P d76e12066fa6950f877cbe33b1892e2b0afa948978815d5b9a90cde1fff8ec98 +R 930f1a264ff138489be35924f879ef78 U drh -Z ade3bde65575a1ed1ca48cdbaee1adc1 +Z 2620b1a658dd06210670b65491310e1c diff --git a/manifest.uuid b/manifest.uuid index e738275177..97230d7170 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d76e12066fa6950f877cbe33b1892e2b0afa948978815d5b9a90cde1fff8ec98 \ No newline at end of file +86e30fc284c740b55f75884b67988fe837b28878f586f6ec8850ecf80164e700 \ No newline at end of file diff --git a/tool/lempar.c b/tool/lempar.c index 29dc15d03d..5404fa5f5f 100644 --- a/tool/lempar.c +++ b/tool/lempar.c @@ -476,9 +476,11 @@ int ParseCoverage(FILE *out){ int nMissed = 0; for(i=0; i Date: Wed, 27 Dec 2017 15:21:16 +0000 Subject: [PATCH 16/40] In LEMON, fix an off-by-one error that can make the lookahead table one byte too smal. FossilOrigin-Name: 93792bc58a2eccc7e07b14307388350bb376db32c5055b79a44e4fa8ff91d58e --- manifest | 12 ++++++------ manifest.uuid | 2 +- tool/lemon.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index ffec829b50..784faa63b2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\slemon-parser\scoverage\sreport\sformat\sto\sreport\sall\sstate/lookahead\npairs\sand\sindicate\son\seach\swhether\sit\sis\shit\sor\smissed. -D 2017-12-26T18:32:06.041 +C In\sLEMON,\sfix\san\soff-by-one\serror\sthat\scan\smake\sthe\slookahead\stable\sone\nbyte\stoo\ssmal. +D 2017-12-27T15:21:16.478 F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69 @@ -1608,7 +1608,7 @@ F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4 F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f -F tool/lemon.c d92031adf63377ff5055441c9d26a41a03378e8cac8dbcc1cd6ef7190f51aa6a +F tool/lemon.c 7f7735326ca9c3b48327b241063cee52d35d44e20ebe1b3624a81658052a4d39 F tool/lempar.c 64e760f7cc21ea7e73513b062a86a3c478dfd1ed41fe9837a6f49958cdb61e03 F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 @@ -1687,7 +1687,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P d76e12066fa6950f877cbe33b1892e2b0afa948978815d5b9a90cde1fff8ec98 -R 930f1a264ff138489be35924f879ef78 +P 86e30fc284c740b55f75884b67988fe837b28878f586f6ec8850ecf80164e700 +R 4a4c12385039bdde527999ce093c45db U drh -Z 2620b1a658dd06210670b65491310e1c +Z dbb131aa448f925318d1af4566b5714c diff --git a/manifest.uuid b/manifest.uuid index 97230d7170..d4b1dea234 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -86e30fc284c740b55f75884b67988fe837b28878f586f6ec8850ecf80164e700 \ No newline at end of file +93792bc58a2eccc7e07b14307388350bb376db32c5055b79a44e4fa8ff91d58e \ No newline at end of file diff --git a/tool/lemon.c b/tool/lemon.c index 111082c72a..96bbed7473 100644 --- a/tool/lemon.c +++ b/tool/lemon.c @@ -766,7 +766,7 @@ int acttab_insert(acttab *p, int makeItSafe){ p->aAction[k] = p->aLookahead[j]; if( k>=p->nAction ) p->nAction = k+1; } - if( makeItSafe && i+p->nterminal>p->nAction ) p->nAction = i+p->nterminal; + if( makeItSafe && i+p->nterminal>=p->nAction ) p->nAction = i+p->nterminal+1; p->nLookahead = 0; /* Return the offset that is added to the lookahead in order to get the From 7e7b753158f6c7fa0442f6609179df2512da2633 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 27 Dec 2017 16:13:22 +0000 Subject: [PATCH 17/40] In the lemon-generated parser, do not report the End-of-input character and the wildcard character as missed coverage. FossilOrigin-Name: 3fe964873da16c0e0b1c4f1945f965d4137df7a307acd6a3eb6585ffbaa2afd1 --- manifest | 12 ++++++------ manifest.uuid | 2 +- tool/lempar.c | 3 ++- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 784faa63b2..74d89bf960 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sLEMON,\sfix\san\soff-by-one\serror\sthat\scan\smake\sthe\slookahead\stable\sone\nbyte\stoo\ssmal. -D 2017-12-27T15:21:16.478 +C In\sthe\slemon-generated\sparser,\sdo\snot\sreport\sthe\sEnd-of-input\scharacter\sand\nthe\swildcard\scharacter\sas\smissed\scoverage. +D 2017-12-27T16:13:22.261 F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69 @@ -1609,7 +1609,7 @@ F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f F tool/lemon.c 7f7735326ca9c3b48327b241063cee52d35d44e20ebe1b3624a81658052a4d39 -F tool/lempar.c 64e760f7cc21ea7e73513b062a86a3c478dfd1ed41fe9837a6f49958cdb61e03 +F tool/lempar.c 48ca9d9f280762da24d667f423c5421e09a6839d08a7d6a516d009db22974deb F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca @@ -1687,7 +1687,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 86e30fc284c740b55f75884b67988fe837b28878f586f6ec8850ecf80164e700 -R 4a4c12385039bdde527999ce093c45db +P 93792bc58a2eccc7e07b14307388350bb376db32c5055b79a44e4fa8ff91d58e +R 930e0d52d43acba766af53475563b556 U drh -Z dbb131aa448f925318d1af4566b5714c +Z 594a8d4b6a5a5a1f42055bf091b10e50 diff --git a/manifest.uuid b/manifest.uuid index d4b1dea234..5d9f174839 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -93792bc58a2eccc7e07b14307388350bb376db32c5055b79a44e4fa8ff91d58e \ No newline at end of file +3fe964873da16c0e0b1c4f1945f965d4137df7a307acd6a3eb6585ffbaa2afd1 \ No newline at end of file diff --git a/tool/lempar.c b/tool/lempar.c index 5404fa5f5f..e5dd50cfb7 100644 --- a/tool/lempar.c +++ b/tool/lempar.c @@ -475,7 +475,8 @@ int ParseCoverage(FILE *out){ int i, j; int nMissed = 0; for(i=0; i Date: Wed, 27 Dec 2017 17:14:50 +0000 Subject: [PATCH 18/40] Change the coverage measurement logic in the lemon-generated parser so that it only checks for coverage of state/lookahead pairs that are valid syntax. It turns out that some states are unreachable if the lookahead is not valid syntax, because the states are only reachable through a shift following a reduce, and the reduce does not happen if the lookahead is a syntax error. FossilOrigin-Name: 9dce46508772bd0f9e940c4d44933154044bb58c1b3511dd0143287bf795dd6b --- manifest | 12 ++++++------ manifest.uuid | 2 +- tool/lempar.c | 26 ++++++++++++++++---------- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/manifest b/manifest index 74d89bf960..cb95612f6f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\slemon-generated\sparser,\sdo\snot\sreport\sthe\sEnd-of-input\scharacter\sand\nthe\swildcard\scharacter\sas\smissed\scoverage. -D 2017-12-27T16:13:22.261 +C Change\sthe\scoverage\smeasurement\slogic\sin\sthe\slemon-generated\sparser\sso\sthat\nit\sonly\schecks\sfor\scoverage\sof\sstate/lookahead\spairs\sthat\sare\svalid\ssyntax.\nIt\sturns\sout\sthat\ssome\sstates\sare\sunreachable\sif\sthe\slookahead\sis\snot\svalid\nsyntax,\sbecause\sthe\sstates\sare\sonly\sreachable\sthrough\sa\sshift\sfollowing\sa\nreduce,\sand\sthe\sreduce\sdoes\snot\shappen\sif\sthe\slookahead\sis\sa\ssyntax\serror. +D 2017-12-27T17:14:50.938 F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69 @@ -1609,7 +1609,7 @@ F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f F tool/lemon.c 7f7735326ca9c3b48327b241063cee52d35d44e20ebe1b3624a81658052a4d39 -F tool/lempar.c 48ca9d9f280762da24d667f423c5421e09a6839d08a7d6a516d009db22974deb +F tool/lempar.c 1b1279a362b7045b4e3214301665c12e32689e2c9caf33b35587669bac6b22fa F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca @@ -1687,7 +1687,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 93792bc58a2eccc7e07b14307388350bb376db32c5055b79a44e4fa8ff91d58e -R 930e0d52d43acba766af53475563b556 +P 3fe964873da16c0e0b1c4f1945f965d4137df7a307acd6a3eb6585ffbaa2afd1 +R 43f297c7f87ea228ee76b1c746f9c4a6 U drh -Z 594a8d4b6a5a5a1f42055bf091b10e50 +Z 38efd78b8cbae26fc786eb4139191684 diff --git a/manifest.uuid b/manifest.uuid index 5d9f174839..8cb561dc1a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3fe964873da16c0e0b1c4f1945f965d4137df7a307acd6a3eb6585ffbaa2afd1 \ No newline at end of file +9dce46508772bd0f9e940c4d44933154044bb58c1b3511dd0143287bf795dd6b \ No newline at end of file diff --git a/tool/lempar.c b/tool/lempar.c index e5dd50cfb7..97fd421334 100644 --- a/tool/lempar.c +++ b/tool/lempar.c @@ -467,20 +467,25 @@ static unsigned char yycoverage[YYNSTATE][YYNTOKEN]; /* ** Write into out a description of every state/lookahead combination that -** has not previously been seen by the parser. Return the number of -** missed state/lookahead combinations. +** +** (1) has not been used by the parser, and +** (2) is not a syntax error. +** +** Return the number of missed state/lookahead combinations. */ #if defined(YYCOVERAGE) int ParseCoverage(FILE *out){ - int i, j; + int stateno, iLookAhead, i; int nMissed = 0; - for(i=0; i=0 && i+YYNTOKEN<=sizeof(yy_lookahead)/sizeof(yy_lookahead[0]) ); assert( iLookAhead!=YYNOCODE ); + assert( iLookAhead < YYNTOKEN ); i += iLookAhead; - assert( i>=0 && i Date: Wed, 27 Dec 2017 17:36:58 +0000 Subject: [PATCH 19/40] The previous check-in had an error in the coverage reporting logic. FossilOrigin-Name: ec9b19eb652e81cd3c8a5595eb39aac3aca4abe72136c4b65c9cc257594a9c92 --- manifest | 12 ++++++------ manifest.uuid | 2 +- tool/lempar.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index cb95612f6f..2ca894e566 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\scoverage\smeasurement\slogic\sin\sthe\slemon-generated\sparser\sso\sthat\nit\sonly\schecks\sfor\scoverage\sof\sstate/lookahead\spairs\sthat\sare\svalid\ssyntax.\nIt\sturns\sout\sthat\ssome\sstates\sare\sunreachable\sif\sthe\slookahead\sis\snot\svalid\nsyntax,\sbecause\sthe\sstates\sare\sonly\sreachable\sthrough\sa\sshift\sfollowing\sa\nreduce,\sand\sthe\sreduce\sdoes\snot\shappen\sif\sthe\slookahead\sis\sa\ssyntax\serror. -D 2017-12-27T17:14:50.938 +C The\sprevious\scheck-in\shad\san\serror\sin\sthe\scoverage\sreporting\slogic. +D 2017-12-27T17:36:58.482 F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69 @@ -1609,7 +1609,7 @@ F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f F tool/lemon.c 7f7735326ca9c3b48327b241063cee52d35d44e20ebe1b3624a81658052a4d39 -F tool/lempar.c 1b1279a362b7045b4e3214301665c12e32689e2c9caf33b35587669bac6b22fa +F tool/lempar.c dddd4f592b8bad36aec4500d456c5db5fe42fefc4ee384913880439d8917f87a F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca @@ -1687,7 +1687,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 3fe964873da16c0e0b1c4f1945f965d4137df7a307acd6a3eb6585ffbaa2afd1 -R 43f297c7f87ea228ee76b1c746f9c4a6 +P 9dce46508772bd0f9e940c4d44933154044bb58c1b3511dd0143287bf795dd6b +R 0e64cfa85d322f92630985625ab9cde3 U drh -Z 38efd78b8cbae26fc786eb4139191684 +Z afc4d6b44fe600f4cffd568a58de353c diff --git a/manifest.uuid b/manifest.uuid index 8cb561dc1a..3498a34465 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9dce46508772bd0f9e940c4d44933154044bb58c1b3511dd0143287bf795dd6b \ No newline at end of file +ec9b19eb652e81cd3c8a5595eb39aac3aca4abe72136c4b65c9cc257594a9c92 \ No newline at end of file diff --git a/tool/lempar.c b/tool/lempar.c index 97fd421334..9164eb0c1e 100644 --- a/tool/lempar.c +++ b/tool/lempar.c @@ -480,7 +480,7 @@ int ParseCoverage(FILE *out){ for(stateno=0; stateno Date: Wed, 27 Dec 2017 19:43:22 +0000 Subject: [PATCH 20/40] Add and use the internal sqlite3DbSpanDup() interface. FossilOrigin-Name: a8e1545cb7aacb6a26a8c92a3ad4a3d584d150c3a00d2828c8adbb1ee19fcb6d --- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- src/build.c | 6 +----- src/expr.c | 6 +----- src/malloc.c | 13 +++++++++++++ src/sqliteInt.h | 1 + test/capi2.test | 2 +- 7 files changed, 28 insertions(+), 22 deletions(-) diff --git a/manifest b/manifest index c8a3a065d3..0b31af5927 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\srecent\senhancements\sfrom\strunk. -D 2017-12-27T19:27:26.668 +C Add\sand\suse\sthe\sinternal\ssqlite3DbSpanDup()\sinterface. +D 2017-12-27T19:43:22.931 F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69 @@ -423,7 +423,7 @@ F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca F src/btree.c b83a6b03f160528020bb965f0c3a40af5286cd4923c3870fd218177f03a120a7 F src/btree.h 32ef5d3f25dc70ef1ee9cecf84a023c21378f06a57cd701d2e866e141b150f09 F src/btreeInt.h 55b702efce17e5d1941865464227d3802cfc9c7c832fac81d4c94dced47a71fc -F src/build.c 972224edcc3385f1d6ad265f84a8120f777a2c4f7405ad848def0aee082a9573 +F src/build.c a03eb5a1cfff74784c24a4478ba5455711571936f1ac9d43f94fa7df57509977 F src/callback.c fe677cb5f5abb02f7a772a62a98c2f516426081df68856e8f2d5f950929b966a F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c ff1be3eed7bdd75aaca61ca8dc848f7c9f850ef2fb9cb56f2734e922a098f9c0 @@ -431,7 +431,7 @@ F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957 F src/dbpage.c 8db4c97f630e7d83f884ea75caf1ffd0988c160e9d530194d93721c80821e0f6 F src/dbstat.c 7a4ba8518b6369ef3600c49cf9c918ad979acba610b2aebef1b656d649b96720 F src/delete.c 74667ad914ac143731a444a1bacf29ceb18f6eded8a0dd17aafae80baa07f8bb -F src/expr.c 04188faa71b86bff3a1de46d92f41b9ec2b18fa1bbbdbf683cfff657fe803f3d +F src/expr.c f03666d7f50caf4139eb777085833808028e8af6b6dfafa722b3e843a369a126 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c d617daf66b5515e2b42c1405b2b4984c30ca50fb705ab164271a9bf66c69e331 F src/func.c 0fb9a2d678d3c8aba89b46468b309cd7e8fa9806a369a30aa89024660845bb13 @@ -444,7 +444,7 @@ F src/insert.c cb67cc56ef2ddd13e6944b2c0dd08a920bcd9503230adef8b9928d338097c722 F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e F src/loadext.c 55bcc3c741059a1056859e8adaf133aa179e22be12215c0936b2f354ef71209b F src/main.c 690c4134f944cbd5b71d59dd6e61ce4131f6a50ab774f38108e57d07d79cf876 -F src/malloc.c a02c9e69bc76bee0f639416b947a946412890b606301454727feadcb313536d6 +F src/malloc.c 6f684fd039f53bf9195193eb0cde731a2954970fabc6ef054ba379b6052dc296 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 @@ -483,7 +483,7 @@ F src/shell.c.in f3ec8f90dd698ea98781a90642c91eacbc24f4e55bb551c7b2762000d3ef55d F src/sqlite.h.in b4dc75265ed04b98e2184011a7dd0054ce2137ff84867a6be8b4f3bdfbc03d30 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34 -F src/sqliteInt.h d7054a71c87fe6b21c42147d4857f5baa8f19e959003b6011e473a1f5f93a542 +F src/sqliteInt.h 707e078db16dafad27401bb023da2dd12bafb0a2a421900ef4a1ff1e38c2b01f F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 9737ed017279a9e0c5da748701c3c7bf1e8ae0dae459aad20dd64fcff97a7e35 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -658,7 +658,7 @@ F test/busy.test 510dc6daaad18bcbbc085bcc6217d6dc418def5e73f72ce1475eea0cb783472 F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de F test/cacheflush.test af25bb1509df04c1da10e38d8f322d66eceedf61 F test/cachespill.test 895997f84a25b323b166aecb69baab2d6380ea98f9e0bcc688c4493c535cfab9 -F test/capi2.test 011c16da245fdc0106a2785035de6b242c05e738 +F test/capi2.test d3267a146df2251e7ad09a672d59e33e836d74c6fbeb843c18e87835ef646c12 F test/capi3.test 986e57cea8ab423b3fc8c2e3b69330394252d3d2a4496122ff3749e258305695 F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4 F test/capi3c.test 7ebed1d8fa2f3190149d556fe8cff5a006be62af437c5c4640db614470126098 @@ -1687,7 +1687,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 74a0181fc016fb0b7934188cfcc2ec26c689f0d33cc42453875f4392b7240d3a 1b22b42e59793af19c69a2e5f6822883cc2687d4a0d9b9280bbff885276c6baa -R a3246aa6793f9a1aed1e1936973e7f16 +P 76373091354f27577e5235e96cfaa4b31429a38d1e0e1d6e094c4cc323b92a0a +R 913c4466610a0123883763647119d1c7 U drh -Z 2e8cea4c20132476e571ae504e9351f9 +Z 28dbbdc669e3541be1657ab76b942c72 diff --git a/manifest.uuid b/manifest.uuid index c3e1771bba..9cbf31ff1c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -76373091354f27577e5235e96cfaa4b31429a38d1e0e1d6e094c4cc323b92a0a \ No newline at end of file +a8e1545cb7aacb6a26a8c92a3ad4a3d584d150c3a00d2828c8adbb1ee19fcb6d \ No newline at end of file diff --git a/src/build.c b/src/build.c index 9447d02d48..26eb0579e6 100644 --- a/src/build.c +++ b/src/build.c @@ -1241,14 +1241,10 @@ void sqlite3AddDefaultValue( ** tokens that point to volatile memory. */ Expr x; - int n; sqlite3ExprDelete(db, pCol->pDflt); memset(&x, 0, sizeof(x)); x.op = TK_SPAN; - while( sqlite3Isspace(zStart[0]) ) zStart++; - n = (int)(zEnd - zStart); - while( n>0 && sqlite3Isspace(zStart[n-1]) ) n--; - x.u.zToken = sqlite3DbStrNDup(db, zStart, n); + x.u.zToken = sqlite3DbSpanDup(db, zStart, zEnd); x.pLeft = pExpr; x.flags = EP_Skip; pCol->pDflt = sqlite3ExprDup(db, &x, EXPRDUP_REDUCE); diff --git a/src/expr.c b/src/expr.c index 129c1299bf..1592f10408 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1661,13 +1661,9 @@ void sqlite3ExprListSetSpan( assert( pList!=0 || db->mallocFailed!=0 ); if( pList ){ struct ExprList_item *pItem = &pList->a[pList->nExpr-1]; - int n; assert( pList->nExpr>0 ); sqlite3DbFree(db, pItem->zSpan); - while( sqlite3Isspace(zStart[0]) ) zStart++; - n = (int)(zEnd - zStart); - while( n>0 && sqlite3Isspace(zStart[n-1]) ) n--; - pItem->zSpan = sqlite3DbStrNDup(db, zStart, n); + pItem->zSpan = sqlite3DbSpanDup(db, zStart, zEnd); } } diff --git a/src/malloc.c b/src/malloc.c index b750f6e72f..ec2d93ac89 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -627,6 +627,19 @@ char *sqlite3DbStrNDup(sqlite3 *db, const char *z, u64 n){ return zNew; } +/* +** The text between zStart and zEnd represents a phrase within a larger +** SQL statement. Make a copy of this phrase in space obtained form +** sqlite3DbMalloc(). Omit leading and trailing whitespace. +*/ +char *sqlite3DbSpanDup(sqlite3 *db, const char *zStart, const char *zEnd){ + int n; + while( sqlite3Isspace(zStart[0]) ) zStart++; + n = (int)(zEnd - zStart); + while( n>0 && sqlite3Isspace(zStart[n-1]) ) n--; + return sqlite3DbStrNDup(db, zStart, n); +} + /* ** Free any prior content in *pz and replace it with a copy of zNew. */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index af351fc114..a51bae25c1 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3513,6 +3513,7 @@ void *sqlite3DbMallocRaw(sqlite3*, u64); void *sqlite3DbMallocRawNN(sqlite3*, u64); char *sqlite3DbStrDup(sqlite3*,const char*); char *sqlite3DbStrNDup(sqlite3*,const char*, u64); +char *sqlite3DbSpanDup(sqlite3*,const char*,const char*); void *sqlite3Realloc(void*, u64); void *sqlite3DbReallocOrFree(sqlite3 *, void *, u64); void *sqlite3DbRealloc(sqlite3 *, void *, u64); diff --git a/test/capi2.test b/test/capi2.test index 39f50dd079..5e51871814 100644 --- a/test/capi2.test +++ b/test/capi2.test @@ -184,7 +184,7 @@ do_test capi2-3.5 { } {1 {(1) no such column: bogus} {;;x;}} do_test capi2-3.6 { set rc [catch { - sqlite3_prepare $DB {select 5/0} -1 TAIL + sqlite3_prepare $DB {select 5/0;} -1 TAIL } VM] lappend rc $TAIL } {0 {}} From f259df5fc8f6cff45a322e3cd3eca4db54fa6e1d Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 27 Dec 2017 20:38:35 +0000 Subject: [PATCH 21/40] Show the text of individual statements within a trigger, as they execute, as comments in the output from sqlite3_trace() and sqlite3_trace_v2(). FossilOrigin-Name: fe3d2b97d8945e6a9636472f77bcdc92cc5dda8b3e6e3a4fcbdd0a212ea5b9aa --- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- src/parse.y | 24 +++++++++++------------- src/sqliteInt.h | 12 ++++++++---- src/trigger.c | 49 +++++++++++++++++++++++++++++++++++++++++-------- src/vdbe.c | 14 ++++++++++++-- test/trace.test | 2 +- 7 files changed, 84 insertions(+), 39 deletions(-) diff --git a/manifest b/manifest index 0b31af5927..e45bddc5bc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sand\suse\sthe\sinternal\ssqlite3DbSpanDup()\sinterface. -D 2017-12-27T19:43:22.931 +C Show\sthe\stext\sof\sindividual\sstatements\swithin\sa\strigger,\sas\sthey\nexecute,\sas\scomments\sin\sthe\soutput\sfrom\ssqlite3_trace()\sand\ssqlite3_trace_v2(). +D 2017-12-27T20:38:35.013 F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69 @@ -467,7 +467,7 @@ F src/os_win.c 0a4afa35cc8e812000df3ea2f64b476131b39e29e75d8007d0504726e4761de4 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c 07cf850241667874fcce9d7d924c814305e499b26c804322e2261247b5921903 F src/pager.h 581698f2177e8bd4008fe4760898ce20b6133d1df22139b9101b5155f900df7a -F src/parse.y 2b0653fd44534d941ff5289f372fedfc213e78c4698e28334d073cf4cfd146f2 +F src/parse.y 44cbbc3e132ea128258eff7be7f6d5c5dfa25522f89ec8b5501276966511bd50 F src/pcache.c 7ae91a4557a43d77d449accbfdc68846e6516f8e2eda46e8bbe4536fb669b201 F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170 F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880 @@ -483,7 +483,7 @@ F src/shell.c.in f3ec8f90dd698ea98781a90642c91eacbc24f4e55bb551c7b2762000d3ef55d F src/sqlite.h.in b4dc75265ed04b98e2184011a7dd0054ce2137ff84867a6be8b4f3bdfbc03d30 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34 -F src/sqliteInt.h 707e078db16dafad27401bb023da2dd12bafb0a2a421900ef4a1ff1e38c2b01f +F src/sqliteInt.h 394655443ab2ee9bde2c2f629bd1e613d5ee211dd6c16995f68e6014bbe60b5d F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 9737ed017279a9e0c5da748701c3c7bf1e8ae0dae459aad20dd64fcff97a7e35 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -542,12 +542,12 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c 1003d6d90c6783206c711f0a9397656fa5b055209f4d092caa43bb3bf5215db5 F src/treeview.c eae35972ff44f67064de2eaf35f04afe94e7aea3271a8b3bcebb3f954880fec3 -F src/trigger.c 775053eecf6b73062e243404b56f5064446254d5cce17d8704d5cdffd72a546a +F src/trigger.c 5fa038ae62adae53b62776bacc34dc56191385eedac79d49264389620ddc2526 F src/update.c 961bd1265d4d1e5cd65c9a54fa5122fb7aefcb003fcf2de0c092fceb7e58972c F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c 7315e97a8dc2c8e19ca64196c652cf0a65d13fd0a211b2cec082062372dc6261 F src/vacuum.c 90839322fd5f00df9617eb21b68beda9b6e2a2937576b0d65985e4aeb1c53739 -F src/vdbe.c 3393b508d9ad084ffce232a7c53e375ef5ac99b50b685c5131fcdfce97a9d534 +F src/vdbe.c e0a1ca7539d7071d5fa582bdf27195a51197b5ae1ab0f143888b1561df592fd0 F src/vdbe.h d50cadf12bcf9fb99117ef392ce1ea283aa429270481426b6e8b0280c101fd97 F src/vdbeInt.h 1fe00770144c12c4913128f35262d11527ef3284561baaab59b947a41c08d0d9 F src/vdbeapi.c 9c670ca0dcc1cd86373aa353b747b26fe531ca5cd4331690c611d1f03842e2a1 @@ -1443,7 +1443,7 @@ F test/tkt3997.test a335fa41ca3985660a139df7b734a26ef53284bd F test/tkt4018.test 18dbc6617f7a4b90e938d1bd6d26ad18daafaf08 F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7 F test/tpch01.test 04adbf8d8300fa60a222f28d901abd76e7be6dd4 -F test/trace.test 6f676313e3ebd2a50585036d2f212a3319dd5836 +F test/trace.test a659a9862957f4789e37a92b3bf6d2caf5c86b02cdeefc41e850ae53acf6992a F test/trace2.test f5cb67ad3bc09e0c58e8cca78dfd0b5639259983 F test/trace3.test 56ab944fddacf628b118cc298503fc45c2e50ab0 F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6 @@ -1687,7 +1687,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 76373091354f27577e5235e96cfaa4b31429a38d1e0e1d6e094c4cc323b92a0a -R 913c4466610a0123883763647119d1c7 +P a8e1545cb7aacb6a26a8c92a3ad4a3d584d150c3a00d2828c8adbb1ee19fcb6d +R 0ae5195579783355d0e4696ba0c5bdad U drh -Z 28dbbdc669e3541be1657ab76b942c72 +Z 4ebaaf3c94dd44dc4a2d0b266bee40f3 diff --git a/manifest.uuid b/manifest.uuid index 9cbf31ff1c..49211259e2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a8e1545cb7aacb6a26a8c92a3ad4a3d584d150c3a00d2828c8adbb1ee19fcb6d \ No newline at end of file +fe3d2b97d8945e6a9636472f77bcdc92cc5dda8b3e6e3a4fcbdd0a212ea5b9aa \ No newline at end of file diff --git a/src/parse.y b/src/parse.y index fe2251db4b..e780f8c3ab 100644 --- a/src/parse.y +++ b/src/parse.y @@ -288,11 +288,8 @@ signed ::= minus_num. // %type scanpt {const char*} scanpt(A) ::= . { - if( yyLookahead!=YYNOCODE ){ - A = yyLookaheadToken.z; - }else{ - A = pParse->sLastToken.z + pParse->sLastToken.n; - } + assert( yyLookahead!=YYNOCODE ); + A = yyLookaheadToken.z; } // "carglist" is a list of additional constraints that come after the @@ -1371,20 +1368,21 @@ tridxby ::= NOT INDEXED. { %destructor trigger_cmd {sqlite3DeleteTriggerStep(pParse->db, $$);} // UPDATE trigger_cmd(A) ::= - UPDATE orconf(R) trnm(X) tridxby SET setlist(Y) where_opt(Z). - {A = sqlite3TriggerUpdateStep(pParse->db, &X, Y, Z, R);} + UPDATE(B) orconf(R) trnm(X) tridxby SET setlist(Y) where_opt(Z) scanpt(E). + {A = sqlite3TriggerUpdateStep(pParse->db, &X, Y, Z, R, B.z, E);} // INSERT -trigger_cmd(A) ::= insert_cmd(R) INTO trnm(X) idlist_opt(F) select(S). - {A = sqlite3TriggerInsertStep(pParse->db, &X, F, S, R);/*A-overwrites-R*/} +trigger_cmd(A) ::= scanpt(B) insert_cmd(R) INTO + trnm(X) idlist_opt(F) select(S) scanpt(Z). + {A = sqlite3TriggerInsertStep(pParse->db,&X,F,S,R,B,Z);/*A-overwrites-R*/} // DELETE -trigger_cmd(A) ::= DELETE FROM trnm(X) tridxby where_opt(Y). - {A = sqlite3TriggerDeleteStep(pParse->db, &X, Y);} +trigger_cmd(A) ::= DELETE(B) FROM trnm(X) tridxby where_opt(Y) scanpt(E). + {A = sqlite3TriggerDeleteStep(pParse->db, &X, Y, B.z, E);} // SELECT -trigger_cmd(A) ::= select(X). - {A = sqlite3TriggerSelectStep(pParse->db, X); /*A-overwrites-X*/} +trigger_cmd(A) ::= scanpt(B) select(X) scanpt(E). + {A = sqlite3TriggerSelectStep(pParse->db, X, B, E); /*A-overwrites-X*/} // The special RAISE expression that may occur in trigger programs expr(A) ::= RAISE LP IGNORE RP. { diff --git a/src/sqliteInt.h b/src/sqliteInt.h index a51bae25c1..b11b5a8ada 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3203,6 +3203,7 @@ struct TriggerStep { Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */ ExprList *pExprList; /* SET clause for UPDATE. */ IdList *pIdList; /* Column names for INSERT */ + char *zSpan; /* Original SQL text of this command */ TriggerStep *pNext; /* Next in the link-list */ TriggerStep *pLast; /* Last element in link-list. Valid for 1st elem only */ }; @@ -3903,11 +3904,14 @@ void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int); void sqlite3CodeRowTriggerDirect(Parse *, Trigger *, Table *, int, int, int); void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*); void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*); - TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*); + TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*, + const char*,const char*); TriggerStep *sqlite3TriggerInsertStep(sqlite3*,Token*, IdList*, - Select*,u8); - TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8); - TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*); + Select*,u8,const char*,const char*); + TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8, + const char*,const char*); + TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*, + const char*,const char*); void sqlite3DeleteTrigger(sqlite3*, Trigger*); void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*); u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int); diff --git a/src/trigger.c b/src/trigger.c index d8aac2cc22..cf248a57bc 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -25,6 +25,7 @@ void sqlite3DeleteTriggerStep(sqlite3 *db, TriggerStep *pTriggerStep){ sqlite3ExprListDelete(db, pTmp->pExprList); sqlite3SelectDelete(db, pTmp->pSelect); sqlite3IdListDelete(db, pTmp->pIdList); + sqlite3DbFree(db, pTmp->zSpan); sqlite3DbFree(db, pTmp); } @@ -339,6 +340,17 @@ triggerfinish_cleanup: sqlite3DeleteTriggerStep(db, pStepList); } +/* +** Duplicate a range of text from an SQL statement, then convert all +** whitespace characters into ordinary space characters. +*/ +static char *triggerSpanDup(sqlite3 *db, const char *zStart, const char *zEnd){ + char *z = sqlite3DbSpanDup(db, zStart, zEnd); + int i; + if( z ) for(i=0; z[i]; i++) if( sqlite3Isspace(z[i]) ) z[i] = ' '; + return z; +} + /* ** Turn a SELECT statement (that the pSelect parameter points to) into ** a trigger step. Return a pointer to a TriggerStep structure. @@ -346,7 +358,12 @@ triggerfinish_cleanup: ** The parser calls this routine when it finds a SELECT statement in ** body of a TRIGGER. */ -TriggerStep *sqlite3TriggerSelectStep(sqlite3 *db, Select *pSelect){ +TriggerStep *sqlite3TriggerSelectStep( + sqlite3 *db, /* Database connection */ + Select *pSelect, /* The SELECT statement */ + const char *zStart, /* Start of SQL text */ + const char *zEnd /* End of SQL text */ +){ TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep)); if( pTriggerStep==0 ) { sqlite3SelectDelete(db, pSelect); @@ -355,6 +372,7 @@ TriggerStep *sqlite3TriggerSelectStep(sqlite3 *db, Select *pSelect){ pTriggerStep->op = TK_SELECT; pTriggerStep->pSelect = pSelect; pTriggerStep->orconf = OE_Default; + pTriggerStep->zSpan = triggerSpanDup(db, zStart, zEnd); return pTriggerStep; } @@ -367,7 +385,9 @@ TriggerStep *sqlite3TriggerSelectStep(sqlite3 *db, Select *pSelect){ static TriggerStep *triggerStepAllocate( sqlite3 *db, /* Database connection */ u8 op, /* Trigger opcode */ - Token *pName /* The target name */ + Token *pName, /* The target name */ + const char *zStart, /* Start of SQL text */ + const char *zEnd /* End of SQL text */ ){ TriggerStep *pTriggerStep; @@ -378,6 +398,7 @@ static TriggerStep *triggerStepAllocate( sqlite3Dequote(z); pTriggerStep->zTarget = z; pTriggerStep->op = op; + pTriggerStep->zSpan = triggerSpanDup(db, zStart, zEnd); } return pTriggerStep; } @@ -394,13 +415,15 @@ TriggerStep *sqlite3TriggerInsertStep( Token *pTableName, /* Name of the table into which we insert */ IdList *pColumn, /* List of columns in pTableName to insert into */ Select *pSelect, /* A SELECT statement that supplies values */ - u8 orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */ + u8 orconf, /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */ + const char *zStart, /* Start of SQL text */ + const char *zEnd /* End of SQL text */ ){ TriggerStep *pTriggerStep; assert(pSelect != 0 || db->mallocFailed); - pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName); + pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName, zStart, zEnd); if( pTriggerStep ){ pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); pTriggerStep->pIdList = pColumn; @@ -423,11 +446,13 @@ TriggerStep *sqlite3TriggerUpdateStep( Token *pTableName, /* Name of the table to be updated */ ExprList *pEList, /* The SET clause: list of column and new values */ Expr *pWhere, /* The WHERE clause */ - u8 orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */ + u8 orconf, /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */ + const char *zStart, /* Start of SQL text */ + const char *zEnd /* End of SQL text */ ){ TriggerStep *pTriggerStep; - pTriggerStep = triggerStepAllocate(db, TK_UPDATE, pTableName); + pTriggerStep = triggerStepAllocate(db, TK_UPDATE, pTableName, zStart, zEnd); if( pTriggerStep ){ pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE); pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); @@ -446,11 +471,13 @@ TriggerStep *sqlite3TriggerUpdateStep( TriggerStep *sqlite3TriggerDeleteStep( sqlite3 *db, /* Database connection */ Token *pTableName, /* The table from which rows are deleted */ - Expr *pWhere /* The WHERE clause */ + Expr *pWhere, /* The WHERE clause */ + const char *zStart, /* Start of SQL text */ + const char *zEnd /* End of SQL text */ ){ TriggerStep *pTriggerStep; - pTriggerStep = triggerStepAllocate(db, TK_DELETE, pTableName); + pTriggerStep = triggerStepAllocate(db, TK_DELETE, pTableName, zStart, zEnd); if( pTriggerStep ){ pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); pTriggerStep->orconf = OE_Default; @@ -705,6 +732,12 @@ static int codeTriggerProgram( pParse->eOrconf = (orconf==OE_Default)?pStep->orconf:(u8)orconf; assert( pParse->okConstFactor==0 ); +#ifndef SQLITE_OMIT_TRACE + sqlite3VdbeAddOp4(v, OP_Trace, 0x7fffffff, 1, 0, + sqlite3MPrintf(db, "-- %s", pStep->zSpan), + P4_DYNAMIC); +#endif + switch( pStep->op ){ case TK_UPDATE: { sqlite3Update(pParse, diff --git a/src/vdbe.c b/src/vdbe.c index cfe18a9d1e..1005560562 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -7016,7 +7016,13 @@ case OP_Function: { break; } - +/* Opcode: Trace P1 P2 * P4 * +** +** Write P4 on the statement trace output if statement tracing is +** enabled. +** +** Operand P1 must be 0x7fffffff and P2 must positive. +*/ /* Opcode: Init P1 P2 P3 P4 * ** Synopsis: Start at P2 ** @@ -7035,6 +7041,7 @@ case OP_Function: { ** If P3 is not zero, then it is an address to jump to if an SQLITE_CORRUPT ** error is encountered. */ +case OP_Trace: case OP_Init: { /* jump */ char *zTrace; int i; @@ -7049,7 +7056,9 @@ case OP_Init: { /* jump */ ** sqlite3_expanded_sql(P) otherwise. */ assert( pOp->p4.z==0 || strncmp(pOp->p4.z, "-" "- ", 3)==0 ); - assert( pOp==p->aOp ); /* Always instruction 0 */ + + /* OP_Init is always instruction 0 */ + assert( pOp==p->aOp || pOp->opcode==OP_Trace ); #ifndef SQLITE_OMIT_TRACE if( (db->mTrace & (SQLITE_TRACE_STMT|SQLITE_TRACE_LEGACY))!=0 @@ -7092,6 +7101,7 @@ case OP_Init: { /* jump */ #endif /* SQLITE_OMIT_TRACE */ assert( pOp->p2>0 ); if( pOp->p1>=sqlite3GlobalConfig.iOnceResetThreshold ){ + if( pOp->opcode==OP_Trace ) break; for(i=1; inOp; i++){ if( p->aOp[i].opcode==OP_Once ) p->aOp[i].p1 = 0; } diff --git a/test/trace.test b/test/trace.test index fd51d7ab64..37914857fc 100644 --- a/test/trace.test +++ b/test/trace.test @@ -197,7 +197,7 @@ ifcapable trigger { UPDATE t1 SET a=a+1; } set TRACE_OUT - } {{UPDATE t1 SET a=a+1;} {-- TRIGGER r1t1} {-- TRIGGER r1t2} {-- TRIGGER r1t1} {-- TRIGGER r1t2} {-- TRIGGER r1t1} {-- TRIGGER r1t2}} + } {{UPDATE t1 SET a=a+1;} {-- TRIGGER r1t1} {-- UPDATE t2 SET a=new.a WHERE rowid=new.rowid} {-- TRIGGER r1t2} {-- SELECT 'hello'} {-- TRIGGER r1t1} {-- UPDATE t2 SET a=new.a WHERE rowid=new.rowid} {-- TRIGGER r1t2} {-- SELECT 'hello'} {-- TRIGGER r1t1} {-- UPDATE t2 SET a=new.a WHERE rowid=new.rowid} {-- TRIGGER r1t2} {-- SELECT 'hello'}} } # With 3.6.21, we add the ability to expand host parameters in the trace From e307e11d0a38163d332554f54632d7b8eeb78d5d Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 27 Dec 2017 21:30:34 +0000 Subject: [PATCH 22/40] Omit all sqlite3_trace() output from the triggers associated with foreign key constraints. FossilOrigin-Name: fda08e3d10cc850664a356efdafcfc68187053849e1b00991b0b35d892a6776b --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/trigger.c | 16 ++++++++++------ test/fkey1.test | 14 ++++++++++++++ 4 files changed, 32 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index e45bddc5bc..ea3a94013a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Show\sthe\stext\sof\sindividual\sstatements\swithin\sa\strigger,\sas\sthey\nexecute,\sas\scomments\sin\sthe\soutput\sfrom\ssqlite3_trace()\sand\ssqlite3_trace_v2(). -D 2017-12-27T20:38:35.013 +C Omit\sall\ssqlite3_trace()\soutput\sfrom\sthe\striggers\sassociated\swith\nforeign\skey\sconstraints. +D 2017-12-27T21:30:34.358 F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69 @@ -542,7 +542,7 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c 1003d6d90c6783206c711f0a9397656fa5b055209f4d092caa43bb3bf5215db5 F src/treeview.c eae35972ff44f67064de2eaf35f04afe94e7aea3271a8b3bcebb3f954880fec3 -F src/trigger.c 5fa038ae62adae53b62776bacc34dc56191385eedac79d49264389620ddc2526 +F src/trigger.c a34539c69433276d37b0da9a89c117726ff2d292c0902895af1f393a983cd3a1 F src/update.c 961bd1265d4d1e5cd65c9a54fa5122fb7aefcb003fcf2de0c092fceb7e58972c F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c 7315e97a8dc2c8e19ca64196c652cf0a65d13fd0a211b2cec082062372dc6261 @@ -788,7 +788,7 @@ F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79 F test/fallocate.test 87b5e43c872b7e69cd80b7b8813eb102b571a75d45dda24e38b65537bcc85733 F test/filectrl.test 6e871c2d35dead1d9a88e176e8d2ca094fec6bb3 F test/filefmt.test f393e80c4b8d493b7a7f8f3809a8425bbf4292af1f5140f01cb1427798a2bbd4 -F test/fkey1.test ba64806ff9a04eecab2679caad377ae99a5e94e4 +F test/fkey1.test 9d7e3a0d409e7f64ab077af3b4fc5e5ce1a4e8d8f1272b65b9d93480aeb1fa2b F test/fkey2.test 155809016fad6b2a1491facf2ac53a551bc57c2c F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49 F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d @@ -1687,7 +1687,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P a8e1545cb7aacb6a26a8c92a3ad4a3d584d150c3a00d2828c8adbb1ee19fcb6d -R 0ae5195579783355d0e4696ba0c5bdad +P fe3d2b97d8945e6a9636472f77bcdc92cc5dda8b3e6e3a4fcbdd0a212ea5b9aa +R 22de62f1b2836f49ea0af57f6725c723 U drh -Z 4ebaaf3c94dd44dc4a2d0b266bee40f3 +Z 3aa637606646f6f00ff3a9a21b2a3987 diff --git a/manifest.uuid b/manifest.uuid index 49211259e2..2b2a68d7fa 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fe3d2b97d8945e6a9636472f77bcdc92cc5dda8b3e6e3a4fcbdd0a212ea5b9aa \ No newline at end of file +fda08e3d10cc850664a356efdafcfc68187053849e1b00991b0b35d892a6776b \ No newline at end of file diff --git a/src/trigger.c b/src/trigger.c index cf248a57bc..9f7bff5052 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -733,9 +733,11 @@ static int codeTriggerProgram( assert( pParse->okConstFactor==0 ); #ifndef SQLITE_OMIT_TRACE - sqlite3VdbeAddOp4(v, OP_Trace, 0x7fffffff, 1, 0, - sqlite3MPrintf(db, "-- %s", pStep->zSpan), - P4_DYNAMIC); + if( pStep->zSpan ){ + sqlite3VdbeAddOp4(v, OP_Trace, 0x7fffffff, 1, 0, + sqlite3MPrintf(db, "-- %s", pStep->zSpan), + P4_DYNAMIC); + } #endif switch( pStep->op ){ @@ -878,9 +880,11 @@ static TriggerPrg *codeRowTrigger( pTab->zName )); #ifndef SQLITE_OMIT_TRACE - sqlite3VdbeChangeP4(v, -1, - sqlite3MPrintf(db, "-- TRIGGER %s", pTrigger->zName), P4_DYNAMIC - ); + if( pTrigger->zName ){ + sqlite3VdbeChangeP4(v, -1, + sqlite3MPrintf(db, "-- TRIGGER %s", pTrigger->zName), P4_DYNAMIC + ); + } #endif /* If one was specified, code the WHEN clause. If it evaluates to false diff --git a/test/fkey1.test b/test/fkey1.test index d9b038a022..2530327fce 100644 --- a/test/fkey1.test +++ b/test/fkey1.test @@ -171,6 +171,20 @@ do_catchsql_test fkey1-5.2 { INSERT OR REPLACE INTO t11 VALUES (2, 3); } {1 {FOREIGN KEY constraint failed}} +# Make sure sqlite3_trace() output works with triggers used to implement +# FK constraints +# +proc sqltrace {txt} { + global traceoutput + lappend traceoutput $txt +} +do_test fkey1-5.2.1 { + unset -nocomplain traceoutput + db trace sqltrace + catch {db eval {INSERT OR REPLACE INTO t11 VALUES(2,3);}} + set traceoutput +} {{INSERT OR REPLACE INTO t11 VALUES(2,3);} {INSERT OR REPLACE INTO t11 VALUES(2,3);} {INSERT OR REPLACE INTO t11 VALUES(2,3);}} + # A similar test to the above. do_execsql_test fkey1-5.3 { CREATE TABLE Foo ( From ee052a1c941920dab3fab38785fbf03237677b7a Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 29 Dec 2017 12:50:43 +0000 Subject: [PATCH 23/40] Add test cases for the undocumented behavior of duplicate columns on an INSERT or UPDATE. FossilOrigin-Name: f4349c0c26611de8a7d5beb99431a575cf531cdeb0ca2413efabcf0a61e6f424 --- manifest | 13 ++++++------- manifest.uuid | 2 +- test/misc1.test | 20 ++++++++++++++++++++ 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index d4345bd99c..3e7d60e06a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\soutput\sof\ssqlite3_trace()\snow\sshows\seach\scommand\sof\sa\strigger\sas\sit\sis\nevaluated.\s\sThis\sfeature\sinvolved\smajor\schanges\sto\sthe\sparser,\ssuch\sas\nremoving\sthe\sExprSpan\sobject\sand\sreplacing\sit\swith\sa\snew\smechanism\sfor\ncapturing\sthe\soriginal\sSQL\stext\sof\sphrases\sin\sthe\sinput\sSQL. -D 2017-12-27T22:09:53.804 +C Add\stest\scases\sfor\sthe\sundocumented\sbehavior\sof\sduplicate\scolumns\son\san\nINSERT\sor\sUPDATE. +D 2017-12-29T12:50:43.938 F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69 @@ -1061,7 +1061,7 @@ F test/minmax.test 6751e87b409fe11b02e70a306d846fa544e25a41 F test/minmax2.test dae92964ac87c1d2ef978c582e81a95e11c00f1cbef68980bfb2abaf10315063 F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354 F test/minmax4.test 936941484ebdceb8adec7c86b6cd9b6e5e897c1f -F test/misc1.test 76737c259537586355f45e2a1e121b6e91b5476c4604ad5c53d1abfcb3acf786 +F test/misc1.test 704ea2cc7e7b9deb622b37953f0e77d0879826e8c3bfc1d7a691528035405061 F test/misc2.test 00d7de54eda90e237fc9a38b9e5ccc769ebf6d4d F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d F test/misc4.test 0d8be3466adf123a7791a66ba2bc8e8d229e87f3 @@ -1687,8 +1687,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 1b22b42e59793af19c69a2e5f6822883cc2687d4a0d9b9280bbff885276c6baa fda08e3d10cc850664a356efdafcfc68187053849e1b00991b0b35d892a6776b -R 22de62f1b2836f49ea0af57f6725c723 -T +closed fda08e3d10cc850664a356efdafcfc68187053849e1b00991b0b35d892a6776b +P 0fdf97efe5df745510c6b4b377a8ee5683a3a237630bfbd0f56e57c7c6e5b246 +R 9fe2cb7c2c9b946d64749c1df6cc4954 U drh -Z e235709d3662d8065d80f758148733ed +Z 157cf27648c17a2b2af97b1730aa1c08 diff --git a/manifest.uuid b/manifest.uuid index cf17777f87..3c028df06d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0fdf97efe5df745510c6b4b377a8ee5683a3a237630bfbd0f56e57c7c6e5b246 \ No newline at end of file +f4349c0c26611de8a7d5beb99431a575cf531cdeb0ca2413efabcf0a61e6f424 \ No newline at end of file diff --git a/test/misc1.test b/test/misc1.test index 2acfa5c2dd..05b1b1980f 100644 --- a/test/misc1.test +++ b/test/misc1.test @@ -722,4 +722,24 @@ do_execsql_test misc1-26.0 { SELECT randomblob(min(max(coalesce(EXISTS (SELECT 1 FROM ( SELECT (SELECT 2147483647) NOT IN (SELECT 2147483649 UNION ALL SELECT DISTINCT -1) IN (SELECT 2147483649), 'fault', (SELECT ALL -1 INTERSECT SELECT 'experiments') IN (SELECT ALL 56.1 ORDER BY 'experiments' DESC) FROM (SELECT DISTINCT 2147483648, 'hardware' UNION ALL SELECT -2147483648, 'experiments' ORDER BY 2147483648 LIMIT 1 OFFSET 123456789.1234567899) GROUP BY (SELECT ALL 0 INTERSECT SELECT 'in') IN (SELECT DISTINCT 'experiments' ORDER BY zeroblob(1000) LIMIT 56.1 OFFSET -456) HAVING EXISTS (SELECT 'fault' EXCEPT SELECT DISTINCT 56.1) UNION SELECT 'The', 'The', 2147483649 UNION ALL SELECT DISTINCT 'hardware', 'first', 'experiments' ORDER BY 'hardware' LIMIT 123456789.1234567899 OFFSET -2147483647)) NOT IN (SELECT (SELECT DISTINCT (SELECT 'The') FROM abc ORDER BY EXISTS (SELECT -1 INTERSECT SELECT ALL NULL) ASC) IN (SELECT DISTINCT EXISTS (SELECT ALL 123456789.1234567899 ORDER BY 1 ASC, NULL DESC) FROM sqlite_master INTERSECT SELECT 456)), (SELECT ALL 'injection' UNION ALL SELECT ALL (SELECT DISTINCT 'first' UNION SELECT DISTINCT 'The') FROM (SELECT 456, 'in', 2147483649))),1), 500)), 'first', EXISTS (SELECT DISTINCT 456 FROM abc ORDER BY 'experiments' DESC) FROM abc; } {} +# 2017-12-29 +# +# The following behaviors (duplicate column names on an INSERT or UPDATE) +# are undocumented. These tests are added to ensure that historical behavior +# does not change accidentally. +# +# For duplication columns on an INSERT, the first value is used. +# For duplication columns on an UPDATE, the last value is used. +# +do_execsql_test misc1-27.0 { + CREATE TABLE dup1(a,b,c); + INSERT INTO dup1(a,b,c,a,b,c) VALUES(1,2,3,4,5,6); + SELECT a,b,c FROM dup1; +} {1 2 3} +do_execsql_test misc1-27.1 { + UPDATE dup1 SET a=7, b=8, c=9, a=10, b=11, c=12; + SELECT a,b,c FROM dup1; +} {10 11 12} + + finish_test From fe6d20e9f4d17ad82fd4c4cc69181ad5f52d9d93 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 29 Dec 2017 14:33:54 +0000 Subject: [PATCH 24/40] Enhance location(X) so that it works with indexes and WITHOUT ROWID tables. The function might return an offset to the main table or to an index, depending on whether the column X would be loaded from the main table or from the index. FossilOrigin-Name: dd94d6a880dfec4bddd247239b815b84964f804d24841e25f33f1d46a4b5274d --- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- src/btree.c | 3 +-- src/expr.c | 2 +- src/vdbe.c | 19 ++++++++++++------- src/where.c | 2 +- test/func6.test | 2 +- 7 files changed, 27 insertions(+), 23 deletions(-) diff --git a/manifest b/manifest index 89d90d3cf5..12c0ae8735 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\srecent\senhancements\sfrom\strunk. -D 2017-12-29T13:35:09.867 +C Enhance\slocation(X)\sso\sthat\sit\sworks\swith\sindexes\sand\sWITHOUT\sROWID\stables.\nThe\sfunction\smight\sreturn\san\soffset\sto\sthe\smain\stable\sor\sto\san\sindex,\ndepending\son\swhether\sthe\scolumn\sX\swould\sbe\sloaded\sfrom\sthe\smain\stable\sor\nfrom\sthe\sindex. +D 2017-12-29T14:33:54.266 F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69 @@ -420,7 +420,7 @@ F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73 F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca -F src/btree.c 6fba32ea06e9be55849dd486e88df6c467bf69cf306d38ca3c3a8df34e6499e9 +F src/btree.c 516fea6cad0d904ba1f7d599cb3d8ec9f14c2c6d1b71cf883dcef81d77bc6a5a F src/btree.h e9d22d0475b37422cc2db53f4336cc814645dcca8634bc4aae25ed52d043ef53 F src/btreeInt.h 55b702efce17e5d1941865464227d3802cfc9c7c832fac81d4c94dced47a71fc F src/build.c a03eb5a1cfff74784c24a4478ba5455711571936f1ac9d43f94fa7df57509977 @@ -431,7 +431,7 @@ F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957 F src/dbpage.c 8db4c97f630e7d83f884ea75caf1ffd0988c160e9d530194d93721c80821e0f6 F src/dbstat.c 7a4ba8518b6369ef3600c49cf9c918ad979acba610b2aebef1b656d649b96720 F src/delete.c 74667ad914ac143731a444a1bacf29ceb18f6eded8a0dd17aafae80baa07f8bb -F src/expr.c db1f29a1ee0c8a3abec55134ae7e149fa5684d77b569c6a62121b9e13becc43a +F src/expr.c 119aa8d492bfc05ecf73ff4160b48c65d696972b2c954149271a1363e795874b F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c d617daf66b5515e2b42c1405b2b4984c30ca50fb705ab164271a9bf66c69e331 F src/func.c a23ea9b8869ca47e20a273985013b36a2294788fde5abe1a610be4bb90c8e6e8 @@ -547,7 +547,7 @@ F src/update.c 961bd1265d4d1e5cd65c9a54fa5122fb7aefcb003fcf2de0c092fceb7e58972c F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c 7315e97a8dc2c8e19ca64196c652cf0a65d13fd0a211b2cec082062372dc6261 F src/vacuum.c 90839322fd5f00df9617eb21b68beda9b6e2a2937576b0d65985e4aeb1c53739 -F src/vdbe.c 742812438ab9c897db18025c6040af23feb4679fc63c53bdf25a9b190c7f91ec +F src/vdbe.c 42e79ef2da625fd8c4364bf952b0515760958775beb38cc9f9e84bcec4115964 F src/vdbe.h d50cadf12bcf9fb99117ef392ce1ea283aa429270481426b6e8b0280c101fd97 F src/vdbeInt.h 1fe00770144c12c4913128f35262d11527ef3284561baaab59b947a41c08d0d9 F src/vdbeapi.c 9c670ca0dcc1cd86373aa353b747b26fe531ca5cd4331690c611d1f03842e2a1 @@ -561,7 +561,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 5a3f464edd64596f601683ed321d12e6fd93c5fb9afdfb3653d6ffd0fee9c48f F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a F src/walker.c da987a20d40145c0a03c07d8fefcb2ed363becc7680d0500d9c79915591f5b1f -F src/where.c 5876c9100b622f7b9e5ee7f579b8b6a71ae5ba627724cea4546d9114c32b3cb5 +F src/where.c 9c1fca74de02cf5d8ac6437fc385b683e194c403a2ae675eb4f15a5c19086726 F src/whereInt.h 82c04c5075308abbac59180c8bad5ecb45b07453981f60a53f3c7dee21e1e971 F src/wherecode.c af1e79154aaa88cd802d6f2e5b945f67eaca7c958d1525fbf8ee19d5bd7b9020 F src/whereexpr.c 427ea8e96ec24f2a7814c67b8024ad664a9c7656264c4566c34743cb23186e46 @@ -917,7 +917,7 @@ F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f F test/func3.test d202a7606d23f90988a664e88e268aed1087c11c F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f F test/func5.test cdd224400bc3e48d891827cc913a57051a426fa4 -F test/func6.test 5d4b0526f5013db07e2f6de43df42d990500f636fa32258cfac0c87113a1c1ce +F test/func6.test afd2f720b333f0fbbb220887b3f1b3637ef9bfde47015f664e9bb4ba14a01535 F test/fuzz-oss1.test e58330d01cbbd8215ee636b17a03fe220b37dbfa F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1 F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1 @@ -1688,7 +1688,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 51be9558164301c5dd4df23ab8b3e67de0b522f8d36f79f3d84d45d3dc2a83a4 f4349c0c26611de8a7d5beb99431a575cf531cdeb0ca2413efabcf0a61e6f424 -R 21534cc483241840a2ab1c4e82c69566 +P 6251e438f2a76170fd1e95aa512a46086ed88ab93b9b97a1dba97c4558689305 +R f543ccd2667c3e9285e509d3e9a274bf U drh -Z 27f7d54e41b653412b0ccbce7bf65d00 +Z e0ddcaae57472f72e53764b52bf6363b diff --git a/manifest.uuid b/manifest.uuid index c839229c61..b83335d6cc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6251e438f2a76170fd1e95aa512a46086ed88ab93b9b97a1dba97c4558689305 \ No newline at end of file +dd94d6a880dfec4bddd247239b815b84964f804d24841e25f33f1d46a4b5274d \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index d17cbde846..a8d91cc0c9 100644 --- a/src/btree.c +++ b/src/btree.c @@ -4439,9 +4439,8 @@ i64 sqlite3BtreeIntegerKey(BtCursor *pCur){ i64 sqlite3BtreeLocation(BtCursor *pCur){ assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); - assert( pCur->curIntKey ); getCellInfo(pCur); - return (i64)pCur->pBt->pageSize*(i64)pCur->pPage->pgno + + return (i64)pCur->pBt->pageSize*((i64)pCur->pPage->pgno - 1) + (i64)(pCur->info.pPayload - pCur->pPage->aData); } diff --git a/src/expr.c b/src/expr.c index dbfc1b7ed3..dd7d548edc 100644 --- a/src/expr.c +++ b/src/expr.c @@ -3873,7 +3873,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ if( pDef->funcFlags & SQLITE_FUNC_LOCATION ){ Expr *pArg = pFarg->a[0].pExpr; if( pArg->op==TK_COLUMN ){ - sqlite3VdbeAddOp2(v, OP_Location, pArg->iTable, target); + sqlite3VdbeAddOp3(v, OP_Location, pArg->iTable, pArg->iColumn,target); }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, target); } diff --git a/src/vdbe.c b/src/vdbe.c index 975a098198..68762ae5e1 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2349,22 +2349,27 @@ case OP_IfNullRow: { /* jump */ break; } -/* Opcode: Location P1 P2 * * * -** Synopsis: r[P2] = location(P1) +/* Opcode: Location P1 P2 P3 * * +** Synopsis: r[P3] = location(P1) ** -** Store in register r[P2] the location in the database file that is the +** Store in register r[P3] the location in the database file that is the ** start of the payload for the record at which that cursor P1 is currently ** pointing. +** +** P2 is the column number for the argument to the location() function. +** This opcode does not use P2 itself, but the P2 value is used by the +** code generator. The P1, P2, and P3 operands to this opcode are the +** as as for OP_Column. */ -case OP_Location: { /* out2 */ +case OP_Location: { /* out3 */ VdbeCursor *pC; /* The VDBE cursor */ assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; - pOut = out2Prerelease(p, pOp); + pOut = &p->aMem[pOp->p3]; if( pC==0 || pC->eCurType!=CURTYPE_BTREE ){ - pOut->flags = MEM_Null; + sqlite3VdbeMemSetNull(pOut); }else{ - pOut->u.i = sqlite3BtreeLocation(pC->uc.pCursor); + sqlite3VdbeMemSetInt64(pOut, sqlite3BtreeLocation(pC->uc.pCursor)); } break; } diff --git a/src/where.c b/src/where.c index d3aec354ba..146c8124c8 100644 --- a/src/where.c +++ b/src/where.c @@ -5146,7 +5146,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ pOp = sqlite3VdbeGetOp(v, k); for(; kp1!=pLevel->iTabCur ) continue; - if( pOp->opcode==OP_Column ){ + if( pOp->opcode==OP_Column || pOp->opcode==OP_Location ){ int x = pOp->p2; assert( pIdx->pTable==pTab ); if( !HasRowid(pTab) ){ diff --git a/test/func6.test b/test/func6.test index 5350aeaa7b..3630aa33db 100644 --- a/test/func6.test +++ b/test/func6.test @@ -28,7 +28,7 @@ do_execsql_test func6-120 { do_execsql_test func6-130 { CREATE INDEX t1a ON t1(a); SELECT a, typeof(location(a)) FROM t1 ORDER BY a LIMIT 2; -} {abc001 null abc002 null} +} {abc001 integer abc002 integer} do_execsql_test func6-140 { SELECT a, typeof(location(a)) FROM t1 NOT INDEXED ORDER BY a LIMIT 2; } {abc001 integer abc002 integer} From 092457b18ce71b6b0f30ea8a67817310feffaebc Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 29 Dec 2017 15:04:49 +0000 Subject: [PATCH 25/40] Change the function name to sqlite_unsupported_offset(X). Only enable the function if compiled with -DSQLITE_ENABLE_OFFSET_SQL_FUNC. The makefiles add that definition to shell builds. FossilOrigin-Name: 7a7f826e324b1a2c332e2f1d0740fd0babffcaca6275a798572f02ad367b99ab --- Makefile.in | 1 + Makefile.msc | 1 + main.mk | 1 + manifest | 34 +++++++++++++++++----------------- manifest.uuid | 2 +- src/btree.c | 4 +++- src/btree.h | 4 +++- src/expr.c | 9 ++++++--- src/func.c | 5 ++++- src/sqliteInt.h | 2 +- src/test_config.c | 6 ++++++ src/vdbe.c | 17 +++++++++++------ src/where.c | 6 +++++- test/func6.test | 18 +++++++++++++----- 14 files changed, 73 insertions(+), 37 deletions(-) diff --git a/Makefile.in b/Makefile.in index 009ab2e061..3c9e7b3a96 100644 --- a/Makefile.in +++ b/Makefile.in @@ -582,6 +582,7 @@ SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION SHELL_OPT += -DSQLITE_ENABLE_STMTVTAB SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB +SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1 FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000 diff --git a/Makefile.msc b/Makefile.msc index 652bd81fd0..94fa32dc3a 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -1513,6 +1513,7 @@ FUZZDATA = \ !IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0 SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_STMTVTAB SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_DBSTAT_VTAB +SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_EANBLE_OFFSET_SQL_FUNC !ENDIF # <> diff --git a/main.mk b/main.mk index 8692450441..b46ffa1a52 100644 --- a/main.mk +++ b/main.mk @@ -509,6 +509,7 @@ SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION SHELL_OPT += -DSQLITE_ENABLE_STMTVTAB SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB +SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1 FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000 diff --git a/manifest b/manifest index 12c0ae8735..1328eaf9ce 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Enhance\slocation(X)\sso\sthat\sit\sworks\swith\sindexes\sand\sWITHOUT\sROWID\stables.\nThe\sfunction\smight\sreturn\san\soffset\sto\sthe\smain\stable\sor\sto\san\sindex,\ndepending\son\swhether\sthe\scolumn\sX\swould\sbe\sloaded\sfrom\sthe\smain\stable\sor\nfrom\sthe\sindex. -D 2017-12-29T14:33:54.266 -F Makefile.in ceb40bfcb30ebba8e1202b34c56ff7e13e112f9809e2381d99be32c2726058f5 +C Change\sthe\sfunction\sname\sto\ssqlite_unsupported_offset(X).\s\sOnly\senable\sthe\nfunction\sif\scompiled\swith\s-DSQLITE_ENABLE_OFFSET_SQL_FUNC.\s\sThe\smakefiles\sadd\nthat\sdefinition\sto\sshell\sbuilds. +D 2017-12-29T15:04:49.734 +F Makefile.in 804c347948b0ad5a962aea3e59413e897227e0173d0e76910f11f473e6c7ae9b F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc 6480671f7c129e61208d69492b3c71ce4310d49fceac83cfb17f1c081e242b69 +F Makefile.msc f11644a365122b16628da7839a8ed2e3a781b578a94cb1ebd25ebad260bdc9c2 F README.md eeae1e552f93ef72ef7c5b8f6647b368a001c28820ad1df179d3dae602bef681 F VERSION 0c10cdfed866fdd2d80434f64f042c3330f1daaed12e54287beb104f04b3faaf F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -401,7 +401,7 @@ F ext/userauth/userauth.c 3410be31283abba70255d71fd24734e017a4497f F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk 50bac9920024b5485f06398b3980f09e97ab28cd4b5b6dcd829d2a5e3ce22e7a +F main.mk b5f569262e4f8111bb8cf6110784b8210fe14ea45f6c7ea50fb4230ebe7a4880 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 @@ -420,8 +420,8 @@ F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73 F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca -F src/btree.c 516fea6cad0d904ba1f7d599cb3d8ec9f14c2c6d1b71cf883dcef81d77bc6a5a -F src/btree.h e9d22d0475b37422cc2db53f4336cc814645dcca8634bc4aae25ed52d043ef53 +F src/btree.c 0a1f63b50ab1ac5d4b1637c30cb1ae123fbc162ec8cb6336ddb9491a0bc1e363 +F src/btree.h 0866c0a08255142ea0e754aabd211c843cab32045c978a592a43152405ed0c84 F src/btreeInt.h 55b702efce17e5d1941865464227d3802cfc9c7c832fac81d4c94dced47a71fc F src/build.c a03eb5a1cfff74784c24a4478ba5455711571936f1ac9d43f94fa7df57509977 F src/callback.c fe677cb5f5abb02f7a772a62a98c2f516426081df68856e8f2d5f950929b966a @@ -431,10 +431,10 @@ F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957 F src/dbpage.c 8db4c97f630e7d83f884ea75caf1ffd0988c160e9d530194d93721c80821e0f6 F src/dbstat.c 7a4ba8518b6369ef3600c49cf9c918ad979acba610b2aebef1b656d649b96720 F src/delete.c 74667ad914ac143731a444a1bacf29ceb18f6eded8a0dd17aafae80baa07f8bb -F src/expr.c 119aa8d492bfc05ecf73ff4160b48c65d696972b2c954149271a1363e795874b +F src/expr.c ad6e7a9c34a4bab9d10cc857d647ae7ce370a633b5c0bfa71f1c29b81ae364b8 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c d617daf66b5515e2b42c1405b2b4984c30ca50fb705ab164271a9bf66c69e331 -F src/func.c a23ea9b8869ca47e20a273985013b36a2294788fde5abe1a610be4bb90c8e6e8 +F src/func.c 697a3ee3b8c8481db497226e9e71935727d6a9fb3d3cc049e82a1c717a0a8342 F src/global.c ac3094f1dc59fbeb919aef7cc0cc827a8459d1fb1adb7972ef75bd9e0c10b75b F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4 @@ -483,7 +483,7 @@ F src/shell.c.in f3ec8f90dd698ea98781a90642c91eacbc24f4e55bb551c7b2762000d3ef55d F src/sqlite.h.in b4dc75265ed04b98e2184011a7dd0054ce2137ff84867a6be8b4f3bdfbc03d30 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34 -F src/sqliteInt.h 623712d1ae728cc0ca78c9d8985b9665d89afff3082c1b664cbba08b0b01476d +F src/sqliteInt.h fd8702c65994d7de3e2d8f7d85d958731da1ed29476571fdfa2290fd8ec0bf80 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 9737ed017279a9e0c5da748701c3c7bf1e8ae0dae459aad20dd64fcff97a7e35 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -503,7 +503,7 @@ F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0 F src/test_bestindex.c 78809f11026f18a93fcfd798d9479cba37e1201c830260bf1edc674b2fa9b857 F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274 -F src/test_config.c 3904a8682aac58b77d20ca236face2b11e50781be4116004ba1ba79f69896ec9 +F src/test_config.c cc8a1d44648d9392a14f4ecfc841d027daaf61f952b9f70792edf11373aaa3dd F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f F src/test_demovfs.c a0c3bdd45ed044115c2c9f7779e56eafff18741e F src/test_devsym.c 1960abbb234b97e9b920f07e99503fc04b443f62bbc3c6ff2c2cea2133e3b8a2 @@ -547,7 +547,7 @@ F src/update.c 961bd1265d4d1e5cd65c9a54fa5122fb7aefcb003fcf2de0c092fceb7e58972c F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c 7315e97a8dc2c8e19ca64196c652cf0a65d13fd0a211b2cec082062372dc6261 F src/vacuum.c 90839322fd5f00df9617eb21b68beda9b6e2a2937576b0d65985e4aeb1c53739 -F src/vdbe.c 42e79ef2da625fd8c4364bf952b0515760958775beb38cc9f9e84bcec4115964 +F src/vdbe.c cb3b5035f337c9fed4a0170ca20325dc4500b832c57d00561310cbb78149a73c F src/vdbe.h d50cadf12bcf9fb99117ef392ce1ea283aa429270481426b6e8b0280c101fd97 F src/vdbeInt.h 1fe00770144c12c4913128f35262d11527ef3284561baaab59b947a41c08d0d9 F src/vdbeapi.c 9c670ca0dcc1cd86373aa353b747b26fe531ca5cd4331690c611d1f03842e2a1 @@ -561,7 +561,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 5a3f464edd64596f601683ed321d12e6fd93c5fb9afdfb3653d6ffd0fee9c48f F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a F src/walker.c da987a20d40145c0a03c07d8fefcb2ed363becc7680d0500d9c79915591f5b1f -F src/where.c 9c1fca74de02cf5d8ac6437fc385b683e194c403a2ae675eb4f15a5c19086726 +F src/where.c 36b92103f726609cc3dbe07c619426bd6886bede455de56ccff54c8e567f5582 F src/whereInt.h 82c04c5075308abbac59180c8bad5ecb45b07453981f60a53f3c7dee21e1e971 F src/wherecode.c af1e79154aaa88cd802d6f2e5b945f67eaca7c958d1525fbf8ee19d5bd7b9020 F src/whereexpr.c 427ea8e96ec24f2a7814c67b8024ad664a9c7656264c4566c34743cb23186e46 @@ -917,7 +917,7 @@ F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f F test/func3.test d202a7606d23f90988a664e88e268aed1087c11c F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f F test/func5.test cdd224400bc3e48d891827cc913a57051a426fa4 -F test/func6.test afd2f720b333f0fbbb220887b3f1b3637ef9bfde47015f664e9bb4ba14a01535 +F test/func6.test 8a6ecb974a9d0bdeef6a06aff8e305b1667c3b922103037735b39c716360ebc2 F test/fuzz-oss1.test e58330d01cbbd8215ee636b17a03fe220b37dbfa F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1 F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1 @@ -1688,7 +1688,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 6251e438f2a76170fd1e95aa512a46086ed88ab93b9b97a1dba97c4558689305 -R f543ccd2667c3e9285e509d3e9a274bf +P dd94d6a880dfec4bddd247239b815b84964f804d24841e25f33f1d46a4b5274d +R 78409e335314d524c66761480a13a3e4 U drh -Z e0ddcaae57472f72e53764b52bf6363b +Z 5cd44f60a8e786e38b3cacae6fe91794 diff --git a/manifest.uuid b/manifest.uuid index b83335d6cc..9bbedd7b51 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -dd94d6a880dfec4bddd247239b815b84964f804d24841e25f33f1d46a4b5274d \ No newline at end of file +7a7f826e324b1a2c332e2f1d0740fd0babffcaca6275a798572f02ad367b99ab \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index a8d91cc0c9..8cd5ee6739 100644 --- a/src/btree.c +++ b/src/btree.c @@ -4432,17 +4432,19 @@ i64 sqlite3BtreeIntegerKey(BtCursor *pCur){ return pCur->info.nKey; } +#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC /* ** Return the offset into the database file for the start of the ** payload to which the cursor is pointing. */ -i64 sqlite3BtreeLocation(BtCursor *pCur){ +i64 sqlite3BtreeOffset(BtCursor *pCur){ assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); getCellInfo(pCur); return (i64)pCur->pBt->pageSize*((i64)pCur->pPage->pgno - 1) + (i64)(pCur->info.pPayload - pCur->pPage->aData); } +#endif /* SQLITE_ENABLE_OFFSET_SQL_FUNC */ /* ** Return the number of bytes of payload for the entry that pCur is diff --git a/src/btree.h b/src/btree.h index 43c0b9a8a4..e8e114bd2a 100644 --- a/src/btree.h +++ b/src/btree.h @@ -291,7 +291,9 @@ int sqlite3BtreeNext(BtCursor*, int flags); int sqlite3BtreeEof(BtCursor*); int sqlite3BtreePrevious(BtCursor*, int flags); i64 sqlite3BtreeIntegerKey(BtCursor*); -i64 sqlite3BtreeLocation(BtCursor*); +#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC +i64 sqlite3BtreeOffset(BtCursor*); +#endif int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*); const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt); u32 sqlite3BtreePayloadSize(BtCursor*); diff --git a/src/expr.c b/src/expr.c index dd7d548edc..32cc4423fa 100644 --- a/src/expr.c +++ b/src/expr.c @@ -3870,14 +3870,17 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ if( !pColl ) pColl = db->pDfltColl; sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ); } - if( pDef->funcFlags & SQLITE_FUNC_LOCATION ){ +#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC + if( pDef->funcFlags & SQLITE_FUNC_OFFSET ){ Expr *pArg = pFarg->a[0].pExpr; if( pArg->op==TK_COLUMN ){ - sqlite3VdbeAddOp3(v, OP_Location, pArg->iTable, pArg->iColumn,target); + sqlite3VdbeAddOp3(v, OP_Offset, pArg->iTable, pArg->iColumn, target); }else{ sqlite3VdbeAddOp2(v, OP_Null, 0, target); } - }else{ + }else +#endif + { sqlite3VdbeAddOp4(v, pParse->iSelfTab ? OP_PureFunc0 : OP_Function0, constMask, r1, target, (char*)pDef, P4_FUNCDEF); sqlite3VdbeChangeP5(v, (u8)nFarg); diff --git a/src/func.c b/src/func.c index f81c4865d8..4758b0191d 100644 --- a/src/func.c +++ b/src/func.c @@ -1799,8 +1799,11 @@ void sqlite3RegisterBuiltinFunctions(void){ #ifdef SQLITE_DEBUG FUNCTION2(affinity, 1, 0, 0, noopFunc, SQLITE_FUNC_AFFINITY), #endif - FUNCTION2(location, 1, 0, 0, noopFunc, SQLITE_FUNC_LOCATION| +#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC + FUNCTION2(sqlite_unsupported_offset, + 1, 0, 0, noopFunc, SQLITE_FUNC_OFFSET| SQLITE_FUNC_TYPEOF), +#endif FUNCTION(ltrim, 1, 1, 0, trimFunc ), FUNCTION(ltrim, 2, 1, 0, trimFunc ), FUNCTION(rtrim, 1, 2, 0, trimFunc ), diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 24a36e2c50..8e79133200 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1629,7 +1629,7 @@ struct FuncDestructor { #define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a ** single query - might change over time */ #define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */ -#define SQLITE_FUNC_LOCATION 0x8000 /* Built-in location() function */ +#define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */ /* ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are diff --git a/src/test_config.c b/src/test_config.c index 24a7287da2..ad63016baf 100644 --- a/src/test_config.c +++ b/src/test_config.c @@ -160,6 +160,12 @@ static void set_options(Tcl_Interp *interp){ Tcl_SetVar2(interp, "sqlite_options", "mem5", "0", TCL_GLOBAL_ONLY); #endif +#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC + Tcl_SetVar2(interp, "sqlite_options", "offset_sql_func","1",TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "offset_sql_func","0",TCL_GLOBAL_ONLY); +#endif + #ifdef SQLITE_ENABLE_PREUPDATE_HOOK Tcl_SetVar2(interp, "sqlite_options", "preupdate", "1", TCL_GLOBAL_ONLY); #else diff --git a/src/vdbe.c b/src/vdbe.c index 68762ae5e1..26336d940b 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2349,19 +2349,23 @@ case OP_IfNullRow: { /* jump */ break; } -/* Opcode: Location P1 P2 P3 * * -** Synopsis: r[P3] = location(P1) +#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC +/* Opcode: Offset P1 P2 P3 * * +** Synopsis: r[P3] = sqlite_offset(P1) ** -** Store in register r[P3] the location in the database file that is the +** Store in register r[P3] the byte offset into the database file that is the ** start of the payload for the record at which that cursor P1 is currently ** pointing. ** -** P2 is the column number for the argument to the location() function. +** P2 is the column number for the argument to the sqlite_offset() function. ** This opcode does not use P2 itself, but the P2 value is used by the ** code generator. The P1, P2, and P3 operands to this opcode are the ** as as for OP_Column. +** +** This opcode is only available if SQLite is compiled with the +** -DSQLITE_ENABLE_OFFSET_SQL_FUNC option. */ -case OP_Location: { /* out3 */ +case OP_Offset: { /* out3 */ VdbeCursor *pC; /* The VDBE cursor */ assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; @@ -2369,10 +2373,11 @@ case OP_Location: { /* out3 */ if( pC==0 || pC->eCurType!=CURTYPE_BTREE ){ sqlite3VdbeMemSetNull(pOut); }else{ - sqlite3VdbeMemSetInt64(pOut, sqlite3BtreeLocation(pC->uc.pCursor)); + sqlite3VdbeMemSetInt64(pOut, sqlite3BtreeOffset(pC->uc.pCursor)); } break; } +#endif /* SQLITE_ENABLE_OFFSET_SQL_FUNC */ /* Opcode: Column P1 P2 P3 P4 P5 ** Synopsis: r[P3]=PX diff --git a/src/where.c b/src/where.c index 146c8124c8..ec53527943 100644 --- a/src/where.c +++ b/src/where.c @@ -5146,7 +5146,11 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ pOp = sqlite3VdbeGetOp(v, k); for(; kp1!=pLevel->iTabCur ) continue; - if( pOp->opcode==OP_Column || pOp->opcode==OP_Location ){ + if( pOp->opcode==OP_Column +#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC + || pOp->opcode==OP_Offset +#endif + ){ int x = pOp->p2; assert( pIdx->pTable==pTab ); if( !HasRowid(pTab) ){ diff --git a/test/func6.test b/test/func6.test index 3630aa33db..ff05ee78c5 100644 --- a/test/func6.test +++ b/test/func6.test @@ -9,10 +9,14 @@ # #************************************************************************* # -# Test cases for the location() function. +# Test cases for the sqlite_unsupported_offset() function. # set testdir [file dirname $argv0] source $testdir/tester.tcl +ifcapable !offset_sql_func { + finish_test + return +} do_execsql_test func6-100 { CREATE TABLE t1(a,b,c,d); @@ -20,17 +24,21 @@ do_execsql_test func6-100 { INSERT INTO t1(a,b,c,d) SELECT printf('abc%03x',x), x, 1000-x, NULL FROM c; } do_execsql_test func6-110 { - SELECT a, typeof(location(a)) FROM t1 ORDER BY rowid LIMIT 2; + SELECT a, typeof(sqlite_unsupported_offset(a)) FROM t1 + ORDER BY rowid LIMIT 2; } {abc001 integer abc002 integer} do_execsql_test func6-120 { - SELECT a, typeof(location(+a)) FROM t1 ORDER BY rowid LIMIT 2; + SELECT a, typeof(sqlite_unsupported_offset(+a)) FROM t1 + ORDER BY rowid LIMIT 2; } {abc001 null abc002 null} do_execsql_test func6-130 { CREATE INDEX t1a ON t1(a); - SELECT a, typeof(location(a)) FROM t1 ORDER BY a LIMIT 2; + SELECT a, typeof(sqlite_unsupported_offset(a)) FROM t1 + ORDER BY a LIMIT 2; } {abc001 integer abc002 integer} do_execsql_test func6-140 { - SELECT a, typeof(location(a)) FROM t1 NOT INDEXED ORDER BY a LIMIT 2; + SELECT a, typeof(sqlite_unsupported_offset(a)) FROM t1 NOT INDEXED + ORDER BY a LIMIT 2; } {abc001 integer abc002 integer} finish_test From 23b440f8832a0d239d32008cb1f611508d88b89d Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 29 Dec 2017 15:19:03 +0000 Subject: [PATCH 26/40] Fix a typo in the MSVC makefile. FossilOrigin-Name: 89e5720a8d8d46d4e2f16f15678e91336117e64abc977174e2b345a30308d0d2 --- Makefile.msc | 2 +- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index 94fa32dc3a..27eb23a240 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -1513,7 +1513,7 @@ FUZZDATA = \ !IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0 SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_STMTVTAB SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_DBSTAT_VTAB -SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_EANBLE_OFFSET_SQL_FUNC +SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC !ENDIF # <> diff --git a/manifest b/manifest index 1328eaf9ce..3d0577aaea 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Change\sthe\sfunction\sname\sto\ssqlite_unsupported_offset(X).\s\sOnly\senable\sthe\nfunction\sif\scompiled\swith\s-DSQLITE_ENABLE_OFFSET_SQL_FUNC.\s\sThe\smakefiles\sadd\nthat\sdefinition\sto\sshell\sbuilds. -D 2017-12-29T15:04:49.734 +C Fix\sa\stypo\sin\sthe\sMSVC\smakefile. +D 2017-12-29T15:19:03.549 F Makefile.in 804c347948b0ad5a962aea3e59413e897227e0173d0e76910f11f473e6c7ae9b F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc f11644a365122b16628da7839a8ed2e3a781b578a94cb1ebd25ebad260bdc9c2 +F Makefile.msc 57dcce0595d4a0c4b94b6f6ba732b8e33540358adf5fb8e1aa8389d34a9677e8 F README.md eeae1e552f93ef72ef7c5b8f6647b368a001c28820ad1df179d3dae602bef681 F VERSION 0c10cdfed866fdd2d80434f64f042c3330f1daaed12e54287beb104f04b3faaf F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -1688,7 +1688,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P dd94d6a880dfec4bddd247239b815b84964f804d24841e25f33f1d46a4b5274d -R 78409e335314d524c66761480a13a3e4 +P 7a7f826e324b1a2c332e2f1d0740fd0babffcaca6275a798572f02ad367b99ab +R 0e2a4a2bb72ba4dcfe2f3a815db6ddb3 U drh -Z 5cd44f60a8e786e38b3cacae6fe91794 +Z 9e1beeafb001196cab204d1af69f0fe2 diff --git a/manifest.uuid b/manifest.uuid index 9bbedd7b51..a57419f54c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7a7f826e324b1a2c332e2f1d0740fd0babffcaca6275a798572f02ad367b99ab \ No newline at end of file +89e5720a8d8d46d4e2f16f15678e91336117e64abc977174e2b345a30308d0d2 \ No newline at end of file From 9af41ff4524bce2756d807c43c09a15944f52ed1 Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 29 Dec 2017 16:37:33 +0000 Subject: [PATCH 27/40] Stricter test cases. FossilOrigin-Name: 9406c0a685fd5ff3516a66402b0514a1440652822a5eecf0b7af85929f3079e8 --- manifest | 12 +++++------ manifest.uuid | 2 +- test/func6.test | 56 ++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 56 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index 3d0577aaea..6b6ae42bc2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\stypo\sin\sthe\sMSVC\smakefile. -D 2017-12-29T15:19:03.549 +C Stricter\stest\scases. +D 2017-12-29T16:37:33.070 F Makefile.in 804c347948b0ad5a962aea3e59413e897227e0173d0e76910f11f473e6c7ae9b F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 57dcce0595d4a0c4b94b6f6ba732b8e33540358adf5fb8e1aa8389d34a9677e8 @@ -917,7 +917,7 @@ F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f F test/func3.test d202a7606d23f90988a664e88e268aed1087c11c F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f F test/func5.test cdd224400bc3e48d891827cc913a57051a426fa4 -F test/func6.test 8a6ecb974a9d0bdeef6a06aff8e305b1667c3b922103037735b39c716360ebc2 +F test/func6.test 1a2bc511fedb779e2bd3154361385216c6d35080f36bfe896b8cdd1b1954294a F test/fuzz-oss1.test e58330d01cbbd8215ee636b17a03fe220b37dbfa F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1 F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1 @@ -1688,7 +1688,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 7a7f826e324b1a2c332e2f1d0740fd0babffcaca6275a798572f02ad367b99ab -R 0e2a4a2bb72ba4dcfe2f3a815db6ddb3 +P 89e5720a8d8d46d4e2f16f15678e91336117e64abc977174e2b345a30308d0d2 +R 9cb794037b97521b258cb5fdbbf60d53 U drh -Z 9e1beeafb001196cab204d1af69f0fe2 +Z 8d1ee588df9bbfd069e3afd64819112f diff --git a/manifest.uuid b/manifest.uuid index a57419f54c..b37d8e1f54 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -89e5720a8d8d46d4e2f16f15678e91336117e64abc977174e2b345a30308d0d2 \ No newline at end of file +9406c0a685fd5ff3516a66402b0514a1440652822a5eecf0b7af85929f3079e8 \ No newline at end of file diff --git a/test/func6.test b/test/func6.test index ff05ee78c5..0d3de8ef49 100644 --- a/test/func6.test +++ b/test/func6.test @@ -11,6 +11,10 @@ # # Test cases for the sqlite_unsupported_offset() function. # +# Some of the tests in this file depend on the exact placement of content +# within b-tree pages. Such placement is at the implementations discretion, +# and so it is possible for results to change from one release to the next. +# set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !offset_sql_func { @@ -19,26 +23,64 @@ ifcapable !offset_sql_func { } do_execsql_test func6-100 { + PRAGMA page_size=4096; + PRAGMA auto_vacuum=NONE; CREATE TABLE t1(a,b,c,d); WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100) INSERT INTO t1(a,b,c,d) SELECT printf('abc%03x',x), x, 1000-x, NULL FROM c; + CREATE INDEX t1a ON t1(a); + CREATE INDEX t1bc ON t1(b,c); + CREATE TABLE t2(x TEXT PRIMARY KEY, y) WITHOUT ROWID; + INSERT INTO t2(x,y) SELECT a, b FROM t1; } do_execsql_test func6-110 { - SELECT a, typeof(sqlite_unsupported_offset(a)) FROM t1 + SELECT a, sqlite_unsupported_offset(d)/4096 + 1, + sqlite_unsupported_offset(d)%4096 FROM t1 ORDER BY rowid LIMIT 2; -} {abc001 integer abc002 integer} +} {abc001 2 4084 abc002 2 4069} do_execsql_test func6-120 { SELECT a, typeof(sqlite_unsupported_offset(+a)) FROM t1 ORDER BY rowid LIMIT 2; } {abc001 null abc002 null} do_execsql_test func6-130 { - CREATE INDEX t1a ON t1(a); - SELECT a, typeof(sqlite_unsupported_offset(a)) FROM t1 + SELECT a, sqlite_unsupported_offset(a)/4096+1, + sqlite_unsupported_offset(a)%4096 + FROM t1 ORDER BY a LIMIT 2; -} {abc001 integer abc002 integer} +} {abc001 3 4087 abc002 3 4076} do_execsql_test func6-140 { - SELECT a, typeof(sqlite_unsupported_offset(a)) FROM t1 NOT INDEXED + SELECT a, sqlite_unsupported_offset(d)/4096+1, + sqlite_unsupported_offset(d)%4096 + FROM t1 ORDER BY a LIMIT 2; -} {abc001 integer abc002 integer} +} {abc001 2 4084 abc002 2 4069} +do_execsql_test func6-150 { + SELECT a, + sqlite_unsupported_offset(a)/4096+1, + sqlite_unsupported_offset(a)%4096, + sqlite_unsupported_offset(d)/4096+1, + sqlite_unsupported_offset(d)%4096 + FROM t1 + ORDER BY a LIMIT 2; +} {abc001 3 4087 2 4084 abc002 3 4076 2 4069} +do_execsql_test func6-160 { + SELECT b, + sqlite_unsupported_offset(b)/4096+1, + sqlite_unsupported_offset(b)%4096, + sqlite_unsupported_offset(c)/4096+1, + sqlite_unsupported_offset(c)%4096, + sqlite_unsupported_offset(d)/4096+1, + sqlite_unsupported_offset(d)%4096 + FROM t1 + ORDER BY b LIMIT 2; +} {1 4 4090 4 4090 2 4084 2 4 4081 4 4081 2 4069} + + +do_execsql_test func6-200 { + SELECT y, sqlite_unsupported_offset(y)/4096+1, + sqlite_unsupported_offset(y)%4096 + FROM t2 + ORDER BY x LIMIT 2; +} {1 5 4087 2 5 4076} finish_test From 470fc9ddaabf6475d38eb1ca2071279271404d19 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 1 Jan 2018 19:33:12 +0000 Subject: [PATCH 28/40] Enable the introspection pragmas for command-line shell builds. FossilOrigin-Name: 0b04223f256f5c1e06fa6e899727815ebf650f2dfcf8f36d6cbfb6cb62d4ead8 --- Makefile.in | 1 + Makefile.msc | 2 +- main.mk | 1 + manifest | 17 ++++++++--------- manifest.uuid | 2 +- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Makefile.in b/Makefile.in index 3c9e7b3a96..e3dfb01baa 100644 --- a/Makefile.in +++ b/Makefile.in @@ -583,6 +583,7 @@ SHELL_OPT += -DSQLITE_ENABLE_STMTVTAB SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC +SHELL_OPT += -DSQLITE_INTROSPECTION_PRAGMAS FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1 FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000 diff --git a/Makefile.msc b/Makefile.msc index 27eb23a240..2f038ab1c1 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -1513,7 +1513,7 @@ FUZZDATA = \ !IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0 SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_STMTVTAB SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_DBSTAT_VTAB -SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC +SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC -DSQLITE_INTROSPECTION_PRAGMAS !ENDIF # <> diff --git a/main.mk b/main.mk index b46ffa1a52..85588cd01a 100644 --- a/main.mk +++ b/main.mk @@ -510,6 +510,7 @@ SHELL_OPT += -DSQLITE_ENABLE_STMTVTAB SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC +SHELL_OPT += -DSQLITE_INTROSPECTION_PRAGMAS FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1 FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000 diff --git a/manifest b/manifest index 682ec0eee7..aede5dedf5 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Add\ssupport\sfor\sthe\ssqlite_unsupported_offset()\sSQL\sfunction\sif\sand\sonly\nif\scompiled\susing\s-DSQLITE_ENABLE_OFFSET_SQL_FUNC.\s\sUse\sthat\sdefinition\nwhen\scompiling\sthe\scommand-line\sshell. -D 2017-12-29T17:21:21.319 -F Makefile.in 804c347948b0ad5a962aea3e59413e897227e0173d0e76910f11f473e6c7ae9b +C Enable\sthe\sintrospection\spragmas\sfor\scommand-line\sshell\sbuilds. +D 2018-01-01T19:33:12.194 +F Makefile.in 1b11037c5ed3399a79433cc82c59b5e36a7b3a3e4e195bb27640d0d2145e03e1 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc 57dcce0595d4a0c4b94b6f6ba732b8e33540358adf5fb8e1aa8389d34a9677e8 +F Makefile.msc f68b4f9b83cfeb057b6265e0288ad653f319e2ceacca731e0f22e19617829a89 F README.md eeae1e552f93ef72ef7c5b8f6647b368a001c28820ad1df179d3dae602bef681 F VERSION 0c10cdfed866fdd2d80434f64f042c3330f1daaed12e54287beb104f04b3faaf F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -401,7 +401,7 @@ F ext/userauth/userauth.c 3410be31283abba70255d71fd24734e017a4497f F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk b5f569262e4f8111bb8cf6110784b8210fe14ea45f6c7ea50fb4230ebe7a4880 +F main.mk 59744c818d349d170ff56cdbdfb5af0e0a2029db18ce2824fcd1b0a3fa317d84 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 @@ -1688,8 +1688,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P f4349c0c26611de8a7d5beb99431a575cf531cdeb0ca2413efabcf0a61e6f424 9406c0a685fd5ff3516a66402b0514a1440652822a5eecf0b7af85929f3079e8 -R 35346abc344e9d51558b9d8d5c8f2d13 -T +closed 9406c0a685fd5ff3516a66402b0514a1440652822a5eecf0b7af85929f3079e8 +P 4f1f1f521ae6da96b899e10bfeff6bc1ab7a45de0705076febaae20b441f48c6 +R c9a22e6c8d8b0c74afd8179337182631 U drh -Z b5b643a0e7da393bb8589918154fc3c1 +Z ad901b13942be312e9eb272912737269 diff --git a/manifest.uuid b/manifest.uuid index 1c26686ec7..86076c7330 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4f1f1f521ae6da96b899e10bfeff6bc1ab7a45de0705076febaae20b441f48c6 \ No newline at end of file +0b04223f256f5c1e06fa6e899727815ebf650f2dfcf8f36d6cbfb6cb62d4ead8 \ No newline at end of file From c22b716e316af27b96e3717bd350c828841319b1 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 1 Jan 2018 20:11:23 +0000 Subject: [PATCH 29/40] Minor simplification to the ".schema" logic in the command-line shell. FossilOrigin-Name: add45c47288248ca3745e0fceb5e0d9062a852d173d93ff2ff1a0f8fdf3237dc --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c.in | 24 +++++++----------------- 3 files changed, 14 insertions(+), 24 deletions(-) diff --git a/manifest b/manifest index aede5dedf5..ac3df26d19 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enable\sthe\sintrospection\spragmas\sfor\scommand-line\sshell\sbuilds. -D 2018-01-01T19:33:12.194 +C Minor\ssimplification\sto\sthe\s".schema"\slogic\sin\sthe\scommand-line\sshell. +D 2018-01-01T20:11:23.297 F Makefile.in 1b11037c5ed3399a79433cc82c59b5e36a7b3a3e4e195bb27640d0d2145e03e1 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc f68b4f9b83cfeb057b6265e0288ad653f319e2ceacca731e0f22e19617829a89 @@ -479,7 +479,7 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c bbee7e31d369a18a2f4836644769882e9c5d40ef4a3af911db06410b65cb3730 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c 8b22abe193e4d8243befa2038e4ae2405802fed1c446e5e502d11f652e09ba74 -F src/shell.c.in f3ec8f90dd698ea98781a90642c91eacbc24f4e55bb551c7b2762000d3ef55dc +F src/shell.c.in a3f30523bbf436e886831c9f867419edb957dec60a2b5d70d2a071298206e37d F src/sqlite.h.in b4dc75265ed04b98e2184011a7dd0054ce2137ff84867a6be8b4f3bdfbc03d30 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34 @@ -1688,7 +1688,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 4f1f1f521ae6da96b899e10bfeff6bc1ab7a45de0705076febaae20b441f48c6 -R c9a22e6c8d8b0c74afd8179337182631 +P 0b04223f256f5c1e06fa6e899727815ebf650f2dfcf8f36d6cbfb6cb62d4ead8 +R 2690a690f31be0b2523230103d44d965 U drh -Z ad901b13942be312e9eb272912737269 +Z 17d3ed202c106ebc7057d8eede16f971 diff --git a/manifest.uuid b/manifest.uuid index 86076c7330..953c3c5663 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0b04223f256f5c1e06fa6e899727815ebf650f2dfcf8f36d6cbfb6cb62d4ead8 \ No newline at end of file +add45c47288248ca3745e0fceb5e0d9062a852d173d93ff2ff1a0f8fdf3237dc \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index 155ca708a5..7b994336ea 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -5334,33 +5334,23 @@ static int do_meta_command(char *zLine, ShellState *p){ if( nArg==2 && azArg[1][0]!='-' ){ int i; for(i=0; azArg[1][i]; i++) azArg[1][i] = ToLower(azArg[1][i]); - if( strcmp(azArg[1],"sqlite_master")==0 ){ + if( strcmp(azArg[1],"sqlite_master")==0 + || strcmp(azArg[1],"sqlite_temp_master")==0 + ){ char *new_argv[2], *new_colv[2]; - new_argv[0] = "CREATE TABLE sqlite_master (\n" + new_argv[0] = sqlite3_mprintf( + "CREATE TABLE %s (\n" " type text,\n" " name text,\n" " tbl_name text,\n" " rootpage integer,\n" " sql text\n" - ")"; - new_argv[1] = 0; - new_colv[0] = "sql"; - new_colv[1] = 0; - callback(&data, 1, new_argv, new_colv); - rc = SQLITE_OK; - }else if( strcmp(azArg[1],"sqlite_temp_master")==0 ){ - char *new_argv[2], *new_colv[2]; - new_argv[0] = "CREATE TEMP TABLE sqlite_temp_master (\n" - " type text,\n" - " name text,\n" - " tbl_name text,\n" - " rootpage integer,\n" - " sql text\n" - ")"; + ")", azArg[1]); new_argv[1] = 0; new_colv[0] = "sql"; new_colv[1] = 0; callback(&data, 1, new_argv, new_colv); + sqlite3_free(new_argv[0]); rc = SQLITE_OK; }else{ zDiv = "("; From ceba792a2fb5c242432ab9e4d32277762e1476bb Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 1 Jan 2018 21:28:25 +0000 Subject: [PATCH 30/40] In the output of ".schema", show the column names of virtual tables and views in a separate comment. FossilOrigin-Name: 2234a87fa905312b23f46d52e06cff7cacbf23b187e16c4398a42e6bdae0ee9f --- manifest | 16 +++--- manifest.uuid | 2 +- src/shell.c.in | 127 +++++++++++++++++++++++++++++++--------------- test/pragma5.test | 2 +- test/shell1.test | 6 ++- 5 files changed, 99 insertions(+), 54 deletions(-) diff --git a/manifest b/manifest index ac3df26d19..b8745cef92 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Minor\ssimplification\sto\sthe\s".schema"\slogic\sin\sthe\scommand-line\sshell. -D 2018-01-01T20:11:23.297 +C In\sthe\soutput\sof\s".schema",\sshow\sthe\scolumn\snames\sof\svirtual\stables\sand\nviews\sin\sa\sseparate\scomment. +D 2018-01-01T21:28:25.565 F Makefile.in 1b11037c5ed3399a79433cc82c59b5e36a7b3a3e4e195bb27640d0d2145e03e1 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc f68b4f9b83cfeb057b6265e0288ad653f319e2ceacca731e0f22e19617829a89 @@ -479,7 +479,7 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c bbee7e31d369a18a2f4836644769882e9c5d40ef4a3af911db06410b65cb3730 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c 8b22abe193e4d8243befa2038e4ae2405802fed1c446e5e502d11f652e09ba74 -F src/shell.c.in a3f30523bbf436e886831c9f867419edb957dec60a2b5d70d2a071298206e37d +F src/shell.c.in f151a1181ed4da01c48ecbbeeb4e102d298dd239102c252f92cc331c85a1436b F src/sqlite.h.in b4dc75265ed04b98e2184011a7dd0054ce2137ff84867a6be8b4f3bdfbc03d30 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34 @@ -1127,7 +1127,7 @@ F test/pragma.test 7c8cfc328a1717a95663cf8edb06c52ddfeaf97bb0aee69ae7457132e8d39 F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed F test/pragma4.test 3046501bee2f652dc2a4f9c87781e2741361d6864439c8381aba6c3b774b335c -F test/pragma5.test fd517f42ee847e126afbbbd9fd0fb9e5a4a61a962496a350adb8a22583fbdc37 +F test/pragma5.test 824ce6ced5d6b7ec71abe37fc6005ff836fe39d638273dc5192b39864b9ee983 F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8 F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc F test/printf2.test 9e6db85f81c63f2367c34a9d7db384088bd374ad @@ -1213,7 +1213,7 @@ F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5 F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939 F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304 -F test/shell1.test f78ea0e2637ae9f497cb41206f6346f983052ffc7a359e664aaf6847fc704ea7 +F test/shell1.test 3f23fe267fc591dc6a004a163b719a7a6509e4b46915bab8781e32e854c0a0a4 F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b F test/shell3.test 9b95ba643eaa228376f06a898fb410ee9b6e57c1 F test/shell4.test 89ad573879a745974ff2df20ff97c5d6ffffbd5d @@ -1688,7 +1688,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 0b04223f256f5c1e06fa6e899727815ebf650f2dfcf8f36d6cbfb6cb62d4ead8 -R 2690a690f31be0b2523230103d44d965 +P add45c47288248ca3745e0fceb5e0d9062a852d173d93ff2ff1a0f8fdf3237dc +R dcc0e8850f6f2345f6beb728eed33eca U drh -Z 17d3ed202c106ebc7057d8eede16f971 +Z b932e40f742685fed6e88a07d4738316 diff --git a/manifest.uuid b/manifest.uuid index 953c3c5663..6be3b12497 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -add45c47288248ca3745e0fceb5e0d9062a852d173d93ff2ff1a0f8fdf3237dc \ No newline at end of file +2234a87fa905312b23f46d52e06cff7cacbf23b187e16c4398a42e6bdae0ee9f \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index 7b994336ea..a1e4362f58 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -729,6 +729,33 @@ static char quoteChar(const char *zName){ return 0; } +/* +** Construct a fake CREATE TABLE statement (or at least the part that comes +** after the "CREATE TABLE" keywords) that describes the columns of +** the view, virtual table, or table valued function zName in zSchema. +*/ +static char *shellFakeCrTab( + sqlite3 *db, /* The database connection containing the vtab */ + const char *zSchema, /* Schema of the database holding the vtab */ + const char *zName /* The name of the virtual table */ +){ + sqlite3_stmt *pStmt = 0; + char *zSql; + char *z = 0; + + zSql = sqlite3_mprintf("SELECT group_concat(name,',')" + " FROM pragma_table_info(%Q,%Q);", + zName, zSchema); + sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + if( sqlite3_step(pStmt)==SQLITE_ROW ){ + z = sqlite3_mprintf("/* %s.%s(%s) */", + zSchema ? zSchema : "main", zName, sqlite3_column_text(pStmt, 0)); + } + sqlite3_finalize(pStmt); + return z; +} + /* ** SQL function: shell_add_schema(S,X) ** @@ -764,20 +791,29 @@ static void shellAddSchemaName( int i = 0; const char *zIn = (const char*)sqlite3_value_text(apVal[0]); const char *zSchema = (const char*)sqlite3_value_text(apVal[1]); - assert( nVal==2 ); + sqlite3 *db = sqlite3_context_db_handle(pCtx); if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){ for(i=0; i<(int)(sizeof(aPrefix)/sizeof(aPrefix[0])); i++){ int n = strlen30(aPrefix[i]); if( strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){ - char cQuote = quoteChar(zSchema); - char *z; - if( cQuote ){ - z = sqlite3_mprintf("%.*s \"%w\".%s", n+7, zIn, zSchema, zIn+n+8); - }else{ - z = sqlite3_mprintf("%.*s %s.%s", n+7, zIn, zSchema, zIn+n+8); + char *z = 0; + if( zSchema ){ + char cQuote = quoteChar(zSchema); + if( cQuote && sqlite3_stricmp(zSchema,"temp")!=0 ){ + z = sqlite3_mprintf("%.*s \"%w\".%s", n+7, zIn, zSchema, zIn+n+8); + }else{ + z = sqlite3_mprintf("%.*s %s.%s", n+7, zIn, zSchema, zIn+n+8); + } + } + if( aPrefix[i][0]=='V' ){ + const char *zName = (const char*)sqlite3_value_text(apVal[2]); + if( z==0 ) z = sqlite3_mprintf("%s", zIn); + z = sqlite3_mprintf("%z\n%z", z, shellFakeCrTab(db, zSchema, zName)); + } + if( z ){ + sqlite3_result_text(pCtx, z, -1, sqlite3_free); + return; } - sqlite3_result_text(pCtx, z, -1, sqlite3_free); - return; } } } @@ -2998,7 +3034,7 @@ static void open_db(ShellState *p, int keepAlive){ sqlite3_fileio_init(p->db, 0, 0); sqlite3_shathree_init(p->db, 0, 0); sqlite3_completion_init(p->db, 0, 0); - sqlite3_create_function(p->db, "shell_add_schema", 2, SQLITE_UTF8, 0, + sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0, shellAddSchemaName, 0, 0); } } @@ -5319,23 +5355,32 @@ static int do_meta_command(char *zLine, ShellState *p){ ShellState data; char *zErrMsg = 0; const char *zDiv = 0; + const char *zName = 0; int iSchema = 0; + int bDebug = 0; + int ii; open_db(p, 0); memcpy(&data, p, sizeof(data)); data.showHeader = 0; data.cMode = data.mode = MODE_Semi; initText(&sSelect); - if( nArg>=2 && optionMatch(azArg[1], "indent") ){ - data.cMode = data.mode = MODE_Pretty; - nArg--; - if( nArg==2 ) azArg[1] = azArg[2]; + for(ii=1; ii1 ){ - char *zQarg = sqlite3_mprintf("%Q", azArg[1]); - if( strchr(azArg[1], '.') ){ + if( zName ){ + char *zQarg = sqlite3_mprintf("%Q", zName); + if( strchr(zName, '.') ){ appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0); }else{ appendText(&sSelect, "lower(tbl_name)", 0); } - appendText(&sSelect, strchr(azArg[1], '*') ? " GLOB " : " LIKE ", 0); + appendText(&sSelect, strchr(zName, '*') ? " GLOB " : " LIKE ", 0); appendText(&sSelect, zQarg, 0); appendText(&sSelect, " AND ", 0); sqlite3_free(zQarg); } appendText(&sSelect, "type!='meta' AND sql IS NOT NULL" " ORDER BY snum, rowid", 0); - rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg); + if( bDebug ){ + utf8_printf(p->out, "SQL: %s;\n", sSelect.z); + }else{ + rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg); + } freeText(&sSelect); } if( zErrMsg ){ diff --git a/test/pragma5.test b/test/pragma5.test index 625ab92012..d2c58000cf 100644 --- a/test/pragma5.test +++ b/test/pragma5.test @@ -34,7 +34,7 @@ do_execsql_test 1.0 { 1 builtin {} 0 {} 0 } do_execsql_test 1.1 { - SELECT * FROM pragma_function_list WHERE name='upper' + SELECT * FROM pragma_function_list WHERE name='upper' AND builtin } {upper 1} do_execsql_test 1.2 { SELECT * FROM pragma_function_list WHERE name LIKE 'exter%'; diff --git a/test/shell1.test b/test/shell1.test index ddd72c7180..c2f39435b8 100644 --- a/test/shell1.test +++ b/test/shell1.test @@ -581,8 +581,10 @@ do_test shell1-3.21.4 { } catchcmd "test.db" ".schema" } {0 {CREATE TABLE t1(x); -CREATE VIEW v2 AS SELECT x+1 AS y FROM t1; -CREATE VIEW v1 AS SELECT y+1 FROM v2;}} +CREATE VIEW v2 AS SELECT x+1 AS y FROM t1 +/* main.v2(y) */; +CREATE VIEW v1 AS SELECT y+1 FROM v2 +/* main.v1(y+1) */;}} db eval {DROP VIEW v1; DROP VIEW v2; DROP TABLE t1;} } From 1d315cf7b86052178e4537e57e249499fa0e6187 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 1 Jan 2018 21:49:43 +0000 Subject: [PATCH 31/40] Improved name quoting and escaping in the auxiliary column info section of the ".schema" output for views and virtual tables. FossilOrigin-Name: d64b14e37d9624bf5d86059ddd091170d8e6d341a8043f84548b9b3dbb96a908 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/shell.c.in | 34 +++++++++++++++++++++++++--------- test/shell1.test | 4 ++-- 4 files changed, 35 insertions(+), 19 deletions(-) diff --git a/manifest b/manifest index b8745cef92..71d3959150 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\soutput\sof\s".schema",\sshow\sthe\scolumn\snames\sof\svirtual\stables\sand\nviews\sin\sa\sseparate\scomment. -D 2018-01-01T21:28:25.565 +C Improved\sname\squoting\sand\sescaping\sin\sthe\sauxiliary\scolumn\sinfo\ssection\nof\sthe\s".schema"\soutput\sfor\sviews\sand\svirtual\stables. +D 2018-01-01T21:49:43.315 F Makefile.in 1b11037c5ed3399a79433cc82c59b5e36a7b3a3e4e195bb27640d0d2145e03e1 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc f68b4f9b83cfeb057b6265e0288ad653f319e2ceacca731e0f22e19617829a89 @@ -479,7 +479,7 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c bbee7e31d369a18a2f4836644769882e9c5d40ef4a3af911db06410b65cb3730 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c 8b22abe193e4d8243befa2038e4ae2405802fed1c446e5e502d11f652e09ba74 -F src/shell.c.in f151a1181ed4da01c48ecbbeeb4e102d298dd239102c252f92cc331c85a1436b +F src/shell.c.in e0d3ef676265771a001446906765dd89617df2cece3249b08b1dcd24ba296f63 F src/sqlite.h.in b4dc75265ed04b98e2184011a7dd0054ce2137ff84867a6be8b4f3bdfbc03d30 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34 @@ -1213,7 +1213,7 @@ F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5 F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939 F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304 -F test/shell1.test 3f23fe267fc591dc6a004a163b719a7a6509e4b46915bab8781e32e854c0a0a4 +F test/shell1.test 6d69e08039aea13f2c42749f162fe05eab7b5c93729f31d49d7d27cf36226e5a F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b F test/shell3.test 9b95ba643eaa228376f06a898fb410ee9b6e57c1 F test/shell4.test 89ad573879a745974ff2df20ff97c5d6ffffbd5d @@ -1688,7 +1688,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P add45c47288248ca3745e0fceb5e0d9062a852d173d93ff2ff1a0f8fdf3237dc -R dcc0e8850f6f2345f6beb728eed33eca +P 2234a87fa905312b23f46d52e06cff7cacbf23b187e16c4398a42e6bdae0ee9f +R ca3aef501320cce9e28be13c23be1622 U drh -Z b932e40f742685fed6e88a07d4738316 +Z 2aaca99c49ba21a51639392b75414605 diff --git a/manifest.uuid b/manifest.uuid index 6be3b12497..687c35b1d6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2234a87fa905312b23f46d52e06cff7cacbf23b187e16c4398a42e6bdae0ee9f \ No newline at end of file +d64b14e37d9624bf5d86059ddd091170d8e6d341a8043f84548b9b3dbb96a908 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index a1e4362f58..4861d4b506 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -741,19 +741,34 @@ static char *shellFakeCrTab( ){ sqlite3_stmt *pStmt = 0; char *zSql; - char *z = 0; + ShellText s; + char cQuote; + char *zDiv = "("; - zSql = sqlite3_mprintf("SELECT group_concat(name,',')" - " FROM pragma_table_info(%Q,%Q);", - zName, zSchema); + zSql = sqlite3_mprintf("PRAGMA \"%w\".table_info=%Q;", + zSchema ? zSchema : "main", zName); sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); sqlite3_free(zSql); - if( sqlite3_step(pStmt)==SQLITE_ROW ){ - z = sqlite3_mprintf("/* %s.%s(%s) */", - zSchema ? zSchema : "main", zName, sqlite3_column_text(pStmt, 0)); + initText(&s); + if( zSchema ){ + cQuote = quoteChar(zSchema); + if( cQuote && sqlite3_stricmp(zSchema,"temp")==0 ) cQuote = 0; + appendText(&s, zSchema, cQuote); + appendText(&s, ".", 0); } + cQuote = quoteChar(zName); + appendText(&s, zName, cQuote); + while( sqlite3_step(pStmt)==SQLITE_ROW ){ + const char *zCol = (const char*)sqlite3_column_text(pStmt, 1); + appendText(&s, zDiv, 0); + zDiv = ","; + cQuote = quoteChar(zCol); + appendText(&s, zCol, cQuote); + } + appendText(&s, ")", 0); + sqlite3_finalize(pStmt); - return z; + return s.z; } /* @@ -808,7 +823,8 @@ static void shellAddSchemaName( if( aPrefix[i][0]=='V' ){ const char *zName = (const char*)sqlite3_value_text(apVal[2]); if( z==0 ) z = sqlite3_mprintf("%s", zIn); - z = sqlite3_mprintf("%z\n%z", z, shellFakeCrTab(db, zSchema, zName)); + z = sqlite3_mprintf("%z\n/* %z */", z, + shellFakeCrTab(db, zSchema, zName)); } if( z ){ sqlite3_result_text(pCtx, z, -1, sqlite3_free); diff --git a/test/shell1.test b/test/shell1.test index c2f39435b8..0d03c64f78 100644 --- a/test/shell1.test +++ b/test/shell1.test @@ -582,9 +582,9 @@ do_test shell1-3.21.4 { catchcmd "test.db" ".schema" } {0 {CREATE TABLE t1(x); CREATE VIEW v2 AS SELECT x+1 AS y FROM t1 -/* main.v2(y) */; +/* v2(y) */; CREATE VIEW v1 AS SELECT y+1 FROM v2 -/* main.v1(y+1) */;}} +/* v1("y+1") */;}} db eval {DROP VIEW v1; DROP VIEW v2; DROP TABLE t1;} } From 667a2a25bad684983c4e647fdfa4acfcfab7f67d Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 2 Jan 2018 00:04:37 +0000 Subject: [PATCH 32/40] The ".schema" command in the command-line shell now shows the structure of table-valued functions and eponymous virtual tables if they are named on the ".schema" command line. Example: ".schema sql%" shows the structure of the "sqlite_dbstat" and "sqlite_stmt" virtual tables. FossilOrigin-Name: f80f6651df0b2843c6c9619a8f3e05c56cd50363402800a2e166e6eb664f7768 --- manifest | 12 ++++----- manifest.uuid | 2 +- src/shell.c.in | 70 +++++++++++++++++++++++++++++++++++--------------- 3 files changed, 57 insertions(+), 27 deletions(-) diff --git a/manifest b/manifest index 71d3959150..cf7032a36b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\sname\squoting\sand\sescaping\sin\sthe\sauxiliary\scolumn\sinfo\ssection\nof\sthe\s".schema"\soutput\sfor\sviews\sand\svirtual\stables. -D 2018-01-01T21:49:43.315 +C The\s".schema"\scommand\sin\sthe\scommand-line\sshell\snow\sshows\sthe\sstructure\sof\ntable-valued\sfunctions\sand\seponymous\svirtual\stables\sif\sthey\sare\snamed\son\sthe\n".schema"\scommand\sline.\s\sExample:\s\s".schema\ssql%"\sshows\sthe\sstructure\sof\nthe\s"sqlite_dbstat"\sand\s"sqlite_stmt"\svirtual\stables. +D 2018-01-02T00:04:37.286 F Makefile.in 1b11037c5ed3399a79433cc82c59b5e36a7b3a3e4e195bb27640d0d2145e03e1 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc f68b4f9b83cfeb057b6265e0288ad653f319e2ceacca731e0f22e19617829a89 @@ -479,7 +479,7 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c bbee7e31d369a18a2f4836644769882e9c5d40ef4a3af911db06410b65cb3730 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c 8b22abe193e4d8243befa2038e4ae2405802fed1c446e5e502d11f652e09ba74 -F src/shell.c.in e0d3ef676265771a001446906765dd89617df2cece3249b08b1dcd24ba296f63 +F src/shell.c.in 6b1ec35f31058505650a79807c1facaec399a9a910fb317a40b9e267cb4bb312 F src/sqlite.h.in b4dc75265ed04b98e2184011a7dd0054ce2137ff84867a6be8b4f3bdfbc03d30 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34 @@ -1688,7 +1688,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 2234a87fa905312b23f46d52e06cff7cacbf23b187e16c4398a42e6bdae0ee9f -R ca3aef501320cce9e28be13c23be1622 +P d64b14e37d9624bf5d86059ddd091170d8e6d341a8043f84548b9b3dbb96a908 +R 58693511e34cddcc08538ba153bd6535 U drh -Z 2aaca99c49ba21a51639392b75414605 +Z 527d9b7c91bfab98cfe62f567d2e9f84 diff --git a/manifest.uuid b/manifest.uuid index 687c35b1d6..aed8d4df66 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d64b14e37d9624bf5d86059ddd091170d8e6d341a8043f84548b9b3dbb96a908 \ No newline at end of file +f80f6651df0b2843c6c9619a8f3e05c56cd50363402800a2e166e6eb664f7768 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index 4861d4b506..e0e998632d 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -730,11 +730,10 @@ static char quoteChar(const char *zName){ } /* -** Construct a fake CREATE TABLE statement (or at least the part that comes -** after the "CREATE TABLE" keywords) that describes the columns of -** the view, virtual table, or table valued function zName in zSchema. +** Construct a fake object name and column list to describe the structure +** of the view, virtual table, or table valued function zSchema.zName. */ -static char *shellFakeCrTab( +static char *shellFakeSchema( sqlite3 *db, /* The database connection containing the vtab */ const char *zSchema, /* Schema of the database holding the vtab */ const char *zName /* The name of the virtual table */ @@ -744,6 +743,7 @@ static char *shellFakeCrTab( ShellText s; char cQuote; char *zDiv = "("; + int nRow = 0; zSql = sqlite3_mprintf("PRAGMA \"%w\".table_info=%Q;", zSchema ? zSchema : "main", zName); @@ -760,17 +760,40 @@ static char *shellFakeCrTab( appendText(&s, zName, cQuote); while( sqlite3_step(pStmt)==SQLITE_ROW ){ const char *zCol = (const char*)sqlite3_column_text(pStmt, 1); + nRow++; appendText(&s, zDiv, 0); zDiv = ","; cQuote = quoteChar(zCol); appendText(&s, zCol, cQuote); } appendText(&s, ")", 0); - sqlite3_finalize(pStmt); + if( nRow==0 ){ + freeText(&s); + s.z = 0; + } return s.z; } +/* +** SQL function: shell_module_schema(X) +** +** Return a fake schema for the table-valued function or eponymous virtual +** table X. +*/ +static void shellModuleSchema( + sqlite3_context *pCtx, + int nVal, + sqlite3_value **apVal +){ + const char *zName = (const char*)sqlite3_value_text(apVal[0]); + char *zFake = shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName); + if( zFake ){ + sqlite3_result_text(pCtx, sqlite3_mprintf("/* %z */", zFake), + -1, sqlite3_free); + } +} + /* ** SQL function: shell_add_schema(S,X) ** @@ -806,12 +829,14 @@ static void shellAddSchemaName( int i = 0; const char *zIn = (const char*)sqlite3_value_text(apVal[0]); const char *zSchema = (const char*)sqlite3_value_text(apVal[1]); + const char *zName = (const char*)sqlite3_value_text(apVal[2]); sqlite3 *db = sqlite3_context_db_handle(pCtx); if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){ for(i=0; i<(int)(sizeof(aPrefix)/sizeof(aPrefix[0])); i++){ int n = strlen30(aPrefix[i]); if( strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){ char *z = 0; + char *zFake = 0; if( zSchema ){ char cQuote = quoteChar(zSchema); if( cQuote && sqlite3_stricmp(zSchema,"temp")!=0 ){ @@ -820,11 +845,15 @@ static void shellAddSchemaName( z = sqlite3_mprintf("%.*s %s.%s", n+7, zIn, zSchema, zIn+n+8); } } - if( aPrefix[i][0]=='V' ){ - const char *zName = (const char*)sqlite3_value_text(apVal[2]); - if( z==0 ) z = sqlite3_mprintf("%s", zIn); - z = sqlite3_mprintf("%z\n/* %z */", z, - shellFakeCrTab(db, zSchema, zName)); + if( zName + && aPrefix[i][0]=='V' + && (zFake = shellFakeSchema(db, zSchema, zName))!=0 + ){ + if( z==0 ){ + z = sqlite3_mprintf("%s\n/* %z */", zIn, zFake); + }else{ + z = sqlite3_mprintf("%z\n/* %z */", z, zFake); + } } if( z ){ sqlite3_result_text(pCtx, z, -1, sqlite3_free); @@ -3052,6 +3081,8 @@ static void open_db(ShellState *p, int keepAlive){ sqlite3_completion_init(p->db, 0, 0); sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0, shellAddSchemaName, 0, 0); + sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0, + shellModuleSchema, 0, 0); } } @@ -5370,7 +5401,7 @@ static int do_meta_command(char *zLine, ShellState *p){ ShellText sSelect; ShellState data; char *zErrMsg = 0; - const char *zDiv = 0; + const char *zDiv = "("; const char *zName = 0; int iSchema = 0; int bDebug = 0; @@ -5395,9 +5426,8 @@ static int do_meta_command(char *zLine, ShellState *p){ } } if( zName!=0 ){ - if( sqlite3_stricmp(zName,"sqlite_master")==0 - || sqlite3_stricmp(zName,"sqlite_temp_master")==0 - ){ + int isMaster = sqlite3_strlike(zName, "sqlite_master", 0)==0; + if( isMaster || sqlite3_strlike(zName,"sqlite_temp_master",0)==0 ){ char *new_argv[2], *new_colv[2]; new_argv[0] = sqlite3_mprintf( "CREATE TABLE %s (\n" @@ -5406,18 +5436,13 @@ static int do_meta_command(char *zLine, ShellState *p){ " tbl_name text,\n" " rootpage integer,\n" " sql text\n" - ")", zName); + ")", isMaster ? "sqlite_master" : "sqlite_temp_master"); new_argv[1] = 0; new_colv[0] = "sql"; new_colv[1] = 0; callback(&data, 1, new_argv, new_colv); sqlite3_free(new_argv[0]); - rc = SQLITE_OK; - }else{ - zDiv = "("; } - }else if( zName==0 ){ - zDiv = "("; } if( zDiv ){ sqlite3_stmt *pStmt = 0; @@ -5452,6 +5477,11 @@ static int do_meta_command(char *zLine, ShellState *p){ appendText(&sSelect, ".sqlite_master", 0); } sqlite3_finalize(pStmt); + if( zName ){ + appendText(&sSelect, + " UNION ALL SELECT shell_module_schema(name)," + " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list", 0); + } appendText(&sSelect, ") WHERE ", 0); if( zName ){ char *zQarg = sqlite3_mprintf("%Q", zName); From cde7b77932eade5cd5ed44fec353c78997a91ada Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 2 Jan 2018 12:50:40 +0000 Subject: [PATCH 33/40] Do not attempt to use pragma_module_list in the command-line shell unless it has been compiled with -DSQLITE_INTROSPECTION_PRAGMAS. FossilOrigin-Name: 39ca5fcd31c902cbade4da05125b0dbf2bc5e2b8901af1645f113c9d3dbc8209 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c.in | 2 ++ 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index cf7032a36b..df6e2b86dd 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\s".schema"\scommand\sin\sthe\scommand-line\sshell\snow\sshows\sthe\sstructure\sof\ntable-valued\sfunctions\sand\seponymous\svirtual\stables\sif\sthey\sare\snamed\son\sthe\n".schema"\scommand\sline.\s\sExample:\s\s".schema\ssql%"\sshows\sthe\sstructure\sof\nthe\s"sqlite_dbstat"\sand\s"sqlite_stmt"\svirtual\stables. -D 2018-01-02T00:04:37.286 +C Do\snot\sattempt\sto\suse\spragma_module_list\sin\sthe\scommand-line\sshell\sunless\s\nit\shas\sbeen\scompiled\swith\s-DSQLITE_INTROSPECTION_PRAGMAS. +D 2018-01-02T12:50:40.391 F Makefile.in 1b11037c5ed3399a79433cc82c59b5e36a7b3a3e4e195bb27640d0d2145e03e1 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc f68b4f9b83cfeb057b6265e0288ad653f319e2ceacca731e0f22e19617829a89 @@ -479,7 +479,7 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c bbee7e31d369a18a2f4836644769882e9c5d40ef4a3af911db06410b65cb3730 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c 8b22abe193e4d8243befa2038e4ae2405802fed1c446e5e502d11f652e09ba74 -F src/shell.c.in 6b1ec35f31058505650a79807c1facaec399a9a910fb317a40b9e267cb4bb312 +F src/shell.c.in a418ddceef7a2789f18bdc2bcdd481b2562fe4a7754b8009c8dd33d5a67da332 F src/sqlite.h.in b4dc75265ed04b98e2184011a7dd0054ce2137ff84867a6be8b4f3bdfbc03d30 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34 @@ -1688,7 +1688,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P d64b14e37d9624bf5d86059ddd091170d8e6d341a8043f84548b9b3dbb96a908 -R 58693511e34cddcc08538ba153bd6535 +P f80f6651df0b2843c6c9619a8f3e05c56cd50363402800a2e166e6eb664f7768 +R 6990ef46fea99f4195aa8641bdb529e8 U drh -Z 527d9b7c91bfab98cfe62f567d2e9f84 +Z 071c90bd35c02d763da61d6f60dc05ae diff --git a/manifest.uuid b/manifest.uuid index aed8d4df66..4f0c82c41f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f80f6651df0b2843c6c9619a8f3e05c56cd50363402800a2e166e6eb664f7768 \ No newline at end of file +39ca5fcd31c902cbade4da05125b0dbf2bc5e2b8901af1645f113c9d3dbc8209 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index e0e998632d..4c9e60769a 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -5477,11 +5477,13 @@ static int do_meta_command(char *zLine, ShellState *p){ appendText(&sSelect, ".sqlite_master", 0); } sqlite3_finalize(pStmt); +#ifdef SQLITE_INTROSPECTION_PRAGMAS if( zName ){ appendText(&sSelect, " UNION ALL SELECT shell_module_schema(name)," " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list", 0); } +#endif appendText(&sSelect, ") WHERE ", 0); if( zName ){ char *zQarg = sqlite3_mprintf("%Q", zName); From 9199ac1048e4739c3605f411868c7a5cf3959d4b Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 2 Jan 2018 13:48:48 +0000 Subject: [PATCH 34/40] Updates to the sqlite3_file_control() documentation. No changes to code. FossilOrigin-Name: 240e32ab1f2a18e3c9b92f577b1cc8f8ecb4c68c44eac863d859491e042cb72a --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/sqlite.h.in | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index df6e2b86dd..8af4fc7c93 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Do\snot\sattempt\sto\suse\spragma_module_list\sin\sthe\scommand-line\sshell\sunless\s\nit\shas\sbeen\scompiled\swith\s-DSQLITE_INTROSPECTION_PRAGMAS. -D 2018-01-02T12:50:40.391 +C Updates\sto\sthe\ssqlite3_file_control()\sdocumentation.\s\sNo\schanges\sto\scode. +D 2018-01-02T13:48:48.784 F Makefile.in 1b11037c5ed3399a79433cc82c59b5e36a7b3a3e4e195bb27640d0d2145e03e1 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc f68b4f9b83cfeb057b6265e0288ad653f319e2ceacca731e0f22e19617829a89 @@ -480,7 +480,7 @@ F src/resolve.c bbee7e31d369a18a2f4836644769882e9c5d40ef4a3af911db06410b65cb3730 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c 8b22abe193e4d8243befa2038e4ae2405802fed1c446e5e502d11f652e09ba74 F src/shell.c.in a418ddceef7a2789f18bdc2bcdd481b2562fe4a7754b8009c8dd33d5a67da332 -F src/sqlite.h.in b4dc75265ed04b98e2184011a7dd0054ce2137ff84867a6be8b4f3bdfbc03d30 +F src/sqlite.h.in c597ba5d11666bb2d0179a173cd25e44f0b0333f9e18ce60b07eac8bdc3de67f F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34 F src/sqliteInt.h fd8702c65994d7de3e2d8f7d85d958731da1ed29476571fdfa2290fd8ec0bf80 @@ -1688,7 +1688,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P f80f6651df0b2843c6c9619a8f3e05c56cd50363402800a2e166e6eb664f7768 -R 6990ef46fea99f4195aa8641bdb529e8 +P 39ca5fcd31c902cbade4da05125b0dbf2bc5e2b8901af1645f113c9d3dbc8209 +R 1ce62a1c4d9b56a67e8d1f1aed222781 U drh -Z 071c90bd35c02d763da61d6f60dc05ae +Z d9ace2c20dd904e2b4c8de8f33d7aa5e diff --git a/manifest.uuid b/manifest.uuid index 4f0c82c41f..3dd953071f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -39ca5fcd31c902cbade4da05125b0dbf2bc5e2b8901af1645f113c9d3dbc8209 \ No newline at end of file +240e32ab1f2a18e3c9b92f577b1cc8f8ecb4c68c44eac863d859491e042cb72a \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 7e5fccdae6..a6d328360a 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -6971,9 +6971,9 @@ sqlite3_mutex *sqlite3_db_mutex(sqlite3*); ** the xFileControl method. ^The return value of the xFileControl ** method becomes the return value of this routine. ** -** ^The SQLITE_FCNTL_FILE_POINTER value for the op parameter causes +** ^The [SQLITE_FCNTL_FILE_POINTER] value for the op parameter causes ** a pointer to the underlying [sqlite3_file] object to be written into -** the space pointed to by the 4th parameter. ^The SQLITE_FCNTL_FILE_POINTER +** the space pointed to by the 4th parameter. ^The [SQLITE_FCNTL_FILE_POINTER] ** case is a short-circuit path which does not actually invoke the ** underlying sqlite3_io_methods.xFileControl method. ** @@ -6985,7 +6985,7 @@ sqlite3_mutex *sqlite3_db_mutex(sqlite3*); ** an incorrect zDbName and an SQLITE_ERROR return from the underlying ** xFileControl method. ** -** See also: [SQLITE_FCNTL_LOCKSTATE] +** See also: [file control opcodes] */ int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); From 595a0e2a4a5d6781abaebd4f0da2720568e1c5bb Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 2 Jan 2018 16:02:50 +0000 Subject: [PATCH 35/40] Enhance the memvfs extension so that it can be read/write. FossilOrigin-Name: 04c9197d589666299aef86ee6a56df63448c050274c9fba4af94f932752be237 --- ext/misc/memvfs.c | 161 +++++++++++++++++++++++++++++++++++----------- manifest | 12 ++-- manifest.uuid | 2 +- 3 files changed, 129 insertions(+), 46 deletions(-) diff --git a/ext/misc/memvfs.c b/ext/misc/memvfs.c index 62a8a033d7..27a61c35e4 100644 --- a/ext/misc/memvfs.c +++ b/ext/misc/memvfs.c @@ -10,23 +10,33 @@ ** ****************************************************************************** ** -** This is an in-memory read-only VFS implementation. The application -** supplies a block of memory which is the database file, and this VFS -** uses that block of memory. +** This is an in-memory VFS implementation. The application supplies +** a chunk of memory to hold the database file. ** -** Because there is no place to store journals and no good way to lock -** the "file", this VFS is read-only. +** Because there is place to store a rollback or wal journal, the database +** must use one of journal_mode=MEMORY or journal_mode=NONE. ** ** USAGE: ** -** sqlite3_open_v2("file:/whatever?ptr=0xf05538&sz=14336", &db, -** SQLITE_OPEN_READONLY | SQLITE_OPEN_URI, +** sqlite3_open_v2("file:/whatever?ptr=0xf05538&sz=14336&max=65536", &db, +** SQLITE_OPEN_READWRITE | SQLITE_OPEN_URI, ** "memvfs"); ** -** The ptr= and sz= query parameters are required or the open will fail. -** The ptr= parameter gives the memory address of the buffer holding the -** read-only database and sz= gives the size of the database. The parameter -** values may be in hexadecimal or decimal. The filename is ignored. +** These are the query parameters: +** +** ptr= The address of the memory buffer that holds the database. +** +** sz= The current size the database file +** +** maxsz= The maximum size of the database. In other words, the +** amount of space allocated for the ptr= buffer. +** +** freeonclose= If true, then sqlite3_free() is called on the ptr= +** value when the connection closes. +** +** The ptr= and sz= query parameters are required. If maxsz= is omitted, +** then it defaults to the sz= value. Parameter values can be in either +** decimal or hexadecimal. The filename in the URI is ignored. */ #include SQLITE_EXTENSION_INIT1 @@ -49,7 +59,9 @@ typedef struct MemFile MemFile; struct MemFile { sqlite3_file base; /* IO methods */ sqlite3_int64 sz; /* Size of the file */ + sqlite3_int64 szMax; /* Space allocated to aData */ unsigned char *aData; /* content of the file */ + int bFreeOnClose; /* Invoke sqlite3_free() on aData at close */ }; /* @@ -144,6 +156,8 @@ static const sqlite3_io_methods mem_io_methods = { ** to free. */ static int memClose(sqlite3_file *pFile){ + MemFile *p = (MemFile *)pFile; + if( p->bFreeOnClose ) sqlite3_free(p->aData); return SQLITE_OK; } @@ -170,21 +184,34 @@ static int memWrite( int iAmt, sqlite_int64 iOfst ){ - return SQLITE_READONLY; + MemFile *p = (MemFile *)pFile; + if( iOfst+iAmt>p->sz ){ + if( iOfst+iAmt>p->szMax ) return SQLITE_FULL; + if( iOfst>p->sz ) memset(p->aData+p->sz, 0, iOfst-p->sz); + p->sz = iOfst+iAmt; + } + memcpy(p->aData+iOfst, z, iAmt); + return SQLITE_OK; } /* ** Truncate an mem-file. */ static int memTruncate(sqlite3_file *pFile, sqlite_int64 size){ - return SQLITE_READONLY; + MemFile *p = (MemFile *)pFile; + if( size>p->sz ){ + if( size>p->szMax ) return SQLITE_FULL; + memset(p->aData+p->sz, 0, size-p->sz); + } + p->sz = size; + return SQLITE_OK; } /* ** Sync an mem-file. */ static int memSync(sqlite3_file *pFile, int flags){ - return SQLITE_READONLY; + return SQLITE_OK; } /* @@ -200,7 +227,7 @@ static int memFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ ** Lock an mem-file. */ static int memLock(sqlite3_file *pFile, int eLock){ - return SQLITE_READONLY; + return SQLITE_OK; } /* @@ -242,7 +269,10 @@ static int memSectorSize(sqlite3_file *pFile){ ** Return the device characteristic flags supported by an mem-file. */ static int memDeviceCharacteristics(sqlite3_file *pFile){ - return SQLITE_IOCAP_IMMUTABLE; + return SQLITE_IOCAP_ATOMIC | + SQLITE_IOCAP_POWERSAFE_OVERWRITE | + SQLITE_IOCAP_SAFE_APPEND | + SQLITE_IOCAP_SEQUENTIAL; } /* Create a shared memory file mapping */ @@ -253,12 +283,12 @@ static int memShmMap( int bExtend, void volatile **pp ){ - return SQLITE_READONLY; + return SQLITE_IOERR_SHMMAP; } /* Perform locking on a shared-memory segment */ static int memShmLock(sqlite3_file *pFile, int offset, int n, int flags){ - return SQLITE_READONLY; + return SQLITE_IOERR_SHMLOCK; } /* Memory barrier operation on shared memory */ @@ -305,6 +335,9 @@ static int memOpen( if( p->aData==0 ) return SQLITE_CANTOPEN; p->sz = sqlite3_uri_int64(zName,"sz",0); if( p->sz<0 ) return SQLITE_CANTOPEN; + p->szMax = sqlite3_uri_int64(zName,"max",p->sz); + if( p->szMaxsz ) return SQLITE_CANTOPEN; + p->bFreeOnClose = sqlite3_uri_boolean(zName,"freeonclose",0); pFile->pMethods = &mem_io_methods; return SQLITE_OK; } @@ -315,7 +348,7 @@ static int memOpen( ** returning. */ static int memDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ - return SQLITE_READONLY; + return SQLITE_IOERR_DELETE; } /* @@ -328,14 +361,7 @@ static int memAccess( int flags, int *pResOut ){ - /* The spec says there are three possible values for flags. But only - ** two of them are actually used */ - assert( flags==SQLITE_ACCESS_EXISTS || flags==SQLITE_ACCESS_READWRITE ); - if( flags==SQLITE_ACCESS_READWRITE ){ - *pResOut = 0; - }else{ - *pResOut = 1; - } + *pResOut = 0; return SQLITE_OK; } @@ -416,31 +442,43 @@ static int memCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){ #ifdef MEMVFS_TEST /* -** memload(FILENAME) +** memvfs_from_file(FILENAME, MAXSIZE) ** ** This an SQL function used to help in testing the memvfs VFS. The ** function reads the content of a file into memory and then returns -** a string that gives the locate and size of the in-memory buffer. +** a URI that can be handed to ATTACH to attach the memory buffer as +** a database. Example: +** +** ATTACH memvfs_from_file('test.db',1048576) AS inmem; +** +** The optional MAXSIZE argument gives the size of the memory allocation +** used to hold the database. If omitted, it defaults to the size of the +** file on disk. */ #include -static void memvfsMemloadFunc( +static void memvfsFromFileFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ unsigned char *p; sqlite3_int64 sz; + sqlite3_int64 szMax; FILE *in; const char *zFilename = (const char*)sqlite3_value_text(argv[0]); - char zReturn[100]; + char *zUri; if( zFilename==0 ) return; in = fopen(zFilename, "rb"); if( in==0 ) return; fseek(in, 0, SEEK_END); - sz = ftell(in); + szMax = sz = ftell(in); rewind(in); - p = sqlite3_malloc( sz ); + if( argc>=2 ){ + szMax = sqlite3_value_int64(argv[1]); + if( szMaxzName,"memvfs")!=0 ) return; + rc = sqlite3_file_control(db, zSchema, SQLITE_FCNTL_FILE_POINTER, &p); + if( rc ) return; + fwrite(p->aData, 1, (size_t)p->sz, out); + fclose(out); +} +#endif /* MEMVFS_TEST */ + +#ifdef MEMVFS_TEST /* Called for each new database connection */ static int memvfsRegister( sqlite3 *db, - const char **pzErrMsg, + char **pzErrMsg, const struct sqlite3_api_routines *pThunk ){ - return sqlite3_create_function(db, "memload", 1, SQLITE_UTF8, 0, - memvfsMemloadFunc, 0, 0); + sqlite3_create_function(db, "memvfs_from_file", 1, SQLITE_UTF8, 0, + memvfsFromFileFunc, 0, 0); + sqlite3_create_function(db, "memvfs_from_file", 2, SQLITE_UTF8, 0, + memvfsFromFileFunc, 0, 0); + sqlite3_create_function(db, "memvfs_to_file", 2, SQLITE_UTF8, 0, + memvfsToFileFunc, 0, 0); + return SQLITE_OK; } #endif /* MEMVFS_TEST */ @@ -485,6 +565,9 @@ int sqlite3_memvfs_init( if( rc==SQLITE_OK ){ rc = sqlite3_auto_extension((void(*)(void))memvfsRegister); } + if( rc==SQLITE_OK ){ + rc = memvfsRegister(db, pzErrMsg, pApi); + } #endif if( rc==SQLITE_OK ) rc = SQLITE_OK_LOAD_PERMANENTLY; return rc; diff --git a/manifest b/manifest index 8af4fc7c93..b3405dc4c3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Updates\sto\sthe\ssqlite3_file_control()\sdocumentation.\s\sNo\schanges\sto\scode. -D 2018-01-02T13:48:48.784 +C Enhance\sthe\smemvfs\sextension\sso\sthat\sit\scan\sbe\sread/write. +D 2018-01-02T16:02:50.552 F Makefile.in 1b11037c5ed3399a79433cc82c59b5e36a7b3a3e4e195bb27640d0d2145e03e1 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc f68b4f9b83cfeb057b6265e0288ad653f319e2ceacca731e0f22e19617829a89 @@ -278,7 +278,7 @@ F ext/misc/fileio.c b1aa06c0f1dac277695d4529e5e976c65ab5678dcbb53a0304deaa8adc44 F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25 F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c F ext/misc/json1.c dbe086615b9546c156bf32b9378fc09383b58bd17513b866cfd24c1e15281984 -F ext/misc/memvfs.c e5225bc22e79dde6b28380f3a068ddf600683a33 +F ext/misc/memvfs.c ab36f49e02ebcdf85a1e08dc4d8599ea8f343e073ac9e0bca18a98b7e1ec9567 F ext/misc/mmapwarm.c 70b618f2d0bde43fae288ad0b7498a629f2b6f61b50a27e06fae3cd23c83af29 F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342 F ext/misc/percentile.c 92699c8cd7d517ff610e6037e56506f8904dae2e @@ -1688,7 +1688,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 39ca5fcd31c902cbade4da05125b0dbf2bc5e2b8901af1645f113c9d3dbc8209 -R 1ce62a1c4d9b56a67e8d1f1aed222781 +P 240e32ab1f2a18e3c9b92f577b1cc8f8ecb4c68c44eac863d859491e042cb72a +R e6325f7b9d9fed8be88a348d63977f27 U drh -Z d9ace2c20dd904e2b4c8de8f33d7aa5e +Z de6d00886014fb58a1b54f4eb1670d54 diff --git a/manifest.uuid b/manifest.uuid index 3dd953071f..c9ede0a08a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -240e32ab1f2a18e3c9b92f577b1cc8f8ecb4c68c44eac863d859491e042cb72a \ No newline at end of file +04c9197d589666299aef86ee6a56df63448c050274c9fba4af94f932752be237 \ No newline at end of file From 4d795ef7e4b6e673b2ab84cc2155afc72221d386 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 2 Jan 2018 18:11:11 +0000 Subject: [PATCH 36/40] In the constraint resolution logic, be careful not to cache column values in registers whose initialization might be bypassed by an OP_NoConflict opcode. Fix for ticket [dc3f932f5a147771] reported by OSSFuzz. FossilOrigin-Name: 2846458af5d029a8e4fdcc8f50873a44e57897bbfe6aee8a23a01ffc34c5579f --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/insert.c | 2 ++ test/indexexpr1.test | 11 +++++++++++ 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index b3405dc4c3..e31c0bce91 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\smemvfs\sextension\sso\sthat\sit\scan\sbe\sread/write. -D 2018-01-02T16:02:50.552 +C In\sthe\sconstraint\sresolution\slogic,\sbe\scareful\snot\sto\scache\scolumn\svalues\s\nin\sregisters\swhose\sinitialization\smight\sbe\sbypassed\sby\san\sOP_NoConflict\sopcode.\nFix\sfor\sticket\s[dc3f932f5a147771]\sreported\sby\sOSSFuzz. +D 2018-01-02T18:11:11.985 F Makefile.in 1b11037c5ed3399a79433cc82c59b5e36a7b3a3e4e195bb27640d0d2145e03e1 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc f68b4f9b83cfeb057b6265e0288ad653f319e2ceacca731e0f22e19617829a89 @@ -440,7 +440,7 @@ F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4 F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c cb67cc56ef2ddd13e6944b2c0dd08a920bcd9503230adef8b9928d338097c722 +F src/insert.c 14686083cedc198540b15a79586cdd4be2acf6d5fa97627e355f817ab07e9fee F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e F src/loadext.c 55bcc3c741059a1056859e8adaf133aa179e22be12215c0936b2f354ef71209b F src/main.c 690c4134f944cbd5b71d59dd6e61ce4131f6a50ab774f38108e57d07d79cf876 @@ -969,7 +969,7 @@ F test/index7.test 7feababe16f2091b229c22aff2bcc1d4d6b9d2bb F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7 F test/index9.test 0aa3e509dddf81f93380396e40e9bb386904c1054924ba8fa9bcdfe85a8e7721 F test/indexedby.test faa585e315e868f09bce0eb39c41d6134649b13d2801638294d3ae616edf1609 -F test/indexexpr1.test 84100e880154a4b645db9f4fc7642756d9a2b6011b68f73c8efda4d244816de9 +F test/indexexpr1.test 60e2d6f1d1337fd213208270295c650d268503ff215de728f540ea31eb237f70 F test/indexexpr2.test 13247bac49143196556eb3f65e97ef301bd3e993f4511558b5db322ddc370ea6 F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7 @@ -1688,7 +1688,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 240e32ab1f2a18e3c9b92f577b1cc8f8ecb4c68c44eac863d859491e042cb72a -R e6325f7b9d9fed8be88a348d63977f27 +P 04c9197d589666299aef86ee6a56df63448c050274c9fba4af94f932752be237 +R 264e263a982eceab94b4544263056f03 U drh -Z de6d00886014fb58a1b54f4eb1670d54 +Z 317cb96d5817cef99d6f004b6578f45e diff --git a/manifest.uuid b/manifest.uuid index c9ede0a08a..710f42fb8d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -04c9197d589666299aef86ee6a56df63448c050274c9fba4af94f932752be237 \ No newline at end of file +2846458af5d029a8e4fdcc8f50873a44e57897bbfe6aee8a23a01ffc34c5579f \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index f0af0fbd10..e1514692cc 100644 --- a/src/insert.c +++ b/src/insert.c @@ -1571,6 +1571,7 @@ void sqlite3GenerateConstraintChecks( } /* Check to see if the new index entry will be unique */ + sqlite3ExprCachePush(pParse); sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk, regIdx, pIdx->nKeyCol); VdbeCoverage(v); @@ -1659,6 +1660,7 @@ void sqlite3GenerateConstraintChecks( } } sqlite3VdbeResolveLabel(v, addrUniqueOk); + sqlite3ExprCachePop(pParse); if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField); } if( ipkTop ){ diff --git a/test/indexexpr1.test b/test/indexexpr1.test index 0e24c8066f..1caa3086be 100644 --- a/test/indexexpr1.test +++ b/test/indexexpr1.test @@ -401,5 +401,16 @@ do_execsql_test indexexpr1-1430 { SELECT abs(15+3) IN (SELECT 17 UNION ALL SELECT 18) FROM t1; } {1 1} +# 2018-01-02 ticket https://sqlite.org/src/info/dc3f932f5a147771 +# A REPLACE into a table that uses an index on an expression causes +# an assertion fault. Problem discovered by OSSFuzz. +# +do_execsql_test indexexpr1-1500 { + CREATE TABLE t1500(a INT PRIMARY KEY, b INT UNIQUE); + CREATE INDEX t1500ab ON t1500(a*b); + INSERT INTO t1500(a,b) VALUES(1,2); + REPLACE INTO t1500(a,b) VALUES(1,3); -- formerly caused assertion fault + SELECT * FROM t1500; +} {1 3} finish_test From d9620b8555f1bd62847400b8c9d8d3c2adf60ccb Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 2 Jan 2018 21:29:42 +0000 Subject: [PATCH 37/40] Fix code indentation. No logic changes. FossilOrigin-Name: e115f2583499df0c7ee991d372bed4b89aa717b10a4e4b10977864390cb4fc11 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/pager.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index e31c0bce91..774549626b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\sconstraint\sresolution\slogic,\sbe\scareful\snot\sto\scache\scolumn\svalues\s\nin\sregisters\swhose\sinitialization\smight\sbe\sbypassed\sby\san\sOP_NoConflict\sopcode.\nFix\sfor\sticket\s[dc3f932f5a147771]\sreported\sby\sOSSFuzz. -D 2018-01-02T18:11:11.985 +C Fix\scode\sindentation.\s\sNo\slogic\schanges. +D 2018-01-02T21:29:42.540 F Makefile.in 1b11037c5ed3399a79433cc82c59b5e36a7b3a3e4e195bb27640d0d2145e03e1 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc f68b4f9b83cfeb057b6265e0288ad653f319e2ceacca731e0f22e19617829a89 @@ -465,7 +465,7 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 F src/os_unix.c 7fc2735390a7809d5d893ed735d994ff12521224b89738226fff6f1a0aa1c932 F src/os_win.c 0a4afa35cc8e812000df3ea2f64b476131b39e29e75d8007d0504726e4761de4 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a -F src/pager.c 07cf850241667874fcce9d7d924c814305e499b26c804322e2261247b5921903 +F src/pager.c 9b9cb4e06c03d43d62480a7a685a012d645fcf3a39e7767ccb505fb41ee083ec F src/pager.h 581698f2177e8bd4008fe4760898ce20b6133d1df22139b9101b5155f900df7a F src/parse.y 44cbbc3e132ea128258eff7be7f6d5c5dfa25522f89ec8b5501276966511bd50 F src/pcache.c 7ae91a4557a43d77d449accbfdc68846e6516f8e2eda46e8bbe4536fb669b201 @@ -1688,7 +1688,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 04c9197d589666299aef86ee6a56df63448c050274c9fba4af94f932752be237 -R 264e263a982eceab94b4544263056f03 +P 2846458af5d029a8e4fdcc8f50873a44e57897bbfe6aee8a23a01ffc34c5579f +R 9613ba300b7bd9cce413f2672960fb05 U drh -Z 317cb96d5817cef99d6f004b6578f45e +Z 9fca118926b581510cc96e0ce3702687 diff --git a/manifest.uuid b/manifest.uuid index 710f42fb8d..4bf24d86c2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2846458af5d029a8e4fdcc8f50873a44e57897bbfe6aee8a23a01ffc34c5579f \ No newline at end of file +e115f2583499df0c7ee991d372bed4b89aa717b10a4e4b10977864390cb4fc11 \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index dbb7636ca7..295cbe04c5 100644 --- a/src/pager.c +++ b/src/pager.c @@ -5579,7 +5579,7 @@ static int getPageMMap( } if( pPg==0 ){ rc = pagerAcquireMapPage(pPager, pgno, pData, &pPg); - }else{ + }else{ sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1)*pPager->pageSize, pData); } if( pPg ){ From 9eb8dbad4d09d3f65444f667f92d7ad38739e178 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 3 Jan 2018 01:47:30 +0000 Subject: [PATCH 38/40] Add another test case (found by OSSFuzz) for the problem fixed in check-in [2846458a] and described by ticket [dc3f932f5a147771]. No changes to code. FossilOrigin-Name: 4165fae920a1176c68bfaa1f2cfe17df7f8dd8793519d458b71e3e63670b5495 --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/indexexpr1.test | 12 ++++++++++++ 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 774549626b..ab818a843a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\scode\sindentation.\s\sNo\slogic\schanges. -D 2018-01-02T21:29:42.540 +C Add\sanother\stest\scase\s(found\sby\sOSSFuzz)\sfor\sthe\sproblem\sfixed\sin\s\ncheck-in\s[2846458a]\sand\sdescribed\sby\sticket\s[dc3f932f5a147771].\nNo\schanges\sto\scode. +D 2018-01-03T01:47:30.287 F Makefile.in 1b11037c5ed3399a79433cc82c59b5e36a7b3a3e4e195bb27640d0d2145e03e1 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc f68b4f9b83cfeb057b6265e0288ad653f319e2ceacca731e0f22e19617829a89 @@ -969,7 +969,7 @@ F test/index7.test 7feababe16f2091b229c22aff2bcc1d4d6b9d2bb F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7 F test/index9.test 0aa3e509dddf81f93380396e40e9bb386904c1054924ba8fa9bcdfe85a8e7721 F test/indexedby.test faa585e315e868f09bce0eb39c41d6134649b13d2801638294d3ae616edf1609 -F test/indexexpr1.test 60e2d6f1d1337fd213208270295c650d268503ff215de728f540ea31eb237f70 +F test/indexexpr1.test ace1ad489adc25325ad298434f13b1a515b36bf5dca9fe2a4b66cdf17aea3fa0 F test/indexexpr2.test 13247bac49143196556eb3f65e97ef301bd3e993f4511558b5db322ddc370ea6 F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7 @@ -1688,7 +1688,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 2846458af5d029a8e4fdcc8f50873a44e57897bbfe6aee8a23a01ffc34c5579f -R 9613ba300b7bd9cce413f2672960fb05 +P e115f2583499df0c7ee991d372bed4b89aa717b10a4e4b10977864390cb4fc11 +R 83a0b36c500269c331a5b5ebe1ebb55e U drh -Z 9fca118926b581510cc96e0ce3702687 +Z 192675b51835fbb18bda08bad08dd763 diff --git a/manifest.uuid b/manifest.uuid index 4bf24d86c2..01fb7976a7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e115f2583499df0c7ee991d372bed4b89aa717b10a4e4b10977864390cb4fc11 \ No newline at end of file +4165fae920a1176c68bfaa1f2cfe17df7f8dd8793519d458b71e3e63670b5495 \ No newline at end of file diff --git a/test/indexexpr1.test b/test/indexexpr1.test index 1caa3086be..28c23b9089 100644 --- a/test/indexexpr1.test +++ b/test/indexexpr1.test @@ -413,4 +413,16 @@ do_execsql_test indexexpr1-1500 { SELECT * FROM t1500; } {1 3} +# 2018-01-03 OSSFuzz discovers another test case for the same problem +# above. +# +do_execsql_test indexexpr-1510 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(a PRIMARY KEY,b UNIQUE); + REPLACE INTO t1 VALUES(2, 1); + REPLACE INTO t1 SELECT 6,1; + CREATE INDEX t1aa ON t1(a-a); + REPLACE INTO t1 SELECT a, randomblob(a) FROM t1 +} {} + finish_test From 64c1990c0044718bd3c11d238eb5be3eef48a4d8 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 4 Jan 2018 16:40:44 +0000 Subject: [PATCH 39/40] Fix a broken documentation hyperlink. No code changes. FossilOrigin-Name: d91e3f3d343d281af374dd23eea333e61228539023ad5c5aea622085e5863bc7 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/sqlite.h.in | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index ab818a843a..d48a41447d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sanother\stest\scase\s(found\sby\sOSSFuzz)\sfor\sthe\sproblem\sfixed\sin\s\ncheck-in\s[2846458a]\sand\sdescribed\sby\sticket\s[dc3f932f5a147771].\nNo\schanges\sto\scode. -D 2018-01-03T01:47:30.287 +C Fix\sa\sbroken\sdocumentation\shyperlink.\s\sNo\scode\schanges. +D 2018-01-04T16:40:44.063 F Makefile.in 1b11037c5ed3399a79433cc82c59b5e36a7b3a3e4e195bb27640d0d2145e03e1 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc f68b4f9b83cfeb057b6265e0288ad653f319e2ceacca731e0f22e19617829a89 @@ -480,7 +480,7 @@ F src/resolve.c bbee7e31d369a18a2f4836644769882e9c5d40ef4a3af911db06410b65cb3730 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c 8b22abe193e4d8243befa2038e4ae2405802fed1c446e5e502d11f652e09ba74 F src/shell.c.in a418ddceef7a2789f18bdc2bcdd481b2562fe4a7754b8009c8dd33d5a67da332 -F src/sqlite.h.in c597ba5d11666bb2d0179a173cd25e44f0b0333f9e18ce60b07eac8bdc3de67f +F src/sqlite.h.in 1f1a2da222ec57465794e8984d77f32d0bd0da80cdc136beadda461a0be9d80c F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34 F src/sqliteInt.h fd8702c65994d7de3e2d8f7d85d958731da1ed29476571fdfa2290fd8ec0bf80 @@ -1688,7 +1688,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P e115f2583499df0c7ee991d372bed4b89aa717b10a4e4b10977864390cb4fc11 -R 83a0b36c500269c331a5b5ebe1ebb55e +P 4165fae920a1176c68bfaa1f2cfe17df7f8dd8793519d458b71e3e63670b5495 +R d66f50893f4ffe9e2cfb6738dd929b34 U drh -Z 192675b51835fbb18bda08bad08dd763 +Z 6dbec8e8e1444dbd0ed402b28d5f012a diff --git a/manifest.uuid b/manifest.uuid index 01fb7976a7..66b07243fd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4165fae920a1176c68bfaa1f2cfe17df7f8dd8793519d458b71e3e63670b5495 \ No newline at end of file +d91e3f3d343d281af374dd23eea333e61228539023ad5c5aea622085e5863bc7 \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index a6d328360a..f63b029312 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -8301,7 +8301,7 @@ int sqlite3_vtab_on_conflict(sqlite3 *); ** CAPI3REF: Determine The Collation For a Virtual Table Constraint ** ** This function may only be called from within a call to the [xBestIndex] -** method of a [virtual table implementation]. +** method of a [virtual table]. ** ** The first argument must be the sqlite3_index_info object that is the ** first parameter to the xBestIndex() method. The second argument must be From 35100fb194cfbaf75b31b504e7bf7d4480900c26 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 4 Jan 2018 19:20:37 +0000 Subject: [PATCH 40/40] Remove the snarky "_supported_" qualifier from the name of the sqlite_offset() SQL function. FossilOrigin-Name: a6eee0fcd89d3958f8720ebdb5f0a8558b4795d747128091dae283eb81c4f74f --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/func.c | 3 +-- test/func6.test | 40 ++++++++++++++++++++-------------------- 4 files changed, 29 insertions(+), 30 deletions(-) diff --git a/manifest b/manifest index d48a41447d..3552e5e8ce 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sbroken\sdocumentation\shyperlink.\s\sNo\scode\schanges. -D 2018-01-04T16:40:44.063 +C Remove\sthe\ssnarky\s"_supported_"\squalifier\sfrom\sthe\sname\sof\sthe\nsqlite_offset()\sSQL\sfunction. +D 2018-01-04T19:20:37.203 F Makefile.in 1b11037c5ed3399a79433cc82c59b5e36a7b3a3e4e195bb27640d0d2145e03e1 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc f68b4f9b83cfeb057b6265e0288ad653f319e2ceacca731e0f22e19617829a89 @@ -434,7 +434,7 @@ F src/delete.c 74667ad914ac143731a444a1bacf29ceb18f6eded8a0dd17aafae80baa07f8bb F src/expr.c ad6e7a9c34a4bab9d10cc857d647ae7ce370a633b5c0bfa71f1c29b81ae364b8 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c d617daf66b5515e2b42c1405b2b4984c30ca50fb705ab164271a9bf66c69e331 -F src/func.c 697a3ee3b8c8481db497226e9e71935727d6a9fb3d3cc049e82a1c717a0a8342 +F src/func.c bd528d5ed68ce5cbf78a762e3b735fa75009f7197ff07fab07fd771f35ebaa1b F src/global.c ac3094f1dc59fbeb919aef7cc0cc827a8459d1fb1adb7972ef75bd9e0c10b75b F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4 @@ -917,7 +917,7 @@ F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f F test/func3.test d202a7606d23f90988a664e88e268aed1087c11c F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f F test/func5.test cdd224400bc3e48d891827cc913a57051a426fa4 -F test/func6.test 1a2bc511fedb779e2bd3154361385216c6d35080f36bfe896b8cdd1b1954294a +F test/func6.test a4281c8fcd42b56f7a60f28e8e4d444e8b2256f9e82658b7ab87699f8318f564 F test/fuzz-oss1.test e58330d01cbbd8215ee636b17a03fe220b37dbfa F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1 F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1 @@ -1688,7 +1688,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 4165fae920a1176c68bfaa1f2cfe17df7f8dd8793519d458b71e3e63670b5495 -R d66f50893f4ffe9e2cfb6738dd929b34 +P d91e3f3d343d281af374dd23eea333e61228539023ad5c5aea622085e5863bc7 +R 314fe8cfc8ec7f02f3acb6e4d50707fb U drh -Z 6dbec8e8e1444dbd0ed402b28d5f012a +Z 7ea7a34ef1d7c0cfd34c8e9e5f226383 diff --git a/manifest.uuid b/manifest.uuid index 66b07243fd..561f8b3f92 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d91e3f3d343d281af374dd23eea333e61228539023ad5c5aea622085e5863bc7 \ No newline at end of file +a6eee0fcd89d3958f8720ebdb5f0a8558b4795d747128091dae283eb81c4f74f \ No newline at end of file diff --git a/src/func.c b/src/func.c index 4758b0191d..1076b97161 100644 --- a/src/func.c +++ b/src/func.c @@ -1800,8 +1800,7 @@ void sqlite3RegisterBuiltinFunctions(void){ FUNCTION2(affinity, 1, 0, 0, noopFunc, SQLITE_FUNC_AFFINITY), #endif #ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC - FUNCTION2(sqlite_unsupported_offset, - 1, 0, 0, noopFunc, SQLITE_FUNC_OFFSET| + FUNCTION2(sqlite_offset, 1, 0, 0, noopFunc, SQLITE_FUNC_OFFSET| SQLITE_FUNC_TYPEOF), #endif FUNCTION(ltrim, 1, 1, 0, trimFunc ), diff --git a/test/func6.test b/test/func6.test index 0d3de8ef49..02e1998cd0 100644 --- a/test/func6.test +++ b/test/func6.test @@ -9,7 +9,7 @@ # #************************************************************************* # -# Test cases for the sqlite_unsupported_offset() function. +# Test cases for the sqlite_offset() function. # # Some of the tests in this file depend on the exact placement of content # within b-tree pages. Such placement is at the implementations discretion, @@ -34,51 +34,51 @@ do_execsql_test func6-100 { INSERT INTO t2(x,y) SELECT a, b FROM t1; } do_execsql_test func6-110 { - SELECT a, sqlite_unsupported_offset(d)/4096 + 1, - sqlite_unsupported_offset(d)%4096 FROM t1 + SELECT a, sqlite_offset(d)/4096 + 1, + sqlite_offset(d)%4096 FROM t1 ORDER BY rowid LIMIT 2; } {abc001 2 4084 abc002 2 4069} do_execsql_test func6-120 { - SELECT a, typeof(sqlite_unsupported_offset(+a)) FROM t1 + SELECT a, typeof(sqlite_offset(+a)) FROM t1 ORDER BY rowid LIMIT 2; } {abc001 null abc002 null} do_execsql_test func6-130 { - SELECT a, sqlite_unsupported_offset(a)/4096+1, - sqlite_unsupported_offset(a)%4096 + SELECT a, sqlite_offset(a)/4096+1, + sqlite_offset(a)%4096 FROM t1 ORDER BY a LIMIT 2; } {abc001 3 4087 abc002 3 4076} do_execsql_test func6-140 { - SELECT a, sqlite_unsupported_offset(d)/4096+1, - sqlite_unsupported_offset(d)%4096 + SELECT a, sqlite_offset(d)/4096+1, + sqlite_offset(d)%4096 FROM t1 ORDER BY a LIMIT 2; } {abc001 2 4084 abc002 2 4069} do_execsql_test func6-150 { SELECT a, - sqlite_unsupported_offset(a)/4096+1, - sqlite_unsupported_offset(a)%4096, - sqlite_unsupported_offset(d)/4096+1, - sqlite_unsupported_offset(d)%4096 + sqlite_offset(a)/4096+1, + sqlite_offset(a)%4096, + sqlite_offset(d)/4096+1, + sqlite_offset(d)%4096 FROM t1 ORDER BY a LIMIT 2; } {abc001 3 4087 2 4084 abc002 3 4076 2 4069} do_execsql_test func6-160 { SELECT b, - sqlite_unsupported_offset(b)/4096+1, - sqlite_unsupported_offset(b)%4096, - sqlite_unsupported_offset(c)/4096+1, - sqlite_unsupported_offset(c)%4096, - sqlite_unsupported_offset(d)/4096+1, - sqlite_unsupported_offset(d)%4096 + sqlite_offset(b)/4096+1, + sqlite_offset(b)%4096, + sqlite_offset(c)/4096+1, + sqlite_offset(c)%4096, + sqlite_offset(d)/4096+1, + sqlite_offset(d)%4096 FROM t1 ORDER BY b LIMIT 2; } {1 4 4090 4 4090 2 4084 2 4 4081 4 4081 2 4069} do_execsql_test func6-200 { - SELECT y, sqlite_unsupported_offset(y)/4096+1, - sqlite_unsupported_offset(y)%4096 + SELECT y, sqlite_offset(y)/4096+1, + sqlite_offset(y)%4096 FROM t2 ORDER BY x LIMIT 2; } {1 5 4087 2 5 4076}