12
12
** This file contains C code routines that are called by the parser
13
13
** to handle UPDATE statements.
15
** $Id: update.c,v 1.123 2006/02/24 02:53:50 drh Exp $
15
** $Id: update.c,v 1.133 2006/06/27 13:20:21 drh Exp $
17
17
#include "sqliteInt.h"
19
#ifndef SQLITE_OMIT_VIRTUALTABLE
20
/* Forward declaration */
21
static void updateVirtualTable(
22
Parse *pParse, /* The parsing context */
23
SrcList *pSrc, /* The virtual table to be modified */
24
Table *pTab, /* The virtual table */
25
ExprList *pChanges, /* The columns to change in the UPDATE statement */
26
Expr *pRowidExpr, /* Expression used to recompute the rowid */
27
int *aXRef, /* Mapping from columns of pTab to entries in pChanges */
28
Expr *pWhere /* WHERE clause of the UPDATE statement */
30
#endif /* SQLITE_OMIT_VIRTUALTABLE */
20
33
** The most recently coded instruction was an OP_Column to retrieve the
21
34
** i-th column of table pTab. This routine sets the P3 parameter of the
255
284
sqlite3AuthContextPush(pParse, &sContext, pTab->zName);
258
/* Begin generating code.
260
v = sqlite3GetVdbe(pParse);
261
if( v==0 ) goto update_cleanup;
262
if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
263
sqlite3BeginWriteOperation(pParse, 1, iDb);
265
287
/* If we are trying to update a view, realize that view into
266
288
** a ephemeral table.
270
292
pView = sqlite3SelectDup(pTab->pSelect);
271
sqlite3Select(pParse, pView, SRT_VirtualTab, iCur, 0, 0, 0, 0);
293
sqlite3Select(pParse, pView, SRT_EphemTab, iCur, 0, 0, 0, 0);
272
294
sqlite3SelectDelete(pView);
506
528
sqlite3ExprDelete(pWhere);
532
#ifndef SQLITE_OMIT_VIRTUALTABLE
534
** Generate code for an UPDATE of a virtual table.
536
** The strategy is that we create an ephemerial table that contains
537
** for each row to be changed:
539
** (A) The original rowid of that row.
540
** (B) The revised rowid for the row. (note1)
541
** (C) The content of every column in the row.
543
** Then we loop over this ephemeral table and for each row in
544
** the ephermeral table call VUpdate.
546
** When finished, drop the ephemeral table.
548
** (note1) Actually, if we know in advance that (A) is always the same
549
** as (B) we only store (A), then duplicate (A) when pulling
550
** it out of the ephemeral table before calling VUpdate.
552
static void updateVirtualTable(
553
Parse *pParse, /* The parsing context */
554
SrcList *pSrc, /* The virtual table to be modified */
555
Table *pTab, /* The virtual table */
556
ExprList *pChanges, /* The columns to change in the UPDATE statement */
557
Expr *pRowid, /* Expression used to recompute the rowid */
558
int *aXRef, /* Mapping from columns of pTab to entries in pChanges */
559
Expr *pWhere /* WHERE clause of the UPDATE statement */
561
Vdbe *v = pParse->pVdbe; /* Virtual machine under construction */
562
ExprList *pEList = 0; /* The result set of the SELECT statement */
563
Select *pSelect = 0; /* The SELECT statement */
564
Expr *pExpr; /* Temporary expression */
565
int ephemTab; /* Table holding the result of the SELECT */
566
int i; /* Loop counter */
567
int addr; /* Address of top of loop */
569
/* Construct the SELECT statement that will find the new values for
572
pEList = sqlite3ExprListAppend(0, sqlite3CreateIdExpr("_rowid_"), 0);
574
pEList = sqlite3ExprListAppend(pEList, sqlite3ExprDup(pRowid), 0);
576
assert( pTab->iPKey<0 );
577
for(i=0; i<pTab->nCol; i++){
579
pExpr = sqlite3ExprDup(pChanges->a[aXRef[i]].pExpr);
581
pExpr = sqlite3CreateIdExpr(pTab->aCol[i].zName);
583
pEList = sqlite3ExprListAppend(pEList, pExpr, 0);
585
pSelect = sqlite3SelectNew(pEList, pSrc, pWhere, 0, 0, 0, 0, 0, 0);
587
/* Create the ephemeral table into which the update results will
591
ephemTab = pParse->nTab++;
592
sqlite3VdbeAddOp(v, OP_OpenEphemeral, ephemTab, pTab->nCol+1+(pRowid!=0));
594
/* fill the ephemeral table
596
sqlite3Select(pParse, pSelect, SRT_Table, ephemTab, 0, 0, 0, 0);
599
** Generate code to scan the ephemeral table and call VDelete and
602
sqlite3VdbeAddOp(v, OP_Rewind, ephemTab, 0);
603
addr = sqlite3VdbeCurrentAddr(v);
604
sqlite3VdbeAddOp(v, OP_Column, ephemTab, 0);
606
sqlite3VdbeAddOp(v, OP_Column, ephemTab, 1);
608
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
610
for(i=0; i<pTab->nCol; i++){
611
sqlite3VdbeAddOp(v, OP_Column, ephemTab, i+1+(pRowid!=0));
613
pParse->pVirtualLock = pTab;
614
sqlite3VdbeOp3(v, OP_VUpdate, 0, pTab->nCol+2,
615
(const char*)pTab->pVtab, P3_VTAB);
616
sqlite3VdbeAddOp(v, OP_Next, ephemTab, addr);
617
sqlite3VdbeAddOp(v, OP_Close, ephemTab, 0);
620
sqlite3SelectDelete(pSelect);
622
#endif /* SQLITE_OMIT_VIRTUALTABLE */