SQLite

Check-in [173f281334]
Login

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

Overview
Comment:Modify the code generated for a DELETE to use registers instead of the vdbe stack. (CVS 4675)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 173f281334d340290e1978abea5d1ea804141910
User & Date: danielk1977 2008-01-04 13:24:29.000
Context
2008-01-04
13:57
Modify FifoRead and FifoWrite to work exclusively with memory cells. (CVS 4676) (check-in: 2c913908a4 user: danielk1977 tags: trunk)
13:24
Modify the code generated for a DELETE to use registers instead of the vdbe stack. (CVS 4675) (check-in: 173f281334 user: danielk1977 tags: trunk)
11:01
Add OP_MemSet, for setting a memory cell to a string value. (CVS 4674) (check-in: 8bb9f970dd user: danielk1977 tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/delete.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** in order to generate code for DELETE FROM statements.
**
** $Id: delete.c,v 1.144 2008/01/03 18:03:09 drh Exp $
*/
#include "sqliteInt.h"

/*
** Look up every table that is named in pSrc.  If any table is not found,
** add an error message to pParse->zErrMsg and return NULL.  If all tables
** are found, return a pointer to the last table.







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** in order to generate code for DELETE FROM statements.
**
** $Id: delete.c,v 1.145 2008/01/04 13:24:29 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** Look up every table that is named in pSrc.  If any table is not found,
** add an error message to pParse->zErrMsg and return NULL.  If all tables
** are found, return a pointer to the last table.
295
296
297
298
299
300
301


302
303
304
305
306
307
308
      }
    }
  } 
  /* The usual case: There is a WHERE clause so we have to scan through
  ** the table and pick which records to delete.
  */
  else{


    /* Begin the database scan
    */
    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0);
    if( pWInfo==0 ) goto delete_from_cleanup;

    /* Remember the rowid of every item to be deleted.
    */







>
>







295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
      }
    }
  } 
  /* The usual case: There is a WHERE clause so we have to scan through
  ** the table and pick which records to delete.
  */
  else{
    int iRowid = ++pParse->nMem;    /* Used for storing value read from fifo */

    /* Begin the database scan
    */
    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0);
    if( pWInfo==0 ) goto delete_from_cleanup;

    /* Remember the rowid of every item to be deleted.
    */
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352



353
354

355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389

    /* This is the beginning of the delete loop. If a trigger encounters
    ** an IGNORE constraint, it jumps back to here.
    */
    if( triggers_exist ){
      sqlite3VdbeResolveLabel(v, addr);
    }
    addr = sqlite3VdbeAddOp2(v, OP_FifoRead, 0, end);
    sqlite3VdbeAddOp1(v, OP_StackDepth, -1);

    if( triggers_exist ){
      int mem1 = ++pParse->nMem;
      if( !isView ){
        sqlite3VdbeAddOp1(v, OP_MemStore, mem1);
      }



      sqlite3VdbeAddOp2(v, OP_NotExists, iCur, addr);
      sqlite3VdbeAddOp1(v, OP_Rowid, iCur);

      if( old_col_mask ){
        sqlite3VdbeAddOp1(v, OP_RowData, iCur);
      }else{
        sqlite3VdbeAddOp0(v, OP_Null);
      }
      sqlite3CodeInsert(pParse, oldIdx, 0);

      /* Jump back and run the BEFORE triggers */
      sqlite3VdbeAddOp2(v, OP_Goto, 0, iBeginBeforeTrigger);
      sqlite3VdbeJumpHere(v, iEndBeforeTrigger);

      if( !isView ){
        sqlite3VdbeAddOp1(v, OP_MemLoad, mem1);
      }
    }

    if( !isView ){
      /* Delete the row */
#ifndef SQLITE_OMIT_VIRTUALTABLE
      if( IsVirtual(pTab) ){
        int iReg = sqlite3StackToReg(pParse, 1);
        pParse->pVirtualLock = pTab;
        sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iReg,
                          (const char*)pTab->pVtab, P4_VTAB);
      }else
#endif
      {
        sqlite3GenerateRowDelete(db, v, pTab, iCur, pParse->nested==0);
      }
    }

    /* If there are row triggers, close all cursors then invoke
    ** the AFTER triggers
    */
    if( triggers_exist ){







|



|
<
<
|
>
>
>
|
|
>

|

|

|




<
<
<
<






|

|
<



|







340
341
342
343
344
345
346
347
348
349
350
351


352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368




369
370
371
372
373
374
375
376
377

378
379
380
381
382
383
384
385
386
387
388

    /* This is the beginning of the delete loop. If a trigger encounters
    ** an IGNORE constraint, it jumps back to here.
    */
    if( triggers_exist ){
      sqlite3VdbeResolveLabel(v, addr);
    }
    addr = sqlite3VdbeAddOp2(v, OP_FifoRead, iRowid, end);
    sqlite3VdbeAddOp1(v, OP_StackDepth, -1);

    if( triggers_exist ){
      int iData = ++pParse->nMem;   /* For storing row data of OLD table */



      /* If the record is no longer present in the table, jump to the
      ** next iteration of the loop through the contents of the fifo.
      */
      sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, iRowid);

      /* Populate the OLD.* pseudo-table */
      if( old_col_mask ){
        sqlite3VdbeAddOp3(v, OP_RowData, iCur, 0, iData);
      }else{
        sqlite3VdbeAddOp2(v, OP_MemNull, 0, iData);
      }
      sqlite3VdbeAddOp3(v, OP_Insert, oldIdx, iData, iRowid);

      /* Jump back and run the BEFORE triggers */
      sqlite3VdbeAddOp2(v, OP_Goto, 0, iBeginBeforeTrigger);
      sqlite3VdbeJumpHere(v, iEndBeforeTrigger);




    }

    if( !isView ){
      /* Delete the row */
#ifndef SQLITE_OMIT_VIRTUALTABLE
      if( IsVirtual(pTab) ){
        const char *pVtab = (const char *)pTab->pVtab;
        pParse->pVirtualLock = pTab;
        sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iRowid, pVtab, P4_VTAB);

      }else
#endif
      {
        sqlite3GenerateRowDelete(db, v, pTab, iCur, iRowid, pParse->nested==0);
      }
    }

    /* If there are row triggers, close all cursors then invoke
    ** the AFTER triggers
    */
    if( triggers_exist ){
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450

451
452
453
454
455
456
457
458
459
460
461
**
**   1.  A read/write cursor pointing to pTab, the table containing the row
**       to be deleted, must be opened as cursor number "base".
**
**   2.  Read/write cursors for all indices of pTab must be open as
**       cursor number base+i for the i-th index.
**
**   3.  The record number of the row to be deleted must be on the top
**       of the stack.
**
** This routine pops the top of the stack to remove the record number
** and then generates code to remove both the table record and all index
** entries that point to that record.
*/
void sqlite3GenerateRowDelete(
  sqlite3 *db,       /* The database containing the index */
  Vdbe *v,           /* Generate code into this VDBE */
  Table *pTab,       /* Table containing the row to be deleted */
  int iCur,          /* Cursor number for the table */

  int count          /* Increment the row change counter */
){
  int addr;
  addr = sqlite3VdbeAddOp1(v, OP_NotExists, iCur);
  sqlite3GenerateRowIndexDelete(v, pTab, iCur, 0);
  sqlite3VdbeAddOp2(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0));
  if( count ){
    sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC);
  }
  sqlite3VdbeJumpHere(v, addr);
}







|
|










>



|







