web-dev-qa-db-fra.com

Liste des contraintes pour toutes les tables avec différents propriétaires dans PostgreSQL

Dois-je être propriétaire de la relation avec les données liées aux contraintes d'accès dans le schéma d'information? J'ai testé les éléments suivants et il semble que je dois en être le propriétaire.

create schema rights_test;

create table rights_test.t1 (id int primary key);
create table rights_test.t2 (id int references rights_test.t1(id));

select  
        tc.constraint_name, 
        tc.constraint_schema || '.' || tc.table_name || '.' || kcu.column_name as physical_full_name,  
        tc.constraint_schema,
        tc.table_name, 
        kcu.column_name, 
        ccu.table_name as foreign_table_name, 
        ccu.column_name as foreign_column_name,
        tc.constraint_type
    from 
        information_schema.table_constraints as tc  
        join information_schema.key_column_usage as kcu on (tc.constraint_name = kcu.constraint_name and tc.table_name = kcu.table_name)
        join information_schema.constraint_column_usage as ccu on ccu.constraint_name = tc.constraint_name
    where 
        constraint_type in ('PRIMARY KEY','FOREIGN KEY')
        and tc.constraint_schema = 'rights_test'

/*
This will produce desired output:
t1_pkey;rights_test.t1.id;rights_test;t1;id;t1;id;PRIMARY KEY
t2_id_fkey;rights_test.t2.id;rights_test;t2;id;t1;id;FOREIGN KEY
*/

create user rights_test_role with password 'password';

grant all on rights_test.t1 to rights_test_role;
grant all on rights_test.t2 to rights_test_role;

/* Now login as rights_test_role and try the same constraint select.
   For rights_test_role it returns nothing although I've added ALL privileges
*/

Existe-t-il un autre moyen d'obtenir la même information si je ne suis pas propriétaire de la relation?

13
Tomas Greif

Toutes les données liées aux contraintes ne sont pas "protégées". Vous utilisez trois relations dans votre requête:

  • table_constraints
  • key_column_usage
  • constraint_column_usage

Les deux premiers ne sont pas limités, mais la documentation de constraint_column_usage vous indique: 

La vue constraint_column_usage identifie toutes les colonnes de la base de données actuelle utilisées par une contrainte. Seules les colonnes indiquées sont contenues dans une table appartenant à un rôle actuellement activé.

information_schema.constraint_column_usage étant une vue, vous pouvez voir sa définition en utilisant 

\d+ information_schema.constraint_column_usage

dans le shell psql. Le résultat semble effrayant au premier abord, mais ce n'est pas si grave. La chose la plus intéressante - pour un premier test - est la partie de la dernière ligne: 

  WHERE pg_has_role(x.tblowner, 'USAGE'::text);

Si vous collez la définition dans le shell psql ouvert par le non-propriétaire rights_test_role et supprimez cette dernière ligne, vous obtiendrez le résultat souhaité. C’est bien, car cela signifie que les métadonnées de base ne sont pas protégées par le système. Vous pouvez donc supprimer la définition de vue pour n’inclure que les éléments dont vous avez réellement besoin. 

9
A.H.

Essayez d'utiliser ceci .. donne tous les noms de contrainte et description de contrainte.

  • Foreign key
  • Vérifier
  • Clé primaire
  • Unique

Comme: 

select conrelid::regclass AS table_from, conname, pg_get_constraintdef(c.oid)
from   pg_constraint c
join   pg_namespace n ON n.oid = c.connamespace
where  contype in ('f', 'p','c','u') order by contype
20

Pour lister les contraintes relationnelles, vous pouvez utiliser la requête suivante:

SELECT
    tc.constraint_name, tc.table_name, kcu.column_name, 
    ccu.table_name AS foreign_table_name,
    ccu.column_name AS foreign_column_name 
FROM 
    information_schema.table_constraints AS tc 
    JOIN information_schema.key_column_usage AS kcu
      ON tc.constraint_name = kcu.constraint_name
    JOIN information_schema.constraint_column_usage AS ccu
      ON ccu.constraint_name = tc.constraint_name
WHERE constraint_type = 'FOREIGN KEY'
0
Eugen Konkov