трах-тибидох-тах-тах!

assa
Дата: 06.11.2003 13:30:22
трах-тибидох-тах-тах!
ERROR: ExecutePlan: (junk) `ctid' is NULL!
трах-тибидох-тах-тах!

UPDATE t_values
SET value=COALESCE(Sum(value),0)
WHERE tid=-1000000000;
ERROR: ExecutePlan: (junk) `ctid' is NULL!

што ему не нравится!!!
SELECT * from t_values WHERE tid=-1000000000; (пусто)

Select COALESCE(Sum(value),0) from t_values WHERE tid=-1000000000;
! 0 (- !!! значение возвращаю не null, стал быть не это???)

UPDATE t_values
SET value=1 /* COALESCE(Sum(value),0) */
WHERE tid=-1000000000;
!!! отрабатывает (как и должен - нет записей - не его собачье дело)

- Или я же еще и обязан проверить, а не загнется ли он при запросе от своего унутреннего несовершенства? ("буквы так и лезли из него, но все непечатные")

?Что я делаю не так? Что делать? Как быть? (Кто виноват?)
__
SELECT version();
PostgreSQL 7.3.4 on i386-unknown-freebsd5.1, compiled by GCC gcc (GCC) 3.2.2 [FreeBSD] 20030205 (release)
Sad Spirit
Дата: 06.11.2003 16:30:00
Гм. у Тебя поле в таблице называется tid? Переименуй, tid --- это какое-то внутреннее название, типа oid.
assa
Дата: 06.11.2003 18:18:07
спасибо, но:

UPDATE t_values
SET value=1 /* COALESCE(Sum(value),0) */
WHERE tid=-1000000000;

- работает. т.е. причина идентифицирована - Sum(value), при отсутствии записей в наборе. COALESCE не спасает.

из системных вижу:
tableoid
cmax
xmax
cmin
xmin
ctid /* именно тут мы ругаемся?

-и все.
Sad Spirit
Дата: 07.11.2003 10:34:24
а, наконец разглядел запрос.

tid тут не при чём, скорее всего. а вот тот факт, что ты используешь агрегатную функцию sum(), но при этом не группируешь поля --- при чём. то есть Постгрес можно обвинить только в том, что сообщение об ошибке непонятное.
assa
Дата: 10.11.2003 12:32:32
если записи в наборе есть, - то ошибки нет. Но запрос не "реальный". - Так, - моделька, полученная усечением того, что нужно. (как пробило на ошибку, так и начал отбрасывать "лишнее"). GROUP BY нужна была бы, если выводить поля, по которым НЕ выводятся агрегаты - тогда именно по ним и нужен GROUP BY. А соображение, что "Постгрес можно обвинить только в том, что сообщение об ошибке непонятное" в данном случае равно не вьезжанию в природу SQL :0). Прошу простить за резкость :0). Но в данном случае не работает SUM() по пустому множеству. При не пустоте, оно срабатывает. Вот и все. Т.ч. постгресс облажался :0). Правда я "вдруг" понял, что ТАК мне, собственно, и не надо. И сделал иначе. Там ошибка не выскакивает. Но осадочек-с остается.
assa
Дата: 10.11.2003 13:23:09
НУ вот, подвигли на иллюстративный прогон:

/*
UPDATE t_values
SET value=COALESCE(Sum(value),0)
WHERE tid=-1000000000;
*/
/*
ERROR: ExecutePlan: (junk) `ctid' is NULL!
*/
/*
SELECT * from t_values WHERE tid=-1000000000;
row number -1 is out of range 0..-1
Суммарное время выполнения запроса:63 ms.
Время получения данных:31 ms.
получено строк: 0
*/
НО !
/*
SELECT COALESCE(Sum(value),0) from t_values WHERE tid=-1000000000;
Суммарное время выполнения запроса:47 ms.
Время получения данных:0 ms.
получено строк: 1
*/
/*
UPDATE t_values
SET value=(SELECT COALESCE(Sum(value),0) from t_values WHERE tid=-1000000000)
WHERE tid=-1000000000;
Запрос успешно завершён без результата возврата за 47 мс.
*/
это была просто иллюстрация к "обходу бзика"
А вот это уже интересно:
/*
UPDATE t_values
SET value=COALESCE(Sum(value),0)
WHERE tid=6;
Запрос успешно завершён без результата возврата за 78 мс.
*/
/*
SELECT COALESCE(Sum(value),0) from t_values WHERE tid=6;
Суммарное время выполнения запроса:47 ms.
Время получения данных:0 ms.
получено строк: 1
*/

PS: т.е. на лицо явный таракан в 7.3.х. А "непонятная ошибка" - это - "кишки наружу" (проявление бага во внутренней кухне постгресса).
assa
Дата: 10.11.2003 13:28:15
тьфу, зарапортавался.
- вот вместо последнего запроса в предыдущем посте:

SELECT * from t_values WHERE tid=6;
/*Суммарное время выполнения запроса:63 ms.
Время получения данных:15 ms.
получено строк: 2
*/
Shweik
Дата: 10.11.2003 21:45:58
А ты можешь рассказать что _должен_ по твоемому делать запрос
UPDATE t_values
SET value=COALESCE(Sum(value),0)
WHERE tid=-1000000000;
Запихнуть в строку с tid=-1000000000 сумму?? Дык онож при успешном
выполнении просуммирует все строки! И где тут смысл?
ИМХО подзапрос вида (select Sum(value) where tid != -1000000000)
тут напрашивается в любом случае.
assa
Дата: 11.11.2003 13:58:47
все оказалось много гаже :0))))

Проблема в ПРИНЦИПЕ. Если я имею запрос в триггере (на каждую запись). А он вдруг у меня выдает ЕРРОР при некоторых выпаданиях параметров, и именно из-за кривых кишок инструмента, то это уже ПРОБЛЕМА. Вот собсна и все. Еще раз повторю: у Вас есть триггер, который обновляет некоторые данные в другой таблице(не tid=-1000000000 , а tid={входные данные}, причем если синтаксис позволяет писать агрегаты в теле UPDATE, то агрегаты считаются по тем записям, которые входят в набор отфильтрованный предложением FROM (что проверено), например:
UPDATE t_values 

SET value=COALESCE(Count(*),0)
WHERE tid=0;
но тут начинается полная каша - обновляются НЕ ВСЕ записи с данным tid!!! (но число считается верно!!!)
UPDATE t_values 

SET value=17
WHERE tid=0;
tid value
2 0
2 0
0 17
0 17
0 17
0 17
но!!!
UPDATE t_values 

SET value=COALESCE(Count(*),0)
WHERE tid=0;
tid value
2 0
2 0
0 17
0 17
0 17
0 4
!
далее уменьшу число записей, выставлю value в 0 и запущу запрос несколько раз
--1:


tid value
2 0
0 0
0 0
0 3
--2:

tid value
2 0
0 0
0 3
0 3
--3:

tid value
2 0
0 3
0 3
0 3
!!!
что забавно - находит каждый раз для обновления новую запись (а не все из фром)!!! но считает каунт именно из того ФРОМ, которое и стоит в запросе.

Ну, и, ебстественно, агрегат Count() ничем не отличается от агрегата Sum()

UPDATE t_values
SET value=COALESCE(Count(*),0)
WHERE tid=-1;
ERROR: ExecutePlan: (junk) `ctid' is NULL!

_________________________________________________________________
>>>>> если же вопрос о том, что нужно мне, то, в данном случАе мне, как я уже говорил, потребовалось нечто иное, наподобие:

UPDATE t_values SET
value=sv
FROM
(
SELECT COALESCE(Sum(t.value),0) as sv
...
FROM t_values AS t INNER JOIN tree ON t.tid = tree.id
WHERE tree.id=cid AND t.tid=cid
GROUP BY ... ) AS q

WHERE (t_values.amonth = q.amonth) AND ...;
но это уже не имеет отношения к теме.
assa
Дата: 04.12.2003 14:52:59
Интересное поведение UPDATE даже без группировочных функций!!!
(Перетаскиваю приладу с 7.0 на 7.3.4.)

запрос вида (генерится приладой):
 UPDATE leaf_heap SET id = l.id

FROM leaf AS l, tree AS t
WHERE (leaf_heap.company=l.company) AND leaf_heap.company= 4
AND (leaf_heap.aid=l.aid)
AND (leaf_heap.status=t.status) AND (t.id=l.id)
AND NOT (leaf_heap.id=l.id);

вылетает по таймауту. При запуске из-под pgAdmina я прождал 30 сек. Отрубил сам.

Проверяю:
SELECT * FROM leaf_heap h, leaf AS l, tree AS t

WHERE (h.company=l.company) AND h.company= 4
AND (h.aid=l.aid)
AND (h.status=t.status) AND (t.id=l.id)
AND NOT (h.id=l.aid);
row number -1 is out of range 0..-1
Суммарное время выполнения запроса:828 ms.
Время получения данных:156 ms.
получено строк: 0


долговато :), но в 1 сек. укладываюсь :)
Т.е. при отсутствии подходящих предложению FROM записей мы улетели в бесконечность по временивыполнения.

Для пробы переписываю:
UPDATE leaf_heap SET id = q.id

FROM (SELECT h.company, h.aid, h.status, t.id
FROM leaf_heap h, leaf AS l, tree AS t
WHERE (h.company=l.company) AND h.company= 4
AND (h.aid=l.aid)
AND (h.status=t.status) AND (t.id=l.id)
AND (NOT (h.id=l.id)) ) as q
WHERE leaf_heap.aid=q.aid
AND leaf_heap.status=q.status;

Запрос успешно завершён без результата возврата за 93 мс.
все работает!
и даже быстрее чем простой селект:
(SELECT h.company, h.aid, h.status, t.id

FROM leaf_heap h, leaf AS l, tree AS t
WHERE (h.company=l.company) AND h.company= 4
AND (h.aid=l.aid)
AND (h.status=t.status) AND (t.id=l.id)
AND (NOT (h.id=l.id)) )
row number -1 is out of range 0..-1
Суммарное время выполнения запроса:640 ms.
Время получения данных:16 ms.
получено строк: 0



Ставлю комментарий:
UPDATE leaf_heap SET id = q.id

FROM (SELECT h.company, h.aid, h.status, t.id
FROM leaf_heap h, leaf AS l, tree AS t
WHERE (h.company=l.company) AND h.company= 4
AND (h.aid=l.aid)
AND (h.status=t.status) AND (t.id=l.id)
/*AND (NOT (h.id=l.id))*/) as q
WHERE leaf_heap.aid=q.aid
AND leaf_heap.status=q.status;

опять улетаю на бесконечность

Вспоминаю, что уже переписывал синтаксис, и все работало, только на базе с созданными по умолчанию oid-ами. Запускаю первый запрос там - "опять все работает": Запрос успешно завершён без результата возврата за 219 мс.

"Будь проклят тот день, когда я сел за баранку...." :(

Резюме:
1. oid в явном виде используются во внутренней реализации процедур выполнения запросов. Надеятся на собственные уникальные ключи (особенно из нескольких полей) вряд ли стоит. (вероятно - ошибка в реализации логики). Выбрасывать oid при конструировании крайне рискованно.
2. никто не гарантирует, что работавший на некотором наборе данных запрос не загнется при неопределенных обстоятельствах.

Вопрос: Есть ли еще какие "эмпирические правила", придерживаясь которых можно не натыкаться на дыры в реализации?