431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
**
**   1.  A read/write cursor pointing to pTab, the table containing the row
**       to be deleted, must be opened as cursor number "base".
**
**   2.  Read/write cursors for all indices of pTab must be open as
**       cursor number base+i for the i-th index.
**
**   3.  The record number of the row to be deleted must be stored in
**       memory cell iRowid.
**
** This routine pops the top of the stack to remove the record number
** and then generates code to remove both the table record and all index
** entries that point to that record.
*/
void sqlite3GenerateRowDelete(
  sqlite3 *db,       /* The database containing the index */
  Vdbe *v,           /* Generate code into this VDBE */
  Table *pTab,       /* Table containing the row to be deleted */
  int iCur,          /* Cursor number for the table */
  int iRowid,        /* Memory cell that contains the rowid to delete */
  int count          /* Increment the row change counter */
){
  int addr;
  addr = sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowid);
  sqlite3GenerateRowIndexDelete(v, pTab, iCur, 0);
  sqlite3VdbeAddOp2(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0));
  if( count ){
    sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC);
  }
  sqlite3VdbeJumpHere(v, addr);
}
Changes to src/insert.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
** $Id: insert.c,v 1.208 2008/01/03 23:44:53 drh Exp $
*/
#include "sqliteInt.h"

/*
** Set P4 of the most recently inserted opcode to a column affinity
** string for index pIdx. A column affinity string has one character
** for each column in the table, according to the affinity of the column:







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
** $Id: insert.c,v 1.209 2008/01/04 13:24:29 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** Set P4 of the most recently inserted opcode to a column affinity
** string for index pIdx. A column affinity string has one character
** for each column in the table, according to the affinity of the column:
1172
1173
1174
1175
1176
1177
1178

1179
1180
1181
1182
1183
1184
1185
1186
      case OE_Ignore: {
        assert( seenReplace==0 );
        sqlite3VdbeAddOp2(v, OP_Pop, nCol+extra+3+hasTwoRowids, 0);
        sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
        break;
      }
      case OE_Replace: {

        sqlite3GenerateRowDelete(pParse->db, v, pTab, base, 0);
        if( isUpdate ){
          sqlite3VdbeAddOp2(v, OP_Dup, nCol+extra+1+hasTwoRowids, 1);
          sqlite3VdbeAddOp2(v, OP_MoveGe, base, 0);
        }
        seenReplace = 1;
        break;
      }







>
|







1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
      case OE_Ignore: {
        assert( seenReplace==0 );
        sqlite3VdbeAddOp2(v, OP_Pop, nCol+extra+3+hasTwoRowids, 0);
        sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
        break;
      }
      case OE_Replace: {
        int iRowid = sqlite3StackToReg(pParse, 1);
        sqlite3GenerateRowDelete(pParse->db, v, pTab, base, iRowid, 0);
        if( isUpdate ){
          sqlite3VdbeAddOp2(v, OP_Dup, nCol+extra+1+hasTwoRowids, 1);
          sqlite3VdbeAddOp2(v, OP_MoveGe, base, 0);
        }
        seenReplace = 1;
        break;
      }
Changes to src/sqliteInt.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.636 2008/01/03 23:44:53 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** The macro unlikely() is a hint that surrounds a boolean
** expression that is usually false.  Macro likely() surrounds













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.637 2008/01/04 13:24:29 danielk1977 Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** The macro unlikely() is a hint that surrounds a boolean
** expression that is usually false.  Macro likely() surrounds
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
void sqlite3CommitTransaction(Parse*);
void sqlite3RollbackTransaction(Parse*);
int sqlite3ExprIsConstant(Expr*);
int sqlite3ExprIsConstantNotJoin(Expr*);
int sqlite3ExprIsConstantOrFunction(Expr*);
int sqlite3ExprIsInteger(Expr*, int*);
int sqlite3IsRowid(const char*);
void sqlite3GenerateRowDelete(sqlite3*, Vdbe*, Table*, int, int);
void sqlite3GenerateRowIndexDelete(Vdbe*, Table*, int, char*);
void sqlite3GenerateIndexKey(Vdbe*, Index*, int);
void sqlite3GenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int);
void sqlite3CompleteInsertion(Parse*, Table*, int, char*, int, int, int, int);
void sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
void sqlite3BeginWriteOperation(Parse*, int, int);
Expr *sqlite3ExprDup(sqlite3*,Expr*);







|







1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
void sqlite3CommitTransaction(Parse*);
void sqlite3RollbackTransaction(Parse*);
int sqlite3ExprIsConstant(Expr*);
int sqlite3ExprIsConstantNotJoin(Expr*);
int sqlite3ExprIsConstantOrFunction(Expr*);
int sqlite3ExprIsInteger(Expr*, int*);
int sqlite3IsRowid(const char*);
void sqlite3GenerateRowDelete(sqlite3*, Vdbe*, Table*, int, int, int);
void sqlite3GenerateRowIndexDelete(Vdbe*, Table*, int, char*);
void sqlite3GenerateIndexKey(Vdbe*, Index*, int);
void sqlite3GenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int);
void sqlite3CompleteInsertion(Parse*, Table*, int, char*, int, int, int, int);
void sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
void sqlite3BeginWriteOperation(Parse*, int, int);
Expr *sqlite3ExprDup(sqlite3*,Expr*);
Changes to src/vdbe.c.
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.674 2008/01/04 11:01:04 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
** The following global variable is incremented every time a cursor







|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.675 2008/01/04 13:24:29 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
** The following global variable is incremented every time a cursor
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349

3350
3351
3352

3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364






3365

3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388

3389
3390

3391
3392
3393
3394
3395
3396
3397
    pTos++;
    pTos->u.i = v;
    pTos->flags = MEM_Int;
  }
  break;
}

/* Opcode: NotExists P1 P2 *
**
** Use the top of the stack as a integer key.  If a record with that key

** does not exist in table of P1, then jump to P2.  If the record
** does exist, then fall thru.  The cursor is left pointing to the
** record if it exists.  The integer key is popped from the stack.

**
** The difference between this operation and NotFound is that this
** operation assumes the key is an integer and that P1 is a table whereas
** NotFound assumes key is a blob constructed from MakeRecord and
** P1 is an index.
**
** See also: Distinct, Found, MoveTo, NotFound, IsUnique
*/
case OP_NotExists: {        /* no-push */
  int i = pOp->p1;
  Cursor *pC;
  BtCursor *pCrsr;






  assert( pTos>=p->aStack );

  assert( i>=0 && i<p->nCursor );
  assert( p->apCsr[i]!=0 );
  if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
    int res;
    u64 iKey;
    assert( pTos->flags & MEM_Int );
    assert( p->apCsr[i]->isTable );
    iKey = intToKey(pTos->u.i);
    rc = sqlite3BtreeMoveto(pCrsr, 0, iKey, 0,&res);
    pC->lastRowid = pTos->u.i;
    pC->rowidIsValid = res==0;
    pC->nullRow = 0;
    pC->cacheStatus = CACHE_STALE;
    /* res might be uninitialized if rc!=SQLITE_OK.  But if rc!=SQLITE_OK
    ** processing is about to abort so we really do not care whether or not
    ** the following jump is taken.  (In other words, do not stress over
    ** the error that valgrind sometimes shows on the next statement when
    ** running ioerr.test and similar failure-recovery test scripts.) */
    if( res!=0 ){
      pc = pOp->p2 - 1;
      pC->rowidIsValid = 0;
    }
  }

  Release(pTos);
  pTos--;

  break;
}

