Как search_path влияет на разрешение идентификатора и "текущую схему"

Можно ли определить, в какой схеме создаются новые таблицы по умолчанию? (Называется "неквалифицированными именами таблиц".)

Я видел некоторые подробности об использовании "пути поиска" в Postgres, но я думаю, что он работает только при получении данных, а не при их создании.

У меня есть куча сценариев SQL, которые создают много таблиц. Вместо того, чтобы изменять сценарии, я хочу настроить базы данных для создания таблиц в определенной схеме по умолчанию - когда они имеют неквалифицированные имена.

Это возможно?

2 ответа

Решение

Путь поиска действительно то, что вы хотите:

% create schema blarg;
% set search_path to blarg;
% create table foo (id int);
% \d
       List of relations
 Schema | Name | Type  | Owner 
--------+------+-------+-------
 blarg  | foo  | table | pgsql

Какой путь поиска?

По документации:

[...] таблицы часто называются неквалифицированными именами, которые состоят только из имени таблицы. Система определяет, какая таблица имеется в виду, следуя пути поиска, который представляет собой список схем для поиска.

Жирный акцент мой. Это объясняет разрешение идентификатора, и "текущая схема" для каждой документации:

Первая схема, названная в пути поиска, называется текущей схемой. Помимо первой поисковой схемы, это также схема, в которой будут создаваться новые таблицы, если CREATE TABLE Команда не указывает имя схемы.

Жирный акцент мой. Системные схемы pg_temp (схема для временных объектов текущего сеанса) и pg_catalog автоматически становятся частью пути поиска и ищутся первыми, в этом порядке. По документации:

pg_catalog всегда эффективно часть пути поиска. Если он не указан явно в пути, тогда он неявно ищется перед поиском схем пути. Это гарантирует, что встроенные имена всегда будут доступны для поиска. Тем не менее, вы можете явно разместить pg_catalog в конце вашего пути поиска, если вы предпочитаете, чтобы определяемые пользователем имена переопределяли встроенные имена.

Жирный акцент в соответствии с оригиналом. А также pg_temp предшествует этому, если только он не помещен в другую позицию.

Как это установить?

У вас есть различные варианты, чтобы фактически установить переменную времени выполнения search_path,

  1. Установите кластерное значение по умолчанию для всех ролей во всех базах данных в postgresql.conf (и перезагрузите). Осторожнее с этим!

    search_path = 'blarg,public'
    

    По умолчанию этот параметр поставляется в виде:

    search_path = "$user",public
    

    Первый элемент указывает, что схема с тем же именем, что и текущий пользователь, должна быть найдена. Если такой схемы не существует, запись игнорируется.

  2. Установите его по умолчанию для одной базы данных:

    ALTER DATABASE test SET search_path = blarg,public;
    
  3. Установите его по умолчанию для роли, с которой вы соединяетесь (эффективно для всего кластера):

    ALTER ROLE foo SET search_path = blarg,public;
    
  4. Или даже (часто лучше!) По умолчанию для роли только в данной базе данных:

    ALTER ROLE foo IN DATABASE test SET search_path = blarg,public;
    
  5. Напишите команду в верхней части вашего сценария (или выполните ее в любой момент сеанса:

    SET search_path = blarg,public;
    
  6. Установить конкретный search_path для объема функции (чтобы быть в безопасности от злоумышленников с достаточными привилегиями). Читать о письме SECURITY DEFINER Функции Безопасно в руководстве.

CREATE FUNCTION foo() RETURNS void AS
$func$
BEGIN
   -- do stuff
END
$func$ LANGUAGE plpgsql SECURITY DEFINER
       SET search_path=blarg,public,pg_temp;

Чем выше число в моем списке, тем выше число.
В руководстве есть еще больше способов, таких как установка переменных среды или использование параметров командной строки.

Чтобы увидеть текущие настройки:

SHOW search_path;

Чтобы сбросить его:

RESET search_path;

По документации:

Значение по умолчанию определяется как значение, которое имел бы параметр, если нет SET когда-либо был выпущен для этого на текущей сессии.

Другие вопросы по тегам