~ubuntu-branches/ubuntu/hardy/sqlite3/hardy

« back to all changes in this revision

Viewing changes to src/update.c

  • Committer: Bazaar Package Importer
  • Author(s): Laszlo Boszormenyi (GCS)
  • Date: 2006-10-12 21:55:37 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20061012215537-mgvrxoq8ee4nqxzh
Tags: 3.3.8-1
* New upstream version.
* Create lang_* files for documentation (closes: #310603).
* Enable column metadata functions (closes: #375352).

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
** This file contains C code routines that are called by the parser
13
13
** to handle UPDATE statements.
14
14
**
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 $
16
16
*/
17
17
#include "sqliteInt.h"
18
18
 
 
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 */
 
29
);
 
30
#endif /* SQLITE_OMIT_VIRTUALTABLE */
 
31
 
19
32
/*
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 
130
143
  if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){
131
144
    goto update_cleanup;
132
145
  }
133
 
  if( isView ){
134
 
    if( sqlite3ViewGetColumnNames(pParse, pTab) ){
135
 
      goto update_cleanup;
136
 
    }
 
146
  if( sqlite3ViewGetColumnNames(pParse, pTab) ){
 
147
    goto update_cleanup;
137
148
  }
138
149
  aXRef = sqliteMallocRaw( sizeof(int) * pTab->nCol );
139
150
  if( aXRef==0 ) goto update_cleanup;
242
253
    }
243
254
  }
244
255
 
 
256
  /* Begin generating code.
 
257
  */
 
258
  v = sqlite3GetVdbe(pParse);
 
259
  if( v==0 ) goto update_cleanup;
 
260
  if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
 
261
  sqlite3BeginWriteOperation(pParse, 1, iDb);
 
262
 
 
263
#ifndef SQLITE_OMIT_VIRTUALTABLE
 
264
  /* Virtual tables must be handled separately */
 
265
  if( IsVirtual(pTab) ){
 
266
    updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef,
 
267
                       pWhere);
 
268
    pWhere = 0;
 
269
    pTabList = 0;
 
270
    goto update_cleanup;
 
271
  }
 
272
#endif
 
273
 
245
274
  /* Resolve the column names in all the expressions in the
246
275
  ** WHERE clause.
247
276
  */
255
284
    sqlite3AuthContextPush(pParse, &sContext, pTab->zName);
256
285
  }
257
286
 
258
 
  /* Begin generating code.
259
 
  */
260
 
  v = sqlite3GetVdbe(pParse);
261
 
  if( v==0 ) goto update_cleanup;
262
 
  if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
263
 
  sqlite3BeginWriteOperation(pParse, 1, iDb);
264
 
 
265
287
  /* If we are trying to update a view, realize that view into
266
288
  ** a ephemeral table.
267
289
  */
268
290
  if( isView ){
269
291
    Select *pView;
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);
273
295
  }
274
296
 
277
299
  pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0);
278
300
  if( pWInfo==0 ) goto update_cleanup;
279
301
 
280
 
  /* Remember the index of every item to be updated.
 
302
  /* Remember the rowid of every item to be updated.
281
303
  */
282
 
  sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
 
304
  sqlite3VdbeAddOp(v, IsVirtual(pTab) ? OP_VRowid : OP_Rowid, iCur, 0);
283
305
  sqlite3VdbeAddOp(v, OP_FifoWrite, 0, 0);
284
306
 
285
307
  /* End the database scan loop.
358
380
    }
359
381
  }
360
382
 
361
 
  if( !isView ){
 
383
  if( !isView && !IsVirtual(pTab) ){
362
384
    /* 
363
385
    ** Open every index that needs updating.  Note that if any
364
386
    ** index could potentially invoke a REPLACE conflict resolution 
390
412
    /* Loop over every record that needs updating.  We have to load
391
413
    ** the old data for each record to be updated because some columns
392
414
    ** might not change and we will need to copy the old value.
393
 
    ** Also, the old data is needed to delete the old index entires.
 
415
    ** Also, the old data is needed to delete the old index entries.
394
416
    ** So make the cursor point at the old record.
395
417
    */
396
418
    if( !triggers_exist ){
506
528
  sqlite3ExprDelete(pWhere);
507
529
  return;
508
530
}
 
531
 
 
532
#ifndef SQLITE_OMIT_VIRTUALTABLE
 
533
/*
 
534
** Generate code for an UPDATE of a virtual table.
 
535
**
 
536
** The strategy is that we create an ephemerial table that contains
 
537
** for each row to be changed:
 
538
**
 
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.
 
542
**
 
543
** Then we loop over this ephemeral table and for each row in
 
544
** the ephermeral table call VUpdate.
 
545
**
 
546
** When finished, drop the ephemeral table.
 
547
**
 
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.
 
551
*/
 
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 */
 
560
){
 
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 */
 
568
 
 
569
  /* Construct the SELECT statement that will find the new values for
 
570
  ** all updated rows. 
 
571
  */
 
572
  pEList = sqlite3ExprListAppend(0, sqlite3CreateIdExpr("_rowid_"), 0);
 
573
  if( pRowid ){
 
574
    pEList = sqlite3ExprListAppend(pEList, sqlite3ExprDup(pRowid), 0);
 
575
  }
 
576
  assert( pTab->iPKey<0 );
 
577
  for(i=0; i<pTab->nCol; i++){
 
578
    if( aXRef[i]>=0 ){
 
579
      pExpr = sqlite3ExprDup(pChanges->a[aXRef[i]].pExpr);
 
580
    }else{
 
581
      pExpr = sqlite3CreateIdExpr(pTab->aCol[i].zName);
 
582
    }
 
583
    pEList = sqlite3ExprListAppend(pEList, pExpr, 0);
 
584
  }
 
585
  pSelect = sqlite3SelectNew(pEList, pSrc, pWhere, 0, 0, 0, 0, 0, 0);
 
586
  
 
587
  /* Create the ephemeral table into which the update results will
 
588
  ** be stored.
 
589
  */
 
590
  assert( v );
 
591
  ephemTab = pParse->nTab++;
 
592
  sqlite3VdbeAddOp(v, OP_OpenEphemeral, ephemTab, pTab->nCol+1+(pRowid!=0));
 
593
 
 
594
  /* fill the ephemeral table 
 
595
  */
 
596
  sqlite3Select(pParse, pSelect, SRT_Table, ephemTab, 0, 0, 0, 0);
 
597
 
 
598
  /*
 
599
  ** Generate code to scan the ephemeral table and call VDelete and
 
600
  ** VInsert
 
601
  */
 
602
  sqlite3VdbeAddOp(v, OP_Rewind, ephemTab, 0);
 
603
  addr = sqlite3VdbeCurrentAddr(v);
 
604
  sqlite3VdbeAddOp(v, OP_Column,  ephemTab, 0);
 
605
  if( pRowid ){
 
606
    sqlite3VdbeAddOp(v, OP_Column, ephemTab, 1);
 
607
  }else{
 
608
    sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
 
609
  }
 
610
  for(i=0; i<pTab->nCol; i++){
 
611
    sqlite3VdbeAddOp(v, OP_Column, ephemTab, i+1+(pRowid!=0));
 
612
  }
 
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);
 
618
 
 
619
  /* Cleanup */
 
620
  sqlite3SelectDelete(pSelect);  
 
621
}
 
622
#endif /* SQLITE_OMIT_VIRTUALTABLE */