Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Do not remove the EP_CanBeNull flag from expressions during a LEFT JOIN strength reduction if the query also contains a RIGHT JOIN. Fix for the problem identified by [forum/forumpost/b40696f50145d21c|forum post b40696f50145d21c]. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
b1be2259e2e08ec22a88bc9a18b3ab4d |
User & Date: | drh 2022-06-13 12:42:24 |
Context
2022-06-14
| ||
21:34 | Add missing SQLITE_FCNTL_SIZE_HINT call to a path taken during transaction rollback. (check-in: 6c3266c1 user: dan tags: trunk) | |
19:12 | Attempt to enhance fuzzcheck to do some simple invariant testing on queries. This is an incremental check-in for a work-in-progress. (check-in: ce2d7801 user: drh tags: query-invariant-tests) | |
2022-06-13
| ||
12:42 | Do not remove the EP_CanBeNull flag from expressions during a LEFT JOIN strength reduction if the query also contains a RIGHT JOIN. Fix for the problem identified by [forum/forumpost/b40696f50145d21c|forum post b40696f50145d21c]. (check-in: b1be2259 user: drh tags: trunk) | |
2022-06-10
| ||
16:41 | The same restrictions on the use of WHERE clause terms to drive indexes in the presence of RIGHT JOINs also apply to the use of WHERE clause terms to manufacture automatic indexes. This fixes a problem identified by forum post 51e6959f61. (check-in: 342c501f user: drh tags: trunk) | |
Changes
Changes to src/select.c.
︙ | ︙ | |||
425 426 427 428 429 430 431 432 | } /* Undo the work of sqlite3SetJoinExpr(). In the expression p, convert every ** term that is marked with EP_OuterON and w.iJoin==iTable into ** an ordinary term that omits the EP_OuterON mark. ** ** This happens when a LEFT JOIN is simplified into an ordinary JOIN. */ | > > > > > > | | | | | 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 | } /* Undo the work of sqlite3SetJoinExpr(). In the expression p, convert every ** term that is marked with EP_OuterON and w.iJoin==iTable into ** an ordinary term that omits the EP_OuterON mark. ** ** This happens when a LEFT JOIN is simplified into an ordinary JOIN. ** ** If nullable is true, that means that Expr p might evaluate to NULL even ** if it is a reference to a NOT NULL column. This can happen, for example, ** if the table that p references is on the left side of a RIGHT JOIN. ** If nullable is true, then take care to not remove the EP_CanBeNull bit. ** See forum thread https://sqlite.org/forum/forumpost/b40696f50145d21c */ static void unsetJoinExpr(Expr *p, int iTable, int nullable){ while( p ){ if( ExprHasProperty(p, EP_OuterON) && (iTable<0 || p->w.iJoin==iTable) ){ ExprClearProperty(p, EP_OuterON); ExprSetProperty(p, EP_InnerON); } if( p->op==TK_COLUMN && p->iTable==iTable && !nullable ){ ExprClearProperty(p, EP_CanBeNull); } if( p->op==TK_FUNCTION ){ assert( ExprUseXList(p) ); if( p->x.pList ){ int i; for(i=0; i<p->x.pList->nExpr; i++){ unsetJoinExpr(p->x.pList->a[i].pExpr, iTable, nullable); } } } unsetJoinExpr(p->pLeft, iTable, nullable); p = p->pRight; } } /* ** This routine processes the join information for a SELECT statement. ** |
︙ | ︙ | |||
5063 5064 5065 5066 5067 5068 5069 | if( sqlite3ExprIsTableConstraint(pWhere, pSrc) ){ nChng++; pSubq->selFlags |= SF_PushDown; while( pSubq ){ SubstContext x; pNew = sqlite3ExprDup(pParse->db, pWhere, 0); | | | 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 | if( sqlite3ExprIsTableConstraint(pWhere, pSrc) ){ nChng++; pSubq->selFlags |= SF_PushDown; while( pSubq ){ SubstContext x; pNew = sqlite3ExprDup(pParse->db, pWhere, 0); unsetJoinExpr(pNew, -1, 1); x.pParse = pParse; x.iTable = pSrc->iCursor; x.iNewTable = pSrc->iCursor; x.isOuterJoin = 0; x.pEList = pSubq->pEList; pNew = substExpr(&x, pNew); #ifndef SQLITE_OMIT_WINDOWFUNC |
︙ | ︙ | |||
6747 6748 6749 6750 6751 6752 6753 | if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))==JT_LEFT && sqlite3ExprImpliesNonNullRow(p->pWhere, pItem->iCursor) && OptimizationEnabled(db, SQLITE_SimplifyJoin) ){ SELECTTRACE(0x100,pParse,p, ("LEFT-JOIN simplifies to JOIN on term %d\n",i)); pItem->fg.jointype &= ~(JT_LEFT|JT_OUTER); | | > | 6753 6754 6755 6756 6757 6758 6759 6760 6761 6762 6763 6764 6765 6766 6767 6768 | if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))==JT_LEFT && sqlite3ExprImpliesNonNullRow(p->pWhere, pItem->iCursor) && OptimizationEnabled(db, SQLITE_SimplifyJoin) ){ SELECTTRACE(0x100,pParse,p, ("LEFT-JOIN simplifies to JOIN on term %d\n",i)); pItem->fg.jointype &= ~(JT_LEFT|JT_OUTER); unsetJoinExpr(p->pWhere, pItem->iCursor, pTabList->a[0].fg.jointype & JT_LTORJ); } /* No futher action if this term of the FROM clause is no a subquery */ if( pSub==0 ) continue; /* Catch mismatch in the declared columns of a view and the number of ** columns in the SELECT on the RHS */ |
︙ | ︙ |
Changes to test/join8.test.
︙ | ︙ | |||
690 691 692 693 694 695 696 | SELECT 99 FROM t1 LEFT JOIN t2 ON true RIGHT JOIN t3 ON true RIGHT JOIN t4 ON true WHERE a=b; } {} | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 | SELECT 99 FROM t1 LEFT JOIN t2 ON true RIGHT JOIN t3 ON true RIGHT JOIN t4 ON true WHERE a=b; } {} # 2022-06-13 # https://sqlite.org/forum/forumpost/b40696f501 # # This optimization that converts "x ISNULL" into "FALSE" when column "x" has a # NOT NULL constraint is too aggresive if the query contains RIGHT JOIN. # reset_db db null - do_execsql_test join8-23000 { CREATE TABLE t1(a TEXT); INSERT INTO t1 VALUES('c'); CREATE TABLE t2(b TEXT, c TEXT NOT NULL); INSERT INTO t2 VALUES('a', 'b'); CREATE TABLE t3(d TEXT); INSERT INTO t3 VALUES('x'); CREATE TABLE t4(e TEXT); INSERT INTO t4 VALUES('y'); } do_execsql_test join8-23010 { SELECT * FROM t1 LEFT JOIN t2 ON TRUE JOIN t3 ON c='' RIGHT JOIN t4 ON b=''; } {- - - - y} do_execsql_test join8-23020 { SELECT * FROM t1 LEFT JOIN t2 ON TRUE JOIN t3 ON c='' RIGHT JOIN t4 ON b='' WHERE d ISNULL } {- - - - y} finish_test |