@@ -234,7 +234,8 @@ public function join($fromAlias, $join, $alias, $condition = null, $joinMode = P
234234 $ this ->splitQueries [$ partition ->name ] = new PartitionQuery (
235235 $ this ->newQuery (),
236236 $ joinCondition ->fromAlias ?? $ joinCondition ->fromColumn , $ joinCondition ->toAlias ?? $ joinCondition ->toColumn ,
237- $ joinMode
237+ $ joinMode ,
238+ $ alias ,
238239 );
239240 $ this ->splitQueries [$ partition ->name ]->query ->from ($ join , $ alias );
240241 $ this ->ensureSelect ($ joinCondition ->fromColumn , $ joinCondition ->fromAlias );
@@ -269,7 +270,8 @@ public function join($fromAlias, $join, $alias, $condition = null, $joinMode = P
269270 $ this ->splitQueries [$ partitionName ] = new PartitionQuery (
270271 $ this ->newQuery (),
271272 $ joinCondition ->fromAlias ?? $ joinCondition ->fromColumn , $ joinCondition ->toAlias ?? $ joinCondition ->toColumn ,
272- $ joinMode
273+ $ joinMode ,
274+ $ alias ,
273275 );
274276 $ this ->ensureSelect ($ joinCondition ->fromColumn , $ joinCondition ->fromAlias );
275277 $ this ->ensureSelect ($ joinCondition ->toColumn , $ joinCondition ->toAlias );
@@ -349,11 +351,14 @@ public function andWhere(...$where) {
349351 if ($ where ) {
350352 foreach ($ this ->splitPredicatesByParts ($ where ) as $ alias => $ predicates ) {
351353 if (isset ($ this ->splitQueries [$ alias ])) {
354+ $ mergedPredicate = new CompositeExpression (CompositeExpression::TYPE_AND , $ predicates );
352355 // when there is a condition on a table being left-joined it starts to behave as if it's an inner join
353356 // since any joined column that doesn't have the left part will not match the condition
354357 // when there the condition is `$joinToColumn IS NULL` we instead mark the query as excluding the left half
355358 if ($ this ->splitQueries [$ alias ]->joinMode === PartitionQuery::JOIN_MODE_LEFT ) {
356- $ this ->splitQueries [$ alias ]->joinMode = PartitionQuery::JOIN_MODE_INNER ;
359+ if ($ this ->constraintsTableNotNull ($ mergedPredicate , $ this ->splitQueries [$ alias ]->joinToTableAlias )) {
360+ $ this ->splitQueries [$ alias ]->joinMode = PartitionQuery::JOIN_MODE_INNER ;
361+ }
357362
358363 $ column = $ this ->quoteHelper ->quoteColumnName ($ this ->splitQueries [$ alias ]->joinToColumn );
359364 foreach ($ predicates as $ predicate ) {
@@ -374,6 +379,33 @@ public function andWhere(...$where) {
374379 return $ this ;
375380 }
376381
382+ /**
383+ * Check if any part of a predicates constraints any part of a table to be not null
384+ *
385+ * @return bool
386+ */
387+ private function constraintsTableNotNull ($ predicate , string $ table ): bool {
388+ if ($ predicate instanceof CompositeExpression) {
389+ if ($ predicate ->getType () === CompositeExpression::TYPE_OR ) {
390+ $ all = true ;
391+ foreach ($ predicate ->getParts () as $ part ) {
392+ $ all = $ all && $ this ->constraintsTableNotNull ($ part , $ table );
393+ }
394+ return $ all ;
395+ } else {
396+ foreach ($ predicate ->getParts () as $ part ) {
397+ if ($ this ->constraintsTableNotNull ($ part , $ table )) {
398+ return true ;
399+ }
400+ }
401+ return false ;
402+ }
403+ } else {
404+ $ predicate = (string )$ predicate ;
405+ return str_starts_with ($ predicate , "` $ table`. " ) && !str_ends_with ($ predicate , 'IS NULL ' );
406+ }
407+ }
408+
377409 private function getPartitionForPredicate (string $ predicate ): ?PartitionSplit {
378410 foreach ($ this ->partitions as $ partition ) {
379411
0 commit comments