1
0
mirror of https://github.com/sqlite/sqlite.git synced 2026-10-23 21:49:02 +03:00

New extension ext/misc/optname.c provides the canonical mapping between

optimization bitmaps and optimization names.  This gives a single point
of edit when there are changes.  Used by the CLI, by testfixture, and by
TH3.

FossilOrigin-Name: 135ed9e2cc9bd37c3e158a488e37f4ce14ffeca44ff12e31f25a6686a2622ca1
This commit is contained in:
drh
2026-10-10 17:40:46 +00:00
parent 31e3b6ff45
commit 4c7729af99
8 changed files with 223 additions and 155 deletions

View File

@@ -1594,6 +1594,7 @@ TESTEXT = \
$(TOP)\ext\misc\mmapwarm.c \
$(TOP)\ext\misc\nextchar.c \
$(TOP)\ext\misc\normalize.c \
$(TOP)\ext\misc\optname.c \
$(TOP)\ext\misc\prefixes.c \
$(TOP)\ext\misc\qpvtab.c \
$(TOP)\ext\misc\randomjson.c \

112
ext/misc/optname.c Normal file
View File

@@ -0,0 +1,112 @@
/*
** 2026-10-10
**
** 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.
**
*************************************************************************
**
** The sqlite3_test_control() interface with SQLITE_TESTCTRL_OPTIMIZATIONS
** and SQLITE_TESTCTRL_GETOPT are used to enable and/or disable various
** optimizations within SQLite. Optimizations are identified by a bitmask.
** This file contains external code that will map symbolic names into
** bitmask values, and bitmask values into symbolic names.
**
** This code is not part of the SQLite core because we don't want to use
** code space to store all the symbolic names.
*/
#include "sqlite3.h"
/*
** Convert an optimization number (as recorded in sqliteInt.h) into
** a mask for that optimization.
*/
#define OPT_MASK(N) ((1ull)<<((N)-1))
/*
** This is the mapping between bits and names.
**
** Some bit values have multiple names. The preferred name always
** comes first.
*/
static const struct OptName {
sqlite3_uint64 uMask;
const char *zName;
} aOpt[] = {
{ OPT_MASK(1), "QueryFlattener" },
{ OPT_MASK(1), "Flatten" }, /* Alias for prior */
{ OPT_MASK(2), "WindowFunc" },
{ OPT_MASK(3), "GroupByOrder" },
{ OPT_MASK(4), "JoinMiss" },
{ OPT_MASK(5), "DistinctOpt" },
{ OPT_MASK(6), "CoverIdxScan" },
{ OPT_MASK(7), "OrderByIdxJoin" },
{ OPT_MASK(8), "Transitive" },
{ OPT_MASK(9), "OmitNoopJoin" },
{ OPT_MASK(10), "CountOfView" },
{ OPT_MASK(11), "CursorHints" },
{ OPT_MASK(12), "Stat4" },
{ OPT_MASK(13), "PushDown" },
{ OPT_MASK(14), "SimplifyJoin" },
{ OPT_MASK(15), "SkipScan" },
{ OPT_MASK(16), "PropagateConst" },
{ OPT_MASK(17), "MinMaxOpt" },
{ OPT_MASK(18), "SeekScan" },
{ OPT_MASK(19), "OmitOrderBy" },
{ OPT_MASK(20), "BloomFilter" },
/* 21 currently unused */
{ OPT_MASK(22), "BalancedMerge" },
{ OPT_MASK(23), "ReleaseReg" },
{ OPT_MASK(24), "FlttnUnionAll" },
{ OPT_MASK(25), "IndexedExpr" },
{ OPT_MASK(26), "Coroutines" },
{ OPT_MASK(27), "NullUnusedCols" },
{ OPT_MASK(28), "OnePass" },
{ OPT_MASK(29), "OrderBySubq" },
{ OPT_MASK(29), "OrderBySubquery" }, /* Alias for prior */
{ OPT_MASK(30), "StarQuery" },
{ OPT_MASK(31), "ExistsToJoin" },
{ OPT_MASK(32), "UnionLimit" },
/* Special names */
{ 0xffffffffffffffffULL, "All" },
{ 0x0000000000000000ULL, "None" },
};
/*
** Given a symbolic name, try to compute the corresponding mask.
**
** The return value is:
**
** SQLITE_OK Successful match
** SQLITE_NOTFOUND No match
** SQLITE_MISUSE Bad arguments
*/
int sqlite3_optimization_mask(const char *zName, sqlite3_uint64 *pMask){
int i;
if( zName==0 || pMask==0 ){ return SQLITE_MISUSE; }
for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){
if( sqlite3_stricmp(zName, aOpt[i].zName)==0 ){
*pMask = aOpt[i].uMask;
return SQLITE_OK;
}
}
*pMask = 0;
return SQLITE_NOTFOUND;
}
/*
** Given a bitmap, return the canonical symbolic name. Return 0 for
** a bitmap input of 0 or a bitmap value that matches nothing.
*/
const char *sqlite3_optimization_name(sqlite3_int64 mask){
int i;
for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){
if( aOpt[i].uMask==mask ){ return aOpt[i].zName; }
}
return 0;
}

View File

@@ -803,6 +803,7 @@ TESTSRC += \
$(TOP)/ext/misc/mmapwarm.c \
$(TOP)/ext/misc/nextchar.c \
$(TOP)/ext/misc/normalize.c \
$(TOP)/ext/misc/optname.c \
$(TOP)/ext/misc/prefixes.c \
$(TOP)/ext/misc/qpvtab.c \
$(TOP)/ext/misc/randomjson.c \
@@ -2403,6 +2404,7 @@ SHELL_DEP = \
$(TOP)/ext/misc/fileio.c \
$(TOP)/ext/misc/ieee754.c \
$(TOP)/ext/misc/memtrace.c \
$(TOP)/ext/misc/optname.c \
$(TOP)/ext/misc/pcachetrace.c \
$(TOP)/ext/misc/regexp.c \
$(TOP)/ext/misc/series.c \

View File

@@ -1,5 +1,5 @@
C Update\svec1\sintegrity-check\smethod\sto\stolerate\ssmall\srounding\serrors\swhen\schecking\sthat\sa\svector\shas\sbeen\sassigned\sto\sthe\scorrect\scentroid.
D 2026-10-10T16:05:09.446
C New\sextension\sext/misc/optname.c\sprovides\sthe\scanonical\smapping\sbetween\noptimization\sbitmaps\sand\soptimization\snames.\s\sThis\sgives\sa\ssingle\spoint\nof\sedit\swhen\sthere\sare\schanges.\s\sUsed\sby\sthe\sCLI,\sby\stestfixture,\sand\sby\nTH3.
D 2026-10-10T17:40:46.822
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -7,7 +7,7 @@ F AGENTS.md 44ddfb38ef23e277888bd70ae378e6cbf5f5cab0e2a4420bd21d89b6caff7a4a
F LICENSE.md 3aa673c9c864ea8ee3ac46c7a52d270543a8fb8e1dd7e7b02df8f41dca1b80b6
F Makefile.in b9e64c91cf8bea2305e1ca88bd3eb022afa93963a8561ea8290c65d4fafec03e
F Makefile.linux-generic bd3e3cacd369821a6241d4ea1967395c962dfe3057e38cb0a435cee0e8b789d0
F Makefile.msc 46aa9ff8ace1e23d25e0dc7f80cc1856062f70f44a9517ec323b020a984d9cfa
F Makefile.msc 37777718ae5978a90da81670c691e07aba8e12d6a28dd74bf5adec1e71bcef87
F README.md b261d8e17a18fd45c55172d5ccead58455a9b5fe35f30d39e516338973578375
F VERSION 80115ed2da2f1a67c6ab9e67c3931a85d37c003bfe7b38989258624219ca6663
F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5
@@ -388,6 +388,7 @@ F ext/misc/mmapwarm.c a81af4aaec00f24f308e2f4c19bf1d88f3ac3ce848c36daa7a4cd38145
F ext/misc/nextchar.c 6092d68a78042462827a304b8db3e009f11985d38e2ef3c598917dc3d0fb208c
F ext/misc/noop.c 9d13ea10abab57811cbf2b731fd39b0a7dab46eb34cb95d102a8436cb12f4ccc
F ext/misc/normalize.c 2887c895f7c23b80cd0671af77acc57a88429d95d05ba2ce5c477e736c477a17
F ext/misc/optname.c d489ad3398353c2b9601b5db6d26b90ecf82b7b870fc211403b2ffc2c439a48d
F ext/misc/pcachetrace.c f4227ce03fb16aa8d6f321b72dd051097419d7a028a9853af048bee7645cb405
F ext/misc/percentile.c b6b9c740f0dc42838efd776eec0f68a93bc5ac86524c71337a70950860bf6c4d
F ext/misc/prefixes.c e7d3e7a39174db412c5f77c266fa221c2dc3cb2621a9422835a607ad08805eb2
@@ -723,7 +724,7 @@ F ext/wasm/tests/opfs/sahpool/index.html be736567fd92d3ecb9754c145755037cbbd2bca
F ext/wasm/tests/opfs/sahpool/sahpool-pausing.js f264925cfc82155de38cecb3d204c36e0f6991460fff0cb7c15079454679a4e2
F ext/wasm/tests/opfs/sahpool/sahpool-worker.js bd25a43fc2ab2d1bafd8f2854ad3943ef673f7c3be03e95ecf1612ff6e8e2a61
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
F main.mk dcb16dd1a254df261a53bbb20d9296e89ac879868f0c9182ce7c6f514be3aa3d
F main.mk 9fffb8d9ab5002cc9169005daee9743018b0099180d24472f5009f057e7b0305
F make.bat a136fd0b1c93e89854a86d5f4edcf0386d211e5d5ec2434480f6eea436c7420c
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -802,17 +803,17 @@ F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
F src/resolve.c 0e0990f60c93db38c735d85e5d1741130e72dd0670aec204b5a39118b53c8044
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c f6ad8bbf82f21a32c68ce3d885f1a960469d48efde93f432f5ba680869ae64f6
F src/shell.c.in add42f2c3c4529f038759f734fcaedf73f5cc2ed27451fe09c6e7c2bd319a8f5
F src/shell.c.in 80e6eeb36e3f1075106b591f1c683592da4fba1fc36180cb5bbb10fea479a7f8
F src/sqlite.h.in 648fdc66f52433fc0f6cf9564ac924cde544eca9605bbac36aa22d8c944f11ed
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
F src/sqlite3ext.h 5e113c4c0442f2f1b3345d44cbe4b82fad45f2fc0c35f0ed4eef27fb8f1cb394
F src/sqliteInt.h 3043f4c89ee3b92764bb7978239c57acef9e4930a010666fb15906a0d33c5df0
F src/sqliteInt.h 052ea255b0034edf253cecd294bcc2a2c657f3b344f91f6b586ea0c8f0213811
F src/sqliteLimit.h c433b3fdb5e52f4226bf78d7e8081dff8fd8fbb0ce0cb1a5fee282aaa8976813
F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F src/tclsqlite.c ef6b69d919800d1b2d3e1b57a1a0e78872c3bddd413a4bc639a865226cf91b16
F src/tclsqlite.h 614b3780a62522bc9f8f2b9fb22689e8009958e7aa77e572d0f3149050af348a
F src/test1.c d651507083ceff823113b86c0cd87cbfbb0e27b44f260a9909c78d6037b765dc
F src/test1.c 3ebd3dccf43e0723793c6577c5290e1cced9648bd710ce20b57f5c440f5b98fc
F src/test2.c a61ed01d9264a1db74ab42fbc981fc66165f85d5e3947e92be61a73e79ec4f2d
F src/test3.c c959fe0c3b04157483f5a6fa1950c1f222e062d920fee0a8e70410c6b6d45522
F src/test4.c 0ac87fc13cdb334ab3a71823f99b6c32a6bebe5d603cd6a71d84c823d43a25a0
@@ -2280,8 +2281,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
P c1ad888eec410613fd5d8ce7e9192bafe4073ad56e87d0232b320b53d5e07120
R d4343b895ddea3802d595154e823ac05
U dan
Z e1c1f58077380e607f85a561c82aed52
P 54e6ae3ae6ac533277def3105162d4578ab4499aec6fbca65000289fbdb9df78
R 682bb1150b283db3b91f8980f96a9149
U drh
Z fe5dc37d713d31de555d0de40fef9ca3
# Remove this line to create a well-formed Fossil manifest.

