SQLite

Check-in [274e244c]
Login

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

Overview
Comment:The query flattener should not run if the subquery is a compound that contains a RIGHT JOIN in any arm and the subquery is not the first element of the outer query. Otherwise, prior elements of the outer query will not have the JT_LTORJ flag set. Fix for the problem reported in forum post 174afeae5734d42d.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 274e244c85935084b2f0f85176283f018bf9b74e7703f985bd5a2f6f8bdcff5d
User & Date: drh 2022-07-13 15:52:15
Context
2022-07-13
21:02
Add new script test/testrunner.tcl. For running a set of test scripts using multiple processes. (check-in: 0122e93d user: dan tags: trunk)
16:06
The query flattener should not run if the subquery is a compound that contains a RIGHT JOIN in any arm and the subquery is not the first element of the outer query. Otherwise, prior elements of the outer query will not have the JT_LTORJ flag set. Fix for the problem reported in forum post 174afeae5734d42d. (check-in: cf9ed7f2 user: drh tags: branch-3.39)
15:52
The query flattener should not run if the subquery is a compound that contains a RIGHT JOIN in any arm and the subquery is not the first element of the outer query. Otherwise, prior elements of the outer query will not have the JT_LTORJ flag set. Fix for the problem reported in forum post 174afeae5734d42d. (check-in: 274e244c user: drh tags: trunk)
2022-07-12
15:53
Renamed the SQLITE_SHELL_WASM_WEB_MODE to SQLITE_SHELL_FIDDLE, which seems to be more in line with project convensions and indicates that that flag is only intended for /fiddle mode, as opposed to arbitrary wasm-on-the-web use. (check-in: d1d019bf user: stephan tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/select.c.
4116
4117
4118
4119
4120
4121
4122



4123
4124
4125
4126
4127
4128
4129
**              or DISTINCT, and
**        (17c) every term within the subquery compound must have a FROM clause
**        (17d) the outer query may not be
**              (17d1) aggregate, or
**              (17d2) DISTINCT
**        (17e) the subquery may not contain window functions, and
**        (17f) the subquery must not be the RHS of a LEFT JOIN.



**
**        The parent and sub-query may contain WHERE clauses. Subject to
**        rules (11), (13) and (14), they may also contain ORDER BY,
**        LIMIT and OFFSET clauses.  The subquery cannot use any compound
**        operator other than UNION ALL because all the other compound
**        operators have an implied DISTINCT which is disallowed by
**        restriction (4).







>
>
>







4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
**              or DISTINCT, and
**        (17c) every term within the subquery compound must have a FROM clause
**        (17d) the outer query may not be
**              (17d1) aggregate, or
**              (17d2) DISTINCT
**        (17e) the subquery may not contain window functions, and
**        (17f) the subquery must not be the RHS of a LEFT JOIN.
**        (17g) either the subquery is the first element of the outer
**              query or there are no RIGHT or FULL JOINs in any arm
**              of the subquery.  (This is a duplicate of condition (27b).)
**
**        The parent and sub-query may contain WHERE clauses. Subject to
**        rules (11), (13) and (14), they may also contain ORDER BY,
**        LIMIT and OFFSET clauses.  The subquery cannot use any compound
**        operator other than UNION ALL because all the other compound
**        operators have an implied DISTINCT which is disallowed by
**        restriction (4).
4167
4168
4169
4170
4171
4172
4173
4174




4175
4176
4177
4178
4179
4180
4181
**        function in the select list or ORDER BY clause, flattening
**        is not attempted.
**
**  (26)  The subquery may not be the right operand of a RIGHT JOIN.
**        See also (3) for restrictions on LEFT JOIN.
**
**  (27)  The subquery may not contain a FULL or RIGHT JOIN unless it
**        is the first element of the parent query.




**
**  (28)  The subquery is not a MATERIALIZED CTE.
**
**  (29)  Either the subquery is not the right-hand operand of a join with an
**        ON or USING clause nor the right-hand operand of a NATURAL JOIN, or
**        the right-most table within the FROM clause of the subquery
**        is not part of an outer join.







|
>
>
>
>







4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
**        function in the select list or ORDER BY clause, flattening
**        is not attempted.
**
**  (26)  The subquery may not be the right operand of a RIGHT JOIN.
**        See also (3) for restrictions on LEFT JOIN.
**
**  (27)  The subquery may not contain a FULL or RIGHT JOIN unless it
**        is the first element of the parent query.  This must be the
**        the case if:
**        (27a) the subquery is not compound query, and
**        (27b) the subquery is a compound query and the RIGHT JOIN occurs
**              in any arm of the compound query.  (See also (17g).)
**
**  (28)  The subquery is not a MATERIALIZED CTE.
**
**  (29)  Either the subquery is not the right-hand operand of a join with an
**        ON or USING clause nor the right-hand operand of a NATURAL JOIN, or
**        the right-most table within the FROM clause of the subquery
**        is not part of an outer join.
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
    ** opcode. */
    isOuterJoin = -1;
  }
