Как 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
,
Установите кластерное значение по умолчанию для всех ролей во всех базах данных в
postgresql.conf
(и перезагрузите). Осторожнее с этим!search_path = 'blarg,public'
По умолчанию этот параметр поставляется в виде:
search_path = "$user",public
Первый элемент указывает, что схема с тем же именем, что и текущий пользователь, должна быть найдена. Если такой схемы не существует, запись игнорируется.
Установите его по умолчанию для одной базы данных:
ALTER DATABASE test SET search_path = blarg,public;
Установите его по умолчанию для роли, с которой вы соединяетесь (эффективно для всего кластера):
ALTER ROLE foo SET search_path = blarg,public;
Или даже (часто лучше!) По умолчанию для роли только в данной базе данных:
ALTER ROLE foo IN DATABASE test SET search_path = blarg,public;
Напишите команду в верхней части вашего сценария (или выполните ее в любой момент сеанса:
SET search_path = blarg,public;
Установить конкретный
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
когда-либо был выпущен для этого на текущей сессии.