J'écris un script de configuration pour une application qui est un addon pour une autre application, donc je veux vérifier si les tables de l'autre application existent. Sinon, je veux donner à l'utilisateur une erreur utile. Cependant, je ne sais pas quel schéma contiendra les tables.
DO LANGUAGE plpgsql $$
BEGIN
PERFORM 1
FROM
pg_catalog.pg_class c
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE
n.nspname = current_setting('search_path')
AND c.relname = 'foo'
AND c.relkind = 'r'; -- not sure if I actually need this or not...
IF NOT FOUND THEN
RAISE 'This application depends on tables created by another application';
END IF;
END;
$$;
Cependant, current_setting('search_path')
renvoie un TEXTE contenant "$user",public
Par défaut, ce qui n'est pas très utile.
La seule autre chose à laquelle je peux penser est d'essayer de sélectionner dans le tableau et de saisir l'exception. Cela ferait l'affaire, mais je ne pense pas qu'il soit très élégant et j'ai lu qu'il est cher à utiliser (bien que ce serait peut-être correct dans ce scénario car je ne fais que courir une fois?).
Dans Postgres 9.4 + utilisez
SELECT to_regclass('foo');
Renvoie NULL si l'identifiant n'est pas trouvé dans le chemin de recherche.
Dans Postgres 9.3 ou plus ancien utilisez un transtypé en regclass
:
SELECT 'foo'::regclass;
Ceci déclenche une exception, si l'objet n'est pas trouvé!
Si 'foo'
est trouvé, le oid
est retourné dans sa représentation text
. C'est juste le nom de la table, qualifié par le schéma en fonction du chemin de recherche actuel et placé entre guillemets si nécessaire.
Si l'objet n'est pas trouvé, vous pouvez être bien sûr il n'existe nulle part dans le chemin de recherche - ou pas du tout pour un nom qualifié par le schéma (schema.foo
).
S'il est trouvé, il y a deux défauts :
La recherche inclut des schémas implicites de search_path , à savoir pg_catalog
et pg_temp
. Mais vous souhaiterez peut-être exclure les tables temporaires et système pour votre usage. (?)
Un transtypage en regclass
fonctionne pour tous les objets du catalogue système pg_class
: index, vues, séquences etc. Pas seulement des tables. Vous semblez rechercher une table régulière exclusivement. Cependant, vous aurez probablement aussi des problèmes avec d'autres objets du même nom. Détails:
Nous revenons à votre requête, mais n'utilisez pas , qui renvoie le paramètre nu. Utilisez la fonction d'informations système dédiée current_setting('search_path')
current_schemas()
. Par documentation:
current_schemas(boolean)
name[]
noms des schémas dans le chemin de recherche, y compris éventuellement les schémas implicites
"$user"
dans le chemin de recherche est résolu intelligemment. Si aucun schéma portant le nom de SESSION_USER
n'existe, le schéma n'est pas renvoyé pour commencer. En outre, selon ce que vous voulez exactement, vous pouvez également générer des schémas implicites (pg_catalog
et éventuellement pg_temp
) - mais je suppose que vous ne les voulez pas pour le cas présent, donc utilisation:
DO
$do$
BEGIN
IF EXISTS (
SELECT -- list can be empty
FROM pg_catalog.pg_class c
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname = ANY(current_schemas(FALSE))
AND n.nspname NOT LIKE 'pg_%' -- exclude system schemas!
AND c.relname = 'foo'
AND c.relkind = 'r') -- you probably need this
THEN
RAISE 'This application depends on tables created by another application';
END IF;
END
$do$;
SQL Fiddle , montrant tout sauf la dernière instruction DO
.
SQL Fiddle (JDBC) a des problèmes avec les instructions DO
contenant des caractères de terminaison.
Vous pouvez convertir la valeur de configuration en un tableau et remplacer le $user
avec le nom d'utilisateur actuel. Le tableau peut ensuite être utilisé dans la condition where:
where n.nspname = any(string_to_array(replace(current_setting('search_path'), '$user', current_user), ','))
./sshi.sh vb20deployment controller <<'HERE'
export PGPASSWORD="postgres"
cd logu/postgresql/bin
row=1
tableArray=(table1 table2 table3 table4 table5 table6)
for (( x=0 ; x<=5 ; x++)) ; do
./psql.bin --port=5432 --username=postgres --Host=hostname.rds.amazonaws.com --dbname=mydb -c "SELECT * FROM information_schema.tables WHERE '${tableArray[$x]}' = table_name" | while read -a Record ; do
row=$((row + 1))
if [[ $row -gt 3 ]]; then
echo ${Record[4]}
fi
done
done
HERE