Re: problem with RULEs

Lists: pgsql-general
From: Uros Gruber <uros(at)sir-mag(dot)com>
To: pgsql-general(at)postgresql(dot)org
Subject: problem with RULEs
Date: 2002-05-03 16:53:07
Message-ID: 19330346736.20020503185307@sir-mag.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

Hi!

I don't know if this can be done with RULES or i have to use
FUNCTIONS.

I have table categories with colums

id,parent,name,cats

this is some data

1 | 0 | cat1 | 3
2 | 0 | cat2 | 1
11 | 1 | cat3 | 1
12 | 1 | cat4 | 0
21 | 2 | cat5 | 0
111 | 11 | cat6 | 0

cats colum mean how mani categories are inside some category,
U can see that cat1 have 3 sub cats, one is also sub ob
category cat3. This column is like totalsub category.

Now i want create rule on insert. When i create new category
i want that this cats would get automaticaly increased in all
required rows.

For example if i insert category

INSERT categories (id,parent,name,cats) VALUES (112,11,cat7,0)

I would like to increase by one in cat3 and also in cat1.

I've make some rule to increase oly parent category but where
i try create new rule to update all subs i have error msg

query rewritten 10 times, may contain cycles

I think i've done something wrong.

Can somebody help me with this. What RULE to apply or maybe
this have to be done with function

--
tia,
Uros mailto:uros(at)sir-mag(dot)com


From: "Joel Burton" <joel(at)joelburton(dot)com>
To: "Uros Gruber" <uros(at)sir-mag(dot)com>, <pgsql-general(at)postgresql(dot)org>
Subject: Re: problem with RULEs
Date: 2002-05-03 17:36:28
Message-ID: JGEPJNMCKODMDHGOBKDNIELCCMAA.joel@joelburton.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

> I don't know if this can be done with RULES or i have to use
> FUNCTIONS.
>
> I have table categories with colums
>
> id,parent,name,cats
>
> this is some data
>
> 1 | 0 | cat1 | 3
> 2 | 0 | cat2 | 1
> 11 | 1 | cat3 | 1
> 12 | 1 | cat4 | 0
> 21 | 2 | cat5 | 0
> 111 | 11 | cat6 | 0
>
> cats colum mean how mani categories are inside some category,
> U can see that cat1 have 3 sub cats, one is also sub ob
> category cat3. This column is like totalsub category.
>
> Now i want create rule on insert. When i create new category
> i want that this cats would get automaticaly increased in all
> required rows.
>
> For example if i insert category
>
> INSERT categories (id,parent,name,cats) VALUES (112,11,cat7,0)
>
> I would like to increase by one in cat3 and also in cat1.
>
> I've make some rule to increase oly parent category but where
> i try create new rule to update all subs i have error msg
>
> query rewritten 10 times, may contain cycles
>
> I think i've done something wrong.
>
> Can somebody help me with this. What RULE to apply or maybe
> this have to be done with function

Uros --

You're getting the "may contain cycles" message because your UPDATE query
goes to your rule, which issues an UPDATE query, which goes to your rule ...

You could do this with a function w/o a rule, but you'd lose the natural
solution that rules would provide... other users wouldn't have to understand
anything to get the rule action to work.

How about:

Make a view of your table (CREATE VIEW xxx AS SELECT * FROM table)

Instead of putting the INSERT/UPDATE rules on the table, put them on the
view. Have the view INSERT and UPDATE rules calculate the correct values and
perform the INSERTs and UPDATEs directly on the table.

This way, your users can simply SELECT, INSERT, UPDATE, DELETE from the view
and the changes will get made to the table -- without the risk of the
recursive problem you're having now.

J.


From: Uros Gruber <uros(at)sir-mag(dot)com>
To: "Joel Burton" <joel(at)joelburton(dot)com>
Cc: pgsql-general(at)postgresql(dot)org
Subject: Re: problem with RULEs
Date: 2002-05-03 19:27:55
Message-ID: 1039634781.20020503212755@sir-mag.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

Hi!

I think i don't understand this everything. How can i solve
this with views. Can you put some example, maybe on my table.

--
tia,
Uros mailto:uros(at)sir-mag(dot)com

Friday, May 3, 2002, 7:36:28 PM, you wrote:

>> I don't know if this can be done with RULES or i have to use
>> FUNCTIONS.
>>
>> I have table categories with colums
>>
>> id,parent,name,cats
>>
>> this is some data
>>
>> 1 | 0 | cat1 | 3
>> 2 | 0 | cat2 | 1
>> 11 | 1 | cat3 | 1
>> 12 | 1 | cat4 | 0
>> 21 | 2 | cat5 | 0
>> 111 | 11 | cat6 | 0
>>
>> cats colum mean how mani categories are inside some category,
>> U can see that cat1 have 3 sub cats, one is also sub ob
>> category cat3. This column is like totalsub category.
>>
>> Now i want create rule on insert. When i create new category
>> i want that this cats would get automaticaly increased in all
>> required rows.
>>
>> For example if i insert category
>>
>> INSERT categories (id,parent,name,cats) VALUES (112,11,cat7,0)
>>
>> I would like to increase by one in cat3 and also in cat1.
>>
>> I've make some rule to increase oly parent category but where
>> i try create new rule to update all subs i have error msg
>>
>> query rewritten 10 times, may contain cycles
>>
>> I think i've done something wrong.
>>
>> Can somebody help me with this. What RULE to apply or maybe
>> this have to be done with function

JB> Uros --

JB> You're getting the "may contain cycles" message because your UPDATE query
JB> goes to your rule, which issues an UPDATE query, which goes to your rule ...

JB> You could do this with a function w/o a rule, but you'd lose the natural
JB> solution that rules would provide... other users wouldn't have to understand
JB> anything to get the rule action to work.

JB> How about:

JB> Make a view of your table (CREATE VIEW xxx AS SELECT * FROM table)

JB> Instead of putting the INSERT/UPDATE rules on the table, put them on the
JB> view. Have the view INSERT and UPDATE rules calculate the correct values and
JB> perform the INSERTs and UPDATEs directly on the table.

JB> This way, your users can simply SELECT, INSERT, UPDATE, DELETE from the view
JB> and the changes will get made to the table -- without the risk of the
JB> recursive problem you're having now.

JB> J.

JB> ---------------------------(end of broadcast)---------------------------
JB> TIP 6: Have you searched our list archives?

JB> http://archives.postgresql.org


From: Masaru Sugawara <rk73news(at)rmail(dot)plala(dot)or(dot)jp>
To: Uros Gruber <uros(at)sir-mag(dot)com>
Cc: pgsql-general(at)postgresql(dot)org
Subject: Re: problem with RULEs
Date: 2002-05-04 17:41:34
Message-ID: 20020505005737.1E77.RK73NEWS@rmail.plala.or.jp
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

On Fri, 3 May 2002 21:27:55 +0200
Uros Gruber <uros(at)sir-mag(dot)com> wrote:

> I think i don't understand this everything. How can i solve
> this with views. Can you put some example, maybe on my table.
>

> Friday, May 3, 2002, 7:36:28 PM, you wrote:
>
> >> I don't know if this can be done with RULES or i have to use
> >> FUNCTIONS.

In the recursive task, it seems to be considerably hard to accomplish
auto-increment function by using RULE. In stead of it, I would think its task
can be also solved by TRIGGER + recursive FUNCTIONs. The routines to check
the depth of child-to-parent relations and the value of cats have been attached
already. When necessary, you could take ones more into account.

