/ Check-in [ea9b747e]
Login

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

Overview
Comment:Convert the "~" and "NOT" operators to be two-address instructions. Ticket #3541. (CVS 6028)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:ea9b747efb22fd3f679c3ef86ed51986c5ad9436
User & Date: drh 2008-12-15 15:27:52
Context
2008-12-15
16:33
Add test cases that verify evaluation of randomly generated SQL expressions. (CVS 6029) check-in: 4685ffcc user: drh tags: trunk
15:27
Convert the "~" and "NOT" operators to be two-address instructions. Ticket #3541. (CVS 6028) check-in: ea9b747e user: drh tags: trunk
2008-12-14
14:45
Add the example from #3359 to the test suite. (CVS 6027) check-in: 84f8417c user: danielk1977 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.407 2008/12/10 21:19:57 drh Exp $
           15  +** $Id: expr.c,v 1.408 2008/12/15 15:27:52 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   **
................................................................................
  1971   1971       }
  1972   1972       case TK_BITNOT:
  1973   1973       case TK_NOT: {
  1974   1974         assert( TK_BITNOT==OP_BitNot );
  1975   1975         assert( TK_NOT==OP_Not );
  1976   1976         testcase( op==TK_BITNOT );
  1977   1977         testcase( op==TK_NOT );
  1978         -      inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
  1979         -      testcase( inReg==target );
  1980         -      testcase( usedAsColumnCache(pParse, inReg, inReg) );
  1981         -      inReg = sqlite3ExprWritableRegister(pParse, inReg, target);
  1982         -      sqlite3VdbeAddOp1(v, op, inReg);
         1978  +      r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
         1979  +      testcase( regFree1==0 );
         1980  +      inReg = target;
         1981  +      sqlite3VdbeAddOp2(v, op, r1, inReg);
  1983   1982         break;
  1984   1983       }
  1985   1984       case TK_ISNULL:
  1986   1985       case TK_NOTNULL: {
  1987   1986         int addr;
  1988   1987         assert( TK_ISNULL==OP_IsNull );
  1989   1988         assert( TK_NOTNULL==OP_NotNull );

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.802 2008/12/12 17:56:16 drh Exp $
           46  +** $Id: vdbe.c,v 1.803 2008/12/15 15:27:52 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
................................................................................
  1806   1806     }else{
  1807   1807       pOut->u.i = v1;
  1808   1808       MemSetTypeFlag(pOut, MEM_Int);
  1809   1809     }
  1810   1810     break;
  1811   1811   }
  1812   1812   
  1813         -/* Opcode: Not P1 * * * *
         1813  +/* Opcode: Not P1 P2 * * *
  1814   1814   **
  1815         -** Interpret the value in register P1 as a boolean value.  Replace it
  1816         -** with its complement.  If the value in register P1 is NULL its value
  1817         -** is unchanged.
         1815  +** Interpret the value in register P1 as a boolean value.  Store the
         1816  +** boolean complement in register P2.  If the value in register P1 is 
         1817  +** NULL, then a NULL is stored in P2.
  1818   1818   */
  1819   1819   case OP_Not: {                /* same as TK_NOT, in1 */
  1820         -  if( pIn1->flags & MEM_Null ) break;  /* Do nothing to NULLs */
  1821         -  sqlite3VdbeMemIntegerify(pIn1);
  1822         -  pIn1->u.i = !pIn1->u.i;
  1823         -  assert( pIn1->flags&MEM_Int );
         1820  +  pOut = &p->aMem[pOp->p2];
         1821  +  if( pIn1->flags & MEM_Null ){
         1822  +    sqlite3VdbeMemSetNull(pOut);
         1823  +  }else{
         1824  +    sqlite3VdbeMemSetInt64(pOut, !sqlite3VdbeIntValue(pIn1));
         1825  +  }
  1824   1826     break;
  1825   1827   }
  1826   1828   
  1827         -/* Opcode: BitNot P1 * * * *
         1829  +/* Opcode: BitNot P1 P2 * * *
  1828   1830   **
  1829         -** Interpret the content of register P1 as an integer.  Replace it
  1830         -** with its ones-complement.  If the value is originally NULL, leave
  1831         -** it unchanged.
         1831  +** Interpret the content of register P1 as an integer.  Store the
         1832  +** ones-complement of the P1 value into register P2.  If P1 holds
         1833  +** a NULL then store a NULL in P2.
  1832   1834   */
  1833   1835   case OP_BitNot: {             /* same as TK_BITNOT, in1 */
  1834         -  if( pIn1->flags & MEM_Null ) break;  /* Do nothing to NULLs */
  1835         -  sqlite3VdbeMemIntegerify(pIn1);
  1836         -  pIn1->u.i = ~pIn1->u.i;
  1837         -  assert( pIn1->flags&MEM_Int );
         1836  +  pOut = &p->aMem[pOp->p2];
         1837  +  if( pIn1->flags & MEM_Null ){
         1838  +    sqlite3VdbeMemSetNull(pOut);
         1839  +  }else{
         1840  +    sqlite3VdbeMemSetInt64(pOut, ~sqlite3VdbeIntValue(pIn1));
         1841  +  }
  1838   1842     break;
  1839   1843   }
  1840   1844   
  1841   1845   /* Opcode: If P1 P2 P3 * *
  1842   1846   **
  1843   1847   ** Jump to P2 if the value in register P1 is true.  The value is
  1844   1848   ** is considered true if it is numeric and non-zero.  If the value

Added test/tkt3541.test.

            1  +# 2008 December 16
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +# This file implements regression tests for SQLite library.
           12  +#
           13  +# This file is a verification that the bugs identified in ticket
           14  +# #3541 have been fixed.
           15  +#
           16  +# $Id: tkt3541.test,v 1.1 2008/12/15 15:27:52 drh Exp $
           17  +
           18  +set testdir [file dirname $argv0]
           19  +source $testdir/tester.tcl
           20  +
           21  +do_test tkt3541-1.1 {
           22  +  db eval {
           23  +    CREATE TABLE t1(x);
           24  +    INSERT INTO t1 VALUES(123);
           25  +    SELECT CASE ~max(x) WHEN min(x) THEN 1 ELSE max(x) END FROM t1;
           26  +  }
           27  +} {123}
           28  +do_test tkt3541-1.2 {
           29  +  db eval {
           30  +    SELECT CASE NOT max(x) WHEN min(x) THEN 1 ELSE max(x) END FROM t1;
           31  +  }
           32  +} {123}
           33  +
           34  +
           35  +finish_test