Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1ultU8-006xFc-PU for pgsql-bugs@arkaria.postgresql.org; Tue, 12 Aug 2025 18:12:32 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1ultU6-0098NG-Q0 for pgsql-bugs@arkaria.postgresql.org; Tue, 12 Aug 2025 18:12:31 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1ultU6-0098N6-Fx for pgsql-bugs@lists.postgresql.org; Tue, 12 Aug 2025 18:12:30 +0000 Received: from sss.pgh.pa.us ([68.162.161.243]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1ultU2-000EFL-0o for pgsql-bugs@lists.postgresql.org; Tue, 12 Aug 2025 18:12:29 +0000 Received: from sss1.sss.pgh.pa.us (localhost [127.0.0.1]) by sss.pgh.pa.us (8.15.2/8.15.2) with ESMTP id 57CICM1C3409433; Tue, 12 Aug 2025 14:12:22 -0400 From: Tom Lane To: Richard Wesley cc: pgsql-bugs@lists.postgresql.org Subject: Re: Nested comparison semantics are unpredictable In-reply-to: References: Comments: In-reply-to Richard Wesley message dated "Tue, 12 Aug 2025 09:16:22 -0700" MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-ID: <3409431.1755022342.1@sss.pgh.pa.us> Content-Transfer-Encoding: quoted-printable Date: Tue, 12 Aug 2025 14:12:22 -0400 Message-ID: <3409432.1755022342@sss.pgh.pa.us> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk Richard Wesley writes: > I was trying to make our comparison semantics for nested types match Postgres, and I found that th= e semantics of comparisons change when a join is present. It's not about joins. It's about the syntactic form of the expression. When you write "ROW(...) =3D ROW(...)", that goes through make_row_comparison_op(), which indeed behaves differently from record_eq(), which is where the comparison will end up when it looks like "var =3D var". In particular "ROW(x) =3D ROW(y)" is optimized into "x =3D y" which is why you get a NULL for "row(0) =3D row(NULL)". record_eq() is not allowed to produce a null in such cases, though --- else it would be unsuitable to use as a btree comparator. There's a lot of historical baggage and spec-text-lawyering behind all this, but the short answer is that we're unlikely to change either behavior. regards, tom lane