/ Check-in [7e30fd6a]
Login

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

Overview
Comment:Floating point and 64-bit integer constants store in the virtual machine opcodes in binary, not as text. Performance improvement. Ticket #2733. (CVS 4507)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 7e30fd6a09899842c922b044714dc66796e545d4
User & Date: drh 2007-10-23 15:39:45
Context
2007-10-23
15:51
Make sure the _LARGEFILE_SOURCE macro occurs before any system includes. Ticket #2739. (CVS 4508) check-in: 36465aeb user: drh tags: trunk
15:39
Floating point and 64-bit integer constants store in the virtual machine opcodes in binary, not as text. Performance improvement. Ticket #2733. (CVS 4507) check-in: 7e30fd6a user: drh tags: trunk
14:55
Fix limit assertions in vdbe.c. Ticket #2740. (CVS 4506) check-in: 27f846d0 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/expr.c.

     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   ** This file contains routines used for analyzing expressions and
    13     13   ** for generating VDBE code that evaluates expressions in SQLite.
    14     14   **
    15         -** $Id: expr.c,v 1.313 2007/09/18 15:55:07 drh Exp $
           15  +** $Id: expr.c,v 1.314 2007/10/23 15:39:45 drh Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   #include <ctype.h>
    19     19   
    20     20   /*
    21     21   ** Return the 'affinity' of the expression pExpr if any.
    22     22   **
................................................................................
  1675   1675     if( testAddr ){
  1676   1676       sqlite3VdbeJumpHere(v, testAddr);
  1677   1677     }
  1678   1678   
  1679   1679     return;
  1680   1680   }
  1681   1681   #endif /* SQLITE_OMIT_SUBQUERY */
         1682  +
         1683  +/*
         1684  +** Duplicate an 8-byte value
         1685  +*/
         1686  +static char *dup8bytes(Vdbe *v, const char *in){
         1687  +  char *out = sqlite3DbMallocRaw(sqlite3VdbeDb(v), 8);
         1688  +  if( out ){
         1689  +    memcpy(out, in, 8);
         1690  +  }
         1691  +  return out;
         1692  +}
         1693  +
         1694  +/*
         1695  +** Generate an instruction that will put the floating point
         1696  +** value described by z[0..n-1] on the stack.
         1697  +*/
         1698  +static void codeReal(Vdbe *v, const char *z, int n, int negateFlag){
         1699  +  assert( z || v==0 || sqlite3VdbeDb(v)->mallocFailed );
         1700  +  if( z ){
         1701  +    double value;
         1702  +    char *zV;
         1703  +    sqlite3AtoF(z, &value);
         1704  +    if( negateFlag ) value = -value;
         1705  +    zV = dup8bytes(v, (char*)&value);
         1706  +    sqlite3VdbeOp3(v, OP_Real, 0, 0, zV, P3_REAL);
         1707  +  }
         1708  +}
         1709  +
  1682   1710   
  1683   1711   /*
  1684   1712   ** Generate an instruction that will put the integer describe by
  1685   1713   ** text z[0..n-1] on the stack.
  1686   1714   */
  1687         -static void codeInteger(Vdbe *v, const char *z, int n){
         1715  +static void codeInteger(Vdbe *v, const char *z, int n, int negateFlag){
  1688   1716     assert( z || v==0 || sqlite3VdbeDb(v)->mallocFailed );
  1689   1717     if( z ){
  1690   1718       int i;
  1691   1719       if( sqlite3GetInt32(z, &i) ){
         1720  +      if( negateFlag ) i = -i;
  1692   1721         sqlite3VdbeAddOp(v, OP_Integer, i, 0);
  1693         -    }else if( sqlite3FitsIn64Bits(z) ){
  1694         -      sqlite3VdbeOp3(v, OP_Int64, 0, 0, z, n);
         1722  +    }else if( sqlite3FitsIn64Bits(z, negateFlag) ){
         1723  +      i64 value;
         1724  +      char *zV;
         1725  +      sqlite3Atoi64(z, &value);
         1726  +      if( negateFlag ) value = -value;
         1727  +      zV = dup8bytes(v, (char*)&value);
         1728  +      sqlite3VdbeOp3(v, OP_Int64, 0, 0, zV, P3_INT64);
  1695   1729       }else{
  1696         -      sqlite3VdbeOp3(v, OP_Real, 0, 0, z, n);
         1730  +      codeReal(v, z, n, negateFlag);
  1697   1731       }
  1698   1732     }
  1699   1733   }
  1700   1734   
  1701   1735   
  1702   1736   /*
  1703   1737   ** Generate code that will extract the iColumn-th column from
................................................................................
  1765   1799           sqlite3VdbeAddOp(v, OP_Dup, pParse->ckOffset-pExpr->iColumn-1, 1);
  1766   1800         }else{
  1767   1801           sqlite3ExprCodeGetColumn(v, pExpr->pTab, pExpr->iColumn, pExpr->iTable);
  1768   1802         }
  1769   1803         break;
  1770   1804       }
  1771   1805       case TK_INTEGER: {
  1772         -      codeInteger(v, (char*)pExpr->token.z, pExpr->token.n);
         1806  +      codeInteger(v, (char*)pExpr->token.z, pExpr->token.n, 0);
  1773   1807         break;
  1774   1808       }
  1775         -    case TK_FLOAT:
         1809  +    case TK_FLOAT: {
         1810  +      codeReal(v, (char*)pExpr->token.z, pExpr->token.n, 0);
         1811  +      break;
         1812  +    }
  1776   1813       case TK_STRING: {
  1777         -      assert( TK_FLOAT==OP_Real );
  1778         -      assert( TK_STRING==OP_String8 );
  1779   1814         sqlite3DequoteExpr(pParse->db, pExpr);
  1780         -      sqlite3VdbeOp3(v, op, 0, 0, (char*)pExpr->token.z, pExpr->token.n);
         1815  +      sqlite3VdbeOp3(v,OP_String8, 0, 0, (char*)pExpr->token.z, pExpr->token.n);
  1781   1816         break;
  1782   1817       }
  1783   1818       case TK_NULL: {
  1784   1819         sqlite3VdbeAddOp(v, OP_Null, 0, 0);
  1785   1820         break;
  1786   1821       }
  1787   1822   #ifndef SQLITE_OMIT_BLOB_LITERAL
................................................................................
  1875   1910         break;
  1876   1911       }
  1877   1912       case TK_UMINUS: {
  1878   1913         Expr *pLeft = pExpr->pLeft;
  1879   1914         assert( pLeft );
  1880   1915         if( pLeft->op==TK_FLOAT || pLeft->op==TK_INTEGER ){
  1881   1916           Token *p = &pLeft->token;
  1882         -        char *z = sqlite3MPrintf(pParse->db, "-%.*s", p->n, p->z);
  1883   1917           if( pLeft->op==TK_FLOAT ){
  1884         -          sqlite3VdbeOp3(v, OP_Real, 0, 0, z, p->n+1);
         1918  +          codeReal(v, (char*)p->z, p->n, 1);
  1885   1919           }else{
  1886         -          codeInteger(v, z, p->n+1);
         1920  +          codeInteger(v, (char*)p->z, p->n, 1);
  1887   1921           }
  1888         -        sqlite3_free(z);
  1889   1922           break;
  1890   1923         }
  1891   1924         /* Fall through into TK_NOT */
  1892   1925       }
  1893   1926       case TK_BITNOT:
  1894   1927       case TK_NOT: {
  1895   1928         assert( TK_BITNOT==OP_BitNot );

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.614 2007/10/04 18:11:16 danielk1977 Exp $
           14  +** @(#) $Id: sqliteInt.h,v 1.615 2007/10/23 15:39:45 drh Exp $
    15     15   */
    16     16   #ifndef _SQLITEINT_H_
    17     17   #define _SQLITEINT_H_
    18     18   #include "sqliteLimit.h"
    19     19   
    20     20   /*
    21     21   ** For testing purposes, the various size limit constants are really
................................................................................
  1779   1779   int sqlite3FixSelect(DbFixer*, Select*);
  1780   1780   int sqlite3FixExpr(DbFixer*, Expr*);
  1781   1781   int sqlite3FixExprList(DbFixer*, ExprList*);
  1782   1782   int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
  1783   1783   int sqlite3AtoF(const char *z, double*);
  1784   1784   char *sqlite3_snprintf(int,char*,const char*,...);
  1785   1785   int sqlite3GetInt32(const char *, int*);
  1786         -int sqlite3FitsIn64Bits(const char *);
         1786  +int sqlite3FitsIn64Bits(const char *, int);
  1787   1787   int sqlite3Utf16ByteLen(const void *pData, int nChar);
  1788   1788   int sqlite3Utf8CharLen(const char *pData, int nByte);
  1789   1789   int sqlite3Utf8Read(const u8*, const u8*, const u8**);
  1790   1790   int sqlite3PutVarint(unsigned char *, u64);
  1791   1791   int sqlite3GetVarint(const unsigned char *, u64 *);
  1792   1792   int sqlite3GetVarint32(const unsigned char *, u32 *);
  1793   1793   int sqlite3VarintLen(u64 v);

Changes to src/test1.c.

     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** Code for testing all sorts of SQLite interfaces.  This code
    13     13   ** is not included in the SQLite library.  It is used for automated
    14     14   ** testing of the SQLite library.
    15     15   **
    16         -** $Id: test1.c,v 1.278 2007/10/23 14:49:59 drh Exp $
           16  +** $Id: test1.c,v 1.279 2007/10/23 15:39:45 drh Exp $
    17     17   */
    18     18   #include "sqliteInt.h"
    19     19   #include "tcl.h"
    20     20   #include <stdlib.h>
    21     21   #include <string.h>
    22     22   
    23     23   /*
................................................................................
  1127   1127   }
  1128   1128   
  1129   1129   /*
  1130   1130   ** If zNum represents an integer that will fit in 64-bits, then set
  1131   1131   ** *pValue to that integer and return true.  Otherwise return false.
  1132   1132   */
  1133   1133   static int sqlite3GetInt64(const char *zNum, i64 *pValue){
  1134         -  if( sqlite3FitsIn64Bits(zNum) ){
         1134  +  if( sqlite3FitsIn64Bits(zNum, 0) ){
  1135   1135       sqlite3Atoi64(zNum, pValue);
  1136   1136       return 1;
  1137   1137     }
  1138   1138     return 0;
  1139   1139   }
  1140   1140   
  1141   1141   /*

Changes to src/util.c.

    10     10   **
    11     11   *************************************************************************
    12     12   ** Utility functions used throughout sqlite.
    13     13   **
    14     14   ** This file contains functions for allocating memory, comparing
    15     15   ** strings, and stuff like that.
    16     16   **
    17         -** $Id: util.c,v 1.212 2007/09/01 10:01:13 danielk1977 Exp $
           17  +** $Id: util.c,v 1.213 2007/10/23 15:39:45 drh Exp $
    18     18   */
    19     19   #include "sqliteInt.h"
    20     20   #include <stdarg.h>
    21     21   #include <ctype.h>
    22     22   
    23     23   
    24     24   /*
................................................................................
   372    372   ** 64-bit signed integer, return TRUE.  Otherwise return FALSE.
   373    373   **
   374    374   ** This routine returns FALSE for the string -9223372036854775808 even that
   375    375   ** that number will, in theory fit in a 64-bit integer.  Positive
   376    376   ** 9223373036854775808 will not fit in 64 bits.  So it seems safer to return
   377    377   ** false.
   378    378   */
   379         -int sqlite3FitsIn64Bits(const char *zNum){
          379  +int sqlite3FitsIn64Bits(const char *zNum, int negFlag){
   380    380     int i, c;
   381    381     int neg = 0;
   382    382     if( *zNum=='-' ){
   383    383       neg = 1;
   384    384       zNum++;
   385    385     }else if( *zNum=='+' ){
   386    386       zNum++;
   387    387     }
          388  +  if( negFlag ) neg = 1-neg;
   388    389     while( *zNum=='0' ){
   389    390       zNum++;   /* Skip leading zeros.  Ticket #2454 */
   390    391     }
   391    392     for(i=0; (c=zNum[i])>='0' && c<='9'; i++){}
   392    393     if( i<19 ){
   393    394       /* Guaranteed to fit if less than 19 digits */
   394    395       return 1;

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.652 2007/10/23 14:55:07 drh Exp $
           46  +** $Id: vdbe.c,v 1.653 2007/10/23 15:39:45 drh Exp $
    47     47   */
    48     48   #include "sqliteInt.h"
    49     49   #include <ctype.h>
    50     50   #include "vdbeInt.h"
    51     51   
    52     52   /*
    53     53   ** The following global variable is incremented every time a cursor
................................................................................
   701    701     pTos->flags = MEM_Int;
   702    702     pTos->u.i = pOp->p1;
   703    703     break;
   704    704   }
   705    705   
   706    706   /* Opcode: Int64 * * P3
   707    707   **
   708         -** P3 is a string representation of an integer.  Convert that integer
   709         -** to a 64-bit value and push it onto the stack.
          708  +** P3 is a pointer to a 64-bit integer value.
          709  +** Push  that value onto  the stack.
   710    710   */
   711    711   case OP_Int64: {
   712    712     pTos++;
   713    713     assert( pOp->p3!=0 );
   714         -  pTos->flags = MEM_Str|MEM_Static|MEM_Term;
   715         -  pTos->z = pOp->p3;
   716         -  pTos->n = strlen(pTos->z);
   717         -  pTos->enc = SQLITE_UTF8;
   718         -  pTos->u.i = sqlite3VdbeIntValue(pTos);
   719         -  pTos->flags |= MEM_Int;
          714  +  pTos->flags = MEM_Int;
          715  +  memcpy(&pTos->u.i, pOp->p3, 8);
   720    716     break;
   721    717   }
   722    718   
   723    719   /* Opcode: Real * * P3
   724    720   **
   725         -** The string value P3 is converted to a real and pushed on to the stack.
          721  +** P3 is a pointer to a 64-bit floating point value.  Push that value
          722  +** onto the stack.
   726    723   */
   727    724   case OP_Real: {            /* same as TK_FLOAT, */
   728    725     pTos++;
   729         -  pTos->flags = MEM_Str|MEM_Static|MEM_Term;
   730         -  pTos->z = pOp->p3;
   731         -  pTos->n = strlen(pTos->z);
   732         -  pTos->enc = SQLITE_UTF8;
   733         -  pTos->r = sqlite3VdbeRealValue(pTos);
   734         -  pTos->flags |= MEM_Real;
   735         -  sqlite3VdbeChangeEncoding(pTos, encoding);
          726  +  pTos->flags = MEM_Real;
          727  +  memcpy(&pTos->r, pOp->p3, 8);
   736    728     break;
   737    729   }
   738    730   
   739    731   /* Opcode: String8 * * P3
   740    732   **
   741    733   ** P3 points to a nul terminated UTF-8 string. This opcode is transformed 
   742    734   ** into an OP_String before it is executed for the first time.

Changes to src/vdbe.h.

    11     11   *************************************************************************
    12     12   ** Header file for the Virtual DataBase Engine (VDBE)
    13     13   **
    14     14   ** This header defines the interface to the virtual database engine
    15     15   ** or VDBE.  The VDBE implements an abstract machine that runs a
    16     16   ** simple program to access and modify the underlying database.
    17     17   **
    18         -** $Id: vdbe.h,v 1.113 2007/08/30 01:19:59 drh Exp $
           18  +** $Id: vdbe.h,v 1.114 2007/10/23 15:39:45 drh Exp $
    19     19   */
    20     20   #ifndef _SQLITE_VDBE_H_
    21     21   #define _SQLITE_VDBE_H_
    22     22   #include <stdio.h>
    23     23   
    24     24   /*
    25     25   ** A single VDBE is an opaque structure named "Vdbe".  Only routines
................................................................................
    68     68   #define P3_FUNCDEF  (-5)  /* P3 is a pointer to a FuncDef structure */
    69     69   #define P3_KEYINFO  (-6)  /* P3 is a pointer to a KeyInfo structure */
    70     70   #define P3_VDBEFUNC (-7)  /* P3 is a pointer to a VdbeFunc structure */
    71     71   #define P3_MEM      (-8)  /* P3 is a pointer to a Mem*    structure */
    72     72   #define P3_TRANSIENT (-9) /* P3 is a pointer to a transient string */
    73     73   #define P3_VTAB     (-10) /* P3 is a pointer to an sqlite3_vtab structure */
    74     74   #define P3_MPRINTF  (-11) /* P3 is a string obtained from sqlite3_mprintf() */
           75  +#define P3_REAL     (-12) /* P3 is a 64-bit floating point value */
           76  +#define P3_INT64    (-13) /* P3 is a 64-bit signed integer */
    75     77   
    76     78   /* When adding a P3 argument using P3_KEYINFO, a copy of the KeyInfo structure
    77     79   ** is made.  That copy is freed when the Vdbe is finalized.  But if the
    78     80   ** argument is P3_KEYINFO_HANDOFF, the passed in pointer is used.  It still
    79     81   ** gets freed when the Vdbe is finalized so it still should be obtained
    80     82   ** from a single sqliteMalloc().  But no copy is made and the calling
    81     83   ** function should *not* try to free the KeyInfo.

Changes to src/vdbeaux.c.

   428    428   
   429    429   /*
   430    430   ** Delete a P3 value if necessary.
   431    431   */
   432    432   static void freeP3(int p3type, void *p3){
   433    433     if( p3 ){
   434    434       switch( p3type ){
          435  +      case P3_REAL:
          436  +      case P3_INT64:
          437  +      case P3_MPRINTF:
   435    438         case P3_DYNAMIC:
   436    439         case P3_KEYINFO:
   437    440         case P3_KEYINFO_HANDOFF: {
   438         -        sqlite3_free(p3);
   439         -        break;
   440         -      }
   441         -      case P3_MPRINTF: {
   442    441           sqlite3_free(p3);
   443    442           break;
   444    443         }
   445    444         case P3_VDBEFUNC: {
   446    445           VdbeFunc *pVdbeFunc = (VdbeFunc *)p3;
   447    446           freeEphemeralFunction(pVdbeFunc->pFunc);
   448    447           sqlite3VdbeDeleteAuxData(pVdbeFunc, 0);
................................................................................
   626    625         break;
   627    626       }
   628    627       case P3_FUNCDEF: {
   629    628         FuncDef *pDef = (FuncDef*)pOp->p3;
   630    629         sqlite3_snprintf(nTemp, zTemp, "%s(%d)", pDef->zName, pDef->nArg);
   631    630         zP3 = zTemp;
   632    631         break;
          632  +    }
          633  +    case P3_INT64: {
          634  +      sqlite3_snprintf(nTemp, zTemp, "%lld", *(sqlite3_int64*)pOp->p3);
          635  +      zP3 = zTemp;
          636  +      break;
          637  +    }
          638  +    case P3_REAL: {
          639  +      sqlite3_snprintf(nTemp, zTemp, "%.16g", *(double*)pOp->p3);
          640  +      zP3 = zTemp;
          641  +      break;
   633    642       }
   634    643   #ifndef SQLITE_OMIT_VIRTUALTABLE
   635    644       case P3_VTAB: {
   636    645         sqlite3_vtab *pVtab = (sqlite3_vtab*)pOp->p3;
   637    646         sqlite3_snprintf(nTemp, zTemp, "vtab:%p:%p", pVtab, pVtab->pModule);
   638    647         zP3 = zTemp;
   639    648         break;

Changes to test/alter.test.

     7      7   #    May you find forgiveness for yourself and forgive others.
     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #*************************************************************************
    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this script is testing the ALTER TABLE statement.
    13     13   #
    14         -# $Id: alter.test,v 1.26 2007/10/09 08:29:32 danielk1977 Exp $
           14  +# $Id: alter.test,v 1.27 2007/10/23 15:39:46 drh Exp $
    15     15   #
    16     16   
    17     17   set testdir [file dirname $argv0]
    18     18   source $testdir/tester.tcl
    19     19   
    20     20   # If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
    21     21   ifcapable !altertable {
................................................................................
   634    634   # that includes a COLLATE clause.
   635    635   #
   636    636   do_test alter-7.1 {
   637    637     execsql {
   638    638       CREATE TABLE t1(a TEXT COLLATE BINARY);
   639    639       ALTER TABLE t1 ADD COLUMN b INTEGER COLLATE NOCASE;
   640    640       INSERT INTO t1 VALUES(1,'-2');
   641         -    INSERT INTO t1 VALUES(5.4e-8,'5.4e-8');
          641  +    INSERT INTO t1 VALUES(5.4e-08,'5.4e-08');
   642    642       SELECT typeof(a), a, typeof(b), b FROM t1;
   643    643     }
   644         -} {text 1 integer -2 text 5.4e-8 real 5.4e-08}
          644  +} {text 1 integer -2 text 5.4e-08 real 5.4e-08}
   645    645   
   646    646   # Make sure that when a column is added by ALTER TABLE ADD COLUMN and has
   647    647   # a default value that the default value is used by aggregate functions.
   648    648   #
   649    649   do_test alter-8.1 {
   650    650     execsql {
   651    651       CREATE TABLE t2(a INTEGER);