postgresql устанавливает часовой пояс для материализованного представления

#postgresql

#postgresql

Вопрос:

хорошо — мы обнаружили ошибку в одной из наших систем, когда материализованные представления обновляются для разных данных, в зависимости от того, какая система вызвала обновление.

Это оказалось проблемой с настройками даты клиента — это зависит от часового пояса пользователя.

Это большой риск. Я знаю, что для каждого поля мы можем переопределить настройки, но это сложно, потому что представления используют другие представления, а преобразования / вычисления даты происходят в любом месте иерархии представлений, поэтому мы не можем гарантировать, что вычисления, специфичные для клиента, не пройдут.

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

Я пробовал это — но это не работает:( — но хочу что-то вроде этого:

 create materialized view blah as (
set timezone to 'Australia/Brisbane';
select now())
 

Комментарии:

1. Являются ли типы полей для временных меток в представлениях timestamp или timestamptz ?

2. вот в чем дело — мы говорим о сотнях полей в сотнях таблиц с большой иерархией представлений поверх представлений поверх представлений, включая буквально каждую комбинацию типа даты / метки времени. Также у меня нет контроля над таблицами или структурами таблиц — все они уже существуют, поэтому мне нужно решить проблему для новых представлений. На данный момент я подключаю вышеупомянутый установленный часовой пояс везде, где представления вызываются в коде … и это работает… но кто-то забудет.

3. Ну, вы не можете делать то, что вы показываете выше. Разве невозможно установить часовой пояс сервера на ‘Австралия / Брисбен’ глобально?

4. но в этом весь смысл — это зависит от часового пояса клиента , а не от сервера — если бы он использовал часовой пояс сервера, проблем не было бы. Проблема возникает из-за того, что когда разные люди запускают команду «обновить представление», мы получаем разные значения в таблице

5. Я не понимаю. Если все работают на одном сервере, то используемый часовой пояс будет любым show timezone , что возвращает. Оговорка в том, что люди / клиенты могут выдавать SET time zone ... или эквивалент, чтобы изменить его для сеанса. Это то, что происходит?

Ответ №1:

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

В текущем случае избегайте всего, что приводит date или timestamp without timezone к timestamp with time zone или наоборот, потому timezone что будет тайно входить в любые такие преобразования.

Всегда указывайте часовой пояс явно:

  • чтобы преобразовать из date или timestamp в timestamp with time zone , используйте
     current_date AT TIME ZONE 'whatever'
     
  • чтобы преобразовать из timestamp with time zone в date или timestamp , используйте
     current_timestamp AT TIME ZONE 'whatever'
     

Вызываются оба оператора AT TIME ZONE , но они разные.

Я вижу, что ваша проблема заключается в том, что существует большое количество ранее существовавших определений представлений, которые не соответствуют этому принципу. Возможно, вам сойдет с рук что-то вроде:

 WITH setzone AS (
   SELECT set_config('timezone', 'UTC', TRUE)
)
SELECT /* your query */;
 

Но вам нужно изменить запрос так, чтобы он ссылался setzone на что-то в запросе (вы могли CROSS JOIN бы это сделать), чтобы он был выполнен.

Комментарии:

1. это с блоком кажется именно тем, что я искал, если это сработает — огромное спасибо!

2. боже — это сработало — спасибо!!! с помощью setzone как (выберите set_config(‘часовой пояс’, ‘Австралия / Брисбен’, TRUE), now() как refreshed_at ) выберите refreshed_at, …