Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Rules for View / 15 сообщений из 15, страница 1 из 1
24.03.2008, 09:12
    #35208781
SeniorAndre
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Rules for View
Есть две талицы Doc и child OrgDoc, для них сделан обновляемый VIEW через Rules. Проблема в том, что rules для update and insert отрабатывают правильно, а Rule для удаления только на половину...
Т.к. надо удалить из двух таблиц, то там стоит два оператора DELETE и отрабатывает только один из них и запись из подчинённой таблицы удаляется, а из парента не удаляется, не пойму почему...
Еще пришлось вставить лишний селект, чтобы наружу вернуть правильный статус для ADO, т.к. иначе ADO кричит что запись не найдена...
Код: plaintext
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.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
CREATE OR REPLACE VIEW v_doc_orgdoc AS 
 SELECT d.docid, d.ourfirmid, d.doctypeid, d.docregnumber, d.docregdate,
        d.docname,  d.docdescription, d.docformid,
        od.orgdocid,
        od.docstartdate, od.docclosedate, od.isdocfileoutsave,
        od.docfilename, od.docfile, od.docversion,
        d.isactive,
        d.modifyuser, d.modifyplace, d.modifydate,
        d.createuser, d.createplace, d.createdate
   FROM doc d, orgdoc od
   WHERE
        d.docid=od.orgdocid;

ALTER TABLE v_doc_orgdoc OWNER TO postgres;
GRANT SELECT, UPDATE, INSERT, DELETE, REFERENCES, TRIGGER ON TABLE v_doc_orgdoc TO postgres;
GRANT SELECT, UPDATE, INSERT, DELETE, REFERENCES ON TABLE v_doc_orgdoc TO "ctuUserRole";


CREATE OR REPLACE RULE v_doc_orgdoc_ins AS ON INSERT TO v_doc_orgdoc
        DO INSTEAD (
        INSERT INTO doc 
                (
                docid, ourfirmid, doctypeid, docregnumber, docregdate,
                docname,  docdescription, docformid,
                isactive
                )
        VALUES (
                NEW.docid, NEW.ourfirmid, NEW.doctypeid, NEW.docregnumber, 
                NEW.docregdate,
                NEW.docname,  NEW.docdescription, NEW.docformid,
                NEW.isactive
                );                    

        INSERT INTO orgdoc(
                orgdocid, 
                docstartdate, docclosedate, isdocfileoutsave,
                docfilename, docfile, docversion
                )
        VALUES (
                NEW.orgdocid, 
                NEW.docstartdate, NEW.docclosedate, NEW.isdocfileoutsave,
                NEW.docfilename, NEW.docfile, NEW.docversion
                )
        );
CREATE OR REPLACE RULE v_doc_orgdoc_upd AS ON UPDATE TO v_doc_orgdoc
        DO INSTEAD (
        UPDATE orgdoc SET
                docstartdate=NEW.docstartdate, docclosedate=NEW.docclosedate, isdocfileoutsave=NEW.isdocfileoutsave,
                docfilename=NEW.docfilename, docfile=NEW.docfile, docversion=NEW.docversion
        WHERE
                orgdocid=NEW.orgdocid;
        UPDATE doc SET 
                ourfirmid=NEW.ourfirmid, doctypeid=NEW.doctypeid,
                docregnumber=NEW.docregnumber, docregdate=NEW.docregdate,
                docname=NEW.docname,  docdescription=NEW.docdescription, docformid=NEW.docformid,
                isactive=NEW.isactive
        WHERE
                docid=NEW.docid;
        );        
CREATE OR REPLACE RULE v_doc_orgdoc_del AS ON DELETE TO v_doc_orgdoc
        DO INSTEAD (
        --cтрока с селектом нужна что бы вернуть наружу правильный статус результата команды для ADO
        SELECT orgdoc.orgdocid  FROM orgdoc WHERE orgdoc.orgdocid = old.orgdocid; 
        DELETE FROM orgdoc WHERE orgdoc.orgdocid=OLD.orgdocid;
        DELETE FROM doc WHERE doc.docid=OLD.docid;    
        );
