Skip to content

Conversation

@cbbrowne
Copy link
Contributor

@cbbrowne cbbrowne commented Mar 7, 2012

Here is a "drafty" form of drawing location off of the main ship table to a separate ship_location table.

cbbrowne added 2 commits March 6, 2012 00:25
…bably not complete; future_health should also be drawn out, possibly to the same table.
@Abstrct
Copy link
Owner

Abstrct commented Mar 7, 2012

I was a bit worried about currval(seq) due to the way ID's are handled in the game but I just gave some code a go to test it and there were no complications. There is no reason why we cannot trust currval('ship_id_seq) in the insert into the ship_location table during the my_ships view insert rule.

CREATE SEQUENCE s_seq
INCREMENT 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 1
CACHE 1;

create table s (
id integer,
val integer
);
create table s_l (
id integer,
val integer
);
create view s_v as select
s.id, s.val sval, s_l.val as slval FROM s, s_l WHERE s.id=s_l.id;

CREATE OR REPLACE RULE s_insert AS
ON INSERT TO s_v DO INSTEAD (
INSERT INTO s(val) VALUES(NEW.sval);
INSERT INTO s_l VALUES(currval('s_seq'), NEW.slval);
) ;

CREATE OR REPLACE FUNCTION id_dealer()
RETURNS trigger AS
$BODY$
BEGIN
NEW.id = nextval('s_seq');

RETURN NEW;
END
$BODY$
LANGUAGE plpgsql VOLATILE SECURITY DEFINER
COST 100;

CREATE TRIGGER d_dealer
BEFORE INSERT OR UPDATE
ON s
FOR EACH ROW
EXECUTE PROCEDURE id_dealer();

-- Run each of these in a different process
INSERT INTO s_v(slval, sval) SELECT 1,1 from generate_series(1,1000000);
INSERT INTO s_v(slval, sval) SELECT 2,2 from generate_series(1,1000000);
INSERT INTO s_v(slval, sval) SELECT 3,3 from generate_series(1,1000000);

--Check to missmatched results
select * from s_v where slval <> sval
-- No Results were returned

@cbbrowne
Copy link
Contributor Author

cbbrowne commented Mar 8, 2012

There is an alternate perspective of "currval" which involves the function returning the most recently generated sequence value from ANY sequence associated with your DB connection.

Which is perhaps the most terrible behavior possible; it means that if you decided to (say) replicate Schemaverse using Slony or Londiste, you might instead capture sequence values being used as part of the internals of those replication systems. Horrible, horrible, horrible.

(Poking at docs...) Ah, the function that does this is lastval(). http://www.postgresql.org/docs/9.1/static/functions-sequence.html You'd have to be insane and stupid to use lastval() for anything.

But if you use currval('specific_seq_name'), it's all good.

A couple years ago, I was working on an experimental domain registry prototype where we were using currval() extremely heavily to establish transaction contexts. Basically, we'd create a logical transaction:
insert into transaction (id, when, who) values (nextval('tx'), now(), 'my-user-name');

and then, throughout the rest of the DB activity, HEAVY use was made of currval('tx') to reference the transaction context data.

"Oh, what time are we using for this transaction?" (It didn't have to be NOW() - it was meaningful to backdate/forward date activity.)

  • select when from transaction where id = currval('tx');

"Oh, who's the user?"

  • select who from transaction where id = currval('tx');

We'd attach all kinds of additional data to the transaction by joining in extra tables; the key to getting at it was always currval('tx'). And this worked out AOK. I have a fair bit of faith in currval() :-).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants