/ Check-in [c07e493b]
Login

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

Overview
Comment:Fix for ticket #84: If the WHERE clause is too complex, issue an error message and refuse to do the SELECT. The cutoff is a WHERE clause with 100 terms. (CVS 650)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:c07e493b62125e85eaea36b6945f1e146e2792b8
User & Date: drh 2002-06-28 01:02:38
Context
2002-06-28
12:18
Additional test cases added. The following bug fixed: A segfault was occurring if a VIEW consisted of a join with a USING clause. (CVS 651) check-in: 96515b81 user: drh tags: trunk
01:02
Fix for ticket #84: If the WHERE clause is too complex, issue an error message and refuse to do the SELECT. The cutoff is a WHERE clause with 100 terms. (CVS 650) check-in: c07e493b user: drh tags: trunk
2002-06-27
13:21
Fix for ticket #88: A typo in the documention of the "sqlite" shell command. (CVS 649) check-in: 16552a7a user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/vdbe.c.

    26     26   ** type to the other occurs as necessary.
    27     27   ** 
    28     28   ** Most of the code in this file is taken up by the sqliteVdbeExec()
    29     29   ** function which does the work of interpreting a VDBE program.
    30     30   ** But other routines are also provided to help in building up
    31     31   ** a program instruction by instruction.
    32     32   **
    33         -** $Id: vdbe.c,v 1.161 2002/06/26 02:45:04 drh Exp $
           33  +** $Id: vdbe.c,v 1.162 2002/06/28 01:02:38 drh Exp $
    34     34   */
    35     35   #include "sqliteInt.h"
    36     36   #include <ctype.h>
    37     37   
    38     38   /*
    39     39   ** The following global variable is incremented every time a cursor
    40     40   ** moves, either by the OP_MoveTo or the OP_Next opcode.  The test
................................................................................
  2841   2841   case OP_Commit: {
  2842   2842     if( db->pBeTemp==0 || (rc = sqliteBtreeCommit(db->pBeTemp))==SQLITE_OK ){
  2843   2843       rc = sqliteBtreeCommit(pBt);
  2844   2844     }
  2845   2845     if( rc==SQLITE_OK ){
  2846   2846       sqliteCommitInternalChanges(db);
  2847   2847     }else{
         2848  +    if( db->pBeTemp ) sqliteBtreeRollback(db->pBeTemp);
         2849  +    sqliteBtreeRollback(pBt);
  2848   2850       sqliteRollbackInternalChanges(db);
  2849   2851     }
  2850   2852     break;
  2851   2853   }
  2852   2854   
  2853   2855   /* Opcode: Rollback * * *
  2854   2856   **

Changes to src/where.c.

     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This module contains C code that generates VDBE code used to process
    13     13   ** the WHERE clause of SQL statements.  Also found here are subroutines
    14     14   ** to generate VDBE code to evaluate expressions.
    15     15   **
    16         -** $Id: where.c,v 1.56 2002/06/25 01:09:12 drh Exp $
           16  +** $Id: where.c,v 1.57 2002/06/28 01:02:38 drh Exp $
    17     17   */
    18     18   #include "sqliteInt.h"
    19     19   
    20     20   /*
    21     21   ** The query generator uses an array of instances of this structure to
    22     22   ** help it analyze the subexpressions of the WHERE clause.  Each WHERE
    23     23   ** clause subexpression is separated from the others by an AND operator.
................................................................................
   300    300     int nExpr;           /* Number of subexpressions in the WHERE clause */
   301    301     int loopMask;        /* One bit set for each outer loop */
   302    302     int haveKey;         /* True if KEY is on the stack */
   303    303     int aDirect[32];     /* If TRUE, then index this table using ROWID */
   304    304     int iDirectEq[32];   /* Term of the form ROWID==X for the N-th table */
   305    305     int iDirectLt[32];   /* Term of the form ROWID<X or ROWID<=X */
   306    306     int iDirectGt[32];   /* Term of the form ROWID>X or ROWID>=X */
   307         -  ExprInfo aExpr[50];  /* The WHERE clause is divided into these expressions */
          307  +  ExprInfo aExpr[101]; /* The WHERE clause is divided into these expressions */
   308    308   
   309    309     /* pushKey is only allowed if there is a single table (as in an INSERT or
   310    310     ** UPDATE statement)
   311    311     */
   312    312     assert( pushKey==0 || pTabList->nSrc==1 );
          313  +
          314  +  /* Split the WHERE clause into separate subexpressions where each
          315  +  ** subexpression is separated by an AND operator.  If the aExpr[]
          316  +  ** array fills up, the last entry might point to an expression which
          317  +  ** contains additional unfactored AND operators.
          318  +  */
          319  +  memset(aExpr, 0, sizeof(aExpr));
          320  +  nExpr = exprSplit(ARRAYSIZE(aExpr), aExpr, pWhere);
          321  +  if( nExpr==ARRAYSIZE(aExpr) ){
          322  +    char zBuf[50];
          323  +    sprintf(zBuf, "%d", ARRAYSIZE(aExpr)-1);
          324  +    sqliteSetString(&pParse->zErrMsg, "WHERE clause too complex - no more "
          325  +       "than ", zBuf, " terms allowed", 0);
          326  +    pParse->nErr++;
          327  +    return 0;
          328  +  }
   313    329     
   314    330     /* Allocate space for aOrder[] */
   315    331     aOrder = sqliteMalloc( sizeof(int) * pTabList->nSrc );
   316    332   
   317    333     /* Allocate and initialize the WhereInfo structure that will become the
   318    334     ** return value.
   319    335     */
