3030import org .apache .doris .nereids .trees .expressions .LessThanEqual ;
3131import org .apache .doris .nereids .trees .expressions .Not ;
3232import org .apache .doris .nereids .trees .expressions .Or ;
33+ import org .apache .doris .nereids .trees .expressions .literal .BooleanLiteral ;
3334import org .apache .doris .nereids .trees .expressions .literal .ComparableLiteral ;
3435import org .apache .doris .nereids .trees .expressions .literal .NullLiteral ;
3536import org .apache .doris .nereids .trees .expressions .visitor .ExpressionVisitor ;
4950import java .util .List ;
5051import java .util .Map ;
5152import java .util .Map .Entry ;
53+ import java .util .Optional ;
5254import java .util .Set ;
5355
5456/**
@@ -144,11 +146,18 @@ public ValueDesc visitNot(Not not, ExpressionRewriteContext context) {
144146 ValueDesc childValue = not .child ().accept (this , context );
145147 if (childValue instanceof DiscreteValue ) {
146148 return new NotDiscreteValue (context , childValue .getReference (), ((DiscreteValue ) childValue ).values );
149+ } else if (childValue instanceof IsNullValue ) {
150+ return new IsNotNullValue (context , childValue .getReference (), not );
147151 } else {
148152 return new UnknownValue (context , not );
149153 }
150154 }
151155
156+ @ Override
157+ public ValueDesc visitIsNull (IsNull isNull , ExpressionRewriteContext context ) {
158+ return new IsNullValue (context , isNull .child ());
159+ }
160+
152161 @ Override
153162 public ValueDesc visitAnd (And and , ExpressionRewriteContext context ) {
154163 return simplify (context , ExpressionUtils .extractConjunction (and ), true );
@@ -273,6 +282,13 @@ private ValueDesc intersectForSameReference(ExpressionRewriteContext context, Ex
273282 result .add (new NotDiscreteValue (context , reference , mergeNotDiscreteValues ));
274283 }
275284 }
285+ if (collector .hasIsNullValue && collector .isNotNullValueOpt .isPresent ()) {
286+ return new UnknownValue (context , BooleanLiteral .FALSE );
287+ } else if (collector .hasIsNullValue ) {
288+ result .add (new IsNullValue (context , reference ));
289+ } else {
290+ collector .isNotNullValueOpt .ifPresent (result ::add );
291+ }
276292 result .addAll (collector .compoundValues );
277293 result .addAll (collector .unknownValues );
278294
@@ -341,6 +357,13 @@ private ValueDesc unionForSameReference(ExpressionRewriteContext context, Expres
341357 result .add (new NotDiscreteValue (context , reference , mergeNotDiscreteValues ));
342358 }
343359
360+ if (collector .hasIsNullValue && collector .isNotNullValueOpt .isPresent ()) {
361+ return new UnknownValue (context , BooleanLiteral .TRUE );
362+ } else if (collector .hasIsNullValue ) {
363+ result .add (new IsNullValue (context , reference ));
364+ } else {
365+ collector .isNotNullValueOpt .ifPresent (result ::add );
366+ }
344367 result .addAll (collector .compoundValues );
345368 result .addAll (collector .unknownValues );
346369
@@ -365,12 +388,18 @@ public interface ValueDescVisitor<R, C> {
365388
366389 R visitNotDiscreteValue (NotDiscreteValue notDiscreteValue , C context );
367390
391+ R visitIsNullValue (IsNullValue isNullValue , C context );
392+
393+ R visitIsNotNullValue (IsNotNullValue isNotNullValue , C context );
394+
368395 R visitCompoundValue (CompoundValue compoundValue , C context );
369396
370397 R visitUnknownValue (UnknownValue unknownValue , C context );
371398 }
372399
373400 private static class ValueDescCollector {
401+ Optional <IsNotNullValue > isNotNullValueOpt = Optional .empty ();
402+ boolean hasIsNullValue = false ;
374403 boolean hasEmptyValue = false ;
375404 List <RangeValue > rangeValues = Lists .newArrayList ();
376405 List <DiscreteValue > discreteValues = Lists .newArrayList ();
@@ -389,6 +418,13 @@ void add(ValueDesc value) {
389418 notDiscreteValues .add ((NotDiscreteValue ) value );
390419 } else if (value instanceof CompoundValue ) {
391420 compoundValues .add ((CompoundValue ) value );
421+ } else if (value instanceof IsNullValue ) {
422+ hasIsNullValue = true ;
423+ } else if (value instanceof IsNotNullValue ) {
424+ IsNotNullValue isNotNullValue = (IsNotNullValue ) value ;
425+ if (!isNotNullValueOpt .isPresent () || isNotNullValue .getNotExpression ().isGeneratedIsNotNull ()) {
426+ isNotNullValueOpt = Optional .of (isNotNullValue );
427+ }
392428 } else {
393429 Preconditions .checkArgument (value instanceof UnknownValue );
394430 unknownValues .add ((UnknownValue ) value );
@@ -532,7 +568,6 @@ public String toString() {
532568 }
533569
534570 /**
535- * use `Set` to wrap `InPredicate`
536571 * for example:
537572 * a not in (1,2,3) => [1,2,3]
538573 */
@@ -551,6 +586,42 @@ protected <R, C> R visit(ValueDescVisitor<R, C> visitor, C context) {
551586 }
552587 }
553588
589+ /**
590+ * a is null
591+ */
592+ public static class IsNullValue extends ValueDesc {
593+
594+ public IsNullValue (ExpressionRewriteContext context , Expression reference ) {
595+ super (context , reference );
596+ }
597+
598+ @ Override
599+ protected <R , C > R visit (ValueDescVisitor <R , C > visitor , C context ) {
600+ return visitor .visitIsNullValue (this , context );
601+ }
602+ }
603+
604+ /**
605+ * a is not null
606+ */
607+ public static class IsNotNullValue extends ValueDesc {
608+ final Not not ;
609+
610+ public IsNotNullValue (ExpressionRewriteContext context , Expression reference , Not not ) {
611+ super (context , reference );
612+ this .not = not ;
613+ }
614+
615+ public Not getNotExpression () {
616+ return this .not ;
617+ }
618+
619+ @ Override
620+ protected <R , C > R visit (ValueDescVisitor <R , C > visitor , C context ) {
621+ return visitor .visitIsNotNullValue (this , context );
622+ }
623+ }
624+
554625 /**
555626 * Represents processing compound predicate.
556627 */
0 commit comments