SQLite

Check-in [d8bacc1680]
Login

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

Overview
Comment:Allocates VDBE cursors one by one in separate memory so that pointers to cursors can persist through a realloc(). (CVS 1383)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: d8bacc16801606176fe8639b2f55b4584ad549df
User & Date: drh 2004-05-14 21:59:40.000
Context
2004-05-15
00:29
More speed improvements to btree. (CVS 1384) (check-in: aab4b794b4 user: drh tags: trunk)
2004-05-14
21:59
Allocates VDBE cursors one by one in separate memory so that pointers to cursors can persist through a realloc(). (CVS 1383) (check-in: d8bacc1680 user: drh tags: trunk)
21:12
Cache record headers in the OP_Column opcode. (CVS 1382) (check-in: 8d9eab178f user: drh tags: trunk)
Changes
Side-by-Side Diff Ignore Whitespace Patch
Changes to src/vdbe.c.
39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
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.292 2004/05/14 21:12:23 drh Exp $
** $Id: vdbe.c,v 1.293 2004/05/14 21:59:40 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
409
410
411
412
413
414
415
416
417


418
419
420





421
422
423
424
425
426
427
409
410
411
412
413
414
415


416
417



418
419
420
421
422
423
424
425
426
427
428
429







-
-
+
+
-
-
-
+
+
+
+
+







** allocate more.
**
** If a memory allocation error occurs, return 1.  Return 0 if
** everything works.
*/
static int expandCursorArraySize(Vdbe *p, int mxCursor){
  if( mxCursor>=p->nCursor ){
    Cursor *aCsr = sqliteRealloc( p->aCsr, (mxCursor+1)*sizeof(Cursor) );
    if( aCsr==0 ) return 1;
    p->apCsr = sqliteRealloc( p->apCsr, (mxCursor+1)*sizeof(Cursor*) );
    if( p->apCsr==0 ) return 1;
    p->aCsr = aCsr;
    memset(&p->aCsr[p->nCursor], 0, sizeof(Cursor)*(mxCursor+1-p->nCursor));
    p->nCursor = mxCursor+1;
    while( p->nCursor<=mxCursor ){
      Cursor *pC;
      p->apCsr[p->nCursor++] = pC = sqliteMalloc( sizeof(Cursor) );
      if( pC==0 ) return 1;
    }
  }
  return 0;
}

/*
** Apply any conversion required by the supplied column affinity to
** memory cell pRec. affinity may be one of:
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
560
561
562
563
564
565
566



567
568
569
570
571
572
573







-
-
-







  unsigned long long start;  /* CPU clock count at start of opcode */
  int origPc;                /* Program counter at start of opcode */
#endif
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  int nProgressOps = 0;      /* Opcodes executed since progress callback. */
#endif

  /* FIX ME. */
  expandCursorArraySize(p, 100);

  if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE;
  assert( db->magic==SQLITE_MAGIC_BUSY );
  assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY );
  p->rc = SQLITE_OK;
  assert( p->explain==0 );
  if( sqlite3_malloc_failed ) goto no_mem;
  pTos = p->pTos;
1917
1918
1919
1920
1921
1922
1923
1924

1925
1926
1927
1928
1929
1930
1931
1916
1917
1918
1919
1920
1921
1922

1923
1924
1925
1926
1927
1928
1929
1930







