SQLite4
Check-in [30167422e4]
Not logged in

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

Overview
Comment:Add decoder logic to facilitate extracting column values from the key of a key/value pair for a row.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 30167422e474fd427d033f0db087f0333e3435c2
User & Date: drh 2013-07-26 15:30:15
Context
2013-07-26
16:20
Change the data encoding (again) to make content-in-key use fewer bytes, since one suspects that this will become a common encoding. FILE FORMAT CHANGE. check-in: 0275ee48db user: drh tags: trunk
15:30
Add decoder logic to facilitate extracting column values from the key of a key/value pair for a row. check-in: 30167422e4 user: drh tags: trunk
2013-07-25
23:26
Add the kvreplace(K,V) pragma for use in testing. check-in: b5ceafc26f user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/pragma.c.

651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
    int r1, r2;
    Vdbe *v = sqlite4GetVdbe(pParse);
    pParse->nTab = 1;
    pParse->nMem = 3;
    sqlite4BeginWriteOperation(pParse, 0, iDb);
    r1 = sqlite4ExprCodeTarget(pParse, pList->a[0].pExpr, 1);
    sqlite4VdbeAddOp4(v, OP_HaltIfNull, SQLITE4_CONSTRAINT, OE_Abort,
                         r1, "key may not be null", SQLITE4_STATIC);
    sqlite4VdbeAddOp1(v, OP_ToBlob, r1);
    r2 = sqlite4ExprCodeTarget(pParse, pList->a[1].pExpr, 2);
    sqlite4VdbeAddOp4(v, OP_HaltIfNull, SQLITE4_CONSTRAINT, OE_Abort,
                         r2, "value may not be null", SQLITE4_STATIC);
    sqlite4VdbeAddOp1(v, OP_ToBlob, r2);
    sqlite4VdbeAddOp0(v, OP_OpenWrite);
    sqlite4VdbeAddOp3(v, OP_IdxInsert, 0, r2, r1);
    sqlite4VdbeAddOp0(v, OP_Halt);
  }else
#endif /* SQLITE4_DEBUG








|



|







651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
    int r1, r2;
    Vdbe *v = sqlite4GetVdbe(pParse);
    pParse->nTab = 1;
    pParse->nMem = 3;
    sqlite4BeginWriteOperation(pParse, 0, iDb);
    r1 = sqlite4ExprCodeTarget(pParse, pList->a[0].pExpr, 1);
    sqlite4VdbeAddOp4(v, OP_HaltIfNull, SQLITE4_CONSTRAINT, OE_Abort,
                         r1, "key may not be null", P4_STATIC);
    sqlite4VdbeAddOp1(v, OP_ToBlob, r1);
    r2 = sqlite4ExprCodeTarget(pParse, pList->a[1].pExpr, 2);
    sqlite4VdbeAddOp4(v, OP_HaltIfNull, SQLITE4_CONSTRAINT, OE_Abort,
                         r2, "value may not be null", P4_STATIC);
    sqlite4VdbeAddOp1(v, OP_ToBlob, r2);
    sqlite4VdbeAddOp0(v, OP_OpenWrite);
    sqlite4VdbeAddOp3(v, OP_IdxInsert, 0, r2, r1);
    sqlite4VdbeAddOp0(v, OP_Halt);
  }else
#endif /* SQLITE4_DEBUG

Changes to src/vdbe.c.

3255
3256
3257
3258
3259
3260
3261

3262
3263
3264
3265
3266
3267
3268
....
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
....
3683
3684
3685
3686
3687
3688
3689

3690
3691
3692
3693
3694
3695
3696
....
3705
3706
3707
3708
3709
3710
3711
3712
3713

