Волатильные выражения и подзапросы PostgreSQL

В сообщении блога Брюса Момджяна Генерация случайных данных с помощью SQL он использовал следующий код для генерации 5 случайных строк:

SELECT
(
        SELECT string_agg(x, '')
        FROM (
                SELECT chr(ascii('a') + floor(random() * 26)::integer)
                FROM generate_series(1, 40 + b * 0) as f(g)
        ) AS y(x)
) AS result
FROM generate_series(1,5) as a(b);

              result                  
------------------------------------------
 plwfwcgajxdygfissmxqsywcwiqptytjjppgrvgb
 sjaypirhuoynnvqjdgywfsfphuvzqbbilbhakyhf
 ngtabkjfqibwahlicgisijatliuwgbcuiwujgeox
 mqtnyewalettounachwjjzdrvxbbbpzogscexyfi
 dzcstpsvwpefohwkfxmhnlwteyybxejbdltwamsx
(5 rows)

Я задавался вопросом, почему требуется «b *0» в строке 6. Когда я удалил его, результат изменился на 5 точно похожих строк, что означает, что Postgres кэшировал выражение внешнего выбора (result )!

Я не смог найти, как кэширование выражений работает в Postgres. В соответствии с документация random ()функция помечена как VOLATILE, поэтому я ожидаю, что любое выражение зависит от нее, также будет изменчивым.

Как работает кэширование выражений в Postgres? Это где-нибудь задокументировано? Почему «b *0» отключил кеш, а random ()нет?

Обновление:

Чтобы изучить проблему, я переместил «b *0» внутрь вызова пола (), чтобы он находился на той же позиции / уровне, что и случайный ():

...
                SELECT chr(ascii('a') + floor(random() * 26 + b * 0)::integer)
                FROM generate_series(1, 40) as s(f)
...

. Результат все еще не кэшируется; разные струны.

Обновление :Еще один пример, показывающий проблему

create sequence seq_test;

SELECT (SELECT nextval('seq_test')) FROM generate_series(1,5);

 ?column? 
----------
        1
        1
        1
        1
        1
(5 rows)

5
задан Erwin Brandstetter 21 September 2012 в 16:11
поделиться