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

Overview
Comment:Improved EXPLAIN output for the OP_Permutation and OP_Blob opcodes.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 753ffb58579358cc61ddb868f2c7e59c37876669
User & Date: drh 2013-07-29 17:15:48.668
Context
2013-07-29
17:57
Code clarifications: Do not overload the "nField" variable (in the OP_MakeRecord opcode) to mean something other than the number of fields to be encoded. check-in: 20962f1a72 user: drh tags: trunk
17:15
Improved EXPLAIN output for the OP_Permutation and OP_Blob opcodes. check-in: 753ffb5857 user: drh tags: trunk
12:31
Fix an typo affecting virtual WHERE clause terms made in [3f4a1c7648]. check-in: 736b5e6a1a user: dan tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/func.c.
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
  */
  n = sqlite4_value_int(argv[0]);
  sqlite4_result_text(context, sqlite4_compileoption_get(n), -1,
                      SQLITE4_STATIC, 0);
}
#endif /* SQLITE4_OMIT_COMPILEOPTION_DIAGS */

/* Array for converting from half-bytes (nybbles) into ASCII hex
** digits. */
static const char hexdigits[] = {
  '0', '1', '2', '3', '4', '5', '6', '7',
  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' 
};

/*
** EXPERIMENTAL - This is not an official function.  The interface may
** change.  This function may disappear.  Do not write code that depends
** on this function.
**
** Implementation of the QUOTE() function.  This function takes a single
** argument.  If the argument is numeric, the return value is the same as







<
<
<
<
<
<
<







795
796
797
798
799
800
801







802
803
804
805
806
807
808
  */
  n = sqlite4_value_int(argv[0]);
  sqlite4_result_text(context, sqlite4_compileoption_get(n), -1,
                      SQLITE4_STATIC, 0);
}
#endif /* SQLITE4_OMIT_COMPILEOPTION_DIAGS */








