/ Check-in [e109b27e]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add support for update statements to sqlite3ota.c.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | ota-update
Files: files | file ages | folders
SHA1: e109b27e4d66b83e1a804e7556d9c91aa37fea28
User & Date: dan 2014-09-08 17:50:35
Context
2014-09-15
10:44
Add OP_Affinity opcodes to the VMs generated by sqlite3_index_writer(). check-in: b9b38cb8 user: dan tags: ota-update
2014-09-08
17:50
Add support for update statements to sqlite3ota.c. check-in: e109b27e user: dan tags: ota-update
2014-09-06
20:19
Add support for delete operations to the ota extension. check-in: f988234b user: dan tags: ota-update
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/ota/ota1.test.

    32     32     return $filename
    33     33   }
    34     34   
    35     35   # Create a simple OTA database. That expects to write to a table:
    36     36   #
    37     37   #   CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
    38     38   #
           39  +# This OTA includes both insert and delete operations.
           40  +#
    39     41   proc create_ota4 {filename} {
    40     42     forcedelete $filename
    41     43     sqlite3 ota1 $filename  
    42     44     ota1 eval {
    43     45       CREATE TABLE data_t1(a, b, c, ota_control);
    44     46       INSERT INTO data_t1 VALUES(1, 2, 3, 0);
    45     47       INSERT INTO data_t1 VALUES(2, NULL, 5, 1);
    46     48       INSERT INTO data_t1 VALUES(3, 8, 9, 0);
    47     49       INSERT INTO data_t1 VALUES(4, NULL, 11, 1);
    48     50     }
    49     51     ota1 close
    50     52     return $filename
    51     53   }
           54  +
           55  +# Create a simple OTA database. That expects to write to a table:
           56  +#
           57  +#   CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d);
           58  +#
           59  +# This OTA includes update statements.
           60  +#
           61  +proc create_ota5 {filename} {
           62  +  forcedelete $filename
           63  +  sqlite3 ota5 $filename  
           64  +  ota5 eval {
           65  +    CREATE TABLE data_t1(a, b, c, d, ota_control);
           66  +    INSERT INTO data_t1 VALUES(1, NULL, NULL, 5, '...x');  -- SET d = 5
           67  +    INSERT INTO data_t1 VALUES(2, NULL, 10, 5, '..xx');    -- SET c=10, d = 5
           68  +    INSERT INTO data_t1 VALUES(3, 11, NULL, NULL, '.x..'); -- SET b=11
           69  +  }
           70  +  ota5 close
           71  +  return $filename
           72  +}
    52     73   
    53     74   # Run the OTA in file $ota on target database $target until completion.
    54     75   #
    55     76   proc run_ota {target ota} {
    56     77     sqlite3ota ota $target $ota
    57     78     while { [ota step]=="SQLITE_OK" } {}
    58     79     ota close
................................................................................
   220    241         6 hello xyz
   221    242       }
   222    243     
   223    244       do_execsql_test 4.$tn2.$tn.3 { PRAGMA integrity_check } ok
   224    245     }
   225    246   }
   226    247   
          248  +#-------------------------------------------------------------------------
          249  +#
          250  +foreach {tn2 cmd} {1 run_ota 2 step_ota} {
          251  +  foreach {tn schema} {
          252  +    1 {
          253  +      CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d);
          254  +    }
          255  +    2 {
          256  +      CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d);
          257  +      CREATE INDEX i1 ON t1(d);
          258  +      CREATE INDEX i2 ON t1(d, c);
          259  +      CREATE INDEX i3 ON t1(d, c, b);
          260  +      CREATE INDEX i4 ON t1(b);
          261  +      CREATE INDEX i5 ON t1(c);
          262  +      CREATE INDEX i6 ON t1(c, b);
          263  +    }
          264  +  } {
          265  +    reset_db
          266  +    execsql $schema
          267  +    execsql {
          268  +      INSERT INTO t1 VALUES(1, 2, 3, 4);
          269  +      INSERT INTO t1 VALUES(2, 5, 6, 7);
          270  +      INSERT INTO t1 VALUES(3, 8, 9, 10);
          271  +    }
          272  +  
          273  +    do_test 5.$tn2.$tn.1 {
          274  +      create_ota5 ota.db
          275  +      $cmd test.db ota.db
          276  +    } {SQLITE_DONE}
          277  +    
          278  +    do_execsql_test 5.$tn2.$tn.2 {
          279  +      SELECT * FROM t1 ORDER BY a ASC;
          280  +    } {
          281  +      1 2 3 5
          282  +      2 5 10 5
          283  +      3 11 9 10
          284  +    }
          285  +  
          286  +    do_execsql_test 5.$tn2.$tn.3 { PRAGMA integrity_check } ok
          287  +  }
          288  +}
   227    289   
   228    290   finish_test
   229    291   

Changes to ext/ota/sqlite3ota.c.

    74     74     int iVisit;                     /* Number of points visited, incl. current */
    75     75   
    76     76     /* Statements created by otaObjIterPrepareAll() */
    77     77     int nCol;                       /* Number of columns in current object */
    78     78     sqlite3_stmt *pSelect;          /* Source data */
    79     79     sqlite3_stmt *pInsert;          /* Statement for INSERT operations */
    80     80     sqlite3_stmt *pDelete;          /* Statement for DELETE ops */
           81  +
           82  +  /* Last UPDATE used (for PK b-tree updates only), or NULL. */
           83  +  char *zMask;                    /* Copy of update mask used with pUpdate */
           84  +  sqlite3_stmt *pUpdate;          /* Last update statement (or NULL) */
    81     85   };
    82     86   
    83     87   /*
    84     88   ** OTA handle.
    85     89   */
    86     90   struct sqlite3ota {
    87     91     sqlite3 *db;                    /* "main" -> target db, "ota" -> ota db */
................................................................................
   175    179       sqlite3_free(pIter->azTblCol[i]);
   176    180     }
   177    181     sqlite3_free(pIter->azTblCol);
   178    182     sqlite3_free(pIter->abTblPk);
   179    183     pIter->azTblCol = 0;
   180    184     pIter->abTblPk = 0;
   181    185     pIter->nTblCol = 0;
          186  +  sqlite3_free(pIter->zMask);
          187  +  pIter->zMask = 0;
          188  +}
          189  +
          190  +/*
          191  +** Finalize all statements and free all allocations that are specific to
          192  +** the current object (table/index pair).
          193  +*/
          194  +static void otaObjIterClearStatements(OtaObjIter *pIter){
          195  +  sqlite3_finalize(pIter->pSelect);
          196  +  sqlite3_finalize(pIter->pInsert);
          197  +  sqlite3_finalize(pIter->pDelete);
          198  +  sqlite3_finalize(pIter->pUpdate);
          199  +  pIter->pSelect = 0;
          200  +  pIter->pInsert = 0;
          201  +  pIter->pDelete = 0;
          202  +  pIter->pUpdate = 0;
          203  +  pIter->nCol = 0;
   182    204   }
   183    205   
   184    206   /*
   185    207   ** Clean up any resources allocated as part of the iterator object passed
   186    208   ** as the only argument.
   187    209   */
   188    210   static void otaObjIterFinalize(OtaObjIter *pIter){
          211  +  otaObjIterClearStatements(pIter);
   189    212     sqlite3_finalize(pIter->pTblIter);
   190    213     sqlite3_finalize(pIter->pIdxIter);
   191         -  sqlite3_finalize(pIter->pSelect);
   192         -  sqlite3_finalize(pIter->pInsert);
   193         -  sqlite3_finalize(pIter->pDelete);
   194    214     otaObjIterFreeCols(pIter);
   195    215     memset(pIter, 0, sizeof(OtaObjIter));
   196    216   }
   197    217   
   198    218   /*
   199    219   ** Advance the iterator to the next position.
   200    220   **
................................................................................
   204    224   ** error code is returned.
   205    225   */
   206    226   static int otaObjIterNext(sqlite3ota *p, OtaObjIter *pIter){
   207    227     int rc = p->rc;
   208    228     if( rc==SQLITE_OK ){
   209    229   
   210    230       /* Free any SQLite statements used while processing the previous object */ 
   211         -    sqlite3_finalize(pIter->pSelect);
   212         -    sqlite3_finalize(pIter->pInsert);
   213         -    sqlite3_finalize(pIter->pDelete);
   214         -    pIter->pSelect = 0;
   215         -    pIter->pInsert = 0;
   216         -    pIter->pDelete = 0;
   217         -    pIter->nCol = 0;
          231  +    otaObjIterClearStatements(pIter);
   218    232   
   219    233       if( pIter->bCleanup ){
   220    234         otaObjIterFreeCols(pIter);
   221    235         pIter->bCleanup = 0;
   222    236         rc = sqlite3_step(pIter->pTblIter);
   223    237         if( rc!=SQLITE_ROW ){
   224    238           rc = sqlite3_reset(pIter->pTblIter);
................................................................................
   408    422       }
   409    423     }
   410    424     return zList;
   411    425   }
   412    426   
   413    427   static char *otaObjIterGetOldlist(
   414    428     sqlite3ota *p, 
   415         -  OtaObjIter *pIter
          429  +  OtaObjIter *pIter,
          430  +  const char *zObj
   416    431   ){
   417    432     char *zList = 0;
   418    433     if( p->rc==SQLITE_OK ){
   419         -    const char *zSep = "";
          434  +    const char *zS = "";
   420    435       int i;
   421    436       for(i=0; i<pIter->nTblCol; i++){
   422         -      zList = sqlite3_mprintf("%z%sold.%s", zList, zSep, pIter->azTblCol[i]);
   423         -      zSep = ", ";
          437  +      zList = sqlite3_mprintf("%z%s%s.%s", zList, zS, zObj, pIter->azTblCol[i]);
          438  +      zS = ", ";
   424    439         if( zList==0 ){
   425    440           p->rc = SQLITE_NOMEM;
   426    441           break;
   427    442         }
   428    443       }
   429    444     }
   430    445     return zList;
................................................................................
   436    451   ){
   437    452     char *zList = 0;
   438    453     if( p->rc==SQLITE_OK ){
   439    454       const char *zSep = "";
   440    455       int i;
   441    456       for(i=0; i<pIter->nTblCol; i++){
   442    457         if( pIter->abTblPk[i] ){
   443         -        zList = sqlite3_mprintf("%z%s%s=?", zList, zSep, pIter->azTblCol[i]);
          458  +        const char *zCol = pIter->azTblCol[i];
          459  +        zList = sqlite3_mprintf("%z%s%s=?%d", zList, zSep, zCol, i+1);
   444    460           zSep = " AND ";
   445    461           if( zList==0 ){
   446    462             p->rc = SQLITE_NOMEM;
   447    463             break;
   448    464           }
   449    465         }
   450    466       }
          467  +  }
          468  +  return zList;
          469  +}
          470  +
          471  +/*
          472  +** The SELECT statement iterating through the keys for the current object
          473  +** (p->objiter.pSelect) currently points to a valid row. However, there
          474  +** is something wrong with the ota_control value in the ota_control value
          475  +** stored in the (p->nCol+1)'th column. Set the error code and error message
          476  +** of the OTA handle to something reflecting this.
          477  +*/
          478  +static void otaBadControlError(sqlite3ota *p){
          479  +  p->rc = SQLITE_ERROR;
          480  +  p->zErrmsg = sqlite3_mprintf("Invalid ota_control value");
          481  +}
          482  +
          483  +static char *otaObjIterGetSetlist(
          484  +  sqlite3ota *p,
          485  +  OtaObjIter *pIter,
          486  +  const char *zMask
          487  +){
          488  +  char *zList = 0;
          489  +  if( p->rc==SQLITE_OK ){
          490  +    int i;
          491  +
          492  +    if( strlen(zMask)!=pIter->nTblCol ){
          493  +      otaBadControlError(p);
          494  +    }else{
          495  +      const char *zSep = "";
          496  +      for(i=0; i<pIter->nTblCol; i++){
          497  +        if( zMask[i]=='x' ){
          498  +          zList = sqlite3_mprintf("%z%s%s=?%d", 
          499  +              zList, zSep, pIter->azTblCol[i], i+1
          500  +          );
          501  +          zSep = ", ";
          502  +        }
          503  +      }
          504  +    }
   451    505     }
   452    506     return zList;
   453    507   }
   454    508   
   455    509   static char *otaObjIterGetBindlist(sqlite3ota *p, int nBind){
   456    510     char *zRet = 0;
   457    511     if( p->rc==SQLITE_OK ){
................................................................................
   509    563   
   510    564         /* Create the SELECT statement to read keys in sorted order */
   511    565         zCollist = otaObjIterGetCollist(p, pIter, pIter->nCol, aiCol);
   512    566         if( p->rc==SQLITE_OK ){
   513    567           p->rc = prepareFreeAndCollectError(p->db, &pIter->pSelect, pz,
   514    568               sqlite3_mprintf(
   515    569                 "SELECT %s, ota_control FROM ota.'data_%q' "
          570  +              "WHERE typeof(ota_control)='integer' AND ota_control!=1 "
   516    571                   "UNION ALL "
   517    572                 "SELECT %s, ota_control FROM ota.'ota_tmp_%q' "
   518    573                 "ORDER BY %s%s",
   519    574                 zCollist, pIter->zTbl, 
   520    575                 zCollist, pIter->zTbl, 
   521    576                 zCollist, zLimit
   522    577               )
   523    578           );
   524    579         }
   525    580       }else{
   526    581         char *zBindings = otaObjIterGetBindlist(p, pIter->nTblCol);
   527    582         char *zWhere = otaObjIterGetWhere(p, pIter);
   528         -      char *zOldlist = otaObjIterGetOldlist(p, pIter);
          583  +      char *zOldlist = otaObjIterGetOldlist(p, pIter, "old");
          584  +      char *zNewlist = otaObjIterGetOldlist(p, pIter, "new");
   529    585         zCollist = otaObjIterGetCollist(p, pIter, pIter->nTblCol, 0);
   530    586         pIter->nCol = pIter->nTblCol;
   531    587   
   532    588         /* Create the SELECT statement to read keys from data_xxx */
   533    589         if( p->rc==SQLITE_OK ){
   534    590           p->rc = prepareFreeAndCollectError(p->db, &pIter->pSelect, pz,
   535    591               sqlite3_mprintf(
................................................................................
   557    613           );
   558    614         }
   559    615   
   560    616         if( p->rc==SQLITE_OK ){
   561    617           otaMPrintfExec(p, 
   562    618               "CREATE TABLE IF NOT EXISTS ota.'ota_tmp_%q' AS "
   563    619               "SELECT * FROM ota.'data_%q' WHERE 0;"
          620  +
   564    621               "CREATE TEMP TRIGGER ota_delete_%q BEFORE DELETE ON main.%Q "
   565    622               "BEGIN "
   566    623               "  INSERT INTO 'ota_tmp_%q'(ota_control, %s) VALUES(2, %s);"
   567    624               "END;"
   568         -            , pIter->zTbl, pIter->zTbl, pIter->zTbl, pIter->zTbl, pIter->zTbl,
   569         -            zCollist, zOldlist
          625  +
          626  +            "CREATE TEMP TRIGGER ota_update1_%q BEFORE UPDATE ON main.%Q "
          627  +            "BEGIN "
          628  +            "  INSERT INTO 'ota_tmp_%q'(ota_control, %s) VALUES(2, %s);"
          629  +            "END;"
          630  +
          631  +            "CREATE TEMP TRIGGER ota_update2_%q AFTER UPDATE ON main.%Q "
          632  +            "BEGIN "
          633  +            "  INSERT INTO 'ota_tmp_%q'(ota_control, %s) VALUES(3, %s);"
          634  +            "END;"
          635  +
          636  +            , pIter->zTbl, pIter->zTbl, 
          637  +            pIter->zTbl, pIter->zTbl, pIter->zTbl, zCollist, zOldlist, 
          638  +            pIter->zTbl, pIter->zTbl, pIter->zTbl, zCollist, zOldlist, 
          639  +            pIter->zTbl, pIter->zTbl, pIter->zTbl, zCollist, zNewlist
   570    640           );
   571    641         }
          642  +
          643  +      /* Allocate space required for the zMask field. */
          644  +      if( p->rc==SQLITE_OK ){
          645  +        int nMask = pIter->nTblCol+1;
          646  +        pIter->zMask = (char*)sqlite3_malloc(nMask);
          647  +        if( pIter->zMask==0 ){
          648  +          p->rc = SQLITE_NOMEM;
          649  +        }else{
          650  +          memset(pIter->zMask, 0, nMask);
          651  +        }
          652  +      }
   572    653   
   573    654         sqlite3_free(zWhere);
   574    655         sqlite3_free(zOldlist);
          656  +      sqlite3_free(zNewlist);
   575    657         sqlite3_free(zBindings);
   576    658       }
   577    659       sqlite3_free(zCollist);
   578    660       sqlite3_free(zLimit);
   579    661     }
   580    662     
   581    663     return p->rc;
   582    664   }
   583    665   
   584    666   #define OTA_INSERT     1
   585    667   #define OTA_DELETE     2
   586    668   #define OTA_IDX_DELETE 3
   587         -#define OTA_UPDATE     4
          669  +#define OTA_IDX_INSERT 4
          670  +#define OTA_UPDATE     5
   588    671   
   589         -/*
   590         -** The SELECT statement iterating through the keys for the current object
   591         -** (p->objiter.pSelect) currently points to a valid row. However, there
   592         -** is something wrong with the ota_control value in the ota_control value
   593         -** stored in the (p->nCol+1)'th column. Set the error code and error message
   594         -** of the OTA handle to something reflecting this.
   595         -*/
   596         -static void otaBadControlError(sqlite3ota *p){
   597         -  p->rc = SQLITE_ERROR;
   598         -  p->zErrmsg = sqlite3_mprintf("Invalid ota_control value");
          672  +static int otaGetUpdateStmt(
          673  +  sqlite3ota *p, 
          674  +  OtaObjIter *pIter, 
          675  +  const char *zMask,
          676  +  sqlite3_stmt **ppStmt
          677  +){
          678  +  if( pIter->pUpdate && strcmp(zMask, pIter->zMask)==0 ){
          679  +    *ppStmt = pIter->pUpdate;
          680  +  }else{
          681  +    char *zWhere = otaObjIterGetWhere(p, pIter);
          682  +    char *zSet = otaObjIterGetSetlist(p, pIter, zMask);
          683  +    char *zUpdate = 0;
          684  +    sqlite3_finalize(pIter->pUpdate);
          685  +    pIter->pUpdate = 0;
          686  +    if( p->rc==SQLITE_OK ){
          687  +      zUpdate = sqlite3_mprintf("UPDATE %Q SET %s WHERE %s", 
          688  +          pIter->zTbl, zSet, zWhere
          689  +      );
          690  +      p->rc = prepareFreeAndCollectError(
          691  +          p->db, &pIter->pUpdate, &p->zErrmsg, zUpdate
          692  +      );
          693  +      *ppStmt = pIter->pUpdate;
          694  +    }
          695  +    if( p->rc==SQLITE_OK ){
          696  +      memcpy(pIter->zMask, zMask, pIter->nTblCol);
          697  +    }
          698  +    sqlite3_free(zWhere);
          699  +    sqlite3_free(zSet);
          700  +  }
          701  +  return p->rc;
   599    702   }
   600    703   
   601    704   /*
   602    705   ** The SELECT statement iterating through the keys for the current object
   603    706   ** (p->objiter.pSelect) currently points to a valid row. This function
   604    707   ** determines the type of operation requested by this row and returns
   605    708   ** one of the following values to indicate the result:
................................................................................
   624    727         int iVal = sqlite3_column_int(p->objiter.pSelect, iCol);
   625    728         if( iVal==0 ){
   626    729           res = OTA_INSERT;
   627    730         }else if( iVal==1 ){
   628    731           res = OTA_DELETE;
   629    732         }else if( iVal==2 ){
   630    733           res = OTA_IDX_DELETE;
          734  +      }else if( iVal==3 ){
          735  +        res = OTA_IDX_INSERT;
   631    736         }
   632    737         break;
   633    738       }
   634    739   
   635    740       case SQLITE_TEXT:
   636    741         *pzMask = (const char*)sqlite3_column_text(p->objiter.pSelect, iCol);
   637    742         res = OTA_UPDATE;
................................................................................
   666    771   
   667    772     if( eType ){
   668    773       assert( eType!=OTA_UPDATE || pIter->zIdx==0 );
   669    774   
   670    775       if( pIter->zIdx==0 && eType==OTA_IDX_DELETE ){
   671    776         otaBadControlError(p);
   672    777       }
   673         -    else if( eType==OTA_INSERT || eType==OTA_IDX_DELETE ){
          778  +    else if( 
          779  +        eType==OTA_INSERT 
          780  +     || eType==OTA_DELETE
          781  +     || eType==OTA_IDX_DELETE 
          782  +     || eType==OTA_IDX_INSERT
          783  +    ){
   674    784         sqlite3_stmt *pWriter;
          785  +
   675    786         assert( eType!=OTA_UPDATE );
          787  +      assert( eType!=OTA_DELETE || pIter->zIdx==0 );
   676    788   
   677         -      pWriter = (eType==OTA_INSERT)?pIter->pInsert:pIter->pDelete;
          789  +      if( eType==OTA_IDX_DELETE || eType==OTA_DELETE ){
          790  +        pWriter = pIter->pDelete;
          791  +      }else{
          792  +        pWriter = pIter->pInsert;
          793  +      }
          794  +
   678    795         for(i=0; i<pIter->nCol; i++){
          796  +        if( eType==SQLITE_DELETE && pIter->zIdx==0 && pIter->abTblPk[i]==0 ){
          797  +          continue;
          798  +        }
   679    799           sqlite3_value *pVal = sqlite3_column_value(pIter->pSelect, i);
   680    800           sqlite3_bind_value(pWriter, i+1, pVal);
   681    801         }
   682    802         sqlite3_step(pWriter);
   683    803         p->rc = resetAndCollectError(pWriter, &p->zErrmsg);
   684         -    }
   685         -    else if( eType==OTA_DELETE && pIter->zIdx==0 ){
   686         -      int iVar = 1;
   687         -      assert( pIter->zIdx==0 );
   688         -      assert( pIter->nCol==pIter->nTblCol );
   689         -      for(i=0; i<pIter->nCol; i++){
   690         -        if( pIter->abTblPk[i] ){
          804  +    }else if( eType==OTA_UPDATE ){
          805  +      sqlite3_stmt *pUpdate = 0;
          806  +      otaGetUpdateStmt(p, pIter, zMask, &pUpdate);
          807  +      if( pUpdate ){
          808  +        for(i=0; i<pIter->nCol; i++){
   691    809             sqlite3_value *pVal = sqlite3_column_value(pIter->pSelect, i);
   692         -          sqlite3_bind_value(pIter->pDelete, iVar++, pVal);
          810  +          sqlite3_bind_value(pUpdate, i+1, pVal);
   693    811           }
          812  +        sqlite3_step(pUpdate);
          813  +        p->rc = resetAndCollectError(pUpdate, &p->zErrmsg);
   694    814         }
   695         -      sqlite3_step(pIter->pDelete);
   696         -      p->rc = resetAndCollectError(pIter->pDelete, &p->zErrmsg);
   697         -    }else if( eType==OTA_UPDATE ){
   698         -      p->rc = SQLITE_ERROR;
   699         -      p->zErrmsg = sqlite3_mprintf("not yet");
   700    815       }else{
   701    816         /* no-op */
   702    817         assert( eType==OTA_DELETE && pIter->zIdx );
   703    818       }
   704    819     }
   705    820   
   706    821     return p->rc;
................................................................................
   714    829       OtaObjIter *pIter = &p->objiter;
   715    830       while( p && p->rc==SQLITE_OK && pIter->zTbl ){
   716    831   
   717    832         if( pIter->bCleanup ){
   718    833           /* Clean up the ota_tmp_xxx table for the previous table. It 
   719    834           ** cannot be dropped as there are currently active SQL statements.
   720    835           ** But the contents can be deleted.  */
   721         -        otaMPrintfExec(p, "DELETE FROM ota.'ota_tmp_%q'", pIter->zTbl);
          836  +        // otaMPrintfExec(p, "DELETE FROM ota.'ota_tmp_%q'", pIter->zTbl);
   722    837         }else{
   723    838           otaObjIterPrepareAll(p, pIter, 0);
   724    839           
   725    840           /* Advance to the next row to process. */
   726    841           if( p->rc==SQLITE_OK ){
   727    842             int rc = sqlite3_step(pIter->pSelect);
   728    843             if( rc==SQLITE_ROW ){