File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sqlite3 / src / vdbetrace.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:04:17 2012 UTC (12 years, 8 months ago) by misho
Branches: sqlite3, MAIN
CVS tags: v3_7_10, HEAD
sqlite3

    1: /*
    2: ** 2009 November 25
    3: **
    4: ** The author disclaims copyright to this source code.  In place of
    5: ** a legal notice, here is a blessing:
    6: **
    7: **    May you do good and not evil.
    8: **    May you find forgiveness for yourself and forgive others.
    9: **    May you share freely, never taking more than you give.
   10: **
   11: *************************************************************************
   12: **
   13: ** This file contains code used to insert the values of host parameters
   14: ** (aka "wildcards") into the SQL text output by sqlite3_trace().
   15: **
   16: ** The Vdbe parse-tree explainer is also found here.
   17: */
   18: #include "sqliteInt.h"
   19: #include "vdbeInt.h"
   20: 
   21: #ifndef SQLITE_OMIT_TRACE
   22: 
   23: /*
   24: ** zSql is a zero-terminated string of UTF-8 SQL text.  Return the number of
   25: ** bytes in this text up to but excluding the first character in
   26: ** a host parameter.  If the text contains no host parameters, return
   27: ** the total number of bytes in the text.
   28: */
   29: static int findNextHostParameter(const char *zSql, int *pnToken){
   30:   int tokenType;
   31:   int nTotal = 0;
   32:   int n;
   33: 
   34:   *pnToken = 0;
   35:   while( zSql[0] ){
   36:     n = sqlite3GetToken((u8*)zSql, &tokenType);
   37:     assert( n>0 && tokenType!=TK_ILLEGAL );
   38:     if( tokenType==TK_VARIABLE ){
   39:       *pnToken = n;
   40:       break;
   41:     }
   42:     nTotal += n;
   43:     zSql += n;
   44:   }
   45:   return nTotal;
   46: }
   47: 
   48: /*
   49: ** This function returns a pointer to a nul-terminated string in memory
   50: ** obtained from sqlite3DbMalloc(). If sqlite3.vdbeExecCnt is 1, then the
   51: ** string contains a copy of zRawSql but with host parameters expanded to 
   52: ** their current bindings. Or, if sqlite3.vdbeExecCnt is greater than 1, 
   53: ** then the returned string holds a copy of zRawSql with "-- " prepended
   54: ** to each line of text.
   55: **
   56: ** The calling function is responsible for making sure the memory returned
   57: ** is eventually freed.
   58: **
   59: ** ALGORITHM:  Scan the input string looking for host parameters in any of
   60: ** these forms:  ?, ?N, $A, @A, :A.  Take care to avoid text within
   61: ** string literals, quoted identifier names, and comments.  For text forms,
   62: ** the host parameter index is found by scanning the perpared
   63: ** statement for the corresponding OP_Variable opcode.  Once the host
   64: ** parameter index is known, locate the value in p->aVar[].  Then render
   65: ** the value as a literal in place of the host parameter name.
   66: */
   67: char *sqlite3VdbeExpandSql(
   68:   Vdbe *p,                 /* The prepared statement being evaluated */
   69:   const char *zRawSql      /* Raw text of the SQL statement */
   70: ){
   71:   sqlite3 *db;             /* The database connection */
   72:   int idx = 0;             /* Index of a host parameter */
   73:   int nextIndex = 1;       /* Index of next ? host parameter */
   74:   int n;                   /* Length of a token prefix */
   75:   int nToken;              /* Length of the parameter token */
   76:   int i;                   /* Loop counter */
   77:   Mem *pVar;               /* Value of a host parameter */
   78:   StrAccum out;            /* Accumulate the output here */
   79:   char zBase[100];         /* Initial working space */
   80: 
   81:   db = p->db;
   82:   sqlite3StrAccumInit(&out, zBase, sizeof(zBase), 
   83:                       db->aLimit[SQLITE_LIMIT_LENGTH]);
   84:   out.db = db;
   85:   if( db->vdbeExecCnt>1 ){
   86:     while( *zRawSql ){
   87:       const char *zStart = zRawSql;
   88:       while( *(zRawSql++)!='\n' && *zRawSql );
   89:       sqlite3StrAccumAppend(&out, "-- ", 3);
   90:       sqlite3StrAccumAppend(&out, zStart, (int)(zRawSql-zStart));
   91:     }
   92:   }else{
   93:     while( zRawSql[0] ){
   94:       n = findNextHostParameter(zRawSql, &nToken);
   95:       assert( n>0 );
   96:       sqlite3StrAccumAppend(&out, zRawSql, n);
   97:       zRawSql += n;
   98:       assert( zRawSql[0] || nToken==0 );
   99:       if( nToken==0 ) break;
  100:       if( zRawSql[0]=='?' ){
  101:         if( nToken>1 ){
  102:           assert( sqlite3Isdigit(zRawSql[1]) );
  103:           sqlite3GetInt32(&zRawSql[1], &idx);
  104:         }else{
  105:           idx = nextIndex;
  106:         }
  107:       }else{
  108:         assert( zRawSql[0]==':' || zRawSql[0]=='$' || zRawSql[0]=='@' );
  109:         testcase( zRawSql[0]==':' );
  110:         testcase( zRawSql[0]=='$' );
  111:         testcase( zRawSql[0]=='@' );
  112:         idx = sqlite3VdbeParameterIndex(p, zRawSql, nToken);
  113:         assert( idx>0 );
  114:       }
  115:       zRawSql += nToken;
  116:       nextIndex = idx + 1;
  117:       assert( idx>0 && idx<=p->nVar );
  118:       pVar = &p->aVar[idx-1];
  119:       if( pVar->flags & MEM_Null ){
  120:         sqlite3StrAccumAppend(&out, "NULL", 4);
  121:       }else if( pVar->flags & MEM_Int ){
  122:         sqlite3XPrintf(&out, "%lld", pVar->u.i);
  123:       }else if( pVar->flags & MEM_Real ){
  124:         sqlite3XPrintf(&out, "%!.15g", pVar->r);
  125:       }else if( pVar->flags & MEM_Str ){
  126: #ifndef SQLITE_OMIT_UTF16
  127:         u8 enc = ENC(db);
  128:         if( enc!=SQLITE_UTF8 ){
  129:           Mem utf8;
  130:           memset(&utf8, 0, sizeof(utf8));
  131:           utf8.db = db;
  132:           sqlite3VdbeMemSetStr(&utf8, pVar->z, pVar->n, enc, SQLITE_STATIC);
  133:           sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8);
  134:           sqlite3XPrintf(&out, "'%.*q'", utf8.n, utf8.z);
  135:           sqlite3VdbeMemRelease(&utf8);
  136:         }else
  137: #endif
  138:         {
  139:           sqlite3XPrintf(&out, "'%.*q'", pVar->n, pVar->z);
  140:         }
  141:       }else if( pVar->flags & MEM_Zero ){
  142:         sqlite3XPrintf(&out, "zeroblob(%d)", pVar->u.nZero);
  143:       }else{
  144:         assert( pVar->flags & MEM_Blob );
  145:         sqlite3StrAccumAppend(&out, "x'", 2);
  146:         for(i=0; i<pVar->n; i++){
  147:           sqlite3XPrintf(&out, "%02x", pVar->z[i]&0xff);
  148:         }
  149:         sqlite3StrAccumAppend(&out, "'", 1);
  150:       }
  151:     }
  152:   }
  153:   return sqlite3StrAccumFinish(&out);
  154: }
  155: 
  156: #endif /* #ifndef SQLITE_OMIT_TRACE */
  157: 
  158: /*****************************************************************************
  159: ** The following code implements the data-structure explaining logic
  160: ** for the Vdbe.
  161: */
  162: 
  163: #if defined(SQLITE_ENABLE_TREE_EXPLAIN)
  164: 
  165: /*
  166: ** Allocate a new Explain object
  167: */
  168: void sqlite3ExplainBegin(Vdbe *pVdbe){
  169:   if( pVdbe ){
  170:     sqlite3BeginBenignMalloc();
  171:     Explain *p = sqlite3_malloc( sizeof(Explain) );
  172:     if( p ){
  173:       memset(p, 0, sizeof(*p));
  174:       p->pVdbe = pVdbe;
  175:       sqlite3_free(pVdbe->pExplain);
  176:       pVdbe->pExplain = p;
  177:       sqlite3StrAccumInit(&p->str, p->zBase, sizeof(p->zBase),
  178:                           SQLITE_MAX_LENGTH);
  179:       p->str.useMalloc = 2;
  180:     }else{
  181:       sqlite3EndBenignMalloc();
  182:     }
  183:   }
  184: }
  185: 
  186: /*
  187: ** Return true if the Explain ends with a new-line.
  188: */
  189: static int endsWithNL(Explain *p){
  190:   return p && p->str.zText && p->str.nChar
  191:            && p->str.zText[p->str.nChar-1]=='\n';
  192: }
  193:     
  194: /*
  195: ** Append text to the indentation
  196: */
  197: void sqlite3ExplainPrintf(Vdbe *pVdbe, const char *zFormat, ...){
  198:   Explain *p;
  199:   if( pVdbe && (p = pVdbe->pExplain)!=0 ){
  200:     va_list ap;
  201:     if( p->nIndent && endsWithNL(p) ){
  202:       int n = p->nIndent;
  203:       if( n>ArraySize(p->aIndent) ) n = ArraySize(p->aIndent);
  204:       sqlite3AppendSpace(&p->str, p->aIndent[n-1]);
  205:     }   
  206:     va_start(ap, zFormat);
  207:     sqlite3VXPrintf(&p->str, 1, zFormat, ap);
  208:     va_end(ap);
  209:   }
  210: }
  211: 
  212: /*
  213: ** Append a '\n' if there is not already one.
  214: */
  215: void sqlite3ExplainNL(Vdbe *pVdbe){
  216:   Explain *p;
  217:   if( pVdbe && (p = pVdbe->pExplain)!=0 && !endsWithNL(p) ){
  218:     sqlite3StrAccumAppend(&p->str, "\n", 1);
  219:   }
  220: }
  221: 
  222: /*
  223: ** Push a new indentation level.  Subsequent lines will be indented
  224: ** so that they begin at the current cursor position.
  225: */
  226: void sqlite3ExplainPush(Vdbe *pVdbe){
  227:   Explain *p;
  228:   if( pVdbe && (p = pVdbe->pExplain)!=0 ){
  229:     if( p->str.zText && p->nIndent<ArraySize(p->aIndent) ){
  230:       const char *z = p->str.zText;
  231:       int i = p->str.nChar-1;
  232:       int x;
  233:       while( i>=0 && z[i]!='\n' ){ i--; }
  234:       x = (p->str.nChar - 1) - i;
  235:       if( p->nIndent && x<p->aIndent[p->nIndent-1] ){
  236:         x = p->aIndent[p->nIndent-1];
  237:       }
  238:       p->aIndent[p->nIndent] = x;
  239:     }
  240:     p->nIndent++;
  241:   }
  242: }
  243: 
  244: /*
  245: ** Pop the indentation stack by one level.
  246: */
  247: void sqlite3ExplainPop(Vdbe *p){
  248:   if( p && p->pExplain ) p->pExplain->nIndent--;
  249: }
  250: 
  251: /*
  252: ** Free the indentation structure
  253: */
  254: void sqlite3ExplainFinish(Vdbe *pVdbe){
  255:   if( pVdbe && pVdbe->pExplain ){
  256:     sqlite3_free(pVdbe->zExplain);
  257:     sqlite3ExplainNL(pVdbe);
  258:     pVdbe->zExplain = sqlite3StrAccumFinish(&pVdbe->pExplain->str);
  259:     sqlite3_free(pVdbe->pExplain);
  260:     pVdbe->pExplain = 0;
  261:     sqlite3EndBenignMalloc();
  262:   }
  263: }
  264: 
  265: /*
  266: ** Return the explanation of a virtual machine.
  267: */
  268: const char *sqlite3VdbeExplanation(Vdbe *pVdbe){
  269:   return (pVdbe && pVdbe->zExplain) ? pVdbe->zExplain : 0;
  270: }
  271: #endif /* defined(SQLITE_DEBUG) */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>