Як я можу визначити, чи існує таблиця на поточному пошуковому шляху з PLPGSQL?


10

Я пишу сценарій налаштування для програми, яка є додатком для іншої програми, тому я хочу перевірити, чи існують таблиці для іншого додатка. Якщо ні, я хочу надати користувачеві корисну помилку. Однак я не знаю, яка схема буде містити таблиці.

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

Однак current_setting('search_path')повертає TEXT, що містить "$user",publicза замовчуванням, що не дуже корисно.

Єдине інше, що я можу придумати - спробувати вибрати з таблиці та зловити виняток. Це зробило б роботу, але я не думаю, що це дуже елегантно, і я читав, що це дорого використовувати (хоча, можливо, це було б нормально в цьому сценарії, оскільки я виконую його лише один раз?).

Відповіді:


18

Швидкий і брудний

У Postgres використовують 9.4+

SELECT to_regclass('foo');

Повертає NULL, якщо ідентифікатор не знайдений у шляху пошуку.
У Postgres 9.3 або новіших версіях використовуйте ролик дляregclass :

SELECT 'foo'::regclass;

Це створює виняток , якщо об’єкт не знайдено!

Якщо 'foo'його знайдено, oidповертається у своєму textподанні. Ось лише назва таблиці, кваліфікована за схемою відповідно до поточного шляху пошуку та подвійне цитування, де необхідно.

Якщо об’єкт не знайдено, ви можете бути впевнені, що він не існує ніде в шляху пошуку - або зовсім не для імені, призначеного для схеми ( schema.foo).

Якщо це знайдено, є два недоліки :

  1. Пошук включає неявні схеми search_path , а саме pg_catalogіpg_temp . Але ви можете виключити тимчасові та системні таблиці за своїм призначенням. (?)

  2. Заголовок regclassпрацює для всіх об'єктів у системному каталозі pg_class: покажчики, представлення, послідовності тощо. Не лише таблиці. Ви, здається, шукаєте виключно звичайний стіл. Однак у вас, ймовірно, будуть проблеми і з іншими однойменними об'єктами. Деталі:

Повільно і впевнено

Ми повернулися до вашого запиту, але не використовуємо current_setting('search_path'), що повертає голові налаштування. Використовуйте спеціальну функцію інформаційної системи current_schemas(). За документацію:

current_schemas(boolean) name[]
назви схем у шляху пошуку, необов'язково включаючи неявні схеми

"$user"на шляху пошуку вирішується розумно. Якщо схема з іменем не SESSION_USERіснує, схема не повертається для початку. Крім того, залежно від того, що саме ви хочете, ви можете додатково виводити неявні схеми ( pg_catalogі, можливо, pg_temp) - але я припускаю, що ви не хочете тих, що є для цього випадку, тому використовуйте:

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 , демонструючи всі, крім останньогоDOтвердження.
SQL Fiddle (JDBC) має проблеми з DOоператорами, що містять символи завершення.


1

Ви можете конвертувати значення конфігурації в масив і замінити $userпоточне ім'я користувача. Потім масив може використовуватися в умовах, де:

where n.nspname = any(string_to_array(replace(current_setting('search_path'), '$user', current_user), ','))

0
./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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.