/*
** EXPERIMENTAL - This is not an official function.  The interface may
** change.  This function may disappear.  Do not write code that depends
** on this function.
**
** Implementation of the QUOTE() function.  This function takes a single
** argument.  If the argument is numeric, the return value is the same as
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
    case SQLITE4_FLOAT: {
      sqlite4_result_value(context, argv[0]);
      break;
    }
    case SQLITE4_BLOB: {
      int nBlob;
      char *zText = 0;
      char const *zBlob = sqlite4_value_blob(argv[0], &nBlob);
      zText = (char *)contextMalloc(context, (2*(i64)nBlob)+4); 
      if( zText ){
        int i;
        for(i=0; i<nBlob; i++){
          zText[(i*2)+2] = hexdigits[(zBlob[i]>>4)&0x0F];
          zText[(i*2)+3] = hexdigits[(zBlob[i])&0x0F];
        }
        zText[(nBlob*2)+2] = '\'';
        zText[(nBlob*2)+3] = '\0';
        zText[0] = 'x';
        zText[1] = '\'';
        sqlite4_result_text(context, zText, -1, SQLITE4_TRANSIENT, 0);
        sqlite4_free(sqlite4_context_env(context), zText);
      }
      break;
    }
    case SQLITE4_TEXT: {
      int i,j;







|


|
<
|
|
<

|
<
<







818
819
820
821
822
823
824
825
826
827
828

829
830

831
832


833
834
835
836
837
838
839
    case SQLITE4_FLOAT: {
      sqlite4_result_value(context, argv[0]);
      break;
    }
    case SQLITE4_BLOB: {
      int nBlob;
      char *zText = 0;
      const char *zBlob = sqlite4_value_blob(argv[0], &nBlob);
      zText = (char *)contextMalloc(context, (2*(i64)nBlob)+4); 
      if( zText ){
        zText[0] = 'x';

        zText[1] = '\'';
        sqlite4BlobToHex(nBlob, (const u8*)zBlob, zText+2);

        zText[(nBlob*2)+2] = '\'';
        zText[(nBlob*2)+3] = 0;


        sqlite4_result_text(context, zText, -1, SQLITE4_TRANSIENT, 0);
        sqlite4_free(sqlite4_context_env(context), zText);
      }
      break;
    }
    case SQLITE4_TEXT: {
      int i,j;
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
static void hexFunc(
  sqlite4_context *context,
  int argc,
  sqlite4_value **argv
){
  int i, n;
  const unsigned char *pBlob;
  char *zHex, *z;
  assert( argc==1 );
  UNUSED_PARAMETER(argc);
  pBlob = sqlite4_value_blob(argv[0], &n);
  z = zHex = contextMalloc(context, ((i64)n)*2 + 1);
  if( zHex ){
    for(i=0; i<n; i++, pBlob++){
      unsigned char c = *pBlob;
      *(z++) = hexdigits[(c>>4)&0xf];
      *(z++) = hexdigits[c&0xf];
    }
    *z = 0;
    sqlite4_result_text(context, zHex, n*2, SQLITE4_DYNAMIC, 0);
  }
}

/*
** The replace() function.  Three arguments are all strings: call
** them A, B, and C. The result is also a string which is derived







|



|

|
<
<
<
<
<







873
874
875
876
877
878
879
880
881
882
883
884
885
886





887
888
889
890
891
892
893
static void hexFunc(
  sqlite4_context *context,
  int argc,
  sqlite4_value **argv
){
  int i, n;
  const unsigned char *pBlob;
  char *zHex;
  assert( argc==1 );
  UNUSED_PARAMETER(argc);
  pBlob = sqlite4_value_blob(argv[0], &n);
  zHex = contextMalloc(context, ((i64)n)*2 + 1);
  if( zHex ){
    sqlite4BlobToHex(n, (const u8*)pBlob, zHex);





    sqlite4_result_text(context, zHex, n*2, SQLITE4_DYNAMIC, 0);
  }
}

/*
** The replace() function.  Three arguments are all strings: call
** them A, B, and C. The result is also a string which is derived
Changes to src/insert.c.
1451
1452
1453
1454
1455
1456
1457

1458
1459
1460
1461
1462
1463
1464
1465
      }else if( pIdx->nCover>0 ){
        int nByte = sizeof(int)*pIdx->nCover;
        int *aiPermute = (int *)sqlite4DbMallocRaw(pParse->db, nByte);

        if( aiPermute ){
          memcpy(aiPermute, pIdx->aiCover, nByte);
          sqlite4VdbeAddOp4(

              v, OP_Permutation, 0, 0, 0, (char*)aiPermute, P4_INTARRAY
          );
        }
        regData = regCover;
        sqlite4VdbeAddOp3(v, OP_MakeRecord, regContent, pIdx->nCover, regData);
      }
      sqlite4VdbeAddOp3(v, OP_IdxInsert, baseCur+i, regData, aRegIdx[i]);
      sqlite4VdbeChangeP5(v, flags);







>
|







1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
      }else if( pIdx->nCover>0 ){
        int nByte = sizeof(int)*pIdx->nCover;
        int *aiPermute = (int *)sqlite4DbMallocRaw(pParse->db, nByte);

        if( aiPermute ){
          memcpy(aiPermute, pIdx->aiCover, nByte);
          sqlite4VdbeAddOp4(
              v, OP_Permutation, pIdx->nCover, 0, 0,
              (char*)aiPermute, P4_INTARRAY
          );
        }
        regData = regCover;
        sqlite4VdbeAddOp3(v, OP_MakeRecord, regContent, pIdx->nCover, regData);
      }
      sqlite4VdbeAddOp3(v, OP_IdxInsert, baseCur+i, regData, aRegIdx[i]);
      sqlite4VdbeChangeP5(v, flags);
Changes to src/printf.c.
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
91
92
93
94
95
96
97
98
99
#define FLAG_STRING  4     /* Allow infinity precision */


/*
** The following table is searched linearly, so it is good to put the
** most frequently used conversion types first.
*/
static const char aDigits[] = "0123456789ABCDEF0123456789abcdef";
static const char aPrefix[] = "-x0\000X0";
static const et_info fmtinfo[] = {
  {  'd', 10, 1, etRADIX,      0,  0 },
  {  's',  0, 4, etSTRING,     0,  0 },
  {  'g',  0, 1, etGENERIC,    30, 0 },
  {  'z',  0, 4, etDYNSTRING,  0,  0 },
  {  'q',  0, 4, etSQLESCAPE,  0,  0 },
  {  'Q',  0, 4, etSQLESCAPE2, 0,  0 },
  {  'w',  0, 4, etSQLESCAPE3, 0,  0 },
  {  'c',  0, 0, etCHARX,      0,  0 },
  {  'o',  8, 0, etRADIX,      0,  2 },
  {  'u', 10, 0, etRADIX,      0,  0 },
  {  'x', 16, 0, etRADIX,      16, 1 },
  {  'X', 16, 0, etRADIX,      0,  4 },
#ifndef SQLITE4_OMIT_FLOATING_POINT
  {  'f',  0, 1, etFLOAT,      0,  0 },
  {  'e',  0, 1, etEXP,        30, 0 },
  {  'E',  0, 1, etEXP,        14, 0 },
  {  'G',  0, 1, etGENERIC,    14, 0 },
#endif
  {  'i', 10, 1, etRADIX,      0,  0 },
  {  'n',  0, 0, etSIZE,       0,  0 },
  {  '%',  0, 0, etPERCENT,    0,  0 },
  {  'p', 16, 0, etPOINTER,    0,  1 },

/* All the rest have the FLAG_INTERN bit set and are thus for internal







|




|







|
|


|
|
|







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
91
92
93
94
95
96
97
98
99
#define FLAG_STRING  4     /* Allow infinity precision */


/*
** The following table is searched linearly, so it is good to put the
** most frequently used conversion types first.
*/
static const char aDigits[] = "0123456789abcdef0123456789ABCDEF";
static const char aPrefix[] = "-x0\000X0";
static const et_info fmtinfo[] = {
  {  'd', 10, 1, etRADIX,      0,  0 },
  {  's',  0, 4, etSTRING,     0,  0 },
  {  'g',  0, 1, etGENERIC,    14, 0 },
  {  'z',  0, 4, etDYNSTRING,  0,  0 },
  {  'q',  0, 4, etSQLESCAPE,  0,  0 },
  {  'Q',  0, 4, etSQLESCAPE2, 0,  0 },
  {  'w',  0, 4, etSQLESCAPE3, 0,  0 },
  {  'c',  0, 0, etCHARX,      0,  0 },
  {  'o',  8, 0, etRADIX,      0,  2 },
  {  'u', 10, 0, etRADIX,      0,  0 },
  {  'x', 16, 0, etRADIX,      0,  1 },
  {  'X', 16, 0, etRADIX,      16, 4 },
#ifndef SQLITE4_OMIT_FLOATING_POINT
  {  'f',  0, 1, etFLOAT,      0,  0 },
  {  'e',  0, 1, etEXP,        14, 0 },
  {  'E',  0, 1, etEXP,        30, 0 },
  {  'G',  0, 1, etGENERIC,    30, 0 },
#endif
  {  'i', 10, 1, etRADIX,      0,  0 },
  {  'n',  0, 0, etSIZE,       0,  0 },
  {  '%',  0, 0, etPERCENT,    0,  0 },
  {  'p', 16, 0, etPOINTER,    0,  1 },

/* All the rest have the FLAG_INTERN bit set and are thus for internal
981
982
983
984
985
986
987













void sqlite4XPrintf(StrAccum *p, const char *zFormat, ...){
  va_list ap;
  va_start(ap,zFormat);
  sqlite4VXPrintf(p, 1, zFormat, ap);
  va_end(ap);
}
#endif




















>
>
>
>
>
>
>
>
>
>
>
>
>
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
void sqlite4XPrintf(StrAccum *p, const char *zFormat, ...){
  va_list ap;
  va_start(ap,zFormat);
  sqlite4VXPrintf(p, 1, zFormat, ap);
  va_end(ap);
}
#endif

/*
** Convert an N-byte blob into hex.  The caller is responsible for making
** sure zOut contains at least N*2+1 bytes of usable space.
*/
void sqlite4BlobToHex(int N, const u8 *zIn, char *zOut){
  while( (N--)>0 ){
    u8 c = *(zIn++);
    *(zOut++) = aDigits[c>>4];
    *(zOut++) = aDigits[c&0x0f];
  }
  *zOut = 0;
}
Changes to src/select.c.
2477
2478
2479
2480
2481
2482
2483
2484

2485
2486
2487
2488
2489
2490
2491
  sqlite4VdbeAddOp2(v, OP_Gosub, regAddrB, addrSelectB);
  sqlite4VdbeAddOp2(v, OP_If, regEofA, addrEofA);
  sqlite4VdbeAddOp2(v, OP_If, regEofB, addrEofB);

  /* Implement the main merge loop
  */
  sqlite4VdbeResolveLabel(v, labelCmpr);
  sqlite4VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY);

  sqlite4VdbeAddOp4(v, OP_Compare, destA.iMem, destB.iMem, nOrderBy,
                         (char*)pKeyMerge, P4_KEYINFO_HANDOFF);
  sqlite4VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB);

  /* Jump to the this point in order to terminate the query.
  */
  sqlite4VdbeResolveLabel(v, labelEnd);







|
>







2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
  sqlite4VdbeAddOp2(v, OP_Gosub, regAddrB, addrSelectB);
  sqlite4VdbeAddOp2(v, OP_If, regEofA, addrEofA);
  sqlite4VdbeAddOp2(v, OP_If, regEofB, addrEofB);

  /* Implement the main merge loop
  */
  sqlite4VdbeResolveLabel(v, labelCmpr);
  sqlite4VdbeAddOp4(v, OP_Permutation, nOrderBy, 0, 0,
                    (char*)aPermute, P4_INTARRAY);
  sqlite4VdbeAddOp4(v, OP_Compare, destA.iMem, destB.iMem, nOrderBy,
                         (char*)pKeyMerge, P4_KEYINFO_HANDOFF);
  sqlite4VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB);

  /* Jump to the this point in order to terminate the query.
  */
  sqlite4VdbeResolveLabel(v, labelEnd);
Changes to src/sqliteInt.h.
2599
2600
2601
2602
2603
2604
2605

2606
2607
2608
2609
2610
2611
2612
  int sqlite4IsNaN(double);
  int sqlite4IsInf(double);
#else
# define sqlite4IsNaN(X)  0
# define sqlite4IsInf(X)  0
#endif


void sqlite4VXPrintf(StrAccum*, int, const char*, va_list);
#ifndef SQLITE4_OMIT_TRACE
void sqlite4XPrintf(StrAccum*, const char*, ...);
#endif
char *sqlite4MPrintf(sqlite4*,const char*, ...);
char *sqlite4VMPrintf(sqlite4*,const char*, va_list);
char *sqlite4MAppendf(sqlite4*,char*,const char*,...);







>







2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
  int sqlite4IsNaN(double);
  int sqlite4IsInf(double);
#else
# define sqlite4IsNaN(X)  0
# define sqlite4IsInf(X)  0
#endif

void sqlite4BlobToHex(int, const u8*, char*);
void sqlite4VXPrintf(StrAccum*, int, const char*, va_list);
#ifndef SQLITE4_OMIT_TRACE
void sqlite4XPrintf(StrAccum*, const char*, ...);
#endif
char *sqlite4MPrintf(sqlite4*,const char*, ...);
char *sqlite4VMPrintf(sqlite4*,const char*, va_list);
char *sqlite4MAppendf(sqlite4*,char*,const char*,...);
Changes to src/vdbe.c.
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829

1830
1831
1832
1833
1834
1835
1836

  /* Undo any changes made by applyAffinity() to the input registers. */
  pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (flags1&MEM_TypeMask);
  pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (flags3&MEM_TypeMask);
  break;
}

/* Opcode: Permutation * * * P4 *
**
** Set the permutation used by the OP_Compare operator to be the array
** of integers in P4.

**
** The permutation is only valid until the next OP_Permutation, OP_Compare,
** OP_Halt, or OP_ResultRow.  Typically the OP_Permutation should occur
** immediately prior to the OP_Compare.
*/
case OP_Permutation: {
  assert( pOp->p4type==P4_INTARRAY );







|


|
>







1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837

  /* Undo any changes made by applyAffinity() to the input registers. */
  pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (flags1&MEM_TypeMask);
  pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (flags3&MEM_TypeMask);
  break;
}

/* Opcode: Permutation P1 * * P4 *
**
** Set the permutation used by the OP_Compare operator to be the array
** of integers in P4.  P4 will contain exactly P1 elements.  The P1
** parameter is used only for printing the P4 array when debugging.
**
** The permutation is only valid until the next OP_Permutation, OP_Compare,
** OP_Halt, or OP_ResultRow.  Typically the OP_Permutation should occur
** immediately prior to the OP_Compare.
*/
case OP_Permutation: {
  assert( pOp->p4type==P4_INTARRAY );
Changes to src/vdbeaux.c.
921
922
923
924
925
926
927

928






929
930
931
932
933
934
935
936
937
938
939









940
941
942
943

944
945
946
947
948
949
950
    case P4_VTAB: {
      sqlite4_vtab *pVtab = pOp->p4.pVtab->pVtab;
      sqlite4_snprintf(zTemp, nTemp, "vtab:%p:%p", pVtab, pVtab->pModule);
      break;
    }
#endif
    case P4_INTARRAY: {

      sqlite4_snprintf(zTemp, nTemp, "intarray");






      break;
    }
    case P4_SUBPROGRAM: {
      sqlite4_snprintf(zTemp, nTemp, "program");
      break;
    }
    case P4_ADVANCE: {
      zTemp[0] = 0;
      break;
    }
    default: {









      zP4 = pOp->p4.z;
      if( zP4==0 ){
        zP4 = zTemp;
        zTemp[0] = 0;

      }
    }
  }
  assert( zP4!=0 );
  return zP4;
}
#endif







>
|
>
>
>
>
>
>











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







921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
    case P4_VTAB: {
      sqlite4_vtab *pVtab = pOp->p4.pVtab->pVtab;
      sqlite4_snprintf(zTemp, nTemp, "vtab:%p:%p", pVtab, pVtab->pModule);
      break;
    }
#endif
    case P4_INTARRAY: {
      int i, j, n, cSep = '(';
      i = sqlite4_snprintf(zTemp, nTemp, "intarray");
      n = pOp->opcode==OP_Permutation ? pOp->p1 : 0;
      for(j=0; j<n; j++){
        i += sqlite4_snprintf(zTemp+i, nTemp-i,"%c%d",cSep, pOp->p4.ai[j]);
        cSep = ',';
      }
      sqlite4_snprintf(zTemp+i, nTemp-i, ")");
      break;
    }
    case P4_SUBPROGRAM: {
      sqlite4_snprintf(zTemp, nTemp, "program");
      break;
    }
    case P4_ADVANCE: {
      zTemp[0] = 0;
      break;
    }
    default: {
      if( pOp->opcode==OP_Blob ){
        int n = pOp->p1*2+2;
        if( n>nTemp-2 ) n = nTemp-2;
        zTemp[0] = 'x';
        zTemp[1] = '\'';
        sqlite4BlobToHex((n-2)/2,pOp->p4.z,zTemp+2);
        zTemp[n] = '\'';
        zTemp[n+1] = 0;
      }else{
        zP4 = pOp->p4.z;
        if( zP4==0 ){
          zP4 = zTemp;
          zTemp[0] = 0;
        }
      }
    }
  }
  assert( zP4!=0 );
  return zP4;
}
#endif