SQLite

Check-in [8c856404]
Login

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

Overview
Comment:Ensure sqlite3WindowRewrite() is called on a SELECT statement before any terms aremoved from it as part of IN() clause processing. Fix for [f00d096ca].
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 8c856404b4e98d295449a4e89a41495dc007319a8e9c35c1a763718d7c5f67e8
User & Date: dan 2019-12-22 17:32:25
Context
2019-12-22
18:06
When parsing a CREATE TABLE from the sqlite_master table, delete the CHECK constraints if there are any errors, since there might otherwise be attempts to use those CHECK constraints if PRAGMA writable_schema=ON is set. This undoes the fix in check-in [ea721b34477ab8b4] for a more general solution. (check-in: a982e643 user: drh tags: trunk)
17:32
Ensure sqlite3WindowRewrite() is called on a SELECT statement before any terms aremoved from it as part of IN() clause processing. Fix for [f00d096ca]. (check-in: 8c856404 user: dan tags: trunk)
14:29
Fix "PRAGMA data_version" so that it works the same way with locking_mode=PERSIST and journal_mode=PERSIST configured. Fix for 7a458c2a5f. (check-in: 45748e2d user: dan tags: trunk)
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/wherecode.c.

411
412
413
414
415
416
417


















418
419
420
421
422
423
424
425
static Expr *removeUnindexableInClauseTerms(
  Parse *pParse,        /* The parsing context */
  int iEq,              /* Look at loop terms starting here */
  WhereLoop *pLoop,     /* The current loop */
  Expr *pX              /* The IN expression to be reduced */
){
  sqlite3 *db = pParse->db;


















  Expr *pNew = sqlite3ExprDup(db, pX, 0);
  if( db->mallocFailed==0 ){
    ExprList *pOrigRhs = pNew->x.pSelect->pEList;  /* Original unmodified RHS */
    ExprList *pOrigLhs = pNew->pLeft->x.pList;     /* Original unmodified LHS */
    ExprList *pRhs = 0;         /* New RHS after modifications */
    ExprList *pLhs = 0;         /* New LHS after mods */
    int i;                      /* Loop counter */
    Select *pSelect;            /* Pointer to the SELECT on the RHS */







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|







411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
static Expr *removeUnindexableInClauseTerms(
  Parse *pParse,        /* The parsing context */
  int iEq,              /* Look at loop terms starting here */
  WhereLoop *pLoop,     /* The current loop */
  Expr *pX              /* The IN expression to be reduced */
){
  sqlite3 *db = pParse->db;
  Expr *pNew;
#ifndef SQLITE_OMIT_WINDOWFUNC
  /* The SELECT statement at pX->x.pSelect has already been resolved. This
  ** means that its window functions have already been identified and 
  ** linked into the Select.pWin list. However, if there are multiple 
  ** window functions and they do not all use the same window frame, only
  ** those that use the same window frame as the first resolved are listed
  ** in Select.pWin. Any others are delegated to sub-selects created by the 
  ** call to sqlite3WindowRewrite() made when coding the SELECT statement.
  ** But - sqlite3WindowRewrite() is a no-op if Select.pWin==0. And if 
  ** removing the unindexable terms happens to remove all window functions
  ** in the Select.pWin list, then Select.pWin ends up set to NULL - meaning
  ** that the other window functions are never processed. To work around
  ** this, ensure that sqlite3WindowRewrite() has been called to create the
  ** required sub-selects before the unindexable terms are removed. See
  ** ticket #f00d096ca.  */
  if( sqlite3WindowRewrite(pParse, pX->x.pSelect) ) return 0;
#endif
  pNew = sqlite3ExprDup(db, pX, 0);
  if( db->mallocFailed==0 ){
    ExprList *pOrigRhs = pNew->x.pSelect->pEList;  /* Original unmodified RHS */
    ExprList *pOrigLhs = pNew->pLeft->x.pList;     /* Original unmodified LHS */
    ExprList *pRhs = 0;         /* New RHS after modifications */
    ExprList *pLhs = 0;         /* New LHS after mods */
    int i;                      /* Loop counter */
    Select *pSelect;            /* Pointer to the SELECT on the RHS */

Changes to test/window2.tcl.

443
444
445
446
447
448
449















450
451
452
453
  INSERT INTO t1 VALUES(2, 4);
  INSERT INTO t1 VALUES(1, 5);
}

execsql_float_test 5.1 {
  SELECT avg(x) OVER (ORDER BY y) AS z FROM t1 ORDER BY z;
}
















finish_test









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
  INSERT INTO t1 VALUES(2, 4);
  INSERT INTO t1 VALUES(1, 5);
}

execsql_float_test 5.1 {
  SELECT avg(x) OVER (ORDER BY y) AS z FROM t1 ORDER BY z;
}

==========

execsql_test 6.0 {
  DROP TABLE IF EXISTS t0;
  CREATE TABLE t0(c0 INTEGER UNIQUE);
  INSERT INTO t0 VALUES(0);
}
execsql_test 6.1 {
  SELECT DENSE_RANK() OVER(), LAG(0) OVER() FROM t0;
}
execsql_test 6.2 {
  SELECT * FROM t0 WHERE 
      (0, t0.c0) IN (SELECT DENSE_RANK() OVER(), LAG(0) OVER() FROM t0);
} 

finish_test


Changes to test/window2.test.

925
926
927
928
929
930
931

















932
933
    if {[set r]<([set r2]-0.0001) || [set r]>([set r2]+0.0001)} {
      error "list element [set i] does not match: got=[set r] expected=[set r2]"
    }
    incr i
  }
  set {} {}
} {}


















finish_test







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
    if {[set r]<([set r2]-0.0001) || [set r]>([set r2]+0.0001)} {
      error "list element [set i] does not match: got=[set r] expected=[set r2]"
    }
    incr i
  }
  set {} {}
} {}

#==========================================================================

do_execsql_test 6.0 {
  DROP TABLE IF EXISTS t0;
  CREATE TABLE t0(c0 INTEGER UNIQUE);
  INSERT INTO t0 VALUES(0);
} {}

do_execsql_test 6.1 {
  SELECT DENSE_RANK() OVER(), LAG(0) OVER() FROM t0;
} {1 {}}

do_execsql_test 6.2 {
  SELECT * FROM t0 WHERE 
      (0, t0.c0) IN (SELECT DENSE_RANK() OVER(), LAG(0) OVER() FROM t0);
} {}

finish_test

Changes to test/windowfault.test.

226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244

















245
246
247
248
249

reset_db
do_execsql_test 10.0 {
  CREATE TABLE t1(a, b, c, d);
  CREATE TABLE t2(a, b, c, d);
}

do_faultsim_test 1 -faults oom* -prep {
} -body {
  execsql {
    SELECT row_number() OVER win
    FROM t1
    WINDOW win AS (
      ORDER BY (
        SELECT percent_rank() OVER win2 FROM t2
        WINDOW win2 AS (ORDER BY a)
      )
    )
  }

















} -test {
  faultsim_test_result {0 {}}
}

finish_test







|











>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266

reset_db
do_execsql_test 10.0 {
  CREATE TABLE t1(a, b, c, d);
  CREATE TABLE t2(a, b, c, d);
}

do_faultsim_test 10 -faults oom* -prep {
} -body {
  execsql {
    SELECT row_number() OVER win
    FROM t1
    WINDOW win AS (
      ORDER BY (
        SELECT percent_rank() OVER win2 FROM t2
        WINDOW win2 AS (ORDER BY a)
      )
    )
  }
} -test {
  faultsim_test_result {0 {}}
}

reset_db
do_execsql_test 11.0 {
  DROP TABLE IF EXISTS t0;
  CREATE TABLE t0(c0 INTEGER UNIQUE);
  INSERT INTO t0 VALUES(0);
} {}

do_faultsim_test 11 -faults oom* -prep {
} -body {
  execsql {
    SELECT * FROM t0 WHERE 
      (0, t0.c0) IN (SELECT DENSE_RANK() OVER(), LAG(0) OVER() FROM t0);
  }
} -test {
  faultsim_test_result {0 {}}
}

finish_test