3714
3715
3716
3717
3718
3719
3720
case OP_NewRowid: {           /* out2-prerelease */
  i64 v;                   /* The new rowid */
  VdbeCursor *pC;          /* Cursor of table to get the new rowid */
  const KVByteArray *aKey; /* Key of an existing row */
  KVSize nKey;             /* Size of the existing row key */
  int n;                   /* Number of bytes decoded */
  i64 i3;                  /* Integer value from pIn3 */


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

  /* Some compilers complain about constants of the form 0x7fffffffffffffff.
................................................................................
    rc = sqlite4KVCursorKey(pC->pKVCur, &aKey, &nKey);
    if( rc==SQLITE4_OK ){
      n = sqlite4GetVarint64((u8 *)aKey, nKey, (u64 *)&v);
      if( n==0 ) rc = SQLITE4_CORRUPT_BKPT;
      if( v!=pC->iRoot ) rc = SQLITE4_CORRUPT_BKPT;
    }
    if( rc==SQLITE4_OK ){
      n = sqlite4VdbeDecodeIntKey(&aKey[n], nKey-n, &v);
      if( n==0 || v==LARGEST_INT64 ){
        assert( 0 );
        rc = SQLITE4_FULL;
      }
    }
  }else{
    break;
  }
................................................................................
*/
case OP_Rowid: {                 /* out2-prerelease */
  VdbeCursor *pC;
  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->pPseudoTab==0 );
................................................................................
    rc = pModule->xRowid(pC->pVtabCursor, &v);
    importVtabErrMsg(p, pVtab);
#endif /* SQLITE4_OMIT_VIRTUALTABLE */
  }else{
    rc = sqlite4KVCursorKey(pC->pKVCur, &aKey, &nKey);
    if( rc==SQLITE4_OK ){
      n = sqlite4GetVarint64(aKey, nKey, (sqlite4_uint64*)&v);
      n = sqlite4VdbeDecodeIntKey(&aKey[n], nKey-n, &v);
      if( n==0 ) rc = SQLITE4_CORRUPT;

    }
  }
  pOut->u.num = sqlite4_num_from_int64(v);
  break;
}

/* Opcode: NullRow P1 * * * *







>







 







|
|







 







>







 







|

>







3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
....
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
....
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
....
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
case OP_NewRowid: {           /* out2-prerelease */
  i64 v;                   /* The new rowid */
  VdbeCursor *pC;          /* Cursor of table to get the new rowid */
  const KVByteArray *aKey; /* Key of an existing row */
  KVSize nKey;             /* Size of the existing row key */
  int n;                   /* Number of bytes decoded */
  i64 i3;                  /* Integer value from pIn3 */
  sqlite4_num vNum;        /* Intermediate result */

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

  /* Some compilers complain about constants of the form 0x7fffffffffffffff.
................................................................................
    rc = sqlite4KVCursorKey(pC->pKVCur, &aKey, &nKey);
    if( rc==SQLITE4_OK ){
      n = sqlite4GetVarint64((u8 *)aKey, nKey, (u64 *)&v);
      if( n==0 ) rc = SQLITE4_CORRUPT_BKPT;
      if( v!=pC->iRoot ) rc = SQLITE4_CORRUPT_BKPT;
    }
    if( rc==SQLITE4_OK ){
      n = sqlite4VdbeDecodeNumericKey(&aKey[n], nKey-n, &vNum);
      if( n==0 || (v = sqlite4_num_to_int64(vNum,0))==LARGEST_INT64 ){
        assert( 0 );
        rc = SQLITE4_FULL;
      }
    }
  }else{
    break;
  }
................................................................................
*/
case OP_Rowid: {                 /* out2-prerelease */
  VdbeCursor *pC;
  i64 v;
  const KVByteArray *aKey;
  KVSize nKey;
  int n;
  sqlite4_num vNum;

  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->pPseudoTab==0 );
................................................................................
    rc = pModule->xRowid(pC->pVtabCursor, &v);
    importVtabErrMsg(p, pVtab);
#endif /* SQLITE4_OMIT_VIRTUALTABLE */
  }else{
    rc = sqlite4KVCursorKey(pC->pKVCur, &aKey, &nKey);
    if( rc==SQLITE4_OK ){
      n = sqlite4GetVarint64(aKey, nKey, (sqlite4_uint64*)&v);
      n = sqlite4VdbeDecodeNumericKey(&aKey[n], nKey-n, &vNum);
      if( n==0 ) rc = SQLITE4_CORRUPT;
      v = sqlite4_num_to_int64(vNum,0);
    }
  }
  pOut->u.num = sqlite4_num_from_int64(v);
  break;
}

/* Opcode: NullRow P1 * * * *

Changes to src/vdbeInt.h.

133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
...
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
...
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
  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
*/
#define MEM_Term      0x0200   /* String rep is nul terminated */
................................................................................
  int iTabno,                  /* The table this key applies to */
  KeyInfo *pKeyInfo,           /* Collating sequence information */
  u8 **pzOut,                  /* Write the resulting key here */
  int *pnOut,                  /* Number of bytes in the key */
  int nExtra                   /* Append extra bytes on end of key */
);
int sqlite4VdbeEncodeIntKey(u8 *aBuf,sqlite4_int64 v);
int sqlite4VdbeDecodeIntKey(const KVByteArray*, KVSize, sqlite4_int64*);
int sqlite4VdbeShortKey(const u8 *, int, int, int *);
int sqlite4MemCompare(Mem*, Mem*, const CollSeq*,int*);
int sqlite4VdbeExec(Vdbe*);
int sqlite4VdbeList(Vdbe*);
int sqlite4VdbeHalt(Vdbe*);
int sqlite4VdbeChangeEncoding(Mem *, int);
int sqlite4VdbeMemTooBig(Mem*);







<







 







|
<
<
<
<
<
<
<
<
<
<







 







|







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
...
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
  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
*/
#define MEM_Term      0x0200   /* String rep is nul terminated */
................................................................................
  int iTabno,                  /* The table this key applies to */
  KeyInfo *pKeyInfo,           /* Collating sequence information */
  u8 **pzOut,                  /* Write the resulting key here */
  int *pnOut,                  /* Number of bytes in the key */
  int nExtra                   /* Append extra bytes on end of key */
);
int sqlite4VdbeEncodeIntKey(u8 *aBuf,sqlite4_int64 v);
int sqlite4VdbeDecodeNumericKey(const KVByteArray*, KVSize, sqlite4_num*);
int sqlite4VdbeShortKey(const u8 *, int, int, int *);
int sqlite4MemCompare(Mem*, Mem*, const CollSeq*,int*);
int sqlite4VdbeExec(Vdbe*);
int sqlite4VdbeList(Vdbe*);
int sqlite4VdbeHalt(Vdbe*);
int sqlite4VdbeChangeEncoding(Mem *, int);
int sqlite4VdbeMemTooBig(Mem*);

Changes to src/vdbecodec.c.

108
109
110
111
112
113
114
115























































































































































































































116
117
118
119
120
121









































































































122
123
124
125
126
127
128
...
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
...
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
...
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
...
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
    p->n = pReg->n;
    rc = SQLITE4_OK;
  }
  return rc;
}

/*
** 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 sqlite4VdbeDecoderGetColumn(
  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 */
){
................................................................................
         n += sz;
      }
      size = (type-24)/3;
    }else if( type<=2 ){
      size = 0;
    }else if( type<=10 ){
      size = type - 2;
    }else if( type<=22 ){
      size = type - 9;
    }else{
      /* value in key */
      size = 0;
      sz = sqlite4GetVarint64(p->a+n, p->n-n, &subtype);
      if( sz==0 ) return SQLITE4_CORRUPT;
      n += sz;
................................................................................
      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{
................................................................................
    assert( flags & MEM_Blob );
    n = pMem->n;
    a = (u8*)pMem->z;
    s = 1;
    t = 0;
    if( enlargeEncoderAllocation(p, (n*8+6)/7 + 2) ) return SQLITE4_NOMEM;
    p->aOut[p->nOut++] = 0x25;   /* Blob */
     for(i=0; i<n; i++){
      unsigned char x = a[i];
      p->aOut[p->nOut++] = 0x80 | t | (x>>s);
      if( s<7 ){
        t = x<<(7-s);
        s++;
      }else{
        p->aOut[p->nOut++] = 0x80 | x;
................................................................................
    sqlite4DbFree(db, x.aOut);
  }else{
    *paOut = x.aOut;
    *pnOut = x.nOut;
  }
  return rc;
}

/*
** Decode an integer key encoding.  Return the number of bytes in the
** encoding on success.  On an error, return 0.
*/
int sqlite4VdbeDecodeIntKey(
  const KVByteArray *aKey,       /* Input encoding */
  KVSize nKey,                   /* Number of bytes in aKey[] */
  sqlite4_int64 *pVal            /* Write the result here */
){
  int isNeg;
  int e, x;
  int i;
  sqlite4_int64 m;
  KVByteArray aBuf[12];

  if( nKey<2 ) return 0;
  if( nKey>sizeof(aBuf) ) nKey = sizeof(aBuf);
  x = aKey[0];
  if( x>=0x09 && x<=0x13 ){
    isNeg = 1;
    memcpy(aBuf, aKey, nKey);
    aKey = aBuf;
    for(i=1; i<nKey; i++) aBuf[i] ^= 0xff;
    e = 0x13-x;
  }else if( x>=0x17 && x<=0x21 ){
    isNeg = 0;
    e = x-0x17;
  }else if( x==0x15 ){
    *pVal = 0;
    return 1;
  }else{
    return 0;
  }
  m = 0;
  i = 1;
  do{
    m = m*100 + aKey[i]/2;
    e--;
  }while( aKey[i++] & 1 );
  while( (e--)>0 ){ m = m*100; }

  if( isNeg ){
    *pVal = -m;
  }else{
    *pVal = m;
  }
  return m==0 ? 0 : i;
}







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

<
<
<
<
<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|







 







|
<
<







 







|







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331





332
333
334
335
336
337
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
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
...
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
...
513
514
515
516
517
518
519
520


521
522
523
524
525
526
527
...
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
....
1063
1064
1065
1066
1067
1068
1069

















































    p->n = pReg->n;
    rc = SQLITE4_OK;
  }
  return rc;
}

/*
** Make sure the p->aKey and p->nKey fields are valid and current.
*/
static int decoderFetchKey(RowDecoder *p){
  VdbeCursor *pCur = p->pCur;
  int rc;
  if( pCur==0 ){
    rc = sqlite4KVCursorKey(p->pKVCur, &p->aKey, &p->nKey);
    return rc;
  }
  assert( p->a!=0 );
  if( p->aKey ) return SQLITE4_OK;
  if( pCur->pKVCur ){
    rc = sqlite4KVCursorKey(pCur->pKVCur, &p->aKey, &p->nKey);
  }else{
    Mem *pReg = pCur->pPseudoTab + 1;
    assert( pReg!=0 );
    p->aKey = (const KVByteArray*)pReg->z;
    p->nKey = pReg->n;
    rc = SQLITE4_OK;
  }
  return rc;
}

/*
** Decode a blob from a key.  The blob-key is in a[0] through a[n-1].
** xorMask is either 0x00 for ascending order or 0xff for descending.
** Store the blob in pOut.
*/
static int decoderMemSetFromBlob(
  const KVByteArray *a, KVSize n, /* The blob as a key */
  unsigned int xorMask,           /* 0x00 (ascending) or 0xff (descending) */
  Mem *pOut                       /* Write the blob here */
){
  int rc;
  unsigned int m = 0;
  int i, j, k;

  sqlite4VdbeMemSetStr(pOut, "", 0, 0, 0, 0);
  rc = sqlite4VdbeMemGrow(pOut, n, 0);
  if( rc==SQLITE4_OK ){
    i = 0;
    j = 0;
    k = 0;
    while( i<n ){
      m = (m<<7) | ((a[i++] ^ xorMask)&0x7f);
      j += 7;
      if( j>=8 ){
        pOut->z[k++] = (m>>(j-8))&0xff;
        j -= 8;
      }
    }
    if( j>0 ){
      pOut->z[k] = m<<(7-j);
    }
    pOut->n = k;
  }
  return rc;
}

/*
** Decode a numeric key encoding.  Return the number of bytes in the
** encoding on success.  On an error, return 0.
*/
int sqlite4VdbeDecodeNumericKey(
  const KVByteArray *aKey,       /* Input encoding */
  KVSize nKey,                   /* Number of bytes in aKey[] */
  sqlite4_num *pVal              /* Write the result here */
){
  unsigned int i, y;
  unsigned int xorMask = 0;
  short e;
  sqlite4_uint64 m;
  sqlite4_int64 eBig;
  KVByteArray aInvertedKey[4];

  pVal->approx = 0;
  pVal->sign = 0;
  if( nKey<1 ) return 0;
  switch( aKey[0] ){
    case 0x06:   /* NaN ascending */
    case 0xf9:   /* NaN descending */
      pVal->m = 0;
      pVal->e = 1000;
      return 1;

    case 0x07:   /* -inf ascending */
    case 0xf8:   /* -inf descending */
      pVal->m = 1;
      pVal->sign = 1;
      pVal->e = 1000;
      return 1;

    case 0x15:   /* zero ascending */
    case 0xea:   /* zero descending */
      pVal->m = 0;
      pVal->e = 0;
      return 1;

    case 0x23:   /* +inf ascending */
    case 0xdc:   /* +inf descending */
      pVal->m = 1;
      pVal->e = 1000;
      return 1;

    case 0x09:
    case 0x0a:
    case 0x0b:
    case 0x0c:
    case 0x0d:
    case 0x0e:
    case 0x0f:
    case 0x10:
    case 0x11:
    case 0x12:
    case 0x13:   /* -medium ascending */
      pVal->sign = 1;
      xorMask = 0xff;
      e = 0x13 - aKey[0];
      i = 1;
      break;

    case 0xf6:
    case 0xf5:
    case 0xf4:
    case 0xf3:
    case 0xf2:
    case 0xf1:
    case 0xf0:
    case 0xef:
    case 0xee:
    case 0xed:
    case 0xec:   /* -medium descending */
      pVal->sign = 1;
      e = aKey[0] - 0xec;
      i = 1;
      break;

    case 0x17:
    case 0x18:
    case 0x19:
    case 0x1a:
    case 0x1b:
    case 0x1c:
    case 0x1d:
    case 0x1e:
    case 0x1f:
    case 0x20:
    case 0x21:   /* +medium ascending */
      e = aKey[0] - 0x17;
      i = 1;
      break;

    case 0xe8:
    case 0xe7:
    case 0xe6:
    case 0xe5:
    case 0xe4:
    case 0xe3:
    case 0xe2:
    case 0xe1:
    case 0xe0:
    case 0xdf:
    case 0xde:   /* +medium descending */
      e = 0xe8 - aKey[0];
      xorMask = 0xff;
      i = 1;
      break;

    case 0x14:   /* -small ascending */
    case 0xe9:   /* +small descending */
      i = 1 + sqlite4GetVarint64(aKey+1, 2, &eBig);
      e = (short)-eBig;
      xorMask = 0xff;
      break;

    case 0x16:   /* +small ascending */
    case 0xeb:   /* -small descending */
      aInvertedKey[0] = aKey[1] ^ 0xff;
      aInvertedKey[1] = aKey[2] ^ 0xff;
      i = 1 + sqlite4GetVarint64(aInvertedKey, 2, &eBig);
      e = (short)-eBig;
      break;

    case 0x08:   /* -large ascending */
    case 0xdd:   /* +large descending */
      aInvertedKey[0] = aKey[1] ^ 0xff;
      aInvertedKey[1] = aKey[2] ^ 0xff;
      i = 1 + sqlite4GetVarint64(aInvertedKey, 2, &eBig);
      e = (short)eBig;
      xorMask = 0xff;
      break;

    case 0x22:   /* +large ascending */
    case 0xf7:   /* -large descending */
      i = 1 + sqlite4GetVarint64(aKey+1, 2, &eBig);
      e = (short)eBig;
      break;

    default:
      return 0;
  }
  m = 0;
  do{
    y = aKey[i++] ^ xorMask;
    m = m*100 + y/2;
    e--;
  }while( y & 1 );
  if( m==0 ) return 0;

  pVal->m = m;
  pVal->e = 2*e;
  return i;
}

