extensions/sqlite/sqlite-source/delete.c
author Scott Ehlert <ds@alliedmods.net>
Sun Mar 30 07:00:22 2008 +0000 (2008-03-30)
changeset 1952 b7aa2b626807
permissions -rw-r--r--
Spring Cleaning, Part Ichi (1)
Various minor things done to project files
Updated sample extension project file and updated makefile to the new unified version (more changes likely on the way)
Updated regex project file and makefile
ds@1952
     1
/*
ds@1952
     2
** 2001 September 15
ds@1952
     3
**
ds@1952
     4
** The author disclaims copyright to this source code.  In place of
ds@1952
     5
** a legal notice, here is a blessing:
ds@1952
     6
**
ds@1952
     7
**    May you do good and not evil.
ds@1952
     8
**    May you find forgiveness for yourself and forgive others.
ds@1952
     9
**    May you share freely, never taking more than you give.
ds@1952
    10
**
ds@1952
    11
*************************************************************************
ds@1952
    12
** This file contains C code routines that are called by the parser
ds@1952
    13
** in order to generate code for DELETE FROM statements.
ds@1952
    14
**
ds@1952
    15
** $Id$
ds@1952
    16
*/
ds@1952
    17
#include "sqliteInt.h"
ds@1952
    18
ds@1952
    19
/*
ds@1952
    20
** Look up every table that is named in pSrc.  If any table is not found,
ds@1952
    21
** add an error message to pParse->zErrMsg and return NULL.  If all tables
ds@1952
    22
** are found, return a pointer to the last table.
ds@1952
    23
*/
ds@1952
    24
Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
ds@1952
    25
  Table *pTab = 0;
ds@1952
    26
  int i;
ds@1952
    27
  struct SrcList_item *pItem;
ds@1952
    28
  for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){
ds@1952
    29
    pTab = sqlite3LocateTable(pParse, pItem->zName, pItem->zDatabase);
ds@1952
    30
    sqlite3DeleteTable(pItem->pTab);
ds@1952
    31
    pItem->pTab = pTab;
ds@1952
    32
    if( pTab ){
ds@1952
    33
      pTab->nRef++;
ds@1952
    34
    }
ds@1952
    35
  }
ds@1952
    36
  return pTab;
ds@1952
    37
}
ds@1952
    38
ds@1952
    39
/*
ds@1952
    40
** Check to make sure the given table is writable.  If it is not
ds@1952
    41
** writable, generate an error message and return 1.  If it is
ds@1952
    42
** writable return 0;
ds@1952
    43
*/
ds@1952
    44
int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
ds@1952
    45
  if( (pTab->readOnly && (pParse->db->flags & SQLITE_WriteSchema)==0
ds@1952
    46
        && pParse->nested==0) 
ds@1952
    47
#ifndef SQLITE_OMIT_VIRTUALTABLE
ds@1952
    48
      || (pTab->pMod && pTab->pMod->pModule->xUpdate==0)
ds@1952
    49
#endif
ds@1952
    50
  ){
ds@1952
    51
    sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName);
ds@1952
    52
    return 1;
ds@1952
    53
  }
ds@1952
    54
#ifndef SQLITE_OMIT_VIEW
ds@1952
    55
  if( !viewOk && pTab->pSelect ){
ds@1952
    56
    sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName);
ds@1952
    57
    return 1;
ds@1952
    58
  }
ds@1952
    59
#endif
ds@1952
    60
  return 0;
ds@1952
    61
}
ds@1952
    62
ds@1952
    63
/*
ds@1952
    64
** Generate code that will open a table for reading.
ds@1952
    65
*/
ds@1952
    66
void sqlite3OpenTable(
ds@1952
    67
  Parse *p,       /* Generate code into this VDBE */
ds@1952
    68
  int iCur,       /* The cursor number of the table */
ds@1952
    69
  int iDb,        /* The database index in sqlite3.aDb[] */
ds@1952
    70
  Table *pTab,    /* The table to be opened */
ds@1952
    71
  int opcode      /* OP_OpenRead or OP_OpenWrite */
ds@1952
    72
){
ds@1952
    73
  Vdbe *v;
ds@1952
    74
  if( IsVirtual(pTab) ) return;
ds@1952
    75
  v = sqlite3GetVdbe(p);
ds@1952
    76
  assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );
ds@1952
    77
  sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite), pTab->zName);
ds@1952
    78
  sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
