Eu queria criar uma visão que somasse uma tabela comum a vários esquemas, conforme expresso aqui , e incluísse o nome do esquema ou uma expressão derivada como uma coluna, então criei uma visão que inclui o nome do esquema como um valor constante, por usando o quote_literal
para colocar o nome do esquema entre aspas simples.
Pode quote_literal
não ser a função correta aqui, mas tudo o que eu faço fica entre aspas duplas.
CREATE OR REPLACE FUNCTION create_summary_view_quoted(
created_view text,
common_view text,
VARIADIC schemas text[]
) RETURNS text
LANGUAGE sql AS
$$SELECT format('CREATE VIEW %I AS ', created_view) ||
string_agg(
format('SELECT %I as source_schema, * FROM %I.%I ', quote_literal(schemas[i]) , schemas[i], common_view),
' UNION ALL '
)
FROM generate_series(1, cardinality(schemas)) AS i$$;
")
Aplicando-o à consulta
SELECT create_summary_view_quoted('newv', 'oldv', 's1', 's2', 's3');
produz
create view newv as
select
"'s1'" as source_schema,
*
from
s1.oldv
union all
select
"'s2'" as source_schema,
*
from
s2.oldv
union all
select
"'s3'" as source_schema,
*
from
s3.oldv
O problema são as aspas duplas em torno da constante entre aspas simples que faz com que o Postgres trate como um nome de coluna e vomite.
Corrigi o problema de geração de código usando aspas simples duplas no primeiro espaço reservado e descartando a quote_literal
função,
ou seja, substituir
format('SELECT %I as source_schema, * FROM %I.%I ', quote_literal(schemas[i]) , schemas[i], common_view),
com
format('SELECT ''%I'' as source_schema, * FROM %I.%I ', schemas[i] , schemas[i], common_view),
Meu problema não é tanto, quote_literal
mas como a função sempre envolve a saída de qualquer função que envolve uma string entre aspas simples e aspas duplas.
Mesmo quando usei uma função para retirar um sufixo inicial nos nomes dos esquemas porque eles são redundantes, a saída entre aspas simples é colocada entre aspas duplas.
por exemplo, quote_nullable(right(schemas[i],-10))
a string resultante fica entre aspas duplas.
Eu poderia aplicar o ||
operador em algum lugar, mas prefiro uma função de cotação.
O Postgres não possui uma função integrada de aspas simples?
Há alguma sintaxe SQL necessária que estou faltando?
É uma peculiaridade do Postgres?
O
%I
especificador de tipo de formato diz àformat()
função para tratar o valor do argumento correspondente como um identificador e, como contém aspas simples (como resultado dequote_literal()
), é devidamente colocado entre aspas duplas para torná-lo um identificador válido.No entanto, na
SELECT
lista você deseja que o nome do esquema seja uma string literal simples, portanto o%s
especificador de tipo será apropriado.Talvez você também possa dispensar
quote_literal()
, se souber a origem dos nomes dos esquemas e tiver certeza de que eles não contêm aspas simples: