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 1stThq-00GiTn-1M for pgsql-docs@arkaria.postgresql.org; Wed, 25 Sep 2024 15:13:31 +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 1stThp-00A1Cv-DH for pgsql-docs@arkaria.postgresql.org; Wed, 25 Sep 2024 15:13:29 +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 1stThp-00A1Bu-0R for pgsql-docs@lists.postgresql.org; Wed, 25 Sep 2024 15:13:29 +0000 Received: from mail.postgrespro.ru ([93.174.131.139]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1stThk-0012U7-8f for pgsql-docs@lists.postgresql.org; Wed, 25 Sep 2024 15:13:28 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=postgrespro.ru; s=mx2023; t=1727277204; bh=e1oo4TlduXUS1j21LcOICfzXRPddUZ0fk7hTUDe06JY=; h=Date:From:To:Subject:User-Agent:Message-ID:From; b=DKqdxRseAReM8t/VhtP+yEUOzsJLnJxChOG2e6eiv8a6iHaAzcffnDRqhqnElduPg 14rzR2xWff/cqXm/ZeefltnaB6otV+DIZppoAVJmKzQd8J+PxQGmvZY07UTyiLkzfq EjdFN3vo29woRHqueZHWIlO8f5cRw3lRwOtZ2aVVRL5zQDhQ+HsPz35Ct92HK78AzV 2bPKbliT6yS9SOxbY355hddKIc8ZvCYJtOQ/LM5KrX6rIAxboV5iZ2r2vSHzNMKidC QdBfnwGtGXUuqaCu/C1VS9+Fi2zeQ3ci+I4n6sgjuNrGQHcub54FgvjVH7f7UQp+0T bfUQK1IfcnNmQ== Received: from mail.postgrespro.ru (unknown [192.168.2.28]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (Client did not present a certificate) (Authenticated sender: o.tselebrovskiy@postgrespro.ru) by mail.postgrespro.ru (Postfix/587) with ESMTPSA id 5E633601F1 for ; Wed, 25 Sep 2024 18:13:24 +0300 (MSK) MIME-Version: 1.0 Date: Wed, 25 Sep 2024 22:13:24 +0700 From: Oleg Tselebrovskiy To: pgsql-docs@lists.postgresql.org Subject: Initcap works differently with different locale providers User-Agent: Roundcube Webmail/1.6.9 Message-ID: <804cc10ef95d4d3b298e76b181fd9437@postgrespro.ru> X-Sender: o.tselebrovskiy@postgrespro.ru Organization: Postgres Pro Content-Type: multipart/mixed; boundary="=_9f334a4d6ec0e68aab377bfc6a719812" X-KSMG-AntiPhishing: NotDetected, bases: 2024/09/25 12:44:00 X-KSMG-AntiSpam-Interceptor-Info: not scanned X-KSMG-AntiSpam-Status: not scanned, disabled by settings X-KSMG-AntiVirus: Kaspersky Secure Mail Gateway, version 2.1.0.7854, bases: 2024/09/25 13:22:00 #26670925 X-KSMG-AntiVirus-Status: NotDetected, skipped X-KSMG-LinksScanning: not scanned, disabled by settings X-KSMG-Message-Action: skipped X-KSMG-Rule-ID: 1 List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --=_9f334a4d6ec0e68aab377bfc6a719812 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8; format=flowed Greetings, everyone! One of our clients has found a difference in behaviour of initcap function when using different locale providers, shown below postgres=# create database test_db_1 locale_provider=icu locale="ru_RU.UTF-8" template=template0; NOTICE: using standard form "ru-RU" for ICU locale "ru_RU.UTF-8" CREATE DATABASE postgres=# \c test_db_1; You are now connected to database "test_db_1" as user "postgres". test_db_1=# select initcap('ЧиЮ А.Ю.'); initcap ---------- Чию А.ю. (1 row) test_db_1=# select initcap('joHn d.e.'); initcap ----------- John D.e. (1 row) postgres=# create database test_db_2 locale_provider=libc locale="ru_RU.UTF-8" template=template0; CREATE DATABASE postgres=# \c test_db_2 You are now connected to database "test_db_2" as user "postgres". test_db_2=# select initcap('ЧиЮ А.Ю.'); initcap ---------- Чию А.Ю. (1 row) test_db_2=# select initcap('joHn d.e.'); initcap ----------- John D.E. (1 row) And an easier reproduction (should work for REL_12_STABLE and up) postgres=# SELECT initcap('first.second' COLLATE "en-x-icu"); initcap -------------- First.second (1 row) postgres=# SELECT initcap('first.second' COLLATE "en_US"); initcap -------------- First.Second (1 row) This behaviour is reproducible on REL_12_STABLE and up to master I don't believe that this is an erroneous behaviour, just a differing one, hence just a documentation change proposition I suggest adding a clarification that this function works differently with libc and ICU providers because there is a difference in what a "word" is between them In libc a word is a sequence of alphanumeric characters, separated by non-alphanumeric characters (as it is written in documentation right now) In ICU words are divided according to Unicode® Standard Annex #29 [1] Similar issue was briefly discussed in [2] The suggested documentation patch is attached (versions for REL_13_STABLE+ and for REL_12_STABLE only) [1]: https://www.unicode.org/reports/tr29/#Word_Boundaries [2]: https://www.postgresql.org/message-id/CAEwbS1R8pwhRkwRo3XsPt24ErBNtFWuReAZhVPJwA3oqo148tA%40mail.gmail.com Oleg Tselebrovskiy, Postgres Professional --=_9f334a4d6ec0e68aab377bfc6a719812 Content-Transfer-Encoding: base64 Content-Type: text/x-diff; name=v1-0001-string-functions.patch Content-Disposition: attachment; filename=v1-0001-string-functions.patch; size=952 ZGlmZiAtLWdpdCBhL2RvYy9zcmMvc2dtbC9mdW5jLnNnbWwgYi9kb2Mvc3JjL3NnbWwvZnVuYy5z Z21sCmluZGV4IDFiZGU0MDkxY2E2Li4zY2U1YWQxZDFmMSAxMDA2NDQKLS0tIGEvZG9jL3NyYy9z Z21sL2Z1bmMuc2dtbAorKysgYi9kb2Mvc3JjL3NnbWwvZnVuYy5zZ21sCkBAIC0zMTAwLDggKzMx MDAsMTEgQEAgU0VMRUNUIE5PVChST1codGFibGUuKikgSVMgTk9UIE5VTEwpIEZST00gVEFCTEU7 IC0tIGRldGVjdCBhdCBsZWFzdCBvbmUgbnVsbCBpbgogICAgICAgIDwvcGFyYT4KICAgICAgICA8 cGFyYT4KICAgICAgICAgQ29udmVydHMgdGhlIGZpcnN0IGxldHRlciBvZiBlYWNoIHdvcmQgdG8g dXBwZXIgY2FzZSBhbmQgdGhlCi0gICAgICAgIHJlc3QgdG8gbG93ZXIgY2FzZS4gV29yZHMgYXJl IHNlcXVlbmNlcyBvZiBhbHBoYW51bWVyaWMKLSAgICAgICAgY2hhcmFjdGVycyBzZXBhcmF0ZWQg Ynkgbm9uLWFscGhhbnVtZXJpYyBjaGFyYWN0ZXJzLgorICAgICAgICByZXN0IHRvIGxvd2VyIGNh c2UuIFdoZW4gdXNpbmcgdGhlIDxsaXRlcmFsPmxpYmM8L2xpdGVyYWw+IGxvY2FsZQorICAgICAg ICBwcm92aWRlciwgd29yZHMgYXJlIHNlcXVlbmNlcyBvZiBhbHBoYW51bWVyaWMgY2hhcmFjdGVy cyBzZXBhcmF0ZWQKKyAgICAgICAgYnkgbm9uLWFscGhhbnVtZXJpYyBjaGFyYWN0ZXJzOyB3aGVu IHVzaW5nIHRoZSBJQ1UgbG9jYWxlIHByb3ZpZGVyLAorICAgICAgICB3b3JkcyBhcmUgc2VwYXJh dGVkIGFjY29yZGluZyB0bworICAgICAgICA8dWxpbmsgdXJsPSJodHRwczovL3d3dy51bmljb2Rl Lm9yZy9yZXBvcnRzL3RyMjkvI1dvcmRfQm91bmRhcmllcyI+VW5pY29kZcKuIFN0YW5kYXJkIEFu bmV4ICMyOTwvdWxpbms+LgogICAgICAgIDwvcGFyYT4KICAgICAgICA8cGFyYT4KICAgICAgICAg PGxpdGVyYWw+aW5pdGNhcCgnaGkgVEhPTUFTJyk8L2xpdGVyYWw+Cg== --=_9f334a4d6ec0e68aab377bfc6a719812 Content-Transfer-Encoding: base64 Content-Type: text/x-diff; name=v1-0002-string-functions-REL_12.patch Content-Disposition: attachment; filename=v1-0002-string-functions-REL_12.patch; size=931 ZGlmZiAtLWdpdCBhL2RvYy9zcmMvc2dtbC9mdW5jLnNnbWwgYi9kb2Mvc3JjL3NnbWwvZnVuYy5z Z21sCmluZGV4IDQ4N2JiMTAzNjM3Li4xY2QyODFkZDkwYiAxMDA2NDQKLS0tIGEvZG9jL3NyYy9z Z21sL2Z1bmMuc2dtbAorKysgYi9kb2Mvc3JjL3NnbWwvZnVuYy5zZ21sCkBAIC0xOTMyLDggKzE5 MzIsMTEgQEAKICAgICAgICA8ZW50cnk+PHR5cGU+dGV4dDwvdHlwZT48L2VudHJ5PgogICAgICAg IDxlbnRyeT4KICAgICAgICAgQ29udmVydCB0aGUgZmlyc3QgbGV0dGVyIG9mIGVhY2ggd29yZCB0 byB1cHBlciBjYXNlIGFuZCB0aGUKLSAgICAgICAgcmVzdCB0byBsb3dlciBjYXNlLiBXb3JkcyBh cmUgc2VxdWVuY2VzIG9mIGFscGhhbnVtZXJpYwotICAgICAgICBjaGFyYWN0ZXJzIHNlcGFyYXRl ZCBieSBub24tYWxwaGFudW1lcmljIGNoYXJhY3RlcnMuCisgICAgICAgIHJlc3QgdG8gbG93ZXIg Y2FzZS4gV2hlbiB1c2luZyB0aGUgPGxpdGVyYWw+bGliYzwvbGl0ZXJhbD4gbG9jYWxlCisgICAg ICAgIHByb3ZpZGVyLCB3b3JkcyBhcmUgc2VxdWVuY2VzIG9mIGFscGhhbnVtZXJpYyBjaGFyYWN0 ZXJzIHNlcGFyYXRlZAorCQlieSBub24tYWxwaGFudW1lcmljIGNoYXJhY3RlcnM7IHdoZW4gdXNp bmcgdGhlIElDVSBsb2NhbGUgcHJvdmlkZXIsCisJCXdvcmRzIGFyZSBzZXBhcmF0ZWQgYWNjb3Jk aW5nIHRvCisJCTx1bGluayB1cmw9Imh0dHBzOi8vd3d3LnVuaWNvZGUub3JnL3JlcG9ydHMvdHIy OS8jV29yZF9Cb3VuZGFyaWVzIj5Vbmljb2Rlwq4gU3RhbmRhcmQgQW5uZXggIzI5PC91bGluaz4u CiAgICAgICAgPC9lbnRyeT4KICAgICAgICA8ZW50cnk+PGxpdGVyYWw+aW5pdGNhcCgnaGkgVEhP TUFTJyk8L2xpdGVyYWw+PC9lbnRyeT4KICAgICAgICA8ZW50cnk+PGxpdGVyYWw+SGkgVGhvbWFz PC9saXRlcmFsPjwvZW50cnk+Cg== --=_9f334a4d6ec0e68aab377bfc6a719812--