-C Import\sthe\ssqlite3_analyzer\sfixes\sfrom\strunk.
-D 2013-11-02T11:43:05.572
+C Store\sthe\sroot\spage\sof\sthe\sPRIMARY\sKEY\sindex\sfor\sa\sWITHOUT\sROWID\stable\sin\nthe\ssqlite_master\sentry\sfor\sthe\smain\stable\sand\somit\sthe\ssqlite_master\sentry\nfor\sthe\sPRIMARY\sKEY.
+D 2013-11-02T14:37:18.563
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 0522b53cdc1fcfc18f3a98e0246add129136c654
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F src/btree.c 509722ce305471b626d3401c0631a808fd33237b
F src/btree.h bfe0e8c5759b4ec77b0d18390064a6ef3cdffaaf
F src/btreeInt.h f038e818bfadf75afbd09819ed93c26a333d39e0
-F src/build.c bc63356abffdde0271f8d7667bad32e0566debe1
+F src/build.c 38d6d7396213a5320ce6e822145b671e3e2653eb
F src/callback.c f99a8957ba2adf369645fac0db09ad8adcf1caa2
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
F src/pcache1.c a467393909a4ed7ca9de066d85ba5c5b04a5be63
F src/pragma.c ff1a98998d2038bc9c770326986b7c4728de4973
-F src/prepare.c ea231a8450eef356490b09481db9fe51a6a59c32
+F src/prepare.c fa6988589f39af8504a61731614cd4f6ae71554f
F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b
F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68
F src/resolve.c e729889b2c7a680ba4aa7296efa72c09369956d8
F src/sqlite.h.in 547a44dd4ff4d975e92a645ea2d609e543a83d0f
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
-F src/sqliteInt.h bc4588b0d2eac8429d102609af6cfad583bfb41f
+F src/sqliteInt.h 7cc1b32804563f26cf44a4a48ad370490c8f737c
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
F src/test_vfs.c e72f555ef7a59080f898fcf1a233deb9eb704ea9
F src/test_vfstrace.c 34b544e80ba7fb77be15395a609c669df2e660a2
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
-F src/tokenize.c 70061085a51f2f4fc15ece94f32c03bcb78e63b2
+F src/tokenize.c ec4c1a62b890bf1dbcdb966399e140b904c700a4
F src/trigger.c 53d6b5d50b3b23d4fcd0a36504feb5cff9aed716
F src/update.c 94d63d3e06b09df3618655a841dc95d5b9466dc6
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
F test/conflict.test 0b3922d2304a14a47e3ccd61bbd6824327af659b
F test/contrib01.test 2a1cbc0f2f48955d7d073f725765da6fbceda6b4
F test/corrupt.test 4aabd06cff3fe759e3e658bcc17b71789710665e
-F test/corrupt2.test b8174976fab5bc000e58539ceb3bb9f31b4813f8
+F test/corrupt2.test 9c0ab4becd50e9050bc1ebb8675456a4e5587bf0
F test/corrupt3.test 889d7cdb811800303aa722d7813fe8a4299cf726
F test/corrupt4.test b963f9e01e0f92d15c76fb0747876fd4b96dc30a
F test/corrupt5.test c23da7bfb20917cc7fdbb13ee25c7cc4e9fffeff
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
-P 302a81390f039fc23eeb8510e95b9d9fa0b41edd 42a11e7464ab1d97d603c7409f10710ad4f1f542
-R 3792eebb99bae3c39c82ab2be948da7e
+P ac711459ff243e787ea5e9c01720dff75a5eda9b
+R ae34f785e9853a53b0aaa3951983c6d8
U drh
-Z 67feff5a16da3f8a7e3efdb5ed709f00
+Z 71ade7b873cbec3da5d0aa4bb763c9f6
-ac711459ff243e787ea5e9c01720dff75a5eda9b
\ No newline at end of file
+b7544bb280f1c1c55135a9b35aeb85604fef94a3
\ No newline at end of file
"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->autoIndex = 2;
+ if( v ) sqlite3VdbeJumpHere(v, pParse->addrSkipPK);
}
pList = 0;
}
}
/*
-** The table pTab has a WITHOUT ROWID clause at the end. Go through and
-** make all the changes necessary to make this a WITHOUT ROWID table.
+** This routine runs at the end of parsing a CREATE TABLE statement that
+** has a WITHOUT ROWID clause. The job of this routine is to convert both
+** internal schema data structures and the generated VDBE code so that they
+** are appropriate for a WITHOUT ROWID table instead of a rowid table.
+** Changes include:
**
-** (1) Convert the OP_CreateTable into an no-op.
-** (2) Make sure all table columns are part of the PRIMARY KEY
-** (3) Make sure all PRIMARY KEY columns are part of all UNIQUE
-** indices
+** (1) Convert the OP_CreateTable into an OP_CreateIndex. There is
+** no rowid btree for a WITHOUT ROWID. Instead, the canonical
+** data storage is a covering index btree.
+** (2) Bypass the creation of the sqlite_master table entry
+** for the PRIMARY KEY as the the primary key index is now
+** identified by the sqlite_master table entry of the table itself.
+** (3) Set the Index.tnum of the PRIMARY KEY Index object in the
+** schema to the rootpage from the main table.
+** (4) Set all columns of the PRIMARY KEY schema object to be NOT NULL.
+** (5) Add all table columns to the PRIMARY KEY Index object
+** so that the PRIMARY KEY is a covering index. The surplus
+** columns are part of KeyInfo.nXField and are not used for
+** sorting or lookup or uniqueness checks.
+** (6) Replace the rowid tail on all automatically generated UNIQUE
+** indices with the PRIMARY KEY columns.
*/
static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
Index *pIdx;
int nPk;
int i, j;
sqlite3 *db = pParse->db;
+ Vdbe *v = pParse->pVdbe;
/* Convert the OP_CreateTable opcode that would normally create the
- ** root-page for the table into a OP_Null opcode. This prevents the
- ** allocation of the root-page (which would never been used, as all
- ** content is stored in the primary-key index instead) and it causes
- ** a NULL value in the sqlite_master.rootpage field of the schema.
+ ** root-page for the table into a OP_CreateIndex opcode. The index
+ ** created will become the PRIMARY KEY index.
*/
if( pParse->addrCrTab ){
- sqlite3VdbeGetOp(pParse->pVdbe, pParse->addrCrTab)->opcode = OP_Null;
+ assert( v );
+ 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
}
pPk->uniqNotNull = 1;
+ /* The root page of the PRIMARY KEY is the table root page */
+ pPk->tnum = pTab->tnum;
+
/* Update the in-memory representation of all UNIQUE indices by converting
** the final rowid column into one or more columns of the PRIMARY KEY.
*/
assert( !db->init.busy || !pSelect );
+ /* If the db->init.busy is 1 it means we are reading the SQL off the
+ ** "sqlite_master" or "sqlite_temp_master" table on the disk.
+ ** So do not write to the disk again. Extract the root page number
+ ** for the table from the db->init.newTnum field. (The page number
+ ** should have been put there by the sqliteOpenCb routine.)
+ */
+ if( db->init.busy ){
+ p->tnum = db->init.newTnum;
+ }
+
+ /* Special processing for WITHOUT ROWID Tables */
if( tabOpts & TF_WithoutRowid ){
if( (p->tabFlags & TF_HasPrimaryKey)==0 ){
sqlite3ErrorMsg(pParse, "no PRIMARY KEY for table %s", p->zName);
estimateIndexWidth(pIdx);
}
- /* If the db->init.busy is 1 it means we are reading the SQL off the
- ** "sqlite_master" or "sqlite_temp_master" table on the disk.
- ** So do not write to the disk again. Extract the root page number
- ** for the table from the db->init.newTnum field. (The page number
- ** should have been put there by the sqliteOpenCb routine.)
- */
- if( db->init.busy ){
- p->tnum = db->init.newTnum;
- }
-
/* If not initializing, then create a record for the new table
** in the SQLITE_MASTER table of the database.
**
assert( iDb>=0 && iDb<db->nDb );
if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
- if( argv[2] && argv[2][0] ){
+ if( argv[1]==0 ){
+ corruptSchema(pData, argv[0], 0);
+ }else if( argv[2] && argv[2][0] ){
/* Call the parser to process a CREATE TABLE, INDEX or VIEW.
** But because db->init.busy is set to 1, no VDBE code is generated
** or executed. All the parser does is build the internal data
assert( db->init.busy );
db->init.iDb = iDb;
- db->init.newTnum = argv[1] ? sqlite3Atoi(argv[1]) : 0;
+ db->init.newTnum = sqlite3Atoi(argv[1]);
db->init.orphanTrigger = 0;
TESTONLY(rcp = ) sqlite3_prepare(db, argv[2], -1, &pStmt, 0);
rc = db->errCode;
/* Do Nothing */;
}else if( sqlite3GetInt32(argv[1], &pIndex->tnum)==0 ){
corruptSchema(pData, argv[0], "invalid rootpage");
- }else if( pIndex->autoIndex==2
- && (pIndex->pTable->tabFlags & TF_WithoutRowid)!=0
- ){
- pIndex->pTable->tnum = pIndex->tnum;
}
}
return 0;
/* Information used while coding trigger programs. */
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 */
int nVar; /* Number of '?' variables seen in the SQL so far */
int nzVar; /* Number of available slots in azVar[] */
- int addrCrTab; /* Address of OP_CreateTable opcode */
u8 iPkSortOrder; /* ASC or DESC for INTEGER PRIMARY KEY */
u8 explain; /* True if the EXPLAIN flag is found on the query */
#ifndef SQLITE_OMIT_VIRTUALTABLE
#endif
char **azVar; /* Pointers to names of parameters */
Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */
- int *aAlias; /* Register used to hold aliased result */
const char *zTail; /* All SQL text past the last semicolon parsed */
Table *pNewTable; /* A table being constructed by CREATE TABLE */
Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
for(i=pParse->nzVar-1; i>=0; i--) sqlite3DbFree(db, pParse->azVar[i]);
sqlite3DbFree(db, pParse->azVar);
- sqlite3DbFree(db, pParse->aAlias);
while( pParse->pAinc ){
AutoincInfo *p = pParse->pAinc;
pParse->pAinc = p->pNext;
} {1 {database disk image is malformed}}
}
-# Since the introduction of WITHOUT ROWID tables, having a table entry in
-# the sqlite_master table with a NULL rootpage is no longer a sign of
-# corruption.
-#
-if 0 {
corruption_test -sqlprep {
CREATE TABLE t1(a, b, c);
CREATE TABLE t2(a, b, c);
sqlite3_errcode db
} {SQLITE_CORRUPT}
}
-} ;# Disabled rootpage==NULL corruption test
corruption_test -sqlprep {
PRAGMA auto_vacuum = incremental;