/ Check-in [0140f6db]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix a problem causing the sqlite_master entry corresponding to a virtual table to be removed by a DROP TABLE even if the call to the vtabs xDestroy() method failed.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 0140f6dbfbea93eadcd7f727d84064a0c0d1f0806dbe3e5ef1017da603157e3b
User & Date: dan 2018-12-28 17:45:08
Context
2018-12-28
18:09
Fix another problem with loading the structure record from a corrupt fts5 database. check-in: c4d44542 user: dan tags: trunk
17:45
Fix a problem causing the sqlite_master entry corresponding to a virtual table to be removed by a DROP TABLE even if the call to the vtabs xDestroy() method failed. check-in: 0140f6db user: dan tags: trunk
14:33
Avoid an undefined left-shift operation in fts5 caused by malformed utf-8 text. check-in: c3a3a111 user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/build.c.

  2634   2634     }
  2635   2635   
  2636   2636     /* Remove the table entry from SQLite's internal schema and modify
  2637   2637     ** the schema cookie.
  2638   2638     */
  2639   2639     if( IsVirtual(pTab) ){
  2640   2640       sqlite3VdbeAddOp4(v, OP_VDestroy, iDb, 0, 0, pTab->zName, 0);
         2641  +    sqlite3MayAbort(pParse);
  2641   2642     }
  2642   2643     sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0);
  2643   2644     sqlite3ChangeCookie(pParse, iDb);
  2644   2645     sqliteViewResetAll(db, iDb);
  2645   2646   }
  2646   2647   
  2647   2648   /*

Changes to src/vdbe.c.

  6845   6845   ** P4 is the name of a virtual table in database P1.  Call the xDestroy method
  6846   6846   ** of that table.
  6847   6847   */
  6848   6848   case OP_VDestroy: {
  6849   6849     db->nVDestroy++;
  6850   6850     rc = sqlite3VtabCallDestroy(db, pOp->p1, pOp->p4.z);
  6851   6851     db->nVDestroy--;
         6852  +  assert( p->errorAction==OE_Abort && p->usesStmtJournal );
  6852   6853     if( rc ) goto abort_due_to_error;
  6853   6854     break;
  6854   6855   }
  6855   6856   #endif /* SQLITE_OMIT_VIRTUALTABLE */
  6856   6857   
  6857   6858   #ifndef SQLITE_OMIT_VIRTUALTABLE
  6858   6859   /* Opcode: VOpen P1 * * P4 *

Changes to src/vdbeaux.c.

   599    599     VdbeOpIter sIter;
   600    600     memset(&sIter, 0, sizeof(sIter));
   601    601     sIter.v = v;
   602    602   
   603    603     while( (pOp = opIterNext(&sIter))!=0 ){
   604    604       int opcode = pOp->opcode;
   605    605       if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename 
          606  +     || opcode==OP_VDestroy
   606    607        || ((opcode==OP_Halt || opcode==OP_HaltIfNull) 
   607    608         && ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort))
   608    609       ){
   609    610         hasAbort = 1;
   610    611         break;
   611    612       }
   612    613       if( opcode==OP_CreateBtree && pOp->p3==BTREE_INTKEY ) hasCreateTable = 1;

Added test/vtabdrop.test.

            1  +# 2018 December 28
            2  +#
            3  +#    May you do good and not evil.
            4  +#    May you find forgiveness for yourself and forgive others.
            5  +#    May you share freely, never taking more than you give.
            6  +#
            7  +#***********************************************************************
            8  +#
            9  +# The tests in this file test edge cases surrounding DROP TABLE on 
           10  +# virtual tables.
           11  +#
           12  +
           13  +set testdir [file dirname $argv0]
           14  +source $testdir/tester.tcl
           15  +
           16  +ifcapable !vtab { finish_test ; return }
           17  +source $testdir/fts3_common.tcl
           18  +source $testdir/malloc_common.tcl
           19  +
           20  +set testprefix vtabdrop
           21  +
           22  +#-------------------------------------------------------------------------
           23  +# Test that if a DROP TABLE is executed against an rtree table, but the
           24  +# xDestroy() call fails, the rtree table is not dropped, the sqlite_master
           25  +# table is not modified and the internal schema remains intact.
           26  +# 
           27  +ifcapable rtree {
           28  +  do_execsql_test 1.0 {
           29  +    CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2);
           30  +    CREATE TABLE t1(x, y);
           31  +    INSERT INTO t1 VALUES(1, 2);
           32  +  }
           33  +  
           34  +  do_test 1.1 {
           35  +    execsql {
           36  +      BEGIN;
           37  +        INSERT INTO t1 VALUES(3, 4);
           38  +    }
           39  +    db eval { SELECT * FROM t1 } {
           40  +      catchsql { DROP TABLE rt }
           41  +    }
           42  +    execsql COMMIT
           43  +  } {}
           44  +  
           45  +  do_execsql_test 1.2 {
           46  +    SELECT name FROM sqlite_master ORDER BY 1;
           47  +    SELECT * FROM t1;
           48  +    SELECT * FROM rt;
           49  +  } {rt rt_node rt_parent rt_rowid t1 1 2 3 4}
           50  +  
           51  +  db close
           52  +  sqlite3 db test.db
           53  +  
           54  +  do_execsql_test 1.3 {
           55  +    SELECT name FROM sqlite_master ORDER BY 1;
           56  +  } {rt rt_node rt_parent rt_rowid t1}
           57  +}
           58  +
           59  +#-------------------------------------------------------------------------
           60  +# Same as tests 1.*, except with fts5 instead of rtree.
           61  +# 
           62  +ifcapable fts5 {
           63  +  reset_db
           64  +  do_execsql_test 2.0 {
           65  +    CREATE VIRTUAL TABLE ft USING fts5(x);
           66  +    CREATE TABLE t1(x, y);
           67  +    INSERT INTO t1 VALUES(1, 2);
           68  +  }
           69  +  
           70  +  do_test 2.1 {
           71  +    execsql {
           72  +      BEGIN;
           73  +        INSERT INTO t1 VALUES(3, 4);
           74  +    }
           75  +    db eval { SELECT * FROM t1 } {
           76  +      catchsql { DROP TABLE ft }
           77  +    }
           78  +    execsql COMMIT
           79  +  } {}
           80  +  
           81  +  do_execsql_test 2.2 {
           82  +    SELECT name FROM sqlite_master ORDER BY 1;
           83  +  } {ft ft_config ft_content ft_data ft_docsize ft_idx t1}
           84  +  
           85  +  db close
           86  +  sqlite3 db test.db
           87  +  
           88  +  do_execsql_test 2.3 {
           89  +    SELECT name FROM sqlite_master ORDER BY 1;
           90  +  } {ft ft_config ft_content ft_data ft_docsize ft_idx t1}
           91  +}
           92  +
           93  +#-------------------------------------------------------------------------
           94  +# Same as tests 1.*, except with fts3 instead of rtree.
           95  +# 
           96  +ifcapable fts3 {
           97  +  reset_db
           98  +  do_execsql_test 2.0 {
           99  +    CREATE VIRTUAL TABLE ft USING fts3(x);
          100  +    CREATE TABLE t1(x, y);
          101  +    INSERT INTO t1 VALUES(1, 2);
          102  +  }
          103  +  
          104  +  do_test 2.1 {
          105  +    execsql {
          106  +      BEGIN;
          107  +        INSERT INTO t1 VALUES(3, 4);
          108  +    }
          109  +    db eval { SELECT * FROM t1 } {
          110  +      catchsql { DROP TABLE ft }
          111  +    }
          112  +    execsql COMMIT
          113  +  } {}
          114  +  
          115  +  do_execsql_test 2.2 {
          116  +    SELECT name FROM sqlite_master ORDER BY 1;
          117  +  } {ft ft_content ft_segdir ft_segments sqlite_autoindex_ft_segdir_1 t1}
          118  +  
          119  +  db close
          120  +  sqlite3 db test.db
          121  +  
          122  +  do_execsql_test 2.3 {
          123  +    SELECT name FROM sqlite_master ORDER BY 1;
          124  +  } {ft ft_content ft_segdir ft_segments sqlite_autoindex_ft_segdir_1 t1}
          125  +}
          126  +
          127  +finish_test