/* Opcode: Sequence P1 * *
**
** Push an integer onto the stack which is the next available
** sequence number for cursor P1.  The sequence number on the







|

|
>
|
|
|
>












>
>
>
>
>
>
|
>





|

|

|













>
|
|
>







3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
    pTos++;
    pTos->u.i = v;
    pTos->flags = MEM_Int;
  }
  break;
}

/* Opcode: NotExists P1 P2 P3
**
** Use the top of the stack as a integer key. Or, if P3 is non-zero,
** use the contents of memory cell P3 as an integer key. If a record 
** with that key does not exist in table of P1, then jump to P2. 
** If the record does exist, then fall thru.  The cursor is left 
** pointing to the record if it exists. The integer key is popped 
** from the stack (unless it was read from a memory cell).
**
** The difference between this operation and NotFound is that this
** operation assumes the key is an integer and that P1 is a table whereas
** NotFound assumes key is a blob constructed from MakeRecord and
** P1 is an index.
**
** See also: Distinct, Found, MoveTo, NotFound, IsUnique
*/
case OP_NotExists: {        /* no-push */
  int i = pOp->p1;
  Cursor *pC;
  BtCursor *pCrsr;
  Mem *pKey;
  if( pOp->p3 ){
    assert( pOp->p3<=p->nMem );
    pKey = &p->aMem[pOp->p3];
  }else{
    pKey = pTos;
    assert( pTos>=p->aStack );
  }
  assert( i>=0 && i<p->nCursor );
  assert( p->apCsr[i]!=0 );
  if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
    int res;
    u64 iKey;
    assert( pKey->flags & MEM_Int );
    assert( p->apCsr[i]->isTable );
    iKey = intToKey(pKey->u.i);
    rc = sqlite3BtreeMoveto(pCrsr, 0, iKey, 0,&res);
    pC->lastRowid = pKey->u.i;
    pC->rowidIsValid = res==0;
    pC->nullRow = 0;
    pC->cacheStatus = CACHE_STALE;
    /* res might be uninitialized if rc!=SQLITE_OK.  But if rc!=SQLITE_OK
    ** processing is about to abort so we really do not care whether or not
    ** the following jump is taken.  (In other words, do not stress over
    ** the error that valgrind sometimes shows on the next statement when
    ** running ioerr.test and similar failure-recovery test scripts.) */
    if( res!=0 ){
      pc = pOp->p2 - 1;
      pC->rowidIsValid = 0;
    }
  }
  if( pOp->p3==0 ){
    Release(pTos);
    pTos--;
  }
  break;
}

/* Opcode: Sequence P1 * *
**
** Push an integer onto the stack which is the next available
** sequence number for cursor P1.  The sequence number on the
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732

3733

3734
3735
3736
3737
3738
3739
3740
3741

3742

3743
3744
3745
3746
3747
3748
3749
3750
3751
3752

3753
3754



3755

3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
  if( pOp->p1 ){
    sqlite3VdbeSetChanges(db, p->nChange);
  }
  p->nChange = 0;
  break;
}

/* Opcode: RowData P1 * *
**
** Push onto the stack the complete row data for cursor P1.

** There is no interpretation of the data.  It is just copied

** onto the stack exactly as it is found in the database file.
**
** If the cursor is not pointing to a valid row, a NULL is pushed
** onto the stack.
*/
/* Opcode: RowKey P1 * *
**
** Push onto the stack the complete row key for cursor P1.

** There is no interpretation of the key.  It is just copied

** onto the stack exactly as it is found in the database file.
**
** If the cursor is not pointing to a valid row, a NULL is pushed
** onto the stack.
*/
case OP_RowKey:
case OP_RowData: {
  int i = pOp->p1;
  Cursor *pC;
  u32 n;


  /* Note that RowKey and RowData are really exactly the same instruction */



  pTos++;

  assert( i>=0 && i<p->nCursor );
  pC = p->apCsr[i];
  assert( pC->isTable || pOp->opcode==OP_RowKey );
  assert( pC->isIndex || pOp->opcode==OP_RowData );
  assert( pC!=0 );
  if( pC->nullRow ){
    pTos->flags = MEM_Null;
  }else if( pC->pCursor!=0 ){
    BtCursor *pCrsr = pC->pCursor;
    rc = sqlite3VdbeCursorMoveto(pC);
    if( rc ) goto abort_due_to_error;
    if( pC->nullRow ){
      pTos->flags = MEM_Null;
      break;
    }else if( pC->isIndex ){
      i64 n64;
      assert( !pC->isTable );
      sqlite3BtreeKeySize(pCrsr, &n64);
      if( n64>SQLITE_MAX_LENGTH ){
        goto too_big;
      }
      n = n64;
    }else{
      sqlite3BtreeDataSize(pCrsr, &n);
    }
    if( n>SQLITE_MAX_LENGTH ){
      goto too_big;
    }
    pTos->n = n;
    if( n<=NBFS ){
      pTos->flags = MEM_Blob | MEM_Short;
      pTos->z = pTos->zShort;
    }else{
      char *z = sqlite3_malloc( n );
      if( z==0 ) goto no_mem;
      pTos->flags = MEM_Blob | MEM_Dyn;
      pTos->xDel = 0;
      pTos->z = z;
    }
    if( pC->isIndex ){
      rc = sqlite3BtreeKey(pCrsr, 0, n, pTos->z);
    }else{
      rc = sqlite3BtreeData(pCrsr, 0, n, pTos->z);
    }
  }else if( pC->pseudoTable ){
    pTos->n = pC->nData;
    assert( pC->nData<=SQLITE_MAX_LENGTH );
    pTos->z = pC->pData;
    pTos->flags = MEM_Blob|MEM_Ephem;
  }else{
    pTos->flags = MEM_Null;
  }
  pTos->enc = SQLITE_UTF8;  /* In case the blob is ever cast to text */
  break;
}