ds@1952
    79
  VdbeComment((v, "# %s", pTab->zName));
ds@1952
    80
  sqlite3VdbeAddOp(v, opcode, iCur, pTab->tnum);
ds@1952
    81
  sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, pTab->nCol);
ds@1952
    82
}
ds@1952
    83
ds@1952
    84
ds@1952
    85
/*
ds@1952
    86
** Generate code for a DELETE FROM statement.
ds@1952
    87
**
ds@1952
    88
**     DELETE FROM table_wxyz WHERE a<5 AND b NOT NULL;
ds@1952
    89
**                 \________/       \________________/
ds@1952
    90
**                  pTabList              pWhere
ds@1952
    91
*/
ds@1952
    92
void sqlite3DeleteFrom(
ds@1952
    93
  Parse *pParse,         /* The parser context */
ds@1952
    94
  SrcList *pTabList,     /* The table from which we should delete things */
ds@1952
    95
  Expr *pWhere           /* The WHERE clause.  May be null */
ds@1952
    96
){
ds@1952
    97
  Vdbe *v;               /* The virtual database engine */
ds@1952
    98
  Table *pTab;           /* The table from which records will be deleted */
ds@1952
    99
  const char *zDb;       /* Name of database holding pTab */
ds@1952
   100
  int end, addr = 0;     /* A couple addresses of generated code */
ds@1952
   101
  int i;                 /* Loop counter */
ds@1952
   102
  WhereInfo *pWInfo;     /* Information about the WHERE clause */
ds@1952
   103
  Index *pIdx;           /* For looping over indices of the table */
ds@1952
   104
  int iCur;              /* VDBE Cursor number for pTab */
ds@1952
   105
  sqlite3 *db;           /* Main database structure */
ds@1952
   106
  AuthContext sContext;  /* Authorization context */
ds@1952
   107
  int oldIdx = -1;       /* Cursor for the OLD table of AFTER triggers */
ds@1952
   108
  NameContext sNC;       /* Name context to resolve expressions in */
ds@1952
   109
  int iDb;               /* Database number */
ds@1952
   110
  int memCnt = 0;        /* Memory cell used for change counting */
ds@1952
   111
ds@1952
   112
#ifndef SQLITE_OMIT_TRIGGER
ds@1952
   113
  int isView;                  /* True if attempting to delete from a view */
ds@1952
   114
  int triggers_exist = 0;      /* True if any triggers exist */
ds@1952
   115
#endif
ds@1952
   116
ds@1952
   117
  sContext.pParse = 0;
ds@1952
   118
  db = pParse->db;
ds@1952
   119
  if( pParse->nErr || db->mallocFailed ){
ds@1952
   120
    goto delete_from_cleanup;
ds@1952
   121
  }
ds@1952
   122
  assert( pTabList->nSrc==1 );
ds@1952
   123
ds@1952
   124
  /* Locate the table which we want to delete.  This table has to be
ds@1952
   125
  ** put in an SrcList structure because some of the subroutines we
ds@1952
   126
  ** will be calling are designed to work with multiple tables and expect
ds@1952
   127
  ** an SrcList* parameter instead of just a Table* parameter.
ds@1952
   128
  */
ds@1952
   129
  pTab = sqlite3SrcListLookup(pParse, pTabList);
ds@1952
   130
  if( pTab==0 )  goto delete_from_cleanup;
ds@1952
   131
ds@1952
   132
  /* Figure out if we have any triggers and if the table being
ds@1952
   133
  ** deleted from is a view
ds@1952
   134
  */
ds@1952
   135
#ifndef SQLITE_OMIT_TRIGGER
ds@1952
   136
  triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0);
ds@1952
   137
  isView = pTab->pSelect!=0;
ds@1952
   138
#else
ds@1952
   139
# define triggers_exist 0
ds@1952
   140
# define isView 0
ds@1952
   141
#endif
ds@1952
   142
#ifdef SQLITE_OMIT_VIEW
ds@1952
   143
# undef isView
ds@1952
   144
# define isView 0
ds@1952
   145
#endif
ds@1952
   146
ds@1952
   147
  if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){
ds@1952
   148
    goto delete_from_cleanup;
ds@1952
   149
  }
ds@1952
   150
  iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
ds@1952
   151
  assert( iDb<db->nDb );
ds@1952
   152
  zDb = db->aDb[iDb].zName;
