/ Check-in [b7810062]
Login

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

Overview
Comment:Fix to the rowvalue logic that avoids disabling rowvalue inequality contraints on a virtual table when the virtual table sets the omit flag. The logic has been incorrect since row-values were added. However, this does not come up often as very few virtual tables implement inequality constraints using the omit flag. Ticket [f096d191b6641daa]
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: b7810062ec2489e1c5ca6638dbeb0892e4ce376c5c1834a31d1a332ebab8a871
User & Date: drh 2019-12-05 21:46:23
References
2019-12-06
11:48
The check-in [b7810062ec2489e1] was not quite right in that it allowed an oversized shift operation (which is UB in C) on some obscure inputs. OSSFuzz found the problem for us overnight. (check-in: 62f2235a user: drh tags: trunk)
Context
2019-12-06
01:23
Do not allow UPSERT of a view. (check-in: ebf897e8 user: drh tags: trunk)
2019-12-05
21:46
Fix to the rowvalue logic that avoids disabling rowvalue inequality contraints on a virtual table when the virtual table sets the omit flag. The logic has been incorrect since row-values were added. However, this does not come up often as very few virtual tables implement inequality constraints using the omit flag. Ticket [f096d191b6641daa] (check-in: b7810062 user: drh tags: trunk)
18:29
Documentation update: Clarify that the sqlite3_index_info.aConstraintUsage.omit flag is a hint only and that the code generator is not obligated to follow the hint. (check-in: 7d3e3f6e user: drh tags: trunk)
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Added ext/rtree/rtreeI.test.





















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# 2019-12-05
#
# 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.
#
#***********************************************************************
# Additional test cases

if {![info exists testdir]} {
  set testdir [file join [file dirname [info script]] .. .. test]
} 
source [file join [file dirname [info script]] rtree_util.tcl]
source $testdir/tester.tcl
ifcapable !rtree { finish_test ; return }

# The following is a test of rowvalue handling on virtual tables that
# deal with inequalities and that set the OMIT flag on terms of the
# WHERE clause.  This is not specific to rtree.  We just use rtree because
# it is a convenient test platform since it has all the right
# characteristics.
#
do_execsql_test rtreeI-1.10 {
  CREATE TABLE t1(a);
  INSERT INTO t1 VALUES(2);
  CREATE VIRTUAL TABLE t2 USING rtree(id,x0,x1);
  INSERT INTO t2(id,x0,x1) VALUES(1,2,3);
} {}
do_execsql_test rtreeI-1.20 {
  SELECT 123 FROM t1, t2 WHERE (a,0)>(x0,0);
} {}
do_execsql_test rtreeI-1.21 {
  SELECT 123 FROM t1, t2 WHERE (a,0.1)>(x0,0);
} {123}
do_execsql_test rtreeI-1.22 {
  SELECT 123 FROM t1, t2 WHERE (a,0)>=(x0,0);
} {123}
do_execsql_test rtreeI-1.23 {
  SELECT 123 FROM t1, t2 WHERE (a,0)<=(x0,0);
} {123}
do_execsql_test rtreeI-1.24 {
  SELECT 123 FROM t1, t2 WHERE (a,0)<(x0,0);
} {}
do_execsql_test rtreeI-1.30 {
  SELECT 123 FROM t1, t2 WHERE (x0,0)<(a,0);
} {}
do_execsql_test rtreeI-1.31 {
  SELECT 123 FROM t1, t2 WHERE (x0,0)<(a,0.1);
} {123}
do_execsql_test rtreeI-1.40 {
  SELECT 123 FROM t1, t2 WHERE x1<5 AND id<99 AND (a,0)>(x0,0);
} {}
do_execsql_test rtreeI-1.41 {
  SELECT 123 FROM t1, t2 WHERE x1<5 AND id<99 AND (a,0.5)>(x0,0);
} {123}
do_execsql_test rtreeI-1.42 {
  SELECT 123 FROM t1, t2 WHERE x1<5 AND id<99 AND (a,0)>=(x0,0);
} {123}
do_execsql_test rtreeI-1.43 {
  SELECT 123 FROM t1, t2 WHERE x1<5 AND id<99 AND (a,0)<(x0,0);
} {}
do_execsql_test rtreeI-1.50 {
  SELECT 123 FROM t1, t2 WHERE 5>x1 AND 99>id AND (x0,0)<(a,0);
} {}
do_execsql_test rtreeI-1.51 {
  SELECT 123 FROM t1, t2 WHERE 5>x1 AND 99>id AND (x0,0)<(a,0.5);
} {123}