#endif

  assert( pSubSrc->nSrc>0 );  /* True by restriction (7) */
  if( iFrom>0 && (pSubSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){
    return 0;   /* Restriction (27) */
  }
  if( pSubitem->fg.isCte && pSubitem->u2.pCteUse->eM10d==M10d_Yes ){
    return 0;       /* (28) */
  }

  /* Restriction (29): 
  **
  ** We do not want two constraints on the same term of the flattened
  ** query where one constraint has EP_InnerON and the other is EP_OuterON.
  ** To prevent this, one or the other of the following conditions must be
  ** false:
  **
  **   (29a)  The right-most entry in the FROM clause of the subquery
  **          must not be part of an outer join.
  **
  **   (29b)  The subquery itself must not be the right operand of a 
  **          NATURAL join or a join that as an ON or USING clause.
  **
  ** These conditions are sufficient to keep an EP_OuterON from being
  ** flattened into an EP_InnerON.  Restrictions (3a) and (27) prevent
  ** an EP_InnerON from being flattened into an EP_OuterON.
  */
  if( pSubSrc->nSrc>=2
   && (pSubSrc->a[pSubSrc->nSrc-1].fg.jointype & JT_OUTER)!=0
  ){
    if( (pSubitem->fg.jointype & JT_NATURAL)!=0
     || pSubitem->fg.isUsing







|



















|







4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
    ** opcode. */
    isOuterJoin = -1;
  }
#endif

  assert( pSubSrc->nSrc>0 );  /* True by restriction (7) */
  if( iFrom>0 && (pSubSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){
    return 0;   /* Restriction (27a) */
  }
  if( pSubitem->fg.isCte && pSubitem->u2.pCteUse->eM10d==M10d_Yes ){
    return 0;       /* (28) */
  }

  /* Restriction (29): 
  **
  ** We do not want two constraints on the same term of the flattened
  ** query where one constraint has EP_InnerON and the other is EP_OuterON.
  ** To prevent this, one or the other of the following conditions must be
  ** false:
  **
  **   (29a)  The right-most entry in the FROM clause of the subquery
  **          must not be part of an outer join.
  **
  **   (29b)  The subquery itself must not be the right operand of a 
  **          NATURAL join or a join that as an ON or USING clause.
  **
  ** These conditions are sufficient to keep an EP_OuterON from being
  ** flattened into an EP_InnerON.  Restrictions (3a) and (27a) prevent
  ** an EP_InnerON from being flattened into an EP_OuterON.
  */
  if( pSubSrc->nSrc>=2
   && (pSubSrc->a[pSubSrc->nSrc-1].fg.jointype & JT_OUTER)!=0
  ){
    if( (pSubitem->fg.jointype & JT_NATURAL)!=0
     || pSubitem->fg.isUsing
4353
4354
4355
4356
4357
4358
4359






4360
4361
4362
4363
4364
4365
4366
       || (pSub1->pPrior && pSub1->op!=TK_ALL)                 /* (17a) */
       || pSub1->pSrc->nSrc<1                                  /* (17c) */
#ifndef SQLITE_OMIT_WINDOWFUNC
       || pSub1->pWin                                          /* (17e) */
#endif
      ){
        return 0;






      }
      testcase( pSub1->pSrc->nSrc>1 );
    }

    /* Restriction (18). */
    if( p->pOrderBy ){
      int ii;







>
>
>
>
>
>







4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
       || (pSub1->pPrior && pSub1->op!=TK_ALL)                 /* (17a) */
       || pSub1->pSrc->nSrc<1                                  /* (17c) */
#ifndef SQLITE_OMIT_WINDOWFUNC
       || pSub1->pWin                                          /* (17e) */
#endif
      ){
        return 0;
      }
      if( iFrom>0 && (pSub1->pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){
        /* Without this restriction, the JT_LTORJ flag would end up being
        ** omitted on left-hand tables of the right join that is being
        ** flattened. */
        return 0;   /* Restrictions (17g), (27b) */
      }
      testcase( pSub1->pSrc->nSrc>1 );
    }

    /* Restriction (18). */
    if( p->pOrderBy ){
      int ii;
Changes to test/join8.test.
782
783
784
785
786
787
788















789
do_execsql_test join8-25010 {
  SELECT * FROM t1 LEFT JOIN t2 ON true JOIN t3 ON (b2 IN (a1)) FULL JOIN t4 ON true;
} {- - - - - x}
do_execsql_test join8-25020 {
  SELECT 1 FROM t1 LEFT JOIN t2 ON true JOIN t3 ON (b2 IN (a1)) FULL JOIN t4 ON true;
} {1}
















finish_test







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

782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
do_execsql_test join8-25010 {
  SELECT * FROM t1 LEFT JOIN t2 ON true JOIN t3 ON (b2 IN (a1)) FULL JOIN t4 ON true;
} {- - - - - x}
do_execsql_test join8-25020 {
  SELECT 1 FROM t1 LEFT JOIN t2 ON true JOIN t3 ON (b2 IN (a1)) FULL JOIN t4 ON true;
} {1}

# 2022-07-13
# forum/forumpost/174afeae57
#
reset_db
db null -
do_execsql_test join8-26000 {
  CREATE TABLE t1(a INT);
  CREATE TABLE t2(b INT, c INT);
  CREATE VIEW t3(d) AS SELECT NULL FROM t2 FULL OUTER JOIN t1 ON c=a UNION ALL SELECT b FROM t2;
  INSERT INTO t1(a) VALUES (NULL);
  INSERT INTO t2(b, c) VALUES (99, NULL);
  SELECT DISTINCT b, c, d FROM t2, t3 WHERE b<>0
   UNION SELECT DISTINCT b, c, d FROM t2, t3 WHERE b ISNULL;
} {99 - - 99 - 99}

finish_test