/ Check-in [ad8bc681]
Login

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

Overview
Comment:Add the ability to disable constant factoring using sqlite3_test_control(). Add a TCL interface to this new capability and add tests cases to the TCL test scripts to actually use the new capability.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: ad8bc68197f2b47435149c3dbc035f4e7210fc76
User & Date: drh 2010-12-06 21:06:09
References
2010-12-16
19:52
Fix an assertion fault that can only occur if SQLITE_ENABLE_STAT2 is defined and the constant folding optimization is disabled using sqlite3_test_control(). Problem introduced by [ad8bc68197f2b4] but we missed it prior to the 3.7.4 release due to taking shortcuts and skipping tests in the release checklist. check-in: 70a3d817 user: drh tags: trunk
Context
2010-12-06
21:09
Fix the build so that it once again works with SQLITE_OMIT_SHARED_CACHE and SQLITE_OMIT_AUTOVACUUM. check-in: fabcb6b9 user: drh tags: trunk
21:06
Add the ability to disable constant factoring using sqlite3_test_control(). Add a TCL interface to this new capability and add tests cases to the TCL test scripts to actually use the new capability. check-in: ad8bc681 user: drh tags: trunk
18:59
Back out part of the previous change that was not really necessary in order to fix [80ba201079ea60], and which in fact serves no useful purpose. check-in: fa9eef86 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/expr.c.

  3036   3036     return WRC_Continue;
  3037   3037   }
  3038   3038   
  3039   3039   /*
  3040   3040   ** Preevaluate constant subexpressions within pExpr and store the
  3041   3041   ** results in registers.  Modify pExpr so that the constant subexpresions
  3042   3042   ** are TK_REGISTER opcodes that refer to the precomputed values.
         3043  +**
         3044  +** This routine is a no-op if the jump to the cookie-check code has
         3045  +** already occur.  Since the cookie-check jump is generated prior to
         3046  +** any other serious processing, this check ensures that there is no
         3047  +** way to accidently bypass the constant initializations.
         3048  +**
         3049  +** This routine is also a no-op if the SQLITE_FactorOutConst optimization
         3050  +** is disabled via the sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS)
         3051  +** interface.  This allows test logic to verify that the same answer is
         3052  +** obtained for queries regardless of whether or not constants are
         3053  +** precomputed into registers or if they are inserted in-line.
  3043   3054   */
  3044   3055   void sqlite3ExprCodeConstants(Parse *pParse, Expr *pExpr){
  3045   3056     Walker w;
  3046   3057     if( pParse->cookieGoto ) return;
         3058  +  if( (pParse->db->flags & SQLITE_FactorOutConst)!=0 ) return;
  3047   3059     w.xExprCallback = evalConstExpr;
  3048   3060     w.xSelectCallback = 0;
  3049   3061     w.pParse = pParse;
  3050   3062     sqlite3WalkExpr(&w, pExpr);
  3051   3063   }
  3052   3064   
  3053   3065   

Changes to src/sqliteInt.h.

   930    930   */
   931    931   #define SQLITE_QueryFlattener 0x01        /* Disable query flattening */
   932    932   #define SQLITE_ColumnCache    0x02        /* Disable the column cache */
   933    933   #define SQLITE_IndexSort      0x04        /* Disable indexes for sorting */
   934    934   #define SQLITE_IndexSearch    0x08        /* Disable indexes for searching */
   935    935   #define SQLITE_IndexCover     0x10        /* Disable index covering table */
   936    936   #define SQLITE_GroupByOrder   0x20        /* Disable GROUPBY cover of ORDERBY */
          937  +#define SQLITE_FactorOutConst 0x40        /* Disable factoring out constants */
   937    938   #define SQLITE_OptMask        0xff        /* Mask of all disablable opts */
   938    939   
   939    940   /*
   940    941   ** Possible values for the sqlite.magic field.
   941    942   ** The numbers are obtained at random and have no special meaning, other
   942    943   ** than being distinct from one another.
   943    944   */

