SQLite4
Check-in [6c7c9133d7]
Not logged in

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

Overview
Comment: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.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 6c7c9133d76d9e9b90b66d692c455dc7ef5c38d9
User & Date: drh 2013-07-24 20:07:54
Context
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
19:25
Replace test file distinct.test with the version from sqlite3. This version accounts for NGQP related changes. check-in: 41fc47c1cd user: dan tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/fts5.c.

2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850

        if( rc==SQLITE4_OK ){
          rc = sqlite4KVCursorData(pCsr->pCsr, 0, -1, &aData, &nData);
        }

        if( rc==SQLITE4_OK ){
          int i;
          ValueDecoder *pCodec;   /* The decoder object */

          rc = sqlite4VdbeCreateDecoder(db, aData, nData, pInfo->nCol, &pCodec);
          for(i=0; rc==SQLITE4_OK && i<pInfo->nCol; i++){
            rc = sqlite4VdbeDecodeValue(pCodec, i, 0, &pCsr->aMem[i]);
          }
          sqlite4VdbeDestroyDecoder(pCodec);
        }

        if( rc==SQLITE4_OK ) pCsr->bMemValid = 1;
      }
    }







|



|







2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850

        if( rc==SQLITE4_OK ){
          rc = sqlite4KVCursorData(pCsr->pCsr, 0, -1, &aData, &nData);
        }

        if( rc==SQLITE4_OK ){
          int i;
          RowDecoder *pCodec;   /* The decoder object */

          rc = sqlite4VdbeCreateDecoder(db, aData, nData, pInfo->nCol, &pCodec);
          for(i=0; rc==SQLITE4_OK && i<pInfo->nCol; i++){
            rc = sqlite4VdbeExtractColumn(pCodec, i, 0, &pCsr->aMem[i]);
          }
          sqlite4VdbeDestroyDecoder(pCodec);
        }

        if( rc==SQLITE4_OK ) pCsr->bMemValid = 1;
      }
    }

Changes to src/vdbe.c.

214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
....
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
....
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
....
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
....
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
....
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
....
2889
2890
2891
2892
2893
2894
2895
2896
2897





2898
2899
2900
2901
2902
2903
2904
....
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
....
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
....
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
....
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
....
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
....
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
    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;
    sqlite4_buffer_init(&pCx->key, p->db->pEnv->pMM);
  }
  return pCx;
}

/*
** Try to convert a value into a numeric representation if we can
** do so without loss of information.  In other words, if the string
................................................................................
** If the OPFLAG_CLEARCACHE bit is set on P5 and P1 is a pseudo-table cursor,
** then the cache of the cursor is reset prior to extracting the column.
** The first OP_Column against a pseudo-table after the value of the content
** register has changed should have this bit set.
*/
case OP_Column: {
  KVCursor *pKVCur;         /* Cursor for current entry in the KV storage */
  ValueDecoder *pCodec;     /* The decoder object */
  int p1;                   /* Index of VdbeCursor to decode */
  VdbeCursor *pC;           /* The VDBE cursor */
  Mem *pDest;               /* Where to write the results */
  const KVByteArray *aData; /* The content to be decoded */
  KVSize nData;             /* Size of aData[] in bytes */
  Mem *pDefault;            /* Default value from P4 */
  Mem *pReg;                /* */
................................................................................
    /* TODO: Fix this somehow... */
    int nField = pC->nField;
    if( pC->pKeyInfo && pC->pKeyInfo->nData ) nField = pC->pKeyInfo->nData;

    rc = sqlite4VdbeCreateDecoder(db, aData, nData, nField, &pCodec);
    if( rc==0 ){
      pDefault = (pOp->p4type==P4_MEM) ? pOp->p4.pMem : 0;
      rc = sqlite4VdbeDecodeValue(pCodec, pOp->p2, pDefault, pDest);
      sqlite4VdbeDestroyDecoder(pCodec);
    }
  }else{
    sqlite4VdbeMemSetNull(pDest);
  }
  UPDATE_MAX_BLOBSIZE(pDest);
  REGISTER_TRACE(pOp->p3, pDest);
................................................................................
  }else if( pOp->p4type==P4_INT32 ){
    nField = pOp->p4.i;
  }
  assert( pOp->p1>=0 );
  pCur = allocateCursor(p, pOp->p1, nField, iDb, 1);
  if( pCur==0 ) goto no_mem;
  pCur->nullRow = 1;
  pCur->isOrdered = 1;
  pCur->iRoot = p2;
  rc = sqlite4KVStoreOpenCursor(pX, &pCur->pKVCur);
  pCur->pKeyInfo = pKeyInfo;

  /* Set the VdbeCursor.isTable and isIndex variables. Previous versions of
  ** SQLite used to check if the root-page flags were sane at this point
  ** and report database corruption if they were not, but this check has
  ** since moved into the btree layer.  */  
  pCur->isTable = pOp->p4type!=P4_KEYINFO;
  pCur->isIndex = !pCur->isTable;
  break;
}

