/ Check-in [7e0aa964]
Login

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

Overview
Comment:Coverage improvements for where.c. (CVS 3764)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:7e0aa964129612e2bad6fa45139d124f19cacd48
User & Date: danielk1977 2007-03-30 14:56:34
Original User & Date: danielk1977 2007-03-30 14:56:35
Context
2007-03-30
14:56
Coverage improvements for where.c. (CVS 3765) check-in: df64894b user: danielk1977 tags: trunk
14:56
Coverage improvements for where.c. (CVS 3764) check-in: 7e0aa964 user: danielk1977 tags: trunk
14:46
Tease apart the two phases of pager commit. (CVS 3763) check-in: e5f17078 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/test8.c.

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
...
623
624
625
626
627
628
629

630
631
632
633


634
635
636
637
638
639




640
641
642
643
644
645
646
647
648
649
650

651
652
653
654
655
656
657
...
713
714
715
716
717
718
719


720
721
722
723
724
725
726
727
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the virtual table interfaces.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test8.c,v 1.44 2007/01/03 23:37:29 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>

#ifndef SQLITE_OMIT_VIRTUALTABLE

typedef struct echo_vtab echo_vtab;
typedef struct echo_cursor echo_cursor;

/*
** The test module defined in this file uses two global Tcl variables to
** commicate with test-scripts:
**
**     $::echo_module
**     $::echo_module_sync_fail
**     $::echo_module_begin_fail

**
** The variable ::echo_module is a list. Each time one of the following
** methods is called, one or more elements are appended to the list.
** This is used for automated testing of virtual table modules.
**
** The ::echo_module_sync_fail variable is set by test scripts and read
** by code in this file. If it is set to the name of a real table in the
................................................................................
  int ii;
  char *zQuery = 0;
  char *zNew;
  int nArg = 0;
  const char *zSep = "WHERE";
  echo_vtab *pVtab = (echo_vtab *)tab;
  sqlite3_stmt *pStmt = 0;


  int nRow;
  int useIdx = 0;
  int rc = SQLITE_OK;



  /* Determine the number of rows in the table and store this value in local
  ** variable nRow. The 'estimated-cost' of the scan will be the number of
  ** rows in the table for a linear scan, or the log (base 2) of the 
  ** number of rows if the proposed scan uses an index.  
  */




  zQuery = sqlite3_mprintf("SELECT count(*) FROM %Q", pVtab->zTableName);
  rc = sqlite3_prepare(pVtab->db, zQuery, -1, &pStmt, 0);
  sqlite3_free(zQuery);
  if( rc!=SQLITE_OK ){
    return rc;
  }
  sqlite3_step(pStmt);
  nRow = sqlite3_column_int(pStmt, 0);
  rc = sqlite3_finalize(pStmt);
  if( rc!=SQLITE_OK ){
    return rc;

  }

  zQuery = sqlite3_mprintf("SELECT rowid, * FROM %Q", pVtab->zTableName);
  for(ii=0; ii<pIdxInfo->nConstraint; ii++){
    const struct sqlite3_index_constraint *pConstraint;
    struct sqlite3_index_constraint_usage *pUsage;
    int iCol;
................................................................................

  appendToEchoModule(pVtab->interp, "xBestIndex");;
  appendToEchoModule(pVtab->interp, zQuery);

  pIdxInfo->idxNum = hashString(zQuery);
  pIdxInfo->idxStr = zQuery;
  pIdxInfo->needToFreeIdxStr = 1;


  if( useIdx ){
    /* Approximation of log2(nRow). */
    for( ii=0; ii<(sizeof(int)*8); ii++ ){
      if( nRow & (1<<ii) ){
        pIdxInfo->estimatedCost = (double)ii;
      }
    }
  } else {







|













|





>







 







>




>
>






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







 







>
>
|







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
...
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
...
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the virtual table interfaces.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test8.c,v 1.45 2007/03/30 14:56:35 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>

#ifndef SQLITE_OMIT_VIRTUALTABLE

typedef struct echo_vtab echo_vtab;
typedef struct echo_cursor echo_cursor;

/*
** The test module defined in this file uses four global Tcl variables to
** commicate with test-scripts:
**
**     $::echo_module
**     $::echo_module_sync_fail
**     $::echo_module_begin_fail
**     $::echo_module_cost
**
** The variable ::echo_module is a list. Each time one of the following
** methods is called, one or more elements are appended to the list.
** This is used for automated testing of virtual table modules.
**
** The ::echo_module_sync_fail variable is set by test scripts and read
** by code in this file. If it is set to the name of a real table in the
................................................................................
  int ii;
  char *zQuery = 0;
  char *zNew;
  int nArg = 0;
  const char *zSep = "WHERE";
  echo_vtab *pVtab = (echo_vtab *)tab;
  sqlite3_stmt *pStmt = 0;
  Tcl_Interp *interp = pVtab->interp;

  int nRow;
  int useIdx = 0;
  int rc = SQLITE_OK;
  int useCost = 0;
  double cost;

  /* Determine the number of rows in the table and store this value in local
  ** variable nRow. The 'estimated-cost' of the scan will be the number of
  ** rows in the table for a linear scan, or the log (base 2) of the 
  ** number of rows if the proposed scan uses an index.  
  */
  if( Tcl_GetVar(interp, "echo_module_cost", TCL_GLOBAL_ONLY) ){
    cost = atof(Tcl_GetVar(interp, "echo_module_cost", TCL_GLOBAL_ONLY));
    useCost = 1;
  } else {
    zQuery = sqlite3_mprintf("SELECT count(*) FROM %Q", pVtab->zTableName);
    rc = sqlite3_prepare(pVtab->db, zQuery, -1, &pStmt, 0);
    sqlite3_free(zQuery);
    if( rc!=SQLITE_OK ){
      return rc;
    }
    sqlite3_step(pStmt);
    nRow = sqlite3_column_int(pStmt, 0);
    rc = sqlite3_finalize(pStmt);
    if( rc!=SQLITE_OK ){
      return rc;
    }
  }

  zQuery = sqlite3_mprintf("SELECT rowid, * FROM %Q", pVtab->zTableName);
  for(ii=0; ii<pIdxInfo->nConstraint; ii++){
    const struct sqlite3_index_constraint *pConstraint;
    struct sqlite3_index_constraint_usage *pUsage;
    int iCol;
................................................................................

  appendToEchoModule(pVtab->interp, "xBestIndex");;
  appendToEchoModule(pVtab->interp, zQuery);

  pIdxInfo->idxNum = hashString(zQuery);
  pIdxInfo->idxStr = zQuery;
  pIdxInfo->needToFreeIdxStr = 1;
  if (useCost) {
    pIdxInfo->estimatedCost = cost;
  } else if( useIdx ){
    /* Approximation of log2(nRow). */
    for( ii=0; ii<(sizeof(int)*8); ii++ ){
      if( nRow & (1<<ii) ){
        pIdxInfo->estimatedCost = (double)ii;
      }
    }
  } else {

Changes to src/where.c.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
....
1828
1829
1830
1831
1832
1833
1834




1835
1836
1837
1838
1839
1840
1841
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.  This module is reponsible for
** generating the code that loops through a table looking for applicable
** rows.  Indices are selected and used to speed the search when doing
** so is applicable.  Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
**
** $Id: where.c,v 1.243 2007/03/30 09:13:14 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** The number of bits in a Bitmask.  "BMS" means "BitMask Size".
*/
#define BMS  (sizeof(Bitmask)*8)
................................................................................
static void whereInfoFree(WhereInfo *pWInfo){
  if( pWInfo ){
    int i;
    for(i=0; i<pWInfo->nLevel; i++){
      sqlite3_index_info *pInfo = pWInfo->a[i].pIdxInfo;
      if( pInfo ){
        if( pInfo->needToFreeIdxStr ){




          sqlite3_free(pInfo->idxStr);
        }
        sqliteFree(pInfo);
      }
    }
    sqliteFree(pWInfo);
  }







|







 







>
>
>
>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
....
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.  This module is reponsible for
** generating the code that loops through a table looking for applicable
** rows.  Indices are selected and used to speed the search when doing
** so is applicable.  Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
**
** $Id: where.c,v 1.244 2007/03/30 14:56:35 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** The number of bits in a Bitmask.  "BMS" means "BitMask Size".
*/
#define BMS  (sizeof(Bitmask)*8)
................................................................................
static void whereInfoFree(WhereInfo *pWInfo){
  if( pWInfo ){
    int i;
    for(i=0; i<pWInfo->nLevel; i++){
      sqlite3_index_info *pInfo = pWInfo->a[i].pIdxInfo;
      if( pInfo ){
        if( pInfo->needToFreeIdxStr ){
          /* Coverage: Don't think this can be reached. By the time this
          ** function is called, the index-strings have been passed
          ** to the vdbe layer for deletion.
          */
          sqlite3_free(pInfo->idxStr);
        }
        sqliteFree(pInfo);
      }
    }
    sqliteFree(pWInfo);
  }

Changes to test/misc7.test.

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
...
160
161
162
163
164
165
166
167
168
169




170
171
172
173
174
175
176

177




178
































179
#    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.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# $Id: misc7.test,v 1.5 2007/03/30 13:01:32 drh Exp $

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

do_test misc7-1 {
  c_misuse_test
} {}
................................................................................
    SELECT * 
    FROM (SELECT name+1 AS one FROM sqlite_master LIMIT 1 OFFSET 1) 
    WHERE one LIKE 'hello%';
  }
} {}

#--------------------------------------------------------------------
# Improve reported coverage by running some debugging code:
#
ifcapable vtab {




  do_test misc7-10 {
    register_echo_module [sqlite3_connection_pointer db]
    execsql {
      CREATE VIRTUAL TABLE t1 USING echo(abc);
      SELECT a FROM t1 WHERE a = 1 ORDER BY b;
    }
  } {1}

}





































finish_test







|







 







|


>
>
>
>







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

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
...
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
#    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.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# $Id: misc7.test,v 1.6 2007/03/30 14:56:35 danielk1977 Exp $

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

do_test misc7-1 {
  c_misuse_test
} {}
................................................................................
    SELECT * 
    FROM (SELECT name+1 AS one FROM sqlite_master LIMIT 1 OFFSET 1) 
    WHERE one LIKE 'hello%';
  }
} {}

#--------------------------------------------------------------------
# Improve coverage for vtab code.
#
ifcapable vtab {
  # Run some debug code to improve reported coverage
  #

  # set sqlite_where_trace 1
  do_test misc7-10 {
    register_echo_module [sqlite3_connection_pointer db]
    execsql {
      CREATE VIRTUAL TABLE t1 USING echo(abc);
      SELECT a FROM t1 WHERE a = 1 ORDER BY b;
    }
  } {1}
  set sqlite_where_trace 0

  # Specify an ORDER BY clause that cannot be indexed.
  do_test misc7-11 {
    execsql {
      SELECT t1.a, t2.a FROM t1, t1 AS t2 ORDER BY 2 LIMIT 1;
    }
  } {1 1}

  # The whole point of this is to test an error code other than
  # SQLITE_NOMEM from the vtab xBestIndex callback.
  #
  do_ioerr_test misc7-12 -tclprep {
    sqlite3 db2 test.db
    register_echo_module [sqlite3_connection_pointer db2]
    db2 eval {
      CREATE TABLE abc(a PRIMARY KEY, b, c);
      INSERT INTO abc VALUES(1, 2, 3);
      CREATE VIRTUAL TABLE t1 USING echo(abc);
    }
    db2 close
  } -tclbody {
    register_echo_module [sqlite3_connection_pointer db]
    execsql {SELECT * FROM t1 WHERE a = 1;}
  } 

  # The case where the virtual table module returns a very large number
  # as the cost of a scan (greater than SQLITE_BIG_DOUBLE in the code).
  #
  do_test misc7-13 {
    sqlite3 db test.db
    register_echo_module [sqlite3_connection_pointer db]
    set ::echo_module_cost 2.0e+99
    execsql {SELECT * FROM t1 WHERE a = 1;}
  } {1 2 3}
  unset ::echo_module_cost
}


finish_test

Changes to test/vtab1.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is creating and dropping virtual tables.
#
# $Id: vtab1.test,v 1.41 2007/03/02 08:12:23 danielk1977 Exp $

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

ifcapable !vtab||!schema_pragmas {
  finish_test
  return
................................................................................
    CREATE INDEX i1 ON t2(d);
  }

  db close
  sqlite3 db test.db
  register_echo_module [sqlite3_connection_pointer db]

  set echo_module ""
  execsql {
    SELECT * FROM et1, et2 WHERE et2.d = 2;
  }
} [list \
  1 red green 2 hearts diamonds  \
  2 blue black 2 hearts diamonds \
]
do_test vtab1-5-7 {
  filter $echo_module
} [list \
  xFilter {SELECT rowid, * FROM 't2' WHERE d = ?} \
  xFilter {SELECT rowid, * FROM 't1'}             \
]

execsql {
  DROP TABLE t1;







|







 







|








|







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is creating and dropping virtual tables.
#
# $Id: vtab1.test,v 1.42 2007/03/30 14:56:35 danielk1977 Exp $

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

ifcapable !vtab||!schema_pragmas {
  finish_test
  return
................................................................................
    CREATE INDEX i1 ON t2(d);
  }

  db close
  sqlite3 db test.db
  register_echo_module [sqlite3_connection_pointer db]

  set ::echo_module ""
  execsql {
    SELECT * FROM et1, et2 WHERE et2.d = 2;
  }
} [list \
  1 red green 2 hearts diamonds  \
  2 blue black 2 hearts diamonds \
]
do_test vtab1-5-7 {
  filter $::echo_module
} [list \
  xFilter {SELECT rowid, * FROM 't2' WHERE d = ?} \
  xFilter {SELECT rowid, * FROM 't1'}             \
]

execsql {
  DROP TABLE t1;