From 2476a6f2cb071b4ea17a99b1ddc05111cd1422f4 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 7 Nov 2015 15:19:59 +0000 Subject: [PATCH 01/23] Enhance TreeView to show WITH clauses. Add an assert to detect the infinite loop behavior when certain kinds of errors occur on a nested WITH clause. FossilOrigin-Name: 2040d88e877bdb69de125a047cefb4a1558e89e8 --- manifest | 19 +++++++++++-------- manifest.uuid | 2 +- src/select.c | 3 ++- src/sqliteInt.h | 1 + src/treeview.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 59 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 782863019b..f844244b93 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\sOPFLAG_SEEKEQ\soptimization\sis\sonly\sapplicable\sto\sequality\scomparisons\nagainst\san\sindex,\snot\sagainst\sa\srowid\stable. -D 2015-11-07T01:19:00.997 +C Enhance\sTreeView\sto\sshow\sWITH\sclauses.\s\sAdd\san\sassert\sto\sdetect\sthe\ninfinite\sloop\sbehavior\swhen\scertain\skinds\sof\serrors\soccur\son\sa\snested\nWITH\sclause. +D 2015-11-07T15:19:59.796 F Makefile.in 3a705bb4bd12e194212ddbdbf068310d17153cdb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 702d3e98f3afc6587a78481257f3c4c900efc3a4 @@ -340,12 +340,12 @@ F src/printf.c 0c4bcdd1c2e2521024f0a69cb5eb334f86b3652a F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c 1954a0f01bf65d78d7d559aea3d5c67f33376d91 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e -F src/select.c 167b4e9058bc8e997d18d6b6b20ecbb0c9c457af +F src/select.c f5b0518eeb623ab4e6883a04b19602e5f914cfd7 F src/shell.c d25df04168d6ba5a4fa05bdbf859df667f9eb621 F src/sqlite.h.in 3cfc86c55e57c63d86b9e1e92869e2bfb162ca8e F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 4b66e3e3435da4b4c8c83696d0349f0c503b3924 -F src/sqliteInt.h 12ff325b433c4ded39995b74b01b78aacc19805a +F src/sqliteInt.h a6cddd46ae93372eb3b1acd4f2f23c4de02a94d6 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e @@ -397,7 +397,7 @@ F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c bbfb74450643cb5372a43ad4f6cffd7e9dfcecb0 F src/tokenize.c 338bc8f7c9dd103188952cda7964696bacac6d22 -F src/treeview.c 154f0acc622fa3514de8777dcedf4c8a8802b4ce +F src/treeview.c 78842e90c1f71269e7a73a1d4221b6fe360bab66 F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f F src/update.c 40e51cd0883cb5bfd6abb7d8a7cd8aa47fab2945 F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c @@ -1400,7 +1400,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P dd9a26ecdeaef7b0b9cbf4ff70448ab13a276b4e -R 37fd8f25666e5cc61c467cdb94b7bb71 +P 0f5b147d1fe83c34d0fbeacc7422be94d8441bc1 +R 62a6359affd853c29ced84c847c76120 +T *branch * infinite-with-loop-bug +T *sym-infinite-with-loop-bug * +T -sym-trunk * U drh -Z b3bf4f06c783a2156de71d3cb1963976 +Z 3b853d83f7a6a14368bd6ec3d809b3a9 diff --git a/manifest.uuid b/manifest.uuid index f7a057f393..70e1510060 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0f5b147d1fe83c34d0fbeacc7422be94d8441bc1 \ No newline at end of file +2040d88e877bdb69de125a047cefb4a1558e89e8 \ No newline at end of file diff --git a/src/select.c b/src/select.c index 8db983891f..456271365f 100644 --- a/src/select.c +++ b/src/select.c @@ -3972,7 +3972,7 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){ ** object that the returned CTE belongs to. */ static struct Cte *searchWith( - With *pWith, /* Current outermost WITH clause */ + With *pWith, /* Current innermost WITH clause */ struct SrcList_item *pItem, /* FROM clause element to resolve */ With **ppContext /* OUT: WITH clause return value belongs to */ ){ @@ -4005,6 +4005,7 @@ static struct Cte *searchWith( void sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){ assert( bFree==0 || pParse->pWith==0 ); if( pWith ){ + assert( pParse->pWith!=pWith ); pWith->pOuter = pParse->pWith; pParse->pWith = pWith; pParse->bFreeWith = bFree; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 2b9ece78e2..8956c43b06 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3271,6 +3271,7 @@ char *sqlite3VMPrintf(sqlite3*,const char*, va_list); void sqlite3TreeViewExpr(TreeView*, const Expr*, u8); void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*); void sqlite3TreeViewSelect(TreeView*, const Select*, u8); + void sqlite3TreeViewWith(TreeView*, const With*, u8); #endif diff --git a/src/treeview.c b/src/treeview.c index 971de4e8bc..a26e9e2b9f 100644 --- a/src/treeview.c +++ b/src/treeview.c @@ -79,6 +79,45 @@ static void sqlite3TreeViewItem(TreeView *p, const char *zLabel,u8 moreFollows){ sqlite3TreeViewLine(p, "%s", zLabel); } +/* +** Generate a human-readable description of a WITH clause. +*/ +void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 moreToFollow){ + int i; + if( pWith==0 ) return; + if( pWith->nCte==0 ) return; + if( pWith->pOuter ){ + sqlite3TreeViewLine(pView, "WITH (0x%p, pOuter=0x%p)",pWith,pWith->pOuter); + }else{ + sqlite3TreeViewLine(pView, "WITH (0x%p)", pWith); + } + if( pWith->nCte>0 ){ + pView = sqlite3TreeViewPush(pView, 1); + for(i=0; inCte; i++){ + StrAccum x; + char zLine[1000]; + const struct Cte *pCte = &pWith->a[i]; + sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); + sqlite3XPrintf(&x, 0, "%s", pCte->zName); + if( pCte->pCols && pCte->pCols->nExpr>0 ){ + char cSep = '('; + int j; + for(j=0; jpCols->nExpr; j++){ + sqlite3XPrintf(&x, 0, "%c%s", cSep, pCte->pCols->a[j].zName); + cSep = ','; + } + sqlite3XPrintf(&x, 0, ")"); + } + sqlite3XPrintf(&x, 0, " AS"); + sqlite3StrAccumFinish(&x); + sqlite3TreeViewItem(pView, zLine, inCte-1); + sqlite3TreeViewSelect(pView, pCte->pSelect, 0); + sqlite3TreeViewPop(pView); + } + sqlite3TreeViewPop(pView); + } +} + /* ** Generate a human-readable description of a the Select object. @@ -87,6 +126,11 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){ int n = 0; int cnt = 0; pView = sqlite3TreeViewPush(pView, moreToFollow); + if( p->pWith ){ + sqlite3TreeViewWith(pView, p->pWith, 1); + cnt = 1; + sqlite3TreeViewPush(pView, 1); + } do{ sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p) selFlags=0x%x", ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""), From 6e7722669ec0080c1fec7d315460b77aecbd9e4f Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 7 Nov 2015 17:48:21 +0000 Subject: [PATCH 02/23] Proposed fix for an infinite loop bug in the WITH clause semantic analysis logic. FossilOrigin-Name: 028475cb17a4b50baf0e9aba9bd3403d0a5d03b0 --- manifest | 20 +++++++--------- manifest.uuid | 2 +- src/select.c | 5 ++-- src/sqliteInt.h | 2 +- src/tokenize.c | 2 +- test/with3.test | 64 +++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 79 insertions(+), 16 deletions(-) create mode 100644 test/with3.test diff --git a/manifest b/manifest index f844244b93..c81ed9bc69 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sTreeView\sto\sshow\sWITH\sclauses.\s\sAdd\san\sassert\sto\sdetect\sthe\ninfinite\sloop\sbehavior\swhen\scertain\skinds\sof\serrors\soccur\son\sa\snested\nWITH\sclause. -D 2015-11-07T15:19:59.796 +C Proposed\sfix\sfor\san\sinfinite\sloop\sbug\sin\sthe\sWITH\sclause\ssemantic\sanalysis\nlogic. +D 2015-11-07T17:48:21.602 F Makefile.in 3a705bb4bd12e194212ddbdbf068310d17153cdb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 702d3e98f3afc6587a78481257f3c4c900efc3a4 @@ -340,12 +340,12 @@ F src/printf.c 0c4bcdd1c2e2521024f0a69cb5eb334f86b3652a F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c 1954a0f01bf65d78d7d559aea3d5c67f33376d91 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e -F src/select.c f5b0518eeb623ab4e6883a04b19602e5f914cfd7 +F src/select.c 00a2a10d4298a685d0eeb05b09ef018a2bd81bf8 F src/shell.c d25df04168d6ba5a4fa05bdbf859df667f9eb621 F src/sqlite.h.in 3cfc86c55e57c63d86b9e1e92869e2bfb162ca8e F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 4b66e3e3435da4b4c8c83696d0349f0c503b3924 -F src/sqliteInt.h a6cddd46ae93372eb3b1acd4f2f23c4de02a94d6 +F src/sqliteInt.h bc6d24460fe544323517630b1e20539146379077 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e @@ -396,7 +396,7 @@ F src/test_vfs.c 3b65d42e18b262805716bd96178c81da8f2d9283 F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c bbfb74450643cb5372a43ad4f6cffd7e9dfcecb0 -F src/tokenize.c 338bc8f7c9dd103188952cda7964696bacac6d22 +F src/tokenize.c b05b63e224a12531813efda3bcc73e9438958745 F src/treeview.c 78842e90c1f71269e7a73a1d4221b6fe360bab66 F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f F src/update.c 40e51cd0883cb5bfd6abb7d8a7cd8aa47fab2945 @@ -1331,6 +1331,7 @@ F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972 F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d F test/with1.test a1e8660be88e2eb4648f8860f831d1e38b5b5443 F test/with2.test 2b40da883658eb74ad8ad06afabe11a408e7fb87 +F test/with3.test 511bacdbe41c49cf34f9fd1bd3245fe1575bca98 F test/withM.test e97f2a8c506ab3ea9eab94e6f6072f6cc924c991 F test/without_rowid1.test 1a7b9bd51b899928d327052df9741d2fe8dbe701 F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99 @@ -1400,10 +1401,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 0f5b147d1fe83c34d0fbeacc7422be94d8441bc1 -R 62a6359affd853c29ced84c847c76120 -T *branch * infinite-with-loop-bug -T *sym-infinite-with-loop-bug * -T -sym-trunk * +P 2040d88e877bdb69de125a047cefb4a1558e89e8 +R 6cacd3ab17c16b2093b599a59893b257 U drh -Z 3b853d83f7a6a14368bd6ec3d809b3a9 +Z 3613be9f7ebbfaa0b17b40694bdae79f diff --git a/manifest.uuid b/manifest.uuid index 70e1510060..31d437d0c6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2040d88e877bdb69de125a047cefb4a1558e89e8 \ No newline at end of file +028475cb17a4b50baf0e9aba9bd3403d0a5d03b0 \ No newline at end of file diff --git a/src/select.c b/src/select.c index 456271365f..bd732e5bc8 100644 --- a/src/select.c +++ b/src/select.c @@ -4003,12 +4003,12 @@ static struct Cte *searchWith( ** statement with which it is associated. */ void sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){ - assert( bFree==0 || pParse->pWith==0 ); + assert( bFree==0 || (pParse->pWith==0 && pParse->pWithToFree==0) ); if( pWith ){ assert( pParse->pWith!=pWith ); pWith->pOuter = pParse->pWith; pParse->pWith = pWith; - pParse->bFreeWith = bFree; + if( bFree ) pParse->pWithToFree = pWith; } } @@ -4101,6 +4101,7 @@ static int withExpand( pSavedWith = pParse->pWith; pParse->pWith = pWith; sqlite3WalkSelect(pWalker, bMayRecursive ? pSel->pPrior : pSel); + pParse->pWith = pWith; for(pLeft=pSel; pLeft->pPrior; pLeft=pLeft->pPrior); pEList = pLeft->pEList; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 8956c43b06..c65e0f2051 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2754,7 +2754,6 @@ struct Parse { int nVar; /* Number of '?' variables seen in the SQL so far */ int nzVar; /* Number of available slots in azVar[] */ u8 iPkSortOrder; /* ASC or DESC for INTEGER PRIMARY KEY */ - u8 bFreeWith; /* True if pWith should be freed with parser */ u8 explain; /* True if the EXPLAIN flag is found on the query */ #ifndef SQLITE_OMIT_VIRTUALTABLE u8 declareVtab; /* True if inside sqlite3_declare_vtab() */ @@ -2781,6 +2780,7 @@ struct Parse { Table *pZombieTab; /* List of Table objects to delete after code gen */ TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */ With *pWith; /* Current WITH clause, or NULL */ + With *pWithToFree; /* Free this WITH object at the end of the parse */ }; /* diff --git a/src/tokenize.c b/src/tokenize.c index 9c1403bb29..f2b63b5cf1 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -510,7 +510,7 @@ abort_parse: sqlite3DeleteTable(db, pParse->pNewTable); } - if( pParse->bFreeWith ) sqlite3WithDelete(db, pParse->pWith); + sqlite3WithDelete(db, pParse->pWithToFree); sqlite3DeleteTrigger(db, pParse->pNewTrigger); for(i=pParse->nzVar-1; i>=0; i--) sqlite3DbFree(db, pParse->azVar[i]); sqlite3DbFree(db, pParse->azVar); diff --git a/test/with3.test b/test/with3.test new file mode 100644 index 0000000000..62e88441ab --- /dev/null +++ b/test/with3.test @@ -0,0 +1,64 @@ +# 2015-11-07 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# This file implements regression tests for SQLite library. The +# focus of this file is testing the WITH clause. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set ::testprefix with3 + +ifcapable {!cte} { + finish_test + return +} + +# Test problems found by Kostya Serebryany using +# LibFuzzer. (http://llvm.org/docs/LibFuzzer.html) +# +do_catchsql_test 1.0 { + WITH i(x) AS ( + WITH j AS (SELECT 10) + SELECT 5 FROM t0 UNION SELECT 8 FROM m + ) + SELECT * FROM i; +} {1 {no such table: m}} + +# Additional test cases that came out of the work to +# fix for Kostya's problem. +# +do_execsql_test 2.0 { + WITH + x1 AS (SELECT 10), + x2 AS (SELECT 11), + x3 AS ( + SELECT * FROM x1 UNION ALL SELECT * FROM x2 + ), + x4 AS ( + WITH + x1 AS (SELECT 12), + x2 AS (SELECT 13) + SELECT * FROM x3 + ) + SELECT * FROM x4; + +} {10 11} + +do_execsql_test 2.1 { + CREATE TABLE t1(x); + WITH + x1(a) AS (values(100)) + INSERT INTO t1(x) + SELECT * FROM (WITH x2(y) AS (SELECT * FROM x1) SELECT y+a FROM x1, x2); + SELECT * FROM t1; +} {200} + +finish_test From fe88fbfc828594d00999649ab6a8dcff5db64821 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 7 Nov 2015 17:51:39 +0000 Subject: [PATCH 03/23] Add test cases for WITH clauses. FossilOrigin-Name: e7e65c7559ed43e7065adc2ec1bd242bf187b7c3 --- manifest | 14 +++--- manifest.uuid | 2 +- test/with1.test | 110 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 118 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index c81ed9bc69..b8a59cb2c6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Proposed\sfix\sfor\san\sinfinite\sloop\sbug\sin\sthe\sWITH\sclause\ssemantic\sanalysis\nlogic. -D 2015-11-07T17:48:21.602 +C Add\stest\scases\sfor\sWITH\sclauses. +D 2015-11-07T17:51:39.619 F Makefile.in 3a705bb4bd12e194212ddbdbf068310d17153cdb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 702d3e98f3afc6587a78481257f3c4c900efc3a4 @@ -1329,7 +1329,7 @@ F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972 F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d -F test/with1.test a1e8660be88e2eb4648f8860f831d1e38b5b5443 +F test/with1.test 05c8fc7f809f178a8a0519f02c21fe430948c895 F test/with2.test 2b40da883658eb74ad8ad06afabe11a408e7fb87 F test/with3.test 511bacdbe41c49cf34f9fd1bd3245fe1575bca98 F test/withM.test e97f2a8c506ab3ea9eab94e6f6072f6cc924c991 @@ -1401,7 +1401,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 2040d88e877bdb69de125a047cefb4a1558e89e8 -R 6cacd3ab17c16b2093b599a59893b257 -U drh -Z 3613be9f7ebbfaa0b17b40694bdae79f +P 028475cb17a4b50baf0e9aba9bd3403d0a5d03b0 +R 0a66e1cb90e0f88ea5b94da656f84e5f +U dan +Z 560670311488774642220bf984dfc3d3 diff --git a/manifest.uuid b/manifest.uuid index 31d437d0c6..c4a678277c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -028475cb17a4b50baf0e9aba9bd3403d0a5d03b0 \ No newline at end of file +e7e65c7559ed43e7065adc2ec1bd242bf187b7c3 \ No newline at end of file diff --git a/test/with1.test b/test/with1.test index 71eec61e7d..d98f33dfb0 100644 --- a/test/with1.test +++ b/test/with1.test @@ -865,4 +865,114 @@ do_catchsql_test 16.1 { SELECT * FROM i; } {1 {recursive aggregate queries not supported}} +#------------------------------------------------------------------------- +do_execsql_test 17.1 { + WITH x(a) AS ( + WITH y(b) AS (SELECT 10) + SELECT 9 UNION ALL SELECT * FROM y + ) + SELECT * FROM x +} {9 10} + +do_execsql_test 17.2 { + WITH x AS ( + WITH y(b) AS (SELECT 10) + SELECT * FROM y UNION ALL SELECT * FROM y + ) + SELECT * FROM x +} {10 10} + +do_test 17.2 { + db eval { + WITH x AS ( + WITH y(b) AS (SELECT 10) + SELECT * FROM y UNION ALL SELECT * FROM y + ) + SELECT * FROM x + } A { + # no op + } + set A(*) +} {b} + +do_catchsql_test 17.3 { + WITH i AS ( + WITH j AS (SELECT 5) + SELECT 5 FROM i UNION SELECT 8 FROM i + ) + SELECT * FROM i; +} {1 {circular reference: i}} + +do_catchsql_test 17.4 { + WITH i AS ( + WITH j AS (SELECT 5) + SELECT 5 FROM t1 UNION SELECT 8 FROM t11 + ) + SELECT * FROM i; +} {1 {no such table: t11}} + +do_execsql_test 17.5 { + WITH + x1 AS (SELECT 10), + x2 AS (SELECT * FROM x1), + x3 AS ( + WITH x1 AS (SELECT 11) + SELECT * FROM x2 UNION ALL SELECT * FROM x2 + ) + SELECT * FROM x3; +} {10 10} + +do_execsql_test 17.6 { + WITH + x1 AS (SELECT 10), + x2 AS (SELECT * FROM x1), + x3 AS ( + WITH x1 AS (SELECT 11) + SELECT * FROM x2 UNION ALL SELECT * FROM x1 + ) + SELECT * FROM x3; +} {10 11} + +do_execsql_test 17.7 { + WITH + x1 AS (SELECT 10), + x2 AS (SELECT * FROM x1), + x3 AS ( + WITH + x1 AS ( SELECT 11 ), + x4 AS ( SELECT * FROM x2 ) + SELECT * FROM x4 UNION ALL SELECT * FROM x1 + ) + SELECT * FROM x3; +} {10 11} + +do_execsql_test 17.8 { + WITH + x1 AS (SELECT 10), + x2 AS (SELECT * FROM x1), + x3 AS ( + WITH + x1 AS ( SELECT 11 ), + x4 AS ( SELECT * FROM x2 ) + SELECT * FROM x4 UNION ALL SELECT * FROM x1 + ) + SELECT * FROM x3; +} {10 11} + +do_execsql_test 17.9 { + WITH + x1 AS (SELECT 10), + x2 AS (SELECT 11), + x3 AS ( + SELECT * FROM x1 UNION ALL SELECT * FROM x2 + ), + x4 AS ( + WITH + x1 AS (SELECT 12), + x2 AS (SELECT 13) + SELECT * FROM x3 + ) + SELECT * FROM x4; +} {10 11} + finish_test From edd2260b40ce9182031f35f24aa7652bc1748d7c Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 7 Nov 2015 18:32:17 +0000 Subject: [PATCH 04/23] Enhance the sqldiff utility to deal gracefully with ALTER TABLE ADD COLUMN. FossilOrigin-Name: 7ea036ac37397ed8f6a0fa9f5bfc0994364b53dc --- manifest | 15 +++++++-------- manifest.uuid | 2 +- tool/sqldiff.c | 27 ++++++++++++++++++++------- 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/manifest b/manifest index b2a16a7394..1c72713975 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sbug\sin\sCTE\shandling\sdiscovered\sby\sLibFuzzer\sthat\scan\scause\san\sinfinite\sloop\sin\sthe\squery\splanner. -D 2015-11-07T18:07:15.260 +C Enhance\sthe\ssqldiff\sutility\sto\sdeal\sgracefully\swith\sALTER\sTABLE\sADD\sCOLUMN. +D 2015-11-07T18:32:17.087 F Makefile.in 3a705bb4bd12e194212ddbdbf068310d17153cdb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 702d3e98f3afc6587a78481257f3c4c900efc3a4 @@ -1390,7 +1390,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c -F tool/sqldiff.c b318efc2eaf7a7fac4d281a0ce736193cb2506df +F tool/sqldiff.c 37ab2cd4f0c8b4f0bbdc2f41f63f0f262e25805d F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43 F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f @@ -1401,8 +1401,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 0f5b147d1fe83c34d0fbeacc7422be94d8441bc1 e7e65c7559ed43e7065adc2ec1bd242bf187b7c3 -R 0a66e1cb90e0f88ea5b94da656f84e5f -T +closed e7e65c7559ed43e7065adc2ec1bd242bf187b7c3 -U dan -Z 97f5561994d709cf0287df4980640bc9 +P 088009efdd56160bb4eee0fbd829a529b141274e +R 6849733f18d4f768e8de91b6fdec79e9 +U drh +Z e7f3d6622d7fdf445d9b0889f3775adc diff --git a/manifest.uuid b/manifest.uuid index 576eda30af..4bc50f23f2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -088009efdd56160bb4eee0fbd829a529b141274e \ No newline at end of file +7ea036ac37397ed8f6a0fa9f5bfc0994364b53dc \ No newline at end of file diff --git a/tool/sqldiff.c b/tool/sqldiff.c index 9f0b705c40..944968fe05 100644 --- a/tool/sqldiff.c +++ b/tool/sqldiff.c @@ -558,7 +558,7 @@ static void diff_one_table(const char *zTab, FILE *out){ az = columnNames("main", zTab, &nPk, 0); az2 = columnNames("aux", zTab, &nPk2, 0); if( az && az2 ){ - for(n=0; az[n]; n++){ + for(n=0; az[n] && az2[n]; n++){ if( sqlite3_stricmp(az[n],az2[n])!=0 ) break; } } @@ -568,13 +568,15 @@ static void diff_one_table(const char *zTab, FILE *out){ || az[n] ){ /* Schema mismatch */ - fprintf(out, "DROP TABLE %s;\n", zId); + fprintf(out, "DROP TABLE %s; -- due to schema mismatch\n", zId); dump_table(zTab, out); goto end_diff_one_table; } /* Build the comparison query */ - for(n2=n; az[n2]; n2++){} + for(n2=n; az2[n2]; n2++){ + fprintf(out, "ALTER TABLE %s ADD COLUMN %s;\n", zId, safeId(az2[n2])); + } nQ = nPk2+1+2*(n2-nPk2); if( n2>nPk2 ){ zSep = "SELECT "; @@ -585,7 +587,12 @@ static void diff_one_table(const char *zTab, FILE *out){ strPrintf(&sql, ", 1%s -- changed row\n", nPk==n ? "" : ","); while( az[i] ){ strPrintf(&sql, " A.%s IS NOT B.%s, B.%s%s\n", - az[i], az[i], az[i], i==n2-1 ? "" : ","); + az[i], az2[i], az2[i], az2[i+1]==0 ? "" : ","); + i++; + } + while( az2[i] ){ + strPrintf(&sql, " B.%s IS NOT NULL, B.%s%s\n", + az2[i], az2[i], az2[i+1]==0 ? "" : ","); i++; } strPrintf(&sql, " FROM main.%s A, aux.%s B\n", zId, zId); @@ -597,7 +604,13 @@ static void diff_one_table(const char *zTab, FILE *out){ zSep = "\n AND ("; while( az[i] ){ strPrintf(&sql, "%sA.%s IS NOT B.%s%s\n", - zSep, az[i], az[i], i==n2-1 ? ")" : ""); + zSep, az[i], az2[i], az2[i+1]==0 ? ")" : ""); + zSep = " OR "; + i++; + } + while( az2[i] ){ + strPrintf(&sql, "%sB.%s IS NOT NULL%s\n", + zSep, az2[i], az2[i+1]==0 ? ")" : ""); zSep = " OR "; i++; } @@ -609,7 +622,7 @@ static void diff_one_table(const char *zTab, FILE *out){ zSep = ", "; } strPrintf(&sql, ", 2%s -- deleted row\n", nPk==n ? "" : ","); - while( az[i] ){ + while( az2[i] ){ strPrintf(&sql, " NULL, NULL%s\n", i==n2-1 ? "" : ","); i++; } @@ -628,7 +641,7 @@ static void diff_one_table(const char *zTab, FILE *out){ } strPrintf(&sql, ", 3%s -- inserted row\n", nPk==n ? "" : ","); while( az2[i] ){ - strPrintf(&sql, " 1, B.%s%s\n", az[i], i==n2-1 ? "" : ","); + strPrintf(&sql, " 1, B.%s%s\n", az2[i], az2[i+1]==0 ? "" : ","); i++; } strPrintf(&sql, " FROM aux.%s B\n", zId); From 0739e45bcd8c66cbb7dcde7f5b2b04b167069e26 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 9 Nov 2015 02:08:09 +0000 Subject: [PATCH 05/23] Small size reduction and performance increase in the parser. FossilOrigin-Name: d62cd757a69cc49c2d309e27c948610b5868632f --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/tokenize.c | 34 ++++++++++++---------------------- tool/addopcodes.tcl | 11 ++++++++--- 4 files changed, 28 insertions(+), 33 deletions(-) diff --git a/manifest b/manifest index 1c72713975..f46bfb5259 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\ssqldiff\sutility\sto\sdeal\sgracefully\swith\sALTER\sTABLE\sADD\sCOLUMN. -D 2015-11-07T18:32:17.087 +C Small\ssize\sreduction\sand\sperformance\sincrease\sin\sthe\sparser. +D 2015-11-09T02:08:09.483 F Makefile.in 3a705bb4bd12e194212ddbdbf068310d17153cdb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 702d3e98f3afc6587a78481257f3c4c900efc3a4 @@ -396,7 +396,7 @@ F src/test_vfs.c 3b65d42e18b262805716bd96178c81da8f2d9283 F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c bbfb74450643cb5372a43ad4f6cffd7e9dfcecb0 -F src/tokenize.c b05b63e224a12531813efda3bcc73e9438958745 +F src/tokenize.c c1006aa773da5725ef55e8d48f69c11d7141d011 F src/treeview.c 78842e90c1f71269e7a73a1d4221b6fe360bab66 F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f F src/update.c 40e51cd0883cb5bfd6abb7d8a7cd8aa47fab2945 @@ -1344,7 +1344,7 @@ F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5 F tool/GetTclKit.bat 8606413d3035c05373a0d7fae82ebf59ae9e16c3 -F tool/addopcodes.tcl 26892c394964c194fe96b9a79b8b9f87347c7151 +F tool/addopcodes.tcl f1fd17b639910226749d1ae006beef8f60378274 F tool/build-all-msvc.bat e42141ca3c3812315432f9813ef9eb78aa8d99c9 x F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367 F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2 @@ -1401,7 +1401,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 088009efdd56160bb4eee0fbd829a529b141274e -R 6849733f18d4f768e8de91b6fdec79e9 +P 7ea036ac37397ed8f6a0fa9f5bfc0994364b53dc +R 3231bc9f57ce7558e058f50c744abb1e U drh -Z e7f3d6622d7fdf445d9b0889f3775adc +Z db3ec02e9e575bd3c4a05b8f4b24bc15 diff --git a/manifest.uuid b/manifest.uuid index 4bc50f23f2..cf6442cb11 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7ea036ac37397ed8f6a0fa9f5bfc0994364b53dc \ No newline at end of file +d62cd757a69cc49c2d309e27c948610b5868632f \ No newline at end of file diff --git a/src/tokenize.c b/src/tokenize.c index f2b63b5cf1..81b98d593a 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -416,7 +416,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ assert( pParse->azVar==0 ); enableLookaside = db->lookaside.bEnabled; if( db->lookaside.pStart ) db->lookaside.bEnabled = 1; - while( !db->mallocFailed && zSql[i]!=0 ){ + while( zSql[i]!=0 ){ assert( i>=0 ); pParse->sLastToken.z = &zSql[i]; pParse->sLastToken.n = sqlite3GetToken((unsigned char*)&zSql[i],&tokenType); @@ -425,35 +425,25 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ pParse->rc = SQLITE_TOOBIG; break; } - switch( tokenType ){ - case TK_SPACE: { - if( db->u1.isInterrupted ){ - sqlite3ErrorMsg(pParse, "interrupt"); - pParse->rc = SQLITE_INTERRUPT; - goto abort_parse; - } + if( tokenType>=TK_SPACE ){ + assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL ); + if( db->u1.isInterrupted ){ + sqlite3ErrorMsg(pParse, "interrupt"); + pParse->rc = SQLITE_INTERRUPT; break; } - case TK_ILLEGAL: { + if( tokenType==TK_ILLEGAL ){ sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"", &pParse->sLastToken); - goto abort_parse; - } - case TK_SEMI: { - pParse->zTail = &zSql[i]; - /* Fall thru into the default case */ - } - default: { - sqlite3Parser(pEngine, tokenType, pParse->sLastToken, pParse); - lastTokenParsed = tokenType; - if( pParse->rc!=SQLITE_OK ){ - goto abort_parse; - } break; } + }else{ + if( tokenType==TK_SEMI ) pParse->zTail = &zSql[i]; + sqlite3Parser(pEngine, tokenType, pParse->sLastToken, pParse); + lastTokenParsed = tokenType; + if( pParse->rc!=SQLITE_OK || db->mallocFailed ) break; } } -abort_parse: assert( nErr==0 ); if( pParse->rc==SQLITE_OK && db->mallocFailed==0 ){ assert( zSql[i]==0 ); diff --git a/tool/addopcodes.tcl b/tool/addopcodes.tcl index c5c3525ad4..bd0b73a35f 100644 --- a/tool/addopcodes.tcl +++ b/tool/addopcodes.tcl @@ -18,7 +18,8 @@ while {![eof $in]} { } close $in -# The following are the extra token codes to be added +# The following are the extra token codes to be added. SPACE and +# ILLEGAL *must* be the last two token codes and they must be in that order. # set extras { TO_TEXT @@ -28,8 +29,6 @@ set extras { TO_REAL ISNOT END_OF_FILE - ILLEGAL - SPACE UNCLOSED_STRING FUNCTION COLUMN @@ -38,6 +37,12 @@ set extras { UMINUS UPLUS REGISTER + SPACE + ILLEGAL +} +if {[lrange $extras end-1 end]!="SPACE ILLEGAL"} { + error "SPACE and ILLEGAL must be the last two token codes and they\ + must be in that order" } foreach x $extras { incr max From d797035ac78a0854e6a4c13e03849318d92459af Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 9 Nov 2015 12:33:39 +0000 Subject: [PATCH 06/23] Avoid unnecessary function prologues in the sqlite3VdbeAddOp3() routine. FossilOrigin-Name: 7c6a19ba9b0bdb1cc0b9a9796b7c1c114944d927 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbeaux.c | 10 +++++++--- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index f46bfb5259..cd829a2bee 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Small\ssize\sreduction\sand\sperformance\sincrease\sin\sthe\sparser. -D 2015-11-09T02:08:09.483 +C Avoid\sunnecessary\sfunction\sprologues\sin\sthe\ssqlite3VdbeAddOp3()\sroutine. +D 2015-11-09T12:33:39.340 F Makefile.in 3a705bb4bd12e194212ddbdbf068310d17153cdb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 702d3e98f3afc6587a78481257f3c4c900efc3a4 @@ -407,7 +407,7 @@ F src/vdbe.c 7a9b18027414368d800716e6319e2acd699c70db F src/vdbe.h efb7a8c1459e31f3ea4377824c6a7e4cb5068637 F src/vdbeInt.h 33403622c6a8feaaac5f0f3f17f5d1bf6df42286 F src/vdbeapi.c 020681b943e77766b32ae1cddf86d7831b7374ca -F src/vdbeaux.c 6d55530b05b69bc663c87d2d258318dcdf042644 +F src/vdbeaux.c da9eddc62e025148e30267600a6fe3882d5e912f F src/vdbeblob.c 565fabd302f5fca3bdf3d56cac330483616a39b6 F src/vdbemem.c fdd1578e47bea61390d472de53c565781d81e045 F src/vdbesort.c 8b23930a1289526f6d2a3a9f2e965bcc963e4a68 @@ -1401,7 +1401,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 7ea036ac37397ed8f6a0fa9f5bfc0994364b53dc -R 3231bc9f57ce7558e058f50c744abb1e +P d62cd757a69cc49c2d309e27c948610b5868632f +R a904c99753c26b60df840fbeb9147fea U drh -Z db3ec02e9e575bd3c4a05b8f4b24bc15 +Z 04359d40d10a11f87d61acdb694f52aa diff --git a/manifest.uuid b/manifest.uuid index cf6442cb11..d3a3f51b6e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d62cd757a69cc49c2d309e27c948610b5868632f \ No newline at end of file +7c6a19ba9b0bdb1cc0b9a9796b7c1c114944d927 \ No newline at end of file diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 83a9047dc7..a5bc0b71a2 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -157,6 +157,12 @@ static void test_addop_breakpoint(void){ ** the sqlite3VdbeChangeP4() function to change the value of the P4 ** operand. */ +static SQLITE_NOINLINE int growOp3(Vdbe *p, int op, int p1, int p2, int p3){ + assert( p->pParse->nOpAlloc<=p->nOp ); + if( growOpArray(p, 1) ) return 1; + assert( p->pParse->nOpAlloc>p->nOp ); + return sqlite3VdbeAddOp3(p, op, p1, p2, p3); +} int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){ int i; VdbeOp *pOp; @@ -165,9 +171,7 @@ int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){ assert( p->magic==VDBE_MAGIC_INIT ); assert( op>0 && op<0xff ); if( p->pParse->nOpAlloc<=i ){ - if( growOpArray(p, 1) ){ - return 1; - } + return growOp3(p, op, p1, p2, p3); } p->nOp++; pOp = &p->aOp[i]; From f10b1f78ee6a3bc5aa9b10c2c090516ef49187b7 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 9 Nov 2015 12:44:19 +0000 Subject: [PATCH 07/23] Check in the cg_anno.tcl and run-speed-test.sh scripts, as an historical record. FossilOrigin-Name: 836418d3b7cfcd5ec375c4e08c09bd6b78646307 --- manifest | 12 ++++---- manifest.uuid | 2 +- tool/cg_anno.tcl | 24 +++++++++++++++ tool/run-speed-test.sh | 68 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 100 insertions(+), 6 deletions(-) create mode 100755 tool/cg_anno.tcl create mode 100644 tool/run-speed-test.sh diff --git a/manifest b/manifest index cd829a2bee..3e38a0f6ef 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Avoid\sunnecessary\sfunction\sprologues\sin\sthe\ssqlite3VdbeAddOp3()\sroutine. -D 2015-11-09T12:33:39.340 +C Check\sin\sthe\scg_anno.tcl\sand\srun-speed-test.sh\sscripts,\sas\san\shistorical\nrecord. +D 2015-11-09T12:44:19.680 F Makefile.in 3a705bb4bd12e194212ddbdbf068310d17153cdb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 702d3e98f3afc6587a78481257f3c4c900efc3a4 @@ -1347,6 +1347,7 @@ F tool/GetTclKit.bat 8606413d3035c05373a0d7fae82ebf59ae9e16c3 F tool/addopcodes.tcl f1fd17b639910226749d1ae006beef8f60378274 F tool/build-all-msvc.bat e42141ca3c3812315432f9813ef9eb78aa8d99c9 x F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367 +F tool/cg_anno.tcl 692ce4b8693d59e3a3de77ca97f4139ecfa641b0 x F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2 F tool/extract.c 054069d81b095fbdc189a6f5d4466e40380505e2 F tool/fast_vacuum.c 5ba0d6f5963a0a63bdc42840f678bad75b2ebce1 @@ -1377,6 +1378,7 @@ F tool/pagesig.c ff0ca355fd3c2398e933da5e22439bbff89b803b F tool/replace.tcl 7727c60a04299b65a92f5e1590896fea0f25b9e0 F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5 +F tool/run-speed-test.sh 0ae485af4fe9f826e2b494be8c81f8ca9e222a4a F tool/showdb.c d4476e000a64eca9f5e2c2f68741e747b9778e8d F tool/showjournal.c 5bad7ae8784a43d2b270d953060423b8bd480818 F tool/showlocks.c 9920bcc64f58378ff1118caead34147201f48c68 @@ -1401,7 +1403,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P d62cd757a69cc49c2d309e27c948610b5868632f -R a904c99753c26b60df840fbeb9147fea +P 7c6a19ba9b0bdb1cc0b9a9796b7c1c114944d927 +R 9d7a4cba8878c4f3f14011449d7a4d87 U drh -Z 04359d40d10a11f87d61acdb694f52aa +Z cd8c6de9d269073054c5419c6ba867b6 diff --git a/manifest.uuid b/manifest.uuid index d3a3f51b6e..2649680579 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7c6a19ba9b0bdb1cc0b9a9796b7c1c114944d927 \ No newline at end of file +836418d3b7cfcd5ec375c4e08c09bd6b78646307 \ No newline at end of file diff --git a/tool/cg_anno.tcl b/tool/cg_anno.tcl new file mode 100755 index 0000000000..f806c5a5af --- /dev/null +++ b/tool/cg_anno.tcl @@ -0,0 +1,24 @@ +#!/usr/bin/tclsh +# +# A wrapper around cg_annotate that sets appropriate command-line options +# and rearranges the output so that annotated files occur in a consistent +# sorted order. Used by the run-speed-test.tcl script. +# + +set in [open "|cg_annotate --show=Ir --auto=yes --context=40 $argv" r] +set dest ! +set out(!) {} +while {![eof $in]} { + set line [string map {\t { }} [gets $in]] + if {[regexp {^-- Auto-annotated source: (.*)} $line all name]} { + set dest $name + } elseif {[regexp {^-- line \d+ ------} $line]} { + set line [lreplace $line 2 2 {#}] + } elseif {[regexp {^The following files chosen for } $line]} { + set dest ! + } + append out($dest) $line\n +} +foreach x [lsort [array names out]] { + puts $out($x) +} diff --git a/tool/run-speed-test.sh b/tool/run-speed-test.sh new file mode 100644 index 0000000000..ee2ceac660 --- /dev/null +++ b/tool/run-speed-test.sh @@ -0,0 +1,68 @@ +#!/bin/bash +# +# This is a template for a script used for day-to-day size and +# performance monitoring of SQLite. Typical usage: +# +# sh run-speed-test.sh trunk # Baseline measurement of trunk +# sh run-speed-test.sh x1 # Measure some experimental change +# fossil test-diff --tk cout-trunk.txt cout-x1.txt # View chanages +# +# There are multiple output files, all with a base name given by +# the first argument: +# +# summary-$BASE.txt # Copy of standard output +# cout-$BASE.txt # cachegrind output +# explain-$BASE.txt # EXPLAIN listings +# +if test "$1" = "" +then + echo "Usage: $0 OUTPUTFILE [OPTIONS]" + exit +fi +NAME=$1 +shift +CC_OPTS="-DSQLITE_ENABLE_RTREE" +SPEEDTEST_OPTS="--shrink-memory --reprepare" +SIZE=5 +while test "$1" != ""; do + case $1 in + --reprepare) + SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1" + ;; + --autovacuum) + SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1" + ;; + --utf16be) + SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1" + ;; + --without-rowid) + SPEEDTEST_OPTS="$SPEEDTEST_OPTS $1" + ;; + --size) + shift; SIZE=$1 + ;; + *) + CC_OPTS="$CC_OPTS $1" + ;; + esac + shift +done +SPEEDTEST_OPTS="$SPEEDTEST_OPTS --size $SIZE" +echo "NAME = $NAME" | tee summary-$NAME.txt +echo "SPEEDTEST_OPTS = $SPEEDTEST_OPTS" | tee -a summary-$NAME.txt +echo "CC_OPTS = $CC_OPTS" | tee -a summary-$NAME.txt +rm -f cachegrind.out.* speedtest1 speedtest1.db sqlite3.o +gcc -g -Os -Wall -I. $CC_OPTS -c sqlite3.c +size sqlite3.o | tee -a summary-$NAME.txt +gcc -g -Os -Wall -I. $CC_OPTS \ + -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ + ./shell.c ./sqlite3.c -o sqlite3 -ldl -lpthread +SRC=./speedtest1.c +gcc -g -Os -Wall -I. $CC_OPTS $SRC ./sqlite3.o -o speedtest1 -ldl -lpthread +ls -l speedtest1 | tee -a summary-$NAME.txt +valgrind --tool=cachegrind ./speedtest1 speedtest1.db \ + $SPEEDTEST_OPTS 2>&1 | tee -a summary-$NAME.txt +size sqlite3.o | tee -a summary-$NAME.txt +wc sqlite3.c +cg_anno.tcl cachegrind.out.* >cout-$NAME.txt +./speedtest1 --explain $SPEEDTEST_OPTS | ./sqlite3 >explain-$NAME.txt From 7450494c502469e1814db2328fda725c2ed1ec8b Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 9 Nov 2015 12:47:04 +0000 Subject: [PATCH 08/23] Fix incorrect WHERE clause in sqldiff, as reported on the mailing list by Youcef Hilem. FossilOrigin-Name: e0ed4c3e376248dfbf903e4b5845f910824fa6c6 --- manifest | 12 ++++++------ manifest.uuid | 2 +- tool/sqldiff.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 3e38a0f6ef..00baa3e5e2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Check\sin\sthe\scg_anno.tcl\sand\srun-speed-test.sh\sscripts,\sas\san\shistorical\nrecord. -D 2015-11-09T12:44:19.680 +C Fix\sincorrect\sWHERE\sclause\sin\ssqldiff,\sas\sreported\son\sthe\smailing\slist\nby\sYoucef\sHilem. +D 2015-11-09T12:47:04.583 F Makefile.in 3a705bb4bd12e194212ddbdbf068310d17153cdb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 702d3e98f3afc6587a78481257f3c4c900efc3a4 @@ -1392,7 +1392,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c -F tool/sqldiff.c 37ab2cd4f0c8b4f0bbdc2f41f63f0f262e25805d +F tool/sqldiff.c 40e3458f0015290be8ecb6e03f9dbf1bb1e264c0 F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43 F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f @@ -1403,7 +1403,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 7c6a19ba9b0bdb1cc0b9a9796b7c1c114944d927 -R 9d7a4cba8878c4f3f14011449d7a4d87 +P 836418d3b7cfcd5ec375c4e08c09bd6b78646307 +R d937c57aac217cda0397e7f6695d66bb U drh -Z cd8c6de9d269073054c5419c6ba867b6 +Z 203526c61164c46fffc3cfcb2374dd46 diff --git a/manifest.uuid b/manifest.uuid index 2649680579..cfaa513cbc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -836418d3b7cfcd5ec375c4e08c09bd6b78646307 \ No newline at end of file +e0ed4c3e376248dfbf903e4b5845f910824fa6c6 \ No newline at end of file diff --git a/tool/sqldiff.c b/tool/sqldiff.c index 944968fe05..90a53fe16a 100644 --- a/tool/sqldiff.c +++ b/tool/sqldiff.c @@ -702,7 +702,7 @@ static void diff_one_table(const char *zTab, FILE *out){ for(i=0; i Date: Mon, 9 Nov 2015 14:11:37 +0000 Subject: [PATCH 09/23] Size reduction and performance improvement in the stack-popping logic of the Lemon-generated parser. FossilOrigin-Name: 9748c48a4fbd5c06208bbf80e7bfcb159ec026d9 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/lempar.c | 18 +++++------------- tool/lempar.c | 18 ++++++------------ 4 files changed, 19 insertions(+), 33 deletions(-) diff --git a/manifest b/manifest index 00baa3e5e2..6d273a47e7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sincorrect\sWHERE\sclause\sin\ssqldiff,\sas\sreported\son\sthe\smailing\slist\nby\sYoucef\sHilem. -D 2015-11-09T12:47:04.583 +C Size\sreduction\sand\sperformance\simprovement\sin\sthe\sstack-popping\slogic\sof\nthe\sLemon-generated\sparser. +D 2015-11-09T14:11:37.997 F Makefile.in 3a705bb4bd12e194212ddbdbf068310d17153cdb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 702d3e98f3afc6587a78481257f3c4c900efc3a4 @@ -303,7 +303,7 @@ F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 F src/insert.c 419a947f27ce2da18eebf440a5aa80cc825defae F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e -F src/lempar.c d344a95d60c24e2f490ee59db9784b1b17439012 +F src/lempar.c 68f7e1e9d7a19e97e81e921f35f28063cc57cc91 F src/loadext.c 18586e45a215325f15096821e9c082035d4fb810 F src/main.c f393acc6e5d604cbe0054376d62f668a5560b3f1 F src/malloc.c 337bbe9c7d436ef9b7d06b5dd10bbfc8f3025972 @@ -1357,7 +1357,7 @@ F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4 F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/lemon.c 799e73e19a33b8dd7767a7fa34618ed2a9c2397d -F tool/lempar.c 3617143ddb9b176c3605defe6a9c798793280120 +F tool/lempar.c 5ea7cad700dd4df4486e825b9149f40137efcfbb F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 F tool/mkautoconfamal.sh 4bdf61548a143e5977bd86ab93d68b694d10c8fa @@ -1403,7 +1403,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 836418d3b7cfcd5ec375c4e08c09bd6b78646307 -R d937c57aac217cda0397e7f6695d66bb +P e0ed4c3e376248dfbf903e4b5845f910824fa6c6 +R 08c66b00ee44c1ce6bc53eab9d896126 U drh -Z 203526c61164c46fffc3cfcb2374dd46 +Z 114def794faa9ab9a746aed1255c1eea diff --git a/manifest.uuid b/manifest.uuid index cfaa513cbc..06f04d2a29 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e0ed4c3e376248dfbf903e4b5845f910824fa6c6 \ No newline at end of file +9748c48a4fbd5c06208bbf80e7bfcb159ec026d9 \ No newline at end of file diff --git a/src/lempar.c b/src/lempar.c index 5e5a11aeaa..47be43477e 100644 --- a/src/lempar.c +++ b/src/lempar.c @@ -332,27 +332,19 @@ static void yy_destructor( ** ** If there is a destructor routine associated with the token which ** is popped from the stack, then call it. -** -** Return the major token number for the symbol popped. */ -static int yy_pop_parser_stack(yyParser *pParser){ - YYCODETYPE yymajor; - yyStackEntry *yytos = &pParser->yystack[pParser->yyidx]; - - /* There is no mechanism by which the parser stack can be popped below - ** empty in SQLite. */ +static void yy_pop_parser_stack(yyParser *pParser){ + yyStackEntry *yytos; assert( pParser->yyidx>=0 ); + yytos = &pParser->yystack[pParser->yyidx--]; #ifndef NDEBUG - if( yyTraceFILE && pParser->yyidx>=0 ){ + if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sPopping %s\n", yyTracePrompt, yyTokenName[yytos->major]); } #endif - yymajor = yytos->major; - yy_destructor(pParser, yymajor, &yytos->minor); - pParser->yyidx--; - return yymajor; + yy_destructor(pParser, yytos->major, &yytos->minor); } /* diff --git a/tool/lempar.c b/tool/lempar.c index cdf4ca5a1a..1b2b1798b4 100644 --- a/tool/lempar.c +++ b/tool/lempar.c @@ -326,25 +326,19 @@ static void yy_destructor( ** ** If there is a destructor routine associated with the token which ** is popped from the stack, then call it. -** -** Return the major token number for the symbol popped. */ -static int yy_pop_parser_stack(yyParser *pParser){ - YYCODETYPE yymajor; - yyStackEntry *yytos = &pParser->yystack[pParser->yyidx]; - - if( pParser->yyidx<0 ) return 0; +static void yy_pop_parser_stack(yyParser *pParser){ + yyStackEntry *yytos; + assert( pParser->yyidx>=0 ); + yytos = &pParser->yystack[pParser->yyidx--]; #ifndef NDEBUG - if( yyTraceFILE && pParser->yyidx>=0 ){ + if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sPopping %s\n", yyTracePrompt, yyTokenName[yytos->major]); } #endif - yymajor = yytos->major; - yy_destructor(pParser, yymajor, &yytos->minor); - pParser->yyidx--; - return yymajor; + yy_destructor(pParser, yytos->major, &yytos->minor); } /* From a441404f9215f9a8e7544a4b52899ee3e19b1dff Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 9 Nov 2015 15:06:26 +0000 Subject: [PATCH 10/23] Avoid recursion in the yy_find_shift_action() routine of the Lemon-generated parser, so that routine can be inlined, for a size reduction and performance increase. FossilOrigin-Name: 0557a179f932296cc1fd5217f9a0d2f74e34ce1d --- manifest | 14 ++++---- manifest.uuid | 2 +- src/lempar.c | 83 ++++++++++++++++++++++++---------------------- tool/lempar.c | 92 ++++++++++++++++++++++++++++----------------------- 4 files changed, 103 insertions(+), 88 deletions(-) diff --git a/manifest b/manifest index 6d273a47e7..de4332e89f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Size\sreduction\sand\sperformance\simprovement\sin\sthe\sstack-popping\slogic\sof\nthe\sLemon-generated\sparser. -D 2015-11-09T14:11:37.997 +C Avoid\srecursion\sin\sthe\syy_find_shift_action()\sroutine\sof\sthe\sLemon-generated\nparser,\sso\sthat\sroutine\scan\sbe\sinlined,\sfor\sa\ssize\sreduction\sand\sperformance\nincrease. +D 2015-11-09T15:06:26.258 F Makefile.in 3a705bb4bd12e194212ddbdbf068310d17153cdb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 702d3e98f3afc6587a78481257f3c4c900efc3a4 @@ -303,7 +303,7 @@ F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 F src/insert.c 419a947f27ce2da18eebf440a5aa80cc825defae F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e -F src/lempar.c 68f7e1e9d7a19e97e81e921f35f28063cc57cc91 +F src/lempar.c 62dbf933df3bd95815a4207925f7e1cf31063443 F src/loadext.c 18586e45a215325f15096821e9c082035d4fb810 F src/main.c f393acc6e5d604cbe0054376d62f668a5560b3f1 F src/malloc.c 337bbe9c7d436ef9b7d06b5dd10bbfc8f3025972 @@ -1357,7 +1357,7 @@ F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4 F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/lemon.c 799e73e19a33b8dd7767a7fa34618ed2a9c2397d -F tool/lempar.c 5ea7cad700dd4df4486e825b9149f40137efcfbb +F tool/lempar.c 4ff2afb0449e9367f6cb4c8513339e3333852099 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 F tool/mkautoconfamal.sh 4bdf61548a143e5977bd86ab93d68b694d10c8fa @@ -1403,7 +1403,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P e0ed4c3e376248dfbf903e4b5845f910824fa6c6 -R 08c66b00ee44c1ce6bc53eab9d896126 +P 9748c48a4fbd5c06208bbf80e7bfcb159ec026d9 +R c9026e58b8922b5b815b58f78da1a9b7 U drh -Z 114def794faa9ab9a746aed1255c1eea +Z 94abf9709b7d536396fc03122fef0eed diff --git a/manifest.uuid b/manifest.uuid index 06f04d2a29..12c76b678c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9748c48a4fbd5c06208bbf80e7bfcb159ec026d9 \ No newline at end of file +0557a179f932296cc1fd5217f9a0d2f74e34ce1d \ No newline at end of file diff --git a/src/lempar.c b/src/lempar.c index 47be43477e..beef6cfe49 100644 --- a/src/lempar.c +++ b/src/lempar.c @@ -401,52 +401,57 @@ static int yy_find_shift_action( if( stateno>=YY_MIN_REDUCE ) return stateno; assert( stateno <= YY_SHIFT_COUNT ); - i = yy_shift_ofst[stateno]; - if( i==YY_SHIFT_USE_DFLT ) return yy_default[stateno]; - assert( iLookAhead!=YYNOCODE ); - i += iLookAhead; - if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ - if( iLookAhead>0 ){ + do{ + i = yy_shift_ofst[stateno]; + if( i==YY_SHIFT_USE_DFLT ) return yy_default[stateno]; + assert( iLookAhead!=YYNOCODE ); + i += iLookAhead; + if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ + if( iLookAhead>0 ){ #ifdef YYFALLBACK - YYCODETYPE iFallback; /* Fallback token */ - if( iLookAhead %s\n", - yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); - } -#endif - return yy_find_shift_action(pParser, iFallback); - } -#endif -#ifdef YYWILDCARD - { - int j = i - iLookAhead + YYWILDCARD; - if( -#if YY_SHIFT_MIN+YYWILDCARD<0 - j>=0 && -#endif -#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT - j %s\n", - yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[YYWILDCARD]); + fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n", + yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); + } +#endif + assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */ + iLookAhead = iFallback; + continue; + } +#endif +#ifdef YYWILDCARD + { + int j = i - iLookAhead + YYWILDCARD; + if( +#if YY_SHIFT_MIN+YYWILDCARD<0 + j>=0 && +#endif +#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT + j %s\n", + yyTracePrompt, yyTokenName[iLookAhead], + yyTokenName[YYWILDCARD]); + } +#endif /* NDEBUG */ + return yy_action[j]; } -#endif /* NDEBUG */ - return yy_action[j]; } - } #endif /* YYWILDCARD */ + } + return yy_default[stateno]; + }else{ + return yy_action[i]; } - return yy_default[stateno]; - }else{ - return yy_action[i]; - } + }while(1); } /* diff --git a/tool/lempar.c b/tool/lempar.c index 1b2b1798b4..b7408f60a2 100644 --- a/tool/lempar.c +++ b/tool/lempar.c @@ -390,55 +390,60 @@ static int yy_find_shift_action( ){ int i; int stateno = pParser->yystack[pParser->yyidx].stateno; - - if( stateno>=YY_MIN_REDUCE ) return stateno; + + if( stateno>=YY_MIN_REDUCE ) return stateno; assert( stateno <= YY_SHIFT_COUNT ); - i = yy_shift_ofst[stateno]; - if( i==YY_SHIFT_USE_DFLT ) return yy_default[stateno]; - assert( iLookAhead!=YYNOCODE ); - i += iLookAhead; - if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ - if( iLookAhead>0 ){ + do{ + i = yy_shift_ofst[stateno]; + if( i==YY_SHIFT_USE_DFLT ) return yy_default[stateno]; + assert( iLookAhead!=YYNOCODE ); + i += iLookAhead; + if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ + if( iLookAhead>0 ){ #ifdef YYFALLBACK - YYCODETYPE iFallback; /* Fallback token */ - if( iLookAhead %s\n", - yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); - } -#endif - return yy_find_shift_action(pParser, iFallback); - } -#endif -#ifdef YYWILDCARD - { - int j = i - iLookAhead + YYWILDCARD; - if( -#if YY_SHIFT_MIN+YYWILDCARD<0 - j>=0 && -#endif -#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT - j %s\n", - yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[YYWILDCARD]); + fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n", + yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); + } +#endif + assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */ + iLookAhead = iFallback; + continue; + } +#endif +#ifdef YYWILDCARD + { + int j = i - iLookAhead + YYWILDCARD; + if( +#if YY_SHIFT_MIN+YYWILDCARD<0 + j>=0 && +#endif +#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT + j %s\n", + yyTracePrompt, yyTokenName[iLookAhead], + yyTokenName[YYWILDCARD]); + } +#endif /* NDEBUG */ + return yy_action[j]; } -#endif /* NDEBUG */ - return yy_action[j]; } - } #endif /* YYWILDCARD */ + } + return yy_default[stateno]; + }else{ + return yy_action[i]; } - return yy_default[stateno]; - }else{ - return yy_action[i]; - } + }while(1); } /* @@ -618,6 +623,7 @@ static void yy_reduce( */ %% }; + assert( yyruleno>=0 && yyrulenoyyidx -= yysize; @@ -725,7 +731,9 @@ void Parse( ){ YYMINORTYPE yyminorunion; int yyact; /* The parser action. */ +#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) int yyendofinput; /* True if we are at the end of input */ +#endif #ifdef YYERRORSYMBOL int yyerrorhit = 0; /* True if yymajor has invoked an error */ #endif @@ -748,7 +756,9 @@ void Parse( yypParser->yystack[0].major = 0; } yyminorunion.yy0 = yyminor; +#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) yyendofinput = (yymajor==0); +#endif ParseARG_STORE; #ifndef NDEBUG From 82415f2d8d2ecfe22ad56762ff0f5723ed8da791 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 9 Nov 2015 19:33:42 +0000 Subject: [PATCH 11/23] Change the parser to use the standard "lempar.c" template over in the tool/ folder rather than the customized "lempar.c" found in src/. FossilOrigin-Name: 0a72991f4e54548f6c3268c5a9cac1c8d6437d26 --- Makefile.in | 4 +- Makefile.msc | 4 +- main.mk | 4 +- manifest | 21 +- manifest.uuid | 2 +- src/lempar.c | 892 -------------------------------------------------- src/parse.y | 12 + tool/lempar.c | 190 ++++++----- 8 files changed, 136 insertions(+), 993 deletions(-) delete mode 100644 src/lempar.c diff --git a/Makefile.in b/Makefile.in index 1ad64aa617..eaf021b412 100644 --- a/Makefile.in +++ b/Makefile.in @@ -645,9 +645,9 @@ sqlite3.lo: sqlite3.c # Rules to build the LEMON compiler generator # -lemon$(BEXE): $(TOP)/tool/lemon.c $(TOP)/src/lempar.c +lemon$(BEXE): $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c $(BCC) -o $@ $(TOP)/tool/lemon.c - cp $(TOP)/src/lempar.c . + cp $(TOP)/tool/lempar.c . # Rules to build individual *.o files from generated *.c files. This # applies to: diff --git a/Makefile.msc b/Makefile.msc index 408073c651..57fba11c53 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -1310,8 +1310,8 @@ sqlite3.lo: $(SQLITE3C) # Rules to build the LEMON compiler generator # -lempar.c: $(TOP)\src\lempar.c - copy $(TOP)\src\lempar.c . +lempar.c: $(TOP)\tool\lempar.c + copy $(TOP)\tool\lempar.c . lemon.exe: $(TOP)\tool\lemon.c lempar.c $(BCC) $(NO_WARN) -Daccess=_access \ diff --git a/main.mk b/main.mk index 41bcb1c7e4..838e0753d9 100644 --- a/main.mk +++ b/main.mk @@ -554,9 +554,9 @@ fts3amal.c: target_source $(TOP)/ext/fts3/mkfts3amal.tcl # Rules to build the LEMON compiler generator # -lemon: $(TOP)/tool/lemon.c $(TOP)/src/lempar.c +lemon: $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c $(BCC) -o lemon $(TOP)/tool/lemon.c - cp $(TOP)/src/lempar.c . + cp $(TOP)/tool/lempar.c . # Rules to build individual *.o files from generated *.c files. This # applies to: diff --git a/manifest b/manifest index de4332e89f..09c98aaddf 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -C Avoid\srecursion\sin\sthe\syy_find_shift_action()\sroutine\sof\sthe\sLemon-generated\nparser,\sso\sthat\sroutine\scan\sbe\sinlined,\sfor\sa\ssize\sreduction\sand\sperformance\nincrease. -D 2015-11-09T15:06:26.258 -F Makefile.in 3a705bb4bd12e194212ddbdbf068310d17153cdb +C Change\sthe\sparser\sto\suse\sthe\sstandard\s"lempar.c"\stemplate\sover\sin\sthe\stool/\nfolder\srather\sthan\sthe\scustomized\s"lempar.c"\sfound\sin\ssrc/. +D 2015-11-09T19:33:42.333 +F Makefile.in d828db6afa6c1fa060d01e33e4674408df1942a1 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc 702d3e98f3afc6587a78481257f3c4c900efc3a4 +F Makefile.msc e928e68168df69b353300ac87c10105206653a03 F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7 F VERSION 8b9d3ac6f1962f94e06ba05462422a544f9c4e36 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -263,7 +263,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk ac9746f24334056c85775dbe6b7279b84a6941d7 +F main.mk ae99be5eb22933b1ecf80f94d41d25a3ea80aaf3 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 @@ -303,7 +303,6 @@ F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 F src/insert.c 419a947f27ce2da18eebf440a5aa80cc825defae F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e -F src/lempar.c 62dbf933df3bd95815a4207925f7e1cf31063443 F src/loadext.c 18586e45a215325f15096821e9c082035d4fb810 F src/main.c f393acc6e5d604cbe0054376d62f668a5560b3f1 F src/malloc.c 337bbe9c7d436ef9b7d06b5dd10bbfc8f3025972 @@ -329,7 +328,7 @@ F src/os_win.c 1716291e5ec2dbfc5a1fe0b32182030f1f7d8acf F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c ed5cff11793b6a4146582aabb29ed8613a6cf89e F src/pager.h 7fc069c07f3120ee466ff3d48a9d376974ebffa7 -F src/parse.y 11078cd8e3af00f030505b6a86a06a4536cfdeaa +F src/parse.y 89784cfb2a421e4c2257b3dac86bb79096eaa9b9 F src/pcache.c 24be750c79272e0ca7b6e007bc94999700f3e5ef F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9 F src/pcache1.c 902e1bc7bdaa81b40f8543407c5e2ac8ef4dc035 @@ -1357,7 +1356,7 @@ F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4 F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/lemon.c 799e73e19a33b8dd7767a7fa34618ed2a9c2397d -F tool/lempar.c 4ff2afb0449e9367f6cb4c8513339e3333852099 +F tool/lempar.c 586bd85c5840a69f7f5f5e1ea23c16a2c6f6d724 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 F tool/mkautoconfamal.sh 4bdf61548a143e5977bd86ab93d68b694d10c8fa @@ -1403,7 +1402,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 9748c48a4fbd5c06208bbf80e7bfcb159ec026d9 -R c9026e58b8922b5b815b58f78da1a9b7 +P 0557a179f932296cc1fd5217f9a0d2f74e34ce1d +R 35d70dd8e88f4fe91342592b77f63958 U drh -Z 94abf9709b7d536396fc03122fef0eed +Z 3f3cd24eab0db5510bf6fee027109bd0 diff --git a/manifest.uuid b/manifest.uuid index 12c76b678c..78e17aab36 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0557a179f932296cc1fd5217f9a0d2f74e34ce1d \ No newline at end of file +0a72991f4e54548f6c3268c5a9cac1c8d6437d26 \ No newline at end of file diff --git a/src/lempar.c b/src/lempar.c deleted file mode 100644 index beef6cfe49..0000000000 --- a/src/lempar.c +++ /dev/null @@ -1,892 +0,0 @@ -/* Driver template for the LEMON parser generator. -** The author disclaims copyright to this source code. -** -** This version of "lempar.c" is modified, slightly, for use by SQLite. -** The only modifications are the addition of a couple of NEVER() -** macros to disable tests that are needed in the case of a general -** LALR(1) grammar but which are always false in the -** specific grammar used by SQLite. -*/ -/* First off, code is included that follows the "include" declaration -** in the input grammar file. */ -#include -%% -/* Next is all token values, in a form suitable for use by makeheaders. -** This section will be null unless lemon is run with the -m switch. -*/ -/* -** These constants (all generated automatically by the parser generator) -** specify the various kinds of tokens (terminals) that the parser -** understands. -** -** Each symbol here is a terminal symbol in the grammar. -*/ -%% -/* Make sure the INTERFACE macro is defined. -*/ -#ifndef INTERFACE -# define INTERFACE 1 -#endif -/* The next thing included is series of defines which control -** various aspects of the generated parser. -** YYCODETYPE is the data type used for storing terminal -** and nonterminal numbers. "unsigned char" is -** used if there are fewer than 250 terminals -** and nonterminals. "int" is used otherwise. -** YYNOCODE is a number of type YYCODETYPE which corresponds -** to no legal terminal or nonterminal number. This -** number is used to fill in empty slots of the hash -** table. -** YYFALLBACK If defined, this indicates that one or more tokens -** have fall-back values which should be used if the -** original value of the token will not parse. -** YYACTIONTYPE is the data type used for storing terminal -** and nonterminal numbers. "unsigned char" is -** used if there are fewer than 250 rules and -** states combined. "int" is used otherwise. -** ParseTOKENTYPE is the data type used for minor tokens given -** directly to the parser from the tokenizer. -** YYMINORTYPE is the data type used for all minor tokens. -** This is typically a union of many types, one of -** which is ParseTOKENTYPE. The entry in the union -** for base tokens is called "yy0". -** YYSTACKDEPTH is the maximum depth of the parser's stack. If -** zero the stack is dynamically sized using realloc() -** ParseARG_SDECL A static variable declaration for the %extra_argument -** ParseARG_PDECL A parameter declaration for the %extra_argument -** ParseARG_STORE Code to store %extra_argument into yypParser -** ParseARG_FETCH Code to extract %extra_argument from yypParser -** YYERRORSYMBOL is the code number of the error symbol. If not -** defined, then do no error processing. -** YYNSTATE the combined number of states. -** YYNRULE the number of rules in the grammar -** 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 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 -*/ -%% - -/* The yyzerominor constant is used to initialize instances of -** YYMINORTYPE objects to zero. */ -static const YYMINORTYPE yyzerominor = { 0 }; - -/* Define the yytestcase() macro to be a no-op if is not already defined -** otherwise. -** -** Applications can choose to define yytestcase() in the %include section -** to a macro that can assist in verifying code coverage. For production -** code the yytestcase() macro should be turned off. But it is useful -** for testing. -*/ -#ifndef yytestcase -# define yytestcase(X) -#endif - - -/* Next are the tables used to determine what action to take based on the -** current state and lookahead token. These tables are used to implement -** functions that take a state number and lookahead value and return an -** action integer. -** -** Suppose the action integer is N. Then the action is determined as -** follows -** -** 0 <= N <= YY_MAX_SHIFT Shift N. That is, push the lookahead -** token onto the stack and goto state N. -** -** 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. -** -** N == YY_NO_ACTION No such action. Denotes unused -** slots in the yy_action[] table. -** -** The action table is constructed as a single large table named yy_action[]. -** Given state S and lookahead X, the action is computed as -** -** yy_action[ yy_shift_ofst[S] + X ] -** -** If the index value yy_shift_ofst[S]+X is out of range or if the value -** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S] -** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table -** and that yy_default[S] should be used instead. -** -** The formula above is 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 following are the tables generated in this section: -** -** yy_action[] A single table containing all actions. -** yy_lookahead[] A table containing the lookahead for each entry in -** yy_action. Used to detect hash collisions. -** yy_shift_ofst[] For each state, the offset into yy_action for -** shifting terminals. -** yy_reduce_ofst[] For each state, the offset into yy_action for -** shifting non-terminals after a reduce. -** yy_default[] Default action for each state. -*/ -%% - -/* The next table maps tokens into fallback tokens. If a construct -** like the following: -** -** %fallback ID X Y Z. -** -** appears in the grammar, then ID becomes a fallback token for X, Y, -** and Z. Whenever one of the tokens X, Y, or Z is input to the parser -** but it does not parse, the type of the token is changed to ID and -** the parse is retried before an error is thrown. -*/ -#ifdef YYFALLBACK -static const YYCODETYPE yyFallback[] = { -%% -}; -#endif /* YYFALLBACK */ - -/* The following structure represents a single element of the -** parser's stack. Information stored includes: -** -** + The state number for the parser at this level of the stack. -** -** + The value of the token stored at this level of the stack. -** (In other words, the "major" token.) -** -** + The semantic value stored at this level of the stack. This is -** the information used by the action routines in the grammar. -** It is sometimes called the "minor" token. -** -** After the "shift" half of a SHIFTREDUCE action, the stateno field -** actually contains the reduce action for the second half of the -** SHIFTREDUCE. -*/ -struct yyStackEntry { - YYACTIONTYPE stateno; /* The state-number, or reduce action in SHIFTREDUCE */ - YYCODETYPE major; /* The major token value. This is the code - ** number for the token at this stack level */ - YYMINORTYPE minor; /* The user-supplied minor token value. This - ** is the value of the token */ -}; -typedef struct yyStackEntry yyStackEntry; - -/* The state of the parser is completely contained in an instance of -** the following structure */ -struct yyParser { - int yyidx; /* Index of top element in stack */ -#ifdef YYTRACKMAXSTACKDEPTH - int yyidxMax; /* Maximum value of yyidx */ -#endif - int yyerrcnt; /* Shifts left before out of the error */ - ParseARG_SDECL /* A place to hold %extra_argument */ -#if YYSTACKDEPTH<=0 - int yystksz; /* Current side of the stack */ - yyStackEntry *yystack; /* The parser's stack */ -#else - yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */ -#endif -}; -typedef struct yyParser yyParser; - -#ifndef NDEBUG -#include -static FILE *yyTraceFILE = 0; -static char *yyTracePrompt = 0; -#endif /* NDEBUG */ - -#ifndef NDEBUG -/* -** Turn parser tracing on by giving a stream to which to write the trace -** and a prompt to preface each trace message. Tracing is turned off -** by making either argument NULL -** -** Inputs: -**
    -**
  • A FILE* to which trace output should be written. -** If NULL, then tracing is turned off. -**
  • A prefix string written at the beginning of every -** line of trace output. If NULL, then tracing is -** turned off. -**
-** -** Outputs: -** None. -*/ -void ParseTrace(FILE *TraceFILE, char *zTracePrompt){ - yyTraceFILE = TraceFILE; - yyTracePrompt = zTracePrompt; - if( yyTraceFILE==0 ) yyTracePrompt = 0; - else if( yyTracePrompt==0 ) yyTraceFILE = 0; -} -#endif /* NDEBUG */ - -#ifndef 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 */ - -#ifndef NDEBUG -/* For tracing reduce actions, the names of all rules are required. -*/ -static const char *const yyRuleName[] = { -%% -}; -#endif /* NDEBUG */ - - -#if YYSTACKDEPTH<=0 -/* -** Try to increase the size of the parser stack. -*/ -static void yyGrowStack(yyParser *p){ - int newSize; - yyStackEntry *pNew; - - newSize = p->yystksz*2 + 100; - pNew = realloc(p->yystack, newSize*sizeof(pNew[0])); - if( pNew ){ - p->yystack = pNew; - p->yystksz = newSize; -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sStack grows to %d entries!\n", - yyTracePrompt, p->yystksz); - } -#endif - } -} -#endif - -/* -** This function allocates a new parser. -** The only argument is a pointer to a function which works like -** malloc. -** -** Inputs: -** A pointer to the function used to allocate memory. -** -** Outputs: -** A pointer to a parser. This pointer is used in subsequent calls -** to Parse and ParseFree. -*/ -void *ParseAlloc(void *(*mallocProc)(u64)){ - yyParser *pParser; - pParser = (yyParser*)(*mallocProc)( (u64)sizeof(yyParser) ); - if( pParser ){ - pParser->yyidx = -1; -#ifdef YYTRACKMAXSTACKDEPTH - pParser->yyidxMax = 0; -#endif -#if YYSTACKDEPTH<=0 - pParser->yystack = NULL; - pParser->yystksz = 0; - yyGrowStack(pParser); -#endif - } - return pParser; -} - -/* The following function deletes the value associated with a -** symbol. The symbol can be either a terminal or nonterminal. -** "yymajor" is the symbol code, and "yypminor" is a pointer to -** the value. -*/ -static void yy_destructor( - yyParser *yypParser, /* The parser */ - YYCODETYPE yymajor, /* Type code for object to destroy */ - YYMINORTYPE *yypminor /* The object to be destroyed */ -){ - ParseARG_FETCH; - switch( yymajor ){ - /* Here is inserted the actions which take place when a - ** terminal or non-terminal is destroyed. This can happen - ** when the symbol is popped from the stack during a - ** reduce or during error processing or when a parser is - ** being destroyed before it is finished parsing. - ** - ** Note: during a reduce, the only symbols destroyed are those - ** which appear on the RHS of the rule, but which are not used - ** inside the C code. - */ -%% - default: break; /* If no destructor action specified: do nothing */ - } -} - -/* -** Pop the parser's stack once. -** -** If there is a destructor routine associated with the token which -** is popped from the stack, then call it. -*/ -static void yy_pop_parser_stack(yyParser *pParser){ - yyStackEntry *yytos; - assert( pParser->yyidx>=0 ); - yytos = &pParser->yystack[pParser->yyidx--]; -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sPopping %s\n", - yyTracePrompt, - yyTokenName[yytos->major]); - } -#endif - yy_destructor(pParser, yytos->major, &yytos->minor); -} - -/* -** Deallocate and destroy a parser. Destructors are all called for -** all stack elements before shutting the parser down. -** -** Inputs: -**
    -**
  • A pointer to the parser. This should be a pointer -** obtained from ParseAlloc. -**
  • A pointer to a function used to reclaim memory obtained -** from malloc. -**
-*/ -void ParseFree( - void *p, /* The parser to be deleted */ - void (*freeProc)(void*) /* Function used to reclaim memory */ -){ - yyParser *pParser = (yyParser*)p; - /* In SQLite, we never try to destroy a parser that was not successfully - ** created in the first place. */ - if( NEVER(pParser==0) ) return; - while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser); -#if YYSTACKDEPTH<=0 - free(pParser->yystack); -#endif - (*freeProc)((void*)pParser); -} - -/* -** Return the peak depth of the stack for a parser. -*/ -#ifdef YYTRACKMAXSTACKDEPTH -int ParseStackPeak(void *p){ - yyParser *pParser = (yyParser*)p; - return pParser->yyidxMax; -} -#endif - -/* -** Find the appropriate action for a parser given the terminal -** look-ahead token iLookAhead. -** -** If the look-ahead token is YYNOCODE, then check to see if the action is -** independent of the look-ahead. If it is, return the action, otherwise -** return YY_NO_ACTION. -*/ -static int yy_find_shift_action( - yyParser *pParser, /* The parser */ - YYCODETYPE iLookAhead /* The look-ahead token */ -){ - int i; - int stateno = pParser->yystack[pParser->yyidx].stateno; - - if( stateno>=YY_MIN_REDUCE ) return stateno; - assert( stateno <= YY_SHIFT_COUNT ); - do{ - i = yy_shift_ofst[stateno]; - if( i==YY_SHIFT_USE_DFLT ) return yy_default[stateno]; - assert( iLookAhead!=YYNOCODE ); - i += iLookAhead; - if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ - if( iLookAhead>0 ){ -#ifdef YYFALLBACK - YYCODETYPE iFallback; /* Fallback token */ - if( iLookAhead %s\n", - yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); - } -#endif - assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */ - iLookAhead = iFallback; - continue; - } -#endif -#ifdef YYWILDCARD - { - int j = i - iLookAhead + YYWILDCARD; - if( -#if YY_SHIFT_MIN+YYWILDCARD<0 - j>=0 && -#endif -#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT - j %s\n", - yyTracePrompt, yyTokenName[iLookAhead], - yyTokenName[YYWILDCARD]); - } -#endif /* NDEBUG */ - return yy_action[j]; - } - } -#endif /* YYWILDCARD */ - } - return yy_default[stateno]; - }else{ - return yy_action[i]; - } - }while(1); -} - -/* -** Find the appropriate action for a parser given the non-terminal -** look-ahead token iLookAhead. -** -** If the look-ahead token is YYNOCODE, then check to see if the action is -** independent of the look-ahead. If it is, return the action, otherwise -** return YY_NO_ACTION. -*/ -static int yy_find_reduce_action( - int stateno, /* Current state number */ - YYCODETYPE iLookAhead /* The look-ahead token */ -){ - int i; -#ifdef YYERRORSYMBOL - if( stateno>YY_REDUCE_COUNT ){ - return yy_default[stateno]; - } -#else - assert( stateno<=YY_REDUCE_COUNT ); -#endif - i = yy_reduce_ofst[stateno]; - assert( i!=YY_REDUCE_USE_DFLT ); - assert( iLookAhead!=YYNOCODE ); - i += iLookAhead; -#ifdef YYERRORSYMBOL - if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ - return yy_default[stateno]; - } -#else - assert( i>=0 && iyyidx--; -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt); - } -#endif - while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); - /* Here code is inserted which will execute if the parser - ** stack every overflows */ -%% - ParseARG_STORE; /* Suppress warning about unused %extra_argument var */ -} - -/* -** Print tracing information for a SHIFT action -*/ -#ifndef NDEBUG -static void yyTraceShift(yyParser *yypParser, int yyNewState){ - if( yyTraceFILE ){ - int i; - if( yyNewStateyyidx; i++) - fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]); - fprintf(yyTraceFILE,"\n"); - }else{ - fprintf(yyTraceFILE,"%sShift *\n",yyTracePrompt); - } - } -} -#else -# define yyTraceShift(X,Y) -#endif - -/* -** Perform a shift action. Return the number of errors. -*/ -static void yy_shift( - yyParser *yypParser, /* The parser to be shifted */ - int yyNewState, /* The new state to shift in */ - int yyMajor, /* The major token to shift in */ - YYMINORTYPE *yypMinor /* Pointer to the minor token to shift in */ -){ - yyStackEntry *yytos; - yypParser->yyidx++; -#ifdef YYTRACKMAXSTACKDEPTH - if( yypParser->yyidx>yypParser->yyidxMax ){ - yypParser->yyidxMax = yypParser->yyidx; - } -#endif -#if YYSTACKDEPTH>0 - if( yypParser->yyidx>=YYSTACKDEPTH ){ - yyStackOverflow(yypParser, yypMinor); - return; - } -#else - if( yypParser->yyidx>=yypParser->yystksz ){ - yyGrowStack(yypParser); - if( yypParser->yyidx>=yypParser->yystksz ){ - yyStackOverflow(yypParser, yypMinor); - return; - } - } -#endif - yytos = &yypParser->yystack[yypParser->yyidx]; - yytos->stateno = (YYACTIONTYPE)yyNewState; - yytos->major = (YYCODETYPE)yyMajor; - yytos->minor = *yypMinor; - yyTraceShift(yypParser, yyNewState); -} - -/* The following table contains information about every rule that -** is used during the reduce. -*/ -static const struct { - YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ - unsigned char nrhs; /* Number of right-hand side symbols in the rule */ -} yyRuleInfo[] = { -%% -}; - -static void yy_accept(yyParser*); /* Forward Declaration */ - -/* -** Perform a reduce action and the shift that must immediately -** follow the reduce. -*/ -static void yy_reduce( - yyParser *yypParser, /* The parser */ - int yyruleno /* Number of the rule by which to reduce */ -){ - int yygoto; /* The next state */ - int yyact; /* The next action */ - YYMINORTYPE yygotominor; /* The LHS of the rule reduced */ - yyStackEntry *yymsp; /* The top of the parser's stack */ - int yysize; /* Amount to pop the stack */ - ParseARG_FETCH; - yymsp = &yypParser->yystack[yypParser->yyidx]; -#ifndef NDEBUG - if( yyTraceFILE && yyruleno>=0 - && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ - yysize = yyRuleInfo[yyruleno].nrhs; - fprintf(yyTraceFILE, "%sReduce [%s] -> state %d.\n", yyTracePrompt, - yyRuleName[yyruleno], yymsp[-yysize].stateno); - } -#endif /* NDEBUG */ - - /* Silence complaints from purify about yygotominor being uninitialized - ** in some cases when it is copied into the stack after the following - ** switch. yygotominor is uninitialized when a rule reduces that does - ** not set the value of its left-hand side nonterminal. Leaving the - ** value of the nonterminal uninitialized is utterly harmless as long - ** as the value is never used. So really the only thing this code - ** accomplishes is to quieten purify. - ** - ** 2007-01-16: The wireshark project (www.wireshark.org) reports that - ** without this code, their parser segfaults. I'm not sure what there - ** parser is doing to make this happen. This is the second bug report - ** from wireshark this week. Clearly they are stressing Lemon in ways - ** that it has not been previously stressed... (SQLite ticket #2172) - */ - /*memset(&yygotominor, 0, sizeof(yygotominor));*/ - yygotominor = yyzerominor; - - - switch( yyruleno ){ - /* Beginning here are the reduction cases. A typical example - ** follows: - ** case 0: - ** #line - ** { ... } // User supplied code - ** #line - ** break; - */ -%% - }; - assert( yyruleno>=0 && yyrulenoyyidx -= yysize; - yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto); - if( yyact <= YY_MAX_SHIFTREDUCE ){ - if( yyact>YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; - /* If the reduce action popped at least - ** one element off the stack, then we can push the new element back - ** onto the stack here, and skip the stack overflow test in yy_shift(). - ** That gives a significant speed improvement. */ - if( yysize ){ - yypParser->yyidx++; - yymsp -= yysize-1; - yymsp->stateno = (YYACTIONTYPE)yyact; - yymsp->major = (YYCODETYPE)yygoto; - yymsp->minor = yygotominor; - yyTraceShift(yypParser, yyact); - }else{ - yy_shift(yypParser,yyact,yygoto,&yygotominor); - } - }else{ - assert( yyact == YY_ACCEPT_ACTION ); - yy_accept(yypParser); - } -} - -/* -** The following code executes when the parse fails -*/ -#ifndef YYNOERRORRECOVERY -static void yy_parse_failed( - yyParser *yypParser /* The parser */ -){ - ParseARG_FETCH; -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt); - } -#endif - while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); - /* Here code is inserted which will be executed whenever the - ** parser fails */ -%% - ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ -} -#endif /* YYNOERRORRECOVERY */ - -/* -** The following code executes when a syntax error first occurs. -*/ -static void yy_syntax_error( - yyParser *yypParser, /* The parser */ - int yymajor, /* The major type of the error token */ - YYMINORTYPE yyminor /* The minor type of the error token */ -){ - ParseARG_FETCH; -#define TOKEN (yyminor.yy0) -%% - ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ -} - -/* -** The following is executed when the parser accepts -*/ -static void yy_accept( - yyParser *yypParser /* The parser */ -){ - ParseARG_FETCH; -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt); - } -#endif - while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); - /* Here code is inserted which will be executed whenever the - ** parser accepts */ -%% - ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ -} - -/* The main parser program. -** The first argument is a pointer to a structure obtained from -** "ParseAlloc" which describes the current state of the parser. -** The second argument is the major token number. The third is -** the minor token. The fourth optional argument is whatever the -** user wants (and specified in the grammar) and is available for -** use by the action routines. -** -** Inputs: -**
    -**
  • A pointer to the parser (an opaque structure.) -**
  • The major token number. -**
  • The minor token number. -**
  • An option argument of a grammar-specified type. -**
-** -** Outputs: -** None. -*/ -void Parse( - void *yyp, /* The parser */ - int yymajor, /* The major token code number */ - ParseTOKENTYPE yyminor /* The value for the token */ - ParseARG_PDECL /* Optional %extra_argument parameter */ -){ - YYMINORTYPE yyminorunion; - int yyact; /* The parser action. */ -#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) - int yyendofinput; /* True if we are at the end of input */ -#endif -#ifdef YYERRORSYMBOL - int yyerrorhit = 0; /* True if yymajor has invoked an error */ -#endif - yyParser *yypParser; /* The parser */ - - /* (re)initialize the parser, if necessary */ - yypParser = (yyParser*)yyp; - if( yypParser->yyidx<0 ){ -#if YYSTACKDEPTH<=0 - if( yypParser->yystksz <=0 ){ - /*memset(&yyminorunion, 0, sizeof(yyminorunion));*/ - yyminorunion = yyzerominor; - yyStackOverflow(yypParser, &yyminorunion); - return; - } -#endif - yypParser->yyidx = 0; - yypParser->yyerrcnt = -1; - yypParser->yystack[0].stateno = 0; - yypParser->yystack[0].major = 0; - } - yyminorunion.yy0 = yyminor; -#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) - yyendofinput = (yymajor==0); -#endif - ParseARG_STORE; - -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]); - } -#endif - - do{ - yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor); - if( yyact <= YY_MAX_SHIFTREDUCE ){ - if( yyact > YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; - yy_shift(yypParser,yyact,yymajor,&yyminorunion); - yypParser->yyerrcnt--; - yymajor = YYNOCODE; - }else if( yyact <= YY_MAX_REDUCE ){ - yy_reduce(yypParser,yyact-YY_MIN_REDUCE); - }else{ - assert( yyact == YY_ERROR_ACTION ); -#ifdef YYERRORSYMBOL - int yymx; -#endif -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt); - } -#endif -#ifdef YYERRORSYMBOL - /* A syntax error has occurred. - ** The response to an error depends upon whether or not the - ** grammar defines an error token "ERROR". - ** - ** This is what we do if the grammar does define ERROR: - ** - ** * Call the %syntax_error function. - ** - ** * Begin popping the stack until we enter a state where - ** it is legal to shift the error symbol, then shift - ** the error symbol. - ** - ** * Set the error count to three. - ** - ** * Begin accepting and shifting new tokens. No new error - ** processing will occur until three tokens have been - ** shifted successfully. - ** - */ - if( yypParser->yyerrcnt<0 ){ - yy_syntax_error(yypParser,yymajor,yyminorunion); - } - yymx = yypParser->yystack[yypParser->yyidx].major; - if( yymx==YYERRORSYMBOL || yyerrorhit ){ -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sDiscard input token %s\n", - yyTracePrompt,yyTokenName[yymajor]); - } -#endif - yy_destructor(yypParser, (YYCODETYPE)yymajor,&yyminorunion); - yymajor = YYNOCODE; - }else{ - while( - yypParser->yyidx >= 0 && - yymx != YYERRORSYMBOL && - (yyact = yy_find_reduce_action( - yypParser->yystack[yypParser->yyidx].stateno, - YYERRORSYMBOL)) >= YY_MIN_REDUCE - ){ - yy_pop_parser_stack(yypParser); - } - if( yypParser->yyidx < 0 || yymajor==0 ){ - yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); - yy_parse_failed(yypParser); - yymajor = YYNOCODE; - }else if( yymx!=YYERRORSYMBOL ){ - YYMINORTYPE u2; - u2.YYERRSYMDT = 0; - yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2); - } - } - yypParser->yyerrcnt = 3; - yyerrorhit = 1; -#elif defined(YYNOERRORRECOVERY) - /* If the YYNOERRORRECOVERY macro is defined, then do not attempt to - ** do any kind of error recovery. Instead, simply invoke the syntax - ** error routine and continue going as if nothing had happened. - ** - ** Applications can set this macro (for example inside %include) if - ** they intend to abandon the parse upon the first syntax error seen. - */ - yy_syntax_error(yypParser,yymajor,yyminorunion); - yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); - yymajor = YYNOCODE; - -#else /* YYERRORSYMBOL is not defined */ - /* This is what we do if the grammar does not define ERROR: - ** - ** * Report an error message, and throw away the input token. - ** - ** * If the input token is $, then fail the parse. - ** - ** As before, subsequent error messages are suppressed until - ** three input tokens have been successfully shifted. - */ - if( yypParser->yyerrcnt<=0 ){ - yy_syntax_error(yypParser,yymajor,yyminorunion); - } - yypParser->yyerrcnt = 3; - yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); - if( yyendofinput ){ - yy_parse_failed(yypParser); - } - yymajor = YYNOCODE; -#endif - } - }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 ); -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sReturn\n",yyTracePrompt); - } -#endif - return; -} diff --git a/src/parse.y b/src/parse.y index 797fa9bdeb..220df63681 100644 --- a/src/parse.y +++ b/src/parse.y @@ -60,6 +60,18 @@ */ #define yytestcase(X) testcase(X) +/* +** Indicate that sqlite3ParserFree() will never be called with a null +** pointer. +*/ +#define YYPARSEFREENOTNULL 1 + +/* +** Alternative datatype for the argument to the malloc() routine passed +** into sqlite3ParserAlloc(). The default is size_t. +*/ +#define YYMALLOCARGTYPE u64 + /* ** An instance of this structure holds information about the ** LIMIT clause of a SELECT statement. diff --git a/tool/lempar.c b/tool/lempar.c index b7408f60a2..19da6dd371 100644 --- a/tool/lempar.c +++ b/tool/lempar.c @@ -1,49 +1,66 @@ -/* Driver template for the LEMON parser generator. -** The author disclaims copyright to this source code. -*/ -/* First off, code is included that follows the "include" declaration -** in the input grammar file. */ -#include -%% -/* Next is all token values, in a form suitable for use by makeheaders. -** This section will be null unless lemon is run with the -m switch. -*/ -/* -** These constants (all generated automatically by the parser generator) -** specify the various kinds of tokens (terminals) that the parser -** understands. +/* +** 2000-05-29 ** -** Each symbol here is a terminal symbol in the grammar. +** 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. +** +************************************************************************* +** Driver template for the LEMON parser generator. +** +** The "lemon" program processes an LALR(1) input grammar file, then uses +** this template to construct a parser. The "lemon" program inserts text +** at each "%%" line. Also, any "P-a-r-s-e" identifer prefix (without the +** interstitial "-" characters) contained in this template is changed into +** the value of the %name directive from the grammar. Otherwise, the content +** of this template is copied straight through into the generate parser +** source file. +** +** The following is the concatenation of all %include directives from the +** input grammar file: */ +#include +/************ Begin %include sections from the grammar ************************/ %% -/* Make sure the INTERFACE macro is defined. -*/ -#ifndef INTERFACE -# define INTERFACE 1 -#endif -/* The next thing included is series of defines which control +/**************** End of %include directives **********************************/ +/* These constants specify the various numeric values for terminal symbols +** in a format understandable to "makeheaders". This section is blank unless +** "lemon" is run with the "-m" command-line option. +***************** Begin makeheaders token definitions *************************/ +%% +/**************** End makeheaders token definitions ***************************/ +/* The next sections is a serices of control #defines. ** various aspects of the generated parser. -** YYCODETYPE is the data type used for storing terminal -** and nonterminal numbers. "unsigned char" is -** used if there are fewer than 250 terminals -** and nonterminals. "int" is used otherwise. -** YYNOCODE is a number of type YYCODETYPE which corresponds -** to no legal terminal or nonterminal number. This -** number is used to fill in empty slots of the hash -** table. +** YYCODETYPE is the data type used to store the integer codes +** that represent terminal and non-terminal symbols. +** "unsigned char" is used if there are fewer than +** 256 symbols. Larger types otherwise. +** YYNOCODE is a number of type YYCODETYPE that is not used for +** any terminal or nonterminal symbol. ** YYFALLBACK If defined, this indicates that one or more tokens -** have fall-back values which should be used if the -** original value of the token will not parse. -** YYACTIONTYPE is the data type used for storing terminal -** and nonterminal numbers. "unsigned char" is -** used if there are fewer than 250 rules and -** states combined. "int" is used otherwise. -** ParseTOKENTYPE is the data type used for minor tokens given -** directly to the parser from the tokenizer. -** YYMINORTYPE is the data type used for all minor tokens. +** (also known as: "terminal symbols") have fall-back +** values which should be used if the original symbol +** would not parse. This permits keywords to sometimes +** be used as identifiers, for example. +** YYACTIONTYPE is the data type used for "action codes" - numbers +** that indicate what to do in response to the next +** token. +** ParseTOKENTYPE is the data type used for minor type for terminal +** symbols. Background: A "minor type" is a semantic +** value associated with a terminal or non-terminal +** symbols. For example, for an "ID" terminal symbol, +** the minor type might be the name of the identifier. +** Each non-terminal can have a different minor type. +** Terminal symbols all have the same minor type, though. +** This macros defines the minor type for terminal +** symbols. +** YYMINORTYPE is the data type used for all minor types. ** This is typically a union of many types, one of ** which is ParseTOKENTYPE. The entry in the union -** for base tokens is called "yy0". +** for terminal symbols is called "yy0". ** YYSTACKDEPTH is the maximum depth of the parser's stack. If ** zero the stack is dynamically sized using realloc() ** ParseARG_SDECL A static variable declaration for the %extra_argument @@ -62,7 +79,12 @@ ** YY_ACCEPT_ACTION The yy_action[] code for accept ** YY_NO_ACTION The yy_action[] code for no-op */ +#ifndef INTERFACE +# define INTERFACE 1 +#endif +/************* Begin control #defines *****************************************/ %% +/************* End control #defines *******************************************/ /* The yyzerominor constant is used to initialize instances of ** YYMINORTYPE objects to zero. */ @@ -131,11 +153,13 @@ static const YYMINORTYPE yyzerominor = { 0 }; ** yy_reduce_ofst[] For each state, the offset into yy_action for ** shifting non-terminals after a reduce. ** yy_default[] Default action for each state. -*/ +** +*********** Begin parsing tables **********************************************/ %% +/********** End of lemon-generated parsing tables *****************************/ -/* The next table maps tokens into fallback tokens. If a construct -** like the following: +/* The next table maps tokens (terminal symbols) into fallback tokens. +** If a construct like the following: ** ** %fallback ID X Y Z. ** @@ -143,6 +167,10 @@ static const YYMINORTYPE yyzerominor = { 0 }; ** and Z. Whenever one of the tokens X, Y, or Z is input to the parser ** but it does not parse, the type of the token is changed to ID and ** the parse is retried before an error is thrown. +** +** This feature can be used, for example, to cause some keywords in a language +** to revert to identifiers if they keyword does not apply in the context where +** it appears. */ #ifdef YYFALLBACK static const YYCODETYPE yyFallback[] = { @@ -265,6 +293,15 @@ static void yyGrowStack(yyParser *p){ } #endif +/* Datatype of the argument to the memory allocated passed as the +** second argument to ParseAlloc() below. This can be changed by +** putting an appropriate #define in the %include section of the input +** grammar. +*/ +#ifndef YYMALLOCARGTYPE +# define YYMALLOCARGTYPE size_t +#endif + /* ** This function allocates a new parser. ** The only argument is a pointer to a function which works like @@ -277,9 +314,9 @@ static void yyGrowStack(yyParser *p){ ** A pointer to a parser. This pointer is used in subsequent calls ** to Parse and ParseFree. */ -void *ParseAlloc(void *(*mallocProc)(size_t)){ +void *ParseAlloc(void *(*mallocProc)(YYMALLOCARGTYPE)){ yyParser *pParser; - pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) ); + pParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) ); if( pParser ){ pParser->yyidx = -1; #ifdef YYTRACKMAXSTACKDEPTH @@ -294,10 +331,12 @@ void *ParseAlloc(void *(*mallocProc)(size_t)){ return pParser; } -/* The following function deletes the value associated with a -** symbol. The symbol can be either a terminal or nonterminal. -** "yymajor" is the symbol code, and "yypminor" is a pointer to -** the value. +/* The following function deletes the "minor type" or semantic value +** associated with a symbol. The symbol can be either a terminal +** or nonterminal. "yymajor" is the symbol code, and "yypminor" is +** a pointer to the value to be deleted. The code used to do the +** deletions is derived from the %destructor and/or %token_destructor +** directives of the input grammar. */ static void yy_destructor( yyParser *yypParser, /* The parser */ @@ -313,10 +352,12 @@ static void yy_destructor( ** being destroyed before it is finished parsing. ** ** Note: during a reduce, the only symbols destroyed are those - ** which appear on the RHS of the rule, but which are not used + ** which appear on the RHS of the rule, but which are *not* used ** inside the C code. */ +/********* Begin destructor definitions ***************************************/ %% +/********* End destructor definitions *****************************************/ default: break; /* If no destructor action specified: do nothing */ } } @@ -342,23 +383,21 @@ static void yy_pop_parser_stack(yyParser *pParser){ } /* -** Deallocate and destroy a parser. Destructors are all called for +** Deallocate and destroy a parser. Destructors are called for ** all stack elements before shutting the parser down. ** -** Inputs: -**
    -**
  • A pointer to the parser. This should be a pointer -** obtained from ParseAlloc. -**
  • A pointer to a function used to reclaim memory obtained -** from malloc. -**
+** If the YYPARSEFREENEVERNULL macro exists (for example because it +** is defined in a %include section of the input grammar) then it is +** assumed that the input pointer is never NULL. */ void ParseFree( void *p, /* The parser to be deleted */ void (*freeProc)(void*) /* Function used to reclaim memory */ ){ yyParser *pParser = (yyParser*)p; +#ifndef YYPARSEFREENEVERNULL if( pParser==0 ) return; +#endif while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser); #if YYSTACKDEPTH<=0 free(pParser->yystack); @@ -379,10 +418,6 @@ int ParseStackPeak(void *p){ /* ** Find the appropriate action for a parser given the terminal ** look-ahead token iLookAhead. -** -** If the look-ahead token is YYNOCODE, then check to see if the action is -** independent of the look-ahead. If it is, return the action, otherwise -** return YY_NO_ACTION. */ static int yy_find_shift_action( yyParser *pParser, /* The parser */ @@ -449,10 +484,6 @@ static int yy_find_shift_action( /* ** Find the appropriate action for a parser given the non-terminal ** look-ahead token iLookAhead. -** -** If the look-ahead token is YYNOCODE, then check to see if the action is -** independent of the look-ahead. If it is, return the action, otherwise -** return YY_NO_ACTION. */ static int yy_find_reduce_action( int stateno, /* Current state number */ @@ -495,7 +526,9 @@ static void yyStackOverflow(yyParser *yypParser, YYMINORTYPE *yypMinor){ while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); /* Here code is inserted which will execute if the parser ** stack every overflows */ +/******** Begin %stack_overflow code ******************************************/ %% +/******** End %stack_overflow code ********************************************/ ParseARG_STORE; /* Suppress warning about unused %extra_argument var */ } @@ -522,7 +555,7 @@ static void yyTraceShift(yyParser *yypParser, int yyNewState){ #endif /* -** Perform a shift action. Return the number of errors. +** Perform a shift action. */ static void yy_shift( yyParser *yypParser, /* The parser to be shifted */ @@ -593,25 +626,8 @@ static void yy_reduce( yyRuleName[yyruleno], yymsp[-yysize].stateno); } #endif /* NDEBUG */ - - /* Silence complaints from purify about yygotominor being uninitialized - ** in some cases when it is copied into the stack after the following - ** switch. yygotominor is uninitialized when a rule reduces that does - ** not set the value of its left-hand side nonterminal. Leaving the - ** value of the nonterminal uninitialized is utterly harmless as long - ** as the value is never used. So really the only thing this code - ** accomplishes is to quieten purify. - ** - ** 2007-01-16: The wireshark project (www.wireshark.org) reports that - ** without this code, their parser segfaults. I'm not sure what there - ** parser is doing to make this happen. This is the second bug report - ** from wireshark this week. Clearly they are stressing Lemon in ways - ** that it has not been previously stressed... (SQLite ticket #2172) - */ - /*memset(&yygotominor, 0, sizeof(yygotominor));*/ yygotominor = yyzerominor; - switch( yyruleno ){ /* Beginning here are the reduction cases. A typical example ** follows: @@ -621,7 +637,9 @@ static void yy_reduce( ** #line ** break; */ +/********** Begin reduce actions **********************************************/ %% +/********** End reduce actions ************************************************/ }; assert( yyruleno>=0 && yyrulenoyyidx>=0 ) yy_pop_parser_stack(yypParser); /* Here code is inserted which will be executed whenever the ** parser fails */ +/************ Begin %parse_failure code ***************************************/ %% +/************ End %parse_failure code *****************************************/ ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ } #endif /* YYNOERRORRECOVERY */ @@ -681,7 +701,9 @@ static void yy_syntax_error( ){ ParseARG_FETCH; #define TOKEN (yyminor.yy0) +/************ Begin %syntax_error code ****************************************/ %% +/************ End %syntax_error code ******************************************/ ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ } @@ -700,7 +722,9 @@ static void yy_accept( while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); /* Here code is inserted which will be executed whenever the ** parser accepts */ +/*********** Begin %parse_accept code *****************************************/ %% +/*********** End %parse_accept code *******************************************/ ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ } From 822a62f84daff89539eec5d7b979380e91046424 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 9 Nov 2015 19:35:18 +0000 Subject: [PATCH 12/23] Fix a comment typo in the lempar.c template that was missed by the prior check-in. FossilOrigin-Name: c4a7e93fca622fd11a6e16161fbd2f39c2575f00 --- manifest | 12 ++++++------ manifest.uuid | 2 +- tool/lempar.c | 3 ++- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 09c98aaddf..898e6a7736 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\sparser\sto\suse\sthe\sstandard\s"lempar.c"\stemplate\sover\sin\sthe\stool/\nfolder\srather\sthan\sthe\scustomized\s"lempar.c"\sfound\sin\ssrc/. -D 2015-11-09T19:33:42.333 +C Fix\sa\scomment\stypo\sin\sthe\slempar.c\stemplate\sthat\swas\smissed\sby\sthe\sprior\ncheck-in. +D 2015-11-09T19:35:18.284 F Makefile.in d828db6afa6c1fa060d01e33e4674408df1942a1 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc e928e68168df69b353300ac87c10105206653a03 @@ -1356,7 +1356,7 @@ F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4 F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/lemon.c 799e73e19a33b8dd7767a7fa34618ed2a9c2397d -F tool/lempar.c 586bd85c5840a69f7f5f5e1ea23c16a2c6f6d724 +F tool/lempar.c 02cd882bd3144a5e25c86c652af49a6bc07baeae F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 F tool/mkautoconfamal.sh 4bdf61548a143e5977bd86ab93d68b694d10c8fa @@ -1402,7 +1402,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 0557a179f932296cc1fd5217f9a0d2f74e34ce1d -R 35d70dd8e88f4fe91342592b77f63958 +P 0a72991f4e54548f6c3268c5a9cac1c8d6437d26 +R 8fab66a5e8d9eb9e711e67490ab1fb25 U drh -Z 3f3cd24eab0db5510bf6fee027109bd0 +Z b603d5d9eb956db724fe6f00475658c3 diff --git a/manifest.uuid b/manifest.uuid index 78e17aab36..58748396f4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0a72991f4e54548f6c3268c5a9cac1c8d6437d26 \ No newline at end of file +c4a7e93fca622fd11a6e16161fbd2f39c2575f00 \ No newline at end of file diff --git a/tool/lempar.c b/tool/lempar.c index 19da6dd371..1229646494 100644 --- a/tool/lempar.c +++ b/tool/lempar.c @@ -32,7 +32,8 @@ ***************** Begin makeheaders token definitions *************************/ %% /**************** End makeheaders token definitions ***************************/ -/* The next sections is a serices of control #defines. + +/* The next sections is a series of control #defines. ** various aspects of the generated parser. ** YYCODETYPE is the data type used to store the integer codes ** that represent terminal and non-terminal symbols. From 07b09a942059b4330464a7003602700c75360c17 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 10 Nov 2015 00:02:49 +0000 Subject: [PATCH 13/23] Remove an unused non-terminal from the grammar. FossilOrigin-Name: 3c37c522883ea9f2eec4f0ba5c5141912c003425 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/parse.y | 1 - 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 898e6a7736..a06ddf0f84 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\scomment\stypo\sin\sthe\slempar.c\stemplate\sthat\swas\smissed\sby\sthe\sprior\ncheck-in. -D 2015-11-09T19:35:18.284 +C Remove\san\sunused\snon-terminal\sfrom\sthe\sgrammar. +D 2015-11-10T00:02:49.412 F Makefile.in d828db6afa6c1fa060d01e33e4674408df1942a1 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc e928e68168df69b353300ac87c10105206653a03 @@ -328,7 +328,7 @@ F src/os_win.c 1716291e5ec2dbfc5a1fe0b32182030f1f7d8acf F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c ed5cff11793b6a4146582aabb29ed8613a6cf89e F src/pager.h 7fc069c07f3120ee466ff3d48a9d376974ebffa7 -F src/parse.y 89784cfb2a421e4c2257b3dac86bb79096eaa9b9 +F src/parse.y 56cd095d669ad7cf50599a39525277f37f8148f9 F src/pcache.c 24be750c79272e0ca7b6e007bc94999700f3e5ef F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9 F src/pcache1.c 902e1bc7bdaa81b40f8543407c5e2ac8ef4dc035 @@ -1402,7 +1402,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 0a72991f4e54548f6c3268c5a9cac1c8d6437d26 -R 8fab66a5e8d9eb9e711e67490ab1fb25 +P c4a7e93fca622fd11a6e16161fbd2f39c2575f00 +R 718dc1350ed033f1faf4636e4683af75 U drh -Z b603d5d9eb956db724fe6f00475658c3 +Z ed4dab40ca0663dda7ca06a05db43ba5 diff --git a/manifest.uuid b/manifest.uuid index 58748396f4..7b89cfcfaa 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c4a7e93fca622fd11a6e16161fbd2f39c2575f00 \ No newline at end of file +3c37c522883ea9f2eec4f0ba5c5141912c003425 \ No newline at end of file diff --git a/src/parse.y b/src/parse.y index 220df63681..842bf306e0 100644 --- a/src/parse.y +++ b/src/parse.y @@ -651,7 +651,6 @@ dbnm(A) ::= DOT nm(X). {A = X;} fullname(A) ::= nm(X) dbnm(Y). {A = sqlite3SrcListAppend(pParse->db,0,&X,&Y);} %type joinop {int} -%type joinop2 {int} joinop(X) ::= COMMA|JOIN. { X = JT_INNER; } joinop(X) ::= JOIN_KW(A) JOIN. { X = sqlite3JoinType(pParse,&A,0,0); } joinop(X) ::= JOIN_KW(A) nm(B) JOIN. { X = sqlite3JoinType(pParse,&A,&B,0); } From 54bb56d82a04cb05b53af5475c2052a44756e879 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 10 Nov 2015 03:30:51 +0000 Subject: [PATCH 14/23] Performance enhancement to the tokenizer. FossilOrigin-Name: 6ea2df86c95c226052f528424e9bee367a2e765a --- manifest | 14 +++++------ manifest.uuid | 2 +- src/tokenize.c | 4 ++-- tool/mkkeywordhash.c | 56 ++++++++++++++++---------------------------- 4 files changed, 30 insertions(+), 46 deletions(-) diff --git a/manifest b/manifest index a06ddf0f84..bef5b126ef 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\san\sunused\snon-terminal\sfrom\sthe\sgrammar. -D 2015-11-10T00:02:49.412 +C Performance\senhancement\sto\sthe\stokenizer. +D 2015-11-10T03:30:51.926 F Makefile.in d828db6afa6c1fa060d01e33e4674408df1942a1 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc e928e68168df69b353300ac87c10105206653a03 @@ -395,7 +395,7 @@ F src/test_vfs.c 3b65d42e18b262805716bd96178c81da8f2d9283 F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c bbfb74450643cb5372a43ad4f6cffd7e9dfcecb0 -F src/tokenize.c c1006aa773da5725ef55e8d48f69c11d7141d011 +F src/tokenize.c 5606871a377f390af7040ec3c12e0d183512d785 F src/treeview.c 78842e90c1f71269e7a73a1d4221b6fe360bab66 F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f F src/update.c 40e51cd0883cb5bfd6abb7d8a7cd8aa47fab2945 @@ -1360,7 +1360,7 @@ F tool/lempar.c 02cd882bd3144a5e25c86c652af49a6bc07baeae F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 F tool/mkautoconfamal.sh 4bdf61548a143e5977bd86ab93d68b694d10c8fa -F tool/mkkeywordhash.c dfff09dbbfaf950e89af294f48f902181b144670 +F tool/mkkeywordhash.c 37f9c2e62c31384b697ede8825e2d344e98db22c F tool/mkopcodec.tcl edde8adc42621b5e598127f8cdc6d52cfe21f52b F tool/mkopcodeh.tcl e04177031532b7aa9379ded50e820231ac4abd6e F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e @@ -1402,7 +1402,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P c4a7e93fca622fd11a6e16161fbd2f39c2575f00 -R 718dc1350ed033f1faf4636e4683af75 +P 3c37c522883ea9f2eec4f0ba5c5141912c003425 +R 40750d96ad92c103526c6bd35096918c U drh -Z ed4dab40ca0663dda7ca06a05db43ba5 +Z 8ead9b7802f9e64a677105e8e10b5cbd diff --git a/manifest.uuid b/manifest.uuid index 7b89cfcfaa..be66b8946e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3c37c522883ea9f2eec4f0ba5c5141912c003425 \ No newline at end of file +6ea2df86c95c226052f528424e9bee367a2e765a \ No newline at end of file diff --git a/src/tokenize.c b/src/tokenize.c index 81b98d593a..b85e35dc10 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -369,8 +369,8 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){ break; } for(i=1; IdChar(z[i]); i++){} - *tokenType = keywordCode((char*)z, i); - return i; + *tokenType = TK_ID; + return keywordCode((char*)z, i, tokenType); } } *tokenType = TK_ILLEGAL; diff --git a/tool/mkkeywordhash.c b/tool/mkkeywordhash.c index 721611f5a3..e4d393e3fa 100644 --- a/tool/mkkeywordhash.c +++ b/tool/mkkeywordhash.c @@ -277,27 +277,8 @@ static Keyword aKeywordTable[] = { /* Number of keywords */ static int nKeyword = (sizeof(aKeywordTable)/sizeof(aKeywordTable[0])); -/* An array to map all upper-case characters into their corresponding -** lower-case character. -*/ -const unsigned char sqlite3UpperToLower[] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103, - 104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121, - 122, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107, - 108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125, - 126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, - 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161, - 162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179, - 180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197, - 198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215, - 216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233, - 234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251, - 252,253,254,255 -}; -#define UpperToLower sqlite3UpperToLower +/* Map all alphabetic characters into the same case */ +#define charMap(X) (0x20|(X)) /* ** Comparision function for two Keyword records @@ -347,7 +328,7 @@ static Keyword *findById(int id){ ** output. */ int main(int argc, char **argv){ - int i, j, k, h; + int i, j, k, h, m; int bestSize, bestCount; int count; int nChar; @@ -372,8 +353,8 @@ int main(int argc, char **argv){ assert( p->lenzOrigName) ); memcpy(p->zOrigName, p->zName, p->len+1); totalLen += p->len; - p->hash = (UpperToLower[(int)p->zName[0]]*4) ^ - (UpperToLower[(int)p->zName[p->len-1]]*3) ^ p->len; + p->hash = (charMap(p->zName[0])*4) ^ + (charMap(p->zName[p->len-1])*3) ^ (p->len*1); p->id = i+1; } @@ -481,7 +462,7 @@ int main(int argc, char **argv){ /* Begin generating code */ printf("%s", zHdr); printf("/* Hash score: %d */\n", bestCount); - printf("static int keywordCode(const char *z, int n){\n"); + printf("static int keywordCode(const char *z, int n, int *pType){\n"); printf(" /* zText[] encodes %d bytes of keywords in %d bytes */\n", totalLen + nKeyword, nChar+1 ); for(i=j=k=0; i=0; i=((int)aNext[i])-1){\n"); - printf(" if( aLen[i]==n &&" - " sqlite3StrNICmp(&zText[aOffset[i]],z,n)==0 ){\n"); + printf(" if( n>=2 ){\n"); + printf(" h = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n) %% %d;\n", + bestSize); + printf(" for(i=((int)aHash[h])-1; i>=0; i=((int)aNext[i])-1){\n"); + printf(" if( aLen[i]==n &&" + " sqlite3StrNICmp(&zText[aOffset[i]],z,n)==0 ){\n"); for(i=0; i Date: Tue, 10 Nov 2015 12:31:25 +0000 Subject: [PATCH 15/23] Fix harmless compiler warnings in FTS5. FossilOrigin-Name: 09752e51a18ac1b4c9642965e6ee1b6a32de00df --- ext/fts5/fts5_main.c | 1 - ext/fts5/fts5parse.y | 16 ++++++++++++---- manifest | 14 +++++++------- manifest.uuid | 2 +- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/ext/fts5/fts5_main.c b/ext/fts5/fts5_main.c index ee5adc4b98..9390cb6cb2 100644 --- a/ext/fts5/fts5_main.c +++ b/ext/fts5/fts5_main.c @@ -874,7 +874,6 @@ static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bDesc){ int nPhrase; int nByte; int rc = SQLITE_OK; - char *zSql; const char *zRank = pCsr->zRank; const char *zRankArgs = pCsr->zRankArgs; diff --git a/ext/fts5/fts5parse.y b/ext/fts5/fts5parse.y index 065af77053..0e81771b4f 100644 --- a/ext/fts5/fts5parse.y +++ b/ext/fts5/fts5parse.y @@ -58,6 +58,18 @@ */ #define yytestcase(X) testcase(X) +/* +** Indicate that sqlite3ParserFree() will never be called with a null +** pointer. +*/ +#define YYPARSEFREENOTNULL 1 + +/* +** Alternative datatype for the argument to the malloc() routine passed +** into sqlite3ParserAlloc(). The default is size_t. +*/ +#define YYMALLOCARGTYPE u64 + } // end %include %left OR. @@ -168,7 +180,3 @@ phrase(A) ::= STRING(Y) star_opt(Z). { star_opt(A) ::= STAR. { A = 1; } star_opt(A) ::= . { A = 0; } - - - - diff --git a/manifest b/manifest index bef5b126ef..f9984ba6ea 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Performance\senhancement\sto\sthe\stokenizer. -D 2015-11-10T03:30:51.926 +C Fix\sharmless\scompiler\swarnings\sin\sFTS5. +D 2015-11-10T12:31:25.172 F Makefile.in d828db6afa6c1fa060d01e33e4674408df1942a1 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc e928e68168df69b353300ac87c10105206653a03 @@ -110,7 +110,7 @@ F ext/fts5/fts5_config.c 6fc92c0b1bda5244c28a54c9ba740736bd5513d9 F ext/fts5/fts5_expr.c 28b15c9ae296204bc0a2e5cf7a667d840a9d2900 F ext/fts5/fts5_hash.c a9d4c1efebc2a91d26ad7ebdfcbf2678ceac405f F ext/fts5/fts5_index.c b622a0a70f57a96469e6828da2dd70e0872aeb37 -F ext/fts5/fts5_main.c 0569cd9fc18f3b56f6eeac601836df8ed5fb54cb +F ext/fts5/fts5_main.c 7581280ee242785477df67402f2853c66f77d45b F ext/fts5/fts5_storage.c 9ea3d92178743758b6c54d9fe8836bbbdcc92e3b F ext/fts5/fts5_tcl.c 3bf445e66de32137d4693694ff7b1fd6074e32bd F ext/fts5/fts5_test_mi.c e96be827aa8f571031e65e481251dc1981d608bf @@ -118,7 +118,7 @@ F ext/fts5/fts5_tokenize.c 12c5d925286491a71bb3dad7c8924ce9cfd18320 F ext/fts5/fts5_unicode2.c 78273fbd588d1d9bd0a7e4e0ccc9207348bae33c F ext/fts5/fts5_varint.c 3f86ce09cab152e3d45490d7586b7ed2e40c13f1 F ext/fts5/fts5_vocab.c 3742d0abfe8aa8c3cb4a7df56aa38f2e3c3fb1c2 -F ext/fts5/fts5parse.y e83dca6028e3309178d05b5bd920e372dc295d35 +F ext/fts5/fts5parse.y 1647eba089b9b3fc058b4dc989d9da87d15b9580 F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba F ext/fts5/test/fts5_common.tcl 51f7ef3af444b89c6f6ce3896a0ac349ff4e996d F ext/fts5/test/fts5aa.test 2c553eea4dab4bc5a75928f56729277c7bc1d206 @@ -1402,7 +1402,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 3c37c522883ea9f2eec4f0ba5c5141912c003425 -R 40750d96ad92c103526c6bd35096918c +P 6ea2df86c95c226052f528424e9bee367a2e765a +R c4fc880f1c9308c0365b7757399767dc U drh -Z 8ead9b7802f9e64a677105e8e10b5cbd +Z 622f282d2cf652046e0082888bbfa948 diff --git a/manifest.uuid b/manifest.uuid index be66b8946e..d47f9624b0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6ea2df86c95c226052f528424e9bee367a2e765a \ No newline at end of file +09752e51a18ac1b4c9642965e6ee1b6a32de00df \ No newline at end of file From 3334d08989e24ebde4e39d5bf1d775b10960024a Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 10 Nov 2015 13:45:21 +0000 Subject: [PATCH 16/23] Save a few bytes in the parser by using "int" instead of "u8" or "u16" for all small integer types. FossilOrigin-Name: 5dcd212bf6489f4698a0ed0f21497c78379f7c0f --- manifest | 13 ++++++------- manifest.uuid | 2 +- src/parse.y | 10 +++++----- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index b09b4ed00f..cc368e18c4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sall\sparsers\sto\suse\sthe\sstandard\s"lempar.c"\stemplate\sin\sthe\stool/\nfolder\sand\sremove\sthe\scustomized\slempar.c\sfrom\ssrc/,\splus\sother\scompiler\nperformance\sand\sspace\senhancements. -D 2015-11-10T12:41:03.723 +C Save\sa\sfew\sbytes\sin\sthe\sparser\sby\susing\s"int"\sinstead\sof\s"u8"\sor\s"u16"\sfor\nall\ssmall\sinteger\stypes. +D 2015-11-10T13:45:21.998 F Makefile.in d828db6afa6c1fa060d01e33e4674408df1942a1 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc e928e68168df69b353300ac87c10105206653a03 @@ -328,7 +328,7 @@ F src/os_win.c 1716291e5ec2dbfc5a1fe0b32182030f1f7d8acf F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c ed5cff11793b6a4146582aabb29ed8613a6cf89e F src/pager.h 7fc069c07f3120ee466ff3d48a9d376974ebffa7 -F src/parse.y 56cd095d669ad7cf50599a39525277f37f8148f9 +F src/parse.y 8a364a7a692e517dea8711b3c7f0d07fe32727d8 F src/pcache.c 24be750c79272e0ca7b6e007bc94999700f3e5ef F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9 F src/pcache1.c 902e1bc7bdaa81b40f8543407c5e2ac8ef4dc035 @@ -1402,8 +1402,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 0557a179f932296cc1fd5217f9a0d2f74e34ce1d 09752e51a18ac1b4c9642965e6ee1b6a32de00df -R c4fc880f1c9308c0365b7757399767dc -T +closed 09752e51a18ac1b4c9642965e6ee1b6a32de00df +P 0e7fb24ad3c010884763a97e6ae7a3fd39d0e5a9 +R e95251a17c80e6e8bd0fe3b50f525483 U drh -Z 094c96712972b6d193fe37091ddcf067 +Z 63fd373db42b2e308a08a76dcf855a61 diff --git a/manifest.uuid b/manifest.uuid index 07d0e55fcb..9eec6dca49 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0e7fb24ad3c010884763a97e6ae7a3fd39d0e5a9 \ No newline at end of file +5dcd212bf6489f4698a0ed0f21497c78379f7c0f \ No newline at end of file diff --git a/src/parse.y b/src/parse.y index 842bf306e0..64f234ca7c 100644 --- a/src/parse.y +++ b/src/parse.y @@ -174,7 +174,7 @@ create_table_args ::= AS select(S). { sqlite3EndTable(pParse,0,0,0,S); sqlite3SelectDelete(pParse->db, S); } -%type table_options {u8} +%type table_options {int} table_options(A) ::= . {A = 0;} table_options(A) ::= WITHOUT nm(X). { if( X.n==5 && sqlite3_strnicmp(X.z,"rowid",5)==0 ){ @@ -376,12 +376,12 @@ defer_subclause_opt(A) ::= defer_subclause(X). {A = X;} // default behavior when there is a constraint conflict. // %type onconf {int} -%type orconf {u8} +%type orconf {int} %type resolvetype {int} onconf(A) ::= . {A = OE_Default;} onconf(A) ::= ON CONFLICT resolvetype(X). {A = X;} orconf(A) ::= . {A = OE_Default;} -orconf(A) ::= OR resolvetype(X). {A = (u8)X;} +orconf(A) ::= OR resolvetype(X). {A = X;} resolvetype(A) ::= raisetype(X). {A = X;} resolvetype(A) ::= IGNORE. {A = OE_Ignore;} resolvetype(A) ::= REPLACE. {A = OE_Replace;} @@ -538,7 +538,7 @@ values(A) ::= values(X) COMMA LP exprlist(Y) RP. { // The "distinct" nonterminal is true (1) if the DISTINCT keyword is // present and false (0) if it is not. // -%type distinct {u16} +%type distinct {int} distinct(A) ::= DISTINCT. {A = SF_Distinct;} distinct(A) ::= ALL. {A = SF_All;} distinct(A) ::= . {A = 0;} @@ -811,7 +811,7 @@ cmd ::= with(W) insert_cmd(R) INTO fullname(X) idlist_opt(F) DEFAULT VALUES. sqlite3Insert(pParse, X, 0, F, R); } -%type insert_cmd {u8} +%type insert_cmd {int} insert_cmd(A) ::= INSERT orconf(R). {A = R;} insert_cmd(A) ::= REPLACE. {A = OE_Replace;} From 97e58a2feb32da44234eb24b343ffc968acdccd2 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 10 Nov 2015 14:27:17 +0000 Subject: [PATCH 17/23] Make the output of "PRAGMA parser_trace" go to stdout instead of stderr. FossilOrigin-Name: 1e4849911e3eed65eabee18fdee63bab4faae57a --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/pragma.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index cc368e18c4..4e26b0e80e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Save\sa\sfew\sbytes\sin\sthe\sparser\sby\susing\s"int"\sinstead\sof\s"u8"\sor\s"u16"\sfor\nall\ssmall\sinteger\stypes. -D 2015-11-10T13:45:21.998 +C Make\sthe\soutput\sof\s"PRAGMA\sparser_trace"\sgo\sto\sstdout\sinstead\sof\sstderr. +D 2015-11-10T14:27:17.622 F Makefile.in d828db6afa6c1fa060d01e33e4674408df1942a1 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc e928e68168df69b353300ac87c10105206653a03 @@ -332,7 +332,7 @@ F src/parse.y 8a364a7a692e517dea8711b3c7f0d07fe32727d8 F src/pcache.c 24be750c79272e0ca7b6e007bc94999700f3e5ef F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9 F src/pcache1.c 902e1bc7bdaa81b40f8543407c5e2ac8ef4dc035 -F src/pragma.c 8fd4c8a12e25f0d916426f160255ebe25415eba7 +F src/pragma.c 9dbb9ba2453d79bfc5905be0398aa30342b066bb F src/pragma.h 631a91c8b0e6ca8f051a1d8a4a0da4150e04620a F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1 F src/printf.c 0c4bcdd1c2e2521024f0a69cb5eb334f86b3652a @@ -1402,7 +1402,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 0e7fb24ad3c010884763a97e6ae7a3fd39d0e5a9 -R e95251a17c80e6e8bd0fe3b50f525483 +P 5dcd212bf6489f4698a0ed0f21497c78379f7c0f +R d246e800f7bbd35b4c91162f9a5cfe01 U drh -Z 63fd373db42b2e308a08a76dcf855a61 +Z 7a87ce17e8bd737f41d12f3fe2d64903 diff --git a/manifest.uuid b/manifest.uuid index 9eec6dca49..63c210a12f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5dcd212bf6489f4698a0ed0f21497c78379f7c0f \ No newline at end of file +1e4849911e3eed65eabee18fdee63bab4faae57a \ No newline at end of file diff --git a/src/pragma.c b/src/pragma.c index 14c4811746..a0e394f782 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1324,7 +1324,7 @@ void sqlite3Pragma( case PragTyp_PARSER_TRACE: { if( zRight ){ if( sqlite3GetBoolean(zRight, 0) ){ - sqlite3ParserTrace(stderr, "parser: "); + sqlite3ParserTrace(stdout, "parser: "); }else{ sqlite3ParserTrace(0, 0); } From 0c4105ee1930c56b0b1fce4fa7a27c13f838086d Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 10 Nov 2015 14:51:22 +0000 Subject: [PATCH 18/23] Improved output formatting for "PRAGMA parser_trace=ON;". FossilOrigin-Name: e43e1171fd7837a08069dc25df4eac14db1c2afe --- manifest | 12 ++++++------ manifest.uuid | 2 +- tool/lempar.c | 29 +++++++++++++++++++---------- 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/manifest b/manifest index 4e26b0e80e..cae104ad32 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\sthe\soutput\sof\s"PRAGMA\sparser_trace"\sgo\sto\sstdout\sinstead\sof\sstderr. -D 2015-11-10T14:27:17.622 +C Improved\soutput\sformatting\sfor\s"PRAGMA\sparser_trace=ON;". +D 2015-11-10T14:51:22.311 F Makefile.in d828db6afa6c1fa060d01e33e4674408df1942a1 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc e928e68168df69b353300ac87c10105206653a03 @@ -1356,7 +1356,7 @@ F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4 F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/lemon.c 799e73e19a33b8dd7767a7fa34618ed2a9c2397d -F tool/lempar.c 02cd882bd3144a5e25c86c652af49a6bc07baeae +F tool/lempar.c 3ec1463a034b37d87d782be5f6b8b10a3b1ecbe7 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6 F tool/mkautoconfamal.sh 4bdf61548a143e5977bd86ab93d68b694d10c8fa @@ -1402,7 +1402,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 5dcd212bf6489f4698a0ed0f21497c78379f7c0f -R d246e800f7bbd35b4c91162f9a5cfe01 +P 1e4849911e3eed65eabee18fdee63bab4faae57a +R 09ae4147f1c84fb513e1a92470f43128 U drh -Z 7a87ce17e8bd737f41d12f3fe2d64903 +Z 86e43e17960e74008de165832cc2a68a diff --git a/manifest.uuid b/manifest.uuid index 63c210a12f..cd04978930 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1e4849911e3eed65eabee18fdee63bab4faae57a \ No newline at end of file +e43e1171fd7837a08069dc25df4eac14db1c2afe \ No newline at end of file diff --git a/tool/lempar.c b/tool/lempar.c index 1229646494..312507e5f1 100644 --- a/tool/lempar.c +++ b/tool/lempar.c @@ -539,15 +539,13 @@ static void yyStackOverflow(yyParser *yypParser, YYMINORTYPE *yypMinor){ #ifndef NDEBUG static void yyTraceShift(yyParser *yypParser, int yyNewState){ if( yyTraceFILE ){ - int i; if( yyNewStateyyidx; i++) - fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]); - fprintf(yyTraceFILE,"\n"); + fprintf(yyTraceFILE,"%sShift '%s', go to state %d\n", + yyTracePrompt,yyTokenName[yypParser->yystack[yypParser->yyidx].major], + yyNewState); }else{ - fprintf(yyTraceFILE,"%sShift *\n",yyTracePrompt); + fprintf(yyTraceFILE,"%sShift '%s'\n", + yyTracePrompt,yyTokenName[yypParser->yystack[yypParser->yyidx].major]); } } } @@ -623,7 +621,7 @@ static void yy_reduce( if( yyTraceFILE && yyruleno>=0 && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ yysize = yyRuleInfo[yyruleno].nrhs; - fprintf(yyTraceFILE, "%sReduce [%s] -> state %d.\n", yyTracePrompt, + fprintf(yyTraceFILE, "%sReduce [%s], go to state %d.\n", yyTracePrompt, yyRuleName[yyruleno], yymsp[-yysize].stateno); } #endif /* NDEBUG */ @@ -779,6 +777,12 @@ void Parse( yypParser->yyerrcnt = -1; yypParser->yystack[0].stateno = 0; yypParser->yystack[0].major = 0; +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sInitialize. Empty stack. State 0\n", + yyTracePrompt); + } +#endif } yyminorunion.yy0 = yyminor; #if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) @@ -788,7 +792,7 @@ void Parse( #ifndef NDEBUG if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]); + fprintf(yyTraceFILE,"%sInput '%s'\n",yyTracePrompt,yyTokenName[yymajor]); } #endif @@ -902,7 +906,12 @@ void Parse( }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 ); #ifndef NDEBUG if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sReturn\n",yyTracePrompt); + int i; + fprintf(yyTraceFILE,"%sReturn. Stack=",yyTracePrompt); + for(i=1; i<=yypParser->yyidx; i++) + fprintf(yyTraceFILE,"%c%s", i==1 ? '[' : ' ', + yyTokenName[yypParser->yystack[i].major]); + fprintf(yyTraceFILE,"]\n"); } #endif return; From 3d38cec99a5e635b2a69ca0ca8adfdeb99b96006 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 11 Nov 2015 15:28:52 +0000 Subject: [PATCH 19/23] Improvements to the SQLITE_CONFIG_PAGECACHE documentation. Enhance the command-line shell to be able to take advantage of the full range of SQLITE_CONFIG_PAGECACHE capabilities, such as setting pMem==NULL and N<0. FossilOrigin-Name: 2518d5c971c4b32d9227b3bb7259162e3e27b00b --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/shell.c | 6 +++--- src/sqlite.h.in | 37 +++++++++++++++++++++---------------- 4 files changed, 32 insertions(+), 27 deletions(-) diff --git a/manifest b/manifest index cae104ad32..5e942ee5cf 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\soutput\sformatting\sfor\s"PRAGMA\sparser_trace=ON;". -D 2015-11-10T14:51:22.311 +C Improvements\sto\sthe\sSQLITE_CONFIG_PAGECACHE\sdocumentation.\s\sEnhance\sthe\ncommand-line\sshell\sto\sbe\sable\sto\stake\sadvantage\sof\sthe\sfull\srange\sof\nSQLITE_CONFIG_PAGECACHE\scapabilities,\ssuch\sas\ssetting\spMem==NULL\sand\sN<0. +D 2015-11-11T15:28:52.898 F Makefile.in d828db6afa6c1fa060d01e33e4674408df1942a1 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc e928e68168df69b353300ac87c10105206653a03 @@ -340,8 +340,8 @@ F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 F src/resolve.c 1954a0f01bf65d78d7d559aea3d5c67f33376d91 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/select.c 00a2a10d4298a685d0eeb05b09ef018a2bd81bf8 -F src/shell.c d25df04168d6ba5a4fa05bdbf859df667f9eb621 -F src/sqlite.h.in 3cfc86c55e57c63d86b9e1e92869e2bfb162ca8e +F src/shell.c acefb4593a9bf0338a757c968f1f1bb05690d830 +F src/sqlite.h.in 278df052181b0e5b0bcdb2089ff09596ae9eca15 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 4b66e3e3435da4b4c8c83696d0349f0c503b3924 F src/sqliteInt.h bc6d24460fe544323517630b1e20539146379077 @@ -1402,7 +1402,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 1e4849911e3eed65eabee18fdee63bab4faae57a -R 09ae4147f1c84fb513e1a92470f43128 +P e43e1171fd7837a08069dc25df4eac14db1c2afe +R 9a1d72f8baac116c36385e92e48c0378 U drh -Z 86e43e17960e74008de165832cc2a68a +Z 9d52ec874b9a01b7b0eb1dab69dbb993 diff --git a/manifest.uuid b/manifest.uuid index cd04978930..bf01d0ad61 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e43e1171fd7837a08069dc25df4eac14db1c2afe \ No newline at end of file +2518d5c971c4b32d9227b3bb7259162e3e27b00b \ No newline at end of file diff --git a/src/shell.c b/src/shell.c index f79087122c..7c53995799 100644 --- a/src/shell.c +++ b/src/shell.c @@ -4601,10 +4601,10 @@ int SQLITE_CDECL main(int argc, char **argv){ int n, sz; sz = (int)integerValue(cmdline_option_value(argc,argv,++i)); if( sz>70000 ) sz = 70000; - if( sz<800 ) sz = 800; + if( sz<0 ) sz = 0; n = (int)integerValue(cmdline_option_value(argc,argv,++i)); - if( n<10 ) n = 10; - sqlite3_config(SQLITE_CONFIG_PAGECACHE, malloc(n*sz+1), sz, n); + sqlite3_config(SQLITE_CONFIG_PAGECACHE, + (n>0 && sz>0) ? malloc(n*sz) : 0, sz, n); data.shellFlgs |= SHFLG_Pagecache; }else if( strcmp(z,"-lookaside")==0 ){ int n, sz; diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 961c5169fc..9280343507 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -1599,29 +1599,34 @@ struct sqlite3_mem_methods { ** ** ** [[SQLITE_CONFIG_PAGECACHE]]
SQLITE_CONFIG_PAGECACHE
-**
^The SQLITE_CONFIG_PAGECACHE option specifies a static memory buffer +**
^The SQLITE_CONFIG_PAGECACHE option a memory pool ** that SQLite can use for the database page cache with the default page ** cache implementation. -** This configuration should not be used if an application-define page -** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2] -** configuration option. +** This configuration option is a no-op if an application-define page +** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2]. ** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to -** 8-byte aligned -** memory, the size of each page buffer (sz), and the number of pages (N). +** 8-byte aligned memory (pMem), the size of each page cache line (sz), +** and the number of cache lines (N). ** The sz argument should be the size of the largest database page ** (a power of two between 512 and 65536) plus some extra bytes for each ** page header. ^The number of extra bytes needed by the page header -** can be determined using the [SQLITE_CONFIG_PCACHE_HDRSZ] option -** to [sqlite3_config()]. +** can be determined using [SQLITE_CONFIG_PCACHE_HDRSZ]. ** ^It is harmless, apart from the wasted memory, -** for the sz parameter to be larger than necessary. The first -** argument should pointer to an 8-byte aligned block of memory that -** is at least sz*N bytes of memory, otherwise subsequent behavior is -** undefined. -** ^SQLite will use the memory provided by the first argument to satisfy its -** memory needs for the first N pages that it adds to cache. ^If additional -** page cache memory is needed beyond what is provided by this option, then -** SQLite goes to [sqlite3_malloc()] for the additional storage space.
+** for the sz parameter to be larger than necessary. The pMem +** argument must be either a NULL pointer or a pointer to an 8-byte +** aligned block of memory of at least sz*N bytes, otherwise +** subsequent behavior is undefined. +** ^When pMem is not NULL, SQLite will strive to use the memory provided +** to satisfy page cache needs, falling back to [sqlite3_malloc()] if +** a page cache line is larger than sz bytes or if all of the pMem buffer +** is exhausted. +** ^If pMem is NULL and N is non-zero, then each database connection +** does an initial bulk allocation for page cache memory +** from [sqlite3_malloc()] sufficient for N cache lines if N is positive or +** of -1024*N bytes if N is negative, . ^If additional +** page cache memory is needed beyond what is provided by the initial +** allocation, then SQLite goes to [sqlite3_malloc()] separately for each +** additional cache line. ** ** [[SQLITE_CONFIG_HEAP]]
SQLITE_CONFIG_HEAP
**
^The SQLITE_CONFIG_HEAP option specifies a static memory buffer From 24e9895f81c103fb3aaaf07fe75260e2ec7de146 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Wed, 11 Nov 2015 18:43:49 +0000 Subject: [PATCH 20/23] Fix missing word in a documentation comment. No changes to code. FossilOrigin-Name: ed24d302657e8495bef7f5ed698c7cca12717be9 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/sqlite.h.in | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 5e942ee5cf..21a3de1f3f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improvements\sto\sthe\sSQLITE_CONFIG_PAGECACHE\sdocumentation.\s\sEnhance\sthe\ncommand-line\sshell\sto\sbe\sable\sto\stake\sadvantage\sof\sthe\sfull\srange\sof\nSQLITE_CONFIG_PAGECACHE\scapabilities,\ssuch\sas\ssetting\spMem==NULL\sand\sN<0. -D 2015-11-11T15:28:52.898 +C Fix\smissing\sword\sin\sa\sdocumentation\scomment.\s\sNo\schanges\sto\scode. +D 2015-11-11T18:43:49.517 F Makefile.in d828db6afa6c1fa060d01e33e4674408df1942a1 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc e928e68168df69b353300ac87c10105206653a03 @@ -341,7 +341,7 @@ F src/resolve.c 1954a0f01bf65d78d7d559aea3d5c67f33376d91 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/select.c 00a2a10d4298a685d0eeb05b09ef018a2bd81bf8 F src/shell.c acefb4593a9bf0338a757c968f1f1bb05690d830 -F src/sqlite.h.in 278df052181b0e5b0bcdb2089ff09596ae9eca15 +F src/sqlite.h.in fa62718f73553f06b2f2e362fd09ccb4e1cbb626 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 4b66e3e3435da4b4c8c83696d0349f0c503b3924 F src/sqliteInt.h bc6d24460fe544323517630b1e20539146379077 @@ -1402,7 +1402,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P e43e1171fd7837a08069dc25df4eac14db1c2afe -R 9a1d72f8baac116c36385e92e48c0378 -U drh -Z 9d52ec874b9a01b7b0eb1dab69dbb993 +P 2518d5c971c4b32d9227b3bb7259162e3e27b00b +R 3dc308897daa57a7c4272c874c792ced +U mistachkin +Z 5a3c62c2da73a7a92ccd94cbe3857768 diff --git a/manifest.uuid b/manifest.uuid index bf01d0ad61..5f07e1aae7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2518d5c971c4b32d9227b3bb7259162e3e27b00b \ No newline at end of file +ed24d302657e8495bef7f5ed698c7cca12717be9 \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 9280343507..13c97d8d4a 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -1599,7 +1599,7 @@ struct sqlite3_mem_methods { **
** ** [[SQLITE_CONFIG_PAGECACHE]]
SQLITE_CONFIG_PAGECACHE
-**
^The SQLITE_CONFIG_PAGECACHE option a memory pool +**
^The SQLITE_CONFIG_PAGECACHE option specifies a memory pool ** that SQLite can use for the database page cache with the default page ** cache implementation. ** This configuration option is a no-op if an application-define page From 9b0cf34f813b7d542f593b59e6466f94d7cc11e2 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 12 Nov 2015 14:57:19 +0000 Subject: [PATCH 21/23] First attempt at enhancing the "PRAGMA cache_spill" statement to accept a cache threashold size. FossilOrigin-Name: 549d42be0dac87dc04c3eeccfdc60615c3a6ad3f --- manifest | 33 ++++++------ manifest.uuid | 2 +- src/btree.c | 38 +++++++++----- src/btree.h | 1 + src/pager.c | 11 +++- src/pager.h | 1 + src/pcache.c | 72 ++++++++++++++++---------- src/pcache.h | 7 +++ src/pragma.c | 117 +++++++++++++++++++++++++++++-------------- src/pragma.h | 79 ++++++++++++++--------------- test/pragma2.test | 34 ++++++++++--- tool/mkpragmatab.tcl | 2 - 12 files changed, 257 insertions(+), 140 deletions(-) diff --git a/manifest b/manifest index 5e942ee5cf..d7ec4d4e08 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improvements\sto\sthe\sSQLITE_CONFIG_PAGECACHE\sdocumentation.\s\sEnhance\sthe\ncommand-line\sshell\sto\sbe\sable\sto\stake\sadvantage\sof\sthe\sfull\srange\sof\nSQLITE_CONFIG_PAGECACHE\scapabilities,\ssuch\sas\ssetting\spMem==NULL\sand\sN<0. -D 2015-11-11T15:28:52.898 +C First\sattempt\sat\senhancing\sthe\s"PRAGMA\scache_spill"\sstatement\sto\saccept\sa\ncache\sthreashold\ssize. +D 2015-11-12T14:57:19.268 F Makefile.in d828db6afa6c1fa060d01e33e4674408df1942a1 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc e928e68168df69b353300ac87c10105206653a03 @@ -282,8 +282,8 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c 2869a76c03eb393ee795416e2387005553df72bc F src/bitvec.c d1f21d7d91690747881f03940584f4cc548c9d3d F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79 -F src/btree.c 9e5d713bf54be8bfcae9b60210173dd53570f56d -F src/btree.h 1b8bf2818b5e256c25a5e09126720113b1d783da +F src/btree.c d3bdd8462a86492e2ebc9aca4a0168429017de25 +F src/btree.h 2d76dee44704c47eed323356a758662724b674a0 F src/btreeInt.h 3ab435ed27adea54d040584b0bcc488ee7db1e38 F src/build.c ca574d33ffb1763cfd2979383f4d507095bfbe19 F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0 @@ -326,14 +326,14 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa F src/os_unix.c cf72e06e15839ebe7121e01d3eebf256c039b0ca F src/os_win.c 1716291e5ec2dbfc5a1fe0b32182030f1f7d8acf F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca -F src/pager.c ed5cff11793b6a4146582aabb29ed8613a6cf89e -F src/pager.h 7fc069c07f3120ee466ff3d48a9d376974ebffa7 +F src/pager.c 18341e2b759b447cbc82fb9215d08d9c5864e92e +F src/pager.h 87c4118a71ba3965184148b379a6d93179071091 F src/parse.y 8a364a7a692e517dea8711b3c7f0d07fe32727d8 -F src/pcache.c 24be750c79272e0ca7b6e007bc94999700f3e5ef -F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9 +F src/pcache.c f72f19956f8182ecd97cf9b7b0faa201711225b8 +F src/pcache.h 1ff11adce609ba7de139b6abfabaf9a2bac947b5 F src/pcache1.c 902e1bc7bdaa81b40f8543407c5e2ac8ef4dc035 -F src/pragma.c 9dbb9ba2453d79bfc5905be0398aa30342b066bb -F src/pragma.h 631a91c8b0e6ca8f051a1d8a4a0da4150e04620a +F src/pragma.c 26a612db31748a23dc17b97296e521cf2ef42081 +F src/pragma.h 31b110aaecb5603829c97747b99abfe491df5fa0 F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1 F src/printf.c 0c4bcdd1c2e2521024f0a69cb5eb334f86b3652a F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 @@ -931,7 +931,7 @@ F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442 F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff F test/permutations.test 4ea119731c62d2f7d0aa86dd5b184cbb61ca411b F test/pragma.test a44253f911e7d50127d4a08f927f47c861a4c772 -F test/pragma2.test b5e2ce4c892afceb308c6ae6163a9099b2a0d8d7 +F test/pragma2.test 93ef4f24fb97a59d935859daf26078384b265c12 F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc F test/printf2.test 0b61566dd1c0f0b802f59dffa228c5dc5aa6b054 @@ -1364,7 +1364,7 @@ F tool/mkkeywordhash.c 37f9c2e62c31384b697ede8825e2d344e98db22c F tool/mkopcodec.tcl edde8adc42621b5e598127f8cdc6d52cfe21f52b F tool/mkopcodeh.tcl e04177031532b7aa9379ded50e820231ac4abd6e F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e -F tool/mkpragmatab.tcl 84af2b180484323a2ea22a2279e8bd9e3e1e492e +F tool/mkpragmatab.tcl 473b6a156bc018d36aac5288d8479a879d570b93 F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 F tool/mksqlite3c-noext.tcl 87240b09c20042999b41d5fabe091b7111287835 F tool/mksqlite3c.tcl b66b4170f693602cd6985aed15d9509fe2f18c84 @@ -1402,7 +1402,10 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P e43e1171fd7837a08069dc25df4eac14db1c2afe -R 9a1d72f8baac116c36385e92e48c0378 +P 2518d5c971c4b32d9227b3bb7259162e3e27b00b +R 337aa604616b296340bdf382cbd4b435 +T *branch * cache_spill=N +T *sym-cache_spill=N * +T -sym-trunk * U drh -Z 9d52ec874b9a01b7b0eb1dab69dbb993 +Z e21337491dfb1b39176b63de38883141 diff --git a/manifest.uuid b/manifest.uuid index bf01d0ad61..a425302e46 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2518d5c971c4b32d9227b3bb7259162e3e27b00b \ No newline at end of file +549d42be0dac87dc04c3eeccfdc60615c3a6ad3f \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index a61a6edf2f..4a51b01d75 100644 --- a/src/btree.c +++ b/src/btree.c @@ -2556,19 +2556,11 @@ int sqlite3BtreeClose(Btree *p){ } /* -** Change the limit on the number of pages allowed in the cache. -** -** The maximum number of cache pages is set to the absolute -** value of mxPage. If mxPage is negative, the pager will -** operate asynchronously - it will not stop to do fsync()s -** to insure data is written to the disk surface before -** continuing. Transactions still work if synchronous is off, -** and the database cannot be corrupted if this program -** crashes. But if the operating system crashes or there is -** an abrupt power failure when synchronous is off, the database -** could be left in an inconsistent and unrecoverable state. -** Synchronous is on by default so database corruption is not -** normally a worry. +** Change the "soft" limit on the number of pages in the cache. +** Unused and unmodified pages will be recycled when the number of +** pages in the cache exceeds this soft limit. But the size of the +** cache is allowed to grow larger than this limit if it contains +** dirty pages or pages still in active use. */ int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){ BtShared *pBt = p->pBt; @@ -2579,6 +2571,26 @@ int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){ return SQLITE_OK; } +/* +** Change the "spill" limit on the number of pages in the cache. +** If the number of pages exceeds this limit during a write transaction, +** the pager might attempt to "spill" pages to the journal early in +** order to free up memory. +** +** The value returned is the current spill size. If zero is passed +** as an argument, no changes are made to the spill size setting, so +** using mxPage of 0 is a way to query the current spill size. +*/ +int sqlite3BtreeSetSpillSize(Btree *p, int mxPage){ + BtShared *pBt = p->pBt; + int res; + assert( sqlite3_mutex_held(p->db->mutex) ); + sqlite3BtreeEnter(p); + res = sqlite3PagerSetSpillsize(pBt->pPager, mxPage); + sqlite3BtreeLeave(p); + return res; +} + #if SQLITE_MAX_MMAP_SIZE>0 /* ** Change the limit on the amount of the database file that may be diff --git a/src/btree.h b/src/btree.h index 0c15a59c11..09b713f3db 100644 --- a/src/btree.h +++ b/src/btree.h @@ -63,6 +63,7 @@ int sqlite3BtreeOpen( int sqlite3BtreeClose(Btree*); int sqlite3BtreeSetCacheSize(Btree*,int); +int sqlite3BtreeSetSpillSize(Btree*,int); #if SQLITE_MAX_MMAP_SIZE>0 int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64); #endif diff --git a/src/pager.c b/src/pager.c index b537e9e931..f633a77927 100644 --- a/src/pager.c +++ b/src/pager.c @@ -3392,12 +3392,21 @@ static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){ } /* -** Change the maximum number of in-memory pages that are allowed. +** Change the maximum number of in-memory pages that are allowed +** before attempting to recycle clean and unused pages. */ void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){ sqlite3PcacheSetCachesize(pPager->pPCache, mxPage); } +/* +** Change the maximum number of in-memory pages that are allowed +** before attempting to spill pages to journal. +*/ +int sqlite3PagerSetSpillsize(Pager *pPager, int mxPage){ + return sqlite3PcacheSetSpillsize(pPager->pPCache, mxPage); +} + /* ** Invoke SQLITE_FCNTL_MMAP_SIZE based on the current value of szMmap. */ diff --git a/src/pager.h b/src/pager.h index 9d541dede9..22e73f4c76 100644 --- a/src/pager.h +++ b/src/pager.h @@ -123,6 +123,7 @@ void sqlite3PagerAlignReserve(Pager*,Pager*); #endif int sqlite3PagerMaxPageCount(Pager*, int); void sqlite3PagerSetCachesize(Pager*, int); +int sqlite3PagerSetSpillsize(Pager*, int); void sqlite3PagerSetMmapLimit(Pager *, sqlite3_int64); void sqlite3PagerShrink(Pager*); void sqlite3PagerSetFlags(Pager*,unsigned); diff --git a/src/pcache.c b/src/pcache.c index e39262cb8c..ddcb0bcc45 100644 --- a/src/pcache.c +++ b/src/pcache.c @@ -21,6 +21,7 @@ struct PCache { PgHdr *pSynced; /* Last synced page in dirty page list */ int nRefSum; /* Sum of ref counts over all pages */ int szCache; /* Configured cache size */ + int szSpill; /* Size before spilling occurs */ int szPage; /* Size of every page in this cache */ int szExtra; /* Size of extra space for each page */ u8 bPurgeable; /* True if pages are on backing store */ @@ -110,10 +111,8 @@ static void pcacheUnpin(PgHdr *p){ } /* -** Compute the number of pages of cache requested. p->szCache is the +** Compute the number of pages of cache requested. p->szCache is the ** cache size requested by the "PRAGMA cache_size" statement. -** -** */ static int numberOfCachePages(PCache *p){ if( p->szCache>=0 ){ @@ -176,6 +175,7 @@ int sqlite3PcacheOpen( p->xStress = xStress; p->pStress = pStress; p->szCache = 100; + p->szSpill = 1; return sqlite3PcacheSetPageSize(p, szPage); } @@ -271,32 +271,33 @@ int sqlite3PcacheFetchStress( PgHdr *pPg; if( pCache->eCreate==2 ) return 0; - - /* Find a dirty page to write-out and recycle. First try to find a - ** page that does not require a journal-sync (one with PGHDR_NEED_SYNC - ** cleared), but if that is not possible settle for any other - ** unreferenced dirty page. - */ - for(pPg=pCache->pSynced; - pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC)); - pPg=pPg->pDirtyPrev - ); - pCache->pSynced = pPg; - if( !pPg ){ - for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pDirtyPrev); - } - if( pPg ){ - int rc; + if( sqlite3PcachePagecount(pCache)>pCache->szSpill ){ + /* Find a dirty page to write-out and recycle. First try to find a + ** page that does not require a journal-sync (one with PGHDR_NEED_SYNC + ** cleared), but if that is not possible settle for any other + ** unreferenced dirty page. + */ + for(pPg=pCache->pSynced; + pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC)); + pPg=pPg->pDirtyPrev + ); + pCache->pSynced = pPg; + if( !pPg ){ + for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pDirtyPrev); + } + if( pPg ){ + int rc; #ifdef SQLITE_LOG_CACHE_SPILL - sqlite3_log(SQLITE_FULL, - "spill page %d making room for %d - cache used: %d/%d", - pPg->pgno, pgno, - sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache), + sqlite3_log(SQLITE_FULL, + "spill page %d making room for %d - cache used: %d/%d", + pPg->pgno, pgno, + sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache), numberOfCachePages(pCache)); #endif - rc = pCache->xStress(pCache->pStress, pPg); - if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){ - return rc; + rc = pCache->xStress(pCache->pStress, pPg); + if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){ + return rc; + } } } *ppPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, 2); @@ -641,6 +642,25 @@ void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){ numberOfCachePages(pCache)); } +/* +** Set the suggested cache-spill value. Make no changes if if the +** argument is zero. Return the effective cache-spill size, which will +** be the larger of the szSpill and szCache. +*/ +int sqlite3PcacheSetSpillsize(PCache *p, int mxPage){ + int res; + assert( p->pCache!=0 ); + if( mxPage ){ + if( mxPage<0 ){ + mxPage = (int)((-1024*(i64)p->szCache)/(p->szPage+p->szExtra)); + } + p->szSpill = mxPage; + } + res = numberOfCachePages(p); + if( resszSpill ) res = p->szSpill; + return res; +} + /* ** Free up as much memory as possible from the page cache. */ diff --git a/src/pcache.h b/src/pcache.h index a0724df22f..42c44cf7ba 100644 --- a/src/pcache.h +++ b/src/pcache.h @@ -146,6 +146,13 @@ void sqlite3PcacheSetCachesize(PCache *, int); int sqlite3PcacheGetCachesize(PCache *); #endif +/* Set or get the suggested spill-size for the specified pager-cache. +** +** The spill-size is the minimum number of pages in cache before the cache +** will attempt to spill dirty pages by calling xStress. +*/ +int sqlite3PcacheSetSpillsize(PCache *, int); + /* Free up as much memory as possible from the page cache */ void sqlite3PcacheShrink(PCache*); diff --git a/src/pragma.c b/src/pragma.c index a0e394f782..85693cddfe 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -279,7 +279,7 @@ const char *sqlite3JournalModename(int eMode){ ** ** Pragmas are of this form: ** -** PRAGMA [database.]id [= value] +** PRAGMA [schema.]id [= value] ** ** The identifier might also be a string. The value is a string, and ** identifier, or a number. If minusFlag is true, then the value is @@ -291,8 +291,8 @@ const char *sqlite3JournalModename(int eMode){ */ void sqlite3Pragma( Parse *pParse, - Token *pId1, /* First part of [database.]id field */ - Token *pId2, /* Second part of [database.]id field, or NULL */ + Token *pId1, /* First part of [schema.]id field */ + Token *pId2, /* Second part of [schema.]id field, or NULL */ Token *pValue, /* Token for , or NULL */ int minusFlag /* True if a '-' sign preceded */ ){ @@ -313,7 +313,7 @@ void sqlite3Pragma( sqlite3VdbeRunOnlyOnce(v); pParse->nMem = 2; - /* Interpret the [database.] part of the pragma statement. iDb is the + /* Interpret the [schema.] part of the pragma statement. iDb is the ** index of the database this pragma is being applied to in db.aDb[]. */ iDb = sqlite3TwoPartName(pParse, pId1, pId2, &pId); if( iDb<0 ) return; @@ -402,8 +402,8 @@ void sqlite3Pragma( #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) /* - ** PRAGMA [database.]default_cache_size - ** PRAGMA [database.]default_cache_size=N + ** PRAGMA [schema.]default_cache_size + ** PRAGMA [schema.]default_cache_size=N ** ** The first form reports the current persistent setting for the ** page cache size. The value returned is the maximum number of @@ -454,8 +454,8 @@ void sqlite3Pragma( #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) /* - ** PRAGMA [database.]page_size - ** PRAGMA [database.]page_size=N + ** PRAGMA [schema.]page_size + ** PRAGMA [schema.]page_size=N ** ** The first form reports the current setting for the ** database page size in bytes. The second form sets the @@ -481,8 +481,8 @@ void sqlite3Pragma( } /* - ** PRAGMA [database.]secure_delete - ** PRAGMA [database.]secure_delete=ON/OFF + ** PRAGMA [schema.]secure_delete + ** PRAGMA [schema.]secure_delete=ON/OFF ** ** The first form reports the current setting for the ** secure_delete flag. The second form changes the secure_delete @@ -507,8 +507,8 @@ void sqlite3Pragma( } /* - ** PRAGMA [database.]max_page_count - ** PRAGMA [database.]max_page_count=N + ** PRAGMA [schema.]max_page_count + ** PRAGMA [schema.]max_page_count=N ** ** The first form reports the current setting for the ** maximum number of pages in the database file. The @@ -519,7 +519,7 @@ void sqlite3Pragma( ** change. The only purpose is to provide an easy way to test ** the sqlite3AbsInt32() function. ** - ** PRAGMA [database.]page_count + ** PRAGMA [schema.]page_count ** ** Return the number of pages in the specified database. */ @@ -540,8 +540,8 @@ void sqlite3Pragma( } /* - ** PRAGMA [database.]locking_mode - ** PRAGMA [database.]locking_mode = (normal|exclusive) + ** PRAGMA [schema.]locking_mode + ** PRAGMA [schema.]locking_mode = (normal|exclusive) */ case PragTyp_LOCKING_MODE: { const char *zRet = "normal"; @@ -586,8 +586,8 @@ void sqlite3Pragma( } /* - ** PRAGMA [database.]journal_mode - ** PRAGMA [database.]journal_mode = + ** PRAGMA [schema.]journal_mode + ** PRAGMA [schema.]journal_mode = ** (delete|persist|off|truncate|memory|wal|off) */ case PragTyp_JOURNAL_MODE: { @@ -627,8 +627,8 @@ void sqlite3Pragma( } /* - ** PRAGMA [database.]journal_size_limit - ** PRAGMA [database.]journal_size_limit=N + ** PRAGMA [schema.]journal_size_limit + ** PRAGMA [schema.]journal_size_limit=N ** ** Get or set the size limit on rollback journal files. */ @@ -647,8 +647,8 @@ void sqlite3Pragma( #endif /* SQLITE_OMIT_PAGER_PRAGMAS */ /* - ** PRAGMA [database.]auto_vacuum - ** PRAGMA [database.]auto_vacuum=N + ** PRAGMA [schema.]auto_vacuum + ** PRAGMA [schema.]auto_vacuum=N ** ** Get or set the value of the database 'auto-vacuum' parameter. ** The value is one of: 0 NONE 1 FULL 2 INCREMENTAL @@ -699,7 +699,7 @@ void sqlite3Pragma( #endif /* - ** PRAGMA [database.]incremental_vacuum(N) + ** PRAGMA [schema.]incremental_vacuum(N) ** ** Do N steps of incremental vacuuming on a database. */ @@ -722,8 +722,8 @@ void sqlite3Pragma( #ifndef SQLITE_OMIT_PAGER_PRAGMAS /* - ** PRAGMA [database.]cache_size - ** PRAGMA [database.]cache_size=N + ** PRAGMA [schema.]cache_size + ** PRAGMA [schema.]cache_size=N ** ** The first form reports the current local setting for the ** page cache size. The second form sets the local @@ -747,7 +747,50 @@ void sqlite3Pragma( } /* - ** PRAGMA [database.]mmap_size(N) + ** PRAGMA [schema.]cache_spill + ** PRAGMA cache_spill=BOOLEAN + ** PRAGMA [schema.]cache_spill=N + ** + ** The first form reports the current local setting for the + ** page cache spill size. The second form turns cache spill on + ** or off. When turnning cache spill on, the size is set to the + ** current cache_size. The third form sets a spill size that + ** may be different form the cache size. + ** If N is positive then that is the + ** number of pages in the cache. If N is negative, then the + ** number of pages is adjusted so that the cache uses -N kibibytes + ** of memory. + ** + ** If the number of cache_spill pages is less then the number of + ** cache_size pages, no spilling occurs until the page count exceeds + ** the number of cache_size pages. + ** + ** The cache_spill=BOOLEAN setting applies to all attached schemas, + ** not just the schema specified. + */ + case PragTyp_CACHE_SPILL: { + int size; + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); + if( !zRight ){ + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + returnSingleInt(v, "cache_spill", + (db->flags & SQLITE_CacheSpill)==0 ? 0 : + sqlite3BtreeSetSpillSize(pDb->pBt,0)); + }else{ + if( sqlite3GetInt32(zRight, &size) ){ + sqlite3BtreeSetSpillSize(pDb->pBt, size); + } + if( sqlite3GetBoolean(zRight, 0) ){ + db->flags |= SQLITE_CacheSpill; + }else{ + db->flags &= ~SQLITE_CacheSpill; + } + } + break; + } + + /* + ** PRAGMA [schema.]mmap_size(N) ** ** Used to set mapping size limit. The mapping size limit is ** used to limit the aggregate size of all memory mapped regions of the @@ -891,8 +934,8 @@ void sqlite3Pragma( #if SQLITE_ENABLE_LOCKING_STYLE /* - ** PRAGMA [database.]lock_proxy_file - ** PRAGMA [database.]lock_proxy_file = ":auto:"|"lock_file_path" + ** PRAGMA [schema.]lock_proxy_file + ** PRAGMA [schema.]lock_proxy_file = ":auto:"|"lock_file_path" ** ** Return or set the value of the lock_proxy_file flag. Changing ** the value sets a specific file to be used for database access locks. @@ -927,8 +970,8 @@ void sqlite3Pragma( #endif /* SQLITE_ENABLE_LOCKING_STYLE */ /* - ** PRAGMA [database.]synchronous - ** PRAGMA [database.]synchronous=OFF|ON|NORMAL|FULL + ** PRAGMA [schema.]synchronous + ** PRAGMA [schema.]synchronous=OFF|ON|NORMAL|FULL ** ** Return or set the local value of the synchronous flag. Changing ** the local value does not make changes to the disk file and the @@ -1644,16 +1687,16 @@ void sqlite3Pragma( #ifndef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS /* - ** PRAGMA [database.]schema_version - ** PRAGMA [database.]schema_version = + ** PRAGMA [schema.]schema_version + ** PRAGMA [schema.]schema_version = ** - ** PRAGMA [database.]user_version - ** PRAGMA [database.]user_version = + ** PRAGMA [schema.]user_version + ** PRAGMA [schema.]user_version = ** - ** PRAGMA [database.]freelist_count = + ** PRAGMA [schema.]freelist_count = ** - ** PRAGMA [database.]application_id - ** PRAGMA [database.]application_id = + ** PRAGMA [schema.]application_id + ** PRAGMA [schema.]application_id = ** ** The pragma's schema_version and user_version are used to set or get ** the value of the schema-version and user-version, respectively. Both @@ -1728,7 +1771,7 @@ void sqlite3Pragma( #ifndef SQLITE_OMIT_WAL /* - ** PRAGMA [database.]wal_checkpoint = passive|full|restart|truncate + ** PRAGMA [schema.]wal_checkpoint = passive|full|restart|truncate ** ** Checkpoint the database. */ diff --git a/src/pragma.h b/src/pragma.h index 9e206dac49..1bb6691224 100644 --- a/src/pragma.h +++ b/src/pragma.h @@ -8,43 +8,44 @@ #define PragTyp_FLAG 2 #define PragTyp_BUSY_TIMEOUT 3 #define PragTyp_CACHE_SIZE 4 -#define PragTyp_CASE_SENSITIVE_LIKE 5 -#define PragTyp_COLLATION_LIST 6 -#define PragTyp_COMPILE_OPTIONS 7 -#define PragTyp_DATA_STORE_DIRECTORY 8 -#define PragTyp_DATABASE_LIST 9 -#define PragTyp_DEFAULT_CACHE_SIZE 10 -#define PragTyp_ENCODING 11 -#define PragTyp_FOREIGN_KEY_CHECK 12 -#define PragTyp_FOREIGN_KEY_LIST 13 -#define PragTyp_INCREMENTAL_VACUUM 14 -#define PragTyp_INDEX_INFO 15 -#define PragTyp_INDEX_LIST 16 -#define PragTyp_INTEGRITY_CHECK 17 -#define PragTyp_JOURNAL_MODE 18 -#define PragTyp_JOURNAL_SIZE_LIMIT 19 -#define PragTyp_LOCK_PROXY_FILE 20 -#define PragTyp_LOCKING_MODE 21 -#define PragTyp_PAGE_COUNT 22 -#define PragTyp_MMAP_SIZE 23 -#define PragTyp_PAGE_SIZE 24 -#define PragTyp_SECURE_DELETE 25 -#define PragTyp_SHRINK_MEMORY 26 -#define PragTyp_SOFT_HEAP_LIMIT 27 -#define PragTyp_STATS 28 -#define PragTyp_SYNCHRONOUS 29 -#define PragTyp_TABLE_INFO 30 -#define PragTyp_TEMP_STORE 31 -#define PragTyp_TEMP_STORE_DIRECTORY 32 -#define PragTyp_THREADS 33 -#define PragTyp_WAL_AUTOCHECKPOINT 34 -#define PragTyp_WAL_CHECKPOINT 35 -#define PragTyp_ACTIVATE_EXTENSIONS 36 -#define PragTyp_HEXKEY 37 -#define PragTyp_KEY 38 -#define PragTyp_REKEY 39 -#define PragTyp_LOCK_STATUS 40 -#define PragTyp_PARSER_TRACE 41 +#define PragTyp_CACHE_SPILL 5 +#define PragTyp_CASE_SENSITIVE_LIKE 6 +#define PragTyp_COLLATION_LIST 7 +#define PragTyp_COMPILE_OPTIONS 8 +#define PragTyp_DATA_STORE_DIRECTORY 9 +#define PragTyp_DATABASE_LIST 10 +#define PragTyp_DEFAULT_CACHE_SIZE 11 +#define PragTyp_ENCODING 12 +#define PragTyp_FOREIGN_KEY_CHECK 13 +#define PragTyp_FOREIGN_KEY_LIST 14 +#define PragTyp_INCREMENTAL_VACUUM 15 +#define PragTyp_INDEX_INFO 16 +#define PragTyp_INDEX_LIST 17 +#define PragTyp_INTEGRITY_CHECK 18 +#define PragTyp_JOURNAL_MODE 19 +#define PragTyp_JOURNAL_SIZE_LIMIT 20 +#define PragTyp_LOCK_PROXY_FILE 21 +#define PragTyp_LOCKING_MODE 22 +#define PragTyp_PAGE_COUNT 23 +#define PragTyp_MMAP_SIZE 24 +#define PragTyp_PAGE_SIZE 25 +#define PragTyp_SECURE_DELETE 26 +#define PragTyp_SHRINK_MEMORY 27 +#define PragTyp_SOFT_HEAP_LIMIT 28 +#define PragTyp_STATS 29 +#define PragTyp_SYNCHRONOUS 30 +#define PragTyp_TABLE_INFO 31 +#define PragTyp_TEMP_STORE 32 +#define PragTyp_TEMP_STORE_DIRECTORY 33 +#define PragTyp_THREADS 34 +#define PragTyp_WAL_AUTOCHECKPOINT 35 +#define PragTyp_WAL_CHECKPOINT 36 +#define PragTyp_ACTIVATE_EXTENSIONS 37 +#define PragTyp_HEXKEY 38 +#define PragTyp_KEY 39 +#define PragTyp_REKEY 40 +#define PragTyp_LOCK_STATUS 41 +#define PragTyp_PARSER_TRACE 42 #define PragFlag_NeedSchema 0x01 #define PragFlag_ReadOnly 0x02 static const struct sPragmaNames { @@ -91,9 +92,9 @@ static const struct sPragmaNames { #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) { /* zName: */ "cache_spill", - /* ePragTyp: */ PragTyp_FLAG, + /* ePragTyp: */ PragTyp_CACHE_SPILL, /* ePragFlag: */ 0, - /* iArg: */ SQLITE_CacheSpill }, + /* iArg: */ 0 }, #endif { /* zName: */ "case_sensitive_like", /* ePragTyp: */ PragTyp_CASE_SENSITIVE_LIKE, diff --git a/test/pragma2.test b/test/pragma2.test index e2c87019eb..c0b4f239e5 100644 --- a/test/pragma2.test +++ b/test/pragma2.test @@ -138,7 +138,7 @@ do_execsql_test pragma2-4.1 { PRAGMA cache_spill; PRAGMA main.cache_spill; PRAGMA temp.cache_spill; -} {1 1 1} +} {2000 2000 2000} do_execsql_test pragma2-4.2 { PRAGMA cache_spill=OFF; PRAGMA cache_spill; @@ -178,21 +178,43 @@ do_test pragma2-4.4 { PRAGMA lock_status; } } {main exclusive temp unknown} ;# EXCLUSIVE lock due to cache spill -do_test pragma2-4.5 { +do_test pragma2-4.5.1 { db eval { - COMMIT; + ROLLBACK; PRAGMA cache_spill=OFF; + PRAGMA Cache_Spill; BEGIN; - UPDATE t1 SET c=c-1; + UPDATE t1 SET c=c+1; PRAGMA lock_status; } -} {main reserved temp unknown} ;# No cache spill, so no exclusive lock +} {0 main reserved temp unknown} ;# No cache spill, so no exclusive lock +do_test pragma2-4.5.2 { + db eval { + ROLLBACK; + PRAGMA cache_spill=100000; + PRAGMA cache_spill; + BEGIN; + UPDATE t1 SET c=c+1; + PRAGMA lock_status; + } +} {100000 main reserved temp unknown} ;# Large cache spill threshold +do_test pragma2-4.5.3 { + db eval { + ROLLBACK; + PRAGMA cache_spill=25; + BEGIN; + UPDATE t1 SET c=c+1; + PRAGMA lock_status; + } +} {main exclusive temp unknown} ;# Large cache spill, so no exclusive lock + # Verify that newly attached databases inherit the cache_spill=OFF # setting. # do_execsql_test pragma2-4.6 { - COMMIT; + ROLLBACK; + PRAGMA cache_spill=OFF; ATTACH 'test2.db' AS aux1; PRAGMA aux1.cache_size=50; BEGIN; diff --git a/tool/mkpragmatab.tcl b/tool/mkpragmatab.tcl index bbdf9da754..9e0c7d5153 100644 --- a/tool/mkpragmatab.tcl +++ b/tool/mkpragmatab.tcl @@ -47,8 +47,6 @@ set pragma_def { IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS) NAME: cache_spill - TYPE: FLAG - ARG: SQLITE_CacheSpill IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS) NAME: reverse_unordered_selects From 644f4c1bbb2335d23c245e2bfd4fce0fe33967c7 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 12 Nov 2015 15:04:05 +0000 Subject: [PATCH 22/23] Fix a #define in parse.y that disabled unused code in the generated parser. FossilOrigin-Name: f84e3085c87cfffe4aba0eb4c4a3298b4027db83 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/parse.y | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 21a3de1f3f..0565883d76 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\smissing\sword\sin\sa\sdocumentation\scomment.\s\sNo\schanges\sto\scode. -D 2015-11-11T18:43:49.517 +C Fix\sa\s#define\sin\sparse.y\sthat\sdisabled\sunused\scode\sin\sthe\sgenerated\sparser. +D 2015-11-12T15:04:05.278 F Makefile.in d828db6afa6c1fa060d01e33e4674408df1942a1 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc e928e68168df69b353300ac87c10105206653a03 @@ -328,7 +328,7 @@ F src/os_win.c 1716291e5ec2dbfc5a1fe0b32182030f1f7d8acf F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c ed5cff11793b6a4146582aabb29ed8613a6cf89e F src/pager.h 7fc069c07f3120ee466ff3d48a9d376974ebffa7 -F src/parse.y 8a364a7a692e517dea8711b3c7f0d07fe32727d8 +F src/parse.y aad5cc866dc23719f361fe7e0b8eaec8ce4861a4 F src/pcache.c 24be750c79272e0ca7b6e007bc94999700f3e5ef F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9 F src/pcache1.c 902e1bc7bdaa81b40f8543407c5e2ac8ef4dc035 @@ -1402,7 +1402,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 2518d5c971c4b32d9227b3bb7259162e3e27b00b -R 3dc308897daa57a7c4272c874c792ced -U mistachkin -Z 5a3c62c2da73a7a92ccd94cbe3857768 +P ed24d302657e8495bef7f5ed698c7cca12717be9 +R d2bed45a676ff9fbad30132bc7912ff2 +U drh +Z 9ab7252fe5fcd6a0ff588f1afe46df1d diff --git a/manifest.uuid b/manifest.uuid index 5f07e1aae7..6e51c4b405 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ed24d302657e8495bef7f5ed698c7cca12717be9 \ No newline at end of file +f84e3085c87cfffe4aba0eb4c4a3298b4027db83 \ No newline at end of file diff --git a/src/parse.y b/src/parse.y index 64f234ca7c..e504e64548 100644 --- a/src/parse.y +++ b/src/parse.y @@ -64,7 +64,7 @@ ** Indicate that sqlite3ParserFree() will never be called with a null ** pointer. */ -#define YYPARSEFREENOTNULL 1 +#define YYPARSEFREENEVERNULL 1 /* ** Alternative datatype for the argument to the malloc() routine passed From 4f9c8ec62dbfc5645f14b059862a87dfe3fd58b7 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 12 Nov 2015 15:47:48 +0000 Subject: [PATCH 23/23] Test cases. Minor problems fixed. All appears to work now. FossilOrigin-Name: 9a431362dccbc9b8f93375f30a3b8955903cca79 --- manifest | 19 ++++++++----------- manifest.uuid | 2 +- src/pcache.c | 2 +- src/pragma.c | 5 +++-- test/pragma2.test | 35 +++++++++++++++++++++++++++++++++-- 5 files changed, 46 insertions(+), 17 deletions(-) diff --git a/manifest b/manifest index d7ec4d4e08..1b21bffde4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C First\sattempt\sat\senhancing\sthe\s"PRAGMA\scache_spill"\sstatement\sto\saccept\sa\ncache\sthreashold\ssize. -D 2015-11-12T14:57:19.268 +C Test\scases.\s\sMinor\sproblems\sfixed.\s\sAll\sappears\sto\swork\snow. +D 2015-11-12T15:47:48.274 F Makefile.in d828db6afa6c1fa060d01e33e4674408df1942a1 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc e928e68168df69b353300ac87c10105206653a03 @@ -329,10 +329,10 @@ F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c 18341e2b759b447cbc82fb9215d08d9c5864e92e F src/pager.h 87c4118a71ba3965184148b379a6d93179071091 F src/parse.y 8a364a7a692e517dea8711b3c7f0d07fe32727d8 -F src/pcache.c f72f19956f8182ecd97cf9b7b0faa201711225b8 +F src/pcache.c 73895411fa6b7bd6f0091212feabbe833b358d23 F src/pcache.h 1ff11adce609ba7de139b6abfabaf9a2bac947b5 F src/pcache1.c 902e1bc7bdaa81b40f8543407c5e2ac8ef4dc035 -F src/pragma.c 26a612db31748a23dc17b97296e521cf2ef42081 +F src/pragma.c 0e91830e5cea31771121eb8967e8c110f7e8216a F src/pragma.h 31b110aaecb5603829c97747b99abfe491df5fa0 F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1 F src/printf.c 0c4bcdd1c2e2521024f0a69cb5eb334f86b3652a @@ -931,7 +931,7 @@ F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442 F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff F test/permutations.test 4ea119731c62d2f7d0aa86dd5b184cbb61ca411b F test/pragma.test a44253f911e7d50127d4a08f927f47c861a4c772 -F test/pragma2.test 93ef4f24fb97a59d935859daf26078384b265c12 +F test/pragma2.test a8e11a7a38e2a5053fe4b807fc806c937d9a7469 F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc F test/printf2.test 0b61566dd1c0f0b802f59dffa228c5dc5aa6b054 @@ -1402,10 +1402,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 2518d5c971c4b32d9227b3bb7259162e3e27b00b -R 337aa604616b296340bdf382cbd4b435 -T *branch * cache_spill=N -T *sym-cache_spill=N * -T -sym-trunk * +P 549d42be0dac87dc04c3eeccfdc60615c3a6ad3f +R 675bbffc41ae7c4e7c58162bf39590a3 U drh -Z e21337491dfb1b39176b63de38883141 +Z 4ec2916143a078881954f66921bb963f diff --git a/manifest.uuid b/manifest.uuid index a425302e46..27ce563ab6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -549d42be0dac87dc04c3eeccfdc60615c3a6ad3f \ No newline at end of file +9a431362dccbc9b8f93375f30a3b8955903cca79 \ No newline at end of file diff --git a/src/pcache.c b/src/pcache.c index ddcb0bcc45..5ac9d34a1e 100644 --- a/src/pcache.c +++ b/src/pcache.c @@ -652,7 +652,7 @@ int sqlite3PcacheSetSpillsize(PCache *p, int mxPage){ assert( p->pCache!=0 ); if( mxPage ){ if( mxPage<0 ){ - mxPage = (int)((-1024*(i64)p->szCache)/(p->szPage+p->szExtra)); + mxPage = (int)((-1024*(i64)mxPage)/(p->szPage+p->szExtra)); } p->szSpill = mxPage; } diff --git a/src/pragma.c b/src/pragma.c index 85693cddfe..7754e26c89 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -769,7 +769,6 @@ void sqlite3Pragma( ** not just the schema specified. */ case PragTyp_CACHE_SPILL: { - int size; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); if( !zRight ){ if( sqlite3ReadSchema(pParse) ) goto pragma_out; @@ -777,14 +776,16 @@ void sqlite3Pragma( (db->flags & SQLITE_CacheSpill)==0 ? 0 : sqlite3BtreeSetSpillSize(pDb->pBt,0)); }else{ + int size = 1; if( sqlite3GetInt32(zRight, &size) ){ sqlite3BtreeSetSpillSize(pDb->pBt, size); } - if( sqlite3GetBoolean(zRight, 0) ){ + if( sqlite3GetBoolean(zRight, size!=0) ){ db->flags |= SQLITE_CacheSpill; }else{ db->flags &= ~SQLITE_CacheSpill; } + setAllPagerFlags(db); } break; } diff --git a/test/pragma2.test b/test/pragma2.test index c0b4f239e5..9cb31fa14f 100644 --- a/test/pragma2.test +++ b/test/pragma2.test @@ -197,16 +197,27 @@ do_test pragma2-4.5.2 { UPDATE t1 SET c=c+1; PRAGMA lock_status; } -} {100000 main reserved temp unknown} ;# Large cache spill threshold +} {100000 main reserved temp unknown} ;# Big spill threshold -> no excl lock do_test pragma2-4.5.3 { db eval { ROLLBACK; PRAGMA cache_spill=25; + PRAGMA main.cache_spill; BEGIN; UPDATE t1 SET c=c+1; PRAGMA lock_status; } -} {main exclusive temp unknown} ;# Large cache spill, so no exclusive lock +} {50 main exclusive temp unknown} ;# Small cache spill -> exclusive lock +do_test pragma2-4.5.4 { + db eval { + ROLLBACK; + PRAGMA cache_spill(-25); + PRAGMA main.cache_spill; + BEGIN; + UPDATE t1 SET c=c+1; + PRAGMA lock_status; + } +} {50 main exclusive temp unknown} ;# Small cache spill -> exclusive lock # Verify that newly attached databases inherit the cache_spill=OFF @@ -231,6 +242,26 @@ do_execsql_test pragma2-4.8 { UPDATE t2 SET c=c-1; PRAGMA lock_status; } {main unlocked temp unknown aux1 exclusive} +db close +forcedelete test.db +sqlite3 db test.db + +breakpoint +do_execsql_test pragma2-5.1 { + PRAGMA page_size=16384; + CREATE TABLE t1(x); + PRAGMA cache_size=2; + PRAGMA cache_spill=YES; + PRAGMA cache_spill; +} {2} +do_execsql_test pragma2-5.2 { + PRAGMA cache_spill=NO; + PRAGMA cache_spill; +} {0} +do_execsql_test pragma2-5.3 { + PRAGMA cache_spill(-51); + PRAGMA cache_spill; +} {3} test_restore_config_pagecache finish_test