ds@1952
   153
  if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){
ds@1952
   154
    goto delete_from_cleanup;
ds@1952
   155
  }
ds@1952
   156
ds@1952
   157
  /* If pTab is really a view, make sure it has been initialized.
ds@1952
   158
  */
ds@1952
   159
  if( sqlite3ViewGetColumnNames(pParse, pTab) ){
ds@1952
   160
    goto delete_from_cleanup;
ds@1952
   161
  }
ds@1952
   162
ds@1952
   163
  /* Allocate a cursor used to store the old.* data for a trigger.
ds@1952
   164
  */
ds@1952
   165
  if( triggers_exist ){ 
ds@1952
   166
    oldIdx = pParse->nTab++;
ds@1952
   167
  }
ds@1952
   168
ds@1952
   169
  /* Resolve the column names in the WHERE clause.
ds@1952
   170
  */
ds@1952
   171
  assert( pTabList->nSrc==1 );
ds@1952
   172
  iCur = pTabList->a[0].iCursor = pParse->nTab++;
ds@1952
   173
  memset(&sNC, 0, sizeof(sNC));
ds@1952
   174
  sNC.pParse = pParse;
ds@1952
   175
  sNC.pSrcList = pTabList;
ds@1952
   176
  if( sqlite3ExprResolveNames(&sNC, pWhere) ){
ds@1952
   177
    goto delete_from_cleanup;
ds@1952
   178
  }
ds@1952
   179
ds@1952
   180
  /* Start the view context
ds@1952
   181
  */
ds@1952
   182
  if( isView ){
ds@1952
   183
    sqlite3AuthContextPush(pParse, &sContext, pTab->zName);
ds@1952
   184
  }
ds@1952
   185
ds@1952
   186
  /* Begin generating code.
ds@1952
   187
  */
ds@1952
   188
  v = sqlite3GetVdbe(pParse);
ds@1952
   189
  if( v==0 ){
ds@1952
   190
    goto delete_from_cleanup;
ds@1952
   191
  }
ds@1952
   192
  if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
ds@1952
   193
  sqlite3BeginWriteOperation(pParse, triggers_exist, iDb);
ds@1952
   194
ds@1952
   195
  /* If we are trying to delete from a view, realize that view into
ds@1952
   196
  ** a ephemeral table.
ds@1952
   197
  */
ds@1952
   198
  if( isView ){
ds@1952
   199
    Select *pView = sqlite3SelectDup(db, pTab->pSelect);
ds@1952
   200
    sqlite3Select(pParse, pView, SRT_EphemTab, iCur, 0, 0, 0, 0);
ds@1952
   201
    sqlite3SelectDelete(pView);
ds@1952
   202
  }
ds@1952
   203
ds@1952
   204
  /* Initialize the counter of the number of rows deleted, if
ds@1952
   205
  ** we are counting rows.
ds@1952
   206
  */
ds@1952
   207
  if( db->flags & SQLITE_CountRows ){
ds@1952
   208
    memCnt = pParse->nMem++;
ds@1952
   209
    sqlite3VdbeAddOp(v, OP_MemInt, 0, memCnt);
ds@1952
   210
  }
ds@1952
   211
ds@1952
   212
  /* Special case: A DELETE without a WHERE clause deletes everything.
ds@1952
   213
  ** It is easier just to erase the whole table.  Note, however, that
ds@1952
   214
  ** this means that the row change count will be incorrect.
ds@1952
   215
  */
ds@1952
   216
  if( pWhere==0 && !triggers_exist && !IsVirtual(pTab) ){
ds@1952
   217
    if( db->flags & SQLITE_CountRows ){
ds@1952
   218
      /* If counting rows deleted, just count the total number of
ds@1952
   219
      ** entries in the table. */
ds@1952
   220
      int endOfLoop = sqlite3VdbeMakeLabel(v);
ds@1952
   221
      int addr2;
ds@1952
   222
      if( !isView ){
ds@1952
   223
        sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);
ds@1952
   224
      }
ds@1952
   225
      sqlite3VdbeAddOp(v, OP_Rewind, iCur, sqlite3VdbeCurrentAddr(v)+2);
ds@1952
   226
      addr2 = sqlite3VdbeAddOp(v, OP_MemIncr, 1, memCnt);
ds@1952
   227
      sqlite3VdbeAddOp(v, OP_Next, iCur, addr2);
ds@1952
   228
      sqlite3VdbeResolveLabel(v, endOfLoop);
ds@1952
   229
      sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
ds@1952
   230
    }
ds@1952
   231
    if( !isView ){
ds@1952
   232
      sqlite3VdbeAddOp(v, OP_Clear, pTab->tnum, iDb);
ds@1952
   233
      if( !pParse->nested ){
ds@1952
   234
        sqlite3VdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
ds@1952
   235
      }
ds@1952
   236
      for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
ds@1952
   237
        assert( pIdx->pSchema==pTab->pSchema );
ds@1952
   238
        sqlite3VdbeAddOp(v, OP_Clear, pIdx->tnum, iDb);
ds@1952
   239
      }
ds@1952
   240
    }
ds@1952
   241
  } 
ds@1952
   242
  /* The usual case: There is a WHERE clause so we have to scan through
ds@1952
   243
  ** the table and pick which records to delete.
ds@1952
   244
  */
ds@1952
   245
  else{
ds@1952
   246
    /* Begin the database scan
ds@1952
   247
    */
ds@1952
   248
    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0);
ds@1952
   249
    if( pWInfo==0 ) goto delete_from_cleanup;
ds@1952
   250
ds@1952
   251
    /* Remember the rowid of every item to be deleted.
ds@1952
   252
    */
ds@1952
   253
    sqlite3VdbeAddOp(v, IsVirtual(pTab) ? OP_VRowid : OP_Rowid, iCur, 0);
ds@1952
   254
    sqlite3VdbeAddOp(v, OP_FifoWrite, 0, 0);
ds@1952
   255
    if( db->flags & SQLITE_CountRows ){
ds@1952
   256
      sqlite3VdbeAddOp(v, OP_MemIncr, 1, memCnt);
ds@1952
   257
    }
ds@1952
   258
ds@1952
   259
    /* End the database scan loop.
ds@1952
   260
    */
ds@1952
   261
    sqlite3WhereEnd(pWInfo);
ds@1952
   262
ds@1952
   263
    /* Open the pseudo-table used to store OLD if there are triggers.
ds@1952
   264
    */
ds@1952
   265
    if( triggers_exist ){
ds@1952
   266
      sqlite3VdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
ds@1952
   267
      sqlite3VdbeAddOp(v, OP_SetNumColumns, oldIdx, pTab->nCol);
ds@1952
   268
    }
ds@1952
   269
ds@1952
   270
    /* Delete every item whose key was written to the list during the
ds@1952
   271
    ** database scan.  We have to delete items after the scan is complete
ds@1952
   272
    ** because deleting an item can change the scan order.
ds@1952
   273
    */
ds@1952
   274
    end = sqlite3VdbeMakeLabel(v);
ds@1952
   275
ds@1952
   276
    /* This is the beginning of the delete loop when there are
ds@1952
   277
    ** row triggers.
ds@1952
   278
    */
ds@1952
   279
    if( triggers_exist ){
ds@1952
   280
      addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, end);
ds@1952
   281
      if( !isView ){
ds@1952
   282
        sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
ds@1952
   283
        sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);
ds@1952
   284
      }
ds@1952
   285
      sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
ds@1952
   286
      sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
ds@1952
   287
      sqlite3VdbeAddOp(v, OP_RowData, iCur, 0);
ds@1952
   288
      sqlite3VdbeAddOp(v, OP_Insert, oldIdx, 0);
ds@1952
   289
      if( !isView ){
ds@1952
   290
        sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
ds@1952
   291
      }
ds@1952
   292
ds@1952
   293
      (void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_BEFORE, pTab,
ds@1952
   294
          -1, oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
ds@1952
   295
          addr);
ds@1952
   296
    }
ds@1952
   297
ds@1952
   298
    if( !isView ){
ds@1952
   299
      /* Open cursors for the table we are deleting from and all its
ds@1952
   300
      ** indices.  If there are row triggers, this happens inside the
ds@1952
   301
      ** OP_FifoRead loop because the cursor have to all be closed
ds@1952
   302
      ** before the trigger fires.  If there are no row triggers, the
ds@1952
   303
      ** cursors are opened only once on the outside the loop.
ds@1952
   304
      */
ds@1952
   305
      sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite);
ds@1952
   306
ds@1952
   307
      /* This is the beginning of the delete loop when there are no
ds@1952
   308
      ** row triggers */
