SQLite

Check-in [7e8156129d]
Login

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

Overview
Comment:More test cases and bug fixes with CSE. (CVS 4948)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 7e8156129d6d240fe046bbc4ea269ebe1657e2a1
User & Date: drh 2008-04-01 03:27:39.000
Context
2008-04-01
05:07
Fix the CSE mechanism so that it takes into account column affinity changes that might be imposed by comparison operators. (CVS 4949) (check-in: 91cc646e2b user: drh tags: trunk)
03:27
More test cases and bug fixes with CSE. (CVS 4948) (check-in: 7e8156129d user: drh tags: trunk)
02:45
Add a configure option for using gcov (makes things easier for versions of GCC that fail to build otherwise) (CVS 4947) (check-in: 7d1e797162 user: mlcreech tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/build.c.
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
**     CREATE INDEX
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**
** $Id: build.c,v 1.477 2008/03/25 17:23:33 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called when a new SQL statement is beginning to
** be parsed.  Initialize the pParse structure as needed.







|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
**     CREATE INDEX
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**
** $Id: build.c,v 1.478 2008/04/01 03:27:39 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called when a new SQL statement is beginning to
** be parsed.  Initialize the pParse structure as needed.
201
202
203
204
205
206
207

208
209
210
211
212
213
214
  /* Get the VDBE program ready for execution
  */
  if( v && pParse->nErr==0 && !db->mallocFailed ){
#ifdef SQLITE_DEBUG
    FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0;
    sqlite3VdbeTrace(v, trace);
#endif

    sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem+3,
                         pParse->nTab+3, pParse->explain);
    pParse->rc = SQLITE_DONE;
    pParse->colNamesSet = 0;
  }else if( pParse->rc==SQLITE_OK ){
    pParse->rc = SQLITE_ERROR;
  }







>







201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
  /* Get the VDBE program ready for execution
  */
  if( v && pParse->nErr==0 && !db->mallocFailed ){
#ifdef SQLITE_DEBUG
    FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0;
    sqlite3VdbeTrace(v, trace);
#endif
    assert( pParse->disableColCache==0 );  /* Disables and re-enables match */
    sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem+3,
                         pParse->nTab+3, pParse->explain);
    pParse->rc = SQLITE_DONE;
    pParse->colNamesSet = 0;
  }else if( pParse->rc==SQLITE_OK ){
    pParse->rc = SQLITE_ERROR;
  }
Changes to src/expr.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.360 2008/04/01 01:42:41 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** Return the 'affinity' of the expression pExpr if any.
**







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.361 2008/04/01 03:27:39 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** Return the 'affinity' of the expression pExpr if any.
**
218
219
220
221
222
223
224




225
226
227
228
229
230
231
  CollSeq *p4;

  p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight);
  p5 = binaryCompareP5(pLeft, pRight, jumpIfNull);
  addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1,
                           (void*)p4, P4_COLLSEQ);
  sqlite3VdbeChangeP5(pParse->pVdbe, p5);




  return addr;
}

/*
** Construct a new expression node and return a pointer to it.  Memory
** for this node is obtained from sqlite3_malloc().  The calling function
** is responsible for making sure the node eventually gets freed.







>
>
>
>







218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
  CollSeq *p4;

  p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight);
  p5 = binaryCompareP5(pLeft, pRight, jumpIfNull);
  addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1,
                           (void*)p4, P4_COLLSEQ);
  sqlite3VdbeChangeP5(pParse->pVdbe, p5);
  if( p5 & SQLITE_AFF_MASK ){
    sqlite3ExprExpireColumnCacheLines(pParse, in1, in1);
    sqlite3ExprExpireColumnCacheLines(pParse, in2, in2);
  }
  return addr;
}

/*
** Construct a new expression node and return a pointer to it.  Memory
** for this node is obtained from sqlite3_malloc().  The calling function
** is responsible for making sure the node eventually gets freed.
1943
1944
1945
1946
1947
1948
1949
1950
1951

1952
1953
1954
1955
1956
1957
1958
  }
  if( pParse->disableColCache==0 ){
    i = pParse->iColCache;
    pParse->aColCache[i].iTable = iTable;
    pParse->aColCache[i].iColumn = iColumn;
    pParse->aColCache[i].iReg = iReg;
    i++;
    if( i>ArraySize(pParse->aColCache) ) i = 0;
    if( i>pParse->nColCache ) pParse->nColCache = i;

  }
  return iReg;
}

/*
** Disable (+1) or enable (-1) the adding of new column cache entries.
*/







|

>







1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
  }
  if( pParse->disableColCache==0 ){
    i = pParse->iColCache;
    pParse->aColCache[i].iTable = iTable;
    pParse->aColCache[i].iColumn = iColumn;
    pParse->aColCache[i].iReg = iReg;
    i++;
    if( i>=ArraySize(pParse->aColCache) ) i = 0;
    if( i>pParse->nColCache ) pParse->nColCache = i;
    pParse->iColCache = i;
  }
  return iReg;
}

/*
** Disable (+1) or enable (-1) the adding of new column cache entries.
*/
2042
2043
2044
2045
2046
2047
2048

2049

2050
2051
2052
2053
2054
2055
2056
** Return the register that the value ends up in.
*/
int sqlite3ExprWritableRegister(Parse *pParse, int iCurrent, int iTarget){
  assert( pParse->pVdbe!=0 );
  if( !usedAsColumnCache(pParse, iCurrent, iCurrent) ){
    return iCurrent;
  }

  sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, iCurrent, iTarget);

  sqlite3ExprExpireColumnCacheLines(pParse, iTarget, iTarget);
  return iTarget;
}

/*
** Generate code into the current Vdbe to evaluate the given
** expression.  Attempt to store the results in register "target".







>
|
>







2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
** Return the register that the value ends up in.
*/
int sqlite3ExprWritableRegister(Parse *pParse, int iCurrent, int iTarget){
  assert( pParse->pVdbe!=0 );
  if( !usedAsColumnCache(pParse, iCurrent, iCurrent) ){
    return iCurrent;
  }
  if( iCurrent!=iTarget ){
    sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, iCurrent, iTarget);
  }
  sqlite3ExprExpireColumnCacheLines(pParse, iTarget, iTarget);
  return iTarget;
}

/*
** Generate code into the current Vdbe to evaluate the given
** expression.  Attempt to store the results in register "target".
Changes to src/sqliteInt.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.684 2008/04/01 01:42:41 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Include the configuration header output by 'configure' if it was run
** (otherwise we get an empty default).













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.685 2008/04/01 03:27:39 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Include the configuration header output by 'configure' if it was run
** (otherwise we get an empty default).
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471

1472
1473
1474
1475
1476
1477
1478
  int nTab;            /* Number of previously allocated VDBE cursors */
  int nMem;            /* Number of memory cells used so far */
  int nSet;            /* Number of sets used so far */
  int ckBase;          /* Base register of data during check constraints */
  int disableColCache; /* True to disable adding to column cache */
  int nColCache;       /* Number of entries in the column cache */
  int iColCache;       /* Next entry of the cache to replace */
  struct {
    int iTable;           /* Table cursor number */
    int iColumn;          /* Table column number */

    int iReg;             /* Register holding value of this column */
  } aColCache[10];     /* One for each valid column cache entry */
  u32 writeMask;       /* Start a write transaction on these databases */
  u32 cookieMask;      /* Bitmask of schema verified databases */
  int cookieGoto;      /* Address of OP_Goto to cookie verifier subroutine */
  int cookieValue[SQLITE_MAX_ATTACHED+2];  /* Values of cookies to verify */
#ifndef SQLITE_OMIT_SHARED_CACHE







|


>







1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
  int nTab;            /* Number of previously allocated VDBE cursors */
  int nMem;            /* Number of memory cells used so far */
  int nSet;            /* Number of sets used so far */
  int ckBase;          /* Base register of data during check constraints */
  int disableColCache; /* True to disable adding to column cache */
  int nColCache;       /* Number of entries in the column cache */
  int iColCache;       /* Next entry of the cache to replace */
  struct yColCache {
    int iTable;           /* Table cursor number */
    int iColumn;          /* Table column number */
    char aff;             /* Affinity.  Or 0 if none specified */
    int iReg;             /* Register holding value of this column */
  } aColCache[10];     /* One for each valid column cache entry */
  u32 writeMask;       /* Start a write transaction on these databases */
  u32 cookieMask;      /* Bitmask of schema verified databases */
  int cookieGoto;      /* Address of OP_Goto to cookie verifier subroutine */
  int cookieValue[SQLITE_MAX_ATTACHED+2];  /* Values of cookies to verify */
#ifndef SQLITE_OMIT_SHARED_CACHE
Changes to test/cse.test.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#
#***********************************************************************
#
# Test cases designed to exercise and verify the logic for
# factoring constant expressions out of loops and for
# common subexpression eliminations.
#
# $Id: cse.test,v 1.1 2008/04/01 01:42:41 drh Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test cse-1.1 {
  execsql {







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#
#***********************************************************************
#
# Test cases designed to exercise and verify the logic for
# factoring constant expressions out of loops and for
# common subexpression eliminations.
#
# $Id: cse.test,v 1.2 2008/04/01 03:27:39 drh Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test cse-1.1 {
  execsql {
61
62
63
64
65
66
67


68

































69
} {1 -1 -2 0 1 0 2 1 1 1 2 -2 -3 0 1 0 4 4 1 2}
do_test cse-1.8 {
  execsql {
    SELECT a, a%a, a==a, a!=a, a<a, a<=a, a IS NULL, a NOT NULL, a FROM t1
  }
} {1 0 1 0 0 1 0 1 1 2 0 1 0 0 1 0 1 2}





































finish_test







>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
} {1 -1 -2 0 1 0 2 1 1 1 2 -2 -3 0 1 0 4 4 1 2}
do_test cse-1.8 {
  execsql {
    SELECT a, a%a, a==a, a!=a, a<a, a<=a, a IS NULL, a NOT NULL, a FROM t1
  }
} {1 0 1 0 0 1 0 1 1 2 0 1 0 0 1 0 1 2}

# Overflow the column cache.  Create queries involving more and more
# columns until the cache overflows.  Verify correct operation throughout.
#
do_test cse-2.1 {
  execsql {
    CREATE TABLE t2(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,
                    a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,
                    a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,
                    a30,a31,a32,a33,a34,a35,a36,a37,a38,a39,
                    a40,a41,a42,a43,a44,a45,a46,a47,a48,a49);
    INSERT INTO t2 VALUES(0,1,2,3,4,5,6,7,8,9,
                    10,11,12,13,14,15,16,17,18,19,
                    20,21,22,23,24,25,26,27,28,29,
                    30,31,32,33,34,35,36,37,38,39,
                    40,41,42,43,44,45,46,47,48,49);
    SELECT * FROM t2;
  }
} {0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49}

for {set i 1} {$i<100} {incr i} {
  set n [expr {int(rand()*44)+5}]
  set colset {}
  set answer {}
  for {set j 0} {$j<$n} {incr j} {
    set r [expr {$j+int(rand()*5)}]
    if {$r>49} {set r [expr {99-$r}]}
    lappend colset a$j a$r 
    lappend answer $j $r
  }
  set sql "SELECT [join $colset ,] FROM t2"
  do_test cse-2.2.$i {
    # explain $::sql
    execsql $::sql
  } $answer
}

finish_test