/*
** This is a private method for the RowDecoder object.
**





** Attempt to extract a single column value from the key of the current
** key/value pair.  If beginning of the value is iOfst bytes from the beginning
** of the key.  If affReal is true, then force numeric values to be floating
** point.  Write the result in pOut.  Or return non-zero if there is an
** error.
*/
static int decoderFromKey(
  RowDecoder *p,           /* The current key/value pair */
  int affReal,             /* True to coerce numbers to floating point */
  sqlite4_int64 iOfst,     /* Offset of value in the key */
  Mem *pOut                /* Write the results here */
){
  int rc;
  KVSize i;
  KVSize n;
  const KVByteArray *a;
  char *z;

  if( iOfst<0 ){
    return SQLITE4_CORRUPT_BKPT;
  }
  rc = decoderFetchKey(p);
  if( rc ) return rc;
  if( iOfst>=p->nKey ){
    return SQLITE4_CORRUPT_BKPT;
  }
  a = p->aKey;
  n = p->nKey;
  switch( a[iOfst++] ){
    case 0x05: case 0xFA:       /* NULL */
    case 0x06: case 0xF9: {     /* NaN */
      sqlite4VdbeMemSetNull(pOut);
      break;
    }

    case 0x24: {                /* Text (ascending index) */
      for(i=iOfst; i<n && a[i]!=0; i++){}
      rc = sqlite4VdbeMemSetStr(pOut, &a[iOfst], i-iOfst,
                                SQLITE4_UTF8, SQLITE4_TRANSIENT, 0);
      break;
    }
    case 0xDB: {                /* Text (descending index) */
      for(i=iOfst; i<n && a[i]!=0xFF; i++){}
      rc = sqlite4VdbeMemSetStr(pOut, &a[iOfst+1], n = i - iOfst,
                                SQLITE4_UTF8, SQLITE4_TRANSIENT, 0);
      if( rc==SQLITE4_OK ){
        z = pOut->z;
        for(i=n-1; i>=0; i--) *(z++) ^= 0xFF;
      }
      break;
    }

    case 0x25: {                /* Blob (ascending index) */
      for(i=iOfst; i<n && a[i]!=0; i++){}
      rc = decoderMemSetFromBlob(&a[iOfst], i-iOfst, 0x00, pOut);
      break;
    }
    case 0xDA: {                /* Blob (descending index) */
      for(i=iOfst; i<n && a[i]!=0xFF; i++){}
      rc = decoderMemSetFromBlob(&a[iOfst], i-iOfst, 0xFF, pOut);
      break;
    }

    case 0x26: {                /* Blob-final (ascending) */
      rc = sqlite4VdbeMemSetStr(pOut, &a[iOfst], n-iOfst, 0,
                                SQLITE4_TRANSIENT, 0);
      break;
    }
    case 0xD9: {                /* Blob-final (descending) */
      rc = sqlite4VdbeMemSetStr(pOut, &a[iOfst], n-iOfst,
                                SQLITE4_UTF8, SQLITE4_TRANSIENT, 0);
      if( rc==SQLITE4_OK ){
        z = pOut->z;
        for(i=n-iOfst; i>0; i--) *(z++) ^= 0xFF;
      }
      break;
    }
    default: {
      sqlite4_num v;
      i = sqlite4VdbeDecodeNumericKey(a+iOfst-1, n-iOfst+1, &v);
      if( i==0 ){
        rc = SQLITE4_CORRUPT_BKPT;
      }else{
        sqlite4VdbeMemSetNum(pOut, v, affReal ? MEM_Real : MEM_Int);
        rc = SQLITE4_OK;
      }
      break;
    }
  };
  return rc;
}

/*
** Decode a single column from a key/value pair taken from the storage
** engine.  The key/value pair to be decoded is the one that the VdbeCursor
** or KVCursor is currently pointing to.
**
** iVal is the column index of the value.  0 is the first column of the
** value.  If N is the number of columns in the value and iVal>=N then
** the result is pDefault.  Write the result into pOut.  Return SQLITE4_OK
** on success or an appropriate error code on failure.
**
** The key is referenced only if the iVal-th column in the value is either
** the 22 or 23 header code which indicates that the value is stored in the
** key instead.
*/
int sqlite4VdbeDecoderGetColumn(
  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 */
){
................................................................................
         n += sz;
      }
      size = (type-24)/3;
    }else if( type<=2 ){
      size = 0;
    }else if( type<=10 ){
      size = type - 2;
    }else if( type<=21 ){
      size = type - 9;
    }else{
      /* value in key */
      size = 0;
      sz = sqlite4GetVarint64(p->a+n, p->n-n, &subtype);
      if( sz==0 ) return SQLITE4_CORRUPT;
      n += sz;
................................................................................
      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 ){
      return decoderFromKey(p, type==23, subtype, pOut);


    }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{
................................................................................
    assert( flags & MEM_Blob );
    n = pMem->n;
    a = (u8*)pMem->z;
    s = 1;
    t = 0;
    if( enlargeEncoderAllocation(p, (n*8+6)/7 + 2) ) return SQLITE4_NOMEM;
    p->aOut[p->nOut++] = 0x25;   /* Blob */
    for(i=0; i<n; i++){
      unsigned char x = a[i];
      p->aOut[p->nOut++] = 0x80 | t | (x>>s);
      if( s<7 ){
        t = x<<(7-s);
        s++;
      }else{
        p->aOut[p->nOut++] = 0x80 | x;
................................................................................
    sqlite4DbFree(db, x.aOut);
  }else{
    *paOut = x.aOut;
    *pnOut = x.nOut;
  }
  return rc;
}