PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Cosa significa regclass in Postgresql

No, non è necessario il cast per regclass quando si chiama una funzione come nextval che accetta una regclass parametro, poiché esiste un cast implicito da text a regclass . In altri contesti un cast esplicito a regclass potrebbe essere richiesto.

Spiegazione:

::regclass è un cast, come ::integer .

regclass è un tipo di dati "magico"; in realtà è un alias per oid o "identificatore oggetto". Vedi Tipi di identificatore di oggetto nella documentazione. Trasmetti a regclass è un modo abbreviato per dire "questo è il nome di una relazione, per favore convertilo nell'oid di quella relazione". Trasmette a regclass sono a conoscenza del search_path , a differenza della query su pg_class per un oid di una relazione direttamente, quindi trasmettere a regclass non equivale esattamente a sottoquery pg_class .

Le tabelle sono relazioni. Così sono le sequenze e le viste. Quindi puoi ottenere l'oid di una vista o sequenza eseguendo il cast anche su regclass.

Ci sono cast impliciti definiti per text a regclass , quindi se ometti il ​​cast esplicito e stai chiamando una funzione che accetta regclass il cast viene eseguito automaticamente. Quindi non ne hai bisogno, ad esempio, nextval chiamate.

Ci sono altri posti dove potresti. Ad esempio non puoi confrontare text direttamente con oid; quindi puoi farlo:

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

ma non questo:

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';

Solo per divertimento ho provato a scrivere una query che eseguisse l'operazione equivalente di eseguire il casting su regclass . Non usarlo, è principalmente per divertimento e come tentativo di dimostrare ciò che sta effettivamente accadendo. A meno che tu non sia veramente interessato a come funzionano le viscere di Pg, puoi smettere di leggere qui.

A quanto ho capito, 'sequence_name'::regclass::oid è più o meno equivalente alla seguente query:

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;

tranne per il fatto che è molto più breve e molto più veloce. Vedi Funzioni di informazioni di sistema per la definizione di current_schemas(...) , ecc.

In altre parole:

  • Ottieni un array ab che elenca tutti gli schemi a cui abbiamo accesso e abbina ogni voce a un numero ordinale per la sua posizione nell'array
  • Cerca pg_class per le relazioni con nomi corrispondenti e associare ciascuna al proprio spazio dei nomi (schema)
  • Ordina l'elenco delle relazioni rimanenti in base all'ordine in cui i loro schemi sono apparsi in search_path
  • e scegli la prima corrispondenza