Le module intarray fournit un certain nombre de fonctions et d'opérateurs utiles pour manipuler des tableaux d'entiers sur une dimension. Il y a aussi un support pour les recherches par index en utilisant certains des opérateurs.
Tableau F.7. Fonctions intarray
Fonction | Type en retour | Description | Exemple | Résultat |
---|---|---|---|---|
icount(int[]) | int | nombre d'éléments dans un tableau | icount('{1,2,3}'::int[]) | 3 |
sort(int[], text dir) | int[] | tri du tableau -- dir doit valoir asc ou desc | sort('{1,2,3}'::int[], 'desc') | {3,2,1} |
sort(int[]) | int[] | tri en ordre ascendant | sort(array[11,77,44]) | {11,44,77} |
sort_asc(int[]) | int[] | tri en ordre descendant | ||
sort_desc(int[]) | int[] | tri en ordre descendant | ||
uniq(int[]) | int[] | supprime les duplicats adjacents | uniq(sort('{1,2,3,2,1}'::int[])) | {1,2,3} |
idx(int[], int item) | int | index du premier élément correspondant à item (0 si aucune correspondance) | idx(array[11,22,33,22,11], 22) | 2 |
subarray(int[], int start, int len) | int[] | portion du tableau commençant à la position start, de longueur len | subarray('{1,2,3,2,1}'::int[], 2, 3) | {2,3,2} |
subarray(int[], int start) | int[] | portion du tableau commençant à la position start | subarray('{1,2,3,2,1}'::int[], 2) | {2,3,2,1} |
intset(int) | int[] | crée un tableau à un élément | intset(42) | {42} |
Tableau F.8. Opérateurs d'intarray
Opérateur | Renvoie | Description |
---|---|---|
int[] && int[] | boolean | surcharge -- true si les tableaux ont au moins un élément en commun |
int[] @> int[] | boolean | contient -- true si le tableau gauche contient le tableau droit |
int[] <@ int[] | boolean | est contenu -- true si le tableau gauche est contenu dans le tableau droit |
# int[] | int | nombre d'éléments dans le tableau |
int[] # int | int | index (identique à la fonction idx) |
int[] + int | int[] | pousse l'élément dans le tableau (l'ajoute à la fin du tableau) |
int[] + int[] | int[] | concaténation de tableau (le tableau à droite est ajouté à la fin du tableau à gauche) |
int[] - int | int[] | supprime les entrée correspondant à l'argument droit du tableau |
int[] - int[] | int[] | supprime les éléments du tableau droit à partir de la gauche |
int[] | int | int[] | union des arguments |
int[] | int[] | int[] | union des tableaux |
int[] & int[] | int[] | intersection des tableaux |
int[] @@ query_int | boolean | true si le tableau satisfait la requête (voir ci-dessous) |
query_int ~~ int[] | boolean | true si le tableau satisfait la requête (commutateur de @@) |
Avant PostgreSQL 8.2, les opérateurs de contenance @> et <@ étaient appelés respectivement @ et ~. Ces noms sont toujours disponibles mais sont devenus obsolètes et pourraient éventuellement être supprimés. Notez que les anciens noms sont inversés par rapport à la convention suivie par les types de données géométriques.
Les opérateurs @@ et ~~ testent si un tableau satisfait une requête, qui est exprimée comme une valeur d'un type de données spécialisé query_int. Une requête consiste en des valeurs de type integer qui sont vérifiées avec les éléments du tableau, parfois combinées en utilisant les opérateurs & (AND), | (OR) et ! (NOT). Les parenthèses peuvent être utilisées si nécessaire. Par exemple, la requête 1&(2|3) établit une correspondance avec les tableaux qui contiennent 1 et aussi soit 2 soit 3.
intarray fournit un support des index pour les opérateurs &&, @>, <@ et @@, ainsi qu'une égalité des tableaux standards. L'implémentation utilise une structure de données RD-tree avec une compression interne à perte.
Deux classes d'opérateur pour index GiST sont fournies : gist__int_ops (utilisé par défaut) convient pour des tableaux de petites et moyennes tailles alors que gist__intbig_ops utilise une signature plus importante et est donc plus intéressant pour indexer des gros tableaux.
Il y a aussi une classe d'opérateur GIN,gin__int_ops, qui n'est pas disponible par défaut.
Le choix d'un indexage GiST ou IN dépend des caractéristiques relatives de performance qui sont discutées ailleurs. Comme règle de base, un index GIN est plus rapide pour la recherche qu'un index GiST mais plus lent pour la construction et la mise à jour ; donc GIN est préférable pour des données statiques et GiST pour des données souvent mises à jour.
-- un message peut être dans un ou plusieurs « sections »
CREATE TABLE message (mid INT PRIMARY KEY, sections INT[], ...);
-- crée un index spécialisé
CREATE INDEX message_rdtree_idx ON message USING GIST (sections gist__int_ops);
-- sélectionne les messages dans la section 1 ou 2 - opérateur OVERLAP
SELECT message.mid FROM message WHERE message.sections && '{1,2}';
-- sélectionne les messages dans sections 1 et 2 - opérateur CONTAINS
SELECT message.mid FROM message WHERE message.sections @> '{1,2}';
-- idem, en utilisant l'opérateur QUERY
SELECT message.mid FROM message WHERE message.sections @@ '1&2'::query_int;
Le répertoire des sources (contrib/intarray/bench) contient une suite de tests de performance. Pour l'exécuter :
cd .../bench createdb TEST psql TEST < ../_int.sql ./create_test.pl | psql TEST ./bench.pl
Le script bench.pl contient un grand nombre d'options. Elles sont affichées quand il est exécuté sans arguments.
Ce travail a été réalisé par Teodor Sigaev (<teodor@stack.net>) et Oleg Bartunov (<oleg@sai.msu.su>). Voir le site de GiST pour des informations supplémentaires. Andrey Oktyabrski a fait un gros travail en ajoutant des nouvelles fonctions et opérateurs.