/ Check-in [6d2a816e]
Login

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

Overview
Comment:Cache the encoding value inside VdbeExec. (CVS 2927)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 6d2a816ede8d17b993a21e418cf25edd103334de
User & Date: drh 2006-01-12 17:20:51
Context
2006-01-12
19:42
Automatically cast BLOBs to strings prior to handing them over to functions like LIKE that want strings. Ticket #1605. (CVS 2928) check-in: 730ddb0b user: drh tags: trunk
17:20
Cache the encoding value inside VdbeExec. (CVS 2927) check-in: 6d2a816e user: drh tags: trunk
15:01
Additional performance improvements in sqlite3BtreeMoveto. (CVS 2926) check-in: 52b3be96 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/sqliteInt.h.

     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** Internal interface definitions for SQLite.
    13     13   **
    14         -** @(#) $Id: sqliteInt.h,v 1.465 2006/01/12 12:43:36 drh Exp $
           14  +** @(#) $Id: sqliteInt.h,v 1.466 2006/01/12 17:20:51 drh Exp $
    15     15   */
    16     16   #ifndef _SQLITEINT_H_
    17     17   #define _SQLITEINT_H_
    18     18   
    19     19   /*
    20     20   ** Extra interface definitions for those who need them
    21     21   */
................................................................................
   397    397     int schema_cookie;   /* Database schema version number for this file */
   398    398     Hash tblHash;        /* All tables indexed by name */
   399    399     Hash idxHash;        /* All (named) indices indexed by name */
   400    400     Hash trigHash;       /* All triggers indexed by name */
   401    401     Hash aFKey;          /* Foreign keys indexed by to-table */
   402    402     Table *pSeqTab;      /* The sqlite_sequence table used by AUTOINCREMENT */
   403    403     u8 file_format;      /* Schema format version for this file */
          404  +  u8 enc;              /* Text encoding used by this database */
   404    405     u16 flags;           /* Flags associated with this schema */
   405    406     int cache_size;      /* Number of pages to use in the cache */
   406         -  u8 enc;              /* Text encoding used by this database */
   407    407   };
   408    408   
   409    409   /*
   410    410   ** These macros can be used to test, set, or clear bits in the 
   411    411   ** Db.flags field.
   412    412   */
   413    413   #define DbHasProperty(D,I,P)     (((D)->aDb[I].pSchema->flags&(P))==(P))

Changes to src/vdbe.c.

    39     39   **
    40     40   ** Various scripts scan this source file in order to generate HTML
    41     41   ** documentation, headers files, or other derived files.  The formatting
    42     42   ** of the code in this file is, therefore, important.  See other comments
    43     43   ** in this file for details.  If in doubt, do not deviate from existing
    44     44   ** commenting and indentation practices when changing or adding code.
    45     45   **
    46         -** $Id: vdbe.c,v 1.524 2006/01/12 01:25:18 drh Exp $
           46  +** $Id: vdbe.c,v 1.525 2006/01/12 17:20:51 drh Exp $
    47     47   */
    48     48   #include "sqliteInt.h"
    49     49   #include "os.h"
    50     50   #include <ctype.h>
    51     51   #include "vdbeInt.h"
    52     52   
    53     53   /*
................................................................................
   375    375   int sqlite3VdbeExec(
   376    376     Vdbe *p                    /* The VDBE */
   377    377   ){
   378    378     int pc;                    /* The program counter */
   379    379     Op *pOp;                   /* Current operation */
   380    380     int rc = SQLITE_OK;        /* Value to return */
   381    381     sqlite3 *db = p->db;       /* The database */
          382  +  u8 encoding = ENC(db);     /* The database encoding */
   382    383     Mem *pTos;                 /* Top entry in the operand stack */
   383    384   #ifdef VDBE_PROFILE
   384    385     unsigned long long start;  /* CPU clock count at start of opcode */
   385    386     int origPc;                /* Program counter at start of opcode */
   386    387   #endif
   387    388   #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
   388    389     int nProgressOps = 0;      /* Opcodes executed since progress callback. */
................................................................................
   638    639     pTos++;
   639    640     pTos->flags = MEM_Str|MEM_Static|MEM_Term;
   640    641     pTos->z = pOp->p3;
   641    642     pTos->n = strlen(pTos->z);
   642    643     pTos->enc = SQLITE_UTF8;
   643    644     pTos->r = sqlite3VdbeRealValue(pTos);
   644    645     pTos->flags |= MEM_Real;
   645         -  sqlite3VdbeChangeEncoding(pTos, ENC(db));
          646  +  sqlite3VdbeChangeEncoding(pTos, encoding);
   646    647     break;
   647    648   }
   648    649   
   649    650   /* Opcode: String8 * * P3
   650    651   **
   651    652   ** P3 points to a nul terminated UTF-8 string that is P1 character long
   652    653   ** (not counting the nul terminator). This opcode is transformed
................................................................................
   654    655   */
   655    656   case OP_String8: {         /* same as TK_STRING */
   656    657     assert( pOp->p3!=0 );
   657    658     pOp->opcode = OP_String;
   658    659     pOp->p1 = strlen(pOp->p3);
   659    660   
   660    661   #ifndef SQLITE_OMIT_UTF16
   661         -  if( ENC(db)!=SQLITE_UTF8 ){
          662  +  if( encoding!=SQLITE_UTF8 ){
   662    663       pTos++;
   663    664       sqlite3VdbeMemSetStr(pTos, pOp->p3, -1, SQLITE_UTF8, SQLITE_STATIC);
   664         -    if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pTos, ENC(db)) ) goto no_mem;
          665  +    if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pTos, encoding) ) goto no_mem;
   665    666       if( SQLITE_OK!=sqlite3VdbeMemDynamicify(pTos) ) goto no_mem;
   666    667       pTos->flags &= ~(MEM_Dyn);
   667    668       pTos->flags |= MEM_Static;
   668    669       if( pOp->p3type==P3_DYNAMIC ){
   669    670         sqliteFree(pOp->p3);
   670    671       }
   671    672       pOp->p3type = P3_DYNAMIC;