/* Opcode: Rowid P1 P2 * * *
**
** Store in register P2 an integer which is the key of the table entry that
** P1 is currently point to.  If p2==0 then pust the integer.







|

|
>
|
>
|

|
|

|

|
>
|
>
|









>


>
>
>
|
>






|





|















|

|
|



|
|
|


|

|


|

|
|

|

|







3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
  if( pOp->p1 ){
    sqlite3VdbeSetChanges(db, p->nChange);
  }
  p->nChange = 0;
  break;
}

/* Opcode: RowData P1 * P3
**
** Push onto the stack the complete row data for cursor P1. Or if P3 
** is a positive non-zero integer register number, then the value 
** is written into that register. There is no interpretation of the data.  
** It is just copied onto the stack or into the memory cell exactly as 
** it is found in the database file.
**
** If the cursor is not pointing to a valid row, a NULL value is
** pushed/inserted instead.
*/
/* Opcode: RowKey P1 * P3
**
** Push onto the stack the complete row key for cursor P1. Or if P3 
** is a positive non-zero integer register number, then the value 
** is written into that register. There is no interpretation of the data.  
** It is just copied onto the stack or into the memory cell exactly as 
** it is found in the database file.
**
** If the cursor is not pointing to a valid row, a NULL is pushed
** onto the stack.
*/
case OP_RowKey:
case OP_RowData: {
  int i = pOp->p1;
  Cursor *pC;
  u32 n;
  Mem *pOut;

  /* Note that RowKey and RowData are really exactly the same instruction */
  if( pOp->p3 ){
    pOut = &p->aMem[pOp->p3];
  }else{
    pOut = ++pTos;
  }
  assert( i>=0 && i<p->nCursor );
  pC = p->apCsr[i];
  assert( pC->isTable || pOp->opcode==OP_RowKey );
  assert( pC->isIndex || pOp->opcode==OP_RowData );
  assert( pC!=0 );
  if( pC->nullRow ){
    pOut->flags = MEM_Null;
  }else if( pC->pCursor!=0 ){
    BtCursor *pCrsr = pC->pCursor;
    rc = sqlite3VdbeCursorMoveto(pC);
    if( rc ) goto abort_due_to_error;
    if( pC->nullRow ){
      pOut->flags = MEM_Null;
      break;
    }else if( pC->isIndex ){
      i64 n64;
      assert( !pC->isTable );
      sqlite3BtreeKeySize(pCrsr, &n64);
      if( n64>SQLITE_MAX_LENGTH ){
        goto too_big;
      }
      n = n64;
    }else{
      sqlite3BtreeDataSize(pCrsr, &n);
    }
    if( n>SQLITE_MAX_LENGTH ){
      goto too_big;
    }
    pOut->n = n;
    if( n<=NBFS ){
      pOut->flags = MEM_Blob | MEM_Short;
      pOut->z = pOut->zShort;
    }else{
      char *z = sqlite3_malloc( n );
      if( z==0 ) goto no_mem;
      pOut->flags = MEM_Blob | MEM_Dyn;
      pOut->xDel = 0;
      pOut->z = z;
    }
    if( pC->isIndex ){
      rc = sqlite3BtreeKey(pCrsr, 0, n, pOut->z);
    }else{
      rc = sqlite3BtreeData(pCrsr, 0, n, pOut->z);
    }
  }else if( pC->pseudoTable ){
    pOut->n = pC->nData;
    assert( pC->nData<=SQLITE_MAX_LENGTH );
    pOut->z = pC->pData;
    pOut->flags = MEM_Blob|MEM_Ephem;
  }else{
    pOut->flags = MEM_Null;
  }
  pOut->enc = SQLITE_UTF8;  /* In case the blob is ever cast to text */
  break;
}

/* Opcode: Rowid P1 P2 * * *
**
** Store in register P2 an integer which is the key of the table entry that
** P1 is currently point to.  If p2==0 then pust the integer.
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524



4525
4526
4527
4528
4529
4530
4531
4532
4533



4534
4535

4536
4537
4538
4539
4540
4541
4542
4543
  sqlite3_free(aRoot);
  break;
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */

/* Opcode: FifoWrite * * *
**
** Write the integer on the top of the stack
** into the Fifo.
*/
case OP_FifoWrite: {        /* no-push */
  assert( pTos>=p->aStack );
  sqlite3VdbeMemIntegerify(pTos);
  if( sqlite3VdbeFifoPush(&p->sFifo, pTos->u.i)==SQLITE_NOMEM ){
    goto no_mem;
  }
  assert( (pTos->flags & MEM_Dyn)==0 );
  pTos--;
  break;
}

/* Opcode: FifoRead * P2 *
**
** Attempt to read a single integer from the Fifo



** and push it onto the stack.  If the Fifo is empty
** push nothing but instead jump to P2.
*/
case OP_FifoRead: {
  i64 v;
  CHECK_FOR_INTERRUPT;
  if( sqlite3VdbeFifoPop(&p->sFifo, &v)==SQLITE_DONE ){
    pc = pOp->p2 - 1;
  }else{



    pTos++;
    pTos->u.i = v;

    pTos->flags = MEM_Int;
  }
  break;
}

#ifndef SQLITE_OMIT_TRIGGER
/* Opcode: ContextPush * * * 
**







|
<












|

|
>
>
>
|
|







>
>
>
|
|
>
|







4521
4522
4523
4524
4525
4526
4527
4528

4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
  sqlite3_free(aRoot);
  break;
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */

/* Opcode: FifoWrite * * *
**
** Write the integer on the top of the stack into the Fifo.

*/
case OP_FifoWrite: {        /* no-push */
  assert( pTos>=p->aStack );
  sqlite3VdbeMemIntegerify(pTos);
  if( sqlite3VdbeFifoPush(&p->sFifo, pTos->u.i)==SQLITE_NOMEM ){
    goto no_mem;
  }
  assert( (pTos->flags & MEM_Dyn)==0 );
  pTos--;
  break;
}

/* Opcode: FifoRead P1 P2 *
**
** Attempt to read a single integer from the Fifo. If P1 is zero,
** push the result onto the stack. Otherwise, store the read integer 
** in register P1.
** 
** If the Fifo is empty do not push an entry onto the stack or set
** a memory register but instead jump to P2.
*/
case OP_FifoRead: {
  i64 v;
  CHECK_FOR_INTERRUPT;
  if( sqlite3VdbeFifoPop(&p->sFifo, &v)==SQLITE_DONE ){
    pc = pOp->p2 - 1;
  }else{
    Mem *pOut;
    if( pOp->p1 ){
      pOut = &p->aMem[pOp->p1];
    }else{
      pOut = ++pTos;
    }
    sqlite3VdbeMemSetInt64(pOut, v);
  }
  break;
}

#ifndef SQLITE_OMIT_TRIGGER
/* Opcode: ContextPush * * * 
**