Eu tenho dois não public
-esquemas em um banco de dados. Uma tabela chamada "foo"
existe em ambos os esquemas e posso executar todos os comandos DDL e DML necessários em ambos. No entanto, quando executo \d
, não consigo ver os dois. O que da?
Reprodução
create schema a;
create schema b;
create table a.foo (i int);
create table b.foo (i int);
set search_path = "$user", public, a, b;
Dentropsql
postgres=# \d
List of relations
Schema | Name | Type | Owner
--------+-----------+-------+------------
a | foo | table | pvandivier
(1 row)
Eu \set ECHO_HIDDEN on
para extrair a consulta subjacente executada \d
e movi as linhas relevantes da WHERE
cláusula SELECT
para examinar as diferenças entre os dois objetos de tabela.
SELECT n.nspname as "Schema",
c.relname as "Name",
CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized view' WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 's' THEN 'special' WHEN 'f' THEN 'foreign table' WHEN 'p' THEN 'partitioned table' WHEN 'I' THEN 'partitioned index' END as "Type",
pg_catalog.pg_get_userbyid(c.relowner) as "Owner",
pg_catalog.pg_table_is_visible(c.oid),
n.nspname,
c.relkind
FROM pg_catalog.pg_class c
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname IN ('a','b')
ORDER BY 1,2;
A execução desta consulta revela...
Schema | Name | Type | Owner | pg_table_is_visible | nspname | relkind
--------+------+-------+------------+---------------------+---------+---------
a | foo | table | pvandivier | t | a | r
b | foo | table | pvandivier | f | b | r
A diferença relevante parece ser a saída de pg_table_is_visible()
. Mas por que deveria retornar " False
" ao perguntar se b.foo
está visível?
Por que está
pg_table_is_visible()
retornandoFalse
para uma mesa a que tenho acesso?
O conceito
is_visible
aqui parece significar " o primeiro que você vê nosearch_path
"; e não " você pode vê-lo ". Você pode demonstrar isso por si mesmo alterando a ordem dos esquemas no arquivosearch_path
.Observe que
b.foo
é retornado quandob
é listado primeiro no arquivosearch_path
. Isso também é suportado pela saída da consulta anterior re-executada no mesmo arquivosearch_path
.Agora podemos ver claramente que
pg_table_is_visible()
éTrue
parab
eFalse
paraa
. Portanto, "is_visible
" é um indicador de acessibilidade atual e não um indicador da existência de uma relação.Observe que tentar determinar a visibilidade de um objeto inexistente tem um conjunto diferente de comportamentos.
Você também pode ler isso um pouco na fonte em src/backend/catalog/namespace.c. Não sou fluente em C, mas as citações a seguir parecem apoiar esse raciocínio.
RelationIsVisible
RelationIsVisible
revela os seguintes comentários de código logo acima da lógica de retorno