Re: [ADMIN] How to enforce the use of the sequence for serial columns

2006-12-14 Thread Ben K.

It's not a full solution anyway since it prevents any kind of update
on the table due to check constraints firing  even if target field not
updated.  See below;


Right. It was not a valid idea ...


Regards,

Ben K.
Developer
http://benix.tamu.edu

---(end of broadcast)---
TIP 3: Have you checked our extensive FAQ?

  http://www.postgresql.org/docs/faq


Re: [ADMIN] How to enforce the use of the sequence for serial columns

2006-12-14 Thread Marc Mamin

> It's not a full solution anyway since it prevents any kind of update
on the table due to check constraints firing  even if target field not
updated.  >

Well, we can extend the check within the trigger:

if (coalesce old.a=new.a -- Update
OR 
new.a = currval(tg_argv[0] -- Insert
) then
  return new;  
end if;

Marc



---(end of broadcast)---
TIP 9: In versions below 8.0, the planner will ignore your desire to
   choose an index scan if your joining column's datatypes do not
   match


Re: [ADMIN] How to enforce the use of the sequence for serial columns

2006-12-14 Thread Jerry Sievers
"Ben K." <[EMAIL PROTECTED]> writes:

> > create table mytable (myid serial primary key constraint
> mytable_myid_chk check (myid = currval('mytable_myid_seq'), mydata
> varchar(255), ...);
> 
> 
> I'd like to clarify that this will not be a full solution, since it
> will not allow update of the table unless nextval has been used in the
> same sequence already.

It's not a full solution anyway since it prevents any kind of update
on the table due to check constraints firing  even if target field not
updated.  See below;


[EMAIL PROTECTED]
= create table foo (a serial check (a = currval('foo_a_seq')), b int);
NOTICE:  CREATE TABLE will create implicit sequence "foo_a_seq" for serial 
column "foo.a"
CREATE TABLE
[EMAIL PROTECTED]
= insert into foo values (default, 1);
INSERT 0 1
[EMAIL PROTECTED]
= insert into foo values (default, 1);
INSERT 0 1
[EMAIL PROTECTED]
= insert into foo values (default, 1);
INSERT 0 1
[EMAIL PROTECTED]
= insert into foo values (default, 1);
INSERT 0 1
[EMAIL PROTECTED]
= select * from foo;
 a | b 
---+---
 1 | 1
 2 | 1
 3 | 1
 4 | 1
(4 rows)

[EMAIL PROTECTED]
= update foo set b=2;
ERROR:  new row for relation "foo" violates check constraint "foo_a_check"
[EMAIL PROTECTED]
= 


> 
> There seems to be a hack in case of oracle that allows using currval
> without nextval, but it's a hack and I don't know if there's an
> equivalent in postgresql
> (http://rootshell.be/~yong321/computer/sequence.txt). (Oracle seems to
> have "disable" option when adding check constraint by alter table, but
> the context seem a bit different from ours so may not be useful in our
> case, at any rate.)
> 
> 
> 
> 
> Regards
> 
> Ben K.
> Developer
> http://benix.tamu.edu
> 
> 
> 
> 
> ---(end of broadcast)---
> TIP 2: Don't 'kill -9' the postmaster
> 
> ---(end of broadcast)---
> TIP 5: don't forget to increase your free space map settings
> 

-- 
---
Jerry Sievers   305 854-3001 (home) Production Database Administrator
305 321-1144 (mobil WWW E-Commerce Consultant

---(end of broadcast)---
TIP 3: Have you checked our extensive FAQ?

   http://www.postgresql.org/docs/faq


Re: [ADMIN] How to enforce the use of the sequence for serial columns

2006-12-14 Thread Ben K.



create table mytable (myid serial primary key constraint 
mytable_myid_chk check 
(myid = currval('mytable_myid_seq'), mydata varchar(255), ...);



I'd like to clarify that this will not be a full solution, since it will 
not allow update of the table unless nextval has been used in the same 
sequence already.


There seems to be a hack in case of oracle that allows using currval 
without nextval, but it's a hack and I don't know if there's an equivalent 
in postgresql (http://rootshell.be/~yong321/computer/sequence.txt). 
(Oracle seems to have "disable" option when adding check constraint by 
alter table, but the context seem a bit different from ours so may not be 
useful in our case, at any rate.)





Regards

Ben K.
Developer
http://benix.tamu.edu




---(end of broadcast)---
TIP 2: Don't 'kill -9' the postmaster

---(end of broadcast)---
TIP 5: don't forget to increase your free space map settings


Re: [ADMIN] How to enforce the use of the sequence for serial columns ?

2006-12-14 Thread Marc Mamin
 

>Trigger based solution where same trig can be used for any number of
tables by changing the parameter.

>Will throw one of 2 exceptions on failure to use sequence for the
insert.


Many thanks,
This seems to be the simplest solution,

Marc

---(end of broadcast)---
TIP 2: Don't 'kill -9' the postmaster


Re: [ADMIN] How to enforce the use of the sequence for serial columns

2006-12-13 Thread Ben K.

"Marc Mamin" <[EMAIL PROTECTED]> writes:

I'd like to ensure that nobody provide the ID in an insert statement
when the id is linked to a sequence.
I tried it with a trigger, but the id value is fed before the "BEFORE
INSERT" test is performed (see below)...


If you have the luxury of re-creating the table (dump, edit schema, 
reload), you might want to try this:


create table mytable (myid serial primary key constraint mytable_myid_chk check (myid = 
currval('mytable_myid_seq'), mydata varchar(255), ...);


This will prevent "serial" id field from being arbitrarily manipulated
outside the sequence..

There may be an equivalent way using alter table, but on a first look, currval
cannot be used to check existing values.


Regards

Ben K.
Developer
http://benix.tamu.edu




---(end of broadcast)---
TIP 2: Don't 'kill -9' the postmaster


Re: [ADMIN] How to enforce the use of the sequence for serial columns ?

2006-12-13 Thread Jerry Sievers
"Marc Mamin" <[EMAIL PROTECTED]> writes:

> I'd like to ensure that nobody provide the ID in an insert statement
> when the id is linked to a sequence.
> I tried it with a trigger, but the id value is fed before the "BEFORE
> INSERT" test is performed (see below)...
> 
> 
> Any Idea ?

Trigger based solution where same trig can be used for any number of
tables by changing the parameter.

Will throw one of 2 exceptions on failure to use sequence for the insert.

create table foo (a serial);
psql:q:2: NOTICE:  CREATE TABLE will create implicit sequence "foo_a_seq" for 
serial column "foo.a"
CREATE TABLE
create function footrig()
returns trigger
as $$
begin
-- may throw currval not defined exception
if new.a = currval(tg_argv[0]) then
-- currval defined and equal new col value
return new;
end if;

-- currval is defined but not used for this insert
raise exception 'Not using default sequence';
end
$$ language plpgsql;
CREATE FUNCTION
create trigger footrig
before insert on foo
for each row
execute procedure footrig('foo_a_seq');
CREATE TRIGGER
You are now connected to database "jerry".
insert into foo values (1000);
psql:q:25: ERROR:  currval of sequence "foo_a_seq" is not yet defined in this 
session
CONTEXT:  PL/pgSQL function "footrig" line 3 at if
insert into foo values (default);
INSERT 0 1
insert into foo values (1000);
psql:q:27: ERROR:  Not using default sequence
select * from foo;
 a 
---
 1
(1 row)


> Cheers,
> 
> Marc
> 
> 
> 
> CREATE FUNCTION serialtest() RETURNS trigger AS $serialtest$
> BEGIN
> -- Check that the id is provided
> IF NEW.id IS NOT NULL THEN
> RAISE EXCEPTION 'id will be set from a sequence; do not
> provide it!';
> END IF;
> 
> RETURN NEW;
> END;
> $serialtest$ LANGUAGE plpgsql;
> 
> 
> CREATE TABLE test_table
> (
>   id serial primary key,
>   foo int
> );
> 
> 
> CREATE TRIGGER test BEFORE INSERT OR UPDATE ON test_table 
> FOR EACH ROW EXECUTE PROCEDURE serialtest();
> 
> 
> insert into test_table(foo)values(1);
> 
> ERROR: id will be set from a sequence; do not provide it!
> SQL state: P0001

-- 
---
Jerry Sievers   305 854-3001 (home) Production Database Administrator
305 321-1144 (mobil WWW E-Commerce Consultant

---(end of broadcast)---
TIP 1: if posting/reading through Usenet, please send an appropriate
   subscribe-nomail command to [EMAIL PROTECTED] so that your
   message can get through to the mailing list cleanly


Re: [ADMIN] How to enforce the use of the sequence for serial columns ?

2006-12-13 Thread Donald Fraser
How to enforce the use of the sequence for serial columns ?There are many
ways, here are a couple to think about:
1)
Revoke all access to the table and then create a VIEW to access the table
where by you simply don't use column "id" in the VIEWs insert / update
statements.

2)
Manually retrieve the serial number from a trigger function and modify
column "id" in the function.


Regards
Donald Fraser

- Original Message - 
From: Marc Mamin

I'd like to ensure that nobody provide the ID in an insert statement when
the id is linked to a sequence.
I tried it with a trigger, but the id value is fed before the "BEFORE
INSERT" test is performed (see below)...


Any Idea ?
Cheers,
Marc



CREATE FUNCTION serialtest() RETURNS trigger AS $serialtest$
BEGIN
-- Check that the id is provided
IF NEW.id IS NOT NULL THEN
RAISE EXCEPTION 'id will be set from a sequence; do not provide
it!';
END IF;

RETURN NEW;
END;
$serialtest$ LANGUAGE plpgsql;


CREATE TABLE test_table
(
  id serial primary key,
  foo int
);


CREATE TRIGGER test BEFORE INSERT OR UPDATE ON test_table
FOR EACH ROW EXECUTE PROCEDURE serialtest();


insert into test_table(foo)values(1);
ERROR: id will be set from a sequence; do not provide it!
SQL state: P0001



---(end of broadcast)---
TIP 9: In versions below 8.0, the planner will ignore your desire to
   choose an index scan if your joining column's datatypes do not
   match