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 1qnPXm-00ArWM-31 for pgsql-hackers@arkaria.postgresql.org; Mon, 02 Oct 2023 20:29:30 +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 1qnPXk-00HDmc-Gz for pgsql-hackers@arkaria.postgresql.org; Mon, 02 Oct 2023 20:29:28 +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 1qnPXj-00HDmP-K2 for pgsql-hackers@lists.postgresql.org; Mon, 02 Oct 2023 20:29:27 +0000 Received: from eastern.birch.relay.mailchannels.net ([23.83.209.55]) by makus.postgresql.org with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1qnPXg-007qt4-SJ for pgsql-hackers@postgresql.org; Mon, 02 Oct 2023 20:29:26 +0000 X-Sender-Id: dreamhost|x-authsender|nico@cryptonector.com Received: from relay.mailchannels.net (localhost [127.0.0.1]) by relay.mailchannels.net (Postfix) with ESMTP id 2651E9409E9; Mon, 2 Oct 2023 20:27:12 +0000 (UTC) Received: from pdx1-sub0-mail-a310.dreamhost.com (unknown [127.0.0.6]) (Authenticated sender: dreamhost) by relay.mailchannels.net (Postfix) with ESMTPA id B08679416B2; Mon, 2 Oct 2023 20:27:11 +0000 (UTC) ARC-Seal: i=1; s=arc-2022; d=mailchannels.net; t=1696278431; a=rsa-sha256; cv=none; b=bZN5C9y6Jpn2jpGkVTpOP6C8ZC9+wzJLDiZbJ5aWEswBHxpLOxBRW6wMnmkXKvHvC/lPvu IYeu2kic2Bgd/ve3vHYb6Y/uuPwk5UlpoDBGqMhP/Edtb+tT+0wdOt1xyUnI2H/p2cKlbh bJzl7BFJ1oXtgm8CbU/tWosnnRR8aEZJUvPBz7jA0rIyJ19W9xPNNa0G/VCJKHyp7akMes y4LUxeu4P1SJ0i0SE7L0tT/iu7yodamTrL1m8a3bfPzGCRvAut8mS7IITZ+zfccsouJGXY Zs8aama9v6XXpKXPbt1XUWz449ytnaHSXL4TYXY9nA4nrulovvAwnI3L6kkS+Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=mailchannels.net; s=arc-2022; t=1696278431; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=JZKSULWVyczRfEUxwH8tc5M5+IFafEGTaGemW1WCL4g=; b=alehfE+YTTgDJozaKWQDTcqJU0eeLLHqmmalu47+Np5l2gCWB4uJqeJp9Misl/mJ/yrdrT jImvLdG3cdQQsZI5FLkInQ3wBpzAhitpnR+lyin1gcbk+2MV4JldYW50rVyLelrKzRf9Fr QEr+4x7z7zRi6obJZJrNxkmIzoD/EoP/1Gam68BSGg4zmh/fjeeijAtzI9Gn+A5J+HUxZI whWo8LGFPic3fM1WGYiSZ3wdHcrxSLeLK7Uf6Lfh8x5WdLQptq7peViijCdlT5CkElM3Ad drJqNWE4QdzT1h9tt1vPl+DJLolD8t3SxbMNo28lO/ezPVQzCplMuKUaBdZiVg== ARC-Authentication-Results: i=1; rspamd-7d5dc8fd68-2nx6v; auth=pass smtp.auth=dreamhost smtp.mailfrom=nico@cryptonector.com X-Sender-Id: dreamhost|x-authsender|nico@cryptonector.com X-MC-Relay: Neutral X-MailChannels-SenderId: dreamhost|x-authsender|nico@cryptonector.com X-MailChannels-Auth-Id: dreamhost X-Stupid-Tart: 1f473f41524ee8c2_1696278431959_1857251643 X-MC-Loop-Signature: 1696278431959:123916018 X-MC-Ingress-Time: 1696278431958 Received: from pdx1-sub0-mail-a310.dreamhost.com (pop.dreamhost.com [64.90.62.162]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384) by 100.109.110.212 (trex/6.9.1); Mon, 02 Oct 2023 20:27:11 +0000 Received: from ubby21 (075-081-095-064.res.spectrum.com [75.81.95.64]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: nico@cryptonector.com) by pdx1-sub0-mail-a310.dreamhost.com (Postfix) with ESMTPSA id 4Rzsv31RSXz6b; Mon, 2 Oct 2023 13:27:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cryptonector.com; s=dreamhost; t=1696278431; bh=JZKSULWVyczRfEUxwH8tc5M5+IFafEGTaGemW1WCL4g=; h=Date:From:To:Cc:Subject:Content-Type:Content-Transfer-Encoding; b=pQR0O6Afb98Ayxnls3ojyi9pxM+4Z8A9A+4GIp/3h+kzSyP7RaMgl9xrF4WOpgDeG e8AQgnbN1eeabjaJixc3Y/SxPaGVpkosZqbICeM72eB3ec2EF/6sWie8fXU7i3+ubZ 1jM1Yyf989ZR8ywn6421tbXFD+T6JTR2a3wP44Yf00lPPuIez8DBtv4osIAAJ52Rrr RbSfMRS6fWBpaU/4TR+6qFnTSb3Dt/3WS6y2DeoU885rn2hzhIdAXBVlarSq0bKtSQ gbWkaWSx1mS+umX9BMOwt1pM9mkOA1uEgBXKBrFoj8F25JQBdsXxWU+a+FrAMM6ftW VjfMrDuoOrNDg== Date: Mon, 2 Oct 2023 15:27:08 -0500 From: Nico Williams To: Jeff Davis Cc: pgsql-hackers@postgresql.org Subject: Re: Pre-proposal: unicode normalized text Message-ID: References: MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Tue, Sep 12, 2023 at 03:47:10PM -0700, Jeff Davis wrote: > One of the frustrations with using the "C" locale (or any deterministic > locale) is that the following returns false: > > SELECT 'á' = 'á'; -- false > > because those are the unicode sequences U&'\0061\0301' and U&'\00E1', > respectively, so memcmp() returns non-zero. But it's really the same > character with just a different representation, and if you normalize > them they are equal: > > SELECT normalize('á') = normalize('á'); -- true I think you misunderstand Unicode normalization and equivalence. There is no standard Unicode `normalize()` that would cause the above equality predicate to be true. If you normalize to NFD (normal form decomposed) then a _prefix_ of those two strings will be equal, but that's clearly not what you're looking for. PostgreSQL already has Unicode normalization support, though it would be nice to also have form-insensitive indexing and equality predicates. There are two ways to write 'á' in Unicode: one is pre-composed (one codepoint) and the other is decomposed (two codepoints in this specific case), and it would be nice to be able to preserve input form when storing strings but then still be able to index and match them form-insensitively (in the case of 'á' both equivalent representations should be considered equal, and for UNIQUE indexes they should be considered the same). You could also have functions that perform lossy normalization in the sort of way that soundex does, such as first normalizing to NFD then dropping all combining codepoints which then could allow 'á' to be eq to 'a'. But this would not be a Unicode normalization function. Nico --