PostgreSQL: Можно ли определить переменную сеанса с языком и использовать ее в представлениях? - PullRequest
2 голосов
/ 20 августа 2009

Вот упрощенный пример схемы:

Table l10n ( l10n_id SMALLINT, code VARCHAR(5) )  
Table product ( product_id INT, ..language-neutral columns.. )  
Table product_l10n ( product_id INT, l10n_id SMALLINT, ..language-specific columns.. )

Запрос для продуктов с локализованными данными выполняется следующим образом:

    SELECT *
    FROM product a
        LEFT JOIN product_l10n b ON b.id = a.id
        LEFT JOIN l10n c ON c.id = b.id
    WHERE c.code = 'en-US';

Чтобы избежать этого большого жирного запроса, я хотел бы использовать представления.
Основная идея заключается в создании представления на основе указанного выше запроса без предложения where.
Запросы для продуктов тогда станут:

    SELECT * FROM product_view WHERE c.code = 'en-US';

Другая идея заключается в том, чтобы иметь переменную, содержащую языковой тег, определенный для каждого соединения / сеанса БД.
Представление будет основано на первом запросе с использованием переменной в предложении where.
Переменная, устанавливаемая в текущем сеансе работы с БД, в таком случае будет запрашивать товары:

    SELECT * FROM product_view;

Итак, мой вопрос: можно ли это сделать? Как?

Это возможно при использовании пользовательских переменных в postgresql.conf. См. Документ Индивидуальные параметры .

В postgresql.conf:

    custom_variable_classes = 'myproject'
    myproject.l10n_id = 'en-US'

В начале сеанса БД (параметр устанавливается на уровне сеанса по умолчанию):

    SET myproject.l10n_id = 'en-US';

В просмотрах:

    WHERE c.code = current_setting('myproject.l10n_id')

Но ... Мне не нравится определять переменную для всего сервера. Есть ли способ добиться того же, но для каждой базы данных?

Заранее спасибо,
Pascal

PS: У меня есть еще один вопрос, касающийся использования l10n_id в качестве SMALLINT или непосредственно в качестве кода ISO в VARCHAR (5). См. Http: // stackoverflow.com / questions / 1307087 / как хранить языковые теги-идентификаторы-в-базах данных-как-smallint-или-varchar (извините, только 1 URL для новых пользователей: - )

1 Ответ

2 голосов
/ 20 августа 2009

Ну, в чём именно проблема создания переменной для всего сервера? Это не влияет на другие соединения / запросы, поэтому должно быть в порядке.

Другой подход может быть использован тем фактом, что каждое соединение может быть найдено с помощью внутреннего идентификатора, который можно получить с помощью

select pg_backend_pid();

Таким образом, вы можете создать таблицу с такими столбцами, как:

  • backend_pid int4
  • переменная_имя текста
  • переменная_значение текста

с включенным первичным ключом (backend_pid, variable_name) и предоставлением набора функций, которые получают значение и устанавливают значение, внутренне проверяя pg_backend_pid.

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

Я немного подумал об этом и написал сообщение в блоге с точным sql, который создаст таблицу и функции, необходимые для его работы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...