-- DROP TABLE categories;
CREATE TABLE categories(id int4 UNIQUE,
parent int4 NOT NULL,
name text,
cats int4 NOT NULL DEFAULT 0);
INSERT INTO categories VALUES( 1, 0, 'cat1', 3);
INSERT INTO categories VALUES( 2, 0, 'cat2', 1);
INSERT INTO categories VALUES( 11, 1, 'cat3', 1);
INSERT INTO categories VALUES( 12, 1, 'cat4', 0);
INSERT INTO categories VALUES( 21, 2, 'cat5', 0);
INSERT INTO categories VALUES(111, 11, 'cat6', 0);

-- DROP FUNCTION fn_inclement_cats(int4, int4);
CREATE OR REPLACE FUNCTION fn_inclement_cats(int4, int4) RETURNS boolean AS '
DECLARE
p int4; -- p is used for searching parent.
n int4; -- n is limitation of the depth of child-to-parent relations.
rec RECORD;
ret boolean := true;
BEGIN
p := $1;
n := $2;

WHILE ret = true LOOP
SELECT INTO rec * FROM categories WHERE id = p;
IF NOT FOUND THEN
ret := false;
ELSE
UPDATE categories SET cats = cats + 1 WHERE id = p;
RAISE NOTICE
''The value of cats at id = % is updated.'', rec.id;
IF n < 1000 THEN
ret := fn_inclement_cats(rec.parent, n + 1);
ELSE
RAISE EXCEPTION
''These child-to-parent relations are too deep !!'';
ret := false;
END IF;
END IF;
END LOOP;
RETURN ret;
END;
' LANGUAGE 'plpgsql';

-- DROP FUNCTION fn_cats();
CREATE OR REPLACE FUNCTION fn_cats() RETURNS opaque AS '
BEGIN
IF NEW.cats = 0 THEN
PERFORM fn_inclement_cats(NEW.parent, 1);
RAISE NOTICE ''Updating is done.'';
ELSE
RAISE EXCEPTION ''The value of cats must be zero.'';
END IF;
RETURN NEW;
END;
' LANGUAGE 'plpgsql';

-- DROP TRIGGER tg_cats ON categories;
CREATE TRIGGER tg_cats
BEFORE INSERT ON categories
FOR EACH ROW
EXECUTE PROCEDURE fn_cats();

> >> For example if i insert category
> >>
> >> INSERT categories (id,parent,name,cats) VALUES (112,11,cat7,0)
> >>
> >> I would like to increase by one in cat3 and also in cat1.
> >>

renew=# select * from categories order by 1;
id | parent | name | cats
-----+--------+------+------
1 | 0 | cat1 | 3
2 | 0 | cat2 | 1
11 | 1 | cat3 | 1
12 | 1 | cat4 | 0
21 | 2 | cat5 | 0
111 | 11 | cat6 | 0
(6 rows)

renew=# insert into categories values(112, 11, 'cat7', 0);
NOTICE: The value of cats at id = 11 is updated.
NOTICE: The value of cats at id = 1 is updated.
NOTICE: Updating is done.
INSERT 74123 1

renew=# select * from categories order by 1;
id | parent | name | cats
-----+--------+------+------
1 | 0 | cat1 | 4
2 | 0 | cat2 | 1
11 | 1 | cat3 | 2
12 | 1 | cat4 | 0
21 | 2 | cat5 | 0
111 | 11 | cat6 | 0
112 | 11 | cat7 | 0
(7 rows)

Regards,
Masaru Sugawara


From: Masaru Sugawara <rk73(at)sea(dot)plala(dot)or(dot)jp>
To: Uros Gruber <uros(at)sir-mag(dot)com>
Cc: pgsql-general(at)postgresql(dot)org
Subject: Re: problem with RULEs
Date: 2002-05-04 19:22:56
Message-ID: 20020505042149.1E83.RK73@sea.plala.or.jp
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

On Fri, 3 May 2002 21:27:55 +0200
Uros Gruber <uros(at)sir-mag(dot)com> wrote:

> I think i don't understand this everything. How can i solve
> this with views. Can you put some example, maybe on my table.
>

