-C Update\sthe\sinterface\sto\sthe\ssqlite3GenerateRowDelete()\sutility\sso\sthat\sit\sis\nable\sto\shandle\sWITHOUT\sROWID\stables.\s\sThe\simplementation\sstill\sneeds\sto\sbe\s\ncompleted.
-D 2013-10-24T19:48:39.042
+C Basic\sDELETE\soperations\snow\sworking\son\sWITHOUT\sROWID\stables.
+D 2013-10-25T14:46:15.958
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 0522b53cdc1fcfc18f3a98e0246add129136c654
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 2af0330bb1b601af7a7789bf7229675fd772a083
-F src/analyze.c ee880a4c0deb1c4090a4bbff03adfbf934451f50
+F src/analyze.c b6b115d69adaf0d2fa15001748b12735832fb296
F src/attach.c 0a17c9364895316ca4f52d06a97a72c0af1ae8b3
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c 2f1987981139bd2f6d8c728d64bf09fb387443c3
F src/btree.c 509722ce305471b626d3401c0631a808fd33237b
F src/btree.h bfe0e8c5759b4ec77b0d18390064a6ef3cdffaaf
F src/btreeInt.h f038e818bfadf75afbd09819ed93c26a333d39e0
-F src/build.c f99c6980a258e32e0e0068b04dd8eed6a4af9445
+F src/build.c 4d62e99fa36db1793cc1bed63e6775defdf8c587
F src/callback.c f99a8957ba2adf369645fac0db09ad8adcf1caa2
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
-F src/delete.c 3a750695133bf8646124b07cf8a51222110885a6
+F src/delete.c 8b9aa9c935fdd48a7a8ac0eff22c03cb29f12e96
F src/expr.c 3180b6332072b263f845592e72e92971af562ab0
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 628f81177299660a86e40359b3689b81f517e125
F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
-F src/insert.c a188b1abcc80cb835a1a9b76e78190d1516d22bc
+F src/insert.c 71b3d1f551ab8e0ba59fdbaff3feef8d931a424e
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
F src/pcache1.c a467393909a4ed7ca9de066d85ba5c5b04a5be63
-F src/pragma.c d6eee7e1b6343996883e5c7e0f60bfad77be2180
+F src/pragma.c 5986f119f6350839a28936fce4e2d6a4c703922c
F src/prepare.c f47ba2bba7ac5650881ab6c41f6d33a6de1a8d52
F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b
F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68
F src/resolve.c e729889b2c7a680ba4aa7296efa72c09369956d8
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
-F src/select.c dbcd2271470b5d074252ea75e2e50f3544638b49
+F src/select.c 8290456f2a516abaf8cbbed5e61944d3082e497e
F src/shell.c 6f11f0e9ded63d48e306f2c6858c521e568a47bb
F src/sqlite.h.in 547a44dd4ff4d975e92a645ea2d609e543a83d0f
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
-F src/sqliteInt.h a0834a450cd990eadcb18b790557abfe6dc52270
+F src/sqliteInt.h 674cee6761771e7c1d6446671fcf7daf27b4c0f7
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
F src/util.c 2fa6c821d28bbdbeec1b2a7b091a281c9ef8f918
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
-F src/vdbe.c cca2c5eb4eb85ff10955c766cc75b78b4cbb5b08
+F src/vdbe.c f7a2fb5d707db64f59ebb2d054485790350f84db
F src/vdbe.h 4f554b5627f26710c4c36d919110a3fc611ca5c4
F src/vdbeInt.h ff57f67aee1ba26a3a47e786533dab155ab6dad6
F src/vdbeapi.c 93a22a9ba2abe292d5c2cf304d7eb2e894dde0ed
F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c e9e593d5bb798c3e67fc3893dfe7055c9e7d8d74
-F src/where.c 04217a957c1423dd5f177b21b4ced319bf24b77c
+F src/where.c 512ddbf2884f5560a0ad5b076efc142ad7a07c7b
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
-P 0e56ba69f0fcd12a5166c32f6e4eacdcc29fba04
-R 23965d1fb428e8ef205e9927049056c2
+P 85daf5174679630474b3bccf3d662d5d56bf00d5
+R 98e4cedace27c103667612897f7b7404
U drh
-Z 7e96dccb2394803edfe091e61702bf27
+Z b296ee4a843fc7eab50d30ebcbf09f32
-85daf5174679630474b3bccf3d662d5d56bf00d5
\ No newline at end of file
+9eafafa31c4a2bbcf48418743e0fcb17c374e9a6
\ No newline at end of file
/* Open the sqlite_stat[134] tables for writing. */
for(i=0; aTable[i].zCols; i++){
assert( i<ArraySize(aTable) );
- sqlite3VdbeAddOp3(v, OP_OpenWrite, iStatCur+i, aRoot[i], iDb);
- sqlite3VdbeChangeP4(v, -1, (char *)3, P4_INT32);
+ sqlite3VdbeAddOp4Int(v, OP_OpenWrite, iStatCur+i, aRoot[i], iDb, 3);
sqlite3VdbeChangeP5(v, aCreateTbl[i]);
}
}
void sqlite3OpenMasterTable(Parse *p, int iDb){
Vdbe *v = sqlite3GetVdbe(p);
sqlite3TableLock(p, iDb, MASTER_ROOT, 1, SCHEMA_TABLE(iDb));
- sqlite3VdbeAddOp3(v, OP_OpenWrite, 0, MASTER_ROOT, iDb);
- sqlite3VdbeChangeP4(v, -1, (char *)5, P4_INT32); /* 5 column table */
+ sqlite3VdbeAddOp4Int(v, OP_OpenWrite, 0, MASTER_ROOT, iDb, 5);
if( p->nTab==0 ){
p->nTab = 1;
}
){
assert( !isView );
sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName);
- sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt,
- pTab->zName, P4_STATIC);
+ if( HasRowid(pTab) ){
+ sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt,
+ pTab->zName, P4_STATIC);
+ }
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
assert( pIdx->pSchema==pTab->pSchema );
sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
}
}else
#endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */
- /* The usual case: There is a WHERE clause so we have to scan through
- ** the table and pick which records to delete.
- */
- {
+ if( !HasRowid(pTab) ){
+ /* There is a WHERE clause on a WITHOUT ROWID table.
+ */
+ Index *pPk; /* The PRIMARY KEY index on the table */
+ int iPk; /* First of nPk memory cells holding PRIMARY KEY value */
+ int iEph; /* Ephemeral table holding all primary key values */
+ int iKey; /* Key value inserting into iEph */
+ i16 nPk; /* Number of components of the PRIMARY KEY */
+
+ pPk = sqlite3PrimaryKeyIndex(pTab);
+ assert( pPk!=0 );
+ nPk = pPk->nKeyCol;
+ iPk = pParse->nMem+1;
+ pParse->nMem += nPk;
+ iKey = ++pParse->nMem;
+ iEph = pParse->nTab++;
+
+ sqlite3VdbeAddOp4(v, OP_OpenEphemeral, iEph, nPk, 0,
+ (char*)sqlite3IndexKeyinfo(pParse, pPk),
+ P4_KEYINFO_HANDOFF);
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, 0, 0);
+ if( pWInfo==0 ) goto delete_from_cleanup;
+ for(i=0; i<nPk; i++){
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, pPk->aiColumn[i], iPk+i);
+ }
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey,
+ sqlite3IndexAffinityStr(v, pPk), P4_TRANSIENT);
+ sqlite3VdbeAddOp2(v, OP_IdxInsert, iEph, iKey);
+ sqlite3WhereEnd(pWInfo);
+
+ /* Open cursors for all indices of the table.
+ */
+ sqlite3OpenTableAndIndices(pParse, pTab, iCur, iCur, OP_OpenWrite);
+
+ /* Loop over the primary keys to be deleted. */
+ addr = sqlite3VdbeAddOp1(v, OP_Rewind, iEph);
+ sqlite3VdbeAddOp2(v, OP_RowKey, iEph, iPk);
+
+ /* Delete the row */
+ sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iCur, iPk, 0,
+ 1, OE_Default);
+
+ /* End of the delete loop */
+ sqlite3VdbeAddOp2(v, OP_Next, iEph, addr+1);
+ sqlite3VdbeJumpHere(v, addr);
+
+ /* Close the cursors open on the table and its indexes. */
+ for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
+ sqlite3VdbeAddOp2(v, OP_Close, pIdx==pPk ? iCur : iCur + i, pIdx->tnum);
+ }
+ }else{
+ /* There is a WHERE clause on a rowid table. Run a loop that extracts
+ ** all rowids to be deleted into a RowSet.
+ */
int iRowSet = ++pParse->nMem; /* Register for rowset of rows to delete */
int iRowid = ++pParse->nMem; /* Used for storing rowid values. */
int regRowid; /* Actual register containing rowids */
** only effect this statement has is to fire the INSTEAD OF
** triggers. */
if( !isView ){
- sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite);
+ sqlite3OpenTableAndIndices(pParse, pTab, iCur, -1, OP_OpenWrite);
}
addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, end, iRowid);
** cursor number iCur+i for the i-th index.
**
** 3. The primary key for the row to be deleted must be stored in a
-** sequence of memory cells starting at iPk. If nPk==0 then the
-** primary key is a rowid an uses just one memory cell. If nPk>0
-** then a WITHOUT ROWID table is being used and there are nPk elements
-** of the primary key.
+** sequence of memory cells starting at iPk.
**
** This routine generates code to remove both the table record and all
** index entries that point to that record.
Vdbe *v = pParse->pVdbe; /* Vdbe */
int iOld = 0; /* First register in OLD.* array */
int iLabel; /* Label resolved to end of generated code */
+ u8 opSeek; /* Seek opcode */
/* Vdbe is guaranteed to have been allocated by this stage. */
assert( v );
** (this can happen if a trigger program has already deleted it), do
** not attempt to delete it or fire any DELETE triggers. */
iLabel = sqlite3VdbeMakeLabel(v);
- sqlite3VdbeAddOp3(v, OP_NotExists, iCur, iLabel, iPk);
+ opSeek = HasRowid(pTab) ? OP_NotExists : OP_NotFound;
+ sqlite3VdbeAddOp4Int(v, opSeek, iCur, iLabel, iPk, nPk);
/* If there are any triggers to fire, allocate a range of registers to
** use for the old.* references in the triggers. */
** the BEFORE triggers coded above have already removed the row
** being deleted. Do not attempt to delete the row a second time, and
** do not fire AFTER triggers. */
- sqlite3VdbeAddOp3(v, OP_NotExists, iCur, iLabel, iPk);
+ sqlite3VdbeAddOp4Int(v, opSeek, iCur, iLabel, iPk, nPk);
/* Do FK processing. This call checks that any FK constraints that
** refer to this table (i.e. constraints attached to other tables)
int iCur, /* Cursor number for the table */
int *aRegIdx /* Only delete if aRegIdx!=0 && aRegIdx[i]>0 */
){
- int i, iPk = 0;
+ int i;
Index *pIdx;
int r1;
int iPartIdxLabel;
Vdbe *v = pParse->pVdbe;
Index *pPk;
- pPk = sqlite3PrimaryKeyIndex(pTab);
+ pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
if( aRegIdx!=0 && aRegIdx[i-1]==0 ) continue;
- if( pIdx==pPk ){ iPk = iCur+i; continue; }
+ if( pIdx==pPk ) continue;
r1 = sqlite3GenerateIndexKey(pParse, pIdx, iCur, 0, 1, &iPartIdxLabel);
sqlite3VdbeAddOp3(v, OP_IdxDelete, iCur+i, r1,
pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
sqlite3VdbeResolveLabel(v, iPartIdxLabel);
}
- if( iPk ){
- r1 = sqlite3GenerateIndexKey(pParse, pPk, iCur, 0, 1, &iPartIdxLabel);
- sqlite3VdbeAddOp3(v, OP_IdxDelete, iPk, r1,
- pPk->uniqNotNull ? pPk->nKeyCol : pPk->nColumn);
- sqlite3VdbeResolveLabel(v, iPartIdxLabel);
- }
}
/*
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regBase+j);
}else{
sqlite3VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j);
- sqlite3ColumnDefault(v, pTab, idx, -1);
+ sqlite3ColumnDefault(v, pTab, pIdx->aiColumn[j], -1);
}
}
if( regOut ){
assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );
sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite)?1:0, pTab->zName);
if( HasRowid(pTab) ){
- sqlite3VdbeAddOp4(v, opcode, iCur, pTab->tnum, iDb,
- SQLITE_INT_TO_PTR(pTab->nCol), P4_INT32);
+ sqlite3VdbeAddOp4Int(v, opcode, iCur, pTab->tnum, iDb, pTab->nCol);
VdbeComment((v, "%s", pTab->zName));
}else if( opcode==OP_OpenRead ){
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
int nIdx;
baseCur = pParse->nTab - withoutRowid;
- nIdx = sqlite3OpenTableAndIndices(pParse, pTab, baseCur, OP_OpenWrite);
+ nIdx = sqlite3OpenTableAndIndices(pParse, pTab, baseCur, -1, OP_OpenWrite);
aRegIdx = sqlite3DbMallocRaw(db, sizeof(int)*(nIdx+1));
if( aRegIdx==0 ){
goto insert_cleanup;
}
/* Create a key for accessing the index entry */
- regIdx = sqlite3GetTempRange(pParse, pIdx->nKeyCol+1);
+ regIdx = sqlite3GetTempRange(pParse, pIdx->nColumn+1);
for(i=0; i<pIdx->nColumn; i++){
i16 idx = pIdx->aiColumn[i];
if( idx<0 || idx==pTab->iPKey ){
/* Check to see if the new index entry will be unique */
regR = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_SCopy, regOldRowid, regR);
- j3 = sqlite3VdbeAddOp4(v, OP_IsUnique, baseCur+iCur+1, 0,
- regR, SQLITE_INT_TO_PTR(regIdx),
- P4_INT32);
+ j3 = sqlite3VdbeAddOp4Int(v, OP_IsUnique, baseCur+iCur+1, 0, regR, regIdx);
sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nKeyCol+1);
/* Generate code that executes if the new index entry is not unique */
Parse *pParse, /* Parsing context */
Table *pTab, /* Table to be opened */
int baseCur, /* Cursor number assigned to the table */
+ int pkCur, /* Cursor number for the primary key */
int op /* OP_OpenRead or OP_OpenWrite */
){
int i;
sqlite3OpenTable(pParse, baseCur, iDb, pTab, op);
for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
+ int iCur = (pkCur>=0 && pIdx->autoIndex==2) ? pkCur : i+baseCur;
assert( pIdx->pSchema==pTab->pSchema );
- sqlite3VdbeAddOp4(v, op, i+baseCur, pIdx->tnum, iDb,
+ sqlite3VdbeAddOp4(v, op, iCur, pIdx->tnum, iDb,
(char*)pKey, P4_KEYINFO_HANDOFF);
VdbeComment((v, "%s", pIdx->zName));
}
- if( pParse->nTab<baseCur+i ){
- pParse->nTab = baseCur+i;
- }
+ if( pParse->nTab<=i+baseCur ) pParse->nTab = i+baseCur;
return i-1;
}
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
sqlite3VdbeJumpHere(v, addr);
sqlite3ExprCacheClear(pParse);
- sqlite3OpenTableAndIndices(pParse, pTab, 1, OP_OpenRead);
+ sqlite3OpenTableAndIndices(pParse, pTab, 1, -1, OP_OpenRead);
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
sqlite3VdbeAddOp2(v, OP_Integer, 0, 7+j); /* index entries counter */
}
}
/* Open a read-only cursor, execute the OP_Count, close the cursor. */
- sqlite3VdbeAddOp4(v, OP_OpenRead, iCsr, iRoot, iDb,
- SQLITE_INT_TO_PTR(1), P4_INT32);
+ sqlite3VdbeAddOp4Int(v, OP_OpenRead, iCsr, iRoot, iDb, 1);
if( pKeyInfo ){
sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO_HANDOFF);
}
void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int,
int*,int,int,int,int,int*);
void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*, int, int, int);
-int sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
+int sqlite3OpenTableAndIndices(Parse*, Table*, int, int, int);
void sqlite3BeginWriteOperation(Parse*, int, int);
void sqlite3MultiWrite(Parse*);
void sqlite3MayAbort(Parse*);
break;
}
alreadyExists = (res==0);
+ pC->nullRow = 1-alreadyExists;
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
}
/* Opcode: NotExists P1 P2 P3 * *
**
-** Use the content of register P3 as an integer key. If a record
-** with that key does not exist in table of P1, then jump to P2.
-** If the record does exist, then fall through. The cursor is left
-** pointing to the record if it exists.
+** P1 is the index of a cursor open on an SQL table btree (with integer
+** keys). P3 is an integer rowid. If P1 does not contain a record with
+** rowid P3 then jump immediately to P2. If P1 does contain a record
+** with rowid P3 then leave the cursor pointing at that record and fall
+** through to the next instruction.
**
-** The difference between this operation and NotFound is that this
-** operation assumes the key is an integer and that P1 is a table whereas
-** NotFound assumes key is a blob constructed from MakeRecord and
-** P1 is an index.
+** The OP_NotFound opcode performs the same operation on index btrees
+** (with arbitrary multi-value keys).
**
** See also: Found, NotFound, IsUnique
*/
k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]);
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, iRowidReg+j);
}
- sqlite3VdbeAddOp4(v, OP_NotFound, iCur, addrCont, iRowidReg,
- SQLITE_INT_TO_PTR(pPk->nKeyCol), P4_INT32);
+ sqlite3VdbeAddOp4Int(v, OP_NotFound, iCur, addrCont,
+ iRowidReg, pPk->nKeyCol);
}
/* Record the instruction used to terminate the loop. Disable
if( b
|| ( m==0
&& pProbe->bUnordered==0
- && pProbe->szIdxRow<pTab->szTabRow
+ && (!HasRowid(pTab) || pProbe->szIdxRow<pTab->szTabRow)
&& (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
&& sqlite3GlobalConfig.bUseCis
&& OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan)