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.96) (envelope-from ) id 1vJnfM-003C9M-2W for pgsql-hackers@arkaria.postgresql.org; Fri, 14 Nov 2025 06:52:15 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vJnfK-004r0b-1V for pgsql-hackers@arkaria.postgresql.org; Fri, 14 Nov 2025 06:52:14 +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.96) (envelope-from ) id 1vJnfJ-004r0R-39 for pgsql-hackers@lists.postgresql.org; Fri, 14 Nov 2025 06:52:14 +0000 Received: from mail-qk1-x736.google.com ([2607:f8b0:4864:20::736]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1vJnfF-0073WX-1L for pgsql-hackers@lists.postgresql.org; Fri, 14 Nov 2025 06:52:13 +0000 Received: by mail-qk1-x736.google.com with SMTP id af79cd13be357-88f239686f2so145028585a.0 for ; Thu, 13 Nov 2025 22:52:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1763103128; x=1763707928; darn=lists.postgresql.org; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=Cn4M6LwpoIxmZl/MIXYM7KMjd02GmQJR7fe0VQAApyE=; b=RiJ+KfhAAoiAsXKeaaXM6BrEddbY+yb6jZlUC0t/Bk7MDEp9jqZ9XhH1HjYiFPDCnN IY0RE62VSDnZJrMsTZh9AusJJ8mHnTQEMwAAmQJIpYidwUsev9h4IfRU5E6NnrYnlXiV aW8ZXi9nQBAEp3/i1mb0Ti34KAFLdJW0ZOehVka6m78FtVJwsCArzPl4vgPf34O8GeFb G7ZUkV4tdl8yo2y8Sgr1i973/uQIJAk55xUxXMsjq1FG8dLZaMzq4QmN7wPP9/HY21ng SN+aQ4u/yO+gm3gNZEwM0+YYgWW7nKf//mtin+aMKUY2PYVbcNrGNNLUITrEo1bP65l3 eTHg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763103128; x=1763707928; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:x-gm-gg:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=Cn4M6LwpoIxmZl/MIXYM7KMjd02GmQJR7fe0VQAApyE=; b=uK1Lfv+8Q3sGnYNT5XakU31jTjhPekvJkkz7ZeCJmk9YNGKttZDTYk/hNPeVWPGRP/ wbozfeQJgb7N70x2jBdh6VR90W4L7+EawzDNh7EEopJXRnbBvn9dl5qYBdyrTTptZ9uP ESoED7wrqcGzR6416hYjidLSBFv+ZupuECVePkmYXsqHpYknf2KHghBOFX+dejQsr11W LfMcbo7kq1gjO8X3MikayRUoOQ/dBzlFWffYYksrevJNwkM2pRUFN6SZZnmbiEtUp/NZ OQV+WKsxy7Z0ctBDiPGxwBwtUpv1JOf0VgrXXE1MlKJUbxrNgyCKZml0IzDYFYEL6PRH RZyw== X-Forwarded-Encrypted: i=1; AJvYcCVyBKefOtEajgS0sr3Wc2tsceTGiRY3l/lhJ3UhxcqJlyZ72ZSMMJJy3fuIXK3dWdnJs1bO64Jjz+7g+455@lists.postgresql.org X-Gm-Message-State: AOJu0YwfoGEZWcUfSJJNHClcKGy8q/HZnulzwtqqzoN08ex2O9ROL3Ge zjVUUoqGDXKhGxsMQO38IF+35qI0Jq/6UFFT5bGISn4nP/vngMrOvme/ X-Gm-Gg: ASbGncvOcxG0oDODupiSNa1fQ/k3ATw1rKoMNk0Htwdx5du894/iYEPeHcPxCiNVWAH IvtI1SGLPuOzNGNbMjmg7yvvetF6kJ8vxqEMLK49ZXj2N9k/PCFT3U6sh2D9UzDnPlwphfCi2Vh 7uc9MpHFBpWa4q0sHpLrp4tgY7cuTodr1CwVcsQKWggH71ahePwjTtEYyHNUKsEKYedxoTOmw2v L1F6oLDdc8HTPBrWcXCO9zb7M3IJ7QhlnHlma4NGmOsrQJU/PFrrP8jCXjql6+CIJ1/ga0C0hCq GRY5lp4OjFFMOPRHmePW5K/zpXtwLF76L0coEVofmqQVRDmlTrtqwPtiFiic7asXsCqsduF9X5Y ckiCBah5vdr3IJ3hfsSNBWtuLKa6wL01zmwQ34hJSNSxFETEZT7sOWK5Zz5Z6EIjWcVbxN+3cCf QboYuCpZaLZA== X-Google-Smtp-Source: AGHT+IEdZZ1GJSGgjDqdJ8OdepvPTgu0SXyidlfYyzZQTBQX0YmQ5wPsPvOrzP/f2oGgc3d01NIBsg== X-Received: by 2002:a05:620a:2a09:b0:8ab:58d3:6032 with SMTP id af79cd13be357-8b2c31db4a0mr242542485a.80.1763103128216; Thu, 13 Nov 2025 22:52:08 -0800 (PST) Received: from smtpclient.apple ([209.127.78.222]) by smtp.gmail.com with ESMTPSA id af79cd13be357-8b2af044e3asm278245885a.41.2025.11.13.22.52.01 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 13 Nov 2025 22:52:06 -0800 (PST) Content-Type: text/plain; charset=utf-8 Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3826.700.81\)) Subject: Re: Document NULL From: Chao Li In-Reply-To: <202511111530.xp4avso6b4pb@alvherre.pgsql> Date: Fri, 14 Nov 2025 14:51:22 +0800 Cc: "David G. Johnston" , jian he , Jeff Davis , Yugo NAGATA , Tom Lane , Peter Eisentraut , David Rowley , PostgreSQL Hackers , Marcos Pegoraro Content-Transfer-Encoding: quoted-printable Message-Id: References: <202511111530.xp4avso6b4pb@alvherre.pgsql> To: =?utf-8?Q?=C3=81lvaro_Herrera?= X-Mailer: Apple Mail (2.3826.700.81) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk > On Nov 11, 2025, at 23:34, =C3=81lvaro Herrera = wrote: >=20 > On 2025-Jun-18, David G. Johnston wrote: >=20 >> Version 8. >>=20 >> Marking this Ready to Commit in CF 2025-09 (CF PG19-1) >=20 > I have rebased this; here's v9. I haven't reviewed it in depth, but > intend to give it a read and get it pushed sometime in the > not-too-distant future, so if anybody wants to review it some more, = it'd > be appreciated. I just reviewed this patch and got some comments: >=20 > Note that this rebase was across the func.sgml split, which means I = had > to do some "manual" merging. Looking at the git diff --stat output, = it > seems to match what was there before, so I don't think anything was > lost. >=20 > --=20 > =C3=81lvaro Herrera Breisgau, Deutschland =E2=80=94 = https://www.EnterpriseDB.com/ > "Linux transform=C3=B3 mi computadora, de una `m=C3=A1quina para hacer = cosas', > en un aparato realmente entretenido, sobre el cual cada d=C3=ADa = aprendo > algo nuevo" (Jaime Salinas) > 1 - func-comparsions.sgml ``` + tests are AND'd together. Note that IS DISTINCT = FROM is not an operator. ``` The =E2=80=9Cnote that=E2=80=9D sentence is not clear. I believe you = meant to say the =E2=80=9CIS DISTINCT FROM=E2=80=9D cannot generate null = values because it is not an operator. But one thing being not an = operator doesn=E2=80=99t mean it cannot generate null value, right? So I = think we=E2=80=99d be explicit, I am suggesting: "Note that, IS DISTINCT FROM does not produce null results =E2=80=94 it = always returns true or false." This comment applies to 2 occurrences. 2 - func-comparsions.sgml ``` + Each side is evaluated and they are compared row-wise. + As discussed and shown in , + null values are treated as being equal to other null values and = greater + than all non-null values. + Composite type comparisons are allowed when the operator = is ``` The =E2=80=9Ccomposite type=E2=80=9D line is too short, consider move = the next line up. 3 - func-comparsions.sgml ``` - If the array expression yields a null array, the result of - ANY will be null. If the left-hand expression yields = null, - the result of ANY is ordinarily null (though a = non-strict - comparison operator could possibly yield a different result). - Also, if the right-hand array contains any null elements and no true - comparison result is obtained, the result of ANY - will be null, not false (again, assuming a strict comparison = operator). - This is in accordance with SQL's normal rules for Boolean = combinations - of null values. + If operator can produce null valued = booleans then, as explained in + , it is not possible to = see + a false result in the presence of both elements and = null values since the multiple equality + tests are AND'd together. Note that IS DISTINCT = FROM is not an operator. ``` For ANY, it should be =E2=80=9COR=E2=80=99d=E2=80=9D. 4 - func-subquery.sgml ``` The right-hand side is a parenthesized - subquery, which must return exactly one column. The left-hand = expression + subquery, which must return exactly one column. The result of = IN + is false if the subquery returns no rows, otherwise = the left-hand expression is evaluated and compared to each row of the subquery result. - The result of IN is true if any equal = subquery row is found. - The result is false if no equal row is found = (including the - case where the subquery returns no rows). + The result is true if any equal subquery row is = found. + The result is false if no equal row is found. =20 - Note that if the left-hand expression yields null, or if there are - no equal right-hand values and at least one right-hand row yields - null, the result of the IN construct will be null, = not false. - This is in accordance with SQL's normal rules for Boolean = combinations - of null values. + As explained in , it is = not possible to see + a false result in the presence of both rows and null = values since the multiple equality + tests are AND'd together. ``` IN should be ORed. 5 - func-subquery.sgml ``` - The right-hand side is a parenthesized - subquery, which must return exactly one column. The left-hand = expression - is evaluated and compared to each row of the subquery result. - The result of NOT IN is true if only = unequal subquery rows - are found (including the case where the subquery returns no rows). + The right-hand side is a parenthesized subquery, which must return = exactly one column. + The result of NOT IN is true if the = subquery returns no rows, + otherwise the left-hand expression is evaluated and compared to each = row of the subquery result. + The result is true if only unequal subquery rows are = found. The result is false if any equal row is found. =20 - Note that if the left-hand expression yields null, or if there are - no equal right-hand values and at least one right-hand row yields - null, the result of the NOT IN construct will be = null, not true. - This is in accordance with SQL's normal rules for Boolean = combinations - of null values. + As explained in , it is = not possible to see + a true result in the presence of both rows and null = values since the multiple inequality + tests are OR'd together. ``` NOT IN should be ANDed. 6 - func-subquery.sgml ``` - The result of ANY is true if any true = result is obtained. - The result is false if no true result is found = (including the - case where the subquery returns no rows). + The result is true if any true result is obtained. + The result is false if no true result is found. =20 @@ -223,11 +213,10 @@ WHERE EXISTS (SELECT 1 FROM tab2 WHERE col2 =3D = tab1.col2); =20 - Note that if there are no successes and at least one right-hand row = yields - null for the operator's result, the result of the ANY = construct - will be null, not false. - This is in accordance with SQL's normal rules for Boolean = combinations - of null values. + If operator can produce null valued = booleans then, as explained in + , it is not possible to = see + a false result in the presence of both rows and null = values since the multiple equality + tests are AND'd together. Note that IS DISTINCT = FROM is not an operator. ``` ANY should be OR-ed 7 - func-subquery.sgml ``` + Note that IS DISTINCT FROM is not an operator. ``` Same as 1. 8 - nullvalues.sgml ``` + to any other value (e.g., IS DISTINCT, and = IS TRUE.) ``` Should =E2=80=9CIS DISTINCT=E2=80=9D be =E2=80=9CIS DISTINCT FROM=E2=80=9D= ? 9 - nullvalues.sgml ``` + all non-null valueS. ``` Nit typo. Should be small =E2=80=9Cs". Best regards, -- Chao Li (Evan) HighGo Software Co., Ltd. https://www.highgo.com/