Que signifie regclass dans Postgresql

J'ai la ligne suivante dans une instruction CREATE TABLE:

field1_id bigint DEFAULT nextval('table1_field1_id_seq'::regclass) NOT NULL,

Que signifie regclass dans ce qui précède? Est-ce une exigence absolue d'ajouter ::regclass?

N. B: j'avais vu la documentation Postgresql link qui parle de regclass, mais je ne pouvais pas le comprendre.

33
demandé sur Craig Ringer 2012-11-08 16:26:00

2 réponses

Non, vous n'avez pas besoin de la distribution à regclass lors de l'appel d'une fonction comme nextval qui accepte un paramètre regclass, car il y a une distribution implicite de text à regclass. Dans d'autres contextes, une distribution explicite à regclass peut être requise.

Explication:

::regclass est un casting, comme ::integer.

regclass est une "magie" type de données; c'est en fait un alias pour oid, ou "identificateur d'objet". Voir types D'identificateur D'objet dans la documentation. Le Casting à regclass est un raccourci façon de dire "c'est le nom d'une relation, veuillez le convertir en oid de cette relation". Les conversions vers {[3] } sont au courant du search_path, contrairement à l'interrogation pg_class pour une relation oid directement, donc la conversion en regclass n'est pas exactement équivalente à la sous-requête pg_class.

Les Tables sont des relations. Tout comme les séquences et les vues. Ainsi, vous pouvez obtenir l'oid d'une vue ou d'une séquence en convertissant aussi en regclass.

Il y a des conversions implicites définies pour text à regclass, donc si vous omettez l' distribution explicite et vous appelez une fonction qui accepte regclass la distribution est effectuée automatiquement. Donc, vous n'avez pas besoin de dans les appels nextval, par exemple.

Il y a d'autres endroits où vous pouvez. Par exemple, vous ne pouvez pas comparer text directement avec oid; Vous pouvez donc faire ceci:

regress=> select * from pg_class where oid = 'table1'::regclass;

, Mais pas ceci:

regress=> select * from pg_class where oid = 'table1';
ERROR:  invalid input syntax for type oid: "table1"
LINE 1: select * from pg_class where oid = 'table1';

Juste pour le plaisir, j'ai essayé d'écrire une requête qui effectuait l'opération équivalente de coulée à regclass. Ne l'utilisez pas, c'est surtout pour le plaisir, et comme un essayez de démo ce qui se passe réellement. Sauf si vous êtes vraiment intéressé par la façon dont les tripes de Pg fonctionnent, vous pouvez arrêter de lire ici.

Si je comprends bien, 'sequence_name'::regclass::oid est à peu près équivalent à la requête suivante:

WITH sp(sp_ord, sp_schema) AS (
  SELECT 
    generate_series(1, array_length(current_schemas('t'),1)),
    unnest(current_schemas('t'))
)
SELECT c.oid
FROM pg_class c INNER JOIN pg_namespace n ON (c.relnamespace = n.oid)
INNER JOIN sp ON (n.nspname = sp.sp_schema)
WHERE c.relname = 'sequence_name'
ORDER BY sp.sp_ord
LIMIT 1;

, Sauf que c'est beaucoup plus court et beaucoup plus vite. Voir fonctions D'information Système pour la définition de current_schemas(...), etc.

En d'autres termes:

  • obtenez un tableau ab listant tous les schémas auxquels nous avons accès et associez chaque entrée avec un nombre ordinal pour sa position dans le tableau
  • Recherche pg_class les relations avec les noms correspondants et associe chacun à son espace de noms (schéma)
  • trie la liste des relations restantes selon l'ordre dans lequel leurs schémas apparaissent dans search_path
  • et choisissez le premier match
48
répondu Craig Ringer 2012-11-09 05:14:57

D'après ce que je comprends de la documentation, les oid sont subdivisés en types. regclass sont des objets de base de données représentant des relations (de sorte qu'ils appartiennent à la table de métadonnées pg_class).

Il exprime une dépendance entre la séquence et l'expression DEFAULT (ce qui signifie le processus de production d'une valeur par défaut si aucune valeur explicite n'est fournie dans une requête INSERT par exemple), de sorte que si l'on émet un DROP SEQUENCE ... sur la séquence, la requête ne passera pas, sauf si elle est en cascade (en écrivant DROP SEQUENCE table1_field1_id_seq CASCADE).

0
répondu didierc 2012-11-09 09:39:03