CREATE OPERATOR name ( PROCEDURE = func_name [, LEFTARG = type1 ] [, RIGHTARG = type2 ] [, COMMUTATOR = com_op ] [, NEGATOR = neg_op ] [, RESTRICT = res_proc ] [, JOIN = join_proc ] [, HASHES ] [, SORT1 = left_sort_op ] [, SORT2 = right_sort_op ] )
El operador a definir. Véanse más abajo los caracteres permitidos.
La función utilizada para implementar este operador.
El tipo de la parte izquierda del operador, si procede. Esta opción debería ser omitida para un operador unario por la derecha.
El tipo para la parte derecha del operador, si procede. Esta opción debería ser omitida para un operador unario por la izquierda.
El commutador para este operador.
El negador para este operador.
La función estimadora de restricción selectiva para este operador.
***********The join selectivity estimator function for this operator. ***********La función estimador de ?????
Indica que este operador soporta un algoritmo "hash-join".
Operador que ordena el tipo de dato de la parte izquierda de este operador.
Operador que ordena el tipo de dato de la parte derecha de este operador.
CREATE OPERATOR define un nuevo operador, name. El usuario que define el operador se convierte en su propietario.
El operador name es una secuencia de hasta treinta y dos (32) caracteres con cualquiera combinación de lo siguiente:
+ - * / < > = ~ ! @ # % ^ & | ` ? $ :
Nota: No se permite ningún caracter alfabético en un nombre de operador. Esto permite a Postgres analizar la entrada SQL en elementos sin requerir espacion entre cada elemento.
El operador "!=" es convertido a "<>" en la entrada, por lo que son en consecuencia equivalentes.
Por lo menos uno de LEFTARG o RIGHTARG deben ser definidos. Para operadores binarios, ambos deberían ser definidos. Para operadores unarios por la derecha, solamente LEFTARG debería ser definido, mientras que en operadores unarios por la derecha solamente RIGHTARG debería ser definido.
También, el procedimiento func_name debe haber sido previamente definido utilizando CREATE FUNCTION y debe se definido para aceptar el número correcto de argumentos (bien uno o dos).
El operador commutador debería ser identificado si existe uno, para que Postgres pudiese invertir el orden de los operandos si lo desea. Por ejemplo, el operador area-menor-que, <<<, debería probablemente tener un operador conmutador area-mayor-que>>>. De esta forma, el optimizador de consultas podría convertir libremente:
"0,0,1,1"::box >>> MYBOXES.descriptiona
MYBOXES.description <<< "0,0,1,1"::box
Esto permite la ejecución de código para utiliar siempre la última representación y simplifica algo el optimizador.
De forma similar, si existe un operador negador entonces debería ser identificado. Supongamos que un operador, area-igual, ===, existe, y también un operador area-no-igual, !==. El negador permite al optimizador simpificar
NOT MYBOXES.description === "0,0,1,1"::boxa
MYBOXES.description !== "0,0,1,1"::box
Si el nombre de un operador commutador es suministrado, Postgres lo busca en el catálogo. Si es encontrado e no tiene aún un commutador él mismo, entonces la entrada del commutador es actualizada para tener el recien creado operador como su commutador. Esto se aplica al negador, también.
Esto es para permitir la definición de dos operadores que son commutadores de los negadores de cada uno de los otros. El primer operador debería der definido sin un commutador o negador (como sea apropiado). Cuando el segundo operador es definido, se debe nombrar el primero como el commutador o negador. El primero será actualizado como un efecto lateral. (En Postgres 6.5, esto también funciona para simplemente que ambos operadores se refieran al otro).
Los siguientes tres especificadores están presentes para auxiliar al optimizador de consultas al realizar uniones ("joins"). Postgres siempre puede evaluar una unión (i.e., procesando una cláusula con dos variables de tuplas separadas por un operador que retorno un booleano) por substitución iterativa [WONG76]. Además,Postgres es capaz de utilizar un algoritmo "hash-join" siguiendo las líneas de [SHAP86]; sin embargo, debe saber si esta estrategia es aplicable. Es algoritmo "hash-join" actual es solamente correcto para operadores que representan tests de igualdad; además la igualdad del tipo de dato debe significar igualdad a nivel de bits de la representación del tipo. (Por ejemplo, un tipo de dato que contiene bits no utilizados que no tienen repercusión para tests de igualdad podría no ser usado en el "hash-join"). El indicador HASHES indica al optimizador de consultas que un hash join poude ser utilizado de forma segura por este operador.
De forma parecida, los dos operadores de orden indican al optimizador de consultas si la estrategia mezclar-ordenar es utilizable y que operadores deberían ser utilizados para ordenar las clases de los dos operadores. Los operadores de orden deberían ser suministrados solamente para un operador de igualdad, y deberían referirse a operadores menor-que para los tipos de la parte izquierda y derecha respectivamente.
Si otras estrategias de unión son consideradas prácticas, Postgres cambiará el optimizador en tiempo de ejecución para utilizarlas y requerirán especificación adicional cuando un operador sea definido. Afortunadamente, la comunidad investigadora inventa nuevas estrategias de unión infrecuentemente, y la generalidad añadida de estrategias definidas por el usuario no merece la complejidad resultante.
Las dos últimas piezas de la especificación están presentes para que el optimizador pueda estimar los tamaños de los resultados. Si una cláusula de la forma:
MYBOXES.description <<< "0,0,1,1"::boxestá presente in la cualificación, entoncesPostgres puede tener que estimar la fracción de instancias en MYBOXES que satisfacen la cláusula. La función res_proc debe ser una función registrada (lo que significa que ya está definida utilizando CREATE FUNCTION), acepta argumentos del tipo correcto y devuelve un numero en punto flotante. El optimizador simplemente llama a esta función, pasandole el parámetro "0,0,1,1" y multiplica el resultado por el tamaño de la relación para obtener el deseado numero de instancias estimado.
Cuando ambos operandos del operador contienen variables de instancia, el optimizador debe estimar el tamaño de la unión resultante. La función join_proc retornara otro numero decimal que será multiplicado por las cardinalidades de las dos clases envueltas en el cómputo del tamaño esperado.
La diferencia entre la función
my_procedure_1 (MYBOXES.description, "0,0,1,1"::box)y el operador
MYBOXES.description === "0,0,1,1"::boxes quePostgres intenta optimizar operadores y puede decidir utilizar un índice para restringir el espacio de búsqueda cuando aparecen operadores. Sin embargo, no se intenta optimizar funciones, y son ejecutadas mediante fuerza bruta. Además, las funciones pueden tener cualquier número de argumentos mientras que los operadores están restringidos a uno o dos.
El siguiente comando define un nuevo operador, area-igualdad, para el tipo de dato BOX.
CREATE OPERATOR === ( LEFTARG = box, RIGHTARG = box, PROCEDURE = area_equal_procedure, COMMUTATOR = ===, NEGATOR = !==, RESTRICT = area_restriction_procedure, JOIN = area_join_procedure, HASHES, SORT1 = <<<, SORT2 = <<< );