> Friday, May 3, 2002, 7:36:28 PM, you wrote:
>
> >> I don't know if this can be done with RULES or i have to use
> >> FUNCTIONS.

In the recursive task, it seems to be considerably hard to accomplish
auto-increment function by using RULE. In stead of it, I would think its
task can be also solved by TRIGGER + recursive FUNCTIONs. The routines
to check the depth of child-to-parent relations and the value of cats
have been attached already. When necessary, you could take ones more
into account.

-- DROP TABLE categories;
CREATE TABLE categories(id int4 UNIQUE,
parent int4 NOT NULL,
name text,
cats int4 NOT NULL DEFAULT 0);
INSERT INTO categories VALUES( 1, 0, 'cat1', 3);
INSERT INTO categories VALUES( 2, 0, 'cat2', 1);
INSERT INTO categories VALUES( 11, 1, 'cat3', 1);
INSERT INTO categories VALUES( 12, 1, 'cat4', 0);
INSERT INTO categories VALUES( 21, 2, 'cat5', 0);
INSERT INTO categories VALUES(111, 11, 'cat6', 0);

-- DROP FUNCTION fn_inclement_cats(int4, int4);
CREATE OR REPLACE FUNCTION fn_inclement_cats(int4, int4) RETURNS boolean AS '
DECLARE
p int4; -- p is used for searching parent.
n int4; -- n is limitation of the depth of child-to-parent relations.
rec RECORD;
ret boolean := true;
BEGIN
p := $1;
n := $2;

WHILE ret = true LOOP
SELECT INTO rec * FROM categories WHERE id = p;
IF NOT FOUND THEN
ret := false;
ELSE
UPDATE categories SET cats = cats + 1 WHERE id = p;
RAISE NOTICE
''The value of cats at id = % is updated.'', rec.id;
IF n < 1000 THEN
ret := fn_inclement_cats(rec.parent, n + 1);
ELSE
RAISE EXCEPTION
''These child-to-parent relations are too deep !!'';
ret := false;
END IF;
END IF;
END LOOP;
RETURN ret;
END;
' LANGUAGE 'plpgsql';

-- DROP FUNCTION fn_cats();
CREATE OR REPLACE FUNCTION fn_cats() RETURNS opaque AS '
BEGIN
IF NEW.cats = 0 THEN
PERFORM fn_inclement_cats(NEW.parent, 1);
RAISE NOTICE ''Updating is done.'';
ELSE
RAISE EXCEPTION ''The value of cats must be zero.'';
END IF;
RETURN NEW;
END;
' LANGUAGE 'plpgsql';

-- DROP TRIGGER tg_cats ON categories;
CREATE TRIGGER tg_cats
BEFORE INSERT ON categories
FOR EACH ROW
EXECUTE PROCEDURE fn_cats();

> >> For example if i insert category
> >>
> >> INSERT categories (id,parent,name,cats) VALUES (112,11,cat7,0)
> >>
> >> I would like to increase by one in cat3 and also in cat1.
> >>

renew=# select * from categories order by 1;
id | parent | name | cats
-----+--------+------+------
1 | 0 | cat1 | 3
2 | 0 | cat2 | 1
11 | 1 | cat3 | 1
12 | 1 | cat4 | 0
21 | 2 | cat5 | 0
111 | 11 | cat6 | 0
(6 rows)

renew=# insert into categories values(112, 11, 'cat7', 0);
NOTICE: The value of cats at id = 11 is updated.
NOTICE: The value of cats at id = 1 is updated.
NOTICE: Updating is done.
INSERT 74123 1

renew=# select * from categories order by 1;
id | parent | name | cats
-----+--------+------+------
1 | 0 | cat1 | 4
2 | 0 | cat2 | 1
11 | 1 | cat3 | 2
12 | 1 | cat4 | 0
21 | 2 | cat5 | 0
111 | 11 | cat6 | 0
112 | 11 | cat7 | 0
(7 rows)

Regards,
Masaru Sugawara