/ Check-in [0e50c020]
Login

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

Overview
Comment:Remove the OP_HexBlob instruction and code OP_Blob directly. Reduce the amount of memory allocation required to encode blob literals. Remove the "out2" instruction type. Other minor optimizations. (CVS 4726)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:0e50c0200a3c1c04e63cbb55a7255cdbbd225347
User & Date: drh 2008-01-18 14:08:24
Context
2008-01-18
14:17
Remove an absolute path from crash5.test. (CVS 4727) check-in: 42d8a377 user: danielk1977 tags: trunk
14:08
Remove the OP_HexBlob instruction and code OP_Blob directly. Reduce the amount of memory allocation required to encode blob literals. Remove the "out2" instruction type. Other minor optimizations. (CVS 4726) check-in: 0e50c020 user: drh tags: trunk
13:42
Add a test (and fix) for possible corruption if malloc() fails during a CREATE INDEX statement, the application continues with the transaction, then crashes. (CVS 4725) check-in: 65245d99 user: danielk1977 tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to mkopcodeh.awk.

51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
..
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
...
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
  sub("\r","",name)
  op[name] = -1
  jump[name] = 0
  out2_prerelease[name] = 0
  in1[name] = 0
  in2[name] = 0
  in3[name] = 0
  out2[name] = 0
  out3[name] = 0
  for(i=3; i<NF; i++){
    if($i=="same" && $(i+1)=="as"){
      sym = $(i+2)
      sub(/,/,"",sym)
      op[name] = tk[sym]
      used[op[name]] = 1
................................................................................
      out2_prerelease[name] = 1
    }else if(x=="in1"){
      in1[name] = 1
    }else if(x=="in2"){
      in2[name] = 1
    }else if(x=="in3"){
      in3[name] = 1
    }else if(x=="out2"){
      out2[name] = 1
    }else if(x=="out3"){
      out3[name] = 1
    }
  }
}

# Assign numbers to all opcodes and output the result.
................................................................................
    a0 = a1 = a2 = a3 = a4 = a5 = a6 = a7 = 0
    # a8 = a9 = a10 = a11 = a12 = a13 = a14 = a15 = 0
    if( jump[name] ) a0 = 1;
    if( out2_prerelease[name] ) a1 = 2;
    if( in1[name] ) a2 = 4;
    if( in2[name] ) a3 = 8;
    if( in3[name] ) a4 = 16;
    if( out2[name] ) a5 = 32;
    if( out3[name] ) a6 = 64;
    # bv[x] = a0+a1+a2+a3+a4+a5+a6+a7+a8+a9+a10+a11+a12+a13+a14+a15;
    bv[x] = a0+a1+a2+a3+a4+a5+a6;
  }
  print "\n"
  print "/* Properties such as \"out2\" or \"jump\" that are specified in"
  print "** comments following the \"case\" for each opcode in the vdbe.c"
  print "** are encoded into bitvectors as follows:"
  print "*/"
  print "#define OPFLG_JUMP            0x0001  /* jump:  P2 holds jmp target */"
  print "#define OPFLG_OUT2_PRERELEASE 0x0002  /* out2-prerelease: */"
  print "#define OPFLG_IN1             0x0004  /* in1:   P1 is an input */"
  print "#define OPFLG_IN2             0x0008  /* in2:   P2 is an input */"
  print "#define OPFLG_IN3             0x0010  /* in3:   P3 is an input */"
  print "#define OPFLG_OUT2            0x0020  /* out2:  P2 is an output */"
  print "#define OPFLG_OUT3            0x0040  /* out3:  P3 is an output */"
  print "#define OPFLG_INITIALIZER {\\"
  for(i=0; i<=max; i++){
    if( i%8==0 ) printf("/* %3d */",i)
    printf " 0x%02x,", bv[i]
    if( i%8==7 ) printf("\\\n");
  }
  print "}"
}







<







 







<
<







 







<
|

|











<
|








51
52
53
54
55
56
57

58
59
60
61
62
63
64
..
72
73
74
75
76
77
78


79
80
81
82
83
84
85
...
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
  sub("\r","",name)
  op[name] = -1
  jump[name] = 0
  out2_prerelease[name] = 0
  in1[name] = 0
  in2[name] = 0
  in3[name] = 0

  out3[name] = 0
  for(i=3; i<NF; i++){
    if($i=="same" && $(i+1)=="as"){
      sym = $(i+2)
      sub(/,/,"",sym)
      op[name] = tk[sym]
      used[op[name]] = 1
................................................................................
      out2_prerelease[name] = 1
    }else if(x=="in1"){
      in1[name] = 1
    }else if(x=="in2"){
      in2[name] = 1
    }else if(x=="in3"){
      in3[name] = 1


    }else if(x=="out3"){
      out3[name] = 1
    }
  }
}

# Assign numbers to all opcodes and output the result.
................................................................................
    a0 = a1 = a2 = a3 = a4 = a5 = a6 = a7 = 0
    # a8 = a9 = a10 = a11 = a12 = a13 = a14 = a15 = 0
    if( jump[name] ) a0 = 1;
    if( out2_prerelease[name] ) a1 = 2;
    if( in1[name] ) a2 = 4;
    if( in2[name] ) a3 = 8;
    if( in3[name] ) a4 = 16;

    if( out3[name] ) a5 = 32;
    # bv[x] = a0+a1+a2+a3+a4+a5+a6+a7+a8+a9+a10+a11+a12+a13+a14+a15;
    bv[x] = a0+a1+a2+a3+a4+a5+a6+a7;
  }
  print "\n"
  print "/* Properties such as \"out2\" or \"jump\" that are specified in"
  print "** comments following the \"case\" for each opcode in the vdbe.c"
  print "** are encoded into bitvectors as follows:"
  print "*/"
  print "#define OPFLG_JUMP            0x0001  /* jump:  P2 holds jmp target */"
  print "#define OPFLG_OUT2_PRERELEASE 0x0002  /* out2-prerelease: */"
  print "#define OPFLG_IN1             0x0004  /* in1:   P1 is an input */"
  print "#define OPFLG_IN2             0x0008  /* in2:   P2 is an input */"
  print "#define OPFLG_IN3             0x0010  /* in3:   P3 is an input */"

  print "#define OPFLG_OUT3            0x0020  /* out3:  P3 is an output */"
  print "#define OPFLG_INITIALIZER {\\"
  for(i=0; i<=max; i++){
    if( i%8==0 ) printf("/* %3d */",i)
    printf " 0x%02x,", bv[i]
    if( i%8==7 ) printf("\\\n");
  }
  print "}"
}

Changes to src/expr.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
....
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014

2015
2016
2017
2018
2019
2020
2021
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.349 2008/01/18 02:31:56 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** Return the 'affinity' of the expression pExpr if any.
**
................................................................................
      sqlite3VdbeAddOp2(v, OP_Null, 0, target);
      break;
    }
#ifndef SQLITE_OMIT_BLOB_LITERAL
    case TK_BLOB: {
      int n;
      const char *z;
      assert( TK_BLOB==OP_HexBlob );
      n = pExpr->token.n - 3;
      z = (char*)pExpr->token.z + 2;
      assert( n>=0 );
      if( n==0 ){
        z = "";
      }
      sqlite3VdbeAddOp4(v, op, 0, target, 0, z, n);

      break;
    }
#endif
    case TK_VARIABLE: {
      sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iTable, target);
      if( pExpr->token.n>1 ){
        sqlite3VdbeChangeP4(v, -1, (char*)pExpr->token.z, pExpr->token.n);







|







 







|
|
|
|
|
|
|
|
>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
....
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.350 2008/01/18 14:08:24 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** Return the 'affinity' of the expression pExpr if any.
**
................................................................................
      sqlite3VdbeAddOp2(v, OP_Null, 0, target);
      break;
    }
#ifndef SQLITE_OMIT_BLOB_LITERAL
    case TK_BLOB: {
      int n;
      const char *z;
      char *zBlob;
      assert( pExpr->token.n>=3 );
      assert( pExpr->token.z[0]=='x' || pExpr->token.z[0]=='X' );
      assert( pExpr->token.z[1]=='\'' );
      assert( pExpr->token.z[pExpr->token.n-1]=='\'' );
      n = pExpr->token.n - 3;
      z = (char*)pExpr->token.z + 2;
      zBlob = sqlite3HexToBlob(sqlite3VdbeDb(v), z, n);
      sqlite3VdbeAddOp4(v, OP_Blob, n/2, target, 0, zBlob, P4_DYNAMIC);
      break;
    }
#endif
    case TK_VARIABLE: {
      sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iTable, target);
      if( pExpr->token.n>1 ){
        sqlite3VdbeChangeP4(v, -1, (char*)pExpr->token.z, pExpr->token.n);

Changes to src/sqliteInt.h.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
....
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.651 2008/01/17 16:22:15 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** The macro unlikely() is a hint that surrounds a boolean
** expression that is usually false.  Macro likely() surrounds
................................................................................
void sqlite3IndexAffinityStr(Vdbe *, Index *);
void sqlite3TableAffinityStr(Vdbe *, Table *);
char sqlite3CompareAffinity(Expr *pExpr, char aff2);
int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
char sqlite3ExprAffinity(Expr *pExpr);
int sqlite3Atoi64(const char*, i64*);
void sqlite3Error(sqlite3*, int, const char*,...);
void *sqlite3HexToBlob(sqlite3*, const char *z);
int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
const char *sqlite3ErrStr(int);
int sqlite3ReadSchema(Parse *pParse);
CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char *,int,int);
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName);
CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
Expr *sqlite3ExprSetColl(Parse *pParse, Expr *, Token *);







|







 







|







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
....
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.652 2008/01/18 14:08:24 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** The macro unlikely() is a hint that surrounds a boolean
** expression that is usually false.  Macro likely() surrounds
................................................................................
void sqlite3IndexAffinityStr(Vdbe *, Index *);
void sqlite3TableAffinityStr(Vdbe *, Table *);
char sqlite3CompareAffinity(Expr *pExpr, char aff2);
int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
char sqlite3ExprAffinity(Expr *pExpr);
int sqlite3Atoi64(const char*, i64*);
void sqlite3Error(sqlite3*, int, const char*,...);
void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
const char *sqlite3ErrStr(int);
int sqlite3ReadSchema(Parse *pParse);
CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char *,int,int);
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName);
CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
Expr *sqlite3ExprSetColl(Parse *pParse, Expr *, Token *);

Changes to src/util.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
633
634
635
636
637
638
639
640
641
642
643
644
645
646

647
648
649
650

651
652
653
654
655
656
657
**
*************************************************************************
** Utility functions used throughout sqlite.
**
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
** $Id: util.c,v 1.213 2007/10/23 15:39:45 drh Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
#include <ctype.h>


/*
................................................................................
#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
/*
** Convert a BLOB literal of the form "x'hhhhhh'" into its binary
** value.  Return a pointer to its binary value.  Space to hold the
** binary value has been obtained from malloc and must be freed by
** the calling routine.
*/
void *sqlite3HexToBlob(sqlite3 *db, const char *z){
  char *zBlob;
  int i;
  int n = strlen(z);
  if( n%2 ) return 0;

  zBlob = (char *)sqlite3DbMallocRaw(db, n/2);

  if( zBlob ){
    for(i=0; i<n; i+=2){
      zBlob[i/2] = (hexToInt(z[i])<<4) | hexToInt(z[i+1]);
    }

  }
  return zBlob;
}
#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */


/*







|







 







|


<
<

|
>




>







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
633
634
635
636
637
638
639
640
641
642


643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
**
*************************************************************************
** Utility functions used throughout sqlite.
**
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
** $Id: util.c,v 1.214 2008/01/18 14:08:25 drh Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
#include <ctype.h>


/*
................................................................................
#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
/*
** Convert a BLOB literal of the form "x'hhhhhh'" into its binary
** value.  Return a pointer to its binary value.  Space to hold the
** binary value has been obtained from malloc and must be freed by
** the calling routine.
*/
void *sqlite3HexToBlob(sqlite3 *db, const char *z, int n){
  char *zBlob;
  int i;



  zBlob = (char *)sqlite3DbMallocRaw(db, n/2 + 1);
  n--;
  if( zBlob ){
    for(i=0; i<n; i+=2){
      zBlob[i/2] = (hexToInt(z[i])<<4) | hexToInt(z[i+1]);
    }
    zBlob[i/2] = 0;
  }
  return zBlob;
}
#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */


/*

Changes to src/vdbe.c.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
..
88
89
90
91
92
93
94





95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
...
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
...
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
...
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
...
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
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
910
911
912
913
914
....
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
**
** 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.698 2008/01/17 16:22:15 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
** The following global variable is incremented every time a cursor
................................................................................
** or MEM_Str that has been used by a VDBE opcode.  The test procedures
** use this information to make sure that the zero-blob functionality
** is working correctly.   This variable has no function other than to
** help verify the correct operation of the library.
*/
#ifdef SQLITE_TEST
int sqlite3_max_blobsize = 0;





#endif

/*
** Test a register to see if it exceeds the current maximum blob size.
** If it does, record the new maximum blob size.
*/
#ifdef SQLITE_TEST
# define UPDATE_MAX_BLOBSIZE(P)  if( ((P)->flags&(MEM_Str|MEM_Blob))!=0 \
                                      && (P)->n>sqlite3_max_blobsize ) \
                                          {sqlite3_max_blobsize = (P)->n;}
#else
# define UPDATE_MAX_BLOBSIZE(P)
#endif

/*
** Release the memory associated with a register.  This
** leaves the Mem.flags field in an inconsistent state.
................................................................................
  unsigned long long start;  /* CPU clock count at start of opcode */
  int origPc;                /* Program counter at start of opcode */
#endif
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  int nProgressOps = 0;      /* Opcodes executed since progress callback. */
#endif

  if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE;
  assert( db->magic==SQLITE_MAGIC_BUSY );
  sqlite3BtreeMutexArrayEnter(&p->aMutex);
  if( p->rc==SQLITE_NOMEM ){
    /* This happens if a malloc() inside a call to sqlite3_column_text() or
    ** sqlite3_column_text16() failed.  */
    goto no_mem;
  }
................................................................................
    /* Do common setup for opcodes marked with one of the following
    ** combinations of properties.
    **
    **           in1
    **           in1 in2
    **           in1 in2 out3
    **           in1 in3
    **           in1 out2
    **
    ** Variables pIn1, pIn2, and pIn3 are made to point to appropriate
    ** registers for inputs.  Variable pOut points to the output register.
    */
    if( (opProperty & OPFLG_IN1)!=0 ){
      assert( pOp->p1>0 );
      assert( pOp->p1<=p->nMem );
................................................................................
          pOut = &p->aMem[pOp->p3];
        }
      }else if( (opProperty & OPFLG_IN3)!=0 ){
        assert( pOp->p3>0 );
        assert( pOp->p3<=p->nMem );
        pIn3 = &p->aMem[pOp->p3];
        REGISTER_TRACE(pOp->p3, pIn3);
      }else if( (opProperty & OPFLG_OUT2)!=0 ){
        assert( pOp->p2>0 );
        assert( pOp->p2<=p->nMem );
        pOut = &p->aMem[pOp->p2];
      }
    }else if( (opProperty & OPFLG_IN2)!=0 ){
      assert( pOp->p2>0 );
      assert( pOp->p2<=p->nMem );
      pIn2 = &p->aMem[pOp->p2];
      REGISTER_TRACE(pOp->p2, pIn2);
    }else if( (opProperty & OPFLG_IN3)!=0 ){
................................................................................
*/
case OP_Null: {           /* out2-prerelease */
  break;
}


#ifndef SQLITE_OMIT_BLOB_LITERAL
/* Opcode: HexBlob * P2 * P4 *
**
** P4 is an UTF-8 SQL hex encoding of a blob. The blob is stored in
** register P2.
**
** The first time this instruction executes, in transforms itself into a
** 'Blob' opcode with a binary blob as P4.
*/
case OP_HexBlob: {            /* same as TK_BLOB, out2-prerelease */
  pOp->opcode = OP_Blob;
  pOp->p1 = strlen(pOp->p4.z)/2;
  if( pOp->p1>SQLITE_MAX_LENGTH ){
    goto too_big;
  }
  if( pOp->p1 ){
    char *zBlob = sqlite3HexToBlob(db, pOp->p4.z);
    if( !zBlob ) goto no_mem;
    if( pOp->p4type==P4_DYNAMIC ){
      sqlite3_free(pOp->p4.z);
    }
    pOp->p4.z = zBlob;
    pOp->p4type = P4_DYNAMIC;
  }else{
    if( pOp->p4type==P4_DYNAMIC ){
      sqlite3_free(pOp->p4.z);
    }
    pOp->p4type = P4_STATIC;
    pOp->p4.z = "";
  }

  /* Fall through to the next case, OP_Blob. */
}

/* Opcode: Blob P1 P2 * P4
**
** P4 points to a blob of data P1 bytes long.  Store this
** blob in register P2. This instruction is not coded directly
** by the compiler. Instead, the compiler layer specifies
** an OP_HexBlob opcode, with the hex string representation of
** the blob as P4. This opcode is transformed to an OP_Blob
................................................................................
    */
#ifndef NDEBUG
    assert( pc>=-1 && pc<p->nOp );

#ifdef SQLITE_DEBUG
    if( p->trace ){
      if( rc!=0 ) fprintf(p->trace,"rc=%d\n",rc);
      if( (opProperty&(OPFLG_OUT2_PRERELEASE|OPFLG_OUT2))!=0 && pOp->p2>0 ){
        registerTrace(p->trace, pOp->p2, pOut);
      }
      if( (opProperty&OPFLG_OUT3)!=0 && pOp->p3>0 ){
        registerTrace(p->trace, pOp->p3, pOut);
      }
    }
#endif  /* SQLITE_DEBUG */
#endif  /* NDEBUG */
  }  /* The end of the for(;;) loop the loops through opcodes */








