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 1qnkra-00BrrE-26 for pgsql-hackers@arkaria.postgresql.org; Tue, 03 Oct 2023 19:15:22 +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 1qnkrY-008Bwc-IJ for pgsql-hackers@arkaria.postgresql.org; Tue, 03 Oct 2023 19:15:20 +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 1qnkrY-008BwQ-4f for pgsql-hackers@lists.postgresql.org; Tue, 03 Oct 2023 19:15:20 +0000 Received: from mail-pl1-x634.google.com ([2607:f8b0:4864:20::634]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1qnkrR-0081j8-7a for pgsql-hackers@postgresql.org; Tue, 03 Oct 2023 19:15:19 +0000 Received: by mail-pl1-x634.google.com with SMTP id d9443c01a7336-1bf55a81eeaso10310275ad.0 for ; Tue, 03 Oct 2023 12:15:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=j-davis-com.20230601.gappssmtp.com; s=20230601; t=1696360512; x=1696965312; darn=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=0ZHq80vYCE5hCUplCCfYL8/uKC+1M5VYtVBZjjjfCuU=; b=ZyfhzbObb3qmdpNTBu84zsR2F++BrxVL8JcJIemtypceJLm1SCuquNNVUufWmGfO0Z eHcGpuwzGj3UGGBEeecXTKrhTRnAvAn5p0ykdW6RfUB5ksMUSme9DXx7TMjEsEUaYVAo QpV1RnRcvySEjUJBhsahZmLrsIYk5IRX8hLr0A21Kl6I1iLPEXfsAa/toTGzejAIrMMn 7NVJ5Delmff6M0xgDbdkBqAiRixR/akKciqreKQI5J22WBm5MwKrMo0NnyPFKy+3hI3C FpqJYgr3SMmEXL7NdM11KtnTYRRiG38KXaplc4E3/qkw2Yp/ObTyqGKMe/VYMQKfm54C MqGQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1696360512; x=1696965312; 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=0ZHq80vYCE5hCUplCCfYL8/uKC+1M5VYtVBZjjjfCuU=; b=pUxoa2Q4p0lZIat1sCojIVuDUrxYgAQ4UwMHBvYAiOaSYPEgNzqAi441pZYckmiGfR FwmfmILWFqdLElCexBQexn2Ci/5NJUUIriHd5tOc6IecwkhfPsVb/TYLlJaAQ1yuF2n2 eQwoo+QMQQnw/S22PmExSHr6iXjcT6IVWnCpbRThEXFJ3SiSmJ8LNHObpxasieRgPDB/ WRlvxDaUA3nOJLx0LA7JyiWBMVUJGoxqx3ftHWDbt6jqD5BI0PEl3VHoOX3Oxnu5/xIY EX5SNFGdHCbrwdQ52G3TmfeNmN8qs/NQyvpfibhp9eWcFKMqczzVAyTJBVABRql414oE wwvA== X-Gm-Message-State: AOJu0YyK1k8ijLF8g8wA8OxS9TvWguevro5i1eZGR0NSooNH6pz6CXC3 qeByp9XSJoWGnOgOHzw0iFOtupErNFBquoj9E3M= X-Google-Smtp-Source: AGHT+IGOfvf0DUcZ0RLIP0YsDAtRFskhW2x22qgwp4WUfZ/klFUEkvtfDR+s7SvjOvRFZvAUCQqDbw== X-Received: by 2002:a17:902:d2c3:b0:1c2:218c:3762 with SMTP id n3-20020a170902d2c300b001c2218c3762mr548965plc.42.1696360511687; Tue, 03 Oct 2023 12:15:11 -0700 (PDT) Received: from [172.18.10.34] ([12.126.244.130]) by smtp.gmail.com with ESMTPSA id g5-20020a170902c38500b001bc445e2497sm1969696plg.79.2023.10.03.12.15.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 03 Oct 2023 12:15:11 -0700 (PDT) Message-ID: <23edd434b490f74a82b564b8027b6a52059f8de7.camel@j-davis.com> Subject: Re: Pre-proposal: unicode normalized text From: Jeff Davis To: Nico Williams Cc: pgsql-hackers@postgresql.org Date: Tue, 03 Oct 2023 12:15:10 -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, 2023-10-02 at 15:27 -0500, Nico Williams wrote: > I think you misunderstand Unicode normalization and equivalence.=C2=A0 > There > is no standard Unicode `normalize()` that would cause the above > equality > predicate to be true.=C2=A0 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. From [1]: "Unicode Normalization Forms are formally defined normalizations of Unicode strings which make it possible to determine whether any two Unicode strings are equivalent to each other. Depending on the particular Unicode Normalization Form, that equivalence can either be a canonical equivalence or a compatibility equivalence... A binary comparison of the transformed strings will then determine equivalence." NFC and NFD are based on Canonical Equivalence. "Canonical equivalence is a fundamental equivalency between characters or sequences of characters which represent the same abstract character, and which when correctly displayed should always have the same visual appearance and behavior." Can you explain why NFC (the default form of normalization used by the postgres normalize() function), followed by memcmp(), is not the right thing to use to determine Canonical Equivalence? Or are you saying that Canonical Equivalence is not a useful thing to test? What do you mean about the "prefix"? In Postgres today: SELECT normalize(U&'\0061\0301', nfc)::bytea; -- \xc3a1 SELECT normalize(U&'\00E1', nfc)::bytea; -- \xc3a1 SELECT normalize(U&'\0061\0301', nfd)::bytea; -- \x61cc81 SELECT normalize(U&'\00E1', nfd)::bytea; -- \x61cc81 which looks useful to me, but I assume you are saying that it doesn't generalize well to other cases? [1] https://unicode.org/reports/tr15/ > There are two ways to write '=C3=A1' 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 '=C3=A1' both equivalent > representations > should be considered equal, and for UNIQUE indexes they should be > considered the same). Sometimes preserving input differences is a good thing, other times it's not, depending on the context. Almost any data type has some aspects of the input that might not be preserved -- leading zeros in a number, or whitespace in jsonb, etc. If text is stored as normalized with NFC, it could be frustrating if the retrieved string has a different binary representation than the source data. But it could also be frustrating to look at two strings made up of ordinary characters that look identical and for the database to consider them unequal. Regards, Jeff Davis