................................................................................
   683    684   */
   684    685   case OP_String: {
   685    686     pTos++;
   686    687     assert( pOp->p3!=0 );
   687    688     pTos->flags = MEM_Str|MEM_Static|MEM_Term;
   688    689     pTos->z = pOp->p3;
   689    690     pTos->n = pOp->p1;
   690         -  pTos->enc = ENC(db);
          691  +  pTos->enc = encoding;
   691    692     break;
   692    693   }
   693    694   
   694    695   /* Opcode: Null * * *
   695    696   **
   696    697   ** Push a NULL onto the stack.
   697    698   */
................................................................................
   887    888   
   888    889     /* Make sure the results of the current row are \000 terminated
   889    890     ** and have an assigned type.  The results are deephemeralized as
   890    891     ** as side effect.
   891    892     */
   892    893     for(; pMem<=pTos; pMem++ ){
   893    894       sqlite3VdbeMemNulTerminate(pMem);
   894         -    storeTypeInfo(pMem, ENC(db));
          895  +    storeTypeInfo(pMem, encoding);
   895    896     }
   896    897   
   897    898     /* Set up the statement structure so that it will pop the current
   898    899     ** results from the stack when the statement returns.
   899    900     */
   900    901     p->resOnStack = 1;
   901    902     p->nCallback++;
................................................................................
   929    930     nByte = 0;
   930    931     for(i=0; i<nField; i++, pTerm++){
   931    932       assert( pOp->p2==0 || (pTerm->flags&MEM_Str) );
   932    933       if( pTerm->flags&MEM_Null ){
   933    934         nByte = -1;
   934    935         break;
   935    936       }
   936         -    Stringify(pTerm, ENC(db));
          937  +    Stringify(pTerm, encoding);
   937    938       nByte += pTerm->n;
   938    939     }
   939    940   
   940    941     if( nByte<0 ){
   941    942       /* If nByte is less than zero, then there is a NULL value on the stack.
   942    943       ** In this case just pop the values off the stack (if required) and
   943    944       ** push on a NULL.
................................................................................
   968    969       if( pOp->p2==0 ){
   969    970         popStack(&pTos, nField);
   970    971       }
   971    972       pTos++;
   972    973       pTos->n = j;
   973    974       pTos->flags = MEM_Str|MEM_Dyn|MEM_Term;
   974    975       pTos->xDel = 0;
   975         -    pTos->enc = ENC(db);
          976  +    pTos->enc = encoding;
   976    977       pTos->z = zNew;
   977    978     }
   978    979     break;
   979    980   }
   980    981   
   981    982   /* Opcode: Add * * *
   982    983   **
................................................................................
  1142   1143   
  1143   1144     apVal = p->apArg;
  1144   1145     assert( apVal || n==0 );
  1145   1146   
  1146   1147     pArg = &pTos[1-n];
  1147   1148     for(i=0; i<n; i++, pArg++){
  1148   1149       apVal[i] = pArg;
  1149         -    storeTypeInfo(pArg, ENC(db));
         1150  +    storeTypeInfo(pArg, encoding);
  1150   1151     }
  1151   1152   
  1152   1153     assert( pOp->p3type==P3_FUNCDEF || pOp->p3type==P3_VDBEFUNC );
  1153   1154     if( pOp->p3type==P3_FUNCDEF ){
  1154   1155       ctx.pFunc = (FuncDef*)pOp->p3;
  1155   1156       ctx.pVdbeFunc = 0;
  1156   1157     }else{
................................................................................
  1180   1181     if( ctx.pVdbeFunc ){
  1181   1182       sqlite3VdbeDeleteAuxData(ctx.pVdbeFunc, pOp->p1);
  1182   1183       pOp->p3 = (char *)ctx.pVdbeFunc;
  1183   1184       pOp->p3type = P3_VDBEFUNC;
  1184   1185     }
  1185   1186   
  1186   1187     /* Copy the result of the function to the top of the stack */
  1187         -  sqlite3VdbeChangeEncoding(&ctx.s, ENC(db));
         1188  +  sqlite3VdbeChangeEncoding(&ctx.s, encoding);
  1188   1189     pTos++;
  1189   1190     pTos->flags = 0;
  1190   1191     sqlite3VdbeMemMove(pTos, &ctx.s);
  1191   1192   
  1192   1193     /* If the function returned an error, throw an exception */
  1193   1194     if( ctx.isError ){
  1194   1195       if( !(pTos->flags&MEM_Str) ){
  1195   1196         sqlite3SetString(&p->zErrMsg, "user function error", (char*)0);
  1196   1197       }else{
  1197   1198         sqlite3SetString(&p->zErrMsg, sqlite3_value_text(pTos), (char*)0);
  1198         -      sqlite3VdbeChangeEncoding(pTos, ENC(db));
         1199  +      sqlite3VdbeChangeEncoding(pTos, encoding);
  1199   1200       }
  1200   1201       rc = SQLITE_ERROR;
  1201   1202     }
  1202   1203     break;
  1203   1204   }
  1204   1205   
  1205   1206   /* Opcode: BitAnd * * *
................................................................................
  1284   1285   ** convert it into the least integer that is greater than or equal to its
  1285   1286   ** current value if P1==0, or to the least integer that is strictly
  1286   1287   ** greater than its current value if P1==1.
  1287   1288   */
  1288   1289   case OP_ForceInt: {            /* no-push */
  1289   1290     i64 v;
  1290   1291     assert( pTos>=p->aStack );
  1291         -  applyAffinity(pTos, SQLITE_AFF_NUMERIC, ENC(db));
         1292  +  applyAffinity(pTos, SQLITE_AFF_NUMERIC, encoding);
  1292   1293     if( (pTos->flags & (MEM_Int|MEM_Real))==0 ){
  1293   1294       Release(pTos);
  1294   1295       pTos--;
  1295   1296       pc = pOp->p2 - 1;
  1296   1297       break;
  1297   1298     }
  1298   1299     if( pTos->flags & MEM_Int ){
................................................................................
  1319   1320   **
  1320   1321   ** If the top of the stack is not an integer and P2 is not zero and
  1321   1322   ** P1 is 1, then the stack is popped.  In all other cases, the depth
  1322   1323   ** of the stack is unchanged.
  1323   1324   */
  1324   1325   case OP_MustBeInt: {            /* no-push */
  1325   1326     assert( pTos>=p->aStack );
  1326         -  applyAffinity(pTos, SQLITE_AFF_NUMERIC, ENC(db));
         1327  +  applyAffinity(pTos, SQLITE_AFF_NUMERIC, encoding);
  1327   1328     if( (pTos->flags & MEM_Int)==0 ){
  1328   1329       if( pOp->p2==0 ){
  1329   1330         rc = SQLITE_MISMATCH;
  1330   1331         goto abort_due_to_error;
  1331   1332       }else{
  1332   1333         if( pOp->p1 ) popStack(&pTos, 1);
  1333   1334         pc = pOp->p2 - 1;
................................................................................
  1367   1368   ** A NULL value is not changed by this routine.  It remains NULL.
  1368   1369   */
  1369   1370   case OP_ToText: {                  /* same as TK_TO_TEXT, no-push */
  1370   1371     assert( pTos>=p->aStack );
  1371   1372     if( pTos->flags & MEM_Null ) break;
  1372   1373     assert( MEM_Str==(MEM_Blob>>3) );
  1373   1374     pTos->flags |= (pTos->flags&MEM_Blob)>>3;
  1374         -  applyAffinity(pTos, SQLITE_AFF_TEXT, ENC(db));
         1375  +  applyAffinity(pTos, SQLITE_AFF_TEXT, encoding);
  1375   1376     assert( pTos->flags & MEM_Str );
  1376   1377     pTos->flags &= ~(MEM_Int|MEM_Real|MEM_Blob);
  1377   1378     break;
  1378   1379   }
  1379   1380   
  1380   1381   /* Opcode: ToBlob * * *
  1381   1382   **
................................................................................
  1386   1387   **
  1387   1388   ** A NULL value is not changed by this routine.  It remains NULL.
  1388   1389   */
  1389   1390   case OP_ToBlob: {                  /* same as TK_TO_BLOB, no-push */
  1390   1391     assert( pTos>=p->aStack );
  1391   1392     if( pTos->flags & MEM_Null ) break;
  1392   1393     if( (pTos->flags & MEM_Blob)==0 ){
  1393         -    applyAffinity(pTos, SQLITE_AFF_TEXT, ENC(db));
         1394  +    applyAffinity(pTos, SQLITE_AFF_TEXT, encoding);
  1394   1395       assert( pTos->flags & MEM_Str );
  1395   1396       pTos->flags |= MEM_Blob;
  1396   1397     }
  1397   1398     pTos->flags &= ~(MEM_Int|MEM_Real|MEM_Str);
  1398   1399     break;
  1399   1400   }
  1400   1401   
................................................................................
  1567   1568         }
  1568   1569         break;
  1569   1570       }
  1570   1571     }
  1571   1572   
  1572   1573     affinity = pOp->p1 & 0xFF;
  1573   1574     if( affinity ){
  1574         -    applyAffinity(pNos, affinity, ENC(db));
  1575         -    applyAffinity(pTos, affinity, ENC(db));
         1575  +    applyAffinity(pNos, affinity, encoding);
         1576  +    applyAffinity(pTos, affinity, encoding);
  1576   1577     }
  1577   1578   
  1578   1579     assert( pOp->p3type==P3_COLLSEQ || pOp->p3==0 );
  1579   1580     res = sqlite3MemCompare(pNos, pTos, (CollSeq*)pOp->p3);
  1580   1581     switch( pOp->opcode ){
  1581   1582       case OP_Eq:    res = res==0;     break;
  1582   1583       case OP_Ne:    res = res!=0;     break;
................................................................................
  2068   2069         rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, pC->isIndex,&sMem);
  2069   2070         if( rc!=SQLITE_OK ){
  2070   2071           goto op_column_out;
  2071   2072         }
  2072   2073         zData = sMem.z;
  2073   2074       }
  2074   2075       sqlite3VdbeSerialGet((u8*)zData, aType[p2], pTos);
  2075         -    pTos->enc = ENC(db);
         2076  +    pTos->enc = encoding;
  2076   2077     }else{
  2077   2078       if( pOp->p3type==P3_MEM ){
  2078   2079         sqlite3VdbeMemShallowCopy(pTos, (Mem *)(pOp->p3), MEM_Static);
  2079   2080       }else{
  2080   2081         pTos->flags = MEM_Null;
  2081   2082       }
  2082   2083     }
................................................................................
  2192   2193     file_format = p->minWriteFileFormat;
  2193   2194   
  2194   2195     /* Loop through the elements that will make up the record to figure
  2195   2196     ** out how much space is required for the new record.
  2196   2197     */
  2197   2198     for(pRec=pData0; pRec<=pTos; pRec++){
  2198   2199       if( zAffinity ){
  2199         -      applyAffinity(pRec, zAffinity[pRec-pData0], ENC(db));
         2200  +      applyAffinity(pRec, zAffinity[pRec-pData0], encoding);
  2200   2201       }
  2201   2202       if( pRec->flags&MEM_Null ){
  2202   2203         containsNull = 1;
  2203   2204       }
  2204   2205       serial_type = sqlite3VdbeSerialType(pRec, file_format);
  2205   2206       nData += sqlite3VdbeSerialTypeLen(serial_type);
  2206   2207       nHdr += sqlite3VarintLen(serial_type);
................................................................................
  2803   2804         if( rc!=SQLITE_OK ){
  2804   2805           goto abort_due_to_error;
  2805   2806         }
  2806   2807         pC->lastRowid = pTos->i;
  2807   2808         pC->rowidIsValid = res==0;
  2808   2809       }else{
  2809   2810         assert( pTos->flags & MEM_Blob );
  2810         -      /* Stringify(pTos, ENC(db)); */
         2811  +      /* Stringify(pTos, encoding); */
  2811   2812         rc = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
  2812   2813         if( rc!=SQLITE_OK ){
  2813   2814           goto abort_due_to_error;
  2814   2815         }
  2815   2816         pC->rowidIsValid = 0;
  2816   2817       }
  2817   2818       pC->deferredMoveto = 0;
