SQLite

Check-in [657c9fb513]
Login

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

Overview
Comment:When constructing records and index keys, use static string space rather than mallocing (when possible) for a small speed improvement. (CVS 817)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 657c9fb5133aef93e4edd433912e6942ad9674ec
User & Date: drh 2003-01-07 13:43:46.000
Context
2003-01-07
13:55
In the VDBE, allocate space to hold column names when the VDBE first starts. The ColumnCount opcode now just writes the null terminator into this space. (CVS 818) (check-in: 46d8f5e377 user: drh tags: trunk)
13:43
When constructing records and index keys, use static string space rather than mallocing (when possible) for a small speed improvement. (CVS 817) (check-in: 657c9fb513 user: drh tags: trunk)
02:47
More optimizations. (CVS 816) (check-in: a362981b20 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/vdbe.c.
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.192 2003/01/07 02:47:48 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** The makefile scans this source file and creates the following
** array of string constants which are the names of all VDBE opcodes.







|







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.193 2003/01/07 13:43:46 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** The makefile scans this source file and creates the following
** array of string constants which are the names of all VDBE opcodes.
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
806
    pElem = sqliteHashFirst(&p->hash);
  }
  return pElem ? sqliteHashData(pElem) : 0;
}

/*
** Convert the given stack entity into a string if it isn't one
** already.  Return non-zero if we run out of memory.
**
** NULLs are converted into an empty string.
*/
#define Stringify(P,I) ((aStack[I].flags & STK_Str)==0 ? hardStringify(P,I) : 0)
static int hardStringify(Vdbe *p, int i){
  Stack *pStack = &p->aStack[i];
  char **pzStack = &p->zStack[i];
  int fg = pStack->flags;
  if( fg & STK_Real ){
    sprintf(pStack->z,"%.15g",pStack->r);
  }else if( fg & STK_Int ){
    sprintf(pStack->z,"%d",pStack->i);
  }else{
    pStack->z[0] = 0;
  }
  *pzStack = pStack->z;
  pStack->n = strlen(*pzStack)+1;
  pStack->flags = STK_Str;
  return 0;
}

























/*
** An ephemeral string value (signified by the STK_Ephem flag) contains
** a pointer to a dynamically allocated string where some other entity
** is responsible for deallocating that string.  Because the stack entry
** does not control the string, it might be deleted without the stack
** entry knowing it.







|
<
<

|


<








|
|



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
    pElem = sqliteHashFirst(&p->hash);
  }
  return pElem ? sqliteHashData(pElem) : 0;
}

/*
** Convert the given stack entity into a string if it isn't one
** already.


*/
#define Stringify(P,I) if((aStack[I].flags & STK_Str)==0){hardStringify(P,I);}
static int hardStringify(Vdbe *p, int i){
  Stack *pStack = &p->aStack[i];

  int fg = pStack->flags;
  if( fg & STK_Real ){
    sprintf(pStack->z,"%.15g",pStack->r);
  }else if( fg & STK_Int ){
    sprintf(pStack->z,"%d",pStack->i);
  }else{
    pStack->z[0] = 0;
  }
  p->zStack[i] = pStack->z;
  pStack->n = strlen(pStack->z)+1;
  pStack->flags = STK_Str;
  return 0;
}

/*
** Convert the given stack entity into a string that has been obtained
** from sqliteMalloc().  This is different from Stringify() above in that
** Stringify() will use the NBFS bytes of static string space if the string
** will fit but this routine always mallocs for space.
** Return non-zero if we run out of memory.
*/
#define Dynamicify(P,I) ((aStack[I].flags & STK_Dyn)==0 ? hardDynamicify(P,I):0)
static int hardDynamicify(Vdbe *p, int i){
  Stack *pStack = &p->aStack[i];
  int fg = pStack->flags;
  char *z;
  if( (fg & STK_Str)==0 ){
    hardStringify(p, i);
  }
  assert( (fg & STK_Dyn)==0 );
  z = sqliteMallocRaw( pStack->n );
  if( z==0 ) return 1;
  memcpy(z, p->zStack[i], pStack->n);
  p->zStack[i] = z;
  pStack->flags |= STK_Dyn;
  return 0;
}

/*
** An ephemeral string value (signified by the STK_Ephem flag) contains
** a pointer to a dynamically allocated string where some other entity
** is responsible for deallocating that string.  Because the stack entry
** does not control the string, it might be deleted without the stack
** entry knowing it.
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
  int i = p->tos - pOp->p1 + 1;
  int j;
  VERIFY( if( i<0 ) goto not_enough_stack; )
  for(j=i; j<=p->tos; j++){
    if( aStack[j].flags & STK_Null ){
      zStack[j] = 0;
    }else{
      if( Stringify(p, j) ) goto no_mem;
    }
  }
  zStack[p->tos+1] = 0;
  if( xCallback!=0 ){
    if( sqliteSafetyOff(db) ) goto abort_due_to_misuse; 
    if( xCallback(pArg, pOp->p1, &zStack[i], p->azColName)!=0 ){
      rc = SQLITE_ABORT;







|







1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
  int i = p->tos - pOp->p1 + 1;
  int j;
  VERIFY( if( i<0 ) goto not_enough_stack; )
  for(j=i; j<=p->tos; j++){
    if( aStack[j].flags & STK_Null ){
      zStack[j] = 0;
    }else{
      Stringify(p, j);
    }
  }
  zStack[p->tos+1] = 0;
  if( xCallback!=0 ){
    if( sqliteSafetyOff(db) ) goto abort_due_to_misuse; 
    if( xCallback(pArg, pOp->p1, &zStack[i], p->azColName)!=0 ){
      rc = SQLITE_ABORT;
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
  VERIFY( if( p->tos+1<nField ) goto not_enough_stack; )
  nByte = 1 - nSep;
  for(i=p->tos-nField+1; i<=p->tos; i++){
    if( aStack[i].flags & STK_Null ){
      nByte = -1;
      break;
    }else{
      if( Stringify(p, i) ) goto no_mem;
      nByte += aStack[i].n - 1 + nSep;
    }
  }
  if( nByte<0 ){
    if( pOp->p2==0 ) PopStack(p, nField);
    p->tos++;
    aStack[p->tos].flags = STK_Null;







|







1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
  VERIFY( if( p->tos+1<nField ) goto not_enough_stack; )
  nByte = 1 - nSep;
  for(i=p->tos-nField+1; i<=p->tos; i++){
    if( aStack[i].flags & STK_Null ){
      nByte = -1;
      break;
    }else{
      Stringify(p, i);
      nByte += aStack[i].n - 1 + nSep;
    }
  }
  if( nByte<0 ){
    if( pOp->p2==0 ) PopStack(p, nField);
    p->tos++;
    aStack[p->tos].flags = STK_Null;
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
  n = pOp->p1;
  VERIFY( if( n<0 ) goto bad_instruction; )
  VERIFY( if( p->tos+1<n ) goto not_enough_stack; )
  for(i=p->tos-n+1; i<=p->tos; i++){
    if( aStack[i].flags & STK_Null ){
      zStack[i] = 0;
    }else{
      if( Stringify(p, i) ) goto no_mem;
    }
  }
  ctx.pFunc = (FuncDef*)pOp->p3;
  ctx.s.flags = STK_Null;
  ctx.z = 0;
  ctx.isError = 0;
  ctx.isStep = 0;







|







2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
  n = pOp->p1;
  VERIFY( if( n<0 ) goto bad_instruction; )
  VERIFY( if( p->tos+1<n ) goto not_enough_stack; )
  for(i=p->tos-n+1; i<=p->tos; i++){
    if( aStack[i].flags & STK_Null ){
      zStack[i] = 0;
    }else{
      Stringify(p, i);
    }
  }
  ctx.pFunc = (FuncDef*)pOp->p3;
  ctx.s.flags = STK_Null;
  ctx.z = 0;
  ctx.isError = 0;
  ctx.isStep = 0;
2279
2280
2281
2282
2283
2284
2285
2286

2287
2288
2289
2290
2291
2292
2293
    c = aStack[nos].i - aStack[tos].i;
  }else if( (fn & STK_Int)!=0 && (ft & STK_Str)!=0 && toInt(zStack[tos],&v) ){
    Release(p, tos);
    aStack[tos].i = v;
    aStack[tos].flags = STK_Int;
    c = aStack[nos].i - aStack[tos].i;
  }else{
    if( Stringify(p, tos) || Stringify(p, nos) ) goto no_mem;

    c = sqliteCompare(zStack[nos], zStack[tos]);
  }
  switch( pOp->opcode ){
    case OP_Eq:    c = c==0;     break;
    case OP_Ne:    c = c!=0;     break;
    case OP_Lt:    c = c<0;      break;
    case OP_Le:    c = c<=0;     break;







|
>







2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
    c = aStack[nos].i - aStack[tos].i;
  }else if( (fn & STK_Int)!=0 && (ft & STK_Str)!=0 && toInt(zStack[tos],&v) ){
    Release(p, tos);
    aStack[tos].i = v;
    aStack[tos].flags = STK_Int;
    c = aStack[nos].i - aStack[tos].i;
  }else{
    Stringify(p, tos);
    Stringify(p, nos);
    c = sqliteCompare(zStack[nos], zStack[tos]);
  }
  switch( pOp->opcode ){
    case OP_Eq:    c = c==0;     break;
    case OP_Ne:    c = c!=0;     break;
    case OP_Lt:    c = c<0;      break;
    case OP_Le:    c = c<=0;     break;
2429
2430
2431
2432
2433
2434
2435
2436

2437
2438
2439
2440
2441
2442
2443
      if( pOp->p1 ) pc = pOp->p2-1;
    }else{
      p->tos++;
      aStack[nos].flags = STK_Null;
    }
    break;
  }else{
    if( Stringify(p, tos) || Stringify(p, nos) ) goto no_mem;

    c = strcmp(zStack[nos], zStack[tos]);
  }
  /* The asserts on each case of the following switch are there to verify
  ** that string comparison opcodes are always exactly 6 greater than the
  ** corresponding numeric comparison opcodes.  The code generator depends
  ** on this fact.
  */







|
>







2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
      if( pOp->p1 ) pc = pOp->p2-1;
    }else{
      p->tos++;
      aStack[nos].flags = STK_Null;
    }
    break;
  }else{
    Stringify(p, tos);
    Stringify(p, nos);
    c = strcmp(zStack[nos], zStack[tos]);
  }
  /* The asserts on each case of the following switch are there to verify
  ** that string comparison opcodes are always exactly 6 greater than the
  ** corresponding numeric comparison opcodes.  The code generator depends
  ** on this fact.
  */
2690
2691
2692
2693
2694
2695
2696

2697
2698
2699
2700
2701
2702
2703
  int nByte;
  int nField;
  int i, j;
  int idxWidth;
  u32 addr;
  int addUnique = 0;   /* True to cause bytes to be added to make the
                       ** generated record distinct */


  /* Assuming the record contains N fields, the record format looks
  ** like this:
  **
  **   -------------------------------------------------------------------
  **   | idx0 | idx1 | ... | idx(N-1) | idx(N) | data0 | ... | data(N-1) |
  **   -------------------------------------------------------------------







>







2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
  int nByte;
  int nField;
  int i, j;
  int idxWidth;
  u32 addr;
  int addUnique = 0;   /* True to cause bytes to be added to make the
                       ** generated record distinct */
  char zTemp[NBFS];    /* Temp space for small records */

  /* Assuming the record contains N fields, the record format looks
  ** like this:
  **
  **   -------------------------------------------------------------------
  **   | idx0 | idx1 | ... | idx(N-1) | idx(N) | data0 | ... | data(N-1) |
  **   -------------------------------------------------------------------
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739



2740
2741

2742
2743
2744
2745
2746
2747
2748
  nField = pOp->p1;
  VERIFY( if( p->tos+1<nField ) goto not_enough_stack; )
  nByte = 0;
  for(i=p->tos-nField+1; i<=p->tos; i++){
    if( (aStack[i].flags & STK_Null) ){
      addUnique = pOp->p2;
    }else{
      if( Stringify(p, i) ) goto no_mem;
      nByte += aStack[i].n;
    }
  }
  if( addUnique ) nByte += sizeof(uniqueCnt);
  if( nByte + nField + 1 < 256 ){
    idxWidth = 1;
  }else if( nByte + 2*nField + 2 < 65536 ){
    idxWidth = 2;
  }else{
    idxWidth = 3;
  }
  nByte += idxWidth*(nField + 1);
  if( nByte>MAX_BYTES_PER_ROW ){
    rc = SQLITE_TOOBIG;
    goto abort_due_to_error;
  }



  zNewRecord = sqliteMallocRaw( nByte );
  if( zNewRecord==0 ) goto no_mem;

  j = 0;
  addr = idxWidth*(nField+1) + addUnique*sizeof(uniqueCnt);
  for(i=p->tos-nField+1; i<=p->tos; i++){
    zNewRecord[j++] = addr & 0xff;
    if( idxWidth>1 ){
      zNewRecord[j++] = (addr>>8)&0xff;
      if( idxWidth>2 ){







|
















>
>
>
|
|
>







2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
  nField = pOp->p1;
  VERIFY( if( p->tos+1<nField ) goto not_enough_stack; )
  nByte = 0;
  for(i=p->tos-nField+1; i<=p->tos; i++){
    if( (aStack[i].flags & STK_Null) ){
      addUnique = pOp->p2;
    }else{
      Stringify(p, i);
      nByte += aStack[i].n;
    }
  }
  if( addUnique ) nByte += sizeof(uniqueCnt);
  if( nByte + nField + 1 < 256 ){
    idxWidth = 1;
  }else if( nByte + 2*nField + 2 < 65536 ){
    idxWidth = 2;
  }else{
    idxWidth = 3;
  }
  nByte += idxWidth*(nField + 1);
  if( nByte>MAX_BYTES_PER_ROW ){
    rc = SQLITE_TOOBIG;
    goto abort_due_to_error;
  }
  if( nByte<=NBFS ){
    zNewRecord = zTemp;
  }else{
    zNewRecord = sqliteMallocRaw( nByte );
    if( zNewRecord==0 ) goto no_mem;
  }
  j = 0;
  addr = idxWidth*(nField+1) + addUnique*sizeof(uniqueCnt);
  for(i=p->tos-nField+1; i<=p->tos; i++){
    zNewRecord[j++] = addr & 0xff;
    if( idxWidth>1 ){
      zNewRecord[j++] = (addr>>8)&0xff;
      if( idxWidth>2 ){
2770
2771
2772
2773
2774
2775
2776







2777
2778

2779
2780
2781
2782
2783
2784
2785
      memcpy(&zNewRecord[j], zStack[i], aStack[i].n);
      j += aStack[i].n;
    }
  }
  PopStack(p, nField);
  p->tos++;
  aStack[p->tos].n = nByte;







  aStack[p->tos].flags = STK_Str | STK_Dyn;
  zStack[p->tos] = zNewRecord;

  break;
}

/* Opcode: MakeKey P1 P2 P3
**
** Convert the top P1 entries of the stack into a single entry suitable
** for use as the key in an index.  The top P1 records are







>
>
>
>
>
>
>
|
|
>







2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
      memcpy(&zNewRecord[j], zStack[i], aStack[i].n);
      j += aStack[i].n;
    }
  }
  PopStack(p, nField);
  p->tos++;
  aStack[p->tos].n = nByte;
  if( nByte<=NBFS ){
    assert( zNewRecord==zTemp );
    memcpy(aStack[p->tos].z, zTemp, nByte);
    zStack[p->tos] = aStack[p->tos].z;
    aStack[p->tos].flags = STK_Str;
  }else{
    assert( zNewRecord!=zTemp );
    aStack[p->tos].flags = STK_Str | STK_Dyn;
    zStack[p->tos] = zNewRecord;
  }
  break;
}

/* Opcode: MakeKey P1 P2 P3
**
** Convert the top P1 entries of the stack into a single entry suitable
** for use as the key in an index.  The top P1 records are
2847
2848
2849
2850
2851
2852
2853

2854
2855
2856
2857
2858
2859
2860
case OP_MakeKey: {
  char *zNewKey;
  int nByte;
  int nField;
  int addRowid;
  int i, j;
  int containsNull = 0;


  addRowid = pOp->opcode==OP_MakeIdxKey;
  nField = pOp->p1;
  VERIFY( if( p->tos+1+addRowid<nField ) goto not_enough_stack; )
  nByte = 0;
  for(j=0, i=p->tos-nField+1; i<=p->tos; i++, j++){
    int flags = aStack[i].flags;







>







2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
case OP_MakeKey: {
  char *zNewKey;
  int nByte;
  int nField;
  int addRowid;
  int i, j;
  int containsNull = 0;
  char zTemp[NBFS];

  addRowid = pOp->opcode==OP_MakeIdxKey;
  nField = pOp->p1;
  VERIFY( if( p->tos+1+addRowid<nField ) goto not_enough_stack; )
  nByte = 0;
  for(j=0, i=p->tos-nField+1; i<=p->tos; i++, j++){
    int flags = aStack[i].flags;
2886
2887
2888
2889
2890
2891
2892



2893
2894

2895
2896
2897
2898
2899
2900
2901
    }
  }
  if( nByte+sizeof(u32)>MAX_BYTES_PER_ROW ){
    rc = SQLITE_TOOBIG;
    goto abort_due_to_error;
  }
  if( addRowid ) nByte += sizeof(u32);



  zNewKey = sqliteMallocRaw( nByte );
  if( zNewKey==0 ) goto no_mem;

  j = 0;
  for(i=p->tos-nField+1; i<=p->tos; i++){
    if( aStack[i].flags & STK_Null ){
      zNewKey[j++] = 'a';
      zNewKey[j++] = 0;
    }else{
      if( aStack[i].flags & (STK_Int|STK_Real) ){







>
>
>
|
|
>







2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
    }
  }
  if( nByte+sizeof(u32)>MAX_BYTES_PER_ROW ){
    rc = SQLITE_TOOBIG;
    goto abort_due_to_error;
  }
  if( addRowid ) nByte += sizeof(u32);
  if( nByte<=NBFS ){
    zNewKey = zTemp;
  }else{
    zNewKey = sqliteMallocRaw( nByte );
    if( zNewKey==0 ) goto no_mem;
  }
  j = 0;
  for(i=p->tos-nField+1; i<=p->tos; i++){
    if( aStack[i].flags & STK_Null ){
      zNewKey[j++] = 'a';
      zNewKey[j++] = 0;
    }else{
      if( aStack[i].flags & (STK_Int|STK_Real) ){
2915
2916
2917
2918
2919
2920
2921






2922
2923

2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
    PopStack(p, nField+1);
    if( pOp->p2 && containsNull ) pc = pOp->p2 - 1;
  }else{
    if( pOp->p2==0 ) PopStack(p, nField+addRowid);
  }
  p->tos++;
  aStack[p->tos].n = nByte;






  aStack[p->tos].flags = STK_Str|STK_Dyn;
  zStack[p->tos] = zNewKey;

  break;
}

/* Opcode: IncrKey * * *
**
** The top of the stack should contain an index key generated by
** The MakeKey opcode.  This routine increases the least significant
** byte of that key by one.  This is used so that the MoveTo opcode
** will move to the first entry greater than the key rather than to
** the key itself.
*/
case OP_IncrKey: {
  int tos = p->tos;

  VERIFY( if( tos<0 ) goto bad_instruction );
  if( Stringify(p, tos) ) goto no_mem;
  if( aStack[tos].flags & (STK_Static|STK_Ephem) ){
    /* CANT HAPPEN.  The IncrKey opcode is only applied to keys
    ** generated by MakeKey or MakeIdxKey and the results of those
    ** operands are always dynamic strings.
    */
    goto abort_due_to_error;
  }







>
>
>
>
>
>
|
|
>















|







2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
    PopStack(p, nField+1);
    if( pOp->p2 && containsNull ) pc = pOp->p2 - 1;
  }else{
    if( pOp->p2==0 ) PopStack(p, nField+addRowid);
  }
  p->tos++;
  aStack[p->tos].n = nByte;
  if( nByte<=NBFS ){
    assert( zNewKey==zTemp );
    zStack[p->tos] = aStack[p->tos].z;
    memcpy(zStack[p->tos], zTemp, nByte);
    aStack[p->tos].flags = STK_Str;
  }else{
    aStack[p->tos].flags = STK_Str|STK_Dyn;
    zStack[p->tos] = zNewKey;
  }
  break;
}

