aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/global.c5
-rw-r--r--src/main.c5
-rw-r--r--src/sqlite.h.in13
-rw-r--r--src/sqliteInt.h2
-rw-r--r--src/test1.c1
-rw-r--r--src/test_malloc.c30
-rw-r--r--src/where.c6
7 files changed, 61 insertions, 1 deletions
diff --git a/src/global.c b/src/global.c
index 7de066825..dc86e1e08 100644
--- a/src/global.c
+++ b/src/global.c
@@ -133,6 +133,10 @@ const unsigned char sqlite3CtypeMap[256] = {
# define SQLITE_USE_URI 0
#endif
+#ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN
+# define SQLITE_ALLOW_COVERING_INDEX_SCAN 1
+#endif
+
/*
** The following singleton contains the global configuration for
** the SQLite library.
@@ -142,6 +146,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
1, /* bCoreMutex */
SQLITE_THREADSAFE==1, /* bFullMutex */
SQLITE_USE_URI, /* bOpenUri */
+ SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */
0x7ffffffe, /* mxStrlen */
128, /* szLookaside */
500, /* nLookaside */
diff --git a/src/main.c b/src/main.c
index 08e62a97e..466dee551 100644
--- a/src/main.c
+++ b/src/main.c
@@ -475,6 +475,11 @@ int sqlite3_config(int op, ...){
break;
}
+ case SQLITE_CONFIG_COVERING_INDEX_SCAN: {
+ sqlite3GlobalConfig.bUseCis = va_arg(ap, int);
+ break;
+ }
+
default: {
rc = SQLITE_ERROR;
break;
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index 3660c442d..cab0b8418 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -1563,6 +1563,18 @@ struct sqlite3_mem_methods {
** disabled. The default value may be changed by compiling with the
** [SQLITE_USE_URI] symbol defined.
**
+** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
+** <dd> This option taks a single integer argument which is interpreted as
+** a boolean in order to enable or disable the use of covering indices for
+** full table scans in the query optimizer. The default setting is determined
+** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
+** if that compile-time option is omitted.
+** The ability to disable the use of covering indices for full table scans
+** is because some incorrectly coded legacy applications might malfunction
+** malfunction when the optimization is enabled. Providing the ability to
+** disable the optimization allows the older, buggy application code to work
+** without change even with newer versions of SQLite.
+**
** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]]
** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE
** <dd> These options are obsolete and should not be used by new code.
@@ -1588,6 +1600,7 @@ struct sqlite3_mem_methods {
#define SQLITE_CONFIG_URI 17 /* int */
#define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */
#define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */
+#define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */
/*
** CAPI3REF: Database Connection Configuration Options
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index b0135f44c..e20e79774 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -968,6 +968,7 @@ struct sqlite3 {
#define SQLITE_FactorOutConst 0x08 /* Disable factoring out constants */
#define SQLITE_IdxRealAsInt 0x10 /* Store REAL as INT in indices */
#define SQLITE_DistinctOpt 0x20 /* DISTINCT using indexes */
+#define SQLITE_CoverIdxScan 0x40 /* Disable covering index scans */
#define SQLITE_OptMask 0xff /* Mask of all disablable opts */
/*
@@ -2461,6 +2462,7 @@ struct Sqlite3Config {
int bCoreMutex; /* True to enable core mutexing */
int bFullMutex; /* True to enable full mutexing */
int bOpenUri; /* True to interpret filenames as URIs */
+ int bUseCis; /* Use covering indices for full-scans */
int mxStrlen; /* Maximum string length */
int szLookaside; /* Default lookaside buffer size */
int nLookaside; /* Default lookaside buffer count */
diff --git a/src/test1.c b/src/test1.c
index 55e2df553..0b9b812e8 100644
--- a/src/test1.c
+++ b/src/test1.c
@@ -5940,6 +5940,7 @@ static int optimization_control(
{ "factor-constants", SQLITE_FactorOutConst },
{ "real-as-int", SQLITE_IdxRealAsInt },
{ "distinct-opt", SQLITE_DistinctOpt },
+ { "cover-idx-scan", SQLITE_CoverIdxScan },
};
if( objc!=4 ){
diff --git a/src/test_malloc.c b/src/test_malloc.c
index f52894d9e..e1420de64 100644
--- a/src/test_malloc.c
+++ b/src/test_malloc.c
@@ -1198,6 +1198,35 @@ static int test_config_uri(
}
/*
+** Usage: sqlite3_config_cis BOOLEAN
+**
+** Enables or disables the use of the covering-index scan optimization.
+** SQLITE_CONFIG_COVERING_INDEX_SCAN.
+*/
+static int test_config_cis(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ int rc;
+ int bUseCis;
+
+ if( objc!=2 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
+ return TCL_ERROR;
+ }
+ if( Tcl_GetBooleanFromObj(interp, objv[1], &bUseCis) ){
+ return TCL_ERROR;
+ }
+
+ rc = sqlite3_config(SQLITE_CONFIG_COVERING_INDEX_SCAN, bUseCis);
+ Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
+
+ return TCL_OK;
+}
+
+/*
** Usage: sqlite3_dump_memsys3 FILENAME
** sqlite3_dump_memsys5 FILENAME
**
@@ -1447,6 +1476,7 @@ int Sqlitetest_malloc_Init(Tcl_Interp *interp){
{ "sqlite3_config_lookaside", test_config_lookaside ,0 },
{ "sqlite3_config_error", test_config_error ,0 },
{ "sqlite3_config_uri", test_config_uri ,0 },
+ { "sqlite3_config_cis", test_config_cis ,0 },
{ "sqlite3_db_config_lookaside",test_db_config_lookaside ,0 },
{ "sqlite3_dump_memsys3", test_dump_memsys3 ,3 },
{ "sqlite3_dump_memsys5", test_dump_memsys3 ,5 },
diff --git a/src/where.c b/src/where.c
index c28386e29..9922d2b3d 100644
--- a/src/where.c
+++ b/src/where.c
@@ -3201,12 +3201,16 @@ static void bestBtreeIndex(
*/
if( wsFlags==WHERE_IDX_ONLY
&& (pWC->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
+ && sqlite3GlobalConfig.bUseCis
+#ifndef SQLITE_OMIT_BUILTIN_TEST
+ && (pParse->db->flags & SQLITE_CoverIdxScan)==0
+#endif
){
/* This index is not useful for indexing, but it is a covering index.
** A full-scan of the index might be a little faster than a full-scan
** of the table, so give this case a cost slightly less than a table
** scan. */
- cost = aiRowEst[0]*3;
+ cost = aiRowEst[0]*3 + pProbe->nColumn;
wsFlags |= WHERE_COVER_SCAN|WHERE_COLUMN_RANGE;
}else if( (wsFlags & WHERE_NOT_FULLSCAN)==0 ){
/* The cost of a full table scan is a number of move operations equal