Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Text encoding débâcles

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for Thomas Munro Thomas Munro
July 15, 2026
1

Text encoding débâcles

(Text encoding débâcles)

A talk given at pgconf.dev 2026 in Vancouver.

https://2026.pgconf.dev/session/572
https://www.youtube.com/watch?v=hgPddKXOP40

Avatar for Thomas Munro

Thomas Munro

July 15, 2026

Transcript

  1. template0 [UTF8] template1 [UTF8] postgres [UTF8] $ initdb -D pgdata

    Default locale comes from environment and implies the encoding. In practice this means -E UTF8 on Unixen*, in modern times. Default template Special template containing no non- ASCII text *On Windows there are complications and un fi nished business around UTF8…
  2. template0 [UTF8] template1 [UTF8] postgres [UTF8] mydb1 [UTF8] CREATE DATABASE

    mydb2 TEMPLATE template0 ENCODING LATIN1 LOCALE 'en_CA.ISO8859-1' mydb2 [LATIN1] Special template containing no non- ASCII text
  3. mydb1 [UTF8] mydb1=# create user frédéric; CREATE ROLE mydb2=# select

    rolname from pg_authid where rolname like 'f%'; rolname ------------- frédéric (1 row) mydb2 [LATIN1] Mojibake! A “shared” pg_catalog table. Encoding is in the eye of the beholder…
  4. * If databases all use the same encoding, it’s OK

    to use non-ASCII role names and databases names [etc] * Otherwise, it’s not OK! * Can we enforce that? 💡 First attempt posted to list a couple of years ago…
  5. initdb --encoding-mode=uniform initdb --encoding-mode=mixed initdb --encoding-mode=legacy * All databases must

    have the same encoding! * Role names, database names etc can use that encoding. * Default option. * Encodings can be mixed. * Role names, database names etc must use ASCII. * Anything goes? * For a limited number of releases? M ore recent prototype…
  6. $ initdb --encoding-mode=uniform -D pgdata postgres# CREATE DATABASE xxx TEMPLATE

    template0 LOCALE 'C' ENCODING LATIN1; ERROR: encoding "LATIN1" does not match existing databases and encoding mode is "UNIFORM"
  7. $ initdb --encoding-mode=mixed -D pgdata postgres# CREATE USER astérix; ERROR:

    the string "astérix" contains invalid characters for encoding mode "MIXED"
  8. * pg_stat_activity * GUCs * various fi les * early

    authentication * … Other unde fi ned/confused encodings
  9. * Verify all applicable strings to change mode, report obstructions

    with suggestions to unblock * Requires WAL logging and coarse locking * Early version had special ALTER SYSTEM command but now considering a function… Changed your mind?
  10. * An encoding of Unicode * Encodes Chinese characters in

    2 bytes instead of UTF8’s 3 * Unlikely to be supported by PostgreSQL (server-side) GB18030 People ask but we can’t easily do it…
  11. * Individual VARCHAR columns can use different encodings (cf COLLATE)

    * In some implementations implied by COLLATE instead * Probably less relevant in the Unicode age…? SQL standard: CHARACTER SET Not gonna happen…
  12. * Like VARCHAR but with an unspeci fi ed special

    encoding * In most implementations it is UTF-16 SQL standard: NVARCHAR (NATIONAL …)
  13. language | octets | delta | string ----------+---------+-------+------------------------------------------------- English |

    45→90 | +100% | In a hole in the ground there lived a hobbit. Spanish | 44→86 | +95% | En un agujero en el suelo, vivía un hobbit. Russian | 59→66 | +12% | В норе под землей жил-был хоббит. Arabic | 57→64 | +12% | ضرﻷا ﻲﻓ ةﺮﻔﺣ ﻲﻓ ﺖﯿﺑﻮھ ﺶﯿﻌﯾ نﺎﻛ. Hebrew | 43→48 | +12% | טיבוה יח המדאב רוח ךותב. Greek | 74→82 | +11% | Σε µια τρύπα στο έδαφος ζούσε ένα χόµπιτ. Korean | 55→46 | -16% | ٶࣘ যו ҳݨী ೠ ഐࡁ੉ ࢓Ҋ ੓঻׮. Hindi | 111→86 | -23% | जमीन मे ं बने एक ग ड ् ढ े मे ं एक हॉ बि ट रहता था। Tamil | 146→108 | -26% | அ ந் த நி ல த் தி ல் ஒ ரு து ைள யி ல் ஒ ரு ஹா பி ட் வ சி த் து வ ந் த து . Chinese | 51→34 | -33% | 在地下 一 个洞 里 ,住着 一 个霍 比 特 人 。 Japanese | 66→44 | -33% | 穴 ͷͳ͔ʹ、ͻͱΓͷϗϏοτ͕暮Β͍ͯͨ͠。 Experimental prototype abandoned! Why would anyone want UTF-16? { * There was a time before UTF-8… * It’s “native” for several environments * It’s smaller for some languages
  14. Unicode compression standards? * SCSU compresses UTF-8 * BOCU-1 also

    maintains binary code point order * Hindi: 3→~1 * CJK: 3->~2 * Greek, Russian: 2→~1 Just an idea…
  15. * A multi-byte aware iterator API (if done right…) could

    avoid mistakes in common patterns as seen in previous CVEs Security and maintenance angle
  16. * We have loops that dispatch via function pointers once

    per character! * Generate inlined specializations of string-processing functions for each encoding? Performance angle
  17. EOF