]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix a problem with ignoring UNIQUE constraints on WITHOUT ROWID tables rendered redun...
authordan <dan@noemail.net>
Tue, 26 May 2015 11:53:14 +0000 (11:53 +0000)
committerdan <dan@noemail.net>
Tue, 26 May 2015 11:53:14 +0000 (11:53 +0000)
FossilOrigin-Name: 3b936913f3dc2cae4c94f983f28d85b136a44c9f

manifest
manifest.uuid
src/build.c
src/sqliteInt.h
test/without_rowid1.test

index 478a7ce19445ac73611f169d0cbd5e7b1597cd02..86465add844c6185e5e30c95773583a83d058e98 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Silence\sharmless\scompiler\swarnings\swhen\sbuilding\sthe\scommand\sline\sutilities\swith\sMSVC.
-D 2015-05-26T03:31:46.981
+C Fix\sa\sproblem\swith\signoring\sUNIQUE\sconstraints\son\sWITHOUT\sROWID\stables\srendered\sredundant\sby\sthe\sPRIMARY\sKEY.
+D 2015-05-26T11:53:14.886
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 69b596e4be75a16f4e55587f29db66497b207fad
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -195,7 +195,7 @@ F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
 F src/btree.c a7d627f89e8382cea8645cc2eec6927b203fdb31
 F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1
 F src/btreeInt.h 973a22a6fd61350b454ad614832b1f0a5e25a1e4
-F src/build.c d5d9090788118178190c5724c19f93953b8c7a4e
+F src/build.c 9552e7490b0310a8c73fcf3a0c36e7624789d8df
 F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
 F src/complete.c a5cf5b4b56390cfb7b8636e8f7ddef90258dd575
 F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b
@@ -255,7 +255,7 @@ F src/shell.c 07dda7cd692911d2f22269953418d049f2e2c0ee
 F src/sqlite.h.in 4d0ecd8e1e0272d9a2742b39602f5e4fad8d3246
 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
 F src/sqlite3ext.h 2ebeb634e751a61a6f0eebfa0f4669f46a42f6cd
-F src/sqliteInt.h 88738d94a343000e7a5c0e295d111c4cfccb18b0
+F src/sqliteInt.h 26484793b2f8017960b30ae2d0cbc7512eff5b17
 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
 F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
 F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
@@ -1215,7 +1215,7 @@ F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
 F test/with1.test a86bf7f9288ba759a25ee57221d3bffaca36032a
 F test/with2.test ee227a663586aa09771cafd4fa269c5217eaf775
 F test/withM.test e97f2a8c506ab3ea9eab94e6f6072f6cc924c991
-F test/without_rowid1.test 7862e605753c8d25329f665fa09072e842183151
+F test/without_rowid1.test 4cda656cb4a452296e0d8d8623513f4be80c6d86
 F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
 F test/without_rowid3.test 1081aabf60a1e1123b7f9a8f6ae19954351843b0
 F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
@@ -1279,7 +1279,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P eda2a437506f148bcb5bb33baa64b5ad8ae73ada
-R 729e132ed27defff17edf873b9ea2761
-U mistachkin
-Z 455a04fccd298870eb1e19dc1cb5545d
+P d26060c468cc6997e9933d9623a47fcc7d86c2da
+R 5fc589e99d7c4f392d71685f4b89ca0e
+U dan
+Z 34e0e604424e8529b6d35704e87be1e0
index 4edb6323373b3a107796bb7b662dc95101c530c3..49abbeb288575bcbd2269500590fbcf7290b6cad 100644 (file)
@@ -1 +1 @@
-d26060c468cc6997e9933d9623a47fcc7d86c2da
\ No newline at end of file
+3b936913f3dc2cae4c94f983f28d85b136a44c9f
\ No newline at end of file
index 44d75e95571aac9f306a659c64fb285c85c01477..1cf427b03332ab271980c027b99478f48852ecdd 100644 (file)
@@ -1325,14 +1325,11 @@ void sqlite3AddPrimaryKey(
        "INTEGER PRIMARY KEY");
 #endif
   }else{
-    Vdbe *v = pParse->pVdbe;
     Index *p;
-    if( v ) pParse->addrSkipPK = sqlite3VdbeAddOp0(v, OP_Noop);
     p = sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0,
                            0, sortOrder, 0);
     if( p ){
       p->idxType = SQLITE_IDXTYPE_PRIMARYKEY;
-      if( v ) sqlite3VdbeJumpHere(v, pParse->addrSkipPK);
     }
     pList = 0;
   }
@@ -1685,14 +1682,6 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
     sqlite3VdbeGetOp(v, pParse->addrCrTab)->opcode = OP_CreateIndex;
   }
 
-  /* Bypass the creation of the PRIMARY KEY btree and the sqlite_master
-  ** table entry.
-  */
-  if( pParse->addrSkipPK ){
-    assert( v );
-    sqlite3VdbeGetOp(v, pParse->addrSkipPK)->opcode = OP_Goto;
-  }
-
   /* Locate the PRIMARY KEY index.  Or, if this table was originally
   ** an INTEGER PRIMARY KEY table, create a new PRIMARY KEY index. 
   */
@@ -1710,6 +1699,16 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
     pTab->iPKey = -1;
   }else{
     pPk = sqlite3PrimaryKeyIndex(pTab);
+
+    /* Bypass the creation of the PRIMARY KEY btree and the sqlite_master
+    ** table entry. This is only required if currently generating VDBE
+    ** code for a CREATE TABLE (not when parsing one as part of reading
+    ** a database schema).  */
+    if( v ){
+      assert( db->init.busy==0 );
+      sqlite3VdbeGetOp(v, pPk->tnum)->opcode = OP_Goto;
+    }
+
     /*
     ** Remove all redundant columns from the PRIMARY KEY.  For example, change
     ** "PRIMARY KEY(a,b,a,b,c,b,c,d)" into just "PRIMARY KEY(a,b,c,d)".  Later
@@ -3250,10 +3249,15 @@ Index *sqlite3CreateIndex(
     v = sqlite3GetVdbe(pParse);
     if( v==0 ) goto exit_create_index;
 
-
-    /* Create the rootpage for the index
-    */
     sqlite3BeginWriteOperation(pParse, 1, iDb);
+
+    /* Create the rootpage for the index using CreateIndex. But before
+    ** doing so, code a Noop instruction and store its address in 
+    ** Index.tnum. This is required in case this index is actually a 
+    ** PRIMARY KEY and the table is actually a WITHOUT ROWID table. In 
+    ** that case the convertToWithoutRowidTable() routine will replace
+    ** the Noop with a Goto to jump over the VDBE code generated below. */
+    pIndex->tnum = sqlite3VdbeAddOp0(v, OP_Noop);
     sqlite3VdbeAddOp2(v, OP_CreateIndex, iDb, iMem);
 
     /* Gather the complete text of the CREATE INDEX statement into
@@ -3293,6 +3297,8 @@ Index *sqlite3CreateIndex(
          sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName));
       sqlite3VdbeAddOp1(v, OP_Expire, 0);
     }
+
+    sqlite3VdbeJumpHere(v, pIndex->tnum);
   }
 
   /* When adding an index to the list of indices for a table, make
index 586d4d07e4996d683fe3520872f9327ac07b7782..cba17d711a043eba6b89db1d22820a986726137f 100644 (file)
@@ -1811,6 +1811,14 @@ struct UnpackedRecord {
 ** and the value of Index.onError indicate the which conflict resolution 
 ** algorithm to employ whenever an attempt is made to insert a non-unique
 ** element.
+**
+** While parsing a CREATE TABLE or CREATE INDEX statement in order to
+** generate VDBE code (as opposed to parsing one read from an sqlite_master
+** table as part of parsing an existing database schema), transient instances
+** of this structure may be created. In this case the Index.tnum variable is
+** used to store the address of a VDBE instruction, not a database page
+** number (it cannot - the database page is not allocated until the VDBE
+** program is executed). See convertToWithoutRowidTable() for details.
 */
 struct Index {
   char *zName;             /* Name of this index */
@@ -2639,7 +2647,6 @@ struct Parse {
   Parse *pToplevel;    /* Parse structure for main program (or NULL) */
   Table *pTriggerTab;  /* Table triggers are being coded for */
   int addrCrTab;       /* Address of OP_CreateTable opcode on CREATE TABLE */
-  int addrSkipPK;      /* Address of instruction to skip PRIMARY KEY index */
   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 */
index 9d7a6430fe3b4b30ce6b9e798fea9913c0faac93..b746cca27792fd9c9a8b9c5c1618e2f7481904f5 100644 (file)
@@ -277,5 +277,37 @@ foreach {tn cnt where eqp} $queries {
   do_eqp_test 5.7.$tn.2  "SELECT count(*) FROM t46 WHERE $where" $eqp
 }
 
+#-------------------------------------------------------------------------
+# Check that redundant UNIQUE constraints do not cause a problem.
+#
+do_execsql_test 6.0 {
+  CREATE TABLE t47(a, b UNIQUE PRIMARY KEY) WITHOUT ROWID;
+  CREATE INDEX i47 ON t47(a);
+  INSERT INTO t47 VALUES(1, 2);
+  INSERT INTO t47 VALUES(2, 4);
+  INSERT INTO t47 VALUES(3, 6);
+  INSERT INTO t47 VALUES(4, 8);
+
+  VACUUM;
+  PRAGMA integrity_check;
+  SELECT name FROM sqlite_master WHERE tbl_name = 't47';
+} {ok t47 i47}
+
+do_execsql_test 6.1 {
+  CREATE TABLE t48(
+    a UNIQUE UNIQUE, 
+    b UNIQUE, 
+    PRIMARY KEY(a), 
+    UNIQUE(a)
+  ) WITHOUT ROWID;
+  INSERT INTO t48 VALUES('a', 'b'), ('c', 'd'), ('e', 'f');
+  VACUUM;
+  PRAGMA integrity_check;
+  SELECT name FROM sqlite_master WHERE tbl_name = 't48';
+} {
+  ok  t48   sqlite_autoindex_t48_2
+}
+
+
   
 finish_test