View File

@@ -1 +1 @@
54e6ae3ae6ac533277def3105162d4578ab4499aec6fbca65000289fbdb9df78
135ed9e2cc9bd37c3e158a488e37f4ce14ffeca44ff12e31f25a6686a2622ca1

View File

@@ -291,6 +291,7 @@ INCLUDE ../ext/misc/uint.c
INCLUDE ../ext/misc/decimal.c
INCLUDE ../ext/misc/base64.c
INCLUDE ../ext/misc/base85.c
INCLUDE ../ext/misc/optname.c
INCLUDE ../ext/misc/ieee754.c
INCLUDE ../ext/misc/series.c
INCLUDE ../ext/misc/regexp.c
@@ -12714,51 +12715,14 @@ static int do_meta_command(const char *zLine, ShellState *p){
** INTEGER Mask of optimizations to disable
*/
case SQLITE_TESTCTRL_OPTIMIZATIONS: {
static const struct {
unsigned int mask; /* Mask for this optimization */
unsigned int bDsply; /* Display this on output */
const char *zLabel; /* Name of optimization */
} aLabel[] = {
/* Keep these values in sync with the th3dbOpt() function of TH3 */
{ 0x00000001, 1, "QueryFlattener" },
{ 0x00000001, 0, "Flatten" },
{ 0x00000002, 1, "WindowFunc" },
{ 0x00000004, 1, "GroupByOrder" },
{ 0x00000008, 1, "JoinMiss" },
{ 0x00000010, 1, "DistinctOpt" },
{ 0x00000020, 1, "CoverIdxScan" },
{ 0x00000040, 1, "OrderByIdxJoin" },
{ 0x00000080, 1, "Transitive" },
{ 0x00000100, 1, "OmitNoopJoin" },
{ 0x00000200, 1, "CountOfView" },
{ 0x00000400, 1, "CursorHints" },
{ 0x00000800, 1, "Stat4" },
{ 0x00001000, 1, "PushDown" },
{ 0x00002000, 1, "SimplifyJoin" },
{ 0x00004000, 1, "SkipScan" },
{ 0x00008000, 1, "PropagateConst" },
{ 0x00010000, 1, "MinMaxOpt" },
{ 0x00020000, 1, "SeekScan" },
{ 0x00040000, 1, "OmitOrderBy" },
{ 0x00080000, 1, "BloomFilter" },
{ 0x00200000, 1, "BalancedMerge" },
{ 0x00400000, 1, "ReleaseReg" },
{ 0x00800000, 1, "FlttnUnionAll" },
{ 0x01000000, 1, "IndexedEXpr" },
{ 0x02000000, 1, "Coroutines" },
{ 0x04000000, 1, "NullUnusedCols" },
{ 0x08000000, 1, "OnePass" },
{ 0x10000000, 1, "OrderBySubq" },
{ 0x20000000, 1, "StarQuery" },
{ 0x40000000, 1, "ExistsToJoin" },
{ 0x80000000, 1, "UnionLimit" },
{ 0xffffffff, 0, "All" },
};
unsigned int curOpt;
unsigned int newOpt;
unsigned int m;
int ii;
int nOff;
unsigned int curOpt; /* Current opt-disabled mask */
unsigned int newOpt; /* New opt-disabled mask */
unsigned int m; /* A working mask value */
sqlite3_uint64 mm; /* 64-bit working mask value */
int ii, jj; /* Loop counters */
int nOff; /* Number of disabled optimizations */
const char *zName; /* Name of an optimization */
sqlite3_test_control(SQLITE_TESTCTRL_GETOPT, p->db, &curOpt);
newOpt = curOpt;
for(ii=2; ii<nArg; ii++){
@@ -12775,25 +12739,23 @@ static int do_meta_command(const char *zLine, ShellState *p){
newOpt = (unsigned int)strtol(z,0,0);
}
if( useLabel ){
int jj;
for(jj=0; jj<ArraySize(aLabel); jj++){
if( sqlite3_stricmp(zLabel, aLabel[jj].zLabel)==0 ) break;
}
if( jj>=ArraySize(aLabel) ){
if( sqlite3_optimization_mask(zLabel,&mm)==SQLITE_NOTFOUND ){
cli_printf(stderr,
"Error: no such optimization: \"%s\"\n", zLabel);
cli_puts("Should be one of:", stderr);
for(jj=0; jj<ArraySize(aLabel); jj++){
cli_printf(stderr," %s", aLabel[jj].zLabel);
cli_puts("Should be one of: All", stderr);
for(jj=0; jj<32; jj++){
zName = sqlite3_optimization_name(1ull<<jj);
if( zName ) cli_printf(stderr," %s", zName);
}
cli_puts("\n", stderr);
rc = 1;
goto meta_command_exit;
}
m = (u32)mm;
if( useLabel=='+' ){
newOpt &= ~aLabel[jj].mask;
newOpt &= ~m;
}else{
newOpt |= aLabel[jj].mask;
newOpt |= m;
}
}
}
@@ -12805,18 +12767,17 @@ static int do_meta_command(const char *zLine, ShellState *p){
}
if( nOff<12 ){
cli_puts("+All", p->out);
for(ii=0; ii<ArraySize(aLabel); ii++){
if( !aLabel[ii].bDsply ) continue;
if( (newOpt & aLabel[ii].mask)!=0 ){
cli_printf(p->out, " -%s", aLabel[ii].zLabel);
for(ii=0, m=1; ii<32; ii++, m <<= 1){
const char *zName;
if( (newOpt & m)!=0 && (zName = sqlite3_optimization_name(m))!=0 ){
cli_printf(p->out, " -%s", zName);
}
}
}else{
cli_puts("-All", p->out);
for(ii=0; ii<ArraySize(aLabel); ii++){
if( !aLabel[ii].bDsply ) continue;
if( (newOpt & aLabel[ii].mask)==0 ){
cli_printf(p->out, " +%s", aLabel[ii].zLabel);
for(ii=0, m=1; ii<32; ii++, m <<= 1){
if( (newOpt & m)==0 && (zName = sqlite3_optimization_name(m))!=0 ){
cli_printf(p->out, " +%s", zName);
}
}
}

View File

@@ -1713,7 +1713,6 @@ struct sqlite3 {
int errByteOffset; /* Byte offset of error in SQL statement */
int errMask; /* & result codes with this before returning */
int iSysErrno; /* Errno value from last system error */
u32 dbOptFlags; /* Flags to enable/disable optimizations */
u8 enc; /* Text encoding */
u8 autoCommit; /* The auto-commit flag. */
u8 temp_store; /* 1: file 2: memory 0: default */
@@ -1732,6 +1731,7 @@ struct sqlite3 {
int nextPagesize; /* Pagesize after VACUUM if >0 */
i64 nChange; /* Value returned by sqlite3_changes() */
i64 nTotalChange; /* Value returned by sqlite3_total_changes() */
u32 dbOptFlags; /* Flags to enable/disable optimizations */
int aLimit[SQLITE_N_LIMIT]; /* Limits */
int nMaxSorterMmap; /* Maximum size of regions mapped by sorter */
struct sqlite3InitInfo { /* Information used during initialization */
@@ -1931,51 +1931,49 @@ struct sqlite3 {
/*
** Bits of the sqlite3.dbOptFlags field that are used by the
** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to
** selectively disable various optimizations.
** selectively disable various optimizations. The numbers in each macro
** are the one-based bit position (for improved readability).
**
** Keep these values in sync with the ".testctrl" command of the CLI
** and the th3dbOpt() function of TH3. Note also that TH3 expects the
** STAT4 optimization to always be 0x800.
** Keep these values in sync with the ext/misc/optname.c extension.
*/
#define SQLITE_QueryFlattener 0x00000001 /* Query flattening */
#define SQLITE_WindowFunc 0x00000002 /* Use xInverse for window functions */
#define SQLITE_GroupByOrder 0x00000004 /* GROUPBY cover of ORDERBY */
#define SQLITE_JoinMiss 0x00000008 /* Unwind join loops on a lookup miss*/
#define SQLITE_DistinctOpt 0x00000010 /* DISTINCT using indexes */
#define SQLITE_CoverIdxScan 0x00000020 /* Covering index scans */
#define SQLITE_OrderByIdxJoin 0x00000040 /* ORDER BY of joins via index */
#define SQLITE_Transitive 0x00000080 /* Transitive constraints */
#define SQLITE_OmitNoopJoin 0x00000100 /* Omit unused tables in joins */
#define SQLITE_CountOfView 0x00000200 /* The count-of-view optimization */
#define SQLITE_CursorHints 0x00000400 /* Add OP_CursorHint opcodes */
#define SQLITE_Stat4 0x00000800 /* Use STAT4 data */
#define SQLITE_PushDown 0x00001000 /* WHERE-clause push-down opt */
#define SQLITE_SimplifyJoin 0x00002000 /* Convert LEFT JOIN to JOIN */
#define SQLITE_SkipScan 0x00004000 /* Skip-scans */
#define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */
#define SQLITE_MinMaxOpt 0x00010000 /* The min/max optimization */
#define SQLITE_SeekScan 0x00020000 /* The OP_SeekScan optimization */
#define SQLITE_OmitOrderBy 0x00040000 /* Omit pointless ORDER BY */
#define SQLITE_BloomFilter 0x00080000 /* Use a Bloom filters */
/* 0x00100000 -- Available for reuse */
#define SQLITE_BalancedMerge 0x00200000 /* Balance multi-way merges */
#define SQLITE_ReleaseReg 0x00400000 /* Use OP_ReleaseReg for testing */
#define SQLITE_FlttnUnionAll 0x00800000 /* Disable the UNION ALL flattener */
#define SQLITE_IndexedExpr 0x01000000 /* Pull exprs from index when able */
#define SQLITE_Coroutines 0x02000000 /* Co-routines for subqueries */
#define SQLITE_NullUnusedCols 0x04000000 /* NULL unused columns in subqueries */
#define SQLITE_OnePass 0x08000000 /* Single-pass DELETE and UPDATE */
#define SQLITE_OrderBySubq 0x10000000 /* ORDER BY in subquery helps outer */
#define SQLITE_StarQuery 0x20000000 /* Heurists for star queries */
#define SQLITE_ExistsToJoin 0x40000000 /* The EXISTS-to-JOIN optimization */
#define SQLITE_UnionLimit 0x80000000 /* Optimizations for UNION + LIMIT */
#define SQLITE_AllOpts 0xffffffff /* All optimizations */
#define SQLITE_QueryFlattener 1 /* Query flattening */
#define SQLITE_WindowFunc 2 /* Use xInverse for window functions */
#define SQLITE_GroupByOrder 3 /* GROUPBY cover of ORDERBY */
#define SQLITE_JoinMiss 4 /* Unwind join loops on a lookup miss*/
#define SQLITE_DistinctOpt 5 /* DISTINCT using indexes */
#define SQLITE_CoverIdxScan 6 /* Covering index scans */
#define SQLITE_OrderByIdxJoin 7 /* ORDER BY of joins via index */
#define SQLITE_Transitive 8 /* Transitive constraints */
#define SQLITE_OmitNoopJoin 9 /* Omit unused tables in joins */
#define SQLITE_CountOfView 10 /* The count-of-view optimization */
#define SQLITE_CursorHints 11 /* Add OP_CursorHint opcodes */
#define SQLITE_Stat4 12 /* Use STAT4 data */
#define SQLITE_PushDown 13 /* WHERE-clause push-down opt */
#define SQLITE_SimplifyJoin 14 /* Convert LEFT JOIN to JOIN */
#define SQLITE_SkipScan 15 /* Skip-scans */
#define SQLITE_PropagateConst 16 /* The constant propagation opt */
#define SQLITE_MinMaxOpt 17 /* The min/max optimization */
#define SQLITE_SeekScan 18 /* The OP_SeekScan optimization */
#define SQLITE_OmitOrderBy 19 /* Omit pointless ORDER BY */
#define SQLITE_BloomFilter 20 /* Use a Bloom filters */
/* 21 -- Available for reuse */
#define SQLITE_BalancedMerge 22 /* Balance multi-way merges */
#define SQLITE_ReleaseReg 23 /* Use OP_ReleaseReg for testing */
#define SQLITE_FlttnUnionAll 24 /* Disable the UNION ALL flattener */
#define SQLITE_IndexedExpr 25 /* Pull exprs from index when able */
#define SQLITE_Coroutines 26 /* Co-routines for subqueries */
#define SQLITE_NullUnusedCols 27 /* NULL unused columns in subqueries */
#define SQLITE_OnePass 28 /* Single-pass DELETE and UPDATE */
#define SQLITE_OrderBySubq 29 /* ORDER BY in subquery helps outer */
#define SQLITE_StarQuery 30 /* Heurists for star queries */
#define SQLITE_ExistsToJoin 31 /* The EXISTS-to-JOIN optimization */
#define SQLITE_UnionLimit 32 /* Optimizations for UNION + LIMIT */
/*
** Macros for testing whether or not optimizations are enabled or disabled.
*/
#define OptimizationDisabled(db, mask) (((db)->dbOptFlags&(mask))!=0)
#define OptimizationEnabled(db, mask) (((db)->dbOptFlags&(mask))==0)
#define OptimizationDisabled(D,M) (((D)->dbOptFlags&(1ul<<((M)-1)))!=0)
#define OptimizationEnabled(D,M) (((D)->dbOptFlags&(1ul<<((M)-1)))==0)
/*
** Return true if it OK to factor constant expressions into the initialization

View File

@@ -8539,35 +8539,15 @@ static int SQLITE_TCLAPI optimization_control(
int objc,
Tcl_Obj *CONST objv[]
){
int i;
size_t i, j, k;
sqlite3 *db;
const char *zOpt;
int onoff;
int mask = 0;
int cnt = 0;
static const struct {
const char *zOptName;
int mask;
} aOpt[] = {
{ "all", SQLITE_AllOpts },
{ "none", 0 },
{ "query-flattener", SQLITE_QueryFlattener },
{ "groupby-order", SQLITE_GroupByOrder },
{ "distinct-opt", SQLITE_DistinctOpt },
{ "cover-idx-scan", SQLITE_CoverIdxScan },
{ "order-by-idx-join", SQLITE_OrderByIdxJoin },
{ "order-by-subquery", SQLITE_OrderBySubq },
{ "transitive", SQLITE_Transitive },
{ "omit-noop-join", SQLITE_OmitNoopJoin },
{ "stat4", SQLITE_Stat4 },
{ "skip-scan", SQLITE_SkipScan },
{ "push-down", SQLITE_PushDown },
{ "balanced-merge", SQLITE_BalancedMerge },
{ "propagate-const", SQLITE_PropagateConst },
{ "one-pass", SQLITE_OnePass },
{ "exists-to-join", SQLITE_ExistsToJoin },
{ "count-of-view", SQLITE_CountOfView },
};
u64 m = 0, mask = 0;
int m32;
char zBuf[50];
extern int sqlite3_optimization_mask(const char*,sqlite3_uint64*);
extern const char *sqlite3_optimization_name(sqlite3_uint64);
if( objc!=4 ){
Tcl_WrongNumArgs(interp, 1, objv, "DB OPT BOOLEAN");
@@ -8576,23 +8556,36 @@ static int SQLITE_TCLAPI optimization_control(
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
if( Tcl_GetBooleanFromObj(interp, objv[3], &onoff) ) return TCL_ERROR;
zOpt = Tcl_GetString(objv[2]);
for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){
if( strstr(zOpt, aOpt[i].zOptName)!=0 ){
mask |= aOpt[i].mask;
cnt++;
while( zOpt && zOpt[0] ){
while( zOpt[0]==' ' || zOpt[0]==',' ) zOpt++;
for(i=0; zOpt[i] && zOpt[i]!=',' && zOpt[i]!=' '; i++){}
if( i==0 ) break;
if( i<sizeof(zBuf)-1 ){
for(j=k=0; j<i; j++){
if( zOpt[j]!='-' ) zBuf[k++] = zOpt[j];
}
zBuf[k] = 0;
if( sqlite3_optimization_mask(zBuf, &m)==SQLITE_NOTFOUND ){
const char *zName;
Tcl_AppendResult(interp, "unknown optimization \"", zBuf,
"\" - should be one of:", (char*)0);
for(i=0; i<64; i++){
m = 1ull<<i;
zName = sqlite3_optimization_name(m);
if( zName ){
Tcl_AppendResult(interp, " ", zName, (char*)0);
}
}
return TCL_ERROR;
}
mask |= m;
}
zOpt += i;
}
if( onoff ) mask = ~mask;
if( cnt==0 ){
Tcl_AppendResult(interp, "unknown optimization - should be one of:",
(char*)0);
for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){
Tcl_AppendResult(interp, " ", aOpt[i].zOptName, (char*)0);
}
return TCL_ERROR;
}
sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, db, mask);
Tcl_SetObjResult(interp, Tcl_NewIntObj(mask));
m32 = (int)(mask & 0xffffffff);
sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,db, m32);
Tcl_SetObjResult(interp, Tcl_NewIntObj(m32));
return TCL_OK;
}