|
|
|
Баг при работе с временными таблицами
|
|||
|---|---|---|---|
|
#18+
Столкнулся с интересной проблемой когда создание временной таблицы влияет на результаты возвращаемые функцией из другой таблицы. Проблему выявил на 9.5.1 х64 под Windows. Ниже код который демонстрирует наличие данной ошибки: Открываем новую сессию и выполняем в ней следующий код: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. Собственно при выполнении получался следующий результат: Должно быть 0, результат 0 Должно быть 1, результат 0 Если убрать строку create temporary table tmp222 (id numeric) on commit delete rows; то результат будет Должно быть 0, результат 0 Должно быть 1, результат 1 Т.е. создание временной таблицы влияет на результат функции которая к созданной таблицы никакого отношения не имеет. Насколько я понимаю при первом выполнении функции сервер запоминает в каком нэймспейсе находилась таблица и дальше ее уже за временную не считает. Мне кажется что данное поведение сервера это явный баг. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.04.2016, 09:30 |
|
||
|
Баг при работе с временными таблицами
|
|||
|---|---|---|---|
|
#18+
ln123, а тут точно баг постгреса? может проблема в том, что у вас по две таблицы существуют с одинаковыми именами? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.04.2016, 09:56 |
|
||
|
Баг при работе с временными таблицами
|
|||
|---|---|---|---|
|
#18+
ln123, А почему вы думаете что должно быть 1? Командой insert into tmp123 (id) values(1); вы вставили в ВРЕМЕННУЮ таблицу (она имеет приоритет в search_path) А хранимка работает с постоянной таблицей. Так что все работает как ожидается. В общем не делайте временные таблицы с именами постоянных и не будет проблем. -- Maxim Boguk www.postgresql-consulting.ru ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.04.2016, 10:10 |
|
||
|
Баг при работе с временными таблицами
|
|||
|---|---|---|---|
|
#18+
ln123, чтобы такого не происходило нужно явно указывать схему (public) таблиц в хранимке. из документации : Likewise, the current session's temporary-table schema, pg_temp_nnn, is always searched if it exists. It can be explicitly listed in the path by using the alias pg_temp. If it is not listed in the path then it is searched first (even before pg_catalog). However, the temporary schema is only searched for relation (table, view, sequence, etc) and data type names. It is never searched for function or operator names. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.04.2016, 10:36 |
|
||
|
Баг при работе с временными таблицами
|
|||
|---|---|---|---|
|
#18+
Maxim Boguk, В том то и дело что предполагается что хранимка будет работать со временной таблицей если такая будет создана т.к. из документации: "Existing permanent tables with the same name are not visible to the current session while the temporary table exists, unless they are referenced with schema-qualified names." А две таблицы с одинаковыми именами существует для того что бы избежать ошибки при вызове функций обращающихся к временным таблицам до их создания/инициализации (мы создаем временные таблицы в функциях записи в них, а в постоянные таблицы запись запрещена). Собственно баг, в том что результат обращения к tmp123 зависит от того была ли ранее в сессии создана какая либо временная таблица в данном случае tmp222, а должен зависеть только от создания tmp123. Кстати Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. вернет Результат прямого запроса 1, результат функции 0 То что запрос и функция выполняющая такой же запрос возвращают разные результаты это то же корректное поведение для СУБД? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.04.2016, 12:34 |
|
||
|
Баг при работе с временными таблицами
|
|||
|---|---|---|---|
|
#18+
Alexius, В том то и дело что в моем примере база работает совсем не так как написано в той цитате что вы привели. 1. Временной таблицы нет функция возвращает 0 т.е. обращается к постоянной таблице 2. Временная таблица появилась и мы в нее вставили запись, а функция все равно возвращает 0 хотя должна обратится к вновь созданной временной таблице и вернуть 1 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.04.2016, 12:38 |
|
||
|
Баг при работе с временными таблицами
|
|||
|---|---|---|---|
|
#18+
ln123Alexius, В том то и дело что в моем примере база работает совсем не так как написано в той цитате что вы привели. 1. Временной таблицы нет функция возвращает 0 т.е. обращается к постоянной таблице 2. Временная таблица появилась и мы в нее вставили запись, а функция все равно возвращает 0 хотя должна обратится к вновь созданной временной таблице и вернуть 1 Функция парсится при первом вызове и далее как оно таблицы разрезолвила так они и останутся. Если вам надо другое поведение - используйте EXECUTE вместо просто SELECT в хранимке. Но тогда это будет медленнее так как теряется главный смысл хранимок - запросы не парсятся и не планируются на каждый вызов а только 1 раз. -- Maxim Boguk www.postgresql-consulting.ru ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.04.2016, 12:47 |
|
||
|
Баг при работе с временными таблицами
|
|||
|---|---|---|---|
|
#18+
Maxim Bogukln123Alexius, В том то и дело что в моем примере база работает совсем не так как написано в той цитате что вы привели. 1. Временной таблицы нет функция возвращает 0 т.е. обращается к постоянной таблице 2. Временная таблица появилась и мы в нее вставили запись, а функция все равно возвращает 0 хотя должна обратится к вновь созданной временной таблице и вернуть 1 Функция парсится при первом вызове и далее как оно таблицы разрезолвила так они и останутся. Если вам надо другое поведение - используйте EXECUTE вместо просто SELECT в хранимке. Но тогда это будет медленнее так как теряется главный смысл хранимок - запросы не парсятся и не планируются на каждый вызов а только 1 раз. -- Maxim Boguk www.postgresql-consulting.ru если бы это было так, то при первом вызове, если закомментировать только создание -- был бы 0 всегда. но "разборы" видимо инвалидизируются, при изменении серч--паса сеанса. и производятся снова. Поэтому, если в момент разбора при первом появлении темповой директории (любого темпового объекта), -- там уже есть табличка tmp123-- то "в плане" будет именно она (хотя и не совсем). Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. т.е. все эти трюки с неявными серч пасами в ф--ях я уже лет 10 как обхожу стороной. хотя ТС формально прав -- пж тут лажает по--полной. а вообще тема своевременной инвалидизации в пж вечна. ещё недавно [~~7.2--7.3] "дроп индекс" требовал переоткрытия сеансов. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.04.2016, 13:02 |
|
||
|
Баг при работе с временными таблицами
|
|||
|---|---|---|---|
|
#18+
qwwq, Да согласен поведение хреновое. Надо придумать как из этого при наличии TEMP привелегий на базе security hole сообразить для частичного обхода/обмана security definer функций. Например в варианте использования базы через pgbouncer в transaction pooling без server reset query (а это рекомендуемый режим) подсунуть чужим сессиям временную таблицу users совпадающую по имени и структуре с той где пароли хранятся (можно сделать эту временную таблицу несколько раз так чтобы наверняка в большей части активных Backend процессов эта временная таблица жила). А дальше уже открываются интересные возможности (от просмотра случайно записанных в нее md5 которые не видны через security definer access функцию) до подсовывания левых реквизитов в эти временные таблицы чтобы залогинится где то с чужими полномочиями. Главное чтобы эта хранимка вызывалась не очень часто и тогда есть шансы что она подцепит временную таблицу с левыми данными при первой компиляции (ну или она почему то execute использует и тогда оно просто гарантированно выстрелит). -- Maxim Boguk www.postgresql-consulting.ru ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.04.2016, 13:28 |
|
||
|
Баг при работе с временными таблицами
|
|||
|---|---|---|---|
|
#18+
ln123Alexius, В том то и дело что в моем примере база работает совсем не так как написано в той цитате что вы привели. Невнимательно прочитал. Действительно неочевидное поведение получается. Сделал для наглядности функцию, возвращающую имя схемы таблицы tmp123: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.04.2016, 14:46 |
|
||
|
Баг при работе с временными таблицами
|
|||
|---|---|---|---|
|
#18+
ln123, проблема налицо можете пока заткнуть это таким лайф--хаком: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. --для волатильных должно быть безпроблемным. -- я пользуюсь для перегрузки иммутабных, при инициации и прописывании констант -- вот там проблема -- инвалидизация рушит кеш [значений ф-ии] ранее стартовавшему конкурентному сеансу. и выносит его на ексепшен. т.е. необходимо быть уверенным, что никто, кроме вас, не может в этот момент работать с ф--ей. но это проблема только иммутабных ф--ий [по чесноку вызов имутабной либо должен лочить определение ф--ии до конца сеанса, либо реализация кеша должна включать в ключи версию xmin из pg_proc. второе было бы удобнее] ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.04.2016, 20:39 |
|
||
|
Баг при работе с временными таблицами
|
|||
|---|---|---|---|
|
#18+
qwwq, По моему куда проще как я предложил вместо: select coalesce(max(id),0) into idv from tmp123; написать EXECUTE 'select coalesce(max(id),0) into idv from tmp123' INTO idv; тогда будет требуемое автору поведение. -- Maxim Boguk www.postgresql-consulting.ru ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.04.2016, 05:40 |
|
||
|
Баг при работе с временными таблицами
|
|||
|---|---|---|---|
|
#18+
Maxim Boguk, согласен, с одним но -- люди б.м. бьются за скорость по крайней мере всякую маргинальщину заюзали а для скорости лучше снизить число синтаксических разборов=> сделать одну точечную инвалидизацию там, где пж лажает унутре ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.04.2016, 14:22 |
|
||
|
Баг при работе с временными таблицами
|
|||
|---|---|---|---|
|
#18+
На самом деле обходной путь довольно простой в начале сессии (до вызова любой функции получающей данные) создать все временные таблицы, правда отсутствие логон триггеров осложняет эту задачу, но все равно задача решаема. Я честно говоря писал на форум в надежде что кто-нибудь из российских разработчиков признает наличие данной проблемы и возьмется за ее решение, т.к. на самом деле бага очень неприятная когда такая ошибка случается в недрах более менее сложной системы найти причину очень сложно. У меня кстати та проблема из-за которой я начал копать, на 9.4 не проявляется, хотя мой тестовый код одинаково лажает и на 9.5 и на 9.4 Хотя судя по наличию в TODO пункта "Allow temporary tables to exist as empty by default in all sessions " да же если я напишу bug-report то на него забьют :( ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.04.2016, 17:07 |
|
||
|
Баг при работе с временными таблицами
|
|||
|---|---|---|---|
|
#18+
ln123, вы так говорите, как будто это что-то плохое, как будто вы не делаете маргинальнейших ужимок, сам смысл которых сомнителен хотите странного -- имеете право. но странным оно от этого быть не перестаёт как макс выше писал -- сама возможность перекрыть таблицу одноимённой времянкой -- более чем сомнительна с т.з. дырок в безопасности. надо много думать -- то ли отказаться от странного в пользу защиты, то ли там дырка кажущаяся -- а фичи -- явные [странные]. и тогда надо чинить (не только при смене сеч-паса или дропе таблички инвалидизировать "планы", но и при появлении одноимённых объектов (какую--то структуру, завязанную на имена, и указывающую на разобранные тела ф-й придётся держать в памяти)). т.ч. вы напишите репорт, не ленитесь. кому то на глаза да попадётся ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.04.2016, 20:41 |
|
||
|
|

start [/forum/topic.php?fid=53&msg=39205941&tid=1997318]: |
0ms |
get settings: |
7ms |
get forum list: |
14ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
203ms |
get topic data: |
11ms |
get forum data: |
3ms |
get page messages: |
57ms |
get tp. blocked users: |
2ms |
| others: | 227ms |
| total: | 532ms |

| 0 / 0 |