В общем удаление проходит только в таблице orgdoc, а в таблице doc записи не удаляются....
...
Рейтинг: 0 / 0
25.03.2008, 00:06
    #35210874
SeniorAndre
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Rules for View
В общем сделал через вызов функции, криво конечно но работает... А в первом варианте видимо после первого DELETE теряется значение OLD.DOCID, но это наверное баг... и вопрос к разработчикам.... BAG
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
CREATE OR REPLACE FUNCTION do_del_orgdoc(pc_orgdocid character varying)
  RETURNS void AS
$BODY$
BEGIN
        DELETE FROM orgdoc WHERE orgdoc.orgdocid=pc_orgdocid;
        DELETE FROM doc WHERE doc.docid= pc_orgdocid;
END
$BODY$
  LANGUAGE 'plpgsql' VOLATILE
  COST  10 ;
ALTER FUNCTION do_del_orgdoc(character varying) OWNER TO postgres;
GRANT EXECUTE ON FUNCTION do_del_orgdoc(character varying) TO postgres;
GRANT EXECUTE ON FUNCTION do_del_orgdoc(character varying) TO "ctuUserRole";
        
CREATE OR REPLACE RULE v_doc_orgdoc_del AS ON DELETE TO v_doc_orgdoc
        DO INSTEAD( 
        --cтрока с селектом нужна что бы вернуть наружу правильный статус результата команды для ADO
        --SELECT orgdoc.orgdocid  FROM orgdoc WHERE orgdoc.orgdocid = old.orgdocid; 
        --DELETE FROM orgdoc WHERE orgdoc.orgdocid=OLD.orgdocid;
        --DELETE FROM doc WHERE doc.docid= OLD.docid;
        SELECT do_del_orgdoc(OLD.docid);
        );
...
Рейтинг: 0 / 0
25.03.2008, 11:01
    #35211396
Ёш
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Rules for View
в http://www.postgresql.org/docs/8.3/interactive/rules-update.html
написано:
авторFirst, their CREATE RULE command allows more:
They are allowed to have no action.
They can have multiple actions.
They can be INSTEAD or ALSO (the default).но я не совсем понял, имеется это ввиду несколько _отдельных_ rule на допустим delete или же несколько выражений через точку с запятой в одном rule... вообще - видимо второе, в примере синтаксиса написано несколько command; command;
авторCREATE [ OR REPLACE ] RULE name AS ON event
TO table [ WHERE condition ]
DO [ ALSO | INSTEAD ] { NOTHING | command | ( command ; command ... ) }так что это видимо ошибка, имхо нужно написать багрепорт. SeniorAndre , напишешь ? или мне написать ?


--
„Истина — это вовсе не то, что можно убедительно доказать, это то, что
делает всё проще и понятнее“ — Антуан де Сент-Экзюпери
...
Рейтинг: 0 / 0
25.03.2008, 11:25
    #35211485
SeniorAndre
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Rules for View
Я честно говоря с английским не очень, токо читаю, поэтому нормально написать BugReport не смогу...., но два оператора DELETE не работают точно, я уже попробовал и LEFT JOIN во VIEW и другие танцы..., не работает... пропадает OLD.DocId когда делаешь удаление из одной из таблиц участвующих во VIEW.
На данный момент убрал вызов процедуры, как указано в примере и поставил на реляцию каскадное удаление при удалении записи из Parent таблицы... и тоже всё Ок.
Хотя Update and Insert отрабатывают правильно, даже если в них прописано несколько команд.
...
Рейтинг: 0 / 0
25.03.2008, 14:26
    #35212166
Ёш
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Rules for View
написал: http://archives.postgresql.org/pgsql-bugs/2008-03/msg00247.php

кстати два отдельных rule тоже не работают:
Код: plaintext
1.
2.
3.
4.
5.
create rule v_del1 as on delete to v do instead (
       delete from o1 where id = old.o1_id;
);
create rule v_del2 as on delete to v do instead (
       delete from o2 where id = old.o2_id;
);
удаляет только первый, видимо какая-то проблема с передачей значений из второй таблицы в OLD параметр...


--
„Истина — это вовсе не то, что можно убедительно доказать, это то, что
делает всё проще и понятнее“ — Антуан де Сент-Экзюпери
...
Рейтинг: 0 / 0
25.03.2008, 14:46
    #35212258
Ёш
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Rules for View
я кажется понял почему второй rule не срабатывает - ведь в исходной таблице (view) из которой выбирается OLD параметр во время выполнения второго rule нужно строчки уже нет, не с чем джоинить вторую таблицу... так что это может быть не ошибка, а стандартное поведение для rule :)


--
„Истина — это вовсе не то, что можно убедительно доказать, это то, что
делает всё проще и понятнее“ — Антуан де Сент-Экзюпери
...
Рейтинг: 0 / 0
25.03.2008, 14:49
    #35212267
SeniorAndre
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Rules for View
Я же написал..., я делал LEFT JOIN таже пестня....
Код: plaintext
1.
2.
3.
CREATE OR REPLACE VIEW v_doc_orgdoc AS 
 SELECT d.docid, d.ourfirmid, d.doctypeid, d.docregnumber, d.docregdate, d.docname, d.docdescription, d.docformid, od.orgdocid, od.docstartdate, od.docclosedate, od.isdocfileoutsave, od.docfilename, od.docfile, od.docversion, d.isactive, d.modifyuser, d.modifyplace, d.modifydate, d.createuser, d.createplace, d.createdate
   FROM doc d
   LEFT JOIN orgdoc od ON d.docid = od.orgdocid;
...
Рейтинг: 0 / 0
25.03.2008, 15:19
    #35212380
Ёш
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Rules for View
Код: plaintext
FROM doc d
ну смотри, если первой удалится строка из doc - с чем джоинить соответствующую ей строку из orgdoc ? мне кажется что если при left join в rule удалять сначала из правой таблицы (orgdoc) то оба правила должны сработать, сейчас попробую... да - всё правильно - работает :) причём в where нужно выбирать по id из левой таблицы, иначе если выбирать в where по orgdoc.id - то после удаления из orgdoc правило опять же перестанет быть true


--
„Истина — это вовсе не то, что можно убедительно доказать, это то, что
делает всё проще и понятнее“ — Антуан де Сент-Экзюпери
...
Рейтинг: 0 / 0
25.03.2008, 15:27
    #35212424
4321
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Rules for View
гм. несколько не в тему:
вообще говоря давно вычисленно, что если надо произвести несколько стейтментов в руле, то наиболее безбаговым будет выполнение этого в одной процедуре. Особо это касается повторного вычисления (т.е. наваривания) счетчиков и прочих дефаултных функций (если что-то по этой части изменилось в 8.3 - было бы хорошо, а то багрепорт был полон ответов, что это "так по дизайну")
...
Рейтинг: 0 / 0
25.03.2008, 15:31
    #35212439
Ёш
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Rules for View
вообщем получается такой вариант:
Код: plaintext
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.
begin;

create table o1 (id int, val text);
create table o2 (id int, val text);
create view v as select o1.id as o1_id, o1.val as o1_val, o2.id as o2_id, o2.val as o2_val
from o1 left join o2 using(id);

create rule v_del as on delete to v do instead (
       delete from o2 where id = old.o2_id; --- обязательно удалять сначала из правой таблицы !
       delete from o1 where id = old.o1_id;
);

insert into o1 values ( 1 , 'o1 1'), ( 2 , 'o1 2'), ( 3 , 'o1 3');
insert into o2 values ( 1 , 'o2 1'), ( 2 , 'o2 2'), ( 3 , 'o2 3');