................................................................................
  2908   2909     Cursor *pC;
  2909   2910     assert( pTos>=p->aStack );
  2910   2911     assert( i>=0 && i<p->nCursor );
  2911   2912     assert( p->apCsr[i]!=0 );
  2912   2913     if( (pC = p->apCsr[i])->pCursor!=0 ){
  2913   2914       int res, rx;
  2914   2915       assert( pC->isTable==0 );
  2915         -    Stringify(pTos, ENC(db));
         2916  +    Stringify(pTos, encoding);
  2916   2917       rx = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
  2917   2918       alreadyExists = rx==SQLITE_OK && res==0;
  2918   2919       pC->deferredMoveto = 0;
  2919   2920       pC->cacheStatus = CACHE_STALE;
  2920   2921     }
  2921   2922     if( pOp->opcode==OP_Found ){
  2922   2923       if( alreadyExists ) pc = pOp->p2 - 1;
................................................................................
  2975   2976       char *zKey;    /* The value of K */
  2976   2977       int nKey;      /* Number of bytes in K */
  2977   2978       int len;       /* Number of bytes in K without the rowid at the end */
  2978   2979       int szRowid;   /* Size of the rowid column at the end of zKey */
  2979   2980   
  2980   2981       /* Make sure K is a string and make zKey point to K
  2981   2982       */
  2982         -    Stringify(pNos, ENC(db));
         2983  +    Stringify(pNos, encoding);
  2983   2984       zKey = pNos->z;
  2984   2985       nKey = pNos->n;
  2985   2986   
  2986   2987       szRowid = sqlite3VdbeIdxRowidLen(nKey, (u8*)zKey);
  2987   2988       len = nKey-szRowid;
  2988   2989   
  2989   2990       /* Search for an entry in P1 where all but the last four bytes match K.
................................................................................
  3806   3807     assert( i>=0 && i<p->nCursor );
  3807   3808     assert( p->apCsr[i]!=0 );
  3808   3809     assert( pTos>=p->aStack );
  3809   3810     if( (pC = p->apCsr[i])->pCursor!=0 ){
  3810   3811       int res, rc;
  3811   3812    
  3812   3813       assert( pTos->flags & MEM_Blob );  /* Created using OP_Make*Key */
  3813         -    Stringify(pTos, ENC(db));
         3814  +    Stringify(pTos, encoding);
  3814   3815       assert( pC->deferredMoveto==0 );
  3815   3816       *pC->pIncrKey = pOp->p3!=0;
  3816   3817       assert( pOp->p3==0 || pOp->opcode!=OP_IdxGT );
  3817   3818       rc = sqlite3VdbeIdxKeyCompare(pC, pTos->n, (u8*)pTos->z, &res);
  3818   3819       *pC->pIncrKey = 0;
  3819   3820       if( rc!=SQLITE_OK ){
  3820   3821         break;
................................................................................
  4135   4136     }else{
  4136   4137       pTos->z = z;
  4137   4138       pTos->n = strlen(z);
  4138   4139       pTos->flags = MEM_Str | MEM_Dyn | MEM_Term;
  4139   4140       pTos->xDel = 0;
  4140   4141     }
  4141   4142     pTos->enc = SQLITE_UTF8;
  4142         -  sqlite3VdbeChangeEncoding(pTos, ENC(db));
         4143  +  sqlite3VdbeChangeEncoding(pTos, encoding);
  4143   4144     sqliteFree(aRoot);
  4144   4145     break;
  4145   4146   }
  4146   4147   #endif /* SQLITE_OMIT_INTEGRITY_CHECK */
  4147   4148   
  4148   4149   /* Opcode: FifoWrite * * *
  4149   4150   **
................................................................................
  4411   4412     assert( n>=0 );
  4412   4413     pRec = &pTos[1-n];
  4413   4414     assert( pRec>=p->aStack );
  4414   4415     apVal = p->apArg;
  4415   4416     assert( apVal || n==0 );
  4416   4417     for(i=0; i<n; i++, pRec++){
  4417   4418       apVal[i] = pRec;
  4418         -    storeTypeInfo(pRec, ENC(db));
         4419  +    storeTypeInfo(pRec, encoding);
  4419   4420     }
  4420   4421     ctx.pFunc = (FuncDef*)pOp->p3;
  4421   4422     assert( pOp->p1>=0 && pOp->p1<p->nMem );
  4422   4423     ctx.pMem = pMem = &p->aMem[pOp->p1];
  4423   4424     pMem->n++;
  4424   4425     ctx.isError = 0;
  4425   4426     ctx.pColl = 0;
................................................................................
  4556   4557       ** of the program.  It is only here for testing and debugging.
  4557   4558       ** On the other hand, it does burn CPU cycles every time through
  4558   4559       ** the evaluator loop.  So we can leave it out when NDEBUG is defined.
  4559   4560       */
  4560   4561   #ifndef NDEBUG
  4561   4562       /* Sanity checking on the top element of the stack */
  4562   4563       if( pTos>=p->aStack ){
  4563         -      sqlite3VdbeMemSanity(pTos, ENC(db));
         4564  +      sqlite3VdbeMemSanity(pTos, encoding);
  4564   4565       }
  4565   4566       assert( pc>=-1 && pc<p->nOp );
  4566   4567   #ifdef SQLITE_DEBUG
  4567   4568       /* Code for tracing the vdbe stack. */
  4568   4569       if( p->trace && pTos>=p->aStack ){
  4569   4570         int i;
  4570   4571         fprintf(p->trace, "Stack:");