SQLite4
Check-in [5d08b14478]
Not logged in

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

Overview
Comment:Move all VdbeCursor methods into the vdbecursor.c source file.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 5d08b144786cbc384a3124db1ca8d47d96c4cf42
User & Date: drh 2013-07-24 21:38:20
Context
2013-07-25
00:55
Enhance the RowDecoder object so that it persists on a VdbeCursor and can be reused for multiple OP_Column operations. This opens the possibility of adding caching of header information and/or values in a later check-in. check-in: 6ed358511b user: drh tags: trunk
2013-07-24
21:38
Move all VdbeCursor methods into the vdbecursor.c source file. check-in: 5d08b14478 user: drh tags: trunk
20:07
Rename the ValueDecoder object to RowDecoder, in anticipation of enhancing it to be able to extract content from both the key and the value. Simplifications and cleanup of the VdbeCursor object. check-in: 6c7c9133d7 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/vdbe.c.

206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
....
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
....
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
....
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
....
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
  VdbeCursor *pCx = 0;
  nByte = 
      ROUND8(sizeof(VdbeCursor)) + 
      2*nField*sizeof(u32);

  assert( iCur<p->nCursor );
  if( p->apCsr[iCur] ){
    sqlite4VdbeFreeCursor(p, p->apCsr[iCur]);
    p->apCsr[iCur] = 0;
  }
  if( SQLITE4_OK==sqlite4VdbeMemGrow(pMem, nByte, 0) ){
    p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->z;
    memset(pCx, 0, sizeof(VdbeCursor));
    pCx->iDb = iDb;
    pCx->nField = nField;
................................................................................
  pC = p->apCsr[p1];
  assert( pC!=0 );
#ifndef SQLITE4_OMIT_VIRTUALTABLE
  assert( pC->pVtabCursor==0 );
#endif
  pKVCur = pC->pKVCur;
  if( pKVCur!=0 ){
    rc = sqlite4VdbeCursorMoveto(db, pC);
    if( rc!=SQLITE4_OK ) break;
    if( pC->nullRow ){
      aData = 0;
    }else{
      rc = sqlite4KVCursorData(pKVCur, 0, -1, &aData, &nData);
    }
  }else if( ALWAYS(pC->pseudoTableReg>0) ){
................................................................................
/* 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: {
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  sqlite4VdbeFreeCursor(p, p->apCsr[pOp->p1]);
  p->apCsr[pOp->p1] = 0;
  break;
}

/* Opcode: SeekPk P1 * P3 * *
**
** P1 must be a cursor open on a PRIMARY KEY index. P3 is a cursor open
................................................................................

  pOut = &aMem[pOp->p2];
  memAboutToChange(p, pOut);

  /* Note that RowKey and RowData are really exactly the same instruction */
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pC = p->apCsr[pOp->p1];
  rc = sqlite4VdbeCursorMoveto(db, pC);
  if( rc!=SQLITE4_OK ) break;
  assert( pC->nullRow==0 );
  assert( pC->pseudoTableReg==0 );
  assert( pC->pKVCur!=0 );
  pCrsr = pC->pKVCur;

  if( pOp->opcode==OP_RowKey ){
................................................................................
  i64 v;
  const KVByteArray *aKey;
  KVSize nKey;
  int n;

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pC = p->apCsr[pOp->p1];
  rc = sqlite4VdbeCursorMoveto(db, pC);
  if( rc!=SQLITE4_OK ) break;
  assert( pC->sSeekKey.n==0 );
  assert( pC->pseudoTableReg==0 );
  if( pC->nullRow ){
    pOut->flags = MEM_Null;
    break;
#ifndef SQLITE4_OMIT_VIRTUALTABLE







|







 







|







 







|







 







|







 







|







206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
....
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
....
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
....
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
....
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
  VdbeCursor *pCx = 0;
  nByte = 
      ROUND8(sizeof(VdbeCursor)) + 
      2*nField*sizeof(u32);

  assert( iCur<p->nCursor );
  if( p->apCsr[iCur] ){
    sqlite4VdbeFreeCursor(p->apCsr[iCur]);
    p->apCsr[iCur] = 0;
  }
  if( SQLITE4_OK==sqlite4VdbeMemGrow(pMem, nByte, 0) ){
    p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->z;
    memset(pCx, 0, sizeof(VdbeCursor));
    pCx->iDb = iDb;
    pCx->nField = nField;
................................................................................
  pC = p->apCsr[p1];
  assert( pC!=0 );
#ifndef SQLITE4_OMIT_VIRTUALTABLE
  assert( pC->pVtabCursor==0 );
#endif
  pKVCur = pC->pKVCur;
  if( pKVCur!=0 ){
    rc = sqlite4VdbeCursorMoveto(pC);
    if( rc!=SQLITE4_OK ) break;
    if( pC->nullRow ){
      aData = 0;
    }else{
      rc = sqlite4KVCursorData(pKVCur, 0, -1, &aData, &nData);
    }
  }else if( ALWAYS(pC->pseudoTableReg>0) ){
................................................................................
/* 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: {
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  sqlite4VdbeFreeCursor(p->apCsr[pOp->p1]);
  p->apCsr[pOp->p1] = 0;
  break;
}

/* Opcode: SeekPk P1 * P3 * *
**
** P1 must be a cursor open on a PRIMARY KEY index. P3 is a cursor open
................................................................................

  pOut = &aMem[pOp->p2];
  memAboutToChange(p, pOut);

  /* Note that RowKey and RowData are really exactly the same instruction */
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pC = p->apCsr[pOp->p1];
  rc = sqlite4VdbeCursorMoveto(pC);
  if( rc!=SQLITE4_OK ) break;
  assert( pC->nullRow==0 );
  assert( pC->pseudoTableReg==0 );
  assert( pC->pKVCur!=0 );
  pCrsr = pC->pKVCur;

  if( pOp->opcode==OP_RowKey ){
................................................................................
  i64 v;
  const KVByteArray *aKey;
  KVSize nKey;
  int n;

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pC = p->apCsr[pOp->p1];
  rc = sqlite4VdbeCursorMoveto(pC);
  if( rc!=SQLITE4_OK ) break;
  assert( pC->sSeekKey.n==0 );
  assert( pC->pseudoTableReg==0 );
  if( pC->nullRow ){
    pOut->flags = MEM_Null;
    break;
#ifndef SQLITE4_OMIT_VIRTUALTABLE

Changes to src/vdbeInt.h.

61
62
63
64
65
66
67








68
69
70
71
72
73
74
...
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
...
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
  i64 seqCount;         /* Sequence counter */
  VdbeSorter *pSorter;  /* Sorter object for OP_SorterOpen cursors */
  Fts5Cursor *pFts;     /* Fts5 cursor object (or NULL) */
  sqlite4_vtab_cursor *pVtabCursor;  /* The cursor for a virtual table */
  const sqlite4_module *pModule;     /* Module for cursor pVtabCursor */
  sqlite4_buffer sSeekKey;           /* Key for deferred seek */
};









/*
** When a sub-program is executed (OP_Program), a structure of this type
** is allocated to store the current value of the program counter, as
** well as the current memory cell array and various other frame specific
** values stored in the Vdbe struct. When the sub-program is finished, 
** these values are copied back to the Vdbe from the VdbeFrame structure,
................................................................................
#define VDBE_MAGIC_RUN      0xbdf20da3    /* VDBE is ready to execute */
#define VDBE_MAGIC_HALT     0x519c2973    /* VDBE has completed execution */
#define VDBE_MAGIC_DEAD     0xb606c3c8    /* The VDBE has been deallocated */

/*
** Function prototypes
*/
void sqlite4VdbeFreeCursor(Vdbe *, VdbeCursor*);
void sqliteVdbePopStack(Vdbe*,int);
#if defined(SQLITE4_DEBUG) || defined(VDBE_PROFILE)
void sqlite4VdbePrintOp(FILE*, int, Op*);
#endif
void sqlite4VdbeDeleteAuxData(VdbeFunc*, int);

int sqlite4VdbeCreateDecoder(
................................................................................
const char *sqlite4OpcodeName(int);
int sqlite4VdbeMemGrow(Mem *pMem, int n, int preserve);
int sqlite4VdbeCloseStatement(Vdbe *, int);
void sqlite4VdbeFrameDelete(VdbeFrame*);
int sqlite4VdbeFrameRestore(VdbeFrame *);
void sqlite4VdbeMemStoreType(Mem *pMem);
int sqlite4VdbeTransferError(Vdbe *p);
int sqlite4VdbeSeekEnd(VdbeCursor*, int);
int sqlite4VdbeNext(VdbeCursor*);
int sqlite4VdbePrevious(VdbeCursor*);
int sqlite4VdbeCursorMoveto(sqlite4 *, VdbeCursor *);
int sqlite4VdbeRollback(sqlite4 *db, int iLevel);
int sqlite4VdbeCommit(sqlite4 *db, int iLevel);

#ifdef SQLITE4_DEBUG
void sqlite4VdbeMemAboutToChange(Vdbe*,Mem*);
#endif








>
>
>
>
>
>
>
>







 







<







 







<
<
<
<







61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
...
344
345
346
347
348
349
350

351
352
353
354
355
356
357
...
429
430
431
432
433
434
435




436
437
438
439
440
441
442
  i64 seqCount;         /* Sequence counter */
  VdbeSorter *pSorter;  /* Sorter object for OP_SorterOpen cursors */
  Fts5Cursor *pFts;     /* Fts5 cursor object (or NULL) */
  sqlite4_vtab_cursor *pVtabCursor;  /* The cursor for a virtual table */
  const sqlite4_module *pModule;     /* Module for cursor pVtabCursor */
  sqlite4_buffer sSeekKey;           /* Key for deferred seek */
};

/* Methods for the VdbeCursor object */
void sqlite4VdbeFreeCursor(VdbeCursor*);
int sqlite4VdbeSeekEnd(VdbeCursor*, int);
int sqlite4VdbeNext(VdbeCursor*);
int sqlite4VdbePrevious(VdbeCursor*);
int sqlite4VdbeCursorMoveto(VdbeCursor *);


/*
** When a sub-program is executed (OP_Program), a structure of this type
** is allocated to store the current value of the program counter, as
** well as the current memory cell array and various other frame specific
** values stored in the Vdbe struct. When the sub-program is finished, 
** these values are copied back to the Vdbe from the VdbeFrame structure,
................................................................................
#define VDBE_MAGIC_RUN      0xbdf20da3    /* VDBE is ready to execute */
#define VDBE_MAGIC_HALT     0x519c2973    /* VDBE has completed execution */
#define VDBE_MAGIC_DEAD     0xb606c3c8    /* The VDBE has been deallocated */

/*
** Function prototypes
*/

void sqliteVdbePopStack(Vdbe*,int);
#if defined(SQLITE4_DEBUG) || defined(VDBE_PROFILE)
void sqlite4VdbePrintOp(FILE*, int, Op*);
#endif
void sqlite4VdbeDeleteAuxData(VdbeFunc*, int);

int sqlite4VdbeCreateDecoder(
................................................................................
const char *sqlite4OpcodeName(int);
int sqlite4VdbeMemGrow(Mem *pMem, int n, int preserve);
int sqlite4VdbeCloseStatement(Vdbe *, int);
void sqlite4VdbeFrameDelete(VdbeFrame*);
int sqlite4VdbeFrameRestore(VdbeFrame *);
void sqlite4VdbeMemStoreType(Mem *pMem);
int sqlite4VdbeTransferError(Vdbe *p);




int sqlite4VdbeRollback(sqlite4 *db, int iLevel);
int sqlite4VdbeCommit(sqlite4 *db, int iLevel);

#ifdef SQLITE4_DEBUG
void sqlite4VdbeMemAboutToChange(Vdbe*,Mem*);
#endif

Changes to src/vdbeaux.c.

1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
....
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
....
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
....
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
** allocated by the OP_Program opcode in sqlite4VdbeExec().
*/
void sqlite4VdbeFrameDelete(VdbeFrame *p){
  int i;
  Mem *aMem = VdbeFrameMem(p);
  VdbeCursor **apCsr = (VdbeCursor **)&aMem[p->nChildMem];
  for(i=0; i<p->nChildCsr; i++){
    sqlite4VdbeFreeCursor(p->v, apCsr[i]);
  }
  releaseMemArray(aMem, p->nChildMem);
  sqlite4DbFree(p->v->db, p);
}

#ifndef SQLITE4_OMIT_EXPLAIN
/*
................................................................................
      p->aMem[n].db = db;
    }
  }
  p->explain = pParse->explain;
  sqlite4VdbeRewind(p);
}

/*
** Close a VDBE cursor and release all the resources that cursor 
** happens to hold.
*/
void sqlite4VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
  if( pCx==0 ){
    return;
  }
  sqlite4Fts5Close(pCx->pFts);
  if( pCx->pKVCur ){
    sqlite4KVCursorClose(pCx->pKVCur);
  }
  if( pCx->pTmpKV ){
    sqlite4KVStoreClose(pCx->pTmpKV);
  }
  sqlite4_buffer_clear(&pCx->sSeekKey);
#ifndef SQLITE4_OMIT_VIRTUALTABLE
  if( pCx->pVtabCursor ){
    sqlite4_vtab_cursor *pVtabCursor = pCx->pVtabCursor;
    const sqlite4_module *pModule = pCx->pModule;
    p->inVtabMethod = 1;
    pModule->xClose(pVtabCursor);
    p->inVtabMethod = 0;
  }
#endif
}

/*
** Copy the values stored in the VdbeFrame structure to its Vdbe. This
** is used, for example, when a trigger sub-program is halted to restore
** control to the main program.
*/
int sqlite4VdbeFrameRestore(VdbeFrame *pFrame){
  Vdbe *v = pFrame->v;
................................................................................
  p->nFrame = 0;

  if( p->apCsr ){
    int i;
    for(i=0; i<p->nCursor; i++){
      VdbeCursor *pC = p->apCsr[i];
      if( pC ){
        sqlite4VdbeFreeCursor(p, pC);
        p->apCsr[i] = 0;
      }
    }
  }
  if( p->aMem ){
    releaseMemArray(&p->aMem[1], p->nMem);
  }
................................................................................
  assert( iVar>0 );
  if( iVar>32 ){
    v->expmask = 0xffffffff;
  }else{
    v->expmask |= ((u32)1 << (iVar-1));
  }
}

/*
** Cursor pPk is open on a primary key index. If there is currently a
** deferred seek pending on the cursor, do the actual seek now.
**
** If the operation is a success, SQLITE4_OK is returned. Or, if the
** required entry is not found in the PK index, SQLITE4_CORRUPT. Or if 
** some other error occurs, an error code is returned.
*/
int sqlite4VdbeCursorMoveto(sqlite4 *db, VdbeCursor *pPk){
  int rc = SQLITE4_OK;            /* Return code */
  if( pPk->sSeekKey.n!=0 ){
    assert( pPk->pKeyInfo->nPK==0 );
    rc = sqlite4KVCursorSeek(pPk->pKVCur, pPk->sSeekKey.p, pPk->sSeekKey.n, 0);
    if( rc==SQLITE4_NOTFOUND ){
      rc = SQLITE4_CORRUPT_BKPT;
    }
    pPk->nullRow = 0;
    pPk->sSeekKey.n = 0;
  }
  return rc;
}







|







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







|







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
....
1482
1483
1484
1485
1486
1487
1488



























1489
1490
1491
1492
1493
1494
1495
....
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
....
2245
2246
2247
2248
2249
2250
2251






















** allocated by the OP_Program opcode in sqlite4VdbeExec().
*/
void sqlite4VdbeFrameDelete(VdbeFrame *p){
  int i;
  Mem *aMem = VdbeFrameMem(p);
  VdbeCursor **apCsr = (VdbeCursor **)&aMem[p->nChildMem];
  for(i=0; i<p->nChildCsr; i++){
    sqlite4VdbeFreeCursor(apCsr[i]);
  }
  releaseMemArray(aMem, p->nChildMem);
  sqlite4DbFree(p->v->db, p);
}

#ifndef SQLITE4_OMIT_EXPLAIN
/*
................................................................................
      p->aMem[n].db = db;
    }
  }
  p->explain = pParse->explain;
  sqlite4VdbeRewind(p);
}




























/*
** Copy the values stored in the VdbeFrame structure to its Vdbe. This
** is used, for example, when a trigger sub-program is halted to restore
** control to the main program.
*/
int sqlite4VdbeFrameRestore(VdbeFrame *pFrame){
  Vdbe *v = pFrame->v;
................................................................................
  p->nFrame = 0;

  if( p->apCsr ){
    int i;
    for(i=0; i<p->nCursor; i++){
      VdbeCursor *pC = p->apCsr[i];
      if( pC ){
        sqlite4VdbeFreeCursor(pC);
        p->apCsr[i] = 0;
      }
    }
  }
  if( p->aMem ){
    releaseMemArray(&p->aMem[1], p->nMem);
  }
................................................................................
  assert( iVar>0 );
  if( iVar>32 ){
    v->expmask = 0xffffffff;
  }else{
    v->expmask |= ((u32)1 << (iVar-1));
  }
}






















Changes to src/vdbecursor.c.

1
2
3
4
5
6
7
8
9
..
97
98
99
100
101
102
103



















































/*
** 2012 February 16
**
** 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.
................................................................................
      iTabno = 0;
      sqlite4GetVarint64(aKey, nKey, &iTabno);
      if( iTabno!=pC->iRoot ) rc = SQLITE4_NOTFOUND;
    }
  }
  return rc;
}




















































|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
..
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*
** 2012-02-16
**
** 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.
................................................................................
      iTabno = 0;
      sqlite4GetVarint64(aKey, nKey, &iTabno);
      if( iTabno!=pC->iRoot ) rc = SQLITE4_NOTFOUND;
    }
  }
  return rc;
}


/*
** Close a VDBE cursor and release all the resources that cursor 
** happens to hold.
*/
void sqlite4VdbeFreeCursor(VdbeCursor *pCx){
  if( pCx==0 ){
    return;
  }
  sqlite4Fts5Close(pCx->pFts);
  if( pCx->pKVCur ){
    sqlite4KVCursorClose(pCx->pKVCur);
  }
  if( pCx->pTmpKV ){
    sqlite4KVStoreClose(pCx->pTmpKV);
  }
  sqlite4_buffer_clear(&pCx->sSeekKey);
#ifndef SQLITE4_OMIT_VIRTUALTABLE
  if( pCx->pVtabCursor ){
    sqlite4_vtab_cursor *pVtabCursor = pCx->pVtabCursor;
    const sqlite4_module *pModule = pCx->pModule;
    p->inVtabMethod = 1;
    pModule->xClose(pVtabCursor);
    p->inVtabMethod = 0;
  }
#endif
}


/*
** Cursor pPk is open on a primary key index. If there is currently a
** deferred seek pending on the cursor, do the actual seek now.
**
** If the operation is a success, SQLITE4_OK is returned. Or, if the
** required entry is not found in the PK index, SQLITE4_CORRUPT. Or if 
** some other error occurs, an error code is returned.
*/
int sqlite4VdbeCursorMoveto(VdbeCursor *pPk){
  int rc = SQLITE4_OK;            /* Return code */
  if( pPk->sSeekKey.n!=0 ){
    assert( pPk->pKeyInfo->nPK==0 );
    rc = sqlite4KVCursorSeek(pPk->pKVCur, pPk->sSeekKey.p, pPk->sSeekKey.n, 0);
    if( rc==SQLITE4_NOTFOUND ){
      rc = SQLITE4_CORRUPT_BKPT;
    }
    pPk->nullRow = 0;
    pPk->sSeekKey.n = 0;
  }
  return rc;
}