SQLite

Check-in [cb4b928648]
Login

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

Overview
Comment:Simplifications to the sqlite3_trace() bound parameter substitution logic.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: cb4b928648504ce29d751834e9ee3b5278dfca65
User & Date: drh 2009-11-26 14:01:53.000
Context
2009-11-27
12:12
Move [7d30880114] to the trunk. Add optimizations to reduce the number of opcodes used for BEFORE UPDATE triggers. (check-in: 1b7c5250cc user: dan tags: trunk)
2009-11-26
14:01
Simplifications to the sqlite3_trace() bound parameter substitution logic. (check-in: cb4b928648 user: drh tags: trunk)
2009-11-25
22:42
Make sure the new fts3Int.h header file is added to the amalgamation. (check-in: f25558f333 user: drh tags: trunk)
Changes
Side-by-Side Diff Ignore Whitespace Patch
Changes to src/sqliteInt.h.
2957
2958
2959
2960
2961
2962
2963

2964
2965
2966
2967
2968
2969
2970
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971







+







void sqlite3VtabArgExtend(Parse*, Token*);
int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **);
int sqlite3VtabCallConnect(Parse*, Table*);
int sqlite3VtabCallDestroy(sqlite3*, int, const char *);
int sqlite3VtabBegin(sqlite3 *, VTable *);
FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**);
int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
int sqlite3Reprepare(Vdbe*);
void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
int sqlite3TempInMemory(const sqlite3*);
VTable *sqlite3GetVTable(sqlite3*, Table*);

Changes to src/vdbeapi.c.
1116
1117
1118
1119
1120
1121
1122
1123

1124
1125
1126
1127
1128
1129
1130
1131
1132
1133

1134
1135
1136
1137
1138
1139



1140
1141
1142
1143
1144
1145
1146
1116
1117
1118
1119
1120
1121
1122

1123

1124
1125
1126
1127
1128
1129
1130
1131

1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148







-
+
-








-
+






+
+
+







}