/* Opcode: OpenEphemeral P1 P2 * P4 P5
**
** Open a new cursor P1 to a transient table.
** The cursor is always opened read/write even if 
................................................................................
          SQLITE4_KVOPEN_TEMPORARY | SQLITE4_KVOPEN_NO_TRANSACTIONS
  );
  if( rc==SQLITE4_OK ) rc = sqlite4KVStoreOpenCursor(pCx->pTmpKV, &pCx->pKVCur);
  if( rc==SQLITE4_OK ) rc = sqlite4KVStoreBegin(pCx->pTmpKV, 2);

  pCx->pKeyInfo = pOp->p4.pKeyInfo;
  if( pCx->pKeyInfo ) pCx->pKeyInfo->enc = ENC(p->db);
  pCx->isIndex = !pCx->isTable;

  pCx->isOrdered = 1;
  break;
}

/* Opcode: OpenSorter P1 P2 * P4 *
**
** This opcode works like OP_OpenEphemeral except that it opens
** a transient index that is specifically designed to sort large
................................................................................
  VdbeCursor *pCx;

  assert( pOp->p1>=0 );
  pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0);
  if( pCx==0 ) goto no_mem;
  pCx->nullRow = 1;
  pCx->pseudoTableReg = pOp->p2;
  pCx->isTable = 1;
  pCx->isIndex = 0;
  break;
}

/* Opcode: Close P1 * * * *
**
** Close a cursor previously opened as P1.  If P1 is not
** currently open, this instruction is a no-op.
................................................................................
**
** P1 must be a cursor open on a PRIMARY KEY index. P3 is a cursor open
** on an auxiliary index on the same table. P3 must be pointing to a valid
** index entry.
**
** This opcode seeks cursor P1 so that it points to the PK index entry
** that corresponds to the same table row as the current entry that 
** cursor P3 points to. The entry must exist. If it does not, this opcode
** throws an SQLITE4_CORRUPT exception.





*/
case OP_SeekPk: {
  KVByteArray *aKey;              /* Key data from cursor pIdx */
  KVSize nKey;                    /* Size of aKey[] in bytes */
  VdbeCursor *pPk;                /* Cursor P1 */
  VdbeCursor *pIdx;               /* Cursor P3 */
  int nShort;                     /* Size of aKey[] without PK fields */
................................................................................
  }else{
    rc = sqlite4KVCursorKey(pIdx->pKVCur, (const KVByteArray **)&aKey, &nKey);
    if( rc!=SQLITE4_OK ) break;
    nShort = sqlite4VdbeShortKey(aKey, nKey, 
        pIdx->pKeyInfo->nField - pIdx->pKeyInfo->nPK, 0
    );
    nVarint = sqlite4VarintLen(pPk->iRoot);
    rc = sqlite4_buffer_resize(&pPk->key, nVarint + nKey - nShort);
    if( rc!=SQLITE4_OK ) break;
    putVarint32((u8 *)(pPk->key.p), pPk->iRoot);
    memcpy(((u8*)pPk->key.p) + nVarint, &aKey[nShort], nKey-nShort);
    assert( pPk->key.n>0 );

#if 0
    rc = sqlite4VdbeCursorMoveto(db, pPk);
#endif
  }

  break;
}

/* Opcode: SeekGe P1 P2 P3 P4 *
**
................................................................................
  KVSize nProbe;                  /* Size of aProbe[] in bytes */
  int dir;                        /* KV search dir (+ve or -ve) */
  const KVByteArray *aKey;        /* Pointer to final cursor key */
  KVSize nKey;                    /* Size of aKey[] in bytes */

  pC = p->apCsr[pOp->p1];
  pC->nullRow = 0;
  pC->key.n = 0;

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( pOp->p2!=0 );
  assert( pC!=0 );
  assert( pC->pseudoTableReg==0 );
  assert( OP_SeekLe == OP_SeekLt+1 );
  assert( OP_SeekGe == OP_SeekLt+2 );
  assert( OP_SeekGt == OP_SeekLt+3 );
  assert( pC->isOrdered );

  /* Encode a database key consisting of the contents of the P4 registers
  ** starting at register P3. Have the vdbecodec module allocate an extra
  ** free byte at the end of the database key (see below).  */
  op = pOp->opcode;
  nField = pOp->p4.i;
  pIn3 = &aMem[pOp->p3];
