Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix spurious "no such table: x1" errors in shared-schema mode that could occur when a query that is a join across two or more databases needs to call the xConnect() methods of a virtual table. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | reuse-schema |
Files: | files | file ages | folders |
SHA3-256: |
edf45cd7c6c1122db961ae66c21c7e97 |
User & Date: | dan 2019-08-08 15:47:32.871 |
Context
2019-08-09
| ||
14:54 | In shared-schema mode, handle the case where a connection has created a virtual-table object, but is later assigned a different shared-schema object for which the virtual-table schema has not yet been initialized. (check-in: e30c7414fe user: dan tags: reuse-schema) | |
2019-08-08
| ||
15:47 | Fix spurious "no such table: x1" errors in shared-schema mode that could occur when a query that is a join across two or more databases needs to call the xConnect() methods of a virtual table. (check-in: edf45cd7c6 user: dan tags: reuse-schema) | |
11:44 | Fix a bug causing "no such table" and other similar sqlite3_prepare*() errors to return SQLITE_SCHEMA instead of SQLITE_ERROR in shared-schema mode when there is an attached database for which the schema has never been loaded. (check-in: 111e2c73cf user: dan tags: reuse-schema) | |
Changes
Changes to src/sqliteInt.h.
︙ | ︙ | |||
3135 3136 3137 3138 3139 3140 3141 | #ifndef SQLITE_OMIT_SHARED_CACHE int nTableLock; /* Number of locks in aTableLock */ TableLock *aTableLock; /* Required table locks for shared-cache mode */ #endif AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */ Parse *pToplevel; /* Parse structure for main program (or NULL) */ Table *pTriggerTab; /* Table triggers are being coded for */ | < | 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 | #ifndef SQLITE_OMIT_SHARED_CACHE int nTableLock; /* Number of locks in aTableLock */ TableLock *aTableLock; /* Required table locks for shared-cache mode */ #endif AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */ Parse *pToplevel; /* Parse structure for main program (or NULL) */ Table *pTriggerTab; /* Table triggers are being coded for */ int addrCrTab; /* Address of OP_CreateBtree opcode on CREATE TABLE */ u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */ u32 oldmask; /* Mask of old.* columns referenced */ u32 newmask; /* Mask of new.* columns referenced */ u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */ u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */ u8 disableTriggers; /* True to disable triggers */ |
︙ | ︙ |
Changes to src/tokenize.c.
︙ | ︙ | |||
556 557 558 559 560 561 562 563 564 565 566 567 568 569 | int nErr = 0; /* Number of errors encountered */ void *pEngine; /* The LEMON-generated LALR(1) parser */ int n = 0; /* Length of the next token token */ int tokenType; /* type of the next token */ int lastTokenParsed = -1; /* type of the previous token */ sqlite3 *db = pParse->db; /* The database connection */ int mxSqlLen; /* Max length of an SQL string */ #ifdef sqlite3Parser_ENGINEALWAYSONSTACK yyParser sEngine; /* Space to hold the Lemon-generated Parser object */ #endif VVA_ONLY( u8 startedWithOom = db->mallocFailed ); assert( zSql!=0 ); mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; | > | 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 | int nErr = 0; /* Number of errors encountered */ void *pEngine; /* The LEMON-generated LALR(1) parser */ int n = 0; /* Length of the next token token */ int tokenType; /* type of the next token */ int lastTokenParsed = -1; /* type of the previous token */ sqlite3 *db = pParse->db; /* The database connection */ int mxSqlLen; /* Max length of an SQL string */ Parse *pParentParse = db->pParse; #ifdef sqlite3Parser_ENGINEALWAYSONSTACK yyParser sEngine; /* Space to hold the Lemon-generated Parser object */ #endif VVA_ONLY( u8 startedWithOom = db->mallocFailed ); assert( zSql!=0 ); mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; |
︙ | ︙ | |||
591 592 593 594 595 596 597 | return SQLITE_NOMEM_BKPT; } #endif assert( pParse->pNewTable==0 ); assert( pParse->pNewTrigger==0 ); assert( pParse->nVar==0 ); assert( pParse->pVList==0 ); | < | 592 593 594 595 596 597 598 599 600 601 602 603 604 605 | return SQLITE_NOMEM_BKPT; } #endif assert( pParse->pNewTable==0 ); assert( pParse->pNewTrigger==0 ); assert( pParse->nVar==0 ); assert( pParse->pVList==0 ); db->pParse = pParse; while( 1 ){ n = sqlite3GetToken((u8*)zSql, &tokenType); mxSqlLen -= n; if( mxSqlLen<0 ){ pParse->rc = SQLITE_TOOBIG; break; |
︙ | ︙ | |||
718 719 720 721 722 723 724 | sqlite3DbFreeNN(db, p); } while( pParse->pZombieTab ){ Table *p = pParse->pZombieTab; pParse->pZombieTab = p->pNextZombie; sqlite3DeleteTable(db, p); } | | < | 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 | sqlite3DbFreeNN(db, p); } while( pParse->pZombieTab ){ Table *p = pParse->pZombieTab; pParse->pZombieTab = p->pNextZombie; sqlite3DeleteTable(db, p); } db->pParse = pParentParse; assert( nErr==0 || pParse->rc!=SQLITE_OK ); return nErr; } #ifdef SQLITE_ENABLE_NORMALIZE /* |
︙ | ︙ |
Changes to src/vdbeblob.c.
︙ | ︙ | |||
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | ){ int nAttempt = 0; int iCol; /* Index of zColumn in row-record */ int rc = SQLITE_OK; char *zErr = 0; Table *pTab; Incrblob *pBlob = 0; Parse sParse; int bUnlock; /* True to unlock reusable schemas before returning */ #ifdef SQLITE_ENABLE_API_ARMOR if( ppBlob==0 ){ return SQLITE_MISUSE_BKPT; } #endif *ppBlob = 0; #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) || zTable==0 ){ return SQLITE_MISUSE_BKPT; } #endif wrFlag = !!wrFlag; /* wrFlag = (wrFlag ? 1 : 0); */ sqlite3_mutex_enter(db->mutex); | > < | 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 | ){ int nAttempt = 0; int iCol; /* Index of zColumn in row-record */ int rc = SQLITE_OK; char *zErr = 0; Table *pTab; Incrblob *pBlob = 0; Parse *pParentParse = db->pParse; Parse sParse; int bUnlock; /* True to unlock reusable schemas before returning */ #ifdef SQLITE_ENABLE_API_ARMOR if( ppBlob==0 ){ return SQLITE_MISUSE_BKPT; } #endif *ppBlob = 0; #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) || zTable==0 ){ return SQLITE_MISUSE_BKPT; } #endif wrFlag = !!wrFlag; /* wrFlag = (wrFlag ? 1 : 0); */ sqlite3_mutex_enter(db->mutex); bUnlock = sqlite3LockReusableSchema(db); pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob)); do { memset(&sParse, 0, sizeof(Parse)); if( !pBlob ) goto blob_open_out; sParse.db = db; |
︙ | ︙ | |||
331 332 333 334 335 336 337 | if( db->mallocFailed ){ goto blob_open_out; } rc = blobSeekToRow(pBlob, iRow, &zErr); } while( (++nAttempt)<SQLITE_MAX_SCHEMA_RETRY && rc==SQLITE_SCHEMA ); blob_open_out: | | | 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 | if( db->mallocFailed ){ goto blob_open_out; } rc = blobSeekToRow(pBlob, iRow, &zErr); } while( (++nAttempt)<SQLITE_MAX_SCHEMA_RETRY && rc==SQLITE_SCHEMA ); blob_open_out: db->pParse = pParentParse; sqlite3UnlockReusableSchema(db, bUnlock); if( rc==SQLITE_OK && db->mallocFailed==0 ){ *ppBlob = (sqlite3_blob *)pBlob; }else{ if( pBlob && pBlob->pStmt ) sqlite3VdbeFinalize((Vdbe *)pBlob->pStmt); sqlite3DbFree(db, pBlob); } |
︙ | ︙ |
Added test/reuse6.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 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 | # 2019 February 26 # # 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. # #*********************************************************************** # # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix reuse6 ifcapable !sharedschema { finish_test return } do_execsql_test 1.0 { CREATE TABLE t1(x, y); CREATE TABLE t2(a, b, c); CREATE INDEX t1x ON t1(x); CREATE INDEX t1y ON t1(y); CREATE VIEW v1 AS SELECT * FROM t2; INSERT INTO t1 VALUES(1, 2), (3, 4), (5, 6); INSERT INTO t2 VALUES('a', 'b', 'c'), ('d', 'e', 'f'), ('g', 'h', 'i'); ATTACH 'test.db2' AS aux; CREATE TABLE t3(i, ii); INSERT INTO t3 VALUES(10, 20); } sqlite3 db1 test.db -shared-schema 1 sqlite3 db2 test.db -shared-schema 1 do_execsql_test -db db1 1.1 { ATTACH 'test.db2' AS aux; } do_test 1.2 { execsql {SELECT * FROM t3} db1 } {10 20} do_execsql_test -db db2 1.3 { ATTACH 'test.db2' AS aux; } do_test 1.3 { execsql {SELECT * FROM t3} db1 } {10 20} do_execsql_test -db db2 1.5 { SELECT * FROM t3; } {10 20} do_test 1.6 { execsql {SELECT * FROM t3} db1 } {10 20} db1 close db2 close #------------------------------------------------------------------------- reset_db forcedelete test.db2 forcedelete test.db3 do_execsql_test 2.0 { CREATE TABLE t1(x, y); ATTACH 'test.db2' AS aux2; CREATE TABLE aux2.t2(x, y); ATTACH 'test.db3' AS aux3; CREATE TABLE aux3.t3(x, y); } sqlite3 db1 test.db -shared-schema 1 do_execsql_test -db db1 2.1 { ATTACH 'test.db2' AS aux2; ATTACH 'test.db3' AS aux3; } do_test 2.2.1 { catchsql { SELECT * FROM aux2.nosuchtable } db1 } {1 {no such table: aux2.nosuchtable}} do_test 2.2.2 { sqlite3_errcode db1 } {SQLITE_ERROR} db1 close #------------------------------------------------------------------------- reset_db forcedelete test.db2 ifcapable fts5 { do_execsql_test 3.0 { CREATE VIRTUAL TABLE ft USING fts5(a, b); ATTACH 'test.db2' AS aux; CREATE TABLE aux.t1(x, y, z); } sqlite3 db1 test.db -shared-schema 1 do_execsql_test -db db1 3.1 { ATTACH 'test.db2' AS aux; } breakpoint do_execsql_test -db db1 3.2 { SELECT * FROM main.ft, aux.t1; } } finish_test |