finish_test

Changes to src/where.c.

1017
1018
1019
1020
1021
1022
1023

1024
1025
1026
1027
1028
1029
1030
1031
....
3198
3199
3200
3201
3202
3203
3204



3205




3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
      assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
      assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
      assert( pTerm->eOperator&(WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_AUX) );

      if( op & (WO_LT|WO_LE|WO_GT|WO_GE)
       && sqlite3ExprIsVector(pTerm->pExpr->pRight) 
      ){

        if( i<16 ) mNoOmit |= (1 << i);
        if( op==WO_LT ) pIdxCons[j].op = WO_LE;
        if( op==WO_GT ) pIdxCons[j].op = WO_GE;
      }
    }

    j++;
  }
................................................................................
      pTerm = &pWC->a[j];
      pNew->prereq |= pTerm->prereqRight;
      assert( iTerm<pNew->nLSlot );
      pNew->aLTerm[iTerm] = pTerm;
      if( iTerm>mxTerm ) mxTerm = iTerm;
      testcase( iTerm==15 );
      testcase( iTerm==16 );



      if( iTerm<16 && pUsage[i].omit ) pNew->u.vtab.omitMask |= 1<<iTerm;




      if( (pTerm->eOperator & WO_IN)!=0 ){
        /* A virtual table that is constrained by an IN clause may not
        ** consume the ORDER BY clause because (1) the order of IN terms
        ** is not necessarily related to the order of output terms and
        ** (2) Multiple outputs from a single IN value will not merge
        ** together.  */
        pIdxInfo->orderByConsumed = 0;
        pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE;
        *pbIn = 1; assert( (mExclude & WO_IN)==0 );
      }
    }
  }
  pNew->u.vtab.omitMask &= ~mNoOmit;

  pNew->nLTerm = mxTerm+1;
  for(i=0; i<=mxTerm; i++){
    if( pNew->aLTerm[i]==0 ){
      /* The non-zero argvIdx values must be contiguous.  Raise an
      ** error if they are not */
      sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName);







>
|







 







>
>
>
|
>
>
>
>












<







1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
....
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225

3226
3227
3228
3229
3230
3231
3232
      assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
      assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
      assert( pTerm->eOperator&(WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_AUX) );

      if( op & (WO_LT|WO_LE|WO_GT|WO_GE)
       && sqlite3ExprIsVector(pTerm->pExpr->pRight) 
      ){
        testcase( j!=i );
        if( j<16 ) mNoOmit |= (1 << j);
        if( op==WO_LT ) pIdxCons[j].op = WO_LE;
        if( op==WO_GT ) pIdxCons[j].op = WO_GE;
      }
    }

    j++;
  }
................................................................................
      pTerm = &pWC->a[j];
      pNew->prereq |= pTerm->prereqRight;
      assert( iTerm<pNew->nLSlot );
      pNew->aLTerm[iTerm] = pTerm;
      if( iTerm>mxTerm ) mxTerm = iTerm;
      testcase( iTerm==15 );
      testcase( iTerm==16 );
      if( iTerm<16 && pUsage[i].omit ){
        if( ((1<<i)&mNoOmit)==0 ){
          testcase( i!=iTerm );
          pNew->u.vtab.omitMask |= 1<<iTerm;
        }else{
          testcase( i!=iTerm );
        }
      }
      if( (pTerm->eOperator & WO_IN)!=0 ){
        /* A virtual table that is constrained by an IN clause may not
        ** consume the ORDER BY clause because (1) the order of IN terms
        ** is not necessarily related to the order of output terms and
        ** (2) Multiple outputs from a single IN value will not merge
        ** together.  */
        pIdxInfo->orderByConsumed = 0;
        pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE;
        *pbIn = 1; assert( (mExclude & WO_IN)==0 );
      }
    }
  }


  pNew->nLTerm = mxTerm+1;
  for(i=0; i<=mxTerm; i++){
    if( pNew->aLTerm[i]==0 ){
      /* The non-zero argvIdx values must be contiguous.  Raise an
      ** error if they are not */
      sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName);