PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LTP GCOV extension - code coverage report
Current view: directory - pdo_sqlite/sqlite/src - update.c
Test: PHP Code Coverage
Date: 2009-11-19 Instrumented lines: 241
Code covered: 43.2 % Executed lines: 104
Legend: not executed executed

       1                 : /*
       2                 : ** 2001 September 15
       3                 : **
       4                 : ** The author disclaims copyright to this source code.  In place of
       5                 : ** a legal notice, here is a blessing:
       6                 : **
       7                 : **    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.
      10                 : **
      11                 : *************************************************************************
      12                 : ** This file contains C code routines that are called by the parser
      13                 : ** to handle UPDATE statements.
      14                 : **
      15                 : ** $Id$
      16                 : */
      17                 : #include "sqliteInt.h"
      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                 : 
      32                 : /*
      33                 : ** The most recently coded instruction was an OP_Column to retrieve the
      34                 : ** i-th column of table pTab. This routine sets the P3 parameter of the 
      35                 : ** OP_Column to the default value, if any.
      36                 : **
      37                 : ** The default value of a column is specified by a DEFAULT clause in the 
      38                 : ** column definition. This was either supplied by the user when the table
      39                 : ** was created, or added later to the table definition by an ALTER TABLE
      40                 : ** command. If the latter, then the row-records in the table btree on disk
      41                 : ** may not contain a value for the column and the default value, taken
      42                 : ** from the P3 parameter of the OP_Column instruction, is returned instead.
      43                 : ** If the former, then all row-records are guaranteed to include a value
      44                 : ** for the column and the P3 value is not required.
      45                 : **
      46                 : ** Column definitions created by an ALTER TABLE command may only have 
      47                 : ** literal default values specified: a number, null or a string. (If a more
      48                 : ** complicated default expression value was provided, it is evaluated 
      49                 : ** when the ALTER TABLE is executed and one of the literal values written
      50                 : ** into the sqlite_master table.)
      51                 : **
      52                 : ** Therefore, the P3 parameter is only required if the default value for
      53                 : ** the column is a literal number, string or null. The sqlite3ValueFromExpr()
      54                 : ** function is capable of transforming these types of expressions into
      55                 : ** sqlite3_value objects.
      56                 : */
      57             428 : void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i){
      58             428 :   if( pTab && !pTab->pSelect ){
      59                 :     sqlite3_value *pValue;
      60             428 :     u8 enc = ENC(sqlite3VdbeDb(v));
      61             428 :     Column *pCol = &pTab->aCol[i];
      62             428 :     sqlite3ValueFromExpr(pCol->pDflt, enc, pCol->affinity, &pValue);
      63             428 :     if( pValue ){
      64               0 :       sqlite3VdbeChangeP3(v, -1, (const char *)pValue, P3_MEM);
      65                 :     }else{
      66                 :       VdbeComment((v, "# %s.%s", pTab->zName, pCol->zName));
      67                 :     }
      68                 :   }
      69             428 : }
      70                 : 
      71                 : /*
      72                 : ** Process an UPDATE statement.
      73                 : **
      74                 : **   UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
      75                 : **          \_______/ \________/     \______/       \________________/
      76                 : *            onError   pTabList      pChanges             pWhere
      77                 : */
      78                 : void sqlite3Update(
      79                 :   Parse *pParse,         /* The parser context */
      80                 :   SrcList *pTabList,     /* The table in which we should change things */
      81                 :   ExprList *pChanges,    /* Things to be changed */
      82                 :   Expr *pWhere,          /* The WHERE clause.  May be null */
      83                 :   int onError            /* How to handle constraint errors */
      84              64 : ){
      85                 :   int i, j;              /* Loop counters */
      86                 :   Table *pTab;           /* The table to be updated */
      87              64 :   int addr = 0;          /* VDBE instruction address of the start of the loop */
      88                 :   WhereInfo *pWInfo;     /* Information about the WHERE clause */
      89                 :   Vdbe *v;               /* The virtual database engine */
      90                 :   Index *pIdx;           /* For looping over indices */
      91                 :   int nIdx;              /* Number of indices that need updating */
      92                 :   int nIdxTotal;         /* Total number of indices */
      93                 :   int iCur;              /* VDBE Cursor number of pTab */
      94                 :   sqlite3 *db;           /* The database structure */
      95              64 :   Index **apIdx = 0;     /* An array of indices that need updating too */
      96              64 :   char *aIdxUsed = 0;    /* aIdxUsed[i]==1 if the i-th index is used */
      97              64 :   int *aXRef = 0;        /* aXRef[i] is the index in pChanges->a[] of the
      98                 :                          ** an expression for the i-th column of the table.
      99                 :                          ** aXRef[i]==-1 if the i-th column is not changed. */
     100                 :   int chngRowid;         /* True if the record number is being changed */
     101              64 :   Expr *pRowidExpr = 0;  /* Expression defining the new record number */
     102              64 :   int openAll = 0;       /* True if all indices need to be opened */
     103                 :   AuthContext sContext;  /* The authorization context */
     104                 :   NameContext sNC;       /* The name-context to resolve expressions in */
     105                 :   int iDb;               /* Database containing the table being updated */
     106              64 :   int memCnt = 0;        /* Memory cell used for counting rows changed */
     107                 : 
     108                 : #ifndef SQLITE_OMIT_TRIGGER
     109                 :   int isView;                  /* Trying to update a view */
     110              64 :   int triggers_exist = 0;      /* True if any row triggers exist */
     111                 : #endif
     112                 : 
     113              64 :   int newIdx      = -1;  /* index of trigger "new" temp table       */
     114              64 :   int oldIdx      = -1;  /* index of trigger "old" temp table       */
     115                 : 
     116              64 :   sContext.pParse = 0;
     117              64 :   if( pParse->nErr || sqlite3MallocFailed() ){
     118                 :     goto update_cleanup;
     119                 :   }
     120              64 :   db = pParse->db;
     121                 :   assert( pTabList->nSrc==1 );
     122                 : 
     123                 :   /* Locate the table which we want to update. 
     124                 :   */
     125              64 :   pTab = sqlite3SrcListLookup(pParse, pTabList);
     126              64 :   if( pTab==0 ) goto update_cleanup;
     127              63 :   iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
     128                 : 
     129                 :   /* Figure out if we have any triggers and if the table being
     130                 :   ** updated is a view
     131                 :   */
     132                 : #ifndef SQLITE_OMIT_TRIGGER
     133              63 :   triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges);
     134              63 :   isView = pTab->pSelect!=0;
     135                 : #else
     136                 : # define triggers_exist 0
     137                 : # define isView 0
     138                 : #endif
     139                 : #ifdef SQLITE_OMIT_VIEW
     140                 : # undef isView
     141                 : # define isView 0
     142                 : #endif
     143                 : 
     144              63 :   if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){
     145               0 :     goto update_cleanup;
     146                 :   }
     147              63 :   if( sqlite3ViewGetColumnNames(pParse, pTab) ){
     148               0 :     goto update_cleanup;
     149                 :   }
     150              63 :   aXRef = sqliteMallocRaw( sizeof(int) * pTab->nCol );
     151              63 :   if( aXRef==0 ) goto update_cleanup;
     152              63 :   for(i=0; i<pTab->nCol; i++) aXRef[i] = -1;
     153                 : 
     154                 :   /* If there are FOR EACH ROW triggers, allocate cursors for the
     155                 :   ** special OLD and NEW tables
     156                 :   */
     157              63 :   if( triggers_exist ){
     158               0 :     newIdx = pParse->nTab++;
     159               0 :     oldIdx = pParse->nTab++;
     160                 :   }
     161                 : 
     162                 :   /* Allocate a cursors for the main database table and for all indices.
     163                 :   ** The index cursors might not be used, but if they are used they
     164                 :   ** need to occur right after the database cursor.  So go ahead and
     165                 :   ** allocate enough space, just in case.
     166                 :   */
     167              63 :   pTabList->a[0].iCursor = iCur = pParse->nTab++;
     168              63 :   for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
     169               0 :     pParse->nTab++;
     170                 :   }
     171                 : 
     172                 :   /* Initialize the name-context */
     173              63 :   memset(&sNC, 0, sizeof(sNC));
     174              63 :   sNC.pParse = pParse;
     175              63 :   sNC.pSrcList = pTabList;
     176                 : 
     177                 :   /* Resolve the column names in all the expressions of the
     178                 :   ** of the UPDATE statement.  Also find the column index
     179                 :   ** for each column to be updated in the pChanges array.  For each
     180                 :   ** column to be updated, make sure we have authorization to change
     181                 :   ** that column.
     182                 :   */
     183              63 :   chngRowid = 0;
     184             354 :   for(i=0; i<pChanges->nExpr; i++){
     185             291 :     if( sqlite3ExprResolveNames(&sNC, pChanges->a[i].pExpr) ){
     186               0 :       goto update_cleanup;
     187                 :     }
     188             876 :     for(j=0; j<pTab->nCol; j++){
     189             876 :       if( sqlite3StrICmp(pTab->aCol[j].zName, pChanges->a[i].zName)==0 ){
     190             291 :         if( j==pTab->iPKey ){
     191               0 :           chngRowid = 1;
     192               0 :           pRowidExpr = pChanges->a[i].pExpr;
     193                 :         }
     194             291 :         aXRef[j] = i;
     195             291 :         break;
     196                 :       }
     197                 :     }
     198             291 :     if( j>=pTab->nCol ){
     199               0 :       if( sqlite3IsRowid(pChanges->a[i].zName) ){
     200               0 :         chngRowid = 1;
     201               0 :         pRowidExpr = pChanges->a[i].pExpr;
     202                 :       }else{
     203               0 :         sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName);
     204               0 :         goto update_cleanup;
     205                 :       }
     206                 :     }
     207                 : #ifndef SQLITE_OMIT_AUTHORIZATION
     208                 :     {
     209                 :       int rc;
     210             291 :       rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName,
     211                 :                            pTab->aCol[j].zName, db->aDb[iDb].zName);
     212             291 :       if( rc==SQLITE_DENY ){
     213               0 :         goto update_cleanup;
     214             291 :       }else if( rc==SQLITE_IGNORE ){
     215               0 :         aXRef[j] = -1;
     216                 :       }
     217                 :     }
     218                 : #endif
     219                 :   }
     220                 : 
     221                 :   /* Allocate memory for the array apIdx[] and fill it with pointers to every
     222                 :   ** index that needs to be updated.  Indices only need updating if their
     223                 :   ** key includes one of the columns named in pChanges or if the record
     224                 :   ** number of the original table entry is changing.
     225                 :   */
     226              63 :   for(nIdx=nIdxTotal=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdxTotal++){
     227               0 :     if( chngRowid ){
     228               0 :       i = 0;
     229                 :     }else {
     230               0 :       for(i=0; i<pIdx->nColumn; i++){
     231               0 :         if( aXRef[pIdx->aiColumn[i]]>=0 ) break;
     232                 :       }
     233                 :     }
     234               0 :     if( i<pIdx->nColumn ) nIdx++;
     235                 :   }
     236              63 :   if( nIdxTotal>0 ){
     237               0 :     apIdx = sqliteMallocRaw( sizeof(Index*) * nIdx + nIdxTotal );
     238               0 :     if( apIdx==0 ) goto update_cleanup;
     239               0 :     aIdxUsed = (char*)&apIdx[nIdx];
     240                 :   }
     241              63 :   for(nIdx=j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
     242               0 :     if( chngRowid ){
     243               0 :       i = 0;
     244                 :     }else{
     245               0 :       for(i=0; i<pIdx->nColumn; i++){
     246               0 :         if( aXRef[pIdx->aiColumn[i]]>=0 ) break;
     247                 :       }
     248                 :     }
     249               0 :     if( i<pIdx->nColumn ){
     250               0 :       apIdx[nIdx++] = pIdx;
     251               0 :       aIdxUsed[j] = 1;
     252                 :     }else{
     253               0 :       aIdxUsed[j] = 0;
     254                 :     }
     255                 :   }
     256                 : 
     257                 :   /* Begin generating code.
     258                 :   */
     259              63 :   v = sqlite3GetVdbe(pParse);
     260              63 :   if( v==0 ) goto update_cleanup;
     261              63 :   if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
     262              63 :   sqlite3BeginWriteOperation(pParse, 1, iDb);
     263                 : 
     264                 : #ifndef SQLITE_OMIT_VIRTUALTABLE
     265                 :   /* Virtual tables must be handled separately */
     266              63 :   if( IsVirtual(pTab) ){
     267               0 :     updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef,
     268                 :                        pWhere);
     269               0 :     pWhere = 0;
     270               0 :     pTabList = 0;
     271               0 :     goto update_cleanup;
     272                 :   }
     273                 : #endif
     274                 : 
     275                 :   /* Resolve the column names in all the expressions in the
     276                 :   ** WHERE clause.
     277                 :   */
     278              63 :   if( sqlite3ExprResolveNames(&sNC, pWhere) ){
     279               0 :     goto update_cleanup;
     280                 :   }
     281                 : 
     282                 :   /* Start the view context
     283                 :   */
     284              63 :   if( isView ){
     285               0 :     sqlite3AuthContextPush(pParse, &sContext, pTab->zName);
     286                 :   }
     287                 : 
     288                 :   /* If we are trying to update a view, realize that view into
     289                 :   ** a ephemeral table.
     290                 :   */
     291              63 :   if( isView ){
     292                 :     Select *pView;
     293               0 :     pView = sqlite3SelectDup(pTab->pSelect);
     294               0 :     sqlite3Select(pParse, pView, SRT_EphemTab, iCur, 0, 0, 0, 0);
     295               0 :     sqlite3SelectDelete(pView);
     296                 :   }
     297                 : 
     298                 :   /* Begin the database scan
     299                 :   */
     300              63 :   pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0);
     301              63 :   if( pWInfo==0 ) goto update_cleanup;
     302                 : 
     303                 :   /* Remember the rowid of every item to be updated.
     304                 :   */
     305              63 :   sqlite3VdbeAddOp(v, IsVirtual(pTab) ? OP_VRowid : OP_Rowid, iCur, 0);
     306              63 :   sqlite3VdbeAddOp(v, OP_FifoWrite, 0, 0);
     307                 : 
     308                 :   /* End the database scan loop.
     309                 :   */
     310              63 :   sqlite3WhereEnd(pWInfo);
     311                 : 
     312                 :   /* Initialize the count of updated rows
     313                 :   */
     314              63 :   if( db->flags & SQLITE_CountRows && !pParse->trigStack ){
     315               0 :     memCnt = pParse->nMem++;
     316               0 :     sqlite3VdbeAddOp(v, OP_MemInt, 0, memCnt);
     317                 :   }
     318                 : 
     319              63 :   if( triggers_exist ){
     320                 :     /* Create pseudo-tables for NEW and OLD
     321                 :     */
     322               0 :     sqlite3VdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
     323               0 :     sqlite3VdbeAddOp(v, OP_SetNumColumns, oldIdx, pTab->nCol);
     324               0 :     sqlite3VdbeAddOp(v, OP_OpenPseudo, newIdx, 0);
     325               0 :     sqlite3VdbeAddOp(v, OP_SetNumColumns, newIdx, pTab->nCol);
     326                 : 
     327                 :     /* The top of the update loop for when there are triggers.
     328                 :     */
     329               0 :     addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, 0);
     330                 : 
     331               0 :     if( !isView ){
     332               0 :       sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
     333               0 :       sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
     334                 :       /* Open a cursor and make it point to the record that is
     335                 :       ** being updated.
     336                 :       */
     337               0 :       sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);
     338                 :     }
     339               0 :     sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
     340                 : 
     341                 :     /* Generate the OLD table
     342                 :     */
     343               0 :     sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
     344               0 :     sqlite3VdbeAddOp(v, OP_RowData, iCur, 0);
     345               0 :     sqlite3VdbeAddOp(v, OP_Insert, oldIdx, 0);
     346                 : 
     347                 :     /* Generate the NEW table
     348                 :     */
     349               0 :     if( chngRowid ){
     350               0 :       sqlite3ExprCodeAndCache(pParse, pRowidExpr);
     351                 :     }else{
     352               0 :       sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
     353                 :     }
     354               0 :     for(i=0; i<pTab->nCol; i++){
     355               0 :       if( i==pTab->iPKey ){
     356               0 :         sqlite3VdbeAddOp(v, OP_Null, 0, 0);
     357               0 :         continue;
     358                 :       }
     359               0 :       j = aXRef[i];
     360               0 :       if( j<0 ){
     361               0 :         sqlite3VdbeAddOp(v, OP_Column, iCur, i);
     362               0 :         sqlite3ColumnDefault(v, pTab, i);
     363                 :       }else{
     364               0 :         sqlite3ExprCodeAndCache(pParse, pChanges->a[j].pExpr);
     365                 :       }
     366                 :     }
     367               0 :     sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
     368               0 :     if( !isView ){
     369               0 :       sqlite3TableAffinityStr(v, pTab);
     370                 :     }
     371               0 :     if( pParse->nErr ) goto update_cleanup;
     372               0 :     sqlite3VdbeAddOp(v, OP_Insert, newIdx, 0);
     373               0 :     if( !isView ){
     374               0 :       sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
     375                 :     }
     376                 : 
     377                 :     /* Fire the BEFORE and INSTEAD OF triggers
     378                 :     */
     379               0 :     if( sqlite3CodeRowTrigger(pParse, TK_UPDATE, pChanges, TRIGGER_BEFORE, pTab,
     380                 :           newIdx, oldIdx, onError, addr) ){
     381               0 :       goto update_cleanup;
     382                 :     }
     383                 :   }
     384                 : 
     385              63 :   if( !isView && !IsVirtual(pTab) ){
     386                 :     /* 
     387                 :     ** Open every index that needs updating.  Note that if any
     388                 :     ** index could potentially invoke a REPLACE conflict resolution 
     389                 :     ** action, then we need to open all indices because we might need
     390                 :     ** to be deleting some records.
     391                 :     */
     392              63 :     sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite); 
     393              63 :     if( onError==OE_Replace ){
     394               0 :       openAll = 1;
     395                 :     }else{
     396              63 :       openAll = 0;
     397              63 :       for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
     398               0 :         if( pIdx->onError==OE_Replace ){
     399               0 :           openAll = 1;
     400               0 :           break;
     401                 :         }
     402                 :       }
     403                 :     }
     404              63 :     for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
     405               0 :       if( openAll || aIdxUsed[i] ){
     406               0 :         KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
     407               0 :         sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
     408               0 :         sqlite3VdbeOp3(v, OP_OpenWrite, iCur+i+1, pIdx->tnum,
     409                 :                        (char*)pKey, P3_KEYINFO_HANDOFF);
     410                 :         assert( pParse->nTab>iCur+i+1 );
     411                 :       }
     412                 :     }
     413                 : 
     414                 :     /* Loop over every record that needs updating.  We have to load
     415                 :     ** the old data for each record to be updated because some columns
     416                 :     ** might not change and we will need to copy the old value.
     417                 :     ** Also, the old data is needed to delete the old index entries.
     418                 :     ** So make the cursor point at the old record.
     419                 :     */
     420              63 :     if( !triggers_exist ){
     421              63 :       addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, 0);
     422              63 :       sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
     423                 :     }
     424              63 :     sqlite3VdbeAddOp(v, OP_NotExists, iCur, addr);
     425                 : 
     426                 :     /* If the record number will change, push the record number as it
     427                 :     ** will be after the update. (The old record number is currently
     428                 :     ** on top of the stack.)
     429                 :     */
     430              63 :     if( chngRowid ){
     431               0 :       sqlite3ExprCode(pParse, pRowidExpr);
     432               0 :       sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);
     433                 :     }
     434                 : 
     435                 :     /* Compute new data for this record.  
     436                 :     */
     437             374 :     for(i=0; i<pTab->nCol; i++){
     438             311 :       if( i==pTab->iPKey ){
     439               0 :         sqlite3VdbeAddOp(v, OP_Null, 0, 0);
     440               0 :         continue;
     441                 :       }
     442             311 :       j = aXRef[i];
     443             311 :       if( j<0 ){
     444              20 :         sqlite3VdbeAddOp(v, OP_Column, iCur, i);
     445              20 :         sqlite3ColumnDefault(v, pTab, i);
     446                 :       }else{
     447             291 :         sqlite3ExprCode(pParse, pChanges->a[j].pExpr);
     448                 :       }
     449                 :     }
     450                 : 
     451                 :     /* Do constraint checks
     452                 :     */
     453              63 :     sqlite3GenerateConstraintChecks(pParse, pTab, iCur, aIdxUsed, chngRowid, 1,
     454                 :                                    onError, addr);
     455                 : 
     456                 :     /* Delete the old indices for the current record.
     457                 :     */
     458              63 :     sqlite3GenerateRowIndexDelete(v, pTab, iCur, aIdxUsed);
     459                 : 
     460                 :     /* If changing the record number, delete the old record.
     461                 :     */
     462              63 :     if( chngRowid ){
     463               0 :       sqlite3VdbeAddOp(v, OP_Delete, iCur, 0);
     464                 :     }
     465                 : 
     466                 :     /* Create the new index entries and the new record.
     467                 :     */
     468              63 :     sqlite3CompleteInsertion(pParse, pTab, iCur, aIdxUsed, chngRowid, 1, -1, 0);
     469                 :   }
     470                 : 
     471                 :   /* Increment the row counter 
     472                 :   */
     473              63 :   if( db->flags & SQLITE_CountRows && !pParse->trigStack){
     474               0 :     sqlite3VdbeAddOp(v, OP_MemIncr, 1, memCnt);
     475                 :   }
     476                 : 
     477                 :   /* If there are triggers, close all the cursors after each iteration
     478                 :   ** through the loop.  The fire the after triggers.
     479                 :   */
     480              63 :   if( triggers_exist ){
     481               0 :     if( !isView ){
     482               0 :       for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
     483               0 :         if( openAll || aIdxUsed[i] )
     484               0 :           sqlite3VdbeAddOp(v, OP_Close, iCur+i+1, 0);
     485                 :       }
     486               0 :       sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
     487                 :     }
     488               0 :     if( sqlite3CodeRowTrigger(pParse, TK_UPDATE, pChanges, TRIGGER_AFTER, pTab, 
     489                 :           newIdx, oldIdx, onError, addr) ){
     490               0 :       goto update_cleanup;
     491                 :     }
     492                 :   }
     493                 : 
     494                 :   /* Repeat the above with the next record to be updated, until
     495                 :   ** all record selected by the WHERE clause have been updated.
     496                 :   */
     497              63 :   sqlite3VdbeAddOp(v, OP_Goto, 0, addr);
     498              63 :   sqlite3VdbeJumpHere(v, addr);
     499                 : 
     500                 :   /* Close all tables if there were no FOR EACH ROW triggers */
     501              63 :   if( !triggers_exist ){
     502              63 :     for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
     503               0 :       if( openAll || aIdxUsed[i] ){
     504               0 :         sqlite3VdbeAddOp(v, OP_Close, iCur+i+1, 0);
     505                 :       }
     506                 :     }
     507              63 :     sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
     508                 :   }else{
     509               0 :     sqlite3VdbeAddOp(v, OP_Close, newIdx, 0);
     510               0 :     sqlite3VdbeAddOp(v, OP_Close, oldIdx, 0);
     511                 :   }
     512                 : 
     513                 :   /*
     514                 :   ** Return the number of rows that were changed. If this routine is 
     515                 :   ** generating code because of a call to sqlite3NestedParse(), do not
     516                 :   ** invoke the callback function.
     517                 :   */
     518              63 :   if( db->flags & SQLITE_CountRows && !pParse->trigStack && pParse->nested==0 ){
     519               0 :     sqlite3VdbeAddOp(v, OP_MemLoad, memCnt, 0);
     520               0 :     sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
     521               0 :     sqlite3VdbeSetNumCols(v, 1);
     522               0 :     sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", P3_STATIC);
     523                 :   }
     524                 : 
     525              64 : update_cleanup:
     526              64 :   sqlite3AuthContextPop(&sContext);
     527              64 :   sqliteFree(apIdx);
     528              64 :   sqliteFree(aXRef);
     529              64 :   sqlite3SrcListDelete(pTabList);
     530              64 :   sqlite3ExprListDelete(pChanges);
     531              64 :   sqlite3ExprDelete(pWhere);
     532                 :   return;
     533                 : }
     534                 : 
     535                 : #ifndef SQLITE_OMIT_VIRTUALTABLE
     536                 : /*
     537                 : ** Generate code for an UPDATE of a virtual table.
     538                 : **
     539                 : ** The strategy is that we create an ephemerial table that contains
     540                 : ** for each row to be changed:
     541                 : **
     542                 : **   (A)  The original rowid of that row.
     543                 : **   (B)  The revised rowid for the row. (note1)
     544                 : **   (C)  The content of every column in the row.
     545                 : **
     546                 : ** Then we loop over this ephemeral table and for each row in
     547                 : ** the ephermeral table call VUpdate.
     548                 : **
     549                 : ** When finished, drop the ephemeral table.
     550                 : **
     551                 : ** (note1) Actually, if we know in advance that (A) is always the same
     552                 : ** as (B) we only store (A), then duplicate (A) when pulling
     553                 : ** it out of the ephemeral table before calling VUpdate.
     554                 : */
     555                 : static void updateVirtualTable(
     556                 :   Parse *pParse,       /* The parsing context */
     557                 :   SrcList *pSrc,       /* The virtual table to be modified */
     558                 :   Table *pTab,         /* The virtual table */
     559                 :   ExprList *pChanges,  /* The columns to change in the UPDATE statement */
     560                 :   Expr *pRowid,        /* Expression used to recompute the rowid */
     561                 :   int *aXRef,          /* Mapping from columns of pTab to entries in pChanges */
     562                 :   Expr *pWhere         /* WHERE clause of the UPDATE statement */
     563               0 : ){
     564               0 :   Vdbe *v = pParse->pVdbe;  /* Virtual machine under construction */
     565               0 :   ExprList *pEList = 0;     /* The result set of the SELECT statement */
     566               0 :   Select *pSelect = 0;      /* The SELECT statement */
     567                 :   Expr *pExpr;              /* Temporary expression */
     568                 :   int ephemTab;             /* Table holding the result of the SELECT */
     569                 :   int i;                    /* Loop counter */
     570                 :   int addr;                 /* Address of top of loop */
     571                 : 
     572                 :   /* Construct the SELECT statement that will find the new values for
     573                 :   ** all updated rows. 
     574                 :   */
     575               0 :   pEList = sqlite3ExprListAppend(0, sqlite3CreateIdExpr("_rowid_"), 0);
     576               0 :   if( pRowid ){
     577               0 :     pEList = sqlite3ExprListAppend(pEList, sqlite3ExprDup(pRowid), 0);
     578                 :   }
     579                 :   assert( pTab->iPKey<0 );
     580               0 :   for(i=0; i<pTab->nCol; i++){
     581               0 :     if( aXRef[i]>=0 ){
     582               0 :       pExpr = sqlite3ExprDup(pChanges->a[aXRef[i]].pExpr);
     583                 :     }else{
     584               0 :       pExpr = sqlite3CreateIdExpr(pTab->aCol[i].zName);
     585                 :     }
     586               0 :     pEList = sqlite3ExprListAppend(pEList, pExpr, 0);
     587                 :   }
     588               0 :   pSelect = sqlite3SelectNew(pEList, pSrc, pWhere, 0, 0, 0, 0, 0, 0);
     589                 :   
     590                 :   /* Create the ephemeral table into which the update results will
     591                 :   ** be stored.
     592                 :   */
     593                 :   assert( v );
     594               0 :   ephemTab = pParse->nTab++;
     595               0 :   sqlite3VdbeAddOp(v, OP_OpenEphemeral, ephemTab, pTab->nCol+1+(pRowid!=0));
     596                 : 
     597                 :   /* fill the ephemeral table 
     598                 :   */
     599               0 :   sqlite3Select(pParse, pSelect, SRT_Table, ephemTab, 0, 0, 0, 0);
     600                 : 
     601                 :   /*
     602                 :   ** Generate code to scan the ephemeral table and call VDelete and
     603                 :   ** VInsert
     604                 :   */
     605               0 :   sqlite3VdbeAddOp(v, OP_Rewind, ephemTab, 0);
     606               0 :   addr = sqlite3VdbeCurrentAddr(v);
     607               0 :   sqlite3VdbeAddOp(v, OP_Column,  ephemTab, 0);
     608               0 :   if( pRowid ){
     609               0 :     sqlite3VdbeAddOp(v, OP_Column, ephemTab, 1);
     610                 :   }else{
     611               0 :     sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
     612                 :   }
     613               0 :   for(i=0; i<pTab->nCol; i++){
     614               0 :     sqlite3VdbeAddOp(v, OP_Column, ephemTab, i+1+(pRowid!=0));
     615                 :   }
     616               0 :   pParse->pVirtualLock = pTab;
     617               0 :   sqlite3VdbeOp3(v, OP_VUpdate, 0, pTab->nCol+2, 
     618                 :                      (const char*)pTab->pVtab, P3_VTAB);
     619               0 :   sqlite3VdbeAddOp(v, OP_Next, ephemTab, addr);
     620               0 :   sqlite3VdbeJumpHere(v, addr-1);
     621               0 :   sqlite3VdbeAddOp(v, OP_Close, ephemTab, 0);
     622                 : 
     623                 :   /* Cleanup */
     624               0 :   sqlite3SelectDelete(pSelect);  
     625               0 : }
     626                 : #endif /* SQLITE_OMIT_VIRTUALTABLE */

Generated by: LTP GCOV extension version 1.5

Generated at Thu, 19 Nov 2009 08:20:17 +0000 (5 days ago)

Copyright © 2005-2009 The PHP Group
All rights reserved.