Capítulo 20. Dialecto Portable de Funciones con Nombre

Todo operador de MobilityDB puede invocarse también como una función con nombre. Una consulta escrita únicamente con funciones con nombre, sin símbolos de operador, es portable: el mismo SQL se ejecuta sin cambios en todo el ecosistema MobilityDB — los motores de base de datos MobilityDB (PostgreSQL), MobilityDuck (DuckDB) y MobilitySpark (Apache Spark), y los motores de streaming —, varios de los cuales no pueden registrar símbolos de operador de PostgreSQL. Cada alias con nombre reutiliza la propia implementación del operador, por lo que devuelve exactamente el mismo resultado que el operador.

Este capítulo es la referencia canónica, a nivel de todo el ecosistema, de esa correspondencia. Un motor que no acepte un operador dado puede consultarlo aquí y usar la forma de función en su lugar. Por ejemplo, DuckDB no acepta ningún operador que contenga # (reserva # para las referencias posicionales de columna), de modo que en MobilityDuck las comparaciones temporales (#=, …) se escriben tEq, … y las pruebas de posición temporal (<<#, #>>, &<#, #&>) se escriben before, after, overbefore, overafter, mientras que los operadores que sí acepta pueden usarse directamente.

Las funciones de relación espacial (eIntersects, aIntersects, eTouches, eDwithin, …) y las funciones de restricción (atTime, atGeometry, atValue, …) son siempre funciones con nombre (no tienen operador). El comparador de ordenación de árbol B es asimismo la función con nombre cmp(a, b), que devuelve -1, 0 o 1 y no tiene operador. Cada operador se corresponde con un nombre simple de la manera siguiente; para los operadores aritméticos y de teoría de conjuntos el nombre de la función lleva el prefijo de la familia de tipos del operando (set, span o spanset, y t para los números temporales).

CategoríaOperadorFunción portable
Topología&&overlaps(a, b)
 @>contains(a, b)
 <@contained(a, b)
 -|-adjacent(a, b)
Posición temporal<<#before(a, b)
 #>>after(a, b)
 &<#overbefore(a, b)
 #&>overafter(a, b)
Espacio, eje X<<left(a, b)
 >>right(a, b)
 &<overleft(a, b)
 &>overright(a, b)
Espacio, eje Y<<|below(a, b)
 |>>above(a, b)
 &<|overbelow(a, b)
 |&>overabove(a, b)
Espacio, eje Z<</front(a, b)
 />>back(a, b)
 &</overfront(a, b)
 /&>overback(a, b)
Comparación temporal#=tEq(a, b)
 #<>tNe(a, b)
 #<tLt(a, b)
 #<=tLe(a, b)
 #>tGt(a, b)
 #>=tGe(a, b)
Distancia<->tDistance(a, b)
 |=|nearestApproachDistance(a, b)
Igual~=same(a, b)
Comparación tradicional=eq(a, b)
 <>ne(a, b)
 <lt(a, b)
 <=le(a, b)
 >gt(a, b)
 >=ge(a, b)
Comparación alguna vez?=eEq(a, b)
 ?<>eNe(a, b)
 ?<eLt(a, b)
 ?<=eLe(a, b)
 ?>eGt(a, b)
 ?>=eGe(a, b)
Comparación siempre%=aEq(a, b)
 %<>aNe(a, b)
 %<aLt(a, b)
 %<=aLe(a, b)
 %>aGt(a, b)
 %>=aGe(a, b)
Booleano (booleano temporales)&tAnd(a, b)
 |tOr(a, b)
 ~tNot(a)
Aritmética (números temporales)+tAdd(a, b)
 -tSub(a, b)
 *tMul(a, b)
 /tDiv(a, b)
Unión (set / span / span set)+setUnion / spanUnion / spansetUnion (a, b)
Intersección (set / span / span set)*setIntersection / spanIntersection / spansetIntersection (a, b)
Diferencia (set / span / span set)-setMinus / spanMinus / spansetMinus (a, b)

Por ejemplo, la superposición de cajas envolventes t1.trip && t2.trip se escribe de forma portable como overlaps(t1.trip, t2.trip), y la prueba temporal «antes» p1.period <<# p2.period como before(p1.period, p2.period).

Las funciones de agregación siguen el mismo principio y se enumeran en su propia tabla a continuación, de modo que un motor pueda localizar la maquinaria que necesita sin rastrear el texto. Una agregación SQL se compone de hasta tres funciones de la maquinaria de PostgreSQL, cada una expuesta bajo un nombre canónico formado a partir del nombre de la agregación y su rol: una función de transición <agregación>Transition (siempre presente), una función de combinación <agregación>Combine usada para la agregación en paralelo, y una función final <agregación>Final. Los roles de combinación y final son opcionales: una agregación cuyo estado de transición ya es su resultado no tiene función final (por ejemplo extent y minDistance), y una agregación que no admite la agregación parcial no tiene función de combinación (por ejemplo las agregaciones de anexado). Los roles se mantienen distintos y con un nombre uniforme para que cada binding pueda reconstruir la agregación a partir del catálogo. La siguiente tabla enumera cada agregación y sus funciones de maquinaria; un guion (—) indica un rol que la agregación no define.

CategoríaTransiciónCombinaciónFinal
ConteotCountTransitiontCountCombinetCountFinal
 wCountTransitionwCountCombinewCountFinal
SumatSumTransitiontSumCombinetSumFinal
 wSumTransitionwSumCombinewSumFinal
PromediotAvgTransitiontAvgCombinetAvgFinal
 wAvgTransitionwAvgCombinewAvgFinal
Mínimo / máximotMinTransitiontMinCombinetMinFinal
 tMaxTransitiontMaxCombinetMaxFinal
 wMinTransitionwMinCombinewMinFinal
 wMaxTransitionwMaxCombinewMaxFinal
BooleanotAndTransitiontAndCombinetAndFinal
 tOrTransitiontOrCombinetOrFinal
CentroidetCentroidTransitiontCentroidCombinetCentroidFinal
Nube de puntostnpointsTransitiontnpointsCombinetnpointsFinal
 tdensityTransitiontdensityCombinetdensityFinal
Caja delimitadoraextentTransitionextentCombine
DistanciaminDistanceTransitionminDistanceCombine
UniónsetUnionTransitionsetUnionCombinesetUnionFinal
 spanUnionTransitionspanUnionCombinespanUnionFinal
 spansetUnionTransitionspansetUnionCombinespansetUnionFinal
FusiónmergeTransitionmergeCombinemergeFinal
AnexadoappendInstantTransitionappendInstantFinal
 appendSequenceTransitionappendSequenceFinal