select * from v;

delete from v where o1_id =  1 ; --- обязательно проверять по индексу (полю) только из левой таблицы
delete from v where o2_id =  2 ; --- не сработает, так как после первого rule o2_id уже нет в OLD и "where o2_id = 2" перестаёт быть true
delete from v where o1_id =  3 ;

select * from v;

select * from o1;
select * from o2;

rollback;
результат как и ожидалось:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
seb=> DELETE  1 
seb=> DELETE  0 
seb=> DELETE  1 
seb=> select * from v;
  o1_id | o1_val | o2_id | o2_val 
-------+--------+-------+--------
      2  | o1  2    |       | 
( 1  запись)

seb=> select * from o1;
  id | val  
----+------
   2  | o1  2 
( 1  запись)

seb=> select * from o2;
  id | val 
----+-----
( 0  rows)

--
„Истина — это вовсе не то, что можно убедительно доказать, это то, что
делает всё проще и понятнее“ — Антуан де Сент-Экзюпери
...
Рейтинг: 0 / 0
25.03.2008, 15:38
    #35212469
Ёш
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Rules for View
4321гм. несколько не в тему:
вообще говоря давно вычисленно, что если надо произвести несколько стейтментов в руле, то наиболее безбаговым будет выполнение этого в одной процедуре. Особо это касается повторного вычисления (т.е. наваривания) счетчиков и прочих дефаултных функций (если что-то по этой части изменилось в 8.3 - было бы хорошо, а то багрепорт был полон ответов, что это "так по дизайну")полностью согласен :) достаточно вспомнить что rule реализованы не как обычные выражения, а как почти-макросы что бы всячески минимизировать их использование :) но зато только они могут сделать view - изменяемым.

В 8.3 по-моему ничего не меняли в этом плане, да в принципе имхо и не нужно...
...
Рейтинг: 0 / 0
25.03.2008, 16:58
    #35212811
SeniorAndre
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Rules for View
авторdelete from v where o1_id = 1; --- обязательно проверять по индексу (полю) только из левой таблицы
delete from v where o2_id = 2; --- не сработает, так как после первого rule o2_id уже нет в OLD и "where o2_id = 2" перестаёт быть true
delete from v where o1_id = 3;

Всем огромное спасибо...., ни когда бы недогался что от условия WHERE будет зависеть как он удаляет
Действительно самый корректный вариант будет делать через проседуру..., да в общем я так и сделал....
...
Рейтинг: 0 / 0
26.03.2008, 00:15
    #35213604
Ёш
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Rules for View
в завершение темы - Том Лейн ответил что вышеприведённое поведение rules - стандартно и так и должно было быть: http://archives.postgresql.org/pgsql-bugs/2008-03/msg00253.php


--
„Истина — это вовсе не то, что можно убедительно доказать, это то, что
делает всё проще и понятнее“ — Антуан де Сент-Экзюпери
...
Рейтинг: 0 / 0
26.03.2008, 08:07
    #35213739
SeniorAndre
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Rules for View
Тогда им просто нобходимо дополнить хелп..., что "OLD валуе меняется, если вы меняете исходные значения в таблицах из которых получается VIEW" или "ОLD валуе пересчитавается после каждого запроса" ХОтя это глупость..., OLD так олд.... на всё время выполнения Rule.
...
Рейтинг: 0 / 0
26.03.2008, 10:25
    #35213998
4321
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Rules for View
SeniorAndreХОтя это глупость..., OLD так олд.... на всё время выполнения Rule.а вот это не соответствует действительности. Руле в пг не "атомарно" - т.е. олд и нью меняются на каждом стейтменте. Даже число записей олдов/ньюев может меняться, не то, что какие-то-там поля.
<...................................................>
...
Рейтинг: 0 / 0
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Rules for View / 15 сообщений из 15, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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