powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Баг или так задумано, where cast ( field as numeric ) > value. postgree 9.3 last stable
4 сообщений из 4, страница 1 из 1
Баг или так задумано, where cast ( field as numeric ) > value. postgree 9.3 last stable
    #38605921
NikolayV81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Решил на днях поставить wordpress + pgsql, как известно расширение PG4WP с текущей версией WP ( 3.8.1 ) не работает, решил его доработать, расширение само по себе представляет парсер запросов mysql в pgsql, первый же запрос выглядит как
Код: sql
1.
2.
3.
4.
5.
DELETE a, b FROM pgwp_options a, pgwp_options b 
  WHERE a.option_name LIKE '\_transient\_%' 
    AND a.option_name NOT LIKE '\_transient\_timeout\_%' 
    AND b.option_name = CONCAT( '_transient_timeout_', SUBSTRING( a.option_name, 12 ) ) 
    AND b.option_value <= 1396370722


при этом поле option_value типа varchar.
написал парсер такого запроса в вид, который вроде как должен работать в postgree:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
delete 
  from pgwp_options 
    where option_id in ( 
	  select option_id 
	    from ( select a.option_id
		            , b.option_value 
				 from pgwp_options a, pgwp_options b 
		         WHERE a.option_name LIKE '\_transient\_%' 
				   AND a.option_name NOT LIKE '\_transient\_timeout\_%' 
				   AND b.option_name = CONCAT( '_transient_timeout_', SUBSTRING( a.option_name, 12 ) )  
			   union 
			   select b.option_id
			        , b.option_value 
				 from pgwp_options a
				    , pgwp_options b 
				 WHERE a.option_name LIKE '\_transient\_%' 
				   AND a.option_name NOT LIKE '\_transient\_timeout\_%' 
				   AND b.option_name = CONCAT( '_transient_timeout_', SUBSTRING( a.option_name, 12 ) )  
				 ) t1 where cast ( t1.option_value as numeric ) <= 1396370722 )


но он не работает, ругается на то что t1.option_value не является числовым, хотя внутренний обзединённый запрос по отдельности выводит только те строки в которых option_value состоит только из цифр.
Вероятно где то в процессе подготовки запроса, оптимизатор решает, что быстрее сначала проверить условие cast ( t1.option_value as numeric ) <= 1396370722 )
при этом если изменить запрос до вида:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
select option_id 
	    from ( select a.option_id
		            , cast ( b.option_value  as numeric ) as option_value
				 from pgwp_options a, pgwp_options b 
		         WHERE a.option_name LIKE '\_transient\_%' 
				   AND a.option_name NOT LIKE '\_transient\_timeout\_%' 
				   AND b.option_name = CONCAT( '_transient_timeout_', SUBSTRING( a.option_name, 12 ) )  
			   union 
			   select b.option_id
			        , cast ( b.option_value  as numeric ) as option_value
				 from pgwp_options a
				    , pgwp_options b 
				 WHERE a.option_name LIKE '\_transient\_%' 
				   AND a.option_name NOT LIKE '\_transient\_timeout\_%' 
				   AND b.option_name = CONCAT( '_transient_timeout_', SUBSTRING( a.option_name, 12 ) )  
				 ) t1 where t1.option_value as numeric <= 1396370722


ситуация не меняется, т.е. запрос
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
elect a.option_id
		            , cast ( b.option_value  as numeric ) as option_value
				 from pgwp_options a, pgwp_options b 
		         WHERE a.option_name LIKE '\_transient\_%' 
				   AND a.option_name NOT LIKE '\_transient\_timeout\_%' 
				   AND b.option_name = CONCAT( '_transient_timeout_', SUBSTRING( a.option_name, 12 ) )  
			   union 
			   select b.option_id
			        , cast ( b.option_value  as numeric ) as option_value
				 from pgwp_options a
				    , pgwp_options b 
				 WHERE a.option_name LIKE '\_transient\_%' 
				   AND a.option_name NOT LIKE '\_transient\_timeout\_%' 
				   AND b.option_name = CONCAT( '_transient_timeout_', SUBSTRING( a.option_name, 12 ) )  


отрабатывает без проблем возвращая только числовые значения, а в сумме не работает.

проблему причём можно решить ( правда при таком поведении неизвестно насколько верно ) изменив условие внешнего запроса на
Код: sql
1.
where t1.option_value similar to '[[:digit:]]' and  cast ( t1.option_value as numeric ) <= 1396370722 )


в первом запросе.

к сожалению создать простой скрипт для сравнения не удалось, т.к. на простых таблицах оптимизатор преобразование сдвигает на последнюю стадию, и ошибка не вылетает ( сама ошибка - неверный синтаксис для типа numeric "строка с буквами которой в рез подзапроса быть не должно" )

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

p.s. как решить задачу с запросом в принципе я нашёл ( 2 способа, собств. функция или pgsql блок ) интересует именно правильно ли с точки зрения теории и документации работает postgree.
...
Рейтинг: 0 / 0
Баг или так задумано, where cast ( field as numeric ) > value. postgree 9.3 last stable
    #38606029
1335
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
NikolayV81,

мальчик, ты дурак ?
-- хотел было написать я, прочитав первые строки до места
авторпри этом поле option_value типа varchar.

но потом почитал дальше, и решал таки, что безусловно
мальчик, ты дурак .

оптимизатор тебе ничего не должен решать насчёт не описанных дефолтных кастов (впрочем и те ему до...)
,которые оно, (неонка, по глупости отождествляемая с оптимайзером) таки умеет делать.

напиши ф-ю, на крайняк - устойчивое выражение, делающее чеккинг и только потом каст.
и ставь везде его вместо поля


в самом ленивом случае это устойчивое выражение будет выглядеть так (собираем из твоих наработок)

Код: sql
1.
2.
3.
4.
5.
6.
CASE WHEN
             t1.option_value similar to '[[:digit:]]'
THEN
             cast ( t1.option_value as numeric )
-- ELSE NULL --by default
END
...
Рейтинг: 0 / 0
Баг или так задумано, where cast ( field as numeric ) > value. postgree 9.3 last stable
    #38606085
NikolayV81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1335напиши ф-ю, на крайняк - устойчивое выражение, делающее чеккинг и только потом каст.
и ставь везде его вместо поля


в самом ленивом случае это устойчивое выражение будет выглядеть так (собираем из твоих наработок)

Код: sql
1.
2.
3.
4.
5.
6.
CASE WHEN
             t1.option_value similar to '[[:digit:]]'
THEN
             cast ( t1.option_value as numeric )
-- ELSE NULL --by default
END


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

к примеру мы можем написать в запросе :
Код: sql
1.
select cast (field as numeric )*10 as new_field where field similar to '[[:digit:]]+'


который будет работать в 100% случаев, но при этом запрос
Код: sql
1.
select n.new_field from (select cast (field as numeric )*10 as new_field where field similar to '[[:digit:]]+' ) n where n.new_field > 10


работать не будет
Тут вопрос в том правильно ли отрабатывает оптимизатор, а не в том кто кому чего обязан, вот о том какое решение было принято я документов не нашёл. Вопрос именно в этом а не в поиске наиболее простого решения.
...
Рейтинг: 0 / 0
Баг или так задумано, where cast ( field as numeric ) > value. postgree 9.3 last stable
    #38606227
в сад
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
NikolayV811335напиши ф-ю, на крайняк - устойчивое выражение, делающее чеккинг и только потом каст.
и ставь везде его вместо поля


в самом ленивом случае это устойчивое выражение будет выглядеть так (собираем из твоих наработок)

Код: sql
1.
2.
3.
4.
5.
6.
CASE WHEN
             t1.option_value similar to '[[:digit:]]'
THEN
             cast ( t1.option_value as numeric )
-- ELSE NULL --by default
END


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

к примеру мы можем написать в запросе :
Код: sql
1.
select cast (field as numeric )*10 as new_field where field similar to '[[:digit:]]+'


который будет работать в 100% случаев, но при этом запрос
Код: sql
1.
select n.new_field from (select cast (field as numeric )*10 as new_field where field similar to '[[:digit:]]+' ) n where n.new_field > 10


работать не будет
Тут вопрос в том правильно ли отрабатывает оптимизатор, а не в том кто кому чего обязан, вот о том какое решение было принято я документов не нашёл. Вопрос именно в этом а не в поиске наиболее простого решения.
мальчик, ты не дурак, я ошибся.
ты, ять, дебил
никаких вопросов про оптимизатор нет
есть вопрос, нужно тебя насильно в дурку закатывать
или ты и так безвреден
короче в сад
...
Рейтинг: 0 / 0
4 сообщений из 4, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Баг или так задумано, where cast ( field as numeric ) > value. postgree 9.3 last stable
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]