|







 







>
>
>
>
>







|
<
<







 







|







 







<







 







<
<
<
<







 







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







 







|


|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
..
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107


108
109
110
111
112
113
114
...
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
...
620
621
622
623
624
625
626

627
628
629
630
631
632
633
...
644
645
646
647
648
649
650




651
652
653
654
655
656
657
...
866
867
868
869
870
871
872

































873
874
875
876
877
878
879
....
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
**
** 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.699 2008/01/18 14:08:25 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
** The following global variable is incremented every time a cursor
................................................................................
** or MEM_Str that has been used by a VDBE opcode.  The test procedures
** use this information to make sure that the zero-blob functionality
** is working correctly.   This variable has no function other than to
** help verify the correct operation of the library.
*/
#ifdef SQLITE_TEST
int sqlite3_max_blobsize = 0;
static void updateMaxBlobsize(Mem *p){
  if( (p->flags & (MEM_Str|MEM_Blob))!=0 && p->n>sqlite3_max_blobsize ){
    sqlite3_max_blobsize = p->n;
  }
}
#endif

/*
** Test a register to see if it exceeds the current maximum blob size.
** If it does, record the new maximum blob size.
*/
#ifdef SQLITE_TEST
# define UPDATE_MAX_BLOBSIZE(P)  updateMaxBlobsize(P)


#else
# define UPDATE_MAX_BLOBSIZE(P)
#endif

/*
** Release the memory associated with a register.  This
** leaves the Mem.flags field in an inconsistent state.
................................................................................
  unsigned long long start;  /* CPU clock count at start of opcode */
  int origPc;                /* Program counter at start of opcode */
#endif
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  int nProgressOps = 0;      /* Opcodes executed since progress callback. */
#endif

  assert( p->magic==VDBE_MAGIC_RUN );  /* sqlite3_step() verifies this */
  assert( db->magic==SQLITE_MAGIC_BUSY );
  sqlite3BtreeMutexArrayEnter(&p->aMutex);
  if( p->rc==SQLITE_NOMEM ){
    /* This happens if a malloc() inside a call to sqlite3_column_text() or
    ** sqlite3_column_text16() failed.  */
    goto no_mem;
  }
