Capítulo 2. Tipos de conjunto y de rango

Tabla de contenidos

Entrada y salida
Constructores
Conversión de tipos
Accesores
Transformaciones
Sistema de referencia espacial
Operaciones de conjuntos
Operaciones de cuadro delimitador
Operaciones topológicas
Operaciones de posición
Operaciones de división
Operaciones de distancia
Comparaciones
Agregaciones
Indexación

MobilityDB proporciona los tipos de conjunto, rango y conjunto de rangos para representar conjuntos de valores de otro tipo, que se denomina tipo base. Los tipos de conjunto son similares a los tipos de matrices de PostgreSQL restringidos a una dimensión, pero imponen la restricción de que los conjuntos no tienen duplicados. Los tipos de rango y conjunto de rangos en MobilityDB corresponden a los tipos de rango y multirango en PostgreSQL pero tienen restricciones adicionales. En particular, los tipos de rango en MobilityDB tienen una longitud fija y no permiten rangos vacíos ni límites infinitos. Si bien los tipos de rango en MobilityDB proporcionan una funcionalidad similar a los tipos de rango en PostgreSQL, los tipos de rango en MobilityDB permiten aumentar el rendimiento. En particular, se elimina la sobrecarga del procesamiento de tipos de longitud variable y, además, se pueden utilizar la aritmética de punteros y la búsqueda binaria.

Los tipos de base que se utilizan para construir tipos de conjunto, de rango y de conjunto de rangos son los tipos integer, bigint, float, text, date, and timestamptz (marca de tiempo con zona horaria) proporcionados por PostgreSQL, los tipos geometry y geography proporcionados por PostGIS, y el tipo npoint (network point o punto de red) proporcionado por MobilityDB (ver Capítulo 11, Puntos de red temporales). MobilityDB proporciona los siguientes tipos de conjunto y de rango:

A continuación presentamos las funciones y operadores para tipos de conjunto y de rango. Estas funciones y operadores son polimórficos, es decir, sus argumentos pueden ser de varios tipos y el tipo de resultado puede depender del tipo de los argumentos. Para expresar esto en la firma de las funciones y los operadores, utilizamos la siguiente notación:

Como ejemplo, la firma del operador contiene (@>) es como sigue:

{set,spans} @> {base,set,spans} → boolean

Nótese que la firma anterior es una versión abreviada de la firma más precisa a continuación

set @> {base,set} → boolean
spans @> {base,spans} → boolean

ya que los conjuntos y los rangos no se pueden mezclar en las operaciones y, por lo tanto, por ejemplo, no se puede preguntar si un rango contiene un conjunto. A continuación, por concisión, utilizamos el estilo abreviado de las firmas anteriores. Además, la parte de tiempo de las marcas de tiempo se omite en la mayoría de los ejemplos. Recuerde que en ese caso PostgreSQL asume el tiempo 00:00:00.

A continuación, dado que los tipos de rango y conjunto de rangos tienen funciones y operadores similares, cuando hablamos de tipos rango nos referimos a los tipos de rango y conjuntos de rangos, a menos que nos refiramos explícitamente a los tipos de rango unitarios y a los tipos de conjunto de rangos para distinguirlos. Además, cuando nos referimos a tipos de tiempo, nos referimos a uno de los siguientes tipos: timestamptz, tstzset, tstzspan o tstzspanset.

Entrada y salida

MobilityDB generaliza los formatos de entrada y salida Well-Known Text (WKT) y Well-Known Binary (WKB) del Open Geospatial Consortium (OGC) a para todos sus tipos. De esta forma, las aplicaciones pueden intercambiar datos entre ellas utilizando un formato de intercambio estandarizado. El formato WKT es legible por humanos, mientras que el formato WKB es más compacto y más eficiente que el formato WKT. El formato WKB se puede generar como una cadena binaria o como una cadena de caracteres codificada en ASCII hexadecimal.

Los tipos de conjunto representan un conjunto ordenado de valores diferentes. Un conjunto debe contener al menos un elemento. Ejemplos de valores de tipos de conjunto son como sigue:

SELECT tstzset '{2001-01-01 08:00:00, 2001-01-03 09:30:00}';
-- Conjunto unitario
SELECT textset '{"highway"}';
-- Conjunto erróneo: elementos desordenados
SELECT floatset '{3.5, 1.2}';
-- Conjunto erróneo: elementos duplicados
SELECT geomset '{"Point(1 1)", "Point(1 1)"}';

Nótese que los elementos de los conjuntos textset, geomset, geogset y npointset deben estar delimitados entre commillas dobles. Nótese también que las geometrías y las geografías utilizan el orden definido por PostGIS.

Un valor de un tipo de rango unitario tiene dos límites, el límite inferior y el límite superior, que son valores del tipo de base subyacente. Por ejemplo, un valor del tipo tstzspan tiene dos límites, que son valores de timestamptz. Los límites pueden ser inclusivos o exclusivos. Un límite inclusivo significa que el instante límite está incluido en el rango, mientras que un límite exclusivo significa que el instante límite no está incluido en el rango. En el formato textual de un valor de un rango, los límites inferiores inclusivos y exclusivos están representados, respectivamente, por “[” y “(”. Asimismo, los límites superiores inclusivos y exclusivos se representan, respectivamente, por “]” y “)”. En un valor de un rango, el límite inferior debe ser menor o igual que el límite superior. Un valor de rango con límites iguales e inclusivos se llama rango instantáneo y corresponde a un valor del tipo de base. Ejemplos de valores de rango son como sigue:

SELECT intspan '[1, 3)';
SELECT floatspan '[1.5, 3.5]';
SELECT tstzspan '[2001-01-01 08:00:00, 2001-01-03 09:30:00)';
-- Rangos instantáneos
SELECT intspan '[1, 1]';
SELECT floatspan '[1.5, 1.5]';
SELECT tstzspan '[2001-01-01 08:00:00, 2001-01-01 08:00:00]';
-- Rango erróneo: límites inválidos
SELECT tstzspan '[2001-01-01 08:10:00, 2001-01-01 08:00:00]';
-- Rango erróneo: rango vacío
SELECT tstzspan '[2001-01-01 08:00:00, 2001-01-01 08:00:00)';
	

Los valores de intspan, bigintspan y datespan son convertidos en forma normal para que los valores equivalentes tengan representaciones idénticas. En la representación canónica de estos tipos, el límite inferior es inclusivo y el límite superior es exclusivo, como se muestra en los siguientes ejemplos:

SELECT intspan '[1, 1]';
-- [1, 2)
SELECT bigintspan '(1, 3]';
--[2, 4)
SELECT datespan '[2001-01-01, 2001-01-03]';
-- [2001-01-01, 2001-01-04)

Un valor de un tipo de conjunto de rangos representa un conjunto ordenado de valores de rango disjuntos. Un valor de conjunto de rangos debe contener al menos un elemento, en cuyo caso corresponde a un único valor de rango. Ejemplos de valores conjunto de rangos son los siguientes:

SELECT floatspanset '{[8.1, 8.5],[9.2, 9.4]}';
-- Singleton spanset
SELECT tstzspanset '{[2001-01-01 08:00:00, 2001-01-01 08:10:00]}';
-- Erroneous spanset: unordered elements
SELECT intspanset '{[3,4],[1,2]}';
-- Erroneous spanset: overlapping elements
SELECT tstzspanset '{[2001-01-01 08:00:00, 2001-01-01 08:10:00],
  [2001-01-01 08:05:00, 2001-01-01 08:15:00]}';

Los valores de los tipos conjunto de rangos son convertidos en forma normal de modo que los valores equivalentes tengan representaciones idénticas. Para ello, los valores de rango consecutivos que son adyacentes se fusionan cuando es posible. Ejemplos de transformación a forma normal son los siguientes:

SELECT intspanset '{[1,2],[3,4]}';
-- {[1, 5)}
SELECT floatspanset '{[1.5,2.5],(2.5,4.5]}';
-- {[1.5, 4.5]}
SELECT tstzspanset '{[2001-01-01 08:00:00, 2001-01-01 08:10:00),
  [2001-01-01 08:10:00, 2001-01-01 08:10:00], (2001-01-01 08:10:00, 2001-01-01 08:20:00]}';
-- {[2001-01-01 08:00:00+00,2001-01-01 08:20:00+00]}

Damos a continuación las funciones de entrada y salida de tipos de conjunto y de rango en formato textual (Well-Known Text o WKT) y binario (Well-Known Binary o WKB). El formato de salida predeterminado de todos los tipos de conjuntos y de rango es el formato de texto conocido. La función asText que se da a continuación permite determinar la salida de valores de punto flotante.

  • Devuelve la representación textual conocida (Well-Known Text o WKT)

    asText({floatset,floatspans},maxdecdigits=15) → text

    El argumento maxdecdigits se puede utilizar para definir el número máximo de decimales para la salida de los valores de coma flotante (por defecto 15).

    SELECT asText(floatset '{1.123456789,2.123456789}', 3);
    -- {1.123, 2.123}
    SELECT asText(floatspanset '{[1.55,2.55],[4,5]}',0);
    -- {[2, 3], [4, 5]}
    
  • Devuelve la representación binaria conocida (Well-Known Binary o WKB)

    asBinary({set,spans},endian text='') → bytea

    El resultado se codifica utilizando la codificación little-endian (NDR) o big-endian (XDR). Si no se especifica ninguna codificación, se utiliza la codificación de la máquina.

    SELECT asBinary(dateset '{2001-01-01, 2001-01-03}');
    -- \x01050001020000006e01000070010000
    SELECT asBinary(intspan '[1, 3)');
    -- \x011300010100000003000000
    SELECT asBinary(floatspanset '{[1, 2], [4, 5]}', 'XDR');
    -- \x00000e00000002033ff000000000000040000000000000000340100000000000004014000000000000
    
  • Devuelve la representación hexadecimal binaria conocida (HexWKB) en formato texto

    asHexWKB({set,spans},endian text='') → text

    El resultado se codifica utilizando la codificación little-endian (NDR) o big-endian (XDR). Si no se especifica ninguna codificación, se utiliza la codificación de la máquina.

    SELECT asHexWKB(dateset '{2001-01-01, 2001-01-03}');
    -- 01050001020000006E01000070010000
    SELECT asHexWKB(intspan '[1, 3)');
    -- 011300010100000003000000
    SELECT asHexWKB(floatspanset '{[1, 2], [4, 5]}', 'XDR');
    -- 00000E00000002033FF000000000000040000000000000000340100000000000004014000000000000
    
  • Devuelve a partir de la representación binaria conocida (WKB)

    settypeFromBinary(bytea) → set

    spantypeFromBinary(bytea) → span

    spansettypeFromBinary(bytea) → spanset

    Hay una función por tipo de conjunto o de rango, el nombre de la función tiene como prefijo el nombre del tipo.

    SELECT datesetFromBinary('\x01050001020000006e01000070010000');
    -- {2001-01-01, 2001-01-03}
    SELECT intspanFromBinary('\x011300010100000003000000');
    -- [1, 3)
    SELECT floatspansetFromBinary(
      '\x00000e00000002033ff000000000000040000000000000000340100000000000004014000000000000');
    -- {[1, 2], [4, 5]}
    
  • Devuelve a partir de la representación hexadecimal binaria conocida (HexWKB)

    settypeFromHexWKB(text) → set

    spantypeFromHexWKB(text) → span

    spansettypeFromHexWKB(text) → spanset

    Hay una función por tipo de conjunto o de rango, el nombre de la función tiene como prefijo el nombre del tipo.

    SELECT datesetFromHexWKB('01050001020000006E01000070010000');
    -- {2001-01-01, 2001-01-03}
    SELECT intspanFromHexWKB('011300010100000003000000');
    -- [1, 3)
    SELECT floatspansetFromHexWKB(
      '00000E00000002033FF000000000000040000000000000000340100000000000004014000000000000');
    -- {[1, 2], [4, 5]}