................................................................................
  KVCursor *pKVCur;
  KVByteArray *aKey;
  KVSize nKey;

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
  assert( pC->isTable );
  pKVCur = pC->pKVCur;
  rc = sqlite4VdbeEncodeKey(db, aMem+pOp->p2, 1, 1, pC->iRoot, 0,
                            &aKey, &nKey, 0);
  if( rc==SQLITE4_OK ){
    rc = sqlite4KVCursorSeek(pKVCur, aKey, nKey, 0);
    if( rc==SQLITE4_NOTFOUND ) rc = SQLITE4_CORRUPT_BKPT;
  }
................................................................................
  sqlite4_found_count++;
#endif

  alreadyExists = 0;
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( pOp->p4type==P4_INT32 );
  pC = p->apCsr[pOp->p1];
  pC->key.n = 0;
  assert( pC!=0 );
  pIn3 = &aMem[pOp->p3];
  assert( pC->pKVCur!=0 );
  assert( pC->isTable==0 || pOp->opcode==OP_NotExists );
  if( pOp->p4.i>0 ){
    rc = sqlite4VdbeEncodeKey(
        db, pIn3, pOp->p4.i, pOp->p4.i + (pOp->p5 & OPFLAG_PARTIALKEY),
        pC->iRoot, pC->pKeyInfo, &pProbe, &nProbe, 0
    );
    pFree = pProbe;
  }else{
................................................................................
** P1 must not be pseudo-table. It has to be a real table.
*/
case OP_Delete: {
  VdbeCursor *pC;
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
  assert( pC->key.n==0 );
  rc = sqlite4KVCursorDelete(pC->pKVCur);
  if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
  break;
}

/* Opcode: ResetCount * * * * *
**
................................................................................
  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->key.n==0 );
  assert( pC->pseudoTableReg==0 );
  if( pC->nullRow ){
    pOut->flags = MEM_Null;
    break;
#ifndef SQLITE4_OMIT_VIRTUALTABLE
  }else if( pC->pVtabCursor ){
    pVtab = pC->pVtabCursor->pVtab;







|







 







|







 







|







 







<



<
<
<
<
<
<
<







 







<

<







 







<
<







 







|
|
>
>
>
>
>







 







|

|
|
|
<
<
<
<







 







|








<







 







<







 







|



<







 







|







 







|







214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
....
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
....
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
....
2761
2762
2763
2764
2765
2766
2767

2768
2769
2770







2771
2772
2773
2774
2775
2776
2777
....
2814
2815
2816
2817
2818
2819
2820

2821

2822
2823
2824
2825
2826
2827
2828
....
2854
2855
2856
2857
2858
2859
2860


2861
2862
2863
2864
2865
2866
2867
....
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
....
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921




2922
2923
2924
2925
2926
2927
2928
....
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001

3002
3003
3004
3005
3006
3007
3008
....
3063
3064
3065
3066
3067
3068
3069

3070
3071
3072
3073
3074
3075
3076
....
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146

3147
3148
3149
3150
3151
3152
3153
....
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
....
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
    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;
    sqlite4_buffer_init(&pCx->sSeekKey, p->db->pEnv->pMM);
  }
  return pCx;
}

/*
** Try to convert a value into a numeric representation if we can
** do so without loss of information.  In other words, if the string
................................................................................
** If the OPFLAG_CLEARCACHE bit is set on P5 and P1 is a pseudo-table cursor,
** then the cache of the cursor is reset prior to extracting the column.
** The first OP_Column against a pseudo-table after the value of the content
** register has changed should have this bit set.
*/
case OP_Column: {
  KVCursor *pKVCur;         /* Cursor for current entry in the KV storage */
  RowDecoder *pCodec;       /* The decoder object */
  int p1;                   /* Index of VdbeCursor to decode */
  VdbeCursor *pC;           /* The VDBE cursor */
  Mem *pDest;               /* Where to write the results */
  const KVByteArray *aData; /* The content to be decoded */
  KVSize nData;             /* Size of aData[] in bytes */
  Mem *pDefault;            /* Default value from P4 */
  Mem *pReg;                /* */
................................................................................
    /* TODO: Fix this somehow... */
    int nField = pC->nField;
    if( pC->pKeyInfo && pC->pKeyInfo->nData ) nField = pC->pKeyInfo->nData;

    rc = sqlite4VdbeCreateDecoder(db, aData, nData, nField, &pCodec);
    if( rc==0 ){
      pDefault = (pOp->p4type==P4_MEM) ? pOp->p4.pMem : 0;
      rc = sqlite4VdbeExtractColumn(pCodec, pOp->p2, pDefault, pDest);
      sqlite4VdbeDestroyDecoder(pCodec);
    }
  }else{
    sqlite4VdbeMemSetNull(pDest);
  }
  UPDATE_MAX_BLOBSIZE(pDest);
  REGISTER_TRACE(pOp->p3, pDest);
................................................................................
  }else if( pOp->p4type==P4_INT32 ){
    nField = pOp->p4.i;
  }
  assert( pOp->p1>=0 );
  pCur = allocateCursor(p, pOp->p1, nField, iDb, 1);
  if( pCur==0 ) goto no_mem;
  pCur->nullRow = 1;

  pCur->iRoot = p2;
  rc = sqlite4KVStoreOpenCursor(pX, &pCur->pKVCur);
  pCur->pKeyInfo = pKeyInfo;







  break;
}

/* Opcode: OpenEphemeral P1 P2 * P4 P5
**
** Open a new cursor P1 to a transient table.
** The cursor is always opened read/write even if 
................................................................................
          SQLITE4_KVOPEN_TEMPORARY | SQLITE4_KVOPEN_NO_TRANSACTIONS
  );
  if( rc==SQLITE4_OK ) rc = sqlite4KVStoreOpenCursor(pCx->pTmpKV, &pCx->pKVCur);
  if( rc==SQLITE4_OK ) rc = sqlite4KVStoreBegin(pCx->pTmpKV, 2);

  pCx->pKeyInfo = pOp->p4.pKeyInfo;
  if( pCx->pKeyInfo ) pCx->pKeyInfo->enc = ENC(p->db);



  break;
}

/* Opcode: OpenSorter P1 P2 * P4 *
**
** This opcode works like OP_OpenEphemeral except that it opens
** a transient index that is specifically designed to sort large
................................................................................
  VdbeCursor *pCx;

  assert( pOp->p1>=0 );
  pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0);
  if( pCx==0 ) goto no_mem;
  pCx->nullRow = 1;
  pCx->pseudoTableReg = pOp->p2;


  break;
}

/* Opcode: Close P1 * * * *
**
** Close a cursor previously opened as P1.  If P1 is not
** currently open, this instruction is a no-op.
................................................................................
**
** P1 must be a cursor open on a PRIMARY KEY index. P3 is a cursor open
** on an auxiliary index on the same table. P3 must be pointing to a valid
** index entry.
**
** This opcode seeks cursor P1 so that it points to the PK index entry
** that corresponds to the same table row as the current entry that 
** cursor P3 points to. The entry must exist.
**
** Actually, the seek is deferred until it is actually needed and if the
** PRIMARY KEY index is never referenced, the seek never takes place.  The
** sqlite3VdbeCursorMoveto() does the seek, if necessary.  If the target
** row does not exist in the PRIMARY KEY table, then the
** sqlite3VdbeCursorMoveto() routine will throw an SQLITE4_CORRUPT error.
*/
case OP_SeekPk: {
  KVByteArray *aKey;              /* Key data from cursor pIdx */
  KVSize nKey;                    /* Size of aKey[] in bytes */
  VdbeCursor *pPk;                /* Cursor P1 */
  VdbeCursor *pIdx;               /* Cursor P3 */
  int nShort;                     /* Size of aKey[] without PK fields */
................................................................................
  }else{
    rc = sqlite4KVCursorKey(pIdx->pKVCur, (const KVByteArray **)&aKey, &nKey);
    if( rc!=SQLITE4_OK ) break;
    nShort = sqlite4VdbeShortKey(aKey, nKey, 
        pIdx->pKeyInfo->nField - pIdx->pKeyInfo->nPK, 0
    );
    nVarint = sqlite4VarintLen(pPk->iRoot);
    rc = sqlite4_buffer_resize(&pPk->sSeekKey, nVarint + nKey - nShort);
    if( rc!=SQLITE4_OK ) break;
    putVarint32((u8 *)(pPk->sSeekKey.p), pPk->iRoot);
    memcpy(((u8*)pPk->sSeekKey.p) + nVarint, &aKey[nShort], nKey-nShort);
    assert( pPk->sSeekKey.n>0 );




  }

  break;
}

/* Opcode: SeekGe P1 P2 P3 P4 *
**
................................................................................
  KVSize nProbe;                  /* Size of aProbe[] in bytes */
  int dir;                        /* KV search dir (+ve or -ve) */
  const KVByteArray *aKey;        /* Pointer to final cursor key */
  KVSize nKey;                    /* Size of aKey[] in bytes */

  pC = p->apCsr[pOp->p1];
  pC->nullRow = 0;
  pC->sSeekKey.n = 0;

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( pOp->p2!=0 );
  assert( pC!=0 );
  assert( pC->pseudoTableReg==0 );
  assert( OP_SeekLe == OP_SeekLt+1 );
  assert( OP_SeekGe == OP_SeekLt+2 );
  assert( OP_SeekGt == OP_SeekLt+3 );


  /* Encode a database key consisting of the contents of the P4 registers
  ** starting at register P3. Have the vdbecodec module allocate an extra
  ** free byte at the end of the database key (see below).  */
  op = pOp->opcode;
  nField = pOp->p4.i;
  pIn3 = &aMem[pOp->p3];
................................................................................
  KVCursor *pKVCur;
  KVByteArray *aKey;
  KVSize nKey;

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );

  pKVCur = pC->pKVCur;
  rc = sqlite4VdbeEncodeKey(db, aMem+pOp->p2, 1, 1, pC->iRoot, 0,
                            &aKey, &nKey, 0);
  if( rc==SQLITE4_OK ){
    rc = sqlite4KVCursorSeek(pKVCur, aKey, nKey, 0);
    if( rc==SQLITE4_NOTFOUND ) rc = SQLITE4_CORRUPT_BKPT;
  }
................................................................................
  sqlite4_found_count++;
#endif

  alreadyExists = 0;
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( pOp->p4type==P4_INT32 );
  pC = p->apCsr[pOp->p1];
  pC->sSeekKey.n = 0;
  assert( pC!=0 );
  pIn3 = &aMem[pOp->p3];
  assert( pC->pKVCur!=0 );

  if( pOp->p4.i>0 ){
    rc = sqlite4VdbeEncodeKey(
        db, pIn3, pOp->p4.i, pOp->p4.i + (pOp->p5 & OPFLAG_PARTIALKEY),
        pC->iRoot, pC->pKeyInfo, &pProbe, &nProbe, 0
    );
    pFree = pProbe;
  }else{
................................................................................
** P1 must not be pseudo-table. It has to be a real table.
*/
case OP_Delete: {
  VdbeCursor *pC;
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
  assert( pC->sSeekKey.n==0 );
  rc = sqlite4KVCursorDelete(pC->pKVCur);
  if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
  break;
}

/* Opcode: ResetCount * * * * *
**
................................................................................
  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
  }else if( pC->pVtabCursor ){
    pVtab = pC->pVtabCursor->pVtab;

Changes to src/vdbeInt.h.

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72


73
74
75
76
77
78
79
80
81
82
83
84
...
133
134
135
136
137
138
139

140
141
142
143
144
145
146
...
167
168
169
170
171
172
173
174









175
176
177
178
179
180
181
...
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
/* Opaque type used by code in vdbesort.c */
typedef struct VdbeSorter VdbeSorter;

/* Opaque type used by the explainer */
typedef struct Explain Explain;

/* Opaque type used by vdbecodec.c */
typedef struct ValueDecoder ValueDecoder;

/*
** A cursor is a pointer into a single database.
** The cursor can seek to an entry with a particular key, or
** loop over all entries.  You can also insert new
** entries or retrieve the key or data from the entry that the cursor
** is currently pointing to.
** 
** Every cursor that the virtual machine has open is represented by an
** instance of the following structure.
*/
struct VdbeCursor {
  KVCursor *pKVCur;     /* The cursor structure of the backend */
  KVStore *pTmpKV;      /* Separate file holding a temporary table */
  KeyInfo *pKeyInfo;    /* Info about index keys needed by index cursors */
  int iDb;              /* Index of cursor database in db->aDb[] (or -1) */
  int iRoot;            /* Root page of the table */
  int pseudoTableReg;   /* Register holding pseudotable content. */
  int nField;           /* Number of fields in the header */
  Bool zeroed;          /* True if zeroed out and ready for reuse */
  Bool atFirst;         /* True if pointing to first entry */
  Bool nullRow;         /* True if pointing to a row with no data */
  Bool isTable;         /* True if a table requiring integer keys */
  Bool isIndex;         /* True if an index containing keys only - no data */
  Bool isOrdered;       /* True if the underlying table is BTREE_UNORDERED */
  sqlite4_vtab_cursor *pVtabCursor;  /* The cursor for a virtual table */
  const sqlite4_module *pModule;     /* Module for cursor pVtabCursor */
  i64 seqCount;         /* Sequence counter */
  i64 movetoTarget;     /* Argument to the deferred move-to */
  VdbeSorter *pSorter;  /* Sorter object for OP_SorterOpen cursors */
  Fts5Cursor *pFts;     /* Fts5 cursor object (or NULL) */



  sqlite4_buffer key;

  /* Result of last sqlite4-Moveto() done by an OP_NotExists or 
  ** OP_IsUnique opcode on this cursor. */
  int seekResult;
};

/*
** 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, 
................................................................................
  sqlite4 *db;        /* The associated database connection */
  char *z;            /* String or BLOB value */
  union {
    sqlite4_num num;    /* Numeric value used by MEM_Int and/or MEM_Real */
    FuncDef *pDef;      /* Used only when flags==MEM_Agg */
    RowSet *pRowSet;    /* Used only when flags==MEM_RowSet */
    VdbeFrame *pFrame;  /* Used when flags==MEM_Frame */

  } u;
  int n;              /* Number of characters in string value, excluding '\0' */
  u16 flags;          /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
  u8  type;           /* One of SQLITE4_NULL, _TEXT, _INTEGER, etc */
  u8  enc;            /* SQLITE4_UTF8, SQLITE4_UTF16BE, SQLITE4_UTF16LE */
#ifdef SQLITE4_DEBUG
  Mem *pScopyFrom;    /* This Mem is a shallow copy of pScopyFrom */
................................................................................
#define MEM_Str       0x0002   /* Value is a string */
#define MEM_Int       0x0004   /* Value is an integer */
#define MEM_Real      0x0008   /* Value is a real number */
#define MEM_Blob      0x0010   /* Value is a BLOB */
#define MEM_RowSet    0x0020   /* Value is a RowSet object */
#define MEM_Frame     0x0040   /* Value is a VdbeFrame object */
#define MEM_Invalid   0x0080   /* Value is undefined */
#define MEM_TypeMask  0x00ff   /* Mask of type bits */











/* Whenever Mem contains a valid string or blob representation, one of
** the following flags must be set to determine the memory management
** policy for Mem.z.  The MEM_Term flag tells us whether or not the
** string is \000 or \u0000 terminated
*/
................................................................................
void sqlite4VdbeDeleteAuxData(VdbeFunc*, int);

int sqlite4VdbeCreateDecoder(
  sqlite4 *db,                /* The database connection */
  const unsigned char *aIn,   /* The input data blob */
  int nIn,                    /* Number of bytes in aIn[] */
  int mxCol,                  /* Maximum number of columns in aIn[] */
  ValueDecoder **ppOut        /* The newly generated decoder object */
);
int sqlite4VdbeDestroyDecoder(ValueDecoder *pDecoder);
int sqlite4VdbeDecodeValue(
  ValueDecoder *pDecoder,      /* The decoder for the whole string */
  int iVal,                    /* Index of the value to decode.  First is 0 */
  Mem *pDefault,               /* The default value.  Often NULL */
  Mem *pOut                    /* Write the result here */
);
int sqlite4VdbeEncodeData(
  sqlite4 *db,                /* The database connection */
  Mem *aIn,                   /* Array of values to encode */







|












|






<
<

<
<
<
<
<

<


<
>
>
|
<
<
<
<







 







>







 







|
>
>
>
>
>
>
>
>
>







 







|

|
|
|







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59


60





61

62
63

64
65
66




67
68
69
70
71
72
73
...
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
...
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
...
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
/* Opaque type used by code in vdbesort.c */
typedef struct VdbeSorter VdbeSorter;

/* Opaque type used by the explainer */
typedef struct Explain Explain;

/* Opaque type used by vdbecodec.c */
typedef struct RowDecoder RowDecoder;

/*
** A cursor is a pointer into a single database.
** The cursor can seek to an entry with a particular key, or
** loop over all entries.  You can also insert new
** entries or retrieve the key or data from the entry that the cursor
** is currently pointing to.
** 
** Every cursor that the virtual machine has open is represented by an
** instance of the following structure.
*/
struct VdbeCursor {
  KVCursor *pKVCur;     /* The cursor structure of the storage engine */
  KVStore *pTmpKV;      /* Separate file holding a temporary table */
  KeyInfo *pKeyInfo;    /* Info about index keys needed by index cursors */
  int iDb;              /* Index of cursor database in db->aDb[] (or -1) */
  int iRoot;            /* Root page of the table */
  int pseudoTableReg;   /* Register holding pseudotable content. */
  int nField;           /* Number of fields in the header */


  Bool nullRow;         /* True if pointing to a row with no data */





  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, 
................................................................................
  sqlite4 *db;        /* The associated database connection */
  char *z;            /* String or BLOB value */
  union {
    sqlite4_num num;    /* Numeric value used by MEM_Int and/or MEM_Real */
    FuncDef *pDef;      /* Used only when flags==MEM_Agg */
    RowSet *pRowSet;    /* Used only when flags==MEM_RowSet */
    VdbeFrame *pFrame;  /* Used when flags==MEM_Frame */
    sqlite4_int64 iOfst;/* Used when flags==MEM_FromKey */
  } u;
  int n;              /* Number of characters in string value, excluding '\0' */
  u16 flags;          /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
  u8  type;           /* One of SQLITE4_NULL, _TEXT, _INTEGER, etc */
  u8  enc;            /* SQLITE4_UTF8, SQLITE4_UTF16BE, SQLITE4_UTF16LE */
#ifdef SQLITE4_DEBUG
  Mem *pScopyFrom;    /* This Mem is a shallow copy of pScopyFrom */
................................................................................
#define MEM_Str       0x0002   /* Value is a string */
#define MEM_Int       0x0004   /* Value is an integer */
#define MEM_Real      0x0008   /* Value is a real number */
#define MEM_Blob      0x0010   /* Value is a BLOB */
#define MEM_RowSet    0x0020   /* Value is a RowSet object */
#define MEM_Frame     0x0040   /* Value is a VdbeFrame object */
#define MEM_Invalid   0x0080   /* Value is undefined */
#define MEM_TypeMask  0x01ff   /* Mask of type bits */

/*
** The following flag is used in the return from sqlite4VdbeDecodeValue()
** to signal that the value is stored in the key of the record.  If this
** bit is set and then the Mem.n field holds an offset into the key for
** the start of the value.  If Mem.type is set to SQLITE_REAL then numeric
** keys are interpreted as real numbers instead of integers.
*/
#define MEM_FromKey   0x0100   /* Actual value stored in key */


/* Whenever Mem contains a valid string or blob representation, one of
** the following flags must be set to determine the memory management
** policy for Mem.z.  The MEM_Term flag tells us whether or not the
** string is \000 or \u0000 terminated
*/
................................................................................
void sqlite4VdbeDeleteAuxData(VdbeFunc*, int);

int sqlite4VdbeCreateDecoder(
  sqlite4 *db,                /* The database connection */
  const unsigned char *aIn,   /* The input data blob */
  int nIn,                    /* Number of bytes in aIn[] */
  int mxCol,                  /* Maximum number of columns in aIn[] */
  RowDecoder **ppOut          /* The newly generated decoder object */
);
int sqlite4VdbeDestroyDecoder(RowDecoder *pDecoder);
int sqlite4VdbeExtractColumn(
  RowDecoder *pDecoder,        /* The decoder for the whole string */
  int iVal,                    /* Index of the value to decode.  First is 0 */
  Mem *pDefault,               /* The default value.  Often NULL */
  Mem *pOut                    /* Write the result here */
);
int sqlite4VdbeEncodeData(
  sqlite4 *db,                /* The database connection */
  Mem *aIn,                   /* Array of values to encode */

Changes to src/vdbeaux.c.

1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
....
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
  sqlite4Fts5Close(pCx->pFts);
  if( pCx->pKVCur ){
    sqlite4KVCursorClose(pCx->pKVCur);
  }
  if( pCx->pTmpKV ){
    sqlite4KVStoreClose(pCx->pTmpKV);
  }
  sqlite4_buffer_clear(&pCx->key);
#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;
................................................................................
**
** 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->key.n!=0 ){
    assert( pPk->pKeyInfo->nPK==0 );
    rc = sqlite4KVCursorSeek(pPk->pKVCur, pPk->key.p, pPk->key.n, 0);
    if( rc==SQLITE4_NOTFOUND ){
      rc = SQLITE4_CORRUPT_BKPT;
    }
    pPk->nullRow = 0;
    pPk->key.n = 0;
  }
  return rc;
}








|







 







|

|




|



<
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
....
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300

  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;
................................................................................
**
** 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;
}

Changes to src/vdbecodec.c.

14
15
16
17
18
19
20









21
22
23
24
25
26
27
28
29
..
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
..
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65






66
67
68
69
70
71
72
73
74
75
...
137
138
139
140
141
142
143
144




145
146
147
148
149
150
151
** insertion and reading from the key/value storage engine.
*/
#include "sqliteInt.h"
#include "vdbeInt.h"

/*
** The decoder object.









*/
struct ValueDecoder {
  sqlite4 *db;                /* The database connection */
  const u8 *a;                /* Content to be decoded */
  int n;                      /* Bytes of content in a[] */
  int mxCol;                  /* Maximum number of columns */
};

/*
................................................................................
** The aIn[] value must remain stable for the life of the decoder.
*/
int sqlite4VdbeCreateDecoder(
  sqlite4 *db,                /* The database connection */
  const unsigned char *aIn,   /* The input data blob */
  int nIn,                    /* Number of bytes in aIn[] */
  int mxCol,                  /* Maximum number of columns in aIn[] */
  ValueDecoder **ppOut        /* The newly generated decoder object */
){
  ValueDecoder *p;

  p = sqlite4DbMallocZero(db, sizeof(*p));
  *ppOut = p;
  if( p==0 ) return SQLITE4_NOMEM;
  p->db = db;
  p->a = aIn;
  p->n = nIn;
................................................................................
  return SQLITE4_OK;
}

/*
** Destroy a decoder object previously created
** using sqlite4VdbeCreateDecoder().
*/
int sqlite4VdbeDestroyDecoder(ValueDecoder *p){
  if( p ){
    sqlite4DbFree(p->db, p);
  }
  return SQLITE4_OK;
}

/*
** Decode a single value from a data string.






*/
int sqlite4VdbeDecodeValue(
  ValueDecoder *p,             /* The decoder for the whole string */
  int iVal,                    /* Index of the value to decode.  First is 0 */
  Mem *pDefault,               /* The default value.  Often NULL */
  Mem *pOut                    /* Write the result here */
){
  u32 size;                    /* Size of a field */
  sqlite4_uint64 ofst;         /* Offset to the payload */
  sqlite4_uint64 type;         /* Datatype */
................................................................................

      num.m = x;
      num.e = (e >> 2);
      if( e & 0x02 ) num.e = -1 * num.e;
      if( e & 0x01 ) num.sign = 1;
      pOut->u.num = num;
      MemSetTypeFlag(pOut, MEM_Real);





    }else if( cclass==0 ){
      if( size==0 ){
        sqlite4VdbeMemSetStr(pOut, "", 0, SQLITE4_UTF8, SQLITE4_TRANSIENT, 0);
      }else if( p->a[ofst]>0x02 ){
        sqlite4VdbeMemSetStr(pOut, (char*)(p->a+ofst), size, 
                             SQLITE4_UTF8, SQLITE4_TRANSIENT, 0);
      }else{







>
>
>
>
>
>
>
>
>

|







 







|

|







 







|







|
>
>
>
>
>
>

|
|







 







<
>
>
>
>







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
..
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
..
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
...
152
153
154
155
156
157
158

159
160
161
162
163
164
165
166
167
168
169
** insertion and reading from the key/value storage engine.
*/
#include "sqliteInt.h"
#include "vdbeInt.h"

/*
** The decoder object.
**
** An instance of this object is used to extract individual columns (numbers,
** strings, blobs, or NULLs) from a row of a table or index.  Usually the
** content is extract from the value side of the key/value pair, though
** sometimes information might be taken from the key as well.
**
** When the VDBE needs to extract multiple columns from the same row, it will
** try to reuse a single decoder object.  The decoder, therefore, should attempt
** to cache any intermediate results that might be useful on later invocations.
*/
struct RowDecoder {
  sqlite4 *db;                /* The database connection */
  const u8 *a;                /* Content to be decoded */
  int n;                      /* Bytes of content in a[] */
  int mxCol;                  /* Maximum number of columns */
};

/*
................................................................................
** The aIn[] value must remain stable for the life of the decoder.
*/
int sqlite4VdbeCreateDecoder(
  sqlite4 *db,                /* The database connection */
  const unsigned char *aIn,   /* The input data blob */
  int nIn,                    /* Number of bytes in aIn[] */
  int mxCol,                  /* Maximum number of columns in aIn[] */
  RowDecoder **ppOut          /* The newly generated decoder object */
){
  RowDecoder *p;

  p = sqlite4DbMallocZero(db, sizeof(*p));
  *ppOut = p;
  if( p==0 ) return SQLITE4_NOMEM;
  p->db = db;
  p->a = aIn;
  p->n = nIn;
................................................................................
  return SQLITE4_OK;
}

/*
** Destroy a decoder object previously created
** using sqlite4VdbeCreateDecoder().
*/
int sqlite4VdbeDestroyDecoder(RowDecoder *p){
  if( p ){
    sqlite4DbFree(p->db, p);
  }
  return SQLITE4_OK;
}

/*
** Decode a single value from a data string.  Store that value in pOut.
**
** If the value is a FROM-KEY reference (header codes 22 and 23) then the
** pOut->flags field is set to MEM_FromKey and pOut->iOfst is the offset into
** the key of the start of the actual value.  The pOut->type field is set to
** SQLITE_FLOAT if a numeric value extracted from the key should be interpreted
** as a floating point even if it has no fractional part.
*/
int sqlite4VdbeExtractColumn(
  RowDecoder *p,             /* The decoder for the whole string */
  int iVal,                    /* Index of the value to decode.  First is 0 */
  Mem *pDefault,               /* The default value.  Often NULL */
  Mem *pOut                    /* Write the result here */
){
  u32 size;                    /* Size of a field */
  sqlite4_uint64 ofst;         /* Offset to the payload */
  sqlite4_uint64 type;         /* Datatype */
................................................................................

      num.m = x;
      num.e = (e >> 2);
      if( e & 0x02 ) num.e = -1 * num.e;
      if( e & 0x01 ) num.sign = 1;
      pOut->u.num = num;
      MemSetTypeFlag(pOut, MEM_Real);

    }else if( type<=23 ){
      MemSetTypeFlag(pOut, MEM_FromKey);
      pOut->u.iOfst = subtype;
      pOut->type = type==23 ? SQLITE4_FLOAT : SQLITE4_INTEGER;
    }else if( cclass==0 ){
      if( size==0 ){
        sqlite4VdbeMemSetStr(pOut, "", 0, SQLITE4_UTF8, SQLITE4_TRANSIENT, 0);
      }else if( p->a[ofst]>0x02 ){
        sqlite4VdbeMemSetStr(pOut, (char*)(p->a+ofst), size, 
                             SQLITE4_UTF8, SQLITE4_TRANSIENT, 0);
      }else{