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 1sH5m1-0037le-4G for pgsql-docs@arkaria.postgresql.org; Tue, 11 Jun 2024 17:59:09 +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 1sH5lx-008NhA-Os for pgsql-docs@arkaria.postgresql.org; Tue, 11 Jun 2024 17:59:06 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1sH5lx-008NgV-Bn for pgsql-docs@lists.postgresql.org; Tue, 11 Jun 2024 17:59:06 +0000 Received: from mail-pl1-x635.google.com ([2607:f8b0:4864:20::635]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1sH5lq-0018rx-D4 for pgsql-docs@lists.postgresql.org; Tue, 11 Jun 2024 17:59:05 +0000 Received: by mail-pl1-x635.google.com with SMTP id d9443c01a7336-1f47f07acd3so54277245ad.0 for ; Tue, 11 Jun 2024 10:58:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=j-davis-com.20230601.gappssmtp.com; s=20230601; t=1718128737; x=1718733537; darn=lists.postgresql.org; h=mime-version:user-agent:content-transfer-encoding:references :in-reply-to:date:cc:to:from:subject:message-id:from:to:cc:subject :date:message-id:reply-to; bh=YPjIKrDwyQLKD0sT210z5TJ7quuva6J7XLV5R04SaS4=; b=f+dOYe7QBaCoX5zYcfOdEOVTweNn6OWaCLIyDn79DP1Z88/nT6iOMhip0CFDx4xShA SQpuCig3teL1y5233//Xf1Vyboonkut6/dotM3KY79C5UHTIKYb4JHrfJVJU+9022FeM qZEJIIsalv+PzuzCBnWGPO2ad1nnAxWykZyKszHRxmWKJI9qQXwflH+EXssPrYOedsLn UFA6PanEcVojxvKI8/PtRp5x47czZ8cPOtLgh438gr9sE82f168cmY4lfCmzgSFpGNtW xty3fBepMghv/QSiZs56Nq6PbYy1DgSSKO3+sCAqGw5FOo1De/ONcrCqUP+RNUXzwxHF Z0nw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1718128737; x=1718733537; h=mime-version:user-agent:content-transfer-encoding:references :in-reply-to:date:cc:to:from:subject:message-id:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=YPjIKrDwyQLKD0sT210z5TJ7quuva6J7XLV5R04SaS4=; b=N4ga5WW9kgzJTlT8CBYRtRI1/ihrDIQrRQZukZ8TnQGVaheTTT4YB/I3EZOYR5qSZR T1py8vThucmrzsPqVa77H+23YqPs2oxKVUFDVzt/3QHZQclYaPn+scEXn7duErIplfdE fYoU5EdJOIeLLEVAOmviJjkj3qrWsClnGhZWFgy2kDgx+QL7ZVSSvWSaPPNJsOvOSOPU TZrXpiFzJKPzgUkynFXRNkpmnTuCBkf1ZqDpzT5d60AYCLY8asMr1Sm4hxuu9JbR7dPV ZwpnISXQwD40ARTMAWTaWCrifh/49BW+nniTuBtAPJUUQViITNWaEAyXdQQgKm18T6Cu y0fg== X-Forwarded-Encrypted: i=1; AJvYcCXxZASk1mwA42v1SucIhWyP3Ngz1NuUj0S0YvgQ96Hlqvhi35AaAD5zAyhotEEvGl1HB6PGPCz7FeS1ZSPfe5q3v5p0iFm/Oin8QW8iCtll X-Gm-Message-State: AOJu0YzBZuzRddK6rA/y1+npFbzRyNIViWYloJlmaMtRYFyTcjAYX8YJ S1EtCQdWOV2S3DVFG3Ola8T7r81dFOaZStcYoNJrMdc6JrICfXpS1UhCM6+g7A== X-Google-Smtp-Source: AGHT+IFy6+svN7fNUOSUePfJUun0V+5Hozz+mE/avQOEGDUejkya6m4xBu+EdZ1hN4jIYEN2H/jPag== X-Received: by 2002:a17:902:d4ca:b0:1f7:1706:25ba with SMTP id d9443c01a7336-1f7170628camr78238645ad.15.1718128736717; Tue, 11 Jun 2024 10:58:56 -0700 (PDT) Received: from jeff-laptop.lan (c-76-102-242-158.hsd1.ca.comcast.net. [76.102.242.158]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-1f6e787d08csm77536015ad.80.2024.06.11.10.58.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 11 Jun 2024 10:58:56 -0700 (PDT) Message-ID: <23342b9d538adeab472217fd6a96c75b48a659fb.camel@j-davis.com> Subject: Re: Documenting more pitfalls of non-default collations? From: Jeff Davis To: Will Mortensen , pgsql-docs@lists.postgresql.org, Jeremy Schneider Cc: Daniel Verite Date: Tue, 11 Jun 2024 10:58:54 -0700 In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable User-Agent: Evolution 3.44.4-0ubuntu2 MIME-Version: 1.0 List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Mon, 2024-06-10 at 23:55 -0700, Will Mortensen wrote: > I mentioned to Jeremy at pgConf.dev that using non-default collations > in some SQL idioms can produce undesired results, and he asked me to > send an email. An example idiom is the way Django implements > case-insensitive comparisons using "upper(x) =3D upper(y)" [1][2][3] , > which returns false if x =3D y but they have different collations that > produce different uppercase. Hi, Thank you for the examples. There are quite a few subtleties to getting case-insensitive comparisons right, and neither LOWER() nor UPPER() get everything quite right even if the collation is the same. For instance (for almost any locale other than "C"): UPPER(LOWER(U&'\1E9E')) !=3D UPPER(U&'\1E9E') And: LOWER(UPPER(U&'\03C2')) !=3D LOWER(U&'\03C2') The results of UPPER() and LOWER() can also change if some language adds a new case variant in the future, which could be a problem if the results are stored somewhere. How should we document all of that? If we include too many caveats, it's just frustrating. Instead, I propose that we implement Unicode "case folding" in PG18, which solves these issues by transforming the string to a canonical form suitable for case-insensitive comparison. (In most cases, the results are the same as LOWER(), but there are exceptions specifically to avoid the problems above.) Then, we can just have a section in the docs on "case folding" to describe the right way to use it. That still leaves one caveat: the handling of dotted- and dotless-i. But one caveat is a lot easier to keep track of. Regards, Jeff Davis