-
+







  */
  if( i<0 ){
    assert( &pTos[i]>=p->aStack );
    assert( pTos[i].flags & MEM_Str );
    zRec = pTos[i].z;
    payloadSize = pTos[i].n;
    pC->cacheValid = 0;
  }else if( (pC = &p->aCsr[i])->pCursor!=0 ){
  }else if( (pC = p->apCsr[i])->pCursor!=0 ){
    sqlite3VdbeCursorMoveto(pC);
    zRec = 0;
    pCrsr = pC->pCursor;
    if( pC->nullRow ){
      payloadSize = 0;
    }else if( pC->cacheValid ){
      payloadSize = pC->payloadSize;
2619
2620
2621
2622
2623
2624
2625
2626

2627
2628
2629
2630
2631
2632
2633
2634
2635
2618
2619
2620
2621
2622
2623
2624

2625
2626

2627
2628
2629
2630
2631
2632
2633







-
+

-







      sqlite3SetString(&p->zErrMsg, "root page number less than 2", (char*)0);
      rc = SQLITE_INTERNAL;
      break;
    }
  }
  assert( i>=0 );
  if( expandCursorArraySize(p, i) ) goto no_mem;
  pCur = &p->aCsr[i];
  pCur = p->apCsr[i];
  sqlite3VdbeCleanupCursor(pCur);
  memset(pCur, 0, sizeof(Cursor));
  pCur->nullRow = 1;
  if( pX==0 ) break;
  do{
    /* When opening cursors, always supply the comparison function
    ** sqlite3VdbeKeyCompare(). If the table being opened is of type
    ** INTKEY, the btree layer won't call the comparison function anyway.
    */
2687
2688
2689
2690
2691
2692
2693
2694

2695
2696
2697
2698
2699
2700
2701
2685
2686
2687
2688
2689
2690
2691

2692
2693
2694
2695
2696
2697
2698
2699







-
+







** of the connection to the database.  Same word; different meanings.
*/
case OP_OpenTemp: {
  int i = pOp->p1;
  Cursor *pCx;
  assert( i>=0 );
  if( expandCursorArraySize(p, i) ) goto no_mem;
  pCx = &p->aCsr[i];
  pCx = p->apCsr[i];
  sqlite3VdbeCleanupCursor(pCx);
  memset(pCx, 0, sizeof(*pCx));
  pCx->nullRow = 1;
  rc = sqlite3BtreeFactory(db, 0, 1, TEMP_PAGES, &pCx->pBt);

  if( rc==SQLITE_OK ){
    rc = sqlite3BtreeBeginTrans(pCx->pBt);
2732
2733
2734
2735
2736
2737
2738
2739

2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755

2756
2757
2758
2759
2760
2761
2762
2730
2731
2732
2733
2734
2735
2736

2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752

2753
2754
2755
2756
2757
2758
2759
2760







-
+















-
+







** NEW or OLD tables in a trigger.
*/
case OP_OpenPseudo: {
  int i = pOp->p1;
  Cursor *pCx;
  assert( i>=0 );
  if( expandCursorArraySize(p, i) ) goto no_mem;
  pCx = &p->aCsr[i];
  pCx = p->apCsr[i];
  sqlite3VdbeCleanupCursor(pCx);
  memset(pCx, 0, sizeof(*pCx));
  pCx->nullRow = 1;
  pCx->pseudoTable = 1;
  break;
}

/* Opcode: Close P1 * *
**
** Close a cursor previously opened as P1.  If P1 is not
** currently open, this instruction is a no-op.
*/
case OP_Close: {
  int i = pOp->p1;
  if( i>=0 && i<p->nCursor ){
    sqlite3VdbeCleanupCursor(&p->aCsr[i]);
    sqlite3VdbeCleanupCursor(p->apCsr[i]);
  }
  break;
}

/* Opcode: MoveTo P1 P2 *
**
** Pop the top of the stack and use its value as a key.  Reposition
2791
2792
2793
2794
2795
2796
2797
2798

2799
2800
2801
2802
2803
2804
2805
2789
2790
2791
2792
2793
2794
2795

2796
2797
2798
2799
2800
2801
2802
2803







-
+







case OP_MoveLt:
case OP_MoveTo: {
  int i = pOp->p1;
  Cursor *pC;

  assert( pTos>=p->aStack );
  assert( i>=0 && i<p->nCursor );
  pC = &p->aCsr[i];
  pC = p->apCsr[i];
  if( pC->pCursor!=0 ){
    int res, oc;
    pC->nullRow = 0;
    if( pC->intKey ){
      i64 iKey;
      assert( !pOp->p3 );
      Integerify(pTos);
2891
2892
2893
2894
2895
2896
2897
2898

2899
2900
2901
2902
2903
2904
2905
2889
2890
2891
2892
2893
2894
2895

2896
2897
2898
2899
2900
2901
2902
2903







-
+







case OP_NotFound:
case OP_Found: {
  int i = pOp->p1;
  int alreadyExists = 0;
  Cursor *pC;
  assert( pTos>=p->aStack );
  assert( i>=0 && i<p->nCursor );
  if( (pC = &p->aCsr[i])->pCursor!=0 ){
  if( (pC = p->apCsr[i])->pCursor!=0 ){
    int res, rx;
    assert( pC->intKey==0 );
    Stringify(pTos);
    rx = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
    alreadyExists = rx==SQLITE_OK && res==0;
    pC->deferredMoveto = 0;
    pC->cacheValid = 0;
2946
2947
2948
2949
2950
2951
2952
2953

2954
2955
2956
2957
2958
2959
2960
2944
2945
2946
2947
2948
2949
2950

2951
2952
2953
2954
2955
2956
2957
2958







-
+







  /* Pop the value R off the top of the stack
  */
  assert( pNos>=p->aStack );
  Integerify(pTos);
  R = pTos->i;
  pTos--;
  assert( i>=0 && i<=p->nCursor );
  pCx = &p->aCsr[i];
  pCx = p->apCsr[i];
  pCrsr = pCx->pCursor;
  if( pCrsr!=0 ){
    int res, rc;
    i64 v;         /* The record number on the P1 entry that matches K */
    char *zKey;    /* The value of K */
    int nKey;      /* Number of bytes in K */
    int len;       /* Number of bytes in K without the rowid at the end */
3030
3031
3032
3033
3034
3035
3036
3037

3038
3039
3040
3041

3042
3043
3044
3045
3046
3047
3048
3028
3029
3030
3031
3032
3033
3034

3035
3036
3037
3038

3039
3040
3041
3042
3043
3044
3045
3046







-
+



-
+







*/
case OP_NotExists: {
  int i = pOp->p1;
  Cursor *pC;
  BtCursor *pCrsr;
  assert( pTos>=p->aStack );
  assert( i>=0 && i<p->nCursor );
  if( (pCrsr = (pC = &p->aCsr[i])->pCursor)!=0 ){
  if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
    int res, rx;
    u64 iKey;
    assert( pTos->flags & MEM_Int );
    assert( p->aCsr[i].intKey );
    assert( p->apCsr[i]->intKey );
    iKey = intToKey(pTos->i);
    rx = sqlite3BtreeMoveto(pCrsr, 0, iKey, &res);
    pC->lastRecno = pTos->i;
    pC->recnoIsValid = res==0;
    pC->nullRow = 0;
    pC->cacheValid = 0;
    if( rx!=SQLITE_OK || res!=0 ){
3063
3064
3065
3066
3067
3068
3069
3070

3071
3072
3073
3074
3075
3076
3077
3061
3062
3063
3064
3065
3066
3067

3068
3069
3070
3071
3072
3073
3074
3075







-
+







** onto the stack.
*/
case OP_NewRecno: {
  int i = pOp->p1;
  i64 v = 0;
  Cursor *pC;
  assert( i>=0 && i<p->nCursor );
  if( (pC = &p->aCsr[i])->pCursor==0 ){
  if( (pC = p->apCsr[i])->pCursor==0 ){
    /* The zero initialization above is all that is needed */
  }else{
    /* The next rowid or record number (different terms for the same
    ** thing) is obtained in a two-step algorithm.
    **
    ** First we attempt to find the largest existing rowid and add one
    ** to that.  But if the largest existing rowid is already the maximum
3191
3192
3193
3194
3195
3196
3197
3198

3199
3200
3201
3202
3203
3204
3205
3189
3190
3191
3192
3193
3194
3195

3196
3197
3198
3199
3200
3201
3202
3203







-
+







case OP_PutIntKey:
case OP_PutStrKey: {
  Mem *pNos = &pTos[-1];
  int i = pOp->p1;
  Cursor *pC;
  assert( pNos>=p->aStack );
  assert( i>=0 && i<p->nCursor );
  if( ((pC = &p->aCsr[i])->pCursor!=0 || pC->pseudoTable) ){
  if( ((pC = p->apCsr[i])->pCursor!=0 || pC->pseudoTable) ){
    char *zKey;
    i64 nKey; 
    i64 iKey;
    if( pOp->opcode==OP_PutStrKey ){
      Stringify(pNos);
      nKey = pNos->n;
      zKey = pNos->z;
3278
3279
3280
3281
3282
3283
3284
3285

3286
3287
3288
3289
3290
3291
3292
3276
3277
3278
3279
3280
3281
3282

3283
3284
3285
3286
3287
3288
3289
3290







-
+







**
** If P1 is a pseudo-table, then this instruction is a no-op.
*/
case OP_Delete: {
  int i = pOp->p1;
  Cursor *pC;
  assert( i>=0 && i<p->nCursor );
  pC = &p->aCsr[i];
  pC = p->apCsr[i];
  if( pC->pCursor!=0 ){
    sqlite3VdbeCursorMoveto(pC);
    rc = sqlite3BtreeDelete(pC->pCursor);
    pC->nextRowidValid = 0;
    pC->cacheValid = 0;
  }
  if( pOp->p2 & OPFLAG_NCHANGE ) db->nChange++;
3311
3312
3313
3314
3315
3316
3317
3318

3319
3320
3321
3322
3323
3324
3325
3309
3310
3311
3312
3313
3314
3315

3316
3317
3318
3319
3320
3321
3322
3323







-
+







** off (if P2==0).  In key-as-data mode, the OP_Column opcode pulls
** data off of the key rather than the data.  This is used for
** processing compound selects.
*/
case OP_KeyAsData: {
  int i = pOp->p1;
  assert( i>=0 && i<p->nCursor );
  p->aCsr[i].keyAsData = pOp->p2;
  p->apCsr[i]->keyAsData = pOp->p2;
  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
3341
3342
3343
3344
3345
3346
3347
3348

3349
3350
3351
3352
3353
3354
3355
3339
3340
3341
3342
3343
3344
3345

3346
3347
3348
3349
3350
3351
3352
3353







-
+







case OP_RowData: {
  int i = pOp->p1;
  Cursor *pC;
  int n;

  pTos++;
  assert( i>=0 && i<p->nCursor );
  pC = &p->aCsr[i];
  pC = p->apCsr[i];
  if( pC->nullRow ){
    pTos->flags = MEM_Null;
  }else if( pC->pCursor!=0 ){
    BtCursor *pCrsr = pC->pCursor;
    sqlite3VdbeCursorMoveto(pC);
    if( pC->nullRow ){
      pTos->flags = MEM_Null;
3396
3397
3398
3399
3400
3401
3402
3403

3404
3405
3406
3407
3408
3409
3410
3394
3395
3396
3397
3398
3399
3400

3401
3402
3403
3404
3405
3406
3407
3408







-
+







*/
case OP_Recno: {
  int i = pOp->p1;
  Cursor *pC;
  i64 v;

  assert( i>=0 && i<p->nCursor );
  pC = &p->aCsr[i];
  pC = p->apCsr[i];
  sqlite3VdbeCursorMoveto(pC);
  pTos++;
  if( pC->recnoIsValid ){
    v = pC->lastRecno;
  }else if( pC->pseudoTable ){
    v = keyToInt(pC->iKey);
  }else if( pC->nullRow || pC->pCursor==0 ){
3430
3431
3432
3433
3434
3435
3436

3437
3438
3439


3440
3441
3442

3443
3444
3445
3446
3447


3448
3449
3450
3451
3452
3453
3454
3428
3429
3430
3431
3432
3433
3434
3435
3436


3437
3438
3439
3440

3441
3442
3443
3444


3445
3446
3447
3448
3449
3450
3451
3452
3453







+

-
-
+
+


-
+



-
-
+
+







** integer.  This instruction pushes the entire key as a string.
**
** This opcode may not be used on a pseudo-table.
*/
case OP_FullKey: {
  int i = pOp->p1;
  BtCursor *pCrsr;
  Cursor *pC;

  assert( p->aCsr[i].keyAsData );
  assert( !p->aCsr[i].pseudoTable );
  assert( p->apCsr[i]->keyAsData );
  assert( !p->apCsr[i]->pseudoTable );
  assert( i>=0 && i<p->nCursor );
  pTos++;
  if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
  if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
    u64 amt;
    char *z;

    sqlite3VdbeCursorMoveto(&p->aCsr[i]);
    assert( p->aCsr[i].intKey==0 );
    sqlite3VdbeCursorMoveto(pC);
    assert( pC->intKey==0 );
    sqlite3BtreeKeySize(pCrsr, &amt);
    if( amt<=0 ){
      rc = SQLITE_CORRUPT;
      goto abort_due_to_error;
    }
    if( amt>NBFS ){
      z = sqliteMallocRaw( amt );
3469
3470
3471
3472
3473
3474
3475

3476
3477

3478
3479


3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497

3498
3499
3500
3501
3502
3503
3504
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478


3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497

3498
3499
3500
3501
3502
3503
3504
3505







+


+
-
-
+
+

















-
+







**
** Move the cursor P1 to a null row.  Any OP_Column operations
** that occur while the cursor is on the null row will always push 
** a NULL onto the stack.
*/
case OP_NullRow: {
  int i = pOp->p1;
  Cursor *pC;

  assert( i>=0 && i<p->nCursor );
  pC = p->apCsr[i];
  p->aCsr[i].nullRow = 1;
  p->aCsr[i].recnoIsValid = 0;
  pC->nullRow = 1;
  pC->recnoIsValid = 0;
  break;
}

/* Opcode: Last P1 P2 *
**
** The next use of the Recno or Column or Next instruction for P1 
** will refer to the last entry in the database table or index.
** If the table or index is empty and P2>0, then jump immediately to P2.
** If P2 is 0 or if the table or index is not empty, fall through
** to the following instruction.
*/
case OP_Last: {
  int i = pOp->p1;
  Cursor *pC;
  BtCursor *pCrsr;

  assert( i>=0 && i<p->nCursor );
  pC = &p->aCsr[i];
  pC = p->apCsr[i];
  if( (pCrsr = pC->pCursor)!=0 ){
    int res;
    rc = sqlite3BtreeLast(pCrsr, &res);
    pC->nullRow = res;
    pC->deferredMoveto = 0;
    pC->cacheValid = 0;
    if( res && pOp->p2>0 ){
3521
3522
3523
3524
3525
3526
3527
3528

3529
3530
3531
3532
3533
3534
3535
3522
3523
3524
3525
3526
3527
3528

3529
3530
3531
3532
3533
3534
3535
3536







-
+







case OP_Rewind: {
  int i = pOp->p1;
  Cursor *pC;
  BtCursor *pCrsr;
  int res;

  assert( i>=0 && i<p->nCursor );
  pC = &p->aCsr[i];
  pC = p->apCsr[i];
  if( (pCrsr = pC->pCursor)!=0 ){
    rc = sqlite3BtreeFirst(pCrsr, &res);
    pC->atFirst = res==0;
    pC->deferredMoveto = 0;
    pC->cacheValid = 0;
  }else{
    res = 1;
3560
3561
3562
3563
3564
3565
3566
3567

3568
3569
3570
3571
3572
3573
3574
3561
3562
3563
3564
3565
3566
3567

3568
3569
3570
3571
3572
3573
3574
3575







-
+







case OP_Prev:
case OP_Next: {
  Cursor *pC;
  BtCursor *pCrsr;

  CHECK_FOR_INTERRUPT;
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pC = &p->aCsr[pOp->p1];
  pC = p->apCsr[pOp->p1];
  if( (pCrsr = pC->pCursor)!=0 ){
    int res;
    if( pC->nullRow ){
      res = 1;
    }else{
      assert( pC->deferredMoveto==0 );
      rc = pOp->opcode==OP_Next ? sqlite3BtreeNext(pCrsr, &res) :
3601
3602
3603
3604
3605
3606
3607
3608

3609
3610
3611
3612
3613
3614
3615
3602
3603
3604
3605
3606
3607
3608

3609
3610
3611
3612
3613
3614
3615
3616







-
+







case OP_IdxPut: {
  int i = pOp->p1;
  Cursor *pC;
  BtCursor *pCrsr;
  assert( pTos>=p->aStack );
  assert( i>=0 && i<p->nCursor );
  assert( pTos->flags & MEM_Str );
  if( (pCrsr = (pC = &p->aCsr[i])->pCursor)!=0 ){
  if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
    int nKey = pTos->n;
    const char *zKey = pTos->z;
    if( pOp->p2 ){
      int res;
      int len;
      u64 n;
   
3658
3659
3660
3661
3662
3663
3664
3665

3666
3667
3668
3669
3670
3671
3672
3659
3660
3661
3662
3663
3664
3665

3666
3667
3668
3669
3670
3671
3672
3673







-
+







case OP_IdxDelete: {
  int i = pOp->p1;
  Cursor *pC;
  BtCursor *pCrsr;
  assert( pTos>=p->aStack );
  assert( pTos->flags & MEM_Str );
  assert( i>=0 && i<p->nCursor );
  if( (pCrsr = (pC = &p->aCsr[i])->pCursor)!=0 ){
  if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
    int rx, res;
    rx = sqlite3BtreeMoveto(pCrsr, pTos->z, pTos->n, &res);
    if( rx==SQLITE_OK && res==0 ){
      rc = sqlite3BtreeDelete(pCrsr);
    }
    assert( pC->deferredMoveto==0 );
    pC->cacheValid = 0;
3683
3684
3685
3686
3687
3688
3689

3690
3691
3692
3693

3694
3695
3696
3697


3698
3699
3700
3701
3702
3703
3704
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694

3695
3696
3697


3698
3699
3700
3701
3702
3703
3704
3705
3706







+



-
+


-
-
+
+







** the record number of the table entry to which this index entry points.
**
** See also: Recno, MakeIdxKey.
*/
case OP_IdxRecno: {
  int i = pOp->p1;
  BtCursor *pCrsr;
  Cursor *pC;

  assert( i>=0 && i<p->nCursor );
  pTos++;
  if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
  if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
    i64 rowid;

    assert( p->aCsr[i].deferredMoveto==0 );
    assert( p->aCsr[i].intKey==0 );
    assert( pC->deferredMoveto==0 );
    assert( pC->intKey==0 );
    rc = sqlite3VdbeIdxRowid(pCrsr, &rowid);
    if( rc!=SQLITE_OK ){
      goto abort_due_to_error;
    }
    pTos->flags = MEM_Int;
    pTos->i = rowid;

3765
3766
3767
3768
3769
3770
3771

3772
3773
3774
3775

3776
3777
3778
3779
3780

3781
3782
3783
3784
3785
3786
3787
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777

3778
3779

3780
3781

3782
3783
3784
3785
3786
3787
3788
3789







+



-
+

-


-
+







** In either case, the stack is popped once.
*/
case OP_IdxLT:
case OP_IdxGT:
case OP_IdxGE: {
  int i= pOp->p1;
  BtCursor *pCrsr;
  Cursor *pC;

  assert( i>=0 && i<p->nCursor );
  assert( pTos>=p->aStack );
  if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
  if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
    int res, rc;
    Cursor *pC = &p->aCsr[i];
 
    Stringify(pTos);
    assert( p->aCsr[i].deferredMoveto==0 );
    assert( pC->deferredMoveto==0 );
    if( pOp->p3 ){
      pC->incrKey = 1;
    }
    rc = sqlite3VdbeIdxKeyCompare(pC, pTos->n, pTos->z, 0, &res);
    pC->incrKey = 0;
    if( rc!=SQLITE_OK ){
      break;
Changes to src/vdbeInt.h.
261
262
263
264
265
266
267
268
269


270
271
272
273
274
275
276
261
262
263
264
265
266
267


268
269
270
271
272
273
274
275
276







-
-
+
+







  int nLabel;         /* Number of labels used */
  int nLabelAlloc;    /* Number of slots allocated in aLabel[] */
  int *aLabel;        /* Space to hold the labels */
  Mem *aStack;        /* The operand stack, except string values */
  Mem *pTos;          /* Top entry in the operand stack */
  char **zArgv;       /* Text values used by the callback */
  char **azColName;   /* Becomes the 4th parameter to callbacks */
  int nCursor;        /* Number of slots in aCsr[] */
  Cursor *aCsr;       /* One element of this array for each open cursor */
  int nCursor;        /* Number of slots in apCsr[] */
  Cursor **apCsr;     /* One element of this array for each open cursor */
  Sorter *pSort;      /* A linked list of objects to be sorted */
  FILE *pFile;        /* At most one open file handler */
  int nField;         /* Number of file fields */
  char **azField;     /* Data for each file field */
  int nVar;           /* Number of entries in azVariable[] */
  char **azVar;       /* Values for the OP_Variable opcode */
  int *anVar;         /* Length of each value in azVariable[] */
Changes to src/vdbeaux.c.
732
733
734
735
736
737
738
739

740
741
742
743
744
745
746
747

748


749
750
751


752
753
754
755
756
757
758
732
733
734
735
736
737
738

739
740
741
742
743
744
745
746
747
748

749
750
751


752
753
754
755
756
757
758
759
760







-
+








+
-
+
+

-
-
+
+







    sqlite3BtreeCloseCursor(pCx->pCursor);
  }
  if( pCx->pBt ){
    sqlite3BtreeClose(pCx->pBt);
  }
  sqliteFree(pCx->pData);
  sqliteFree(pCx->aType);
  memset(pCx, 0, sizeof(Cursor));
  memset(pCx, 0, sizeof(*pCx));
}

/*
** Close all cursors
*/
static void closeAllCursors(Vdbe *p){
  int i;
  for(i=0; i<p->nCursor; i++){
    Cursor *pC = p->apCsr[i];
    sqlite3VdbeCleanupCursor(&p->aCsr[i]);
    sqlite3VdbeCleanupCursor(pC);
    sqliteFree(pC);
  }
  sqliteFree(p->aCsr);
  p->aCsr = 0;
  sqliteFree(p->apCsr);
  p->apCsr = 0;
  p->nCursor = 0;
}

/*
** Clean up the VM after execution.
**
** This routine will automatically close any cursors, lists, and/or