#pragma ident "%Z%%M% %I% %E% SMI"
/*
** 2001 September 15
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle DELETE FROM statements.
**
** $Id: delete.c,v 1.61 2004/02/24 01:05:32 drh Exp $
*/
#include "sqliteInt.h"
/*
** Look up every table that is named in pSrc. If any table is not found,
** add an error message to pParse->zErrMsg and return NULL. If all tables
** are found, return a pointer to the last table.
*/
int i;
}
return pTab;
}
/*
** Check to make sure the given table is writable. If it is not
** writable, generate an error message and return 1. If it is
** writable return 0;
*/
return 1;
}
return 1;
}
return 0;
}
/*
** Process a DELETE FROM statement.
*/
void sqliteDeleteFrom(
){
Vdbe *v; /* The virtual database engine */
int i; /* Loop counter */
pTabList = 0;
goto delete_from_cleanup;
}
/* Locate the table which we want to delete. This table has to be
** put in an SrcList structure because some of the subroutines we
** will be calling are designed to work with multiple tables and expect
** an SrcList* parameter instead of just a Table* parameter.
*/
if( pTab==0 ) goto delete_from_cleanup;
goto delete_from_cleanup;
}
goto delete_from_cleanup;
}
/* If pTab is really a view, make sure it has been initialized.
*/
goto delete_from_cleanup;
}
/* Allocate a cursor used to store the old.* data for a trigger.
*/
if( row_triggers_exist ){
}
/* Resolve the column names in all the expressions.
*/
if( pWhere ){
goto delete_from_cleanup;
}
goto delete_from_cleanup;
}
}
/* Start the view context
*/
if( isView ){
}
/* Begin generating code.
*/
v = sqliteGetVdbe(pParse);
if( v==0 ){
goto delete_from_cleanup;
}
/* If we are trying to delete from a view, construct that view into
** a temporary table.
*/
if( isView ){
}
/* Initialize the counter of the number of rows deleted, if
** we are counting rows.
*/
sqliteVdbeAddOp(v, OP_Integer, 0, 0);
}
/* Special case: A DELETE without a WHERE clause deletes everything.
** It is easier just to erase the whole table. Note, however, that
** this means that the row change count will be incorrect.
*/
if( pWhere==0 && !row_triggers_exist ){
/* If counting rows deleted, just count the total number of
** entries in the table. */
int addr;
if( !isView ){
}
}
if( !isView ){
}
}
}
/* The usual case: There is a WHERE clause so we have to scan through
** the table and pick which records to delete.
*/
else{
/* Begin the database scan
*/
if( pWInfo==0 ) goto delete_from_cleanup;
/* Remember the key of every item to be deleted.
*/
sqliteVdbeAddOp(v, OP_ListWrite, 0, 0);
}
/* End the database scan loop.
*/
/* Open the pseudo-table used to store OLD if there are triggers.
*/
if( row_triggers_exist ){
}
/* Delete every item whose key was written to the list during the
** database scan. We have to delete items after the scan is complete
** because deleting an item can change the scan order.
*/
sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
end = sqliteVdbeMakeLabel(v);
/* This is the beginning of the delete loop when there are
** row triggers.
*/
if( row_triggers_exist ){
sqliteVdbeAddOp(v, OP_Dup, 0, 0);
if( !isView ){
}
if( !isView ){
}
addr);
}
if( !isView ){
/* Open cursors for the table we are deleting from and all its
** indices. If there are row triggers, this happens inside the
** OP_ListRead loop because the cursor have to all be closed
** before the trigger fires. If there are no row triggers, the
** cursors are opened only once on the outside the loop.
*/
/* This is the beginning of the delete loop when there are no
** row triggers */
if( !row_triggers_exist ){
}
/* Delete the row */
}
/* If there are row triggers, close all cursors then invoke
** the AFTER triggers
*/
if( row_triggers_exist ){
if( !isView ){
}
}
addr);
}
/* End of the delete loop */
sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
/* Close the cursors after the loop if there are no row triggers */
if( !row_triggers_exist ){
}
}
}
sqliteVdbeAddOp(v, OP_SetCounts, 0, 0);
/*
** Return the number of rows that were deleted.
*/
}
return;
}
/*
** This routine generates VDBE code that causes a single row of a
** single table to be deleted.
**
** The VDBE must be in a particular state when this routine is called.
** These are the requirements:
**
** to be deleted, must be opened as cursor number "base".
**
** cursor number base+i for the i-th index.
**
** 3. The record number of the row to be deleted must be on the top
** of the stack.
**
** This routine pops the top of the stack to remove the record number
** and then generates code to remove both the table record and all index
** entries that point to that record.
*/
void sqliteGenerateRowDelete(
Vdbe *v, /* Generate code into this VDBE */
int iCur, /* Cursor number for the table */
int count /* Increment the row change counter */
){
int addr;
}
/*
** This routine generates VDBE code that causes the deletion of all
** index entries associated with a single row of a single table.
**
** The VDBE must be in a particular state when this routine is called.
** These are the requirements:
**
** to be deleted, must be opened as cursor number "iCur".
**
** cursor number iCur+i for the i-th index.
**
** 3. The "iCur" cursor must be pointing to the row that is to be
** deleted.
*/
Vdbe *v, /* Generate code into this VDBE */
int iCur, /* Cursor number for the table */
char *aIdxUsed /* Only delete if aIdxUsed!=0 && aIdxUsed[i]!=0 */
){
int i;
int j;
sqliteVdbeAddOp(v, OP_Dup, j, 0);
}else{
}
}
}
}