Changes to src/test1.c.

  5312   5312     }
  5313   5313     if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  5314   5314     rc = printExplainQueryPlan(pStmt);
  5315   5315     Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
  5316   5316     return TCL_OK;
  5317   5317   }
  5318   5318   #endif /* SQLITE_OMIT_EXPLAIN */
         5319  +
         5320  +/*
         5321  +**      optimization_control DB OPT BOOLEAN
         5322  +**
         5323  +** Enable or disable query optimizations using the sqlite3_test_control()
         5324  +** interface.  Disable if BOOLEAN is false and enable if BOOLEAN is true.
         5325  +** OPT is the name of the optimization to be disabled.
         5326  +*/
         5327  +static int optimization_control(
         5328  +  void * clientData,
         5329  +  Tcl_Interp *interp,
         5330  +  int objc,
         5331  +  Tcl_Obj *CONST objv[]
         5332  +){
         5333  +  int i;
         5334  +  sqlite3 *db;
         5335  +  const char *zOpt;
         5336  +  int onoff;
         5337  +  int mask;
         5338  +  static const struct {
         5339  +    const char *zOptName;
         5340  +    int mask;
         5341  +  } aOpt[] = {
         5342  +    { "all",              SQLITE_OptMask        },
         5343  +    { "query-flattener",  SQLITE_QueryFlattener },
         5344  +    { "column-cache",     SQLITE_ColumnCache    },
         5345  +    { "index-sort",       SQLITE_IndexSort      },
         5346  +    { "index-search",     SQLITE_IndexSearch    },
         5347  +    { "index-cover",      SQLITE_IndexCover     },
         5348  +    { "groupby-order",    SQLITE_GroupByOrder   },
         5349  +    { "factor-constants", SQLITE_FactorOutConst },
         5350  +  };
         5351  +
         5352  +  if( objc!=4 ){
         5353  +    Tcl_WrongNumArgs(interp, 1, objv, "DB OPT BOOLEAN");
         5354  +    return TCL_ERROR;
         5355  +  }
         5356  +  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
         5357  +  if( Tcl_GetBooleanFromObj(interp, objv[3], &onoff) ) return TCL_ERROR;
         5358  +  zOpt = Tcl_GetString(objv[2]);
         5359  +  for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){
         5360  +    if( strcmp(zOpt, aOpt[i].zOptName)==0 ){
         5361  +      mask = aOpt[i].mask;
         5362  +      break;
         5363  +    }
         5364  +  }
         5365  +  if( onoff ) mask = ~mask;
         5366  +  if( i>=sizeof(aOpt)/sizeof(aOpt[0]) ){
         5367  +    Tcl_AppendResult(interp, "unknown optimization - should be one of:",
         5368  +                     (char*)0);
         5369  +    for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){
         5370  +      Tcl_AppendResult(interp, " ", aOpt[i].zOptName);
         5371  +    }
         5372  +    return TCL_ERROR;
         5373  +  }
         5374  +  sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, db, mask);
         5375  +  return TCL_OK;
         5376  +}
  5319   5377   
  5320   5378   /*
  5321   5379   ** Register commands with the TCL interpreter.
  5322   5380   */
  5323   5381   int Sqlitetest1_Init(Tcl_Interp *interp){
  5324   5382     extern int sqlite3_search_count;
  5325   5383     extern int sqlite3_found_count;
................................................................................
  5430   5488        { "sqlite3_enable_load_extension", test_enable_load,        0},
  5431   5489        { "sqlite3_extended_result_codes", test_extended_result_codes, 0},
  5432   5490        { "sqlite3_limit",                 test_limit,                 0},
  5433   5491   
  5434   5492        { "save_prng_state",               save_prng_state,    0 },
  5435   5493        { "restore_prng_state",            restore_prng_state, 0 },
  5436   5494        { "reset_prng_state",              reset_prng_state,   0 },
         5495  +     { "optimization_control",          optimization_control,0},
  5437   5496        { "tcl_objproc",                   runAsObjProc,       0 },
  5438   5497   
  5439   5498        /* sqlite3_column_*() API */
  5440   5499        { "sqlite3_column_count",          test_column_count  ,0 },
  5441   5500        { "sqlite3_data_count",            test_data_count    ,0 },
  5442   5501        { "sqlite3_column_type",           test_column_type   ,0 },
  5443   5502        { "sqlite3_column_blob",           test_column_blob   ,0 },

Changes to test/tkt-80ba201079.test.

    35     35     db eval {
    36     36       CREATE INDEX i1 ON t1(a);
    37     37       SELECT * FROM t1, t2
    38     38        WHERE (a='A' AND b='X')
    39     39           OR (a='A' AND EXISTS (SELECT * FROM t3 WHERE c='C'));
    40     40     }
    41     41   } {A B}
           42  +do_test tkt-80ba2-102 {
           43  +  optimization_control db factor-constants 0
           44  +  db cache flush
           45  +  db eval {
           46  +    SELECT * FROM t1, t2
           47  +     WHERE (a='A' AND b='X')
           48  +        OR (a='A' AND EXISTS (SELECT * FROM t3 WHERE c='C'));
           49  +  }
           50  +} {A B}
           51  +optimization_control db all 1
           52  +
           53  +# Verify that the optimization_control command is actually working
           54  +#
           55  +do_test tkt-80ba2-150 {
           56  +  optimization_control db factor-constants 1
           57  +  db cache flush
           58  +  set x1 [db eval {EXPLAIN 
           59  +    SELECT * FROM t1, t2
           60  +     WHERE (a='A' AND b='X')
           61  +        OR (a='A' AND EXISTS (SELECT * FROM t3 WHERE c='C'));}]
           62  +  optimization_control db factor-constants 0
           63  +  db cache flush
           64  +  set x2 [db eval {EXPLAIN 
           65  +    SELECT * FROM t1, t2
           66  +     WHERE (a='A' AND b='X')
           67  +        OR (a='A' AND EXISTS (SELECT * FROM t3 WHERE c='C'));}]
           68  +
           69  +  expr {$x1==$x2}
           70  +} {0}
    42     71   
    43     72   do_test tkt-80ba2-200 {
    44     73     db eval {
    45     74       CREATE TABLE entry_types (
    46     75                           id     integer primary key,
    47     76                           name   text
    48     77                       );
................................................................................
    77    106                                 FROM object_changes
    78    107                                  WHERE obj_context = 'exported_pools'));
    79    108     }
    80    109   } {300 object_change 2048}
    81    110   do_test tkt-80ba2-201 {
    82    111     db eval {
    83    112       CREATE INDEX timeline_entry_id_idx on timeline(entry_id);
          113  +    SELECT entry_type,
          114  +           entry_types.name,
          115  +           entry_id
          116  +      FROM timeline JOIN entry_types ON entry_type = entry_types.id
          117  +     WHERE (entry_types.name = 'cli_command' AND entry_id=2114)
          118  +        OR (entry_types.name = 'object_change'
          119  +             AND entry_id IN (SELECT change_id
          120  +                              FROM object_changes
          121  +                               WHERE obj_context = 'exported_pools'));
          122  +  }
          123  +} {300 object_change 2048}
          124  +do_test tkt-80ba2-202 {
          125  +  optimization_control db factor-constants 0
          126  +  db cache flush
          127  +  db eval {
    84    128       SELECT entry_type,
    85    129              entry_types.name,
    86    130              entry_id
    87    131         FROM timeline JOIN entry_types ON entry_type = entry_types.id
    88    132        WHERE (entry_types.name = 'cli_command' AND entry_id=2114)
    89    133           OR (entry_types.name = 'object_change'
    90    134                AND entry_id IN (SELECT change_id
    91    135                                 FROM object_changes
    92    136                                  WHERE obj_context = 'exported_pools'));
    93    137     }
    94    138   } {300 object_change 2048}
    95    139   
    96    140   finish_test