Клиент mysql выполняет, EMS выполняет, php не хочет

sokol

Zavolga.Net
Клиент mysql выполняет, EMS выполняет, php не хочет

Вобщем запрос вида:
PHP:
SELECT
@access := (
        CASE
        WHEN '31' = '2' OR '0' THEN tbl.access
        WHEN tbl.owner = '31' THEN tbl.access
        WHEN BIT_OR(acl.access) THEN BIT_OR(acl.access)
        WHEN COUNT(utog.user_id) > 0 THEN IF (tbl.access & 1, (tbl.access >> 4) | 1, tbl.access >> 4)
        ELSE IF (tbl.access & 1, (tbl.access >> 8) | 1, tbl.access >> 8)
        END
) AS record_access, tbl.id
FROM company AS tbl
LEFT JOIN access_list AS acl ON (tbl.id = acl.record_id AND (acl.group_id IN (1) OR acl.user_id = '31') AND acl.tbl = 'company')
LEFT JOIN usrtogroup AS utog ON (tbl.owner = utog.user_id AND utog.group_id IN (1)) WHERE 1
GROUP BY tbl.id
HAVING (@access & 2) > 0
Прекрасно выолняется везде, а PHP ошибок не выдает, но возвращает empty set!
Кто нибудь сталкивался с этим?

PHP 4.3.6/MySQL 4.0.17-nt/Apache 1.3.27/WinXP

-~{}~ 21.05.04 20:48:

Если кому интересно, вышлю дамп таблиц
 

ForJest

- свежая кровь
Ну так отладь, однако. Убери HAVING, погляди что выдаётся, какие значения имеет @acess.
К тому же непонятно, зачем ты используешь @access в HAVING если у тебя уже есть record_access - стоит использовать его.

А вообще запрос жутковатый, да :)
 

sokol

Zavolga.Net
ForJest
Конечно же я пробовал убирать having...
Не это главное, главное то, что консольный клиент его прекрасно выполняет и выдает ожидаемый результат, EMS тоже... текст запроса копирую после вывода echo из браузера.
Кстати выполняется довольно быстро на 100 000 записей в company, 0.15 - 0.2 сек

жутковатый, но по другому никак...
можешь предложить варианты?

Грубо говоря он выбирает все записи к которым есть доступ на указанную операцию в данном случае это проверяется в условии having т.е. @access & 2 это как раз проверка на установленный бит.
 

si

Administrator
какй тайный смыл в этом
WHEN '31' = '2' OR '0' THEN tbl.access ?
 

sokol

Zavolga.Net
Берется переменная из сессии и сравнивается не принадлежит ли юзер к группе "Администраторы"... Ну да можно было бы где-нибудь заранее сравнить, это так рабочая версия.

Кстати заработало как только убрал @access из SELECT и HAVING! Ставлю обратно, получаю empty set. Странно, очень странно. Кто объяснит такое поведение?
 

ForJest

- свежая кровь
6.1.4 User Variables
Note: in a SELECT statement, each expression is evaluated only when it's sent to the client. This means that in the HAVING, GROUP BY, or ORDER BY clause, you can't refer to an expression that involves variables that are set in the SELECT part. For example, the following statement will NOT work as expected:

mysql> SELECT (@aa:=id) AS a, (@aa+3) AS b FROM table_name HAVING b=5;

The reason is that @aa will not contain the value of the current row, but the value of id for the previous accepted row.
короче
HAVING (record_access & 2) > 0
Общий смысл в том, что GROUP BY работает над результирующей выборкой. А User Variables работает для каждой строки этой выборки, хотя тебе это может быть и не видно. Т.е. если у тебя до GROUP BY 100 строк, а после всего две, то в переменной ты получишь случайный результат одной из этих 100 строк, т.к. порядок уже зависит от оптимизатора.
 

sokol

Zavolga.Net
ForJest - ага, понятно... вон в чем дело. Ну в общем логично. Саоме прикольное, что консольный клиент и EMS Manager выдавал ожидаемый результат и с @access
 

ForJest

- свежая кровь
а в четверг, когда пятнистные кони идут на запад при попутном свете начетвертьполной луны, в час, когда прокричат двенадцать самых старых лесных птиц и вскинется синяя щука выдадутся ещё и не такие результаты :)
 
Сверху