/*
** Given a wildcard parameter name, return the index of the variable
** with that name.  If there is no variable with the given name,
** return 0.
*/
int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){
int sqlite3VdbeParameterIndex(Vdbe *p, const char *zName, int nName){
  Vdbe *p = (Vdbe*)pStmt;
  int i;
  if( p==0 ){
    return 0;
  }
  createVarMap(p); 
  if( zName ){
    for(i=0; i<p->nVar; i++){
      const char *z = p->azVar[i];
      if( z && strcmp(z,zName)==0 ){
      if( z && memcmp(z,zName,nName)==0 && z[nName]==0 ){
        return i+1;
      }
    }
  }
  return 0;
}
int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){
  return sqlite3VdbeParameterIndex((Vdbe*)pStmt, zName, sqlite3Strlen30(zName));
}

/*
** Transfer all bindings from the first statement over to the second.
*/
int sqlite3TransferBindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
  Vdbe *pFrom = (Vdbe*)pFromStmt;
  Vdbe *pTo = (Vdbe*)pToStmt;
Changes to src/vdbetrace.c.
20
21
22
23
24
25
26
27

28
29
30
31

32
33
34
35




36
37
38
39
40
41
42
43

44
45

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

66
67
68
69
70
71
72
73
74
75
76
77
78

79
80
81

82

83
84
85

86
87

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
115
116
117
118
119
120
121
122
123

124

125
126
127
128

129
130
131
132
133
134
135
20
21
22
23
24
25
26

27
28
29
30
31
32
33
34
35

36
37
38
39
40
41
42
43
44
45
46

47
48

49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

72

73
74
75
76
77
78
79
80

81
82
83
84
85

86
87


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

115
116
117
118

119
120
121
122
123
124
125
126







-
+




+



-
+
+
+
+







-
+

-
+




















+

-

-








-
+



+
-
+

-
-
+
-
-
+
-
-
+
-








-
-
+
-
-
-
-
-
-
+
-
-
+
-
-
-
+
-











+
-
+



-
+








/*
** zSql is a zero-terminated string of UTF-8 SQL text.  Return the number of
** bytes in this text up to but excluding the first character in
** a host parameter.  If the text contains no host parameters, return
** the total number of bytes in the text.
*/
static int findNextHostParameter(const char *zSql){
static int findNextHostParameter(const char *zSql, int *pnToken){
  int tokenType;
  int nTotal = 0;
  int n;

  *pnToken = 0;
  while( zSql[0] ){
    n = sqlite3GetToken((u8*)zSql, &tokenType);
    assert( n>0 && tokenType!=TK_ILLEGAL );
    if( tokenType==TK_VARIABLE ) break;
    if( tokenType==TK_VARIABLE ){
      *pnToken = n;
      break;
    }
    nTotal += n;
    zSql += n;
  }
  return nTotal;
}

/*
** Return a pointer to a string in memory obtained form sqlite3Malloc() which
** Return a pointer to a string in memory obtained form sqlite3DbMalloc() which
** holds a copy of zRawSql but with host parameters expanded to their
** current values.
** current bindings.
**
** The calling function is responsible for making sure the memory returned
** is eventually freed.
**
** ALGORITHM:  Scan the input string looking for host parameters in any of
** these forms:  ?, ?N, $A, @A, :A.  Take care to avoid text within
** string literals, quoted identifier names, and comments.  For text forms,
** the host parameter index is found by scanning the perpared
** statement for the corresponding OP_Variable opcode.  Once the host
** parameter index is known, locate the value in p->aVar[].  Then render
** the value as a literal in place of the host parameter name.
*/
char *sqlite3VdbeExpandSql(
  Vdbe *p,                 /* The prepared statement being evaluated */
  const char *zRawSql      /* Raw text of the SQL statement */
){
  sqlite3 *db;             /* The database connection */
  int idx;                 /* Index of a host parameter */
  int nextIndex = 1;       /* Index of next ? host parameter */
  int n;                   /* Length of a token prefix */
  int nToken;              /* Length of the parameter token */
  int i;                   /* Loop counter */
  int dummy;               /* For holding a unused return value */
  Mem *pVar;               /* Value of a host parameter */
  VdbeOp *pOp;             /* For looping over opcodes */
  StrAccum out;            /* Accumulate the output here */
  char zBase[100];         /* Initial working space */

  db = p->db;
  sqlite3StrAccumInit(&out, zBase, sizeof(zBase), 
                      db->aLimit[SQLITE_LIMIT_LENGTH]);
  out.db = db;
  while( zRawSql[0] ){
    n = findNextHostParameter(zRawSql);
    n = findNextHostParameter(zRawSql, &nToken);
    assert( n>0 );
    sqlite3StrAccumAppend(&out, zRawSql, n);
    zRawSql += n;
    assert( zRawSql[0] || nToken==0 );
    if( zRawSql[0]==0 ) break;
    if( nToken==0 ) break;
    if( zRawSql[0]=='?' ){
      zRawSql++;
      if( sqlite3Isdigit(zRawSql[0]) ){
      if( nToken>1 ){
        idx = 0;
        while( sqlite3Isdigit(zRawSql[0]) ){
        assert( sqlite3Isdigit(zRawSql[1]) );
          idx = idx*10 + zRawSql[0] - '0';
          zRawSql++;
        sqlite3GetInt32(&zRawSql[1], &idx);
        }
      }else{
        idx = nextIndex;
      }
    }else{
      assert( zRawSql[0]==':' || zRawSql[0]=='$' || zRawSql[0]=='@' );
      testcase( zRawSql[0]==':' );
      testcase( zRawSql[0]=='$' );
      testcase( zRawSql[0]=='@' );
      n = sqlite3GetToken((u8*)zRawSql, &dummy);
      idx = 0;
      idx = sqlite3VdbeParameterIndex(p, zRawSql, nToken);
      for(i=0, pOp=p->aOp; ALWAYS(i<p->nOp); i++, pOp++){
        if( pOp->opcode!=OP_Variable ) continue;
        if( pOp->p3>1 ) continue;
        if( pOp->p4.z==0 ) continue;
        if( memcmp(pOp->p4.z, zRawSql, n)==0 && pOp->p4.z[n]==0 ){
          idx = pOp->p1;
      assert( idx>0 );
          break;
        }
    }
      }
      assert( idx>0 );
      zRawSql += n;
    zRawSql += nToken;
    }
    nextIndex = idx + 1;
    assert( idx>0 && idx<=p->nVar );
    pVar = &p->aVar[idx-1];
    if( pVar->flags & MEM_Null ){
      sqlite3StrAccumAppend(&out, "NULL", 4);
    }else if( pVar->flags & MEM_Int ){
      sqlite3XPrintf(&out, "%lld", pVar->u.i);
    }else if( pVar->flags & MEM_Real ){
      sqlite3XPrintf(&out, "%!.15g", pVar->r);
    }else if( pVar->flags & MEM_Str ){
#ifndef SQLITE_OMIT_UTF16
      u8 enc = ENC(db);
      if( ENC(db)!=SQLITE_UTF8 ){
      if( enc!=SQLITE_UTF8 ){
        Mem utf8;
        memset(&utf8, 0, sizeof(utf8));
        utf8.db = db;
        sqlite3VdbeMemSetStr(&utf8, pVar->z, pVar->n, ENC(db), SQLITE_STATIC);
        sqlite3VdbeMemSetStr(&utf8, pVar->z, pVar->n, enc, SQLITE_STATIC);
        sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8);
        sqlite3XPrintf(&out, "'%.*q'", utf8.n, utf8.z);
        sqlite3VdbeMemRelease(&utf8);
      }else
#endif
      {
        sqlite3XPrintf(&out, "'%.*q'", pVar->n, pVar->z);