Saltar al contenido

PostgreSQL: diferencia entre las intercalaciones ‘C’ y ‘C.UTF-8’

Después de de esta prolongada selección de información hemos podido resolver este apuro que pueden tener algunos lectores. Te dejamos la respuesta y esperamos serte de gran apoyo.

Solución:

La documentación de PostgreSQL deja mucho ser deseado (solo digo 😼).

Para empezar, solo hay una codificación para una base de datos en particular, por lo que C y C.UTF-8 en su base de datos UTF-8 ambos utilizan la codificación UTF-8.

Para libc colaciones: típicamente nombres de colación, por convención, son realmente nombres de dos partes de la siguiente estructura:

locale_name.encoding_name

Una “configuración regional” (es decir, “cultura”) es el conjunto de reglas específicas del idioma para ordenar (LC_COLLATE) y capitalización (LC_CTYPE). Aunque a veces hay superposición, esto realmente no tiene nada que ver con cómo se almacenan estos datos.

Una “codificación” es cómo se almacenan los datos (es decir, qué secuencia de bytes equivale a qué carácter). Aunque a veces hay superposición, esto realmente no tiene nada que ver con las reglas de ordenación y uso de mayúsculas de cualquier idioma en particular que use la codificación (algunas codificaciones pueden ser utilizadas por varios lenguajes que pueden tener reglas bastante diferentes en uno o ambos de esas áreas).

Para ilustrarlo, considere almacenar datos coreanos:

  • ko_KR es la localidad.
  • Las posibles codificaciones que funcionan con esta configuración regional son:
    • EUC_KR (Código UNIX extendido-KR)
    • JOHAB
    • UHC (Código Hangul unificado / Windows949)
    • UTF8 (Codificación de 8 bits de Unicode)

También considere lo siguiente, tomado de la documentación “Compatibilidad con intercalaciones: intercalaciones libc” (énfasis agregado):

Por ejemplo, el sistema operativo puede proporcionar una configuración regional llamada de_DE.utf8. initdb luego crearía una colación llamada de_DE.utf8 para codificar UTF8 … También creará una colación con el .utf8 etiqueta despojada del nombre. Por lo tanto, también puede utilizar la intercalación debajo del nombre. de_DE, que es menos engorroso de escribir y hace que el nombre dependa menos de la codificación …

Dentro de cualquier base de datos en particular, solo son de interés las intercalaciones que utilizan la codificación de esa base de datos. Otras entradas en pg_collation son ignorados. Por lo tanto, un nombre de intercalación despojado como de_DE puede considerarse único dentro de una base de datos determinada, aunque no sea único a nivel mundial. Se recomienda el uso de los nombres de intercalación eliminados, ya que hará que necesite cambiar una cosa menos si decide cambiar a otra codificación de base de datos. Sin embargo, tenga en cuenta que el default, C, y POSIX las intercalaciones se pueden utilizar independientemente de la codificación de la base de datos.

Es decir, en una base de datos que utiliza la codificación UTF-8, en_US y en_US.UTF8 son equivalentes. PERO, entre esa base de datos y una base de datos que utiliza el LATIN1 codificación, la en_US las colaciones son no equivalente.

Entonces, ¿esto significa que C y C.UTF-8 ¿son lo mismo?

NO, ¡¡¡eso sería demasiado fácil !!! los C la intercalación es una excepción al comportamiento mencionado anteriormente. los C la intercalación es un conjunto simple de reglas que está disponible independientemente de la codificación de la base de datos, y el comportamiento debe ser coherente en todas las codificaciones (lo que es posible al reconocer solo el alfabeto inglés de EE. UU., “az” y “AZ”, como “letras”, y ordenando por valor de byte, que debería ser el mismo para las codificaciones disponibles para usted).

los C.UTF-8 la intercalación es en realidad un conjunto de reglas ligeramente mejorado, en comparación con la base C normas. Esta diferencia se puede ver en realidad en pg_collation ya que los valores para el collcollate y collctype las columnas son diferentes entre las filas para C y C.UTF-8.

Reuní un conjunto de consultas de prueba para ilustrar algunas de las similitudes y diferencias entre estas dos intercalaciones, así como en comparación con en_GB (e implícitamente en_GB.utf8). Comencé con las consultas proporcionadas en la respuesta de Daniel Vérité, las realicé para que, con suerte, fueran más claras sobre lo que se muestra y lo que no, y agregué algunas consultas. Los resultados nos muestran que:

  1. C y C.UTF-8 son en realidad conjuntos de reglas diferentes, aunque solo sean ligeramente diferentes, en función de sus valores respectivos en el collcollate y collctype columnas en pg_collation (consulta final)
  2. C.UTF-8 expande los caracteres que se consideran “letras”
  3. C.UTF-8, diferente a C (pero al igual que en_GB), reconoce los puntos de código Unicode no válidos (es decir, U + 0378) y los ordena hacia la parte superior
  4. C.UTF-8, igual que C (pero a diferencia en_GB), ordena los caracteres de letras que no son del inglés de EE. UU. por punto de código
  5. ucs_basic parece ser equivalente a C (que se indica en la documentación)

Puede buscar y ejecutar las consultas en: db <> fiddle

¿Es quizás el caso de que C.UTF-8 sea lo mismo que C con codificación UTF-8?

No. Considere, por ejemplo, estas diferencias en una base de datos UTF-8, en Debian 10 Linux:

postgres=# select upper('é' collate "C"), upper('é' collate "C.UTF-8");
 upper | upper 
-------+-------
 é     | É
(1 row)

postgres=# select ('A' < E'u0378' collate "C"),
                  ('A' < E'u0378' collate "C.UTF-8");
 ?column? | ?column? 
----------+----------
 t        | f
(1 row)

(U + 0378 no corresponde a ningún carácter válido en Unicode).

Otro ejemplo con un carácter Unicode válido (el lado izquierdo es 'PULGARES ARRIBA SIGN' U + 1F44D):

=> select '' < 'A' collate "C";
 ?column? 
----------
 f
(1 row)

=> select '' < 'A' collate "C.UTF-8";
 ?column? 
----------
 t
(1 row)

Cuando lc_collate es "C" (o "POSIX"), la comparación se realiza internamente mediante PostgreSQL. En ese caso, compara las representaciones de bytes de las cadenas utilizando memcmp.

En los otros casos donde libc es el proveedor (collprovider='c' en pg_collation), la comparación se realiza mediante strcoll_l de la biblioteca C, por lo que PostgreSQL en sí no es responsable del resultado y, como se muestra en los contraejemplos anteriores, no hay razón para creer que será idéntico.

Esa es true al menos para las intercalaciones respaldadas por libc. A partir de la versión 10 de Postgres, se pueden utilizar intercalaciones de UCI. Estas intercalaciones son consistentes en todos los sistemas operativos.

Los detalles sangrientos se pueden encontrar en el código fuente en backend / utils / adtvarlena.c, especialmente el varstrmp_cmp función.

Comentarios y calificaciones

Nos puedes añadir valor a nuestro contenido aportando tu experiencia en las críticas.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *