Operador de evaluación
Inspecciona en busca de un ajuste exacto en el catálogo del sistema pg_operator.
Si un argumento de un operador binario es unknown, entonces se asume que es del mismo tipo que el otro argumento.
Invierte los argumentos, y busca un ajuste exacto con un operador el cual apunta a él mismo ya que es conmutativo. Si lo halla, entonces invierte los argumentos en el árbol del analizador y usa este operador.
Busca el mejor ajuste.
Hace una lista de todos los operadores con el mismo nombre.
Si solo hay un operador en la lista usa este si el tipo de la entrada puede ser forzado, y genera un error si el tipo no puede ser forzado.
Guarda todos los operadores con los ajustes más explícitos de tipos. Guarda todo si no hay ajustes explícitos y salta al siguiente paso. Si solo queda un candidato, usa este si el tipo puede ser forzado.
Si algún argumento de entrada es "unknown", categoriza los candidatos de entrada como boolean, numeric, string, geometric, o user-defined. Si hay una mezcla de categorías, o más de un tipo definido por el usuario, genera un error porque la elección correcta no puede ser deducida sin más pistas. Si solo está presente una categoría, entonces asigna el tipo preferido a la columna de entrada que previamente era "unknown".
Escoge el candidato con los ajustes de tipos más exactos, y que ajustan el "tipo preferido" para cada categoría de columna del paso previo. Si todavía queda más de un candidato, o si no queda ninguno, entonces se genera un error.
Solo hay un operador exponente definido en el catálogo, y toma argumentos float8. El examinador asigna un tipo inicial int4 a ambos argumentos en la expresión de esta consulta:
tgl=> select 2 ^ 3 AS "Exp"; Exp --- 8 (1 row) |
tgl=> select float8(2) ^ float8(3) AS "Exp"; Exp --- 8 (1 row) |
tgl=> select 2.0 ^ 3.0 AS "Exp"; Exp --- 8 (1 row) |
Esta ultima forma es la que tiene menos sobrecarga, ya que no se llama a funciones para hacer un conversión implícita de tipo. Esto no es una ventaja para pequeñas consultas, pero puede tener un gran impacto en el rendimiento de consultas que abarquen muchas tablas. |
Una sintaxis similar es usada tanto para trabajar con tipos alfanuméricos como con tipos complejos extendidos. Las cadenas alfanuméricas con tipo sin especificar son ajustadas con los operadores candidatos afines.
Un argumento sin especificar:
tgl=> SELECT text 'abc' || 'def' AS "Text and Unknown"; Text and Unknown ---------------- abcdef (1 row) |
En este caso el analizador mira si existe algún operador que necesite el operador text en ambos argumentos. Si existe, asume que el segundo operador debe ser interpretado como de tipo text.
Concatenación con tipos sin especificar:
tgl=> SELECT 'abc' || 'def' AS "Unspecified"; Unspecified ----------- abcdef (1 row) |
En este caso hay ninguna pista inicial sobre que tipo usar, ya que no se han especificado tipos en la consulta. De esta manera, el analizador busca en todos los operadores candidatos aquellos en los que todos los argumentos son de tipo alfanumérico. Elige el "tipo preferido" para las cadenas alfanuméricas, text, para esta consulta.
Si un usuario define un nuevo tipo y define un operador "||" para trabajar con el, entonces esta consulta tal como esta escrita no tendrá éxito. El analizador tendría ahora tipos candidatos de dos categorías, y no podría decidir cual de ellos usar. |
Este ejemplo ilustra un interesante resultado. Tradicionalmente, el operador factorial está definido solo para enteros. El catalogo de operadores de Postgres tiene solamente una entrada para el factorial, que toma un entero como operador. Si recibe un argumento numérico no entero, Postgres intentará convertir este argumento a un entero para la evaluación del factorial.
tgl=> select (4.3 !); ?column? -------- 24 (1 row) |
Por supuesto, esto conduce a un resultado matemáticamente sospechoso, debido a que en principio el factorial de un número no entero no está definido. De cualquier modo, el papel de una base de datos no es enseñar matemáticas, sino más bien ser una herramienta para manipular datos. Si un usuario decide obtener en factorial de un número real, Postgres intentará hacerlo. |