Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1q1mWk-0001Lm-WF for pgsql-hackers@arkaria.postgresql.org; Wed, 24 May 2023 11:19:35 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1q1mWj-00036Z-Bp for pgsql-hackers@arkaria.postgresql.org; Wed, 24 May 2023 11:19:33 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1q1mWj-00036P-2e for pgsql-hackers@lists.postgresql.org; Wed, 24 May 2023 11:19:33 +0000 Received: from mail-yw1-x112c.google.com ([2607:f8b0:4864:20::112c]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1q1mWf-001rJY-Bg for pgsql-hackers@postgresql.org; Wed, 24 May 2023 11:19:32 +0000 Received: by mail-yw1-x112c.google.com with SMTP id 00721157ae682-561c1ae21e7so11612687b3.0 for ; Wed, 24 May 2023 04:19:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1684927168; x=1687519168; h=cc:to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to; bh=UacNgG3qOs0mowAOj5DGc0rb2q462YYlsyst+IFKbVc=; b=H8A19doTwwVU/mvnnE6Rw8x8EDwpkjOthjZaF7IAz9t3L3nJJbcVA3v7reVg8Y/Qfq REjpGPA90fmgsgOT2eY0ofwAH5rFjLl1FBcrqe9LcEeQPCsf8WqlSVUoERakKpCgF3fn Cdn/xtdY8MaEdN/T4qayEzztVz3gw9CcVc6aqJeJoL+BRiKrCSl3Lmb7yFSb9boyLhCG GbDUxJ9FBTxWEnATmhgnj953Ouw8iicWUorch5BgTWdtRVv15tHPLOUBI1pu6tUQl3dR Z5acepYsd2AnRww7AYDv33s2/m7xsAY4FiQpF27n9qh/PJae+B/KSmxs19Zvv7UeMAT+ KzjQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1684927168; x=1687519168; h=cc:to:subject:message-id:date:from:mime-version:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=UacNgG3qOs0mowAOj5DGc0rb2q462YYlsyst+IFKbVc=; b=Dw9RMDFeOPPNgcaaK/T6QZ9tgmjS1DGkRfgEbGVlbke/iifRt3y5pGDPlnLuaEz+ak Fw7HW0bWps5THRY1flTHOGaYz8qZtJMcRlUaIibK8xw3l/z6A2BOdqQm/ZzPi3bUTFOK way8JJGID6caPAyafFw+/5w3vvjFbctZ+LJTDmUzFz0PHrJGij22U0bes6laCDUKoB5I KKpBnPc+RuJhbZfLFq/0icmPHy58FW/eGQs4DuUm6KoXXyTSXmgl/8miC+52OpZ4G9zf USfEjEF4X8Y9POo5thvThCwa2OScD5pn4B9Kd8PEcsyo2VNDz5vfqKh6S1veetjsuUYE 2JOg== X-Gm-Message-State: AC+VfDzEOcD3hNRB3GKfNlEW05MTuxPapuR3y32ijyaSKVxgQouaMeZZ 000R5QBoeL+sUFKUVjydGbUH3LadqyDa5lXaABzEY6n6MN8= X-Google-Smtp-Source: ACHHUZ6JzlQE7UuIgclSk5zmNDNLCkLPSmTrxeG6bRZr2t0OPwGB3H72VGO9LtlnLBk0buOEcsJqXcOWH7OJvZAqGc8= X-Received: by 2002:a25:ac46:0:b0:ba8:5fd6:e657 with SMTP id r6-20020a25ac46000000b00ba85fd6e657mr18910104ybd.49.1684927167890; Wed, 24 May 2023 04:19:27 -0700 (PDT) MIME-Version: 1.0 From: Richard Guo Date: Wed, 24 May 2023 19:19:16 +0800 Message-ID: Subject: Wrong results due to missing quals To: PostgreSQL-development Cc: Tom Lane Content-Type: multipart/alternative; boundary="0000000000005087e305fc6ead53" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --0000000000005087e305fc6ead53 Content-Type: text/plain; charset="UTF-8" Testing with SQLancer reports a wrong results issue on master and I reduced it to the repro query below. create table t (a int, b int); explain (costs off) select * from t t1 left join (t t2 left join t t3 full join t t4 on false on false) left join t t5 on t2.a = t5.a on t2.b = 1; QUERY PLAN -------------------------------------------------- Nested Loop Left Join -> Seq Scan on t t1 -> Materialize -> Nested Loop Left Join -> Nested Loop Left Join Join Filter: false -> Seq Scan on t t2 Filter: (b = 1) -> Result One-Time Filter: false -> Materialize -> Seq Scan on t t5 (12 rows) So the qual 't2.a = t5.a' is missing. I looked into it and found that both clones of this joinqual are rejected by clause_is_computable_at, because their required_relids do not include the outer join of t2/(t3/t4), and meanwhile include nullable rels of this outer join. I think the root cause is that, as Tom pointed out in [1], we're not maintaining required_relids very accurately. In b9c755a2, we make clause_is_computable_at test required_relids for clone clauses. I think this is how this issue sneaks in. To fix it, it seems to me that the ideal way would be to always compute accurate required_relids. But I'm not sure how difficult it is. [1] https://www.postgresql.org/message-id/395264.1684698283%40sss.pgh.pa.us Thanks Richard --0000000000005087e305fc6ead53 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Testing with SQLancer reports a wrong results issue on mas= ter and I
reduced it to the repro query below.

create table t (a = int, b int);

explain (costs off)
select * from t t1 left join
= =C2=A0 =C2=A0 (t t2 left join t t3 full join t t4 on false on false)
=C2= =A0 =C2=A0 left join t t5 on t2.a =3D t5.a
on t2.b =3D 1;
=C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 QUERY PLAN
-= -------------------------------------------------
=C2=A0Nested Loop Left= Join
=C2=A0 =C2=A0-> =C2=A0Seq Scan on t t1
=C2=A0 =C2=A0-> = =C2=A0Materialize
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0-> =C2=A0Nested L= oop Left Join
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0-&g= t; =C2=A0Nested Loop Left Join
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Join Filter: false
=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0-> =C2=A0Seq = Scan on t t2
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Filter: (b =3D 1)
=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0-> =C2=A0R= esult
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0One-Time Filter: false
=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0-> =C2=A0Materialize
=C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0-> =C2= =A0Seq Scan on t t5
(12 rows)

So the qual 't2.a =3D t5.a'= is missing.

I looked into it and found that both clones of this joi= nqual are
rejected by clause_is_computable_at, because their required_re= lids do
not include the outer join of t2/(t3/t4), and meanwhile include = nullable
rels of this outer join.

I think the root cause is that,= as Tom pointed out in [1], we're not
maintaining required_relids ve= ry accurately.=C2=A0 In b9c755a2, we make
clause_is_computable_at test r= equired_relids for clone clauses.=C2=A0 I think
this is how this issue s= neaks in.

To fix it, it seems to me that the ideal way would be to a= lways compute
accurate required_relids.=C2=A0 But I'm not sure how d= ifficult it is.

[1] https://www.postgresql.org/message-id/3= 95264.1684698283%40sss.pgh.pa.us

Thanks
Richard
--0000000000005087e305fc6ead53--