blob: 15e2ea3f9d475b399982c4589ce978cbb33dac83 [file] [log] [blame]
drhcce7d172000-05-31 15:34:51 +00001/*
drhb19a2bc2001-09-16 00:13:26 +00002** 2001 September 15
drhcce7d172000-05-31 15:34:51 +00003**
drhb19a2bc2001-09-16 00:13:26 +00004** The author disclaims copyright to this source code. In place of
5** a legal notice, here is a blessing:
drhcce7d172000-05-31 15:34:51 +00006**
drhb19a2bc2001-09-16 00:13:26 +00007** May you do good and not evil.
8** May you find forgiveness for yourself and forgive others.
9** May you share freely, never taking more than you give.
drhcce7d172000-05-31 15:34:51 +000010**
11*************************************************************************
12** This file contains C code routines that are called by the parser
13** to handle DELETE FROM statements.
14**
drh0ca3e242002-01-29 23:07:02 +000015** $Id: delete.c,v 1.25 2002/01/29 23:07:02 drh Exp $
drhcce7d172000-05-31 15:34:51 +000016*/
17#include "sqliteInt.h"
18
19/*
20** Process a DELETE FROM statement.
21*/
22void sqliteDeleteFrom(
23 Parse *pParse, /* The parser context */
24 Token *pTableName, /* The table from which we should delete things */
25 Expr *pWhere /* The WHERE clause. May be null */
26){
27 Vdbe *v; /* The virtual database engine */
28 Table *pTab; /* The table from which records will be deleted */
29 IdList *pTabList; /* An ID list holding pTab and nothing else */
30 int end, addr; /* A couple addresses of generated code */
31 int i; /* Loop counter */
32 WhereInfo *pWInfo; /* Information about the WHERE clause */
33 Index *pIdx; /* For looping over indices of the table */
drh4794b982000-06-06 13:54:14 +000034 int base; /* Index of the first available table cursor */
drhecdc7532001-09-23 02:35:53 +000035 sqlite *db; /* Main database structure */
drh1bee3d72001-10-15 00:44:35 +000036 int openOp; /* Opcode used to open a cursor to the table */
37
drhcce7d172000-05-31 15:34:51 +000038
drhdaffd0e2001-04-11 14:28:42 +000039 if( pParse->nErr || sqlite_malloc_failed ){
40 pTabList = 0;
41 goto delete_from_cleanup;
42 }
drhecdc7532001-09-23 02:35:53 +000043 db = pParse->db;
drhdaffd0e2001-04-11 14:28:42 +000044
drh1ccde152000-06-17 13:12:39 +000045 /* Locate the table which we want to delete. This table has to be
46 ** put in an IdList structure because some of the subroutines we
drhcce7d172000-05-31 15:34:51 +000047 ** will be calling are designed to work with multiple tables and expect
48 ** an IdList* parameter instead of just a Table* parameger.
49 */
50 pTabList = sqliteIdListAppend(0, pTableName);
drhdaffd0e2001-04-11 14:28:42 +000051 if( pTabList==0 ) goto delete_from_cleanup;
drhcce7d172000-05-31 15:34:51 +000052 for(i=0; i<pTabList->nId; i++){
drhecdc7532001-09-23 02:35:53 +000053 pTabList->a[i].pTab = sqliteFindTable(db, pTabList->a[i].zName);
drhcce7d172000-05-31 15:34:51 +000054 if( pTabList->a[i].pTab==0 ){
55 sqliteSetString(&pParse->zErrMsg, "no such table: ",
56 pTabList->a[i].zName, 0);
57 pParse->nErr++;
58 goto delete_from_cleanup;
59 }
60 if( pTabList->a[i].pTab->readOnly ){
61 sqliteSetString(&pParse->zErrMsg, "table ", pTabList->a[i].zName,
62 " may not be modified", 0);
63 pParse->nErr++;
64 goto delete_from_cleanup;
65 }
66 }
67 pTab = pTabList->a[0].pTab;
68
drh967e8b72000-06-21 13:59:10 +000069 /* Resolve the column names in all the expressions.
drhcce7d172000-05-31 15:34:51 +000070 */
71 if( pWhere ){
drh4794b982000-06-06 13:54:14 +000072 sqliteExprResolveInSelect(pParse, pWhere);
drha2e00042002-01-22 03:13:42 +000073 if( sqliteExprResolveIds(pParse, pTabList, 0, pWhere) ){
drhcce7d172000-05-31 15:34:51 +000074 goto delete_from_cleanup;
75 }
76 if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
77 goto delete_from_cleanup;
78 }
79 }
80
81 /* Begin generating code.
82 */
drhd8bc7082000-06-07 23:51:50 +000083 v = sqliteGetVdbe(pParse);
drhcce7d172000-05-31 15:34:51 +000084 if( v==0 ) goto delete_from_cleanup;
drhecdc7532001-09-23 02:35:53 +000085 if( (db->flags & SQLITE_InTrans)==0 ){
drh99fcd712001-10-13 01:06:47 +000086 sqliteVdbeAddOp(v, OP_Transaction, 0, 0);
87 sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0);
drhecdc7532001-09-23 02:35:53 +000088 pParse->schemaVerified = 1;
drh5e00f6c2001-09-13 13:46:56 +000089 }
90
drh1bee3d72001-10-15 00:44:35 +000091 /* Initialize the counter of the number of rows deleted, if
92 ** we are counting rows.
93 */
94 if( db->flags & SQLITE_CountRows ){
95 sqliteVdbeAddOp(v, OP_Integer, 0, 0);
96 }
drhcce7d172000-05-31 15:34:51 +000097
drh0353ced2001-03-20 22:05:00 +000098 /* Special case: A DELETE without a WHERE clause deletes everything.
drhecdc7532001-09-23 02:35:53 +000099 ** It is easier just to erase the whole table.
drhcce7d172000-05-31 15:34:51 +0000100 */
drh0353ced2001-03-20 22:05:00 +0000101 if( pWhere==0 ){
drh1bee3d72001-10-15 00:44:35 +0000102 if( db->flags & SQLITE_CountRows ){
103 /* If counting rows deleted, just count the total number of
104 ** entries in the table. */
105 int endOfLoop = sqliteVdbeMakeLabel(v);
106 int addr;
107 openOp = pTab->isTemp ? OP_OpenAux : OP_Open;
108 sqliteVdbeAddOp(v, openOp, 0, pTab->tnum);
drh6b563442001-11-07 16:48:26 +0000109 sqliteVdbeAddOp(v, OP_Rewind, 0, sqliteVdbeCurrentAddr(v)+2);
110 addr = sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
111 sqliteVdbeAddOp(v, OP_Next, 0, addr);
drh1bee3d72001-10-15 00:44:35 +0000112 sqliteVdbeResolveLabel(v, endOfLoop);
113 sqliteVdbeAddOp(v, OP_Close, 0, 0);
114 }
drh99fcd712001-10-13 01:06:47 +0000115 sqliteVdbeAddOp(v, OP_Clear, pTab->tnum, pTab->isTemp);
drh0353ced2001-03-20 22:05:00 +0000116 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
drh99fcd712001-10-13 01:06:47 +0000117 sqliteVdbeAddOp(v, OP_Clear, pIdx->tnum, pTab->isTemp);
drhcce7d172000-05-31 15:34:51 +0000118 }
119 }
drh0353ced2001-03-20 22:05:00 +0000120
121 /* The usual case: There is a WHERE clause so we have to scan through
122 ** the table an pick which records to delete.
123 */
124 else{
125 /* Begin the database scan
126 */
drh0353ced2001-03-20 22:05:00 +0000127 pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1);
128 if( pWInfo==0 ) goto delete_from_cleanup;
129
130 /* Remember the key of every item to be deleted.
131 */
drh99fcd712001-10-13 01:06:47 +0000132 sqliteVdbeAddOp(v, OP_ListWrite, 0, 0);
drh1bee3d72001-10-15 00:44:35 +0000133 if( db->flags & SQLITE_CountRows ){
134 sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
135 }
drh0353ced2001-03-20 22:05:00 +0000136
137 /* End the database scan loop.
138 */
139 sqliteWhereEnd(pWInfo);
140
141 /* Delete every item whose key was written to the list during the
142 ** database scan. We have to delete items after the scan is complete
143 ** because deleting an item can change the scan order.
144 */
145 base = pParse->nTab;
drh99fcd712001-10-13 01:06:47 +0000146 sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
drhf57b3392001-10-08 13:22:32 +0000147 openOp = pTab->isTemp ? OP_OpenWrAux : OP_OpenWrite;
drh99fcd712001-10-13 01:06:47 +0000148 sqliteVdbeAddOp(v, openOp, base, pTab->tnum);
drh0353ced2001-03-20 22:05:00 +0000149 for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
drh99fcd712001-10-13 01:06:47 +0000150 sqliteVdbeAddOp(v, openOp, base+i, pIdx->tnum);
drh0353ced2001-03-20 22:05:00 +0000151 }
152 end = sqliteVdbeMakeLabel(v);
drh99fcd712001-10-13 01:06:47 +0000153 addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);
drh9cfcf5d2002-01-29 18:41:24 +0000154 sqliteGenerateRowDelete(v, pTab, base);
drh99fcd712001-10-13 01:06:47 +0000155 sqliteVdbeAddOp(v, OP_Goto, 0, addr);
156 sqliteVdbeResolveLabel(v, end);
drha8b38d22001-11-01 14:41:34 +0000157 sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
drh0353ced2001-03-20 22:05:00 +0000158 }
drhecdc7532001-09-23 02:35:53 +0000159 if( (db->flags & SQLITE_InTrans)==0 ){
drh99fcd712001-10-13 01:06:47 +0000160 sqliteVdbeAddOp(v, OP_Commit, 0, 0);
drh5e00f6c2001-09-13 13:46:56 +0000161 }
162
drh1bee3d72001-10-15 00:44:35 +0000163 /*
164 ** Return the number of rows that were deleted.
165 */
166 if( db->flags & SQLITE_CountRows ){
167 sqliteVdbeAddOp(v, OP_ColumnCount, 1, 0);
168 sqliteVdbeAddOp(v, OP_ColumnName, 0, 0);
169 sqliteVdbeChangeP3(v, -1, "rows deleted", P3_STATIC);
170 sqliteVdbeAddOp(v, OP_Callback, 1, 0);
171 }
drhcce7d172000-05-31 15:34:51 +0000172
173delete_from_cleanup:
174 sqliteIdListDelete(pTabList);
175 sqliteExprDelete(pWhere);
176 return;
177}
drh9cfcf5d2002-01-29 18:41:24 +0000178
179/*
180** This routine generates VDBE code that causes a single row of a
181** single table to be deleted.
182**
183** The VDBE must be in a particular state when this routine is called.
184** These are the requirements:
185**
186** 1. A read/write cursor pointing to pTab, the table containing the row
187** to be deleted, must be opened as cursor number "base".
188**
189** 2. Read/write cursors for all indices of pTab must be open as
190** cursor number base+i for the i-th index.
191**
192** 3. The record number of the row to be deleted must be on the top
193** of the stack.
194**
195** This routine pops the top of the stack to remove the record number
196** and then generates code to remove both the table record and all index
197** entries that point to that record.
198*/
199void sqliteGenerateRowDelete(
200 Vdbe *v, /* Generate code into this VDBE */
201 Table *pTab, /* Table containing the row to be deleted */
202 int base /* Cursor number for the table */
203){
drh0ca3e242002-01-29 23:07:02 +0000204 sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
205 sqliteGenerateRowIndexDelete(v, pTab, base, 0);
206 sqliteVdbeAddOp(v, OP_Delete, base, 0);
207}
208
209/*
210** This routine generates VDBE code that causes the deletion of all
211** index entries associated with a single row of a single table.
212**
213** The VDBE must be in a particular state when this routine is called.
214** These are the requirements:
215**
216** 1. A read/write cursor pointing to pTab, the table containing the row
217** to be deleted, must be opened as cursor number "base".
218**
219** 2. Read/write cursors for all indices of pTab must be open as
220** cursor number base+i for the i-th index.
221**
222** 3. The "base" cursor must be pointing to the row that is to be
223** deleted.
224*/
225void sqliteGenerateRowIndexDelete(
226 Vdbe *v, /* Generate code into this VDBE */
227 Table *pTab, /* Table containing the row to be deleted */
228 int base, /* Cursor number for the table */
229 char *aIdxUsed /* Only delete if aIdxUsed!=0 && aIdxUsed[i]!=0 */
230){
drh9cfcf5d2002-01-29 18:41:24 +0000231 int i;
232 Index *pIdx;
233
drh0ca3e242002-01-29 23:07:02 +0000234 for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
235 int j;
236 if( aIdxUsed!=0 && aIdxUsed[i-1]==0 ) continue;
237 sqliteVdbeAddOp(v, OP_Recno, base, 0);
238 for(j=0; j<pIdx->nColumn; j++){
239 int idx = pIdx->aiColumn[j];
240 if( idx==pTab->iPKey ){
241 sqliteVdbeAddOp(v, OP_Dup, j, 0);
242 }else{
243 sqliteVdbeAddOp(v, OP_Column, base, idx);
drh9cfcf5d2002-01-29 18:41:24 +0000244 }
drh9cfcf5d2002-01-29 18:41:24 +0000245 }
drh0ca3e242002-01-29 23:07:02 +0000246 sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
247 sqliteVdbeAddOp(v, OP_IdxDelete, base+i, 0);
drh9cfcf5d2002-01-29 18:41:24 +0000248 }
drh9cfcf5d2002-01-29 18:41:24 +0000249}