/* Opcode: IncrKey * * *
**
** The top of the stack should contain an index key generated by
** The MakeKey opcode.  This routine increases the least significant
** byte of that key by one.  This is used so that the MoveTo opcode
** will move to the first entry greater than the key rather than to
** the key itself.
*/
case OP_IncrKey: {
  int tos = p->tos;

  VERIFY( if( tos<0 ) goto bad_instruction );
  Stringify(p, tos);
  if( aStack[tos].flags & (STK_Static|STK_Ephem) ){
    /* CANT HAPPEN.  The IncrKey opcode is only applied to keys
    ** generated by MakeKey or MakeIdxKey and the results of those
    ** operands are always dynamic strings.
    */
    goto abort_due_to_error;
  }
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
    int res, oc;
    if( aStack[tos].flags & STK_Int ){
      int iKey = intToKey(aStack[tos].i);
      sqliteBtreeMoveto(pC->pCursor, (char*)&iKey, sizeof(int), &res);
      pC->lastRecno = aStack[tos].i;
      pC->recnoIsValid = res==0;
    }else{
      if( Stringify(p, tos) ) goto no_mem;
      sqliteBtreeMoveto(pC->pCursor, zStack[tos], aStack[tos].n, &res);
      pC->recnoIsValid = 0;
    }
    pC->nullRow = 0;
    sqlite_search_count++;
    oc = pOp->opcode;
    if( oc==OP_MoveTo && res<0 ){







|







3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
    int res, oc;
    if( aStack[tos].flags & STK_Int ){
      int iKey = intToKey(aStack[tos].i);
      sqliteBtreeMoveto(pC->pCursor, (char*)&iKey, sizeof(int), &res);
      pC->lastRecno = aStack[tos].i;
      pC->recnoIsValid = res==0;
    }else{
      Stringify(p, tos);
      sqliteBtreeMoveto(pC->pCursor, zStack[tos], aStack[tos].n, &res);
      pC->recnoIsValid = 0;
    }
    pC->nullRow = 0;
    sqlite_search_count++;
    oc = pOp->opcode;
    if( oc==OP_MoveTo && res<0 ){
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
  int i = pOp->p1;
  int tos = p->tos;
  int alreadyExists = 0;
  Cursor *pC;
  VERIFY( if( tos<0 ) goto not_enough_stack; )
  if( VERIFY( i>=0 && i<p->nCursor && ) (pC = &p->aCsr[i])->pCursor!=0 ){
    int res, rx;
    if( Stringify(p, tos) ) goto no_mem;
    rx = sqliteBtreeMoveto(pC->pCursor, zStack[tos], aStack[tos].n, &res);
    alreadyExists = rx==SQLITE_OK && res==0;
  }
  if( pOp->opcode==OP_Found ){
    if( alreadyExists ) pc = pOp->p2 - 1;
  }else{
    if( !alreadyExists ) pc = pOp->p2 - 1;







|







3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
  int i = pOp->p1;
  int tos = p->tos;
  int alreadyExists = 0;
  Cursor *pC;
  VERIFY( if( tos<0 ) goto not_enough_stack; )
  if( VERIFY( i>=0 && i<p->nCursor && ) (pC = &p->aCsr[i])->pCursor!=0 ){
    int res, rx;
    Stringify(p, tos);
    rx = sqliteBtreeMoveto(pC->pCursor, zStack[tos], aStack[tos].n, &res);
    alreadyExists = rx==SQLITE_OK && res==0;
  }
  if( pOp->opcode==OP_Found ){
    if( alreadyExists ) pc = pOp->p2 - 1;
  }else{
    if( !alreadyExists ) pc = pOp->p2 - 1;
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
    int res, rc;
    int v;         /* The record number on the P1 entry that matches K */
    char *zKey;    /* The value of K */
    int nKey;      /* Number of bytes in K */

    /* Make sure K is a string and make zKey point to K
    */
    if( Stringify(p, nos) ) goto no_mem;
    zKey = zStack[nos];
    nKey = aStack[nos].n;
    assert( nKey >= 4 );

    /* Search for an entry in P1 where all but the last four bytes match K.
    ** If there is no such entry, jump immediately to P2.
    */







|







3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
    int res, rc;
    int v;         /* The record number on the P1 entry that matches K */
    char *zKey;    /* The value of K */
    int nKey;      /* Number of bytes in K */

    /* Make sure K is a string and make zKey point to K
    */
    Stringify(p, nos);
    zKey = zStack[nos];
    nKey = aStack[nos].n;
    assert( nKey >= 4 );

    /* Search for an entry in P1 where all but the last four bytes match K.
    ** If there is no such entry, jump immediately to P2.
    */
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
  int i = pOp->p1;
  Cursor *pC;
  VERIFY( if( nos<0 ) goto not_enough_stack; )
  if( VERIFY( i>=0 && i<p->nCursor && ) (pC = &p->aCsr[i])->pCursor!=0 ){
    char *zKey;
    int nKey, iKey;
    if( pOp->opcode==OP_PutStrKey ){
      if( Stringify(p, nos) ) goto no_mem;
      nKey = aStack[nos].n;
      zKey = zStack[nos];
    }else{
      assert( aStack[nos].flags & STK_Int );
      nKey = sizeof(int);
      iKey = intToKey(aStack[nos].i);
      zKey = (char*)&iKey;







|







3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
  int i = pOp->p1;
  Cursor *pC;
  VERIFY( if( nos<0 ) goto not_enough_stack; )
  if( VERIFY( i>=0 && i<p->nCursor && ) (pC = &p->aCsr[i])->pCursor!=0 ){
    char *zKey;
    int nKey, iKey;
    if( pOp->opcode==OP_PutStrKey ){
      Stringify(p, nos);
      nKey = aStack[nos].n;
      zKey = zStack[nos];
    }else{
      assert( aStack[nos].flags & STK_Int );
      nKey = sizeof(int);
      iKey = intToKey(aStack[nos].i);
      zKey = (char*)&iKey;
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
  int i= pOp->p1;
  int tos = p->tos;
  BtCursor *pCrsr;

  if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
    int res, rc;
 
    if( Stringify(p, tos) ) goto no_mem;
    rc = sqliteBtreeKeyCompare(pCrsr, zStack[tos], aStack[tos].n, 4, &res);
    if( rc!=SQLITE_OK ){
      break;
    }
    if( pOp->opcode==OP_IdxLT ){
      res = -res;
    }else if( pOp->opcode==OP_IdxGE ){







|







4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
  int i= pOp->p1;
  int tos = p->tos;
  BtCursor *pCrsr;

  if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
    int res, rc;
 
    Stringify(p, tos);
    rc = sqliteBtreeKeyCompare(pCrsr, zStack[tos], aStack[tos].n, 4, &res);
    if( rc!=SQLITE_OK ){
      break;
    }
    if( pOp->opcode==OP_IdxLT ){
      res = -res;
    }else if( pOp->opcode==OP_IdxGE ){
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
** made using SortMakeKey and SortMakeRec, respectively.
*/
case OP_SortPut: {
  int tos = p->tos;
  int nos = tos - 1;
  Sorter *pSorter;
  VERIFY( if( tos<1 ) goto not_enough_stack; )
  if( Stringify(p, tos) || Stringify(p, nos) ) goto no_mem;
  pSorter = sqliteMallocRaw( sizeof(Sorter) );
  if( pSorter==0 ) goto no_mem;
  pSorter->pNext = p->pSort;
  p->pSort = pSorter;
  assert( aStack[tos].flags & STK_Dyn );
  pSorter->nKey = aStack[tos].n;
  pSorter->zKey = zStack[tos];







|







4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
** made using SortMakeKey and SortMakeRec, respectively.
*/
case OP_SortPut: {
  int tos = p->tos;
  int nos = tos - 1;
  Sorter *pSorter;
  VERIFY( if( tos<1 ) goto not_enough_stack; )
  if( Dynamicify(p, tos) || Dynamicify(p, nos) ) goto no_mem;
  pSorter = sqliteMallocRaw( sizeof(Sorter) );
  if( pSorter==0 ) goto no_mem;
  pSorter->pNext = p->pSort;
  p->pSort = pSorter;
  assert( aStack[tos].flags & STK_Dyn );
  pSorter->nKey = aStack[tos].n;
  pSorter->zKey = zStack[tos];
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
  int i, j;

  nField = pOp->p1;
  VERIFY( if( p->tos+1<nField ) goto not_enough_stack; )
  nByte = 0;
  for(i=p->tos-nField+1; i<=p->tos; i++){
    if( (aStack[i].flags & STK_Null)==0 ){
      if( Stringify(p, i) ) goto no_mem;
      nByte += aStack[i].n;
    }
  }
  nByte += sizeof(char*)*(nField+1);
  azArg = sqliteMallocRaw( nByte );
  if( azArg==0 ) goto no_mem;
  z = (char*)&azArg[nField+1];







|







4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
  int i, j;

  nField = pOp->p1;
  VERIFY( if( p->tos+1<nField ) goto not_enough_stack; )
  nByte = 0;
  for(i=p->tos-nField+1; i<=p->tos; i++){
    if( (aStack[i].flags & STK_Null)==0 ){
      Stringify(p, i);
      nByte += aStack[i].n;
    }
  }
  nByte += sizeof(char*)*(nField+1);
  azArg = sqliteMallocRaw( nByte );
  if( azArg==0 ) goto no_mem;
  z = (char*)&azArg[nField+1];
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
  nField = strlen(pOp->p3);
  VERIFY( if( p->tos+1<nField ) goto not_enough_stack; )
  nByte = 1;
  for(i=p->tos-nField+1; i<=p->tos; i++){
    if( (aStack[i].flags & STK_Null)!=0 ){
      nByte += 2;
    }else{
      if( Stringify(p, i) ) goto no_mem;
      nByte += aStack[i].n+2;
    }
  }
  zNewKey = sqliteMallocRaw( nByte );
  if( zNewKey==0 ) goto no_mem;
  j = 0;
  k = 0;







|







4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
  nField = strlen(pOp->p3);
  VERIFY( if( p->tos+1<nField ) goto not_enough_stack; )
  nByte = 1;
  for(i=p->tos-nField+1; i<=p->tos; i++){
    if( (aStack[i].flags & STK_Null)!=0 ){
      nByte += 2;
    }else{
      Stringify(p, i);
      nByte += aStack[i].n+2;
    }
  }
  zNewKey = sqliteMallocRaw( nByte );
  if( zNewKey==0 ) goto no_mem;
  j = 0;
  k = 0;
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
  VERIFY( if( n<0 ) goto bad_instruction; )
  VERIFY( if( p->tos+1<n ) goto not_enough_stack; )
  VERIFY( if( aStack[p->tos].flags!=STK_Int ) goto bad_instruction; )
  for(i=p->tos-n; i<p->tos; i++){
    if( aStack[i].flags & STK_Null ){
      zStack[i] = 0;
    }else{
      if( Stringify(p, i) ) goto no_mem;
    }
  }
  i = aStack[p->tos].i;
  VERIFY( if( i<0 || i>=p->agg.nMem ) goto bad_instruction; )
  ctx.pFunc = (FuncDef*)pOp->p3;
  pMem = &p->agg.pCurrent->aMem[i];
  ctx.z = pMem->s.z;







|







5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
  VERIFY( if( n<0 ) goto bad_instruction; )
  VERIFY( if( p->tos+1<n ) goto not_enough_stack; )
  VERIFY( if( aStack[p->tos].flags!=STK_Int ) goto bad_instruction; )
  for(i=p->tos-n; i<p->tos; i++){
    if( aStack[i].flags & STK_Null ){
      zStack[i] = 0;
    }else{
      Stringify(p, i);
    }
  }
  i = aStack[p->tos].i;
  VERIFY( if( i<0 || i>=p->agg.nMem ) goto bad_instruction; )
  ctx.pFunc = (FuncDef*)pOp->p3;
  pMem = &p->agg.pCurrent->aMem[i];
  ctx.z = pMem->s.z;
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
case OP_AggFocus: {
  int tos = p->tos;
  AggElem *pElem;
  char *zKey;
  int nKey;

  VERIFY( if( tos<0 ) goto not_enough_stack; )
  if( Stringify(p, tos) ) goto no_mem;
  zKey = zStack[tos]; 
  nKey = aStack[tos].n;
  pElem = sqliteHashFind(&p->agg.hash, zKey, nKey);
  if( pElem ){
    p->agg.pCurrent = pElem;
    pc = pOp->p2 - 1;
  }else{







|







5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
case OP_AggFocus: {
  int tos = p->tos;
  AggElem *pElem;
  char *zKey;
  int nKey;

  VERIFY( if( tos<0 ) goto not_enough_stack; )
  Stringify(p, tos);
  zKey = zStack[tos]; 
  nKey = aStack[tos].n;
  pElem = sqliteHashFind(&p->agg.hash, zKey, nKey);
  if( pElem ){
    p->agg.pCurrent = pElem;
    pc = pOp->p2 - 1;
  }else{
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
    p->nSet = i+1;
  }
  if( pOp->p3 ){
    sqliteHashInsert(&p->aSet[i].hash, pOp->p3, strlen(pOp->p3)+1, p);
  }else{
    int tos = p->tos;
    if( tos<0 ) goto not_enough_stack;
    if( Stringify(p, tos) ) goto no_mem;
    sqliteHashInsert(&p->aSet[i].hash, zStack[tos], aStack[tos].n, p);
    POPSTACK;
  }
  if( sqlite_malloc_failed ) goto no_mem;
  break;
}

/* Opcode: SetFound P1 P2 *
**
** Pop the stack once and compare the value popped off with the
** contents of set P1.  If the element popped exists in set P1,
** then jump to P2.  Otherwise fall through.
*/
case OP_SetFound: {
  int i = pOp->p1;
  int tos = p->tos;
  VERIFY( if( tos<0 ) goto not_enough_stack; )
  if( Stringify(p, tos) ) goto no_mem;
  if( i>=0 && i<p->nSet &&
       sqliteHashFind(&p->aSet[i].hash, zStack[tos], aStack[tos].n)){
    pc = pOp->p2 - 1;
  }
  POPSTACK;
  break;
}

/* Opcode: SetNotFound P1 P2 *
**
** Pop the stack once and compare the value popped off with the
** contents of set P1.  If the element popped does not exists in 
** set P1, then jump to P2.  Otherwise fall through.
*/
case OP_SetNotFound: {
  int i = pOp->p1;
  int tos = p->tos;
  VERIFY( if( tos<0 ) goto not_enough_stack; )
  if( Stringify(p, tos) ) goto no_mem;
  if( i<0 || i>=p->nSet ||
       sqliteHashFind(&p->aSet[i].hash, zStack[tos], aStack[tos].n)==0 ){
    pc = pOp->p2 - 1;
  }
  POPSTACK;
  break;
}







|

















|


















|







5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
    p->nSet = i+1;
  }
  if( pOp->p3 ){
    sqliteHashInsert(&p->aSet[i].hash, pOp->p3, strlen(pOp->p3)+1, p);
  }else{
    int tos = p->tos;
    if( tos<0 ) goto not_enough_stack;
    Stringify(p, tos);
    sqliteHashInsert(&p->aSet[i].hash, zStack[tos], aStack[tos].n, p);
    POPSTACK;
  }
  if( sqlite_malloc_failed ) goto no_mem;
  break;
}

/* Opcode: SetFound P1 P2 *
**
** Pop the stack once and compare the value popped off with the
** contents of set P1.  If the element popped exists in set P1,
** then jump to P2.  Otherwise fall through.
*/
case OP_SetFound: {
  int i = pOp->p1;
  int tos = p->tos;
  VERIFY( if( tos<0 ) goto not_enough_stack; )
  Stringify(p, tos);
  if( i>=0 && i<p->nSet &&
       sqliteHashFind(&p->aSet[i].hash, zStack[tos], aStack[tos].n)){
    pc = pOp->p2 - 1;
  }
  POPSTACK;
  break;
}

/* Opcode: SetNotFound P1 P2 *
**
** Pop the stack once and compare the value popped off with the
** contents of set P1.  If the element popped does not exists in 
** set P1, then jump to P2.  Otherwise fall through.
*/
case OP_SetNotFound: {
  int i = pOp->p1;
  int tos = p->tos;
  VERIFY( if( tos<0 ) goto not_enough_stack; )
  Stringify(p, tos);
  if( i<0 || i>=p->nSet ||
       sqliteHashFind(&p->aSet[i].hash, zStack[tos], aStack[tos].n)==0 ){
    pc = pOp->p2 - 1;
  }
  POPSTACK;
  break;
}