Conversión de tipos

Las consultasSQL pueden, intencionadamente o no, requerir mezclar diferentes tipos de datos en una misma expresión. Postgres posee grandes facilidades para evaluar expresiones que contengan diferentes tipos.

En muchos casos un usuario no necesita comprender los detalles del mecanismo de conversión de tipos. Sin embargo, la conversión implícita realizada por Postgres puede afectar a los resultados de una consulta. Estos resultados pueden ser ajustados por un usuario o por un programador usando conversión de tipos explícita

Este capitulo es una introducción a los mecanismos y convenciones de conversión de tipos en Postgres. Diríjase a las secciones correspondientes en la guía del usuario y en la guía del programador para obtener más información sobre tipos de datos específicos, funciones y operadores permitidos.

La guía del programador tiene más detalles sobre los algoritmos exactos usados por la conversión implícita de tipos.

Conceptos generales

SQL es un lenguaje con una definición de tipos rígida. Así, cada dato tiene asociado un tipo de dato que determina como se comporta y como se permite usar. Postgres tiene un sistema de tipos extensible que es mucho más general y flexible que otras implementaciones RDBMS. Por lo tanto, la mayoría de las reglas para convertir tipos en Postgres pueden ser regidas por unas normas generales bastante mejores que unas normas heurísticas que permitan a las expresiones con tipos distintos mezclados ser significantes, de la misma manera sucede con los tipos definidos por el usuario.

El analizador de Postgres clasifica los elementos léxicos en solo cinco categorías fundamentales: enteros, reales, cadenas, nombres y palabras clave. La mayoría de los tipos extendidos son convertidos en cadenas en primer lugar. El lenguaje de definición SQL permite especificar nombres de tipo con cadenas. Este mecanismo es usado por Postgres para indicar al analizador el camino correcto. Por ejemplo, la consulta:

tgl=> SELECT text 'Origin' AS "Label", point '(0,0)' AS "Value";
Label |Value
------+-----
Origin|(0,0)
(1 row)
tiene dos cadenas, de tipo text y de tipo point. Si un tipo no es especificado, entonces el tipo unknown es asignado inicialmente. En posteriores fases se resolverá tal y como se describe más adelante.

Hay cuatro construcciones fundamentales en SQL las cuales requieren distintas reglas de conversión de tipos en el analizador de Postgres:

Operadores

Postgres permite tanto expresiones con operadores de un solo argumento como con operadores de dos argumentos.

Llamadas a funciones

Gran parte del sistema de tipos de Postgres está construido alrededor de un rico conjunto de funciones. Las llamadas a funciones tienen uno o más argumentos los cuales, para cualquier consulta especifica, deben ser adaptados a las funciones disponibles en el sistema.

Objetivos de consultas

Una declaración SQL INSERT pone los resultados de una consulta en una tabla. Las expresiones en la consulta debe ser ajustadas, y quizás convertidas, a las columnas del objetivo del INSERT.

Consultas UNION

Debido a que todos los resultados de una declaración UNION SELECT deben aparecer como un único conjunto de columnas, los tipos de cada clausula SELECT deben ser ajustados y convertidos a un conjunto uniforme.

Muchas de las reglas de conversión de tipos generales usan convenciones sencillas que están en las tablas del sistema de funciones y operadores de Postgres. Hay algo de heurística en las reglas de conversión para dar un mejor soporte a las convenciones de los tipos nativos estándar de SQL92 como smallint, integer, y float.

El analizador de Postgres usa la convención de que todas las funciones de conversión de tipo toman un solo argumento como tipo de origen y se llaman de la misma manera que el tipo de destino. Se considera que cualquier función que cumpla este criterio es una función de conversión valida, y debe ser usada por el analizador de esta manera. Esta simple afirmación le da al analizador el poder para explorar las posibilidades de conversión de tipo sin dificultad, permitiendo a los tipos definidos por el usuario usar las mismas características de manera transparente.

El analizador esta provisto de una lógica adicional para permitir ajustarse más a la conducta correcta de los tipos estándar SQL. Hay cinco categorías de tipos definidas: boolean, string, numeric, geometric y user-defined. Cada categoría, con la excepción de user-defined, tiene un "tipo preferido" el cual es usado para resolver ambigüedades entre los candidatos. Cada tipo "user-defined" es su propio "tipo preferido", así las expresiones ambiguas (aquellas en las que el analizador tiene varios candidatos) con solo un tipo definido por el usuario pueden resolverse con una única solución, mientras que las que tienen varios tipos definidos por el usuario serán ambiguas y darán un error.

Las expresiones ambiguas que tienen posibles soluciones con solo una categoría de tipos son fáciles de resolver, mientras que las expresiones ambiguas con posibles soluciones de distintas categorías dan fácilmente un error y preguntan al usuario una aclaración.

Guidelines

Todas las reglas de conversión de tipos están diseñadas teniendo presentes diversos principios:

  • Las conversiones implícitas no deberían tener nunca un resultado sorprendente o impredecible.

  • Los tipos definidos por el usuario, de los cuales el analizador no tiene conocimiento a priori, deben de estar situados en un lugar alto dentro de la jerarquía de tipos. Dentro de expresiones con tipos mezclados, los tipos nativos deberían ser convertidos siempre a tipos definidos por el usuario (por supuesto, solo si la conversión es necesaria).

  • Los tipos definidos por el usuario no están relacionados. Por lo general, Postgres no tiene disponible información sobre las relaciones entre tipos aparte de la lógica codificada para los tipos predefinidos y las relaciones implícitas basadas en las funciones disponibles en en el catálogo.

  • No debería haber una carga extra del analizador o del ejecutor si una consulta no necesita conversión implícita de tipos. De esta manera, si una consulta esta bien construida y los tipos ya están adaptados, entonces la consulta debería realizarse sin consumir tiempo extra en el analizador y sin realizar funciones de conversión innecesarias dentro de la consulta.

    Adicionalmente, si una consulta normalmente requiere una conversión implícita para una función, y entonces el usuario define una función explicita con los tipos de los argumentos correctos, el analizador debería usar esta nueva función y no realizar nunca más una conversión implícita usando la función antigua.