ds@1952
   309
      if( !triggers_exist ){ 
ds@1952
   310
        addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, end);
ds@1952
   311
      }
ds@1952
   312
ds@1952
   313
      /* Delete the row */
ds@1952
   314
#ifndef SQLITE_OMIT_VIRTUALTABLE
ds@1952
   315
      if( IsVirtual(pTab) ){
ds@1952
   316
        pParse->pVirtualLock = pTab;
ds@1952
   317
        sqlite3VdbeOp3(v, OP_VUpdate, 0, 1, (const char*)pTab->pVtab, P3_VTAB);
ds@1952
   318
      }else
ds@1952
   319
#endif
ds@1952
   320
      {
ds@1952
   321
        sqlite3GenerateRowDelete(db, v, pTab, iCur, pParse->nested==0);
ds@1952
   322
      }
ds@1952
   323
    }
ds@1952
   324
ds@1952
   325
    /* If there are row triggers, close all cursors then invoke
ds@1952
   326
    ** the AFTER triggers
ds@1952
   327
    */
ds@1952
   328
    if( triggers_exist ){
ds@1952
   329
      if( !isView ){
ds@1952
   330
        for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
ds@1952
   331
          sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
ds@1952
   332
        }
ds@1952
   333
        sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
ds@1952
   334
      }
ds@1952
   335
      (void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_AFTER, pTab, -1,
ds@1952
   336
          oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
ds@1952
   337
          addr);
ds@1952
   338
    }
ds@1952
   339
ds@1952
   340
    /* End of the delete loop */
ds@1952
   341
    sqlite3VdbeAddOp(v, OP_Goto, 0, addr);
ds@1952
   342
    sqlite3VdbeResolveLabel(v, end);
ds@1952
   343
ds@1952
   344
    /* Close the cursors after the loop if there are no row triggers */
ds@1952
   345
    if( !triggers_exist && !IsVirtual(pTab) ){
ds@1952
   346
      for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
ds@1952
   347
        sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
ds@1952
   348
      }
ds@1952
   349
      sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
ds@1952
   350
    }
ds@1952
   351
  }
ds@1952
   352
ds@1952
   353
  /*
ds@1952
   354
  ** Return the number of rows that were deleted. If this routine is 
ds@1952
   355
  ** generating code because of a call to sqlite3NestedParse(), do not
ds@1952
   356
  ** invoke the callback function.
ds@1952
   357
  */
ds@1952
   358
  if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){
ds@1952
   359
    sqlite3VdbeAddOp(v, OP_MemLoad, memCnt, 0);
ds@1952
   360
    sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
ds@1952
   361
    sqlite3VdbeSetNumCols(v, 1);
ds@1952
   362
    sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", P3_STATIC);
ds@1952
   363
  }
ds@1952
   364
ds@1952
   365
delete_from_cleanup:
ds@1952
   366
  sqlite3AuthContextPop(&sContext);
ds@1952
   367
  sqlite3SrcListDelete(pTabList);
ds@1952
   368
  sqlite3ExprDelete(pWhere);
ds@1952
   369
  return;
ds@1952
   370
}
ds@1952
   371
ds@1952
   372
/*
ds@1952
   373
** This routine generates VDBE code that causes a single row of a
ds@1952
   374
** single table to be deleted.
ds@1952
   375
**
ds@1952
   376
** The VDBE must be in a particular state when this routine is called.
ds@1952
   377
** These are the requirements:
ds@1952
   378
**
ds@1952
   379
**   1.  A read/write cursor pointing to pTab, the table containing the row
ds@1952
   380
**       to be deleted, must be opened as cursor number "base".
ds@1952
   381
**
ds@1952
   382
**   2.  Read/write cursors for all indices of pTab must be open as
ds@1952
   383
**       cursor number base+i for the i-th index.
ds@1952
   384
**
ds@1952
   385
**   3.  The record number of the row to be deleted must be on the top
ds@1952
   386
**       of the stack.
ds@1952
   387
**
ds@1952
   388
** This routine pops the top of the stack to remove the record number
ds@1952
   389
** and then generates code to remove both the table record and all index
ds@1952
   390
** entries that point to that record.
ds@1952
   391
*/
ds@1952
   392
void sqlite3GenerateRowDelete(
ds@1952
   393
  sqlite3 *db,       /* The database containing the index */
ds@1952
   394
  Vdbe *v,           /* Generate code into this VDBE */
ds@1952
   395
  Table *pTab,       /* Table containing the row to be deleted */
ds@1952
   396
  int iCur,          /* Cursor number for the table */
ds@1952
   397
  int count          /* Increment the row change counter */
ds@1952
   398
){
ds@1952
   399
  int addr;
ds@1952
   400
  addr = sqlite3VdbeAddOp(v, OP_NotExists, iCur, 0);
ds@1952
   401
  sqlite3GenerateRowIndexDelete(v, pTab, iCur, 0);
ds@1952
   402
  sqlite3VdbeAddOp(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0));
ds@1952
   403
  if( count ){
ds@1952
   404
    sqlite3VdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
ds@1952
   405
  }
ds@1952
   406
  sqlite3VdbeJumpHere(v, addr);
ds@1952
   407
}
ds@1952
   408
ds@1952
   409
/*
ds@1952
   410
** This routine generates VDBE code that causes the deletion of all
ds@1952
   411
** index entries associated with a single row of a single table.
ds@1952
   412
**
ds@1952
   413
** The VDBE must be in a particular state when this routine is called.
ds@1952
   414
** These are the requirements:
ds@1952
   415
**
ds@1952
   416
**   1.  A read/write cursor pointing to pTab, the table containing the row
ds@1952
   417
**       to be deleted, must be opened as cursor number "iCur".
ds@1952
   418
**
ds@1952
   419
**   2.  Read/write cursors for all indices of pTab must be open as
ds@1952
   420
**       cursor number iCur+i for the i-th index.
ds@1952
   421
**
ds@1952
   422
**   3.  The "iCur" cursor must be pointing to the row that is to be
ds@1952
   423
**       deleted.
ds@1952
   424
*/
ds@1952
   425
void sqlite3GenerateRowIndexDelete(
ds@1952
   426
  Vdbe *v,           /* Generate code into this VDBE */
ds@1952
   427
  Table *pTab,       /* Table containing the row to be deleted */
ds@1952
   428
  int iCur,          /* Cursor number for the table */
ds@1952
   429
  char *aIdxUsed     /* Only delete if aIdxUsed!=0 && aIdxUsed[i]!=0 */
ds@1952
   430
){
ds@1952
   431
  int i;
ds@1952
   432
  Index *pIdx;
ds@1952
   433
ds@1952
   434
  for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
ds@1952
   435
    if( aIdxUsed!=0 && aIdxUsed[i-1]==0 ) continue;
ds@1952
   436
    sqlite3GenerateIndexKey(v, pIdx, iCur);
ds@1952
   437
    sqlite3VdbeAddOp(v, OP_IdxDelete, iCur+i, 0);
ds@1952
   438
  }
ds@1952
   439
}
ds@1952
   440
ds@1952
   441
/*
ds@1952
   442
** Generate code that will assemble an index key and put it on the top
ds@1952
   443
** of the tack.  The key with be for index pIdx which is an index on pTab.
ds@1952
   444
** iCur is the index of a cursor open on the pTab table and pointing to
ds@1952
   445
** the entry that needs indexing.
ds@1952
   446
*/
ds@1952
   447
void sqlite3GenerateIndexKey(
ds@1952
   448
  Vdbe *v,           /* Generate code into this VDBE */
ds@1952
   449
  Index *pIdx,       /* The index for which to generate a key */
ds@1952
   450
  int iCur           /* Cursor number for the pIdx->pTable table */
ds@1952
   451
){
ds@1952
   452
  int j;
ds@1952
   453
  Table *pTab = pIdx->pTable;
ds@1952
   454
ds@1952
   455
  sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
ds@1952
   456
  for(j=0; j<pIdx->nColumn; j++){
ds@1952
   457
    int idx = pIdx->aiColumn[j];
ds@1952
   458
    if( idx==pTab->iPKey ){
ds@1952
   459
      sqlite3VdbeAddOp(v, OP_Dup, j, 0);
ds@1952
   460
    }else{
ds@1952
   461
      sqlite3VdbeAddOp(v, OP_Column, iCur, idx);
ds@1952
   462
      sqlite3ColumnDefault(v, pTab, idx);
ds@1952
   463
    }
ds@1952
   464
  }
ds@1952
   465
  sqlite3VdbeAddOp(v, OP_MakeIdxRec, pIdx->nColumn, 0);
ds@1952
   466
  sqlite3IndexAffinityStr(v, pIdx);
ds@1952
   467
}