blob: 3f7e0f7edf6f4ad60ca14e1cbb5d451acc1aed7e [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**
drhc8d30ac2002-04-12 10:08:59 +000015** $Id: delete.c,v 1.30 2002/04/12 10:08:59 drh Exp $
drhcce7d172000-05-31 15:34:51 +000016*/
17#include "sqliteInt.h"
18
drha76b5df2002-02-23 02:32:10 +000019
20/*
21** Given a table name, find the corresponding table and make sure the
22** table is writeable. Generate an error and return NULL if not. If
23** everything checks out, return a pointer to the Table structure.
24*/
25Table *sqliteTableNameToTable(Parse *pParse, const char *zTab){
26 Table *pTab;
27 pTab = sqliteFindTable(pParse->db, zTab);
28 if( pTab==0 ){
29 sqliteSetString(&pParse->zErrMsg, "no such table: ", zTab, 0);
30 pParse->nErr++;
31 return 0;
32 }
33 if( pTab->readOnly || pTab->pSelect ){
34 sqliteSetString(&pParse->zErrMsg,
35 pTab->pSelect ? "view " : "table ",
36 zTab,
37 " may not be modified", 0);
38 pParse->nErr++;
39 return 0;
40 }
41 return pTab;
42}
43
44/*
45** Given a table name, check to make sure the table exists, is writable
46** and is not a view. If everything is OK, construct an IdList holding
47** the table and return a pointer to the IdList. The calling function
48** is responsible for freeing the IdList when it has finished with it.
49** If there is an error, leave a message on pParse->zErrMsg and return
50** NULL.
51*/
52IdList *sqliteTableTokenToIdList(Parse *pParse, Token *pTableName){
53 Table *pTab;
54 IdList *pTabList;
55
56 pTabList = sqliteIdListAppend(0, pTableName);
57 if( pTabList==0 ) return 0;
58 assert( pTabList->nId==1 );
59 pTab = sqliteTableNameToTable(pParse, pTabList->a[0].zName);
60 if( pTab==0 ){
61 sqliteIdListDelete(pTabList);
62 return 0;
63 }
64 pTabList->a[0].pTab = pTab;
65 return pTabList;
66}
67
drhcce7d172000-05-31 15:34:51 +000068/*
69** Process a DELETE FROM statement.
70*/
71void sqliteDeleteFrom(
72 Parse *pParse, /* The parser context */
73 Token *pTableName, /* The table from which we should delete things */
74 Expr *pWhere /* The WHERE clause. May be null */
75){
76 Vdbe *v; /* The virtual database engine */
77 Table *pTab; /* The table from which records will be deleted */
78 IdList *pTabList; /* An ID list holding pTab and nothing else */
79 int end, addr; /* A couple addresses of generated code */
80 int i; /* Loop counter */
81 WhereInfo *pWInfo; /* Information about the WHERE clause */
82 Index *pIdx; /* For looping over indices of the table */
drh4794b982000-06-06 13:54:14 +000083 int base; /* Index of the first available table cursor */
drhecdc7532001-09-23 02:35:53 +000084 sqlite *db; /* Main database structure */
drh1bee3d72001-10-15 00:44:35 +000085 int openOp; /* Opcode used to open a cursor to the table */
86
drhcce7d172000-05-31 15:34:51 +000087
drhdaffd0e2001-04-11 14:28:42 +000088 if( pParse->nErr || sqlite_malloc_failed ){
89 pTabList = 0;
90 goto delete_from_cleanup;
91 }
drhecdc7532001-09-23 02:35:53 +000092 db = pParse->db;
drhdaffd0e2001-04-11 14:28:42 +000093
drh1ccde152000-06-17 13:12:39 +000094 /* Locate the table which we want to delete. This table has to be
95 ** put in an IdList structure because some of the subroutines we
drhcce7d172000-05-31 15:34:51 +000096 ** will be calling are designed to work with multiple tables and expect
97 ** an IdList* parameter instead of just a Table* parameger.
98 */
drha76b5df2002-02-23 02:32:10 +000099 pTabList = sqliteTableTokenToIdList(pParse, pTableName);
drhdaffd0e2001-04-11 14:28:42 +0000100 if( pTabList==0 ) goto delete_from_cleanup;
drh417be792002-03-03 18:59:40 +0000101 assert( pTabList->nId==1 );
drhcce7d172000-05-31 15:34:51 +0000102 pTab = pTabList->a[0].pTab;
drh417be792002-03-03 18:59:40 +0000103 assert( pTab->pSelect==0 ); /* This table is not a view */
drhcce7d172000-05-31 15:34:51 +0000104
drh967e8b72000-06-21 13:59:10 +0000105 /* Resolve the column names in all the expressions.
drhcce7d172000-05-31 15:34:51 +0000106 */
drh832508b2002-03-02 17:04:07 +0000107 base = pParse->nTab++;
drhcce7d172000-05-31 15:34:51 +0000108 if( pWhere ){
drh832508b2002-03-02 17:04:07 +0000109 if( sqliteExprResolveIds(pParse, base, pTabList, 0, pWhere) ){
drhcce7d172000-05-31 15:34:51 +0000110 goto delete_from_cleanup;
111 }
112 if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
113 goto delete_from_cleanup;
114 }
115 }
116
117 /* Begin generating code.
118 */
drhd8bc7082000-06-07 23:51:50 +0000119 v = sqliteGetVdbe(pParse);
drhcce7d172000-05-31 15:34:51 +0000120 if( v==0 ) goto delete_from_cleanup;
drh1c928532002-01-31 15:54:21 +0000121 sqliteBeginWriteOperation(pParse);
drh5e00f6c2001-09-13 13:46:56 +0000122
drh1bee3d72001-10-15 00:44:35 +0000123 /* Initialize the counter of the number of rows deleted, if
124 ** we are counting rows.
125 */
126 if( db->flags & SQLITE_CountRows ){
127 sqliteVdbeAddOp(v, OP_Integer, 0, 0);
128 }
drhcce7d172000-05-31 15:34:51 +0000129
drh0353ced2001-03-20 22:05:00 +0000130 /* Special case: A DELETE without a WHERE clause deletes everything.
drhecdc7532001-09-23 02:35:53 +0000131 ** It is easier just to erase the whole table.
drhcce7d172000-05-31 15:34:51 +0000132 */
drh0353ced2001-03-20 22:05:00 +0000133 if( pWhere==0 ){
drh1bee3d72001-10-15 00:44:35 +0000134 if( db->flags & SQLITE_CountRows ){
135 /* If counting rows deleted, just count the total number of
136 ** entries in the table. */
137 int endOfLoop = sqliteVdbeMakeLabel(v);
138 int addr;
139 openOp = pTab->isTemp ? OP_OpenAux : OP_Open;
drh832508b2002-03-02 17:04:07 +0000140 assert( base==0 );
drh1bee3d72001-10-15 00:44:35 +0000141 sqliteVdbeAddOp(v, openOp, 0, pTab->tnum);
drh6b563442001-11-07 16:48:26 +0000142 sqliteVdbeAddOp(v, OP_Rewind, 0, sqliteVdbeCurrentAddr(v)+2);
143 addr = sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
144 sqliteVdbeAddOp(v, OP_Next, 0, addr);
drh1bee3d72001-10-15 00:44:35 +0000145 sqliteVdbeResolveLabel(v, endOfLoop);
146 sqliteVdbeAddOp(v, OP_Close, 0, 0);
147 }
drh99fcd712001-10-13 01:06:47 +0000148 sqliteVdbeAddOp(v, OP_Clear, pTab->tnum, pTab->isTemp);
drh0353ced2001-03-20 22:05:00 +0000149 for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
drh99fcd712001-10-13 01:06:47 +0000150 sqliteVdbeAddOp(v, OP_Clear, pIdx->tnum, pTab->isTemp);
drhcce7d172000-05-31 15:34:51 +0000151 }
152 }
drh0353ced2001-03-20 22:05:00 +0000153
154 /* The usual case: There is a WHERE clause so we have to scan through
155 ** the table an pick which records to delete.
156 */
157 else{
158 /* Begin the database scan
159 */
drh832508b2002-03-02 17:04:07 +0000160 pWInfo = sqliteWhereBegin(pParse, base, pTabList, pWhere, 1);
drh0353ced2001-03-20 22:05:00 +0000161 if( pWInfo==0 ) goto delete_from_cleanup;
162
163 /* Remember the key of every item to be deleted.
164 */
drh99fcd712001-10-13 01:06:47 +0000165 sqliteVdbeAddOp(v, OP_ListWrite, 0, 0);
drh1bee3d72001-10-15 00:44:35 +0000166 if( db->flags & SQLITE_CountRows ){
167 sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
168 }
drh0353ced2001-03-20 22:05:00 +0000169
170 /* End the database scan loop.
171 */
172 sqliteWhereEnd(pWInfo);
173
174 /* Delete every item whose key was written to the list during the
175 ** database scan. We have to delete items after the scan is complete
176 ** because deleting an item can change the scan order.
177 */
drh99fcd712001-10-13 01:06:47 +0000178 sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
drhf57b3392001-10-08 13:22:32 +0000179 openOp = pTab->isTemp ? OP_OpenWrAux : OP_OpenWrite;
drh99fcd712001-10-13 01:06:47 +0000180 sqliteVdbeAddOp(v, openOp, base, pTab->tnum);
drh0353ced2001-03-20 22:05:00 +0000181 for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
drh99fcd712001-10-13 01:06:47 +0000182 sqliteVdbeAddOp(v, openOp, base+i, pIdx->tnum);
drh0353ced2001-03-20 22:05:00 +0000183 }
184 end = sqliteVdbeMakeLabel(v);
drh99fcd712001-10-13 01:06:47 +0000185 addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);
drhc8d30ac2002-04-12 10:08:59 +0000186 sqliteGenerateRowDelete(v, pTab, base, 1);
drh99fcd712001-10-13 01:06:47 +0000187 sqliteVdbeAddOp(v, OP_Goto, 0, addr);
188 sqliteVdbeResolveLabel(v, end);
drha8b38d22001-11-01 14:41:34 +0000189 sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
drh0353ced2001-03-20 22:05:00 +0000190 }
drh1c928532002-01-31 15:54:21 +0000191 sqliteEndWriteOperation(pParse);
drh5e00f6c2001-09-13 13:46:56 +0000192
drh1bee3d72001-10-15 00:44:35 +0000193 /*
194 ** Return the number of rows that were deleted.
195 */
196 if( db->flags & SQLITE_CountRows ){
197 sqliteVdbeAddOp(v, OP_ColumnCount, 1, 0);
198 sqliteVdbeAddOp(v, OP_ColumnName, 0, 0);
199 sqliteVdbeChangeP3(v, -1, "rows deleted", P3_STATIC);
200 sqliteVdbeAddOp(v, OP_Callback, 1, 0);
201 }
drhcce7d172000-05-31 15:34:51 +0000202
203delete_from_cleanup:
204 sqliteIdListDelete(pTabList);
205 sqliteExprDelete(pWhere);
206 return;
207}
drh9cfcf5d2002-01-29 18:41:24 +0000208
209/*
210** This routine generates VDBE code that causes a single row of a
211** single table to be deleted.
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 record number of the row to be deleted must be on the top
223** of the stack.
224**
225** This routine pops the top of the stack to remove the record number
226** and then generates code to remove both the table record and all index
227** entries that point to that record.
228*/
229void sqliteGenerateRowDelete(
230 Vdbe *v, /* Generate code into this VDBE */
231 Table *pTab, /* Table containing the row to be deleted */
drhc8d30ac2002-04-12 10:08:59 +0000232 int base, /* Cursor number for the table */
233 int count /* Increment the row change counter */
drh9cfcf5d2002-01-29 18:41:24 +0000234){
drh0ca3e242002-01-29 23:07:02 +0000235 sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
236 sqliteGenerateRowIndexDelete(v, pTab, base, 0);
drhc8d30ac2002-04-12 10:08:59 +0000237 sqliteVdbeAddOp(v, OP_Delete, base, count);
drh0ca3e242002-01-29 23:07:02 +0000238}
239
240/*
241** This routine generates VDBE code that causes the deletion of all
242** index entries associated with a single row of a single table.
243**
244** The VDBE must be in a particular state when this routine is called.
245** These are the requirements:
246**
247** 1. A read/write cursor pointing to pTab, the table containing the row
248** to be deleted, must be opened as cursor number "base".
249**
250** 2. Read/write cursors for all indices of pTab must be open as
251** cursor number base+i for the i-th index.
252**
253** 3. The "base" cursor must be pointing to the row that is to be
254** deleted.
255*/
256void sqliteGenerateRowIndexDelete(
257 Vdbe *v, /* Generate code into this VDBE */
258 Table *pTab, /* Table containing the row to be deleted */
259 int base, /* Cursor number for the table */
260 char *aIdxUsed /* Only delete if aIdxUsed!=0 && aIdxUsed[i]!=0 */
261){
drh9cfcf5d2002-01-29 18:41:24 +0000262 int i;
263 Index *pIdx;
264
drh0ca3e242002-01-29 23:07:02 +0000265 for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
266 int j;
267 if( aIdxUsed!=0 && aIdxUsed[i-1]==0 ) continue;
268 sqliteVdbeAddOp(v, OP_Recno, base, 0);
269 for(j=0; j<pIdx->nColumn; j++){
270 int idx = pIdx->aiColumn[j];
271 if( idx==pTab->iPKey ){
272 sqliteVdbeAddOp(v, OP_Dup, j, 0);
273 }else{
274 sqliteVdbeAddOp(v, OP_Column, base, idx);
drh9cfcf5d2002-01-29 18:41:24 +0000275 }
drh9cfcf5d2002-01-29 18:41:24 +0000276 }
drh0ca3e242002-01-29 23:07:02 +0000277 sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
278 sqliteVdbeAddOp(v, OP_IdxDelete, base+i, 0);
drh9cfcf5d2002-01-29 18:41:24 +0000279 }
drh9cfcf5d2002-01-29 18:41:24 +0000280}