PostgreSQLLa base de données la plus sophistiquée au monde.

Version anglaise

F.9. cube

Ce module code le type de données cube pour représenter des cubes à plusieurs dimensions.

F.9.1. Syntaxe

Tableau F.3, « Représentations externes d'un cube » affiche les représentations externes valides pour le type cube. x, y, etc. dénotent des nombres flottants.

Tableau F.3. Représentations externes d'un cube

Syntaxe externe Signification
x point uni-dimensionnel (ou interval unidimensionnel de longueur nulle)
(x) Identique à ci-dessus
x1,x2,...,xn Un point dans un espace à n dimensions, représenté en interne comme un cube de volume nul
(x1,x2,...,xn) Identique à ci-dessus
(x),(y) Interval uni-dimensionnel débutant à x et finissant à y ou vice-versa ; l'ordre n'importe pas
[(x),(y)] Identique à ci-dessus
(x1,...,xn),(y1,...,yn) Cube à n dimensions représenté par paires de coins diagonalement opposés
[(x1,...,xn),(y1,...,yn)] Identique à ci-dessus

L'ordre de saisie des coins opposés d'un cube n'a aucune importance. Les fonctions cube s'occupent de la bascule nécessaire à l'obtention d'une représentation uniforme « bas gauche, haut droit ». Quand les coins coincident, le type cube enregistre un coin ainsi que le drapeau « is point » pour éviter de perdre de l'espace.

Les espaces sont ignorées, [(x),(y)] est donc identique à [ ( x ), ( y ) ].

F.9.2. Précision

Les valeurs sont enregistrées en interne sous la forme de nombres en virgule flottante. Cela signifie que les nombres avec plus de 16 chiffres significatifs sont tronqués.

F.9.3. Utilisation

Tableau F.4, « Opérateurs pour cube » affiche les opérateurs fournis par le type cube.

Tableau F.4. Opérateurs pour cube

Opérateur Résultat Description
a = b boolean Les cubes a et b sont identiques.
a && b boolean Les cubes a et b se chevauchent.
a @> b boolean Le cube a contient le cube b.
a <@ b boolean Le cube a est contenu dans le cube b.
a < b boolean Le cube a est inférieur au cube b.
a <= b boolean Le cube a est inférieur au égal au cube b.
a > b boolean Le cube a est plus grand que le cube b.
a >= b boolean Le cube a est plus grand ou égam au cube b.
a <> b boolean Le cube a est différent du cube b.
a -> n float8 Obtient la n-ième coordonnée du cube (compteur à partir de 1).
a ~> n float8 Obtient la n-ième coordonnée du cube de la façon suivante : n = 2 * k - 1 signifie la limite basse de la k-ième dimension, n = 2 * k signifie la limite haute de la k-ième dimension. Cet opérateur est conçu pour le support de KNN-GiST.
a <-> b float8 Distance euclidienne entre a et b.
a <#> b float8 Distance Taxicab (métrique L-1) entre a et b.
a <=> b float8 Distance Chebyshev (métrique L-inf) entre a et b.

(Avant PostgreSQL 8.2, les opérateurs de contenance @> et <@ étaient appelés respectivement @ et ~. Ces noms sont toujours disponibles mais sont déclarés obsolètes et seront supprimés un jour. Les anciens noms sont inversés par rapport à la convention suivie par les types de données géométriques !)

Les opérateurs d'ordre scalaire (<, >=, etc) n'ont pas réellement de sens pour tout sens pratique en dehors de tri. Ces opérateurs comparent tout d'abord les premiers coordonnées et, si ces derniers sont égaux, comparent les deuxièmes coordonnées. Ils existent principalement pour supporter la classe d'opérateur d'index b-tree pour cube, qui peut seulement être utile par exemple si vous souhaitez une contrainte UNIQUE sur une colonne cube.

Le module cube fournit aussi une classe d'opérateur pour index GiST pour les valeurs cube. Un index GiST peut être utilisé sur le type cube pour chercher des valeurs en utilisant les opérateurs =, &&, @> et <@ dans les clauses WHERE.

De plus, un index GiST cube peut être utilisé pour trouver les plus proches voisins en utilisant les opérateurs de métriques <->, <#> et <=> dans les clauses ORDER BY. Par exemple, le plus proche voisin du point 3-D (0.5, 0.5, 0.5) peut être trouvé de façon efficace avec :

SELECT c FROM test ORDER BY c <-> cube(array[0.5,0.5,0.5]) LIMIT 1;
   

L'opérateur ~> peut aussi être utilisé de cette façon pour récupérer efficacement les premières valeurs triées par une coordonnée sélectionnée. Par exemple, pour obtenir les quelques premiers cubes triés par la première coordonnée (coin bas gauche) ascendante, il est possible d'utiliser la requête suivante :

SELECT c FROM test ORDER BY c ~> 1 LIMIT 5;
   

Et pour obtenir des cubes 2-D triés par la première coordonnée du coin haut droit descendant :

SELECT c FROM test ORDER BY c ~> 3 DESC LIMIT 5;
   

Tableau F.5, « Fonctions cube » indique les fonctions disponibles.

Tableau F.5. Fonctions cube

Fonction Résultat Description Exemple
cube(float8) cube Crée un cube uni-dimensionnel de coordonnées identiques. cube(1) == '(1)'
cube(float8, float8) cube Crée un cube uni-dimensionnel. cube(1,2) == '(1),(2)'
cube(float8[]) cube Crée un cube de volume nul en utilisant les coordonnées définies par le tableau. cube(ARRAY[1,2]) == '(1,2)'
cube(float8[], float8[]) cube Crée un cube avec les coordonnées haut droit et bas gauche définies par deux tableaux de flottants, obligatoirement de même taille. cube(ARRAY[1,2], ARRAY[3,4]) == '(1,2),(3,4)'
cube(cube, float8) cube Créer un nouveau cube en ajoutant une dimension à un cube existant, avec les mêmes valeurs pour les deux points finaux de la nouvelle coordonnée. Ceci est utile pour construire des cubes pièce par pièce à partir des valeurs calculées. cube('(1,2),(3,4)'::cube, 5) == '(1,2,5),(3,4,5)'
cube(cube, float8, float8) cube Crée un nouveau cube en ajoutant une dimension à un cube existant. Ceci est utile pour construire des cubes pièce par pièce à partir de valeurs calculées. cube('(1,2),(3,4)'::cube, 5, 6) == '(1,2,5),(3,4,6)'
cube_dim(cube) integer Renvoie le nombe de dimensions du cube. cube_dim('(1,2),(3,4)') == '2'
cube_ll_coord(cube, integer) float8 Renvoie la n-ième coordonnée pour le coin bas gauche du cube. cube_ll_coord('(1,2),(3,4)', 2) == '2'
cube_ur_coord(cube, integer) float8 Renvoie la n-ième valeur de coordonnée pour le coin haut à droite du cube. cube_ur_coord('(1,2),(3,4)', 2) == '4'
cube_is_point(cube) boolean Renvoie true si le cube est un point, autrement dit si les deux coins de définition sont identiques.
cube_distance(cube, cube) float8 Renvoie la distance entre deux cubes. Si les deux cubes sont des points, il s'agit de la fonction de distance habituelle.
cube_subset(cube, integer[]) cube Crée un nouveau cube à partir d'un cube existant, en utilisant une liste d'index de dimension à partir d'un tableau. Peut être utilisé pour extraire les points finaux d'une seule dimension ou pour supprimer les dimensions ou pour les réordonner comme souhaité. cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[2]) == '(3),(7)' cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[3,2,1,1]) == '(5,3,1,1),(8,7,6,6)'
cube_union(cube, cube) cube Produit l'union de deux cubes.
cube_inter(cube, cube) cube Produit l'intersection de deux cubes.
cube_enlarge(c cube, r double, n integer) cube Augmente la taille du cube suivant le radius r spécifié sur au moins n dimensions. Si le radius est négatif, le cube est réduit. Toutes les dimensions définies sont modifiées par le radius r. Les coordonnées bas-gauche sont réduites de r et les coordonnées haut-droite sont augmentées de r. Si une coordonnée bas- gauche est augmentée suffisamment pour être plus importante que la coordonnées haute-droite (ceci peut seulement survenir quand r < 0), alors les deux coordonnées sont configurées avec leur moyenne. Si n est supérieur au nombre de dimensions définies et que le cube est grossi (r > 0), alors les dimensions supplémentaires sont ajoutées pour tout n ; 0 est utilisé comme valeur initiale pour les coordonnées supplémentaires. Cette fonction est utile pour créer les « bounding boxes » autour d'un point permettant de chercher les points les plus proches. cube_enlarge('(1,2),(3,4)', 0.5, 3) == '(0.5,1.5,-0.5),(3.5,4.5,0.5)'

F.9.4. Par défaut

Le développeur pense que l'union :

select cube_union('(0,5,2),(2,3,1)', '0');
cube_union
-------------------
(0, 0, 0),(2, 5, 2)
(1 row)
  

n'est pas en contradiction avec le bon sens. Pas plus que l'intersection

select cube_inter('(0,-1),(1,1)', '(-2),(2)');
cube_inter
-------------
(0, 0),(1, 0)
(1 row)
  

Dans toutes les opérations binaires sur des boîtes de tailles différentes, l'auteur suppose que la plus petite est une projection cartésienne, c'est-à-dire qu'il y a des zéros à la place des coordonnées omises dans la représentation sous forme de chaîne. Les exemples ci-dessus sont équivalents à :

cube_union('(0,5,2),(2,3,1)','(0,0,0),(0,0,0)');
cube_inter('(0,-1),(1,1)','(-2,0),(2,0)');
  

Le prédicat de contenance suivant utilise la syntaxe en points alors qu'en fait, le second argument est représenté en interne par une boîte. Cette syntaxe rend inutile la définition du type point et des fonctions pour les prédicats (boîte,point).

select cube_contains('(0,0),(1,1)', '0.5,0.5');
cube_contains
--------------
t
(1 row)
  

F.9.5. Notes

Pour des exemples d'utilisation, voir les tests de régression sql/cube.sql.

Pour éviter toute mauvaise utilisation, le nombre de dimensions des cubes est limité à 100. Cela se configure dans cubedata.h.

F.9.6. Crédits

Auteur d'origine : Gene Selkov, Jr. , Mathematics and Computer Science Division, Argonne National Laboratory.

F.9.7. Note de l'auteur

Mes remerciements vont tout particulièrement au professeur Joe Hellerstein (https://dsf.berkeley.edu/jmh/) qui a su extraire l'idée centrale de GiST (http://gist.cs.berkeley.edu/), et à son étudiant précédant, Andy Dong pour son exemple rédigé dans Illustra. Mes remerciements vont également aux développeurs de PostgreSQL qui m'ont permis de créer mon propre monde et de pouvoir y vivre sans être dérangé. Toute ma gratitude aussi à Argonne Lab et au département américain de l'énergie pour les années de support dans mes recherches sur les bases de données.

Des modifications mineures ont été effectuées sur ce module par Bruno Wolff III en août/septembre 2002. Elles incluent la modification de la précision (de simple à double) et l'ajout de quelques nouvelles fonctions.

Des mises à jour supplémentaires ont été réalisées par Joshua Reich en juillet 2006. Elles concernent l'ajout de cube(float8[], float8[]) et le nettoyage du code pour utiliser le protocole d'appel V1 à la place de la forme V0 maintenant obsolète.