/ Check-in [cb4b9286]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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 | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: cb4b928648504ce29d751834e9ee3b5278dfca65
User & Date: drh 2009-11-26 14:01:53
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: 1b7c5250 user: dan tags: trunk
2009-11-26
14:01
Simplifications to the sqlite3_trace() bound parameter substitution logic. check-in: cb4b9286 user: drh tags: trunk
2009-11-25
22:42
Make sure the new fts3Int.h header file is added to the amalgamation. check-in: f25558f3 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/sqliteInt.h.

  2957   2957   void sqlite3VtabArgExtend(Parse*, Token*);
  2958   2958   int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **);
  2959   2959   int sqlite3VtabCallConnect(Parse*, Table*);
  2960   2960   int sqlite3VtabCallDestroy(sqlite3*, int, const char *);
  2961   2961   int sqlite3VtabBegin(sqlite3 *, VTable *);
  2962   2962   FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
  2963   2963   void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**);
         2964  +int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
  2964   2965   int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
  2965   2966   int sqlite3Reprepare(Vdbe*);
  2966   2967   void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
  2967   2968   CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
  2968   2969   int sqlite3TempInMemory(const sqlite3*);
  2969   2970   VTable *sqlite3GetVTable(sqlite3*, Table*);
  2970   2971   

Changes to src/vdbeapi.c.

  1116   1116   }
  1117   1117   
  1118   1118   /*
  1119   1119   ** Given a wildcard parameter name, return the index of the variable
  1120   1120   ** with that name.  If there is no variable with the given name,
  1121   1121   ** return 0.
  1122   1122   */
  1123         -int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){
  1124         -  Vdbe *p = (Vdbe*)pStmt;
         1123  +int sqlite3VdbeParameterIndex(Vdbe *p, const char *zName, int nName){
  1125   1124     int i;
  1126   1125     if( p==0 ){
  1127   1126       return 0;
  1128   1127     }
  1129   1128     createVarMap(p); 
  1130   1129     if( zName ){
  1131   1130       for(i=0; i<p->nVar; i++){
  1132   1131         const char *z = p->azVar[i];
  1133         -      if( z && strcmp(z,zName)==0 ){
         1132  +      if( z && memcmp(z,zName,nName)==0 && z[nName]==0 ){
  1134   1133           return i+1;
  1135   1134         }
  1136   1135       }
  1137   1136     }
  1138   1137     return 0;
  1139   1138   }
         1139  +int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){
         1140  +  return sqlite3VdbeParameterIndex((Vdbe*)pStmt, zName, sqlite3Strlen30(zName));
         1141  +}
  1140   1142   
  1141   1143   /*
  1142   1144   ** Transfer all bindings from the first statement over to the second.
  1143   1145   */
  1144   1146   int sqlite3TransferBindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
  1145   1147     Vdbe *pFrom = (Vdbe*)pFromStmt;
  1146   1148     Vdbe *pTo = (Vdbe*)pToStmt;

Changes to src/vdbetrace.c.

    20     20   
    21     21   /*
    22     22   ** zSql is a zero-terminated string of UTF-8 SQL text.  Return the number of
    23     23   ** bytes in this text up to but excluding the first character in
    24     24   ** a host parameter.  If the text contains no host parameters, return
    25     25   ** the total number of bytes in the text.
    26     26   */
    27         -static int findNextHostParameter(const char *zSql){
           27  +static int findNextHostParameter(const char *zSql, int *pnToken){
    28     28     int tokenType;
    29     29     int nTotal = 0;
    30     30     int n;
    31     31   
           32  +  *pnToken = 0;
    32     33     while( zSql[0] ){
    33     34       n = sqlite3GetToken((u8*)zSql, &tokenType);
    34     35       assert( n>0 && tokenType!=TK_ILLEGAL );
    35         -    if( tokenType==TK_VARIABLE ) break;
           36  +    if( tokenType==TK_VARIABLE ){
           37  +      *pnToken = n;
           38  +      break;
           39  +    }
    36     40       nTotal += n;
    37     41       zSql += n;
    38     42     }
    39     43     return nTotal;
    40     44   }
    41     45   
    42     46   /*
    43         -** Return a pointer to a string in memory obtained form sqlite3Malloc() which
           47  +** Return a pointer to a string in memory obtained form sqlite3DbMalloc() which
    44     48   ** holds a copy of zRawSql but with host parameters expanded to their
    45         -** current values.
           49  +** current bindings.
    46     50   **
    47     51   ** The calling function is responsible for making sure the memory returned
    48     52   ** is eventually freed.
    49     53   **
    50     54   ** ALGORITHM:  Scan the input string looking for host parameters in any of
    51     55   ** these forms:  ?, ?N, $A, @A, :A.  Take care to avoid text within
    52     56   ** string literals, quoted identifier names, and comments.  For text forms,
................................................................................
    59     63     Vdbe *p,                 /* The prepared statement being evaluated */
    60     64     const char *zRawSql      /* Raw text of the SQL statement */
    61     65   ){
    62     66     sqlite3 *db;             /* The database connection */
    63     67     int idx;                 /* Index of a host parameter */
    64     68     int nextIndex = 1;       /* Index of next ? host parameter */
    65     69     int n;                   /* Length of a token prefix */
           70  +  int nToken;              /* Length of the parameter token */
    66     71     int i;                   /* Loop counter */
    67         -  int dummy;               /* For holding a unused return value */
    68     72     Mem *pVar;               /* Value of a host parameter */
    69         -  VdbeOp *pOp;             /* For looping over opcodes */
    70     73     StrAccum out;            /* Accumulate the output here */
    71     74     char zBase[100];         /* Initial working space */
    72     75   
    73     76     db = p->db;
    74     77     sqlite3StrAccumInit(&out, zBase, sizeof(zBase), 
    75     78                         db->aLimit[SQLITE_LIMIT_LENGTH]);
    76     79     out.db = db;
    77     80     while( zRawSql[0] ){
    78         -    n = findNextHostParameter(zRawSql);
           81  +    n = findNextHostParameter(zRawSql, &nToken);
    79     82       assert( n>0 );
    80     83       sqlite3StrAccumAppend(&out, zRawSql, n);
    81     84       zRawSql += n;
    82         -    if( zRawSql[0]==0 ) break;
           85  +    assert( zRawSql[0] || nToken==0 );
           86  +    if( nToken==0 ) break;
    83     87       if( zRawSql[0]=='?' ){
    84         -      zRawSql++;
    85         -      if( sqlite3Isdigit(zRawSql[0]) ){
    86         -        idx = 0;
    87         -        while( sqlite3Isdigit(zRawSql[0]) ){
    88         -          idx = idx*10 + zRawSql[0] - '0';
    89         -          zRawSql++;
    90         -        }
           88  +      if( nToken>1 ){
           89  +        assert( sqlite3Isdigit(zRawSql[1]) );
           90  +        sqlite3GetInt32(&zRawSql[1], &idx);
    91     91         }else{
    92     92           idx = nextIndex;
    93     93         }
    94     94       }else{
    95     95         assert( zRawSql[0]==':' || zRawSql[0]=='$' || zRawSql[0]=='@' );
    96     96         testcase( zRawSql[0]==':' );
    97     97         testcase( zRawSql[0]=='$' );
    98     98         testcase( zRawSql[0]=='@' );
    99         -      n = sqlite3GetToken((u8*)zRawSql, &dummy);
   100         -      idx = 0;
   101         -      for(i=0, pOp=p->aOp; ALWAYS(i<p->nOp); i++, pOp++){
   102         -        if( pOp->opcode!=OP_Variable ) continue;
   103         -        if( pOp->p3>1 ) continue;
   104         -        if( pOp->p4.z==0 ) continue;
   105         -        if( memcmp(pOp->p4.z, zRawSql, n)==0 && pOp->p4.z[n]==0 ){
   106         -          idx = pOp->p1;
   107         -          break;
   108         -        }
   109         -      }
           99  +      idx = sqlite3VdbeParameterIndex(p, zRawSql, nToken);
   110    100         assert( idx>0 );
   111         -      zRawSql += n;
   112    101       }
          102  +    zRawSql += nToken;
   113    103       nextIndex = idx + 1;
   114    104       assert( idx>0 && idx<=p->nVar );
   115    105       pVar = &p->aVar[idx-1];
   116    106       if( pVar->flags & MEM_Null ){
   117    107         sqlite3StrAccumAppend(&out, "NULL", 4);
   118    108       }else if( pVar->flags & MEM_Int ){
   119    109         sqlite3XPrintf(&out, "%lld", pVar->u.i);
   120    110       }else if( pVar->flags & MEM_Real ){
   121    111         sqlite3XPrintf(&out, "%!.15g", pVar->r);
   122    112       }else if( pVar->flags & MEM_Str ){
   123    113   #ifndef SQLITE_OMIT_UTF16
   124         -      if( ENC(db)!=SQLITE_UTF8 ){
          114  +      u8 enc = ENC(db);
          115  +      if( enc!=SQLITE_UTF8 ){
   125    116           Mem utf8;
   126    117           memset(&utf8, 0, sizeof(utf8));
   127    118           utf8.db = db;
   128         -        sqlite3VdbeMemSetStr(&utf8, pVar->z, pVar->n, ENC(db), SQLITE_STATIC);
          119  +        sqlite3VdbeMemSetStr(&utf8, pVar->z, pVar->n, enc, SQLITE_STATIC);
   129    120           sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8);
   130    121           sqlite3XPrintf(&out, "'%.*q'", utf8.n, utf8.z);
   131    122           sqlite3VdbeMemRelease(&utf8);
   132    123         }else
   133    124   #endif
   134    125         {
   135    126           sqlite3XPrintf(&out, "'%.*q'", pVar->n, pVar->z);