................................................................................
    /* Do common setup for opcodes marked with one of the following
    ** combinations of properties.
    **
    **           in1
    **           in1 in2
    **           in1 in2 out3
    **           in1 in3

    **
    ** Variables pIn1, pIn2, and pIn3 are made to point to appropriate
    ** registers for inputs.  Variable pOut points to the output register.
    */
    if( (opProperty & OPFLG_IN1)!=0 ){
      assert( pOp->p1>0 );
      assert( pOp->p1<=p->nMem );
................................................................................
          pOut = &p->aMem[pOp->p3];
        }
      }else if( (opProperty & OPFLG_IN3)!=0 ){
        assert( pOp->p3>0 );
        assert( pOp->p3<=p->nMem );
        pIn3 = &p->aMem[pOp->p3];
        REGISTER_TRACE(pOp->p3, pIn3);




      }
    }else if( (opProperty & OPFLG_IN2)!=0 ){
      assert( pOp->p2>0 );
      assert( pOp->p2<=p->nMem );
      pIn2 = &p->aMem[pOp->p2];
      REGISTER_TRACE(pOp->p2, pIn2);
    }else if( (opProperty & OPFLG_IN3)!=0 ){
................................................................................
*/
case OP_Null: {           /* out2-prerelease */
  break;
}


#ifndef SQLITE_OMIT_BLOB_LITERAL

































/* Opcode: Blob P1 P2 * P4
**
** P4 points to a blob of data P1 bytes long.  Store this
** blob in register P2. This instruction is not coded directly
** by the compiler. Instead, the compiler layer specifies
** an OP_HexBlob opcode, with the hex string representation of
** the blob as P4. This opcode is transformed to an OP_Blob
................................................................................
    */
#ifndef NDEBUG
    assert( pc>=-1 && pc<p->nOp );

#ifdef SQLITE_DEBUG
    if( p->trace ){
      if( rc!=0 ) fprintf(p->trace,"rc=%d\n",rc);
      if( opProperty & OPFLG_OUT2_PRERELEASE ){
        registerTrace(p->trace, pOp->p2, pOut);
      }
      if( opProperty & OPFLG_OUT3 ){
        registerTrace(p->trace, pOp->p3, pOut);
      }
    }
#endif  /* SQLITE_DEBUG */
#endif  /* NDEBUG */
  }  /* The end of the for(;;) loop the loops through opcodes */

Changes to src/vdbemem.c.

985
986
987
988
989
990
991
992
993
994
995
996
997
998


999
1000
1001
1002
1003
1004
1005
      pVal->u.i = -1 * pVal->u.i;
      pVal->r = -1.0 * pVal->r;
    }
  }
#ifndef SQLITE_OMIT_BLOB_LITERAL
  else if( op==TK_BLOB ){
    int nVal;
    pVal = sqlite3ValueNew(db);
    zVal = sqlite3StrNDup((char*)pExpr->token.z+1, pExpr->token.n-1);
    if( !zVal || !pVal ) goto no_mem;
    sqlite3Dequote(zVal);
    nVal = strlen(zVal)/2;
    sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal), nVal,0,sqlite3_free);
    sqlite3_free(zVal);


  }
#endif

  *ppVal = pVal;
  return SQLITE_OK;

no_mem:







|
|
|
|
|
|
|
>
>







985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
      pVal->u.i = -1 * pVal->u.i;
      pVal->r = -1.0 * pVal->r;
    }
  }
#ifndef SQLITE_OMIT_BLOB_LITERAL
  else if( op==TK_BLOB ){
    int nVal;
    assert( pExpr->token.n>=3 );
    assert( pExpr->token.z[0]=='x' || pExpr->token.z[0]=='X' );
    assert( pExpr->token.z[1]=='\'' );
    assert( pExpr->token.z[pExpr->token.n-1]=='\'' );
    pVal = sqlite3ValueNew(db);
    nVal = pExpr->token.n - 3;
    zVal = (char*)pExpr->token.z + 2;
    sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2,
                         0, sqlite3_free);
  }
#endif

  *ppVal = pVal;
  return SQLITE_OK;

no_mem: