diff --git a/ext/fts5/fts5_aux.c b/ext/fts5/fts5_aux.c index 836de8a0f0..d8147f8111 100644 --- a/ext/fts5/fts5_aux.c +++ b/ext/fts5/fts5_aux.c @@ -189,7 +189,7 @@ static int fts5HighlightCb( if( p->iRangeEnd>0 && iPos==p->iRangeEnd ){ fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iEndOff - p->iOff); p->iOff = iEndOff; - if( iPositer.iEnd ){ + if( iPos>=p->iter.iStart && iPositer.iEnd ){ fts5HighlightAppend(&rc, p, p->zClose, -1); } } @@ -350,6 +350,13 @@ static void fts5SnippetFunction( if( iBestStart>0 ){ fts5HighlightAppend(&rc, &ctx, zEllips, -1); } + + /* Advance iterator ctx.iter so that it points to the first coalesced + ** phrase instance at or following position iBestStart. */ + while( ctx.iter.iStart>=0 && ctx.iter.iStartxTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx,fts5HighlightCb); } diff --git a/ext/fts5/fts5_expr.c b/ext/fts5/fts5_expr.c index ca795a6b35..c8f649c7fd 100644 --- a/ext/fts5/fts5_expr.c +++ b/ext/fts5/fts5_expr.c @@ -1659,7 +1659,7 @@ int sqlite3Fts5ExprClonePhrase( if( rc==SQLITE_OK ){ Fts5Colset *pColsetOrig = pOrig->pNode->pNear->pColset; if( pColsetOrig ){ - int nByte = sizeof(Fts5Colset) + pColsetOrig->nCol * sizeof(int); + int nByte = sizeof(Fts5Colset) + (pColsetOrig->nCol-1) * sizeof(int); Fts5Colset *pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&rc, nByte); if( pColset ){ memcpy(pColset, pColsetOrig, nByte); diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index 65b92a2b99..ef36e007df 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -702,7 +702,6 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){ return pRet; } - /* ** Release a reference to data record returned by an earlier call to ** fts5DataRead(). @@ -711,6 +710,18 @@ static void fts5DataRelease(Fts5Data *pData){ sqlite3_free(pData); } +static Fts5Data *fts5LeafRead(Fts5Index *p, i64 iRowid){ + Fts5Data *pRet = fts5DataRead(p, iRowid); + if( pRet ){ + if( pRet->szLeaf>pRet->nn ){ + p->rc = FTS5_CORRUPT; + fts5DataRelease(pRet); + pRet = 0; + } + } + return pRet; +} + static int fts5IndexPrepareStmt( Fts5Index *p, sqlite3_stmt **ppStmt, @@ -1519,7 +1530,7 @@ static void fts5SegIterNextPage( pIter->pLeaf = pIter->pNextLeaf; pIter->pNextLeaf = 0; }else if( pIter->iLeafPgno<=pSeg->pgnoLast ){ - pIter->pLeaf = fts5DataRead(p, + pIter->pLeaf = fts5LeafRead(p, FTS5_SEGMENT_ROWID(pSeg->iSegid, pIter->iLeafPgno) ); }else{ @@ -2022,9 +2033,8 @@ static void fts5SegIterNext( if( pLeaf->nn>pLeaf->szLeaf ){ pIter->iPgidxOff = pLeaf->szLeaf + fts5GetVarint32( &pLeaf->p[pLeaf->szLeaf], pIter->iEndofDoclist - ); + ); } - } else if( pLeaf->nn>pLeaf->szLeaf ){ pIter->iPgidxOff = pLeaf->szLeaf + fts5GetVarint32( @@ -2269,6 +2279,11 @@ static void fts5LeafSeek( iTermOff += nKeep; iOff = iTermOff; + if( iOff>=n ){ + p->rc = FTS5_CORRUPT; + return; + } + /* Read the nKeep field of the next term. */ fts5FastGetVarint32(a, iOff, nKeep); } diff --git a/ext/fts5/test/fts5af.test b/ext/fts5/test/fts5af.test index d6b2241568..21854662d3 100644 --- a/ext/fts5/test/fts5af.test +++ b/ext/fts5/test/fts5af.test @@ -108,6 +108,9 @@ foreach {tn doc res} { 7.4 {o o o X o o X o o} {...o [X] o o [X] o o} 7.5 {o o o o X o o X o} {...o o [X] o o [X] o} 7.6 {o o o o o X o o X} {...o o o [X] o o [X]} + + 8.1 {o o o o X o o o o o o o o o o o o o o o o o o o o o X X X o o o} + {...o o [X] [X] [X] o o...} } { do_snippet_test 1.$tn $doc X $res } diff --git a/ext/fts5/test/fts5corrupt2.test b/ext/fts5/test/fts5corrupt2.test index 3a4fcfaaed..c10017a266 100644 --- a/ext/fts5/test/fts5corrupt2.test +++ b/ext/fts5/test/fts5corrupt2.test @@ -37,7 +37,7 @@ do_execsql_test 1.0 { } set mask [expr 31 << 31] -if 1 { +if 0 { # Test 1: # @@ -84,6 +84,8 @@ foreach {tno stmt} { } } +} + # Using the same database as the 1.* tests. # # Run N-1 tests, where N is the number of bytes in the rightmost leaf page @@ -212,8 +214,6 @@ foreach {tn nCut} { # do_test 4.$tn.x { expr $nCorrupt>0 } 1 } -} - set doc [string repeat "A B C " 1000] do_execsql_test 5.0 { CREATE VIRTUAL TABLE x5 USING fts5(tt); diff --git a/ext/rbu/rbuprogress.test b/ext/rbu/rbuprogress.test index 6afbffe8ed..af202829c1 100644 --- a/ext/rbu/rbuprogress.test +++ b/ext/rbu/rbuprogress.test @@ -361,6 +361,8 @@ foreach {bReopen} { 0 1 } { } } { + if {$tn=="vtab"} { ifcapable !fts5 break } + foreach {tn2 rbusql r1 r2} { 1 { CREATE TABLE data0_t1(a, b, c, rbu_rowid, rbu_control); diff --git a/ext/rbu/rbuvacuum2.test b/ext/rbu/rbuvacuum2.test index 6397751836..bd38660320 100644 --- a/ext/rbu/rbuvacuum2.test +++ b/ext/rbu/rbuvacuum2.test @@ -156,7 +156,49 @@ foreach step {0 1} { trigger tr1 t1 0 {CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN SELECT 1; END} } } +} + +#------------------------------------------------------------------------- +# Test that passing a NULL value as the second argument to +# sqlite3rbu_vacuum() causes it to: +# +# * Use -vacuum as the state db, and +# * Set the state db permissions to the same as those on the db file. +# +db close +if {$::tcl_platform(platform)=="unix"} { + forcedelete test.db + sqlite3 db test.db + do_execsql_test 5.0 { + CREATE TABLE t1(a, b); + INSERT INTO t1 VALUES(1, 2); + INSERT INTO t1 VALUES(3, 4); + INSERT INTO t1 VALUES(5, 6); + INSERT INTO t1 VALUES(7, 8); + } + db close + + foreach {tn perm} { + 1 00755 + 2 00666 + 3 00644 + 4 00444 + } { + forcedelete test.db-vacuum + + do_test 5.$tn.1 { + file attributes test.db -permissions $perm + sqlite3rbu_vacuum rbu test.db + rbu step + } {SQLITE_OK} + + do_test 5.$tn.2 { file exists test.db-vacuum } 1 + do_test 5.$tn.3 { file attributes test.db-vacuum -permissions} $perm + rbu close + } } + finish_test + diff --git a/ext/rbu/sqlite3rbu.c b/ext/rbu/sqlite3rbu.c index 73c6647a2c..746469a8af 100644 --- a/ext/rbu/sqlite3rbu.c +++ b/ext/rbu/sqlite3rbu.c @@ -2334,15 +2334,18 @@ static RbuState *rbuLoadState(sqlite3rbu *p){ ** error occurs, leave an error code and message in the RBU handle. */ static void rbuOpenDatabase(sqlite3rbu *p){ - assert( p->rc==SQLITE_OK ); - assert( p->dbMain==0 && p->dbRbu==0 ); - assert( rbuIsVacuum(p) || p->zTarget!=0 ); + assert( p->rc || (p->dbMain==0 && p->dbRbu==0) ); + assert( p->rc || rbuIsVacuum(p) || p->zTarget!=0 ); /* Open the RBU database */ p->dbRbu = rbuOpenDbhandle(p, p->zRbu, 1); if( p->rc==SQLITE_OK && rbuIsVacuum(p) ){ sqlite3_file_control(p->dbRbu, "main", SQLITE_FCNTL_RBUCNT, (void*)p); + if( p->zState==0 ){ + const char *zFile = sqlite3_db_filename(p->dbRbu, "main"); + p->zState = rbuMPrintf(p, "file://%s-vacuum?modeof=%s", zFile, zFile); + } } /* If using separate RBU and state databases, attach the state database to @@ -3477,8 +3480,7 @@ static sqlite3rbu *openRbuHandle( sqlite3rbu *p; size_t nTarget = zTarget ? strlen(zTarget) : 0; size_t nRbu = strlen(zRbu); - size_t nState = zState ? strlen(zState) : 0; - size_t nByte = sizeof(sqlite3rbu) + nTarget+1 + nRbu+1+ nState+1; + size_t nByte = sizeof(sqlite3rbu) + nTarget+1 + nRbu+1; p = (sqlite3rbu*)sqlite3_malloc64(nByte); if( p ){ @@ -3500,8 +3502,7 @@ static sqlite3rbu *openRbuHandle( memcpy(p->zRbu, zRbu, nRbu+1); pCsr += nRbu+1; if( zState ){ - p->zState = pCsr; - memcpy(p->zState, zState, nState+1); + p->zState = rbuMPrintf(p, "%s", zState); } rbuOpenDatabase(p); } @@ -3611,6 +3612,20 @@ static sqlite3rbu *openRbuHandle( return p; } +/* +** Allocate and return an RBU handle with all fields zeroed except for the +** error code, which is set to SQLITE_MISUSE. +*/ +static sqlite3rbu *rbuMisuseError(void){ + sqlite3rbu *pRet; + pRet = sqlite3_malloc64(sizeof(sqlite3rbu)); + if( pRet ){ + memset(pRet, 0, sizeof(sqlite3rbu)); + pRet->rc = SQLITE_MISUSE; + } + return pRet; +} + /* ** Open and return a new RBU handle. */ @@ -3619,6 +3634,7 @@ sqlite3rbu *sqlite3rbu_open( const char *zRbu, const char *zState ){ + if( zTarget==0 || zRbu==0 ){ return rbuMisuseError(); } /* TODO: Check that zTarget and zRbu are non-NULL */ return openRbuHandle(zTarget, zRbu, zState); } @@ -3630,6 +3646,7 @@ sqlite3rbu *sqlite3rbu_vacuum( const char *zTarget, const char *zState ){ + if( zTarget==0 ){ return rbuMisuseError(); } /* TODO: Check that both arguments are non-NULL */ return openRbuHandle(0, zTarget, zState); } @@ -3707,6 +3724,7 @@ int sqlite3rbu_close(sqlite3rbu *p, char **pzErrmsg){ rbuEditErrmsg(p); rc = p->rc; *pzErrmsg = p->zErrmsg; + sqlite3_free(p->zState); sqlite3_free(p); }else{ rc = SQLITE_NOMEM; diff --git a/ext/rbu/sqlite3rbu.h b/ext/rbu/sqlite3rbu.h index 9ce39f543c..3f5f29a8e6 100644 --- a/ext/rbu/sqlite3rbu.h +++ b/ext/rbu/sqlite3rbu.h @@ -319,16 +319,22 @@ sqlite3rbu *sqlite3rbu_open( ** An RBU vacuum is similar to SQLite's built-in VACUUM command, except ** that it can be suspended and resumed like an RBU update. ** -** The second argument to this function, which may not be NULL, identifies -** a database in which to store the state of the RBU vacuum operation if -** it is suspended. The first time sqlite3rbu_vacuum() is called, to start -** an RBU vacuum operation, the state database should either not exist or -** be empty (contain no tables). If an RBU vacuum is suspended by calling +** The second argument to this function identifies a database in which +** to store the state of the RBU vacuum operation if it is suspended. The +** first time sqlite3rbu_vacuum() is called, to start an RBU vacuum +** operation, the state database should either not exist or be empty +** (contain no tables). If an RBU vacuum is suspended by calling ** sqlite3rbu_close() on the RBU handle before sqlite3rbu_step() has ** returned SQLITE_DONE, the vacuum state is stored in the state database. ** The vacuum can be resumed by calling this function to open a new RBU ** handle specifying the same target and state databases. ** +** If the second argument passed to this function is NULL, then the +** name of the state database is "-vacuum", where +** is the name of the target database file. In this case, on UNIX, if the +** state database is not already present in the file-system, it is created +** with the same permissions as the target db is made. +** ** This function does not delete the state database after an RBU vacuum ** is completed, even if it created it. However, if the call to ** sqlite3rbu_close() returns any value other than SQLITE_OK, the contents diff --git a/ext/rbu/test_rbu.c b/ext/rbu/test_rbu.c index bc4c800331..b1a2252741 100644 --- a/ext/rbu/test_rbu.c +++ b/ext/rbu/test_rbu.c @@ -240,13 +240,13 @@ static int SQLITE_TCLAPI test_sqlite3rbu_vacuum( const char *zTarget; const char *zStateDb = 0; - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 1, objv, "NAME TARGET-DB STATE-DB"); + if( objc!=3 && objc!=4 ){ + Tcl_WrongNumArgs(interp, 1, objv, "NAME TARGET-DB ?STATE-DB?"); return TCL_ERROR; } zCmd = Tcl_GetString(objv[1]); zTarget = Tcl_GetString(objv[2]); - zStateDb = Tcl_GetString(objv[3]); + if( objc==4 ) zStateDb = Tcl_GetString(objv[3]); pRbu = sqlite3rbu_vacuum(zTarget, zStateDb); Tcl_CreateObjCommand(interp, zCmd, test_sqlite3rbu_cmd, (ClientData)pRbu, 0); diff --git a/manifest b/manifest index 2542b4f4ed..22c5f502bf 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Simplify\sthe\svector\scomparison\scode\sgenerator\slogic,\sand\sthe\sresulting\nVDBE\scode. -D 2016-08-18T15:15:29.853 +C Merge\srecent\senhancements\sfrom\strunk. +D 2016-08-18T15:21:16.759 F Makefile.in cfd8fb987cd7a6af046daa87daa146d5aad0e088 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc d66d0395c38571aab3804f8db0fa20707ae4609a @@ -99,12 +99,12 @@ F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95 F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0 F ext/fts5/fts5.h 62f3e33ceeb9a428db139f9c012186b371da1cc7 F ext/fts5/fts5Int.h b2eda36e0f224365c8e23dc8f559311834f1c13f -F ext/fts5/fts5_aux.c daa57fb45216491814520bbb587e97bf81ced458 +F ext/fts5/fts5_aux.c e4bec077c5190946dbaac72c6555defd823724ca F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857 -F ext/fts5/fts5_expr.c df0004b5bffcbe34c329f2992669c6352443f415 +F ext/fts5/fts5_expr.c 1ee97156421919e497595bfa962bb88ad1665401 F ext/fts5/fts5_hash.c 880998e596b60f078348d48732ca4ad9a90caad2 -F ext/fts5/fts5_index.c 05386732609221d066d204b22c4a5275a0225ed4 +F ext/fts5/fts5_index.c 2d146d5c547f60d22d6fc4014d5e2b64248cd7c4 F ext/fts5/fts5_main.c f85281445dcf8be32d18841c93a6f90fe27dbfe2 F ext/fts5/fts5_storage.c de0ed8a06738bde433afe11e92295ceaffbc4e58 F ext/fts5/fts5_tcl.c 4a901f00c8553740dba63511603f5527d741c26a @@ -122,7 +122,7 @@ F ext/fts5/test/fts5ab.test 30325a89453280160106be411bba3acf138e6d1b F ext/fts5/test/fts5ac.test 55cad4275a1f5acabfe14d8442a8046b47e49e5f F ext/fts5/test/fts5ad.test 36995f0586f30f5602074e012b9224c71ec5171c F ext/fts5/test/fts5ae.test 612dcb51f4069226791ff14c17dbfb3138c56f20 -F ext/fts5/test/fts5af.test be858a96b1f5de66ba6d64f0021bd8b2408e126c +F ext/fts5/test/fts5af.test b6afd7c28ad62d546c30f387fb971f3aaebaac0d F ext/fts5/test/fts5ag.test 27180de76c03036be75ee80b93d8c5f540014071 F ext/fts5/test/fts5ah.test dfb7897711dbcda1dacb038aec310daca139fcf5 F ext/fts5/test/fts5ai.test 3909d0b949b2afcaae4d5795cd79153da75381df @@ -141,7 +141,7 @@ F ext/fts5/test/fts5config.test 7788b9c058074d640dfcdd81d97b6a9480000368 F ext/fts5/test/fts5conflict.test 26f4e46c4d31e16221794832a990dc4e30e18de5 F ext/fts5/test/fts5content.test 9a952c95518a14182dc3b59e3c8fa71cda82a4e1 F ext/fts5/test/fts5corrupt.test c2ad090192708150d50d961278df10ae7a4b8b62 -F ext/fts5/test/fts5corrupt2.test 26c0a39dd9ff73207e6229f83b50b21d37c7658c +F ext/fts5/test/fts5corrupt2.test 128eb6e2d26b09f4da339e581f424b3321e0fdaa F ext/fts5/test/fts5corrupt3.test f77f65e386231daf62902466b40ff998b2c8ce4f F ext/fts5/test/fts5detail.test ef5c690535a797413acaf5ad9b8ab5d49972df69 F ext/fts5/test/fts5determin.test 10648edb75ef1e196b10978fd21a9be0c31e09c3 @@ -250,13 +250,13 @@ F ext/rbu/rbufault.test cc0be8d5d392d98b0c2d6a51be377ea989250a89 F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06 F ext/rbu/rbufault3.test 54a399888ac4af44c68f9f58afbed23149428bca F ext/rbu/rbufts.test 828cd689da825f0a7b7c53ffc1f6f7fdb6fa5bda -F ext/rbu/rbuprogress.test 2023a7df2c523e3df1cb532eff811cda385a789a +F ext/rbu/rbuprogress.test e3e25fb7622641b8f2df7c6b7a7eb6fddfc46a4b F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48 F ext/rbu/rbuvacuum.test 4a977447c15c2581ab668781d9ef4294382530e0 -F ext/rbu/rbuvacuum2.test 45009e127c3fb385e5c0fd5a8a63fb922a79d0ab -F ext/rbu/sqlite3rbu.c 948677ee0ec57da51148e6c5f64ac68afcf36ab2 -F ext/rbu/sqlite3rbu.h db8858120c9be14b60c9225f9da28221f5f6b945 -F ext/rbu/test_rbu.c 1a6bbc6982e32485a48df111d0bb1934d537eabd +F ext/rbu/rbuvacuum2.test 2569205b74ff40fbf3bda2fce33a58eb40eebdcc +F ext/rbu/sqlite3rbu.c e074c38798b90591f7f0cf0032d62f152ce5a95e +F ext/rbu/sqlite3rbu.h 1d91c5b7d066645bd1ff8e4b85c2b9b5dd29fb05 +F ext/rbu/test_rbu.c 5aa22616afac6f71ebd3d9bc9bf1006cfabcca88 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 F ext/rtree/rtree.c d26a815b0df1c412a6881dae8d7fd3c9c08cce68 F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e @@ -321,35 +321,35 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a -F src/alter.c cc28ab933ae615b22add0d609794ffb6596b42ea -F src/analyze.c 37fedc80ac966ce1745811746e68e4d8fa64c7fe -F src/attach.c 771153bd1f4ab0b97a44a13dde2c7e5e1efeba22 -F src/auth.c 5c8e0f37f785f935f589496801edd19840485853 +F src/alter.c 299117695b1f21ac62dfc5b608588810ba22ed0d +F src/analyze.c 8b62b2cf4da85451534ac0af82cafc418d837f68 +F src/attach.c 4711ff365df4072b8c3dcd55db5d12dcf8ffa0c6 +F src/auth.c 930b376a9c56998557367e6f7f8aaeac82a2a792 F src/backup.c 17cd25a36d49330df2bacd2cadf2a61f3b525976 F src/bitvec.c 3ee4c8b2c94ed3a7377256e18199e6ff5cf33f63 F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 F src/btree.c 2551bd3ecb8b8988fb8b23aabadfb214dbc38e46 F src/btree.h 075c45707c0f8f8af118f739f36df8098a08b7da F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 -F src/build.c 7c3c780b703c09314032c8f6e4e7c1d80241a818 +F src/build.c c38fd92a8d886a5b9397267bf63b76ebad05c4d5 F src/callback.c 2e76147783386374bf01b227f752c81ec872d730 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c e77f3dc297b4b65c96da78b4ae4272fdfae863d7 F src/date.c 95c9a8d00767e7221a8e9a31f4e913fc8029bf6b -F src/dbstat.c 4f6f7f52b49beb9636ffbd517cfe44a402ba4ad0 -F src/delete.c 4aba4214a377ce8ddde2d2e609777bcc8235200f +F src/dbstat.c 19ee7a4e89979d4df8e44cfac7a8f905ec89b77d +F src/delete.c 76c084f0265f4a3cd1ecf17eee112a94f1ccbc05 F src/expr.c d79a02ba0f5b44c3319154641247979c48eec637 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb -F src/fkey.c bc4145347595b7770f9a598cff1c848302cf5413 +F src/fkey.c e2be0968c1adc679c87e467aa5b4f167588f38a8 F src/func.c 29cc9acb170ec1387b9f63eb52cd85f8de96c771 F src/global.c c45ea22aff29334f6a9ec549235ac3357c970015 F src/hash.c 55b5fb474100cee0b901edaf203e26c970940f36 F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4 F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da -F src/insert.c 8f4e9fcbd8e95e85f15647ba8b413b18d556ec2b +F src/insert.c d5cd8315c0577e86e17dda9239b45cffa81022c0 F src/legacy.c 75d3023be8f0d2b99d60f905090341a03358c58e F src/loadext.c dd7a2b77902cc66c22555aef02e1a682554b7aec -F src/main.c 16c1b2114eae8804caf3a8de8cb47bf2c6d83ad3 +F src/main.c 8dc7adfeace35ee1f4c489b503ee8fe6bc1fa802 F src/malloc.c 1443d1ad95d67c21d77af7ae3f44678252f0efec F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b @@ -368,7 +368,7 @@ F src/os.c add02933b1dce7a39a005b00a2f5364b763e9a24 F src/os.h 8e976e59eb4ca1c0fca6d35ee803e38951cb0343 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 -F src/os_unix.c a9443cdab41d7f3cdf0df3a5aab62fd6e1c9b234 +F src/os_unix.c be9ca0f901a2b6c1bc93dc338f4863675180c189 F src/os_win.c 520f23475f1de530c435d30b67b7b15fe90874b0 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c 40928c450320da78bb4bd3ae82818f4239e19b7e @@ -377,19 +377,19 @@ F src/parse.y a7402dff6fe8238795f15ca194e1f1b734d169f4 F src/pcache.c 5583c8ade4b05075a60ba953ef471d1c1a9c05df F src/pcache.h 2cedcd8407eb23017d92790b112186886e179490 F src/pcache1.c 4bb7a6a5300c67d0b033d25adb509c120c03e812 -F src/pragma.c c8b499756658cb8b82cfdbb5845c22cf11f297aa +F src/pragma.c d932ba278654617cdd281f88a790a3185fca7c44 F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c -F src/prepare.c 22df6171aec1d86904ed2ad30c2348a5748aa04e +F src/prepare.c a668988f324961397305b8352cf6bd87776fb347 F src/printf.c a5f0ca08ddede803c241266abb46356ec748ded1 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 -F src/resolve.c 0392c6686586b1d4dac9a4106959f03ddd70e9aa +F src/resolve.c d67b9a5cc33339256e2088c5a722745fc2ff5219 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac -F src/select.c 228eec644a778a31763b3d384d1ee1a5e3cf2349 +F src/select.c 3a5ddce5d3773c42e4bd96ee93e758c22cbc59ae F src/shell.c 79dda477be6c96eba6e952a934957ad36f87acc7 F src/sqlite.h.in 0f7580280d1b009b507d8beec1ff0f197ba0cc99 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 8648034aa702469afb553231677306cc6492a1ae -F src/sqliteInt.h 98d9ccfa30c0d4b1b886ed61f409dc6b307e9b0f +F src/sqliteInt.h 1b51d9e1ae63476fbe69423d531afdefab8aa18f F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247 F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1 F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 @@ -445,21 +445,21 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c 78c8085bc7af1922aa687f0f4bbd716821330de5 F src/treeview.c c56d6ddbed564efda746236b35bcbb8238daac4b -F src/trigger.c e14840ee0c3e549e758ec9bf3e4146e166002280 -F src/update.c 4f05ea8cddfa367d045e03589756c02199e8f9bd +F src/trigger.c 11e20b3b12c847b3b9055594c0f1631266bb53fc +F src/update.c 8179e699dbd45b92934fd02d3d8e3732e8da8802 F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c F src/util.c 810ec3f22e2d1b62e66c30fe3621ebdedd23584d -F src/vacuum.c 9dd2f5d276bc6094d8f1d85ecd41b30c1a002a43 -F src/vdbe.c 1b66646c30ae83db67edce52f62801e6204a6e47 +F src/vacuum.c f6f10c88f8af5feb6b3632e5e4133e4482819c4f +F src/vdbe.c 9a1c5a2d1980ca6a111ce8649e06ed8c790ee1fc F src/vdbe.h 67bc551f7faf04c33493892e4b378aada823ed10 F src/vdbeInt.h c59381049af5c7751a83456c39b80d1a6fde1f9d -F src/vdbeapi.c c3f6715a99995c11748ecad91d25e93fd9fc390b +F src/vdbeapi.c a32d61b7dd05e6890d8fd44d2805f55e2f5ba9f3 F src/vdbeaux.c a32d79aeaa88dc2b97c261172d952d395254a055 -F src/vdbeblob.c 83d2d266383157b02e2b809350bb197e89d7895b +F src/vdbeblob.c 3e82a797b60c3b9fed7b8de8c539ca7607874937 F src/vdbemem.c 77d6505956bf4e45c328ab3ebef6b461334cab5d F src/vdbesort.c 91fda3909326860382b0ca8aa251e609c6a9d62c F src/vdbetrace.c 41963d5376f0349842b5fc4aaaaacd7d9cdc0834 -F src/vtab.c 6b3cfaff7e4397739d6b48511e777ca58c6d06d4 +F src/vtab.c 5ca4fa8b028f9e2ed4793ee1670911a83cfcefd8 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 02eeecc265f6ffd0597378f5d8ae9070b62a406a F src/wal.h 6dd221ed384afdc204bc61e25c23ef7fd5a511f2 @@ -1443,7 +1443,7 @@ F tool/fuzzershell.c 94019b185caceffc9f7c7b678a6489e42bc2aefa F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4 F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce -F tool/lemon.c e3aa9ba3469804d7cae13b5e041aab192b7b381a +F tool/lemon.c e4fb7d888873ac88f20a41c84a7d1e61f5209a6d F tool/lempar.c 147e42a5cd83ce38275fde0d07a5df3330cb9b3b F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 @@ -1516,8 +1516,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 381aa73141db8ec59adbcb09e71af660ee4ae5ce c54bd9c82dd34951dc87848c0b19fcccaef928db -R 4db42b6f0c7885d63148768f55fefe94 -T +closed c54bd9c82dd34951dc87848c0b19fcccaef928db +P e2ad0b5d8e1e83118c12889150aca2f2a6b2bdde 92a22f01343a898455fd61c3b8e7d7c954f5b569 +R a3d6c4bcdda8d18e3de85b224695f9f6 U drh -Z 3cfa77acd6574617a13d27cce1aa0dbe +Z 554fed64519eb39711e06c16c9610431 diff --git a/manifest.uuid b/manifest.uuid index 6d15ad67b8..a8a1479273 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e2ad0b5d8e1e83118c12889150aca2f2a6b2bdde \ No newline at end of file +4768a1066cb9c7627064d7efec44188d6755cb03 \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index 806ed49172..2c86a8bac2 100644 --- a/src/alter.c +++ b/src/alter.c @@ -413,7 +413,7 @@ void sqlite3AlterRenameTable( pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]); if( !pTab ) goto exit_rename_table; iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); - zDb = db->aDb[iDb].zName; + zDb = db->aDb[iDb].zDbSName; db->flags |= SQLITE_PreferBuiltin; /* Get a NULL terminated version of the new table name. */ @@ -611,7 +611,7 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ assert( sqlite3BtreeHoldsAllMutexes(db) ); iDb = sqlite3SchemaToIndex(db, pNew->pSchema); - zDb = db->aDb[iDb].zName; + zDb = db->aDb[iDb].zDbSName; zTab = &pNew->zName[16]; /* Skip the "sqlite_altertab_" prefix on the name */ pCol = &pNew->aCol[pNew->nCol-1]; pDflt = pCol->pDflt; diff --git a/src/analyze.c b/src/analyze.c index 3a81c93245..e3955f3022 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -210,14 +210,14 @@ static void openStatTable( for(i=0; izName))==0 ){ + if( (pStat = sqlite3FindTable(db, zTab, pDb->zDbSName))==0 ){ if( aTable[i].zCols ){ /* The sqlite_statN table does not exist. Create it. Note that a ** side-effect of the CREATE TABLE statement is to leave the rootpage ** of the new table in register pParse->regRoot. This is important ** because the OpenWrite opcode below will be needing it. */ sqlite3NestedParse(pParse, - "CREATE TABLE %Q.%s(%s)", pDb->zName, zTab, aTable[i].zCols + "CREATE TABLE %Q.%s(%s)", pDb->zDbSName, zTab, aTable[i].zCols ); aRoot[i] = pParse->regRoot; aCreateTbl[i] = OPFLAG_P2ISREG; @@ -232,7 +232,7 @@ static void openStatTable( if( zWhere ){ sqlite3NestedParse(pParse, "DELETE FROM %Q.%s WHERE %s=%Q", - pDb->zName, zTab, zWhereType, zWhere + pDb->zDbSName, zTab, zWhereType, zWhere ); }else{ /* The sqlite_stat[134] table already exists. Delete all rows. */ @@ -994,7 +994,7 @@ static void analyzeOneTable( assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); #ifndef SQLITE_OMIT_AUTHORIZATION if( sqlite3AuthCheck(pParse, SQLITE_ANALYZE, pTab->zName, 0, - db->aDb[iDb].zName ) ){ + db->aDb[iDb].zDbSName ) ){ return; } #endif @@ -1384,7 +1384,7 @@ void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){ /* Form 3: Analyze the fully qualified table name */ iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pTableName); if( iDb>=0 ){ - zDb = db->aDb[iDb].zName; + zDb = db->aDb[iDb].zDbSName; z = sqlite3NameFromToken(db, pTableName); if( z ){ if( (pIdx = sqlite3FindIndex(db, z, zDb))!=0 ){ @@ -1844,7 +1844,7 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ /* Load new statistics out of the sqlite_stat1 table */ sInfo.db = db; - sInfo.zDatabase = db->aDb[iDb].zName; + sInfo.zDatabase = db->aDb[iDb].zDbSName; if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)!=0 ){ zSql = sqlite3MPrintf(db, "SELECT tbl,idx,stat FROM %Q.sqlite_stat1", sInfo.zDatabase); diff --git a/src/attach.c b/src/attach.c index ea378a40a2..5d2a55278d 100644 --- a/src/attach.c +++ b/src/attach.c @@ -97,7 +97,7 @@ static void attachFunc( goto attach_error; } for(i=0; inDb; i++){ - char *z = db->aDb[i].zName; + char *z = db->aDb[i].zDbSName; assert( z && zName ); if( sqlite3StrICmp(z, zName)==0 ){ zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName); @@ -162,8 +162,8 @@ static void attachFunc( sqlite3BtreeLeave(aNew->pBt); } aNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1; - aNew->zName = sqlite3DbStrDup(db, zName); - if( rc==SQLITE_OK && aNew->zName==0 ){ + aNew->zDbSName = sqlite3DbStrDup(db, zName); + if( rc==SQLITE_OK && aNew->zDbSName==0 ){ rc = SQLITE_NOMEM_BKPT; } @@ -275,7 +275,7 @@ static void detachFunc( for(i=0; inDb; i++){ pDb = &db->aDb[i]; if( pDb->pBt==0 ) continue; - if( sqlite3StrICmp(pDb->zName, zName)==0 ) break; + if( sqlite3StrICmp(pDb->zDbSName, zName)==0 ) break; } if( i>=db->nDb ){ @@ -433,7 +433,7 @@ void sqlite3FixInit( db = pParse->db; assert( db->nDb>iDb ); pFix->pParse = pParse; - pFix->zDb = db->aDb[iDb].zName; + pFix->zDb = db->aDb[iDb].zDbSName; pFix->pSchema = db->aDb[iDb].pSchema; pFix->zType = zType; pFix->pName = pName; diff --git a/src/auth.c b/src/auth.c index 8a3f8e7d08..77a95d4a8f 100644 --- a/src/auth.c +++ b/src/auth.c @@ -107,9 +107,9 @@ int sqlite3AuthReadCol( const char *zCol, /* Column name */ int iDb /* Index of containing database. */ ){ - sqlite3 *db = pParse->db; /* Database handle */ - char *zDb = db->aDb[iDb].zName; /* Name of attached database */ - int rc; /* Auth callback return code */ + sqlite3 *db = pParse->db; /* Database handle */ + char *zDb = db->aDb[iDb].zDbSName; /* Schema name of attached database */ + int rc; /* Auth callback return code */ if( db->init.busy ) return SQLITE_OK; rc = db->xAuth(db->pAuthArg, SQLITE_READ, zTab,zCol,zDb,pParse->zAuthContext diff --git a/src/build.c b/src/build.c index b14e6f2fc2..bf7080ed49 100644 --- a/src/build.c +++ b/src/build.c @@ -318,10 +318,11 @@ Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){ #endif for(i=OMIT_TEMPDB; inDb; i++){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ - if( zDatabase!=0 && sqlite3StrICmp(zDatabase, db->aDb[j].zName) ) continue; - assert( sqlite3SchemaMutexHeld(db, j, 0) ); - p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName); - if( p ) break; + if( zDatabase==0 || sqlite3StrICmp(zDatabase, db->aDb[j].zDbSName)==0 ){ + assert( sqlite3SchemaMutexHeld(db, j, 0) ); + p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName); + if( p ) break; + } } return p; } @@ -395,7 +396,7 @@ Table *sqlite3LocateTableItem( assert( p->pSchema==0 || p->zDatabase==0 ); if( p->pSchema ){ int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema); - zDb = pParse->db->aDb[iDb].zName; + zDb = pParse->db->aDb[iDb].zDbSName; }else{ zDb = p->zDatabase; } @@ -423,7 +424,7 @@ Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ Schema *pSchema = db->aDb[j].pSchema; assert( pSchema ); - if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zName) ) continue; + if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zDbSName) ) continue; assert( sqlite3SchemaMutexHeld(db, j, 0) ); p = sqlite3HashFind(&pSchema->idxHash, zName); if( p ) break; @@ -492,8 +493,8 @@ void sqlite3CollapseDatabaseArray(sqlite3 *db){ for(i=j=2; inDb; i++){ struct Db *pDb = &db->aDb[i]; if( pDb->pBt==0 ){ - sqlite3DbFree(db, pDb->zName); - pDb->zName = 0; + sqlite3DbFree(db, pDb->zDbSName); + pDb->zDbSName = 0; continue; } if( jnDb-1), pDb=&db->aDb[i]; i>=0; i--, pDb--){ - if( 0==sqlite3StrICmp(pDb->zName, zName) ) break; + if( 0==sqlite3StrICmp(pDb->zDbSName, zName) ) break; } } return i; @@ -883,7 +884,7 @@ void sqlite3StartTable( SQLITE_CREATE_VIEW, SQLITE_CREATE_TEMP_VIEW }; - char *zDb = db->aDb[iDb].zName; + char *zDb = db->aDb[iDb].zDbSName; if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){ goto begin_table_error; } @@ -902,7 +903,7 @@ void sqlite3StartTable( ** collisions. */ if( !IN_DECLARE_VTAB ){ - char *zDb = db->aDb[iDb].zName; + char *zDb = db->aDb[iDb].zDbSName; if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ goto begin_table_error; } @@ -1995,7 +1996,7 @@ void sqlite3EndTable( "UPDATE %Q.%s " "SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q " "WHERE rowid=#%d", - db->aDb[iDb].zName, SCHEMA_TABLE(iDb), + db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), zType, p->zName, p->zName, @@ -2016,7 +2017,7 @@ void sqlite3EndTable( if( pDb->pSchema->pSeqTab==0 ){ sqlite3NestedParse(pParse, "CREATE TABLE %Q.sqlite_sequence(name,seq)", - pDb->zName + pDb->zDbSName ); } } @@ -2330,7 +2331,7 @@ static void destroyRootPage(Parse *pParse, int iTable, int iDb){ */ sqlite3NestedParse(pParse, "UPDATE %Q.%s SET rootpage=%d WHERE #%d AND rootpage=#%d", - pParse->db->aDb[iDb].zName, SCHEMA_TABLE(iDb), iTable, r1, r1); + pParse->db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), iTable, r1, r1); #endif sqlite3ReleaseTempReg(pParse, r1); } @@ -2406,7 +2407,7 @@ static void sqlite3ClearStatTables( const char *zName /* Name of index or table */ ){ int i; - const char *zDbName = pParse->db->aDb[iDb].zName; + const char *zDbName = pParse->db->aDb[iDb].zDbSName; for(i=1; i<=4; i++){ char zTab[24]; sqlite3_snprintf(sizeof(zTab),zTab,"sqlite_stat%d",i); @@ -2459,7 +2460,7 @@ void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, int isView){ if( pTab->tabFlags & TF_Autoincrement ){ sqlite3NestedParse(pParse, "DELETE FROM %Q.sqlite_sequence WHERE name=%Q", - pDb->zName, pTab->zName + pDb->zDbSName, pTab->zName ); } #endif @@ -2473,7 +2474,7 @@ void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, int isView){ */ sqlite3NestedParse(pParse, "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'", - pDb->zName, SCHEMA_TABLE(iDb), pTab->zName); + pDb->zDbSName, SCHEMA_TABLE(iDb), pTab->zName); if( !isView && !IsVirtual(pTab) ){ destroyTable(pParse, pTab); } @@ -2527,7 +2528,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){ { int code; const char *zTab = SCHEMA_TABLE(iDb); - const char *zDb = db->aDb[iDb].zName; + const char *zDb = db->aDb[iDb].zDbSName; const char *zArg2 = 0; if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb)){ goto exit_drop_table; @@ -2768,7 +2769,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ #ifndef SQLITE_OMIT_AUTHORIZATION if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0, - db->aDb[iDb].zName ) ){ + db->aDb[iDb].zDbSName ) ){ return; } #endif @@ -3020,7 +3021,7 @@ void sqlite3CreateIndex( goto exit_create_index; } } - if( sqlite3FindIndex(db, zName, pDb->zName)!=0 ){ + if( sqlite3FindIndex(db, zName, pDb->zDbSName)!=0 ){ if( !ifNotExist ){ sqlite3ErrorMsg(pParse, "index %s already exists", zName); }else{ @@ -3050,7 +3051,7 @@ void sqlite3CreateIndex( */ #ifndef SQLITE_OMIT_AUTHORIZATION { - const char *zDb = pDb->zName; + const char *zDb = pDb->zDbSName; if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iDb), 0, zDb) ){ goto exit_create_index; } @@ -3365,7 +3366,7 @@ void sqlite3CreateIndex( */ sqlite3NestedParse(pParse, "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);", - db->aDb[iDb].zName, SCHEMA_TABLE(iDb), + db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), pIndex->zName, pTab->zName, iMem, @@ -3499,7 +3500,7 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){ { int code = SQLITE_DROP_INDEX; Table *pTab = pIndex->pTable; - const char *zDb = db->aDb[iDb].zName; + const char *zDb = db->aDb[iDb].zDbSName; const char *zTab = SCHEMA_TABLE(iDb); if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ goto exit_drop_index; @@ -3517,7 +3518,7 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){ sqlite3BeginWriteOperation(pParse, 1, iDb); sqlite3NestedParse(pParse, "DELETE FROM %Q.%s WHERE name=%Q AND type='index'", - db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pIndex->zName + db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), pIndex->zName ); sqlite3ClearStatTables(pParse, iDb, "idx", pIndex->zName); sqlite3ChangeCookie(pParse, iDb); @@ -4062,7 +4063,7 @@ void sqlite3CodeVerifyNamedSchema(Parse *pParse, const char *zDb){ int i; for(i=0; inDb; i++){ Db *pDb = &db->aDb[i]; - if( pDb->pBt && (!zDb || 0==sqlite3StrICmp(zDb, pDb->zName)) ){ + if( pDb->pBt && (!zDb || 0==sqlite3StrICmp(zDb, pDb->zDbSName)) ){ sqlite3CodeVerifySchema(pParse, i); } } @@ -4309,7 +4310,7 @@ void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){ if( iDb<0 ) return; z = sqlite3NameFromToken(db, pObjName); if( z==0 ) return; - zDb = db->aDb[iDb].zName; + zDb = db->aDb[iDb].zDbSName; pTab = sqlite3FindTable(db, z, zDb); if( pTab ){ reindexTable(pParse, pTab, 0); diff --git a/src/dbstat.c b/src/dbstat.c index 92ce650df1..13974bb979 100644 --- a/src/dbstat.c +++ b/src/dbstat.c @@ -602,7 +602,7 @@ static int statFilter( " UNION ALL " "SELECT name, rootpage, type" " FROM \"%w\".%s WHERE rootpage!=0" - " ORDER BY name", pTab->db->aDb[pCsr->iDb].zName, zMaster); + " ORDER BY name", pTab->db->aDb[pCsr->iDb].zDbSName, zMaster); if( zSql==0 ){ return SQLITE_NOMEM_BKPT; }else{ @@ -656,7 +656,7 @@ static int statColumn( default: { /* schema */ sqlite3 *db = sqlite3_context_db_handle(ctx); int iDb = pCsr->iDb; - sqlite3_result_text(ctx, db->aDb[iDb].zName, -1, SQLITE_STATIC); + sqlite3_result_text(ctx, db->aDb[iDb].zDbSName, -1, SQLITE_STATIC); break; } } diff --git a/src/delete.c b/src/delete.c index e9e669e21c..3d9360e925 100644 --- a/src/delete.c +++ b/src/delete.c @@ -102,7 +102,7 @@ void sqlite3MaterializeView( if( pFrom ){ assert( pFrom->nSrc==1 ); pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName); - pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zName); + pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName); assert( pFrom->a[0].pOn==0 ); assert( pFrom->a[0].pUsing==0 ); } @@ -289,7 +289,7 @@ void sqlite3DeleteFrom( } iDb = sqlite3SchemaToIndex(db, pTab->pSchema); assert( iDbnDb ); - zDb = db->aDb[iDb].zName; + zDb = db->aDb[iDb].zDbSName; rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb); assert( rcauth==SQLITE_OK || rcauth==SQLITE_DENY || rcauth==SQLITE_IGNORE ); if( rcauth==SQLITE_DENY ){ diff --git a/src/fkey.c b/src/fkey.c index 25d9f84917..609c3c6017 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -871,7 +871,7 @@ void sqlite3FkCheck( if( (db->flags&SQLITE_ForeignKeys)==0 ) return; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - zDb = db->aDb[iDb].zName; + zDb = db->aDb[iDb].zDbSName; /* Loop through all the foreign key constraints for which pTab is the ** child table (the table that the foreign key definition is part of). */ diff --git a/src/insert.c b/src/insert.c index 5dc045ab69..dacd37c7f1 100644 --- a/src/insert.c +++ b/src/insert.c @@ -547,7 +547,7 @@ void sqlite3Insert( iDb = sqlite3SchemaToIndex(db, pTab->pSchema); assert( iDbnDb ); pDb = &db->aDb[iDb]; - zDb = pDb->zName; + zDb = pDb->zDbSName; if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){ goto insert_cleanup; } diff --git a/src/main.c b/src/main.c index f31f865818..e719e76289 100644 --- a/src/main.c +++ b/src/main.c @@ -2932,9 +2932,9 @@ static int openDatabase( /* The default safety_level for the main database is FULL; for the temp ** database it is OFF. This matches the pager layer defaults. */ - db->aDb[0].zName = "main"; + db->aDb[0].zDbSName = "main"; db->aDb[0].safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1; - db->aDb[1].zName = "temp"; + db->aDb[1].zDbSName = "temp"; db->aDb[1].safety_level = PAGER_SYNCHRONOUS_OFF; db->magic = SQLITE_MAGIC_OPEN; @@ -3895,7 +3895,7 @@ Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){ int i; for(i=0; inDb; i++){ if( db->aDb[i].pBt - && (zDbName==0 || sqlite3StrICmp(zDbName, db->aDb[i].zName)==0) + && (zDbName==0 || sqlite3StrICmp(zDbName, db->aDb[i].zDbSName)==0) ){ return db->aDb[i].pBt; } diff --git a/src/os_unix.c b/src/os_unix.c index f5b01e9958..08d4cb5d11 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -5529,6 +5529,27 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){ return pUnused; } +/* +** Find the mode, uid and gid of file zFile. +*/ +static int getFileMode( + const char *zFile, /* File name */ + mode_t *pMode, /* OUT: Permissions of zFile */ + uid_t *pUid, /* OUT: uid of zFile. */ + gid_t *pGid /* OUT: gid of zFile. */ +){ + struct stat sStat; /* Output of stat() on database file */ + int rc = SQLITE_OK; + if( 0==osStat(zFile, &sStat) ){ + *pMode = sStat.st_mode & 0777; + *pUid = sStat.st_uid; + *pGid = sStat.st_gid; + }else{ + rc = SQLITE_IOERR_FSTAT; + } + return rc; +} + /* ** This function is called by unixOpen() to determine the unix permissions ** to create new files with. If no error occurs, then SQLITE_OK is returned @@ -5564,7 +5585,6 @@ static int findCreateFileMode( if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){ char zDb[MAX_PATHNAME+1]; /* Database file path */ int nDb; /* Number of valid bytes in zDb */ - struct stat sStat; /* Output of stat() on database file */ /* zPath is a path to a WAL or journal file. The following block derives ** the path to the associated database file from zPath. This block handles @@ -5595,15 +5615,18 @@ static int findCreateFileMode( memcpy(zDb, zPath, nDb); zDb[nDb] = '\0'; - if( 0==osStat(zDb, &sStat) ){ - *pMode = sStat.st_mode & 0777; - *pUid = sStat.st_uid; - *pGid = sStat.st_gid; - }else{ - rc = SQLITE_IOERR_FSTAT; - } + rc = getFileMode(zDb, pMode, pUid, pGid); }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){ *pMode = 0600; + }else if( flags & SQLITE_OPEN_URI ){ + /* If this is a main database file and the file was opened using a URI + ** filename, check for the "modeof" parameter. If present, interpret + ** its value as a filename and try to copy the mode, uid and gid from + ** that file. */ + const char *z = sqlite3_uri_parameter(zPath, "modeof"); + if( z ){ + rc = getFileMode(z, pMode, pUid, pGid); + } } return rc; } diff --git a/src/pragma.c b/src/pragma.c index 1ee08fbec0..e774de3421 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -338,7 +338,7 @@ void sqlite3Pragma( } assert( pId2 ); - zDb = pId2->n>0 ? pDb->zName : 0; + zDb = pId2->n>0 ? pDb->zDbSName : 0; if( sqlite3AuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, zDb) ){ goto pragma_out; } @@ -1191,10 +1191,10 @@ void sqlite3Pragma( setAllColumnNames(v, 3, azCol); assert( 3==ArraySize(azCol) ); for(i=0; inDb; i++){ if( db->aDb[i].pBt==0 ) continue; - assert( db->aDb[i].zName!=0 ); + assert( db->aDb[i].zDbSName!=0 ); sqlite3VdbeMultiLoad(v, 1, "iss", i, - db->aDb[i].zName, + db->aDb[i].zDbSName, sqlite3BtreeGetFilename(db->aDb[i].pBt)); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); } @@ -1483,7 +1483,7 @@ void sqlite3Pragma( sqlite3VdbeChangeP5(v, (u8)i); addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); VdbeCoverage(v); sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, - sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName), + sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zDbSName), P4_DYNAMIC); sqlite3VdbeAddOp3(v, OP_Move, 2, 4, 1); sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2); @@ -1922,15 +1922,15 @@ void sqlite3Pragma( Btree *pBt; const char *zState = "unknown"; int j; - if( db->aDb[i].zName==0 ) continue; + if( db->aDb[i].zDbSName==0 ) continue; pBt = db->aDb[i].pBt; if( pBt==0 || sqlite3BtreePager(pBt)==0 ){ zState = "closed"; - }else if( sqlite3_file_control(db, i ? db->aDb[i].zName : 0, + }else if( sqlite3_file_control(db, i ? db->aDb[i].zDbSName : 0, SQLITE_FCNTL_LOCKSTATE, &j)==SQLITE_OK ){ zState = azLockName[j]; } - sqlite3VdbeMultiLoad(v, 1, "ss", db->aDb[i].zName, zState); + sqlite3VdbeMultiLoad(v, 1, "ss", db->aDb[i].zDbSName, zState); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2); } break; diff --git a/src/prepare.c b/src/prepare.c index 6685dfeaf7..e193c54665 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -107,7 +107,7 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){ ** to do here is record the root page number for that index. */ Index *pIndex; - pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zName); + pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zDbSName); if( pIndex==0 ){ /* This can occur if there exists an index on a TEMP table which ** has the same name as another index on a permanent index. Since @@ -286,7 +286,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ char *zSql; zSql = sqlite3MPrintf(db, "SELECT name, rootpage, sql FROM \"%w\".%s ORDER BY rowid", - db->aDb[iDb].zName, zMasterName); + db->aDb[iDb].zDbSName, zMasterName); #ifndef SQLITE_OMIT_AUTHORIZATION { sqlite3_xauth xAuth; @@ -561,7 +561,7 @@ static int sqlite3Prepare( assert( sqlite3BtreeHoldsMutex(pBt) ); rc = sqlite3BtreeSchemaLocked(pBt); if( rc ){ - const char *zDb = db->aDb[i].zName; + const char *zDb = db->aDb[i].zDbSName; sqlite3ErrorWithMsg(db, rc, "database schema is locked: %s", zDb); testcase( db->flags & SQLITE_ReadUncommitted ); goto end_prepare; diff --git a/src/resolve.c b/src/resolve.c index 8ae7f0919c..206015fcfa 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -221,8 +221,8 @@ static int lookupName( zDb = 0; }else{ for(i=0; inDb; i++){ - assert( db->aDb[i].zName ); - if( sqlite3StrICmp(db->aDb[i].zName,zDb)==0 ){ + assert( db->aDb[i].zDbSName ); + if( sqlite3StrICmp(db->aDb[i].zDbSName,zDb)==0 ){ pSchema = db->aDb[i].pSchema; break; } diff --git a/src/select.c b/src/select.c index 7bcf3eca16..7fce8568a5 100644 --- a/src/select.c +++ b/src/select.c @@ -4396,7 +4396,7 @@ static int selectExpander(Walker *pWalker, Select *p){ continue; } iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - zSchemaName = iDb>=0 ? db->aDb[iDb].zName : "*"; + zSchemaName = iDb>=0 ? db->aDb[iDb].zDbSName : "*"; } for(j=0; jnCol; j++){ char *zName = pTab->aCol[j].zName; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 4c6554367f..f1d29c643e 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1097,7 +1097,7 @@ typedef struct With With; ** databases may be attached. */ struct Db { - char *zName; /* Name of this database */ + char *zDbSName; /* Name of this database. (schema name, not filename) */ Btree *pBt; /* The B*Tree structure for this database file */ u8 safety_level; /* How aggressive at syncing data to disk */ u8 bSyncSet; /* True if "PRAGMA synchronous=N" has been run */ diff --git a/src/trigger.c b/src/trigger.c index 72c31eb2a3..a1c16dd354 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -214,8 +214,8 @@ void sqlite3BeginTrigger( #ifndef SQLITE_OMIT_AUTHORIZATION { int code = SQLITE_CREATE_TRIGGER; - const char *zDb = db->aDb[iTabDb].zName; - const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb; + const char *zDb = db->aDb[iTabDb].zDbSName; + const char *zDbTrig = isTemp ? db->aDb[1].zDbSName : zDb; if( iTabDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER; if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){ goto trigger_cleanup; @@ -309,7 +309,7 @@ void sqlite3FinishTrigger( z = sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n); sqlite3NestedParse(pParse, "INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')", - db->aDb[iDb].zName, SCHEMA_TABLE(iDb), zName, + db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), zName, pTrig->table, z); sqlite3DbFree(db, z); sqlite3ChangeCookie(pParse, iDb); @@ -498,7 +498,7 @@ void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){ assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) ); for(i=OMIT_TEMPDB; inDb; i++){ int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ - if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue; + if( zDb && sqlite3StrICmp(db->aDb[j].zDbSName, zDb) ) continue; assert( sqlite3SchemaMutexHeld(db, j, 0) ); pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName); if( pTrigger ) break; @@ -544,7 +544,7 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){ #ifndef SQLITE_OMIT_AUTHORIZATION { int code = SQLITE_DROP_TRIGGER; - const char *zDb = db->aDb[iDb].zName; + const char *zDb = db->aDb[iDb].zDbSName; const char *zTab = SCHEMA_TABLE(iDb); if( iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER; if( sqlite3AuthCheck(pParse, code, pTrigger->zName, pTable->zName, zDb) || @@ -560,7 +560,7 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){ if( (v = sqlite3GetVdbe(pParse))!=0 ){ sqlite3NestedParse(pParse, "DELETE FROM %Q.%s WHERE name=%Q AND type='trigger'", - db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pTrigger->zName + db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), pTrigger->zName ); sqlite3ChangeCookie(pParse, iDb); sqlite3VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->zName, 0); @@ -663,8 +663,10 @@ static SrcList *targetSrcList( pSrc->a[pSrc->nSrc-1].zName = sqlite3DbStrDup(db, pStep->zTarget); iDb = sqlite3SchemaToIndex(db, pStep->pTrig->pSchema); if( iDb==0 || iDb>=2 ){ + const char *zDb; assert( iDbnDb ); - pSrc->a[pSrc->nSrc-1].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zName); + zDb = db->aDb[iDb].zDbSName; + pSrc->a[pSrc->nSrc-1].zDatabase = sqlite3DbStrDup(db, zDb); } } return pSrc; diff --git a/src/update.c b/src/update.c index 1436501264..15e58e34c5 100644 --- a/src/update.c +++ b/src/update.c @@ -249,7 +249,7 @@ void sqlite3Update( int rc; rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName, j<0 ? "ROWID" : pTab->aCol[j].zName, - db->aDb[iDb].zName); + db->aDb[iDb].zDbSName); if( rc==SQLITE_DENY ){ goto update_cleanup; }else if( rc==SQLITE_IGNORE ){ diff --git a/src/vacuum.c b/src/vacuum.c index b72663c066..eb07664c88 100644 --- a/src/vacuum.c +++ b/src/vacuum.c @@ -173,7 +173,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ rc = execSql(db, pzErrMsg, zSql); if( db->nDb>nDb ){ pDb = &db->aDb[db->nDb-1]; - assert( strcmp(pDb->zName,"vacuum_db")==0 ); + assert( strcmp(pDb->zDbSName,"vacuum_db")==0 ); } if( rc!=SQLITE_OK ) goto end_of_vacuum; pTemp = db->aDb[db->nDb-1].pBt; diff --git a/src/vdbe.c b/src/vdbe.c index 1578d2d87e..97939a727d 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -4382,7 +4382,7 @@ case OP_InsertInt: { if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){ assert( pC->isTable ); assert( pC->iDb>=0 ); - zDb = db->aDb[pC->iDb].zName; + zDb = db->aDb[pC->iDb].zDbSName; pTab = pOp->p4.pTab; assert( HasRowid(pTab) ); op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT); @@ -4499,7 +4499,7 @@ case OP_Delete: { if( pOp->p4type==P4_TABLE && HAS_UPDATE_HOOK(db) ){ assert( pC->iDb>=0 ); assert( pOp->p4.pTab!=0 ); - zDb = db->aDb[pC->iDb].zName; + zDb = db->aDb[pC->iDb].zDbSName; pTab = pOp->p4.pTab; if( (pOp->p5 & OPFLAG_SAVEPOSITION)!=0 && pC->isTable ){ pC->movetoTarget = sqlite3BtreeIntegerKey(pC->uc.pCursor); @@ -5469,7 +5469,7 @@ case OP_ParseSchema: { initData.pzErrMsg = &p->zErrMsg; zSql = sqlite3MPrintf(db, "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid", - db->aDb[iDb].zName, zMaster, pOp->p4.z); + db->aDb[iDb].zDbSName, zMaster, pOp->p4.z); if( zSql==0 ){ rc = SQLITE_NOMEM_BKPT; }else{ @@ -6853,7 +6853,7 @@ case OP_Init: { /* jump */ int i; for(i=0; inDb; i++){ if( DbMaskTest(p->btreeMask, i)==0 ) continue; - sqlite3_file_control(db, db->aDb[i].zName, SQLITE_FCNTL_TRACE, zTrace); + sqlite3_file_control(db, db->aDb[i].zDbSName, SQLITE_FCNTL_TRACE, zTrace); } } #endif /* SQLITE_USE_FCNTL_TRACE */ diff --git a/src/vdbeapi.c b/src/vdbeapi.c index b17c0e0a40..3d36413bc4 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -499,7 +499,7 @@ static int doWalCallbacks(sqlite3 *db){ nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt)); sqlite3BtreeLeave(pBt); if( db->xWalCallback && nEntry>0 && rc==SQLITE_OK ){ - rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zName, nEntry); + rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zDbSName, nEntry); } } } diff --git a/src/vdbeblob.c b/src/vdbeblob.c index 01827f94d0..570e253fdb 100644 --- a/src/vdbeblob.c +++ b/src/vdbeblob.c @@ -176,7 +176,7 @@ int sqlite3_blob_open( goto blob_open_out; } pBlob->pTab = pTab; - pBlob->zDb = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zName; + pBlob->zDb = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName; /* Now search pTab for the exact column. */ for(iCol=0; iColnCol; iCol++) { diff --git a/src/vtab.c b/src/vtab.c index 45c5e79abd..53800dd40e 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -344,7 +344,7 @@ void sqlite3VtabBeginParse( */ if( pTable->azModuleArg ){ sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName, - pTable->azModuleArg[0], pParse->db->aDb[iDb].zName); + pTable->azModuleArg[0], pParse->db->aDb[iDb].zDbSName); } #endif } @@ -408,7 +408,7 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ "UPDATE %Q.%s " "SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q " "WHERE rowid=#%d", - db->aDb[iDb].zName, SCHEMA_TABLE(iDb), + db->aDb[iDb].zDbSName, SCHEMA_TABLE(iDb), pTab->zName, pTab->zName, zStmt, @@ -518,7 +518,7 @@ static int vtabCallConstructor( pVTable->pMod = pMod; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); - pTab->azModuleArg[1] = db->aDb[iDb].zName; + pTab->azModuleArg[1] = db->aDb[iDb].zDbSName; /* Invoke the virtual table constructor */ assert( &db->pVtabCtx ); @@ -682,7 +682,7 @@ int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){ Module *pMod; const char *zMod; - pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName); + pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName); assert( pTab && (pTab->tabFlags & TF_Virtual)!=0 && !pTab->pVTable ); /* Locate the required virtual table module */ @@ -806,7 +806,7 @@ int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab){ int rc = SQLITE_OK; Table *pTab; - pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName); + pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName); if( pTab!=0 && ALWAYS(pTab->pVTable!=0) ){ VTable *p; int (*xDestroy)(sqlite3_vtab *); diff --git a/tool/lemon.c b/tool/lemon.c index df758a5da6..0fa3d63b4e 100644 --- a/tool/lemon.c +++ b/tool/lemon.c @@ -263,7 +263,8 @@ struct symbol { int useCnt; /* Number of times used */ char *destructor; /* Code which executes whenever this symbol is ** popped from the stack during error processing */ - int destLineno; /* Line number for start of destructor */ + int destLineno; /* Line number for start of destructor. Set to + ** -1 for duplicate destructors. */ char *datatype; /* The data type of information held by this ** object. Only used if type==NONTERMINAL */ int dtnum; /* The data type number. In the parser, the value @@ -4385,6 +4386,7 @@ void ReportTable( for(i=0; insymbol; i++){ struct symbol *sp = lemp->symbols[i]; if( sp==0 || sp->type==TERMINAL || sp->destructor==0 ) continue; + if( sp->destLineno<0 ) continue; /* Already emitted */ fprintf(out," case %d: /* %s */\n", sp->index, sp->name); lineno++; /* Combine duplicate destructors into a single case */ @@ -4395,7 +4397,7 @@ void ReportTable( && strcmp(sp->destructor,sp2->destructor)==0 ){ fprintf(out," case %d: /* %s */\n", sp2->index, sp2->name); lineno++; - sp2->destructor = 0; + sp2->destLineno = -1; /* Avoid emitting this destructor again */ } }