From daa6e78e4b810eff826f995aa52f9e38197f1b7e Mon Sep 17 00:00:00 2001 From: Jo <46752250+georgesittas@users.noreply.github.com> Date: Mon, 14 Oct 2024 18:24:44 +0300 Subject: [PATCH] Fix(optimizer): handle subquery predicate substitution correctly in de morgan's rule (#4240) --- sqlglot/optimizer/simplify.py | 14 +++++++++++--- tests/fixtures/optimizer/simplify.sql | 3 +++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/sqlglot/optimizer/simplify.py b/sqlglot/optimizer/simplify.py index bafc86238..68a4a1501 100644 --- a/sqlglot/optimizer/simplify.py +++ b/sqlglot/optimizer/simplify.py @@ -206,6 +206,11 @@ def rewrite_between(expression: exp.Expression) -> exp.Expression: exp.NEQ: exp.EQ, } +COMPLEMENT_SUBQUERY_PREDICATES = { + exp.All: exp.Any, + exp.Any: exp.All, +} + def simplify_not(expression): """ @@ -218,9 +223,12 @@ def simplify_not(expression): if is_null(this): return exp.null() if this.__class__ in COMPLEMENT_COMPARISONS: - return COMPLEMENT_COMPARISONS[this.__class__]( - this=this.this, expression=this.expression - ) + right = this.expression + complement_subquery_predicate = COMPLEMENT_SUBQUERY_PREDICATES.get(right.__class__) + if complement_subquery_predicate: + right = complement_subquery_predicate(this=right.this) + + return COMPLEMENT_COMPARISONS[this.__class__](this=this.this, expression=right) if isinstance(this, exp.Paren): condition = this.unnest() if isinstance(condition, exp.And): diff --git a/tests/fixtures/optimizer/simplify.sql b/tests/fixtures/optimizer/simplify.sql index fa2dc7964..1842e5550 100644 --- a/tests/fixtures/optimizer/simplify.sql +++ b/tests/fixtures/optimizer/simplify.sql @@ -140,6 +140,9 @@ TRUE; COALESCE(x, y) <> ALL (SELECT z FROM w); COALESCE(x, y) <> ALL (SELECT z FROM w); +SELECT NOT (2 <> ALL (SELECT 2 UNION ALL SELECT 3)); +SELECT 2 = ANY(SELECT 2 UNION ALL SELECT 3); + -------------------------------------- -- Absorption --------------------------------------