................................................................................
   333    349     ** expression and either jump over all of the code or fall thru.
   334    350     */
   335    351     if( pWhere && sqliteExprIsConstant(pWhere) ){
   336    352       sqliteExprIfFalse(pParse, pWhere, pWInfo->iBreak, 1);
   337    353       pWhere = 0;
   338    354     }
   339    355   
   340         -  /* Split the WHERE clause into as many as 32 separate subexpressions
   341         -  ** where each subexpression is separated by an AND operator.  Any additional
   342         -  ** subexpressions are attached in the aExpr[32] and will not enter
   343         -  ** into the query optimizer computations.  32 is chosen as the cutoff
   344         -  ** since that is the number of bits in an integer that we use for an
   345         -  ** expression-used mask.  
   346         -  */
   347         -  memset(aExpr, 0, sizeof(aExpr));
   348         -  nExpr = exprSplit(ARRAYSIZE(aExpr), aExpr, pWhere);
   349         -
   350    356     /* Analyze all of the subexpressions.
   351    357     */
   352    358     for(i=0; i<nExpr; i++){
   353    359       exprAnalyze(base, &aExpr[i]);
   354    360   
   355    361       /* If we are executing a trigger body, remove all references to
   356    362       ** new.* and old.* tables from the prerequisite masks.

Changes to test/misc1.test.

     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.
    12     12   #
    13     13   # This file implements tests for miscellanous features that were
    14     14   # left out of other test files.
    15     15   #
    16         -# $Id: misc1.test,v 1.9 2002/06/21 23:01:51 drh Exp $
           16  +# $Id: misc1.test,v 1.10 2002/06/28 01:02:39 drh Exp $
    17     17   
    18     18   set testdir [file dirname $argv0]
    19     19   source $testdir/tester.tcl
    20     20   
    21     21   # Test the creation and use of tables that have a large number
    22     22   # of columns.
    23     23   #
................................................................................
   253    253       CREATE TABLE t1(a unique not null, b unique not null);
   254    254       INSERT INTO t1 VALUES('a',12345678901234567890);
   255    255       INSERT INTO t1 VALUES('b',12345678911234567890);
   256    256       INSERT INTO t1 VALUES('c',12345678921234567890);
   257    257       SELECT * FROM t1;
   258    258     }
   259    259   } {0 {a 12345678901234567890 b 12345678911234567890 c 12345678921234567890}}
          260  +
          261  +# A WHERE clause is not allowed to contain more than 99 terms.  Check to
          262  +# make sure this limit is enforced.
          263  +#
          264  +do_test misc1-10.0 {
          265  +  execsql {SELECT count(*) FROM manycol}
          266  +} {9}
          267  +do_test misc1-10.1 {
          268  +  set ::where {WHERE x0>=0}
          269  +  for {set i 1} {$i<=99} {incr i} {
          270  +    append ::where " AND x$i<>0"
          271  +  }
          272  +  catchsql "SELECT count(*) FROM manycol $::where"
          273  +} {0 9}
          274  +do_test misc1-10.2 {
          275  +  catchsql "SELECT count(*) FROM manycol $::where AND rowid>0"
          276  +} {1 {WHERE clause too complex - no more than 100 terms allowed}}
          277  +do_test misc1-10.3 {
          278  +  regsub "x0>=0" $::where "x0=0" ::where
          279  +  catchsql "DELETE FROM manycol $::where"
          280  +} {0 {}}
          281  +do_test misc1-10.4 {
          282  +  execsql {SELECT count(*) FROM manycol}
          283  +} {8}
          284  +do_test misc1-10.5 {
          285  +  catchsql "DELETE FROM manycol $::where AND rowid>0"
          286  +} {1 {WHERE clause too complex - no more than 100 terms allowed}}
          287  +do_test misc1-10.6 {
          288  +  execsql {SELECT x1 FROM manycol WHERE x0=100}
          289  +} {101}
          290  +do_test misc1-10.7 {
          291  +  regsub "x0=0" $::where "x0=100" ::where
          292  +  catchsql "UPDATE manycol SET x1=x1+1 $::where"
          293  +} {0 {}}
          294  +do_test misc1-10.8 {
          295  +  execsql {SELECT x1 FROM manycol WHERE x0=100}
          296  +} {102}
          297  +do_test misc1-10.9 {
          298  +  catchsql "UPDATE manycol SET x1=x1+1 $::where AND rowid>0"
          299  +} {1 {WHERE clause too complex - no more than 100 terms allowed}}
          300  +do_test misc1-10.10 {
          301  +  execsql {SELECT x1 FROM manycol WHERE x0=100}
          302  +} {102}
   260    303   
   261    304   finish_test