mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
Basic DELETE operations now working on WITHOUT ROWID tables.
FossilOrigin-Name: 9eafafa31c4a2bbcf48418743e0fcb17c374e9a6
This commit is contained in:
28
manifest
28
manifest
@@ -1,5 +1,5 @@
|
|||||||
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.
|
C Basic\sDELETE\soperations\snow\sworking\son\sWITHOUT\sROWID\stables.
|
||||||
D 2013-10-24T19:48:39.042
|
D 2013-10-25T14:46:15.958
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in 0522b53cdc1fcfc18f3a98e0246add129136c654
|
F Makefile.in 0522b53cdc1fcfc18f3a98e0246add129136c654
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
@@ -159,7 +159,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
|||||||
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
|
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
|
||||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||||
F src/alter.c 2af0330bb1b601af7a7789bf7229675fd772a083
|
F src/alter.c 2af0330bb1b601af7a7789bf7229675fd772a083
|
||||||
F src/analyze.c ee880a4c0deb1c4090a4bbff03adfbf934451f50
|
F src/analyze.c b6b115d69adaf0d2fa15001748b12735832fb296
|
||||||
F src/attach.c 0a17c9364895316ca4f52d06a97a72c0af1ae8b3
|
F src/attach.c 0a17c9364895316ca4f52d06a97a72c0af1ae8b3
|
||||||
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
||||||
F src/backup.c 2f1987981139bd2f6d8c728d64bf09fb387443c3
|
F src/backup.c 2f1987981139bd2f6d8c728d64bf09fb387443c3
|
||||||
@@ -168,12 +168,12 @@ F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
|
|||||||
F src/btree.c 509722ce305471b626d3401c0631a808fd33237b
|
F src/btree.c 509722ce305471b626d3401c0631a808fd33237b
|
||||||
F src/btree.h bfe0e8c5759b4ec77b0d18390064a6ef3cdffaaf
|
F src/btree.h bfe0e8c5759b4ec77b0d18390064a6ef3cdffaaf
|
||||||
F src/btreeInt.h f038e818bfadf75afbd09819ed93c26a333d39e0
|
F src/btreeInt.h f038e818bfadf75afbd09819ed93c26a333d39e0
|
||||||
F src/build.c f99c6980a258e32e0e0068b04dd8eed6a4af9445
|
F src/build.c 4d62e99fa36db1793cc1bed63e6775defdf8c587
|
||||||
F src/callback.c f99a8957ba2adf369645fac0db09ad8adcf1caa2
|
F src/callback.c f99a8957ba2adf369645fac0db09ad8adcf1caa2
|
||||||
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||||
F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c
|
F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c
|
||||||
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
|
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
|
||||||
F src/delete.c 3a750695133bf8646124b07cf8a51222110885a6
|
F src/delete.c 8b9aa9c935fdd48a7a8ac0eff22c03cb29f12e96
|
||||||
F src/expr.c 3180b6332072b263f845592e72e92971af562ab0
|
F src/expr.c 3180b6332072b263f845592e72e92971af562ab0
|
||||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||||
F src/fkey.c 628f81177299660a86e40359b3689b81f517e125
|
F src/fkey.c 628f81177299660a86e40359b3689b81f517e125
|
||||||
@@ -182,7 +182,7 @@ F src/global.c 5caf4deab621abb45b4c607aad1bd21c20aac759
|
|||||||
F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4
|
F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4
|
||||||
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
|
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
|
||||||
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
||||||
F src/insert.c a188b1abcc80cb835a1a9b76e78190d1516d22bc
|
F src/insert.c 71b3d1f551ab8e0ba59fdbaff3feef8d931a424e
|
||||||
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
||||||
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
|
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
|
||||||
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
|
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
|
||||||
@@ -212,18 +212,18 @@ F src/parse.y 073a8294e1826f1b1656e84806b77e4199f4bb57
|
|||||||
F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
|
F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
|
||||||
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
|
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
|
||||||
F src/pcache1.c a467393909a4ed7ca9de066d85ba5c5b04a5be63
|
F src/pcache1.c a467393909a4ed7ca9de066d85ba5c5b04a5be63
|
||||||
F src/pragma.c d6eee7e1b6343996883e5c7e0f60bfad77be2180
|
F src/pragma.c 5986f119f6350839a28936fce4e2d6a4c703922c
|
||||||
F src/prepare.c f47ba2bba7ac5650881ab6c41f6d33a6de1a8d52
|
F src/prepare.c f47ba2bba7ac5650881ab6c41f6d33a6de1a8d52
|
||||||
F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b
|
F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b
|
||||||
F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68
|
F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68
|
||||||
F src/resolve.c e729889b2c7a680ba4aa7296efa72c09369956d8
|
F src/resolve.c e729889b2c7a680ba4aa7296efa72c09369956d8
|
||||||
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
|
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
|
||||||
F src/select.c dbcd2271470b5d074252ea75e2e50f3544638b49
|
F src/select.c 8290456f2a516abaf8cbbed5e61944d3082e497e
|
||||||
F src/shell.c 6f11f0e9ded63d48e306f2c6858c521e568a47bb
|
F src/shell.c 6f11f0e9ded63d48e306f2c6858c521e568a47bb
|
||||||
F src/sqlite.h.in 547a44dd4ff4d975e92a645ea2d609e543a83d0f
|
F src/sqlite.h.in 547a44dd4ff4d975e92a645ea2d609e543a83d0f
|
||||||
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
||||||
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
||||||
F src/sqliteInt.h a0834a450cd990eadcb18b790557abfe6dc52270
|
F src/sqliteInt.h 674cee6761771e7c1d6446671fcf7daf27b4c0f7
|
||||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||||
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
||||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||||
@@ -279,7 +279,7 @@ F src/update.c 2bb5a267796e6d0177ef5689487c3688de5c309e
|
|||||||
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
|
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
|
||||||
F src/util.c 2fa6c821d28bbdbeec1b2a7b091a281c9ef8f918
|
F src/util.c 2fa6c821d28bbdbeec1b2a7b091a281c9ef8f918
|
||||||
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
|
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
|
||||||
F src/vdbe.c cca2c5eb4eb85ff10955c766cc75b78b4cbb5b08
|
F src/vdbe.c f7a2fb5d707db64f59ebb2d054485790350f84db
|
||||||
F src/vdbe.h 4f554b5627f26710c4c36d919110a3fc611ca5c4
|
F src/vdbe.h 4f554b5627f26710c4c36d919110a3fc611ca5c4
|
||||||
F src/vdbeInt.h ff57f67aee1ba26a3a47e786533dab155ab6dad6
|
F src/vdbeInt.h ff57f67aee1ba26a3a47e786533dab155ab6dad6
|
||||||
F src/vdbeapi.c 93a22a9ba2abe292d5c2cf304d7eb2e894dde0ed
|
F src/vdbeapi.c 93a22a9ba2abe292d5c2cf304d7eb2e894dde0ed
|
||||||
@@ -292,7 +292,7 @@ F src/vtab.c 5a423b042eb1402ef77697d03d6a67378d97bc8d
|
|||||||
F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4
|
F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4
|
||||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||||
F src/walker.c e9e593d5bb798c3e67fc3893dfe7055c9e7d8d74
|
F src/walker.c e9e593d5bb798c3e67fc3893dfe7055c9e7d8d74
|
||||||
F src/where.c 04217a957c1423dd5f177b21b4ced319bf24b77c
|
F src/where.c 512ddbf2884f5560a0ad5b076efc142ad7a07c7b
|
||||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||||
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
|
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
|
||||||
@@ -1127,7 +1127,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
|
|||||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||||
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
||||||
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
||||||
P 0e56ba69f0fcd12a5166c32f6e4eacdcc29fba04
|
P 85daf5174679630474b3bccf3d662d5d56bf00d5
|
||||||
R 23965d1fb428e8ef205e9927049056c2
|
R 98e4cedace27c103667612897f7b7404
|
||||||
U drh
|
U drh
|
||||||
Z 7e96dccb2394803edfe091e61702bf27
|
Z b296ee4a843fc7eab50d30ebcbf09f32
|
||||||
|
@@ -1 +1 @@
|
|||||||
85daf5174679630474b3bccf3d662d5d56bf00d5
|
9eafafa31c4a2bbcf48418743e0fcb17c374e9a6
|
@@ -244,8 +244,7 @@ static void openStatTable(
|
|||||||
/* Open the sqlite_stat[134] tables for writing. */
|
/* Open the sqlite_stat[134] tables for writing. */
|
||||||
for(i=0; aTable[i].zCols; i++){
|
for(i=0; aTable[i].zCols; i++){
|
||||||
assert( i<ArraySize(aTable) );
|
assert( i<ArraySize(aTable) );
|
||||||
sqlite3VdbeAddOp3(v, OP_OpenWrite, iStatCur+i, aRoot[i], iDb);
|
sqlite3VdbeAddOp4Int(v, OP_OpenWrite, iStatCur+i, aRoot[i], iDb, 3);
|
||||||
sqlite3VdbeChangeP4(v, -1, (char *)3, P4_INT32);
|
|
||||||
sqlite3VdbeChangeP5(v, aCreateTbl[i]);
|
sqlite3VdbeChangeP5(v, aCreateTbl[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -642,8 +642,7 @@ char *sqlite3NameFromToken(sqlite3 *db, Token *pName){
|
|||||||
void sqlite3OpenMasterTable(Parse *p, int iDb){
|
void sqlite3OpenMasterTable(Parse *p, int iDb){
|
||||||
Vdbe *v = sqlite3GetVdbe(p);
|
Vdbe *v = sqlite3GetVdbe(p);
|
||||||
sqlite3TableLock(p, iDb, MASTER_ROOT, 1, SCHEMA_TABLE(iDb));
|
sqlite3TableLock(p, iDb, MASTER_ROOT, 1, SCHEMA_TABLE(iDb));
|
||||||
sqlite3VdbeAddOp3(v, OP_OpenWrite, 0, MASTER_ROOT, iDb);
|
sqlite3VdbeAddOp4Int(v, OP_OpenWrite, 0, MASTER_ROOT, iDb, 5);
|
||||||
sqlite3VdbeChangeP4(v, -1, (char *)5, P4_INT32); /* 5 column table */
|
|
||||||
if( p->nTab==0 ){
|
if( p->nTab==0 ){
|
||||||
p->nTab = 1;
|
p->nTab = 1;
|
||||||
}
|
}
|
||||||
|
85
src/delete.c
85
src/delete.c
@@ -352,18 +352,70 @@ void sqlite3DeleteFrom(
|
|||||||
){
|
){
|
||||||
assert( !isView );
|
assert( !isView );
|
||||||
sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName);
|
sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName);
|
||||||
|
if( HasRowid(pTab) ){
|
||||||
sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt,
|
sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt,
|
||||||
pTab->zName, P4_STATIC);
|
pTab->zName, P4_STATIC);
|
||||||
|
}
|
||||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||||
assert( pIdx->pSchema==pTab->pSchema );
|
assert( pIdx->pSchema==pTab->pSchema );
|
||||||
sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
|
sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
|
||||||
}
|
}
|
||||||
}else
|
}else
|
||||||
#endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */
|
#endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */
|
||||||
/* The usual case: There is a WHERE clause so we have to scan through
|
if( !HasRowid(pTab) ){
|
||||||
** the table and pick which records to delete.
|
/* 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 iRowSet = ++pParse->nMem; /* Register for rowset of rows to delete */
|
||||||
int iRowid = ++pParse->nMem; /* Used for storing rowid values. */
|
int iRowid = ++pParse->nMem; /* Used for storing rowid values. */
|
||||||
int regRowid; /* Actual register containing rowids */
|
int regRowid; /* Actual register containing rowids */
|
||||||
@@ -392,7 +444,7 @@ void sqlite3DeleteFrom(
|
|||||||
** only effect this statement has is to fire the INSTEAD OF
|
** only effect this statement has is to fire the INSTEAD OF
|
||||||
** triggers. */
|
** triggers. */
|
||||||
if( !isView ){
|
if( !isView ){
|
||||||
sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite);
|
sqlite3OpenTableAndIndices(pParse, pTab, iCur, -1, OP_OpenWrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, end, iRowid);
|
addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, end, iRowid);
|
||||||
@@ -475,10 +527,7 @@ delete_from_cleanup:
|
|||||||
** cursor number iCur+i for the i-th index.
|
** cursor number iCur+i for the i-th index.
|
||||||
**
|
**
|
||||||
** 3. The primary key for the row to be deleted must be stored in a
|
** 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
|
** sequence of memory cells starting at iPk.
|
||||||
** 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.
|
|
||||||
**
|
**
|
||||||
** This routine generates code to remove both the table record and all
|
** This routine generates code to remove both the table record and all
|
||||||
** index entries that point to that record.
|
** index entries that point to that record.
|
||||||
@@ -496,6 +545,7 @@ void sqlite3GenerateRowDelete(
|
|||||||
Vdbe *v = pParse->pVdbe; /* Vdbe */
|
Vdbe *v = pParse->pVdbe; /* Vdbe */
|
||||||
int iOld = 0; /* First register in OLD.* array */
|
int iOld = 0; /* First register in OLD.* array */
|
||||||
int iLabel; /* Label resolved to end of generated code */
|
int iLabel; /* Label resolved to end of generated code */
|
||||||
|
u8 opSeek; /* Seek opcode */
|
||||||
|
|
||||||
/* Vdbe is guaranteed to have been allocated by this stage. */
|
/* Vdbe is guaranteed to have been allocated by this stage. */
|
||||||
assert( v );
|
assert( v );
|
||||||
@@ -504,7 +554,8 @@ void sqlite3GenerateRowDelete(
|
|||||||
** (this can happen if a trigger program has already deleted it), do
|
** (this can happen if a trigger program has already deleted it), do
|
||||||
** not attempt to delete it or fire any DELETE triggers. */
|
** not attempt to delete it or fire any DELETE triggers. */
|
||||||
iLabel = sqlite3VdbeMakeLabel(v);
|
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
|
/* If there are any triggers to fire, allocate a range of registers to
|
||||||
** use for the old.* references in the triggers. */
|
** use for the old.* references in the triggers. */
|
||||||
@@ -539,7 +590,7 @@ void sqlite3GenerateRowDelete(
|
|||||||
** the BEFORE triggers coded above have already removed the row
|
** the BEFORE triggers coded above have already removed the row
|
||||||
** being deleted. Do not attempt to delete the row a second time, and
|
** being deleted. Do not attempt to delete the row a second time, and
|
||||||
** do not fire AFTER triggers. */
|
** 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
|
/* Do FK processing. This call checks that any FK constraints that
|
||||||
** refer to this table (i.e. constraints attached to other tables)
|
** refer to this table (i.e. constraints attached to other tables)
|
||||||
@@ -600,28 +651,22 @@ void sqlite3GenerateRowIndexDelete(
|
|||||||
int iCur, /* Cursor number for the table */
|
int iCur, /* Cursor number for the table */
|
||||||
int *aRegIdx /* Only delete if aRegIdx!=0 && aRegIdx[i]>0 */
|
int *aRegIdx /* Only delete if aRegIdx!=0 && aRegIdx[i]>0 */
|
||||||
){
|
){
|
||||||
int i, iPk = 0;
|
int i;
|
||||||
Index *pIdx;
|
Index *pIdx;
|
||||||
int r1;
|
int r1;
|
||||||
int iPartIdxLabel;
|
int iPartIdxLabel;
|
||||||
Vdbe *v = pParse->pVdbe;
|
Vdbe *v = pParse->pVdbe;
|
||||||
Index *pPk;
|
Index *pPk;
|
||||||
|
|
||||||
pPk = sqlite3PrimaryKeyIndex(pTab);
|
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
|
||||||
for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
|
for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
|
||||||
if( aRegIdx!=0 && aRegIdx[i-1]==0 ) continue;
|
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);
|
r1 = sqlite3GenerateIndexKey(pParse, pIdx, iCur, 0, 1, &iPartIdxLabel);
|
||||||
sqlite3VdbeAddOp3(v, OP_IdxDelete, iCur+i, r1,
|
sqlite3VdbeAddOp3(v, OP_IdxDelete, iCur+i, r1,
|
||||||
pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
|
pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
|
||||||
sqlite3VdbeResolveLabel(v, iPartIdxLabel);
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -677,7 +722,7 @@ int sqlite3GenerateIndexKey(
|
|||||||
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regBase+j);
|
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regBase+j);
|
||||||
}else{
|
}else{
|
||||||
sqlite3VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j);
|
sqlite3VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j);
|
||||||
sqlite3ColumnDefault(v, pTab, idx, -1);
|
sqlite3ColumnDefault(v, pTab, pIdx->aiColumn[j], -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( regOut ){
|
if( regOut ){
|
||||||
|
19
src/insert.c
19
src/insert.c
@@ -36,8 +36,7 @@ void sqlite3OpenTable(
|
|||||||
assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );
|
assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );
|
||||||
sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite)?1:0, pTab->zName);
|
sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite)?1:0, pTab->zName);
|
||||||
if( HasRowid(pTab) ){
|
if( HasRowid(pTab) ){
|
||||||
sqlite3VdbeAddOp4(v, opcode, iCur, pTab->tnum, iDb,
|
sqlite3VdbeAddOp4Int(v, opcode, iCur, pTab->tnum, iDb, pTab->nCol);
|
||||||
SQLITE_INT_TO_PTR(pTab->nCol), P4_INT32);
|
|
||||||
VdbeComment((v, "%s", pTab->zName));
|
VdbeComment((v, "%s", pTab->zName));
|
||||||
}else if( opcode==OP_OpenRead ){
|
}else if( opcode==OP_OpenRead ){
|
||||||
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
|
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
|
||||||
@@ -825,7 +824,7 @@ void sqlite3Insert(
|
|||||||
int nIdx;
|
int nIdx;
|
||||||
|
|
||||||
baseCur = pParse->nTab - withoutRowid;
|
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));
|
aRegIdx = sqlite3DbMallocRaw(db, sizeof(int)*(nIdx+1));
|
||||||
if( aRegIdx==0 ){
|
if( aRegIdx==0 ){
|
||||||
goto insert_cleanup;
|
goto insert_cleanup;
|
||||||
@@ -1411,7 +1410,7 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Create a key for accessing the index entry */
|
/* 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++){
|
for(i=0; i<pIdx->nColumn; i++){
|
||||||
i16 idx = pIdx->aiColumn[i];
|
i16 idx = pIdx->aiColumn[i];
|
||||||
if( idx<0 || idx==pTab->iPKey ){
|
if( idx<0 || idx==pTab->iPKey ){
|
||||||
@@ -1444,9 +1443,7 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
/* Check to see if the new index entry will be unique */
|
/* Check to see if the new index entry will be unique */
|
||||||
regR = sqlite3GetTempReg(pParse);
|
regR = sqlite3GetTempReg(pParse);
|
||||||
sqlite3VdbeAddOp2(v, OP_SCopy, regOldRowid, regR);
|
sqlite3VdbeAddOp2(v, OP_SCopy, regOldRowid, regR);
|
||||||
j3 = sqlite3VdbeAddOp4(v, OP_IsUnique, baseCur+iCur+1, 0,
|
j3 = sqlite3VdbeAddOp4Int(v, OP_IsUnique, baseCur+iCur+1, 0, regR, regIdx);
|
||||||
regR, SQLITE_INT_TO_PTR(regIdx),
|
|
||||||
P4_INT32);
|
|
||||||
sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nKeyCol+1);
|
sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nKeyCol+1);
|
||||||
|
|
||||||
/* Generate code that executes if the new index entry is not unique */
|
/* Generate code that executes if the new index entry is not unique */
|
||||||
@@ -1582,6 +1579,7 @@ int sqlite3OpenTableAndIndices(
|
|||||||
Parse *pParse, /* Parsing context */
|
Parse *pParse, /* Parsing context */
|
||||||
Table *pTab, /* Table to be opened */
|
Table *pTab, /* Table to be opened */
|
||||||
int baseCur, /* Cursor number assigned to the table */
|
int baseCur, /* Cursor number assigned to the table */
|
||||||
|
int pkCur, /* Cursor number for the primary key */
|
||||||
int op /* OP_OpenRead or OP_OpenWrite */
|
int op /* OP_OpenRead or OP_OpenWrite */
|
||||||
){
|
){
|
||||||
int i;
|
int i;
|
||||||
@@ -1596,14 +1594,13 @@ int sqlite3OpenTableAndIndices(
|
|||||||
sqlite3OpenTable(pParse, baseCur, iDb, pTab, op);
|
sqlite3OpenTable(pParse, baseCur, iDb, pTab, op);
|
||||||
for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
|
for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
|
||||||
KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
|
KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
|
||||||
|
int iCur = (pkCur>=0 && pIdx->autoIndex==2) ? pkCur : i+baseCur;
|
||||||
assert( pIdx->pSchema==pTab->pSchema );
|
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);
|
(char*)pKey, P4_KEYINFO_HANDOFF);
|
||||||
VdbeComment((v, "%s", pIdx->zName));
|
VdbeComment((v, "%s", pIdx->zName));
|
||||||
}
|
}
|
||||||
if( pParse->nTab<baseCur+i ){
|
if( pParse->nTab<=i+baseCur ) pParse->nTab = i+baseCur;
|
||||||
pParse->nTab = baseCur+i;
|
|
||||||
}
|
|
||||||
return i-1;
|
return i-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1847,7 +1847,7 @@ void sqlite3Pragma(
|
|||||||
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
|
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
|
||||||
sqlite3VdbeJumpHere(v, addr);
|
sqlite3VdbeJumpHere(v, addr);
|
||||||
sqlite3ExprCacheClear(pParse);
|
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++){
|
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
|
||||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, 7+j); /* index entries counter */
|
sqlite3VdbeAddOp2(v, OP_Integer, 0, 7+j); /* index entries counter */
|
||||||
}
|
}
|
||||||
|
@@ -4656,8 +4656,7 @@ int sqlite3Select(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Open a read-only cursor, execute the OP_Count, close the cursor. */
|
/* Open a read-only cursor, execute the OP_Count, close the cursor. */
|
||||||
sqlite3VdbeAddOp4(v, OP_OpenRead, iCsr, iRoot, iDb,
|
sqlite3VdbeAddOp4Int(v, OP_OpenRead, iCsr, iRoot, iDb, 1);
|
||||||
SQLITE_INT_TO_PTR(1), P4_INT32);
|
|
||||||
if( pKeyInfo ){
|
if( pKeyInfo ){
|
||||||
sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO_HANDOFF);
|
sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO_HANDOFF);
|
||||||
}
|
}
|
||||||
|
@@ -2920,7 +2920,7 @@ int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*);
|
|||||||
void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int,
|
void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int,
|
||||||
int*,int,int,int,int,int*);
|
int*,int,int,int,int,int*);
|
||||||
void sqlite3CompleteInsertion(Parse*, Table*, 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 sqlite3BeginWriteOperation(Parse*, int, int);
|
||||||
void sqlite3MultiWrite(Parse*);
|
void sqlite3MultiWrite(Parse*);
|
||||||
void sqlite3MayAbort(Parse*);
|
void sqlite3MayAbort(Parse*);
|
||||||
|
16
src/vdbe.c
16
src/vdbe.c
@@ -3681,6 +3681,7 @@ case OP_Found: { /* jump, in3 */
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
alreadyExists = (res==0);
|
alreadyExists = (res==0);
|
||||||
|
pC->nullRow = 1-alreadyExists;
|
||||||
pC->deferredMoveto = 0;
|
pC->deferredMoveto = 0;
|
||||||
pC->cacheStatus = CACHE_STALE;
|
pC->cacheStatus = CACHE_STALE;
|
||||||
}
|
}
|
||||||
@@ -3781,15 +3782,14 @@ case OP_IsUnique: { /* jump, in3 */
|
|||||||
|
|
||||||
/* Opcode: NotExists P1 P2 P3 * *
|
/* Opcode: NotExists P1 P2 P3 * *
|
||||||
**
|
**
|
||||||
** Use the content of register P3 as an integer key. If a record
|
** P1 is the index of a cursor open on an SQL table btree (with integer
|
||||||
** with that key does not exist in table of P1, then jump to P2.
|
** keys). P3 is an integer rowid. If P1 does not contain a record with
|
||||||
** If the record does exist, then fall through. The cursor is left
|
** rowid P3 then jump immediately to P2. If P1 does contain a record
|
||||||
** pointing to the record if it exists.
|
** 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
|
** The OP_NotFound opcode performs the same operation on index btrees
|
||||||
** operation assumes the key is an integer and that P1 is a table whereas
|
** (with arbitrary multi-value keys).
|
||||||
** NotFound assumes key is a blob constructed from MakeRecord and
|
|
||||||
** P1 is an index.
|
|
||||||
**
|
**
|
||||||
** See also: Found, NotFound, IsUnique
|
** See also: Found, NotFound, IsUnique
|
||||||
*/
|
*/
|
||||||
|
@@ -3565,8 +3565,8 @@ static Bitmask codeOneLoopStart(
|
|||||||
k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]);
|
k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]);
|
||||||
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, iRowidReg+j);
|
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, iRowidReg+j);
|
||||||
}
|
}
|
||||||
sqlite3VdbeAddOp4(v, OP_NotFound, iCur, addrCont, iRowidReg,
|
sqlite3VdbeAddOp4Int(v, OP_NotFound, iCur, addrCont,
|
||||||
SQLITE_INT_TO_PTR(pPk->nKeyCol), P4_INT32);
|
iRowidReg, pPk->nKeyCol);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Record the instruction used to terminate the loop. Disable
|
/* Record the instruction used to terminate the loop. Disable
|
||||||
@@ -4603,7 +4603,7 @@ static int whereLoopAddBtree(
|
|||||||
if( b
|
if( b
|
||||||
|| ( m==0
|
|| ( m==0
|
||||||
&& pProbe->bUnordered==0
|
&& pProbe->bUnordered==0
|
||||||
&& pProbe->szIdxRow<pTab->szTabRow
|
&& (!HasRowid(pTab) || pProbe->szIdxRow<pTab->szTabRow)
|
||||||
&& (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
|
&& (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
|
||||||
&& sqlite3GlobalConfig.bUseCis
|
&& sqlite3GlobalConfig.bUseCis
|
||||||
&& OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan)
|
&& OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan)
|
||||||
|
Reference in New Issue
Block a user