confounding, incorrect constraint error
I've hit some really evil nastiness that is either a Postgres 7.1.3 bug,
or signs of early-onset senility for me. I was having trouble with my
database dying while inserting some values, and running some PL/pgSQL.
The schema is as listed below, and I'm getting
psql:fuck.sql:175: ERROR: ExecReplace: rejected due to CHECK constraint users_logged_in
while inserting values into the uservote table. If I had a few columns to
the users table, postgres crashes instead of giving this (nonsensical)
error.
I'd greatly appreciate any insight, even if it involves a 2x4.
Below is a significantly simplified version of my schema, which exhibits
the above problem.
DROP RULE uservote_update_item_mod;
DROP RULE uservote_delete_item_dec;
DROP RULE uservote_insert_item_inc;
DROP RULE itemvote_update_item_mod;
DROP RULE itemvote_delete_item_dec;
DROP RULE itemvote_insert_item_inc;
DROP FUNCTION mod_node_vote_count(INT4, INT2, INT2);
DROP TABLE uservote;
DROP TABLE itemvote;
DROP TABLE item;
DROP TABLE users;
DROP TABLE node;
DROP SEQUENCE node_id_seq;
CREATE SEQUENCE node_id_seq;
CREATE TABLE node (
node_id INT4 UNIQUE NOT NULL DEFAULT nextval('node_id_seq'),
name TEXT NOT NULL,
nays INT4 NOT NULL DEFAULT 0
CHECK ( nays >= 0 ),
yays INT4 NOT NULL DEFAULT 0,
CHECK ( yays >= 0 ),
rating INT2 NOT NULL DEFAULT 50
CHECK ( rating >= 0 AND rating <= 100 ),
PRIMARY KEY (node_id)
);
CREATE TABLE users (
node_id INT4 UNIQUE NOT NULL,
email TEXT NOT NULL,
realname TEXT NOT NULL,
pass_hash VARCHAR(32) NOT NULL,
logged_in INT2 NOT NULL DEFAULT 0
CHECK (logged_in = 0 OR logged_in = 1)
) INHERITS (node);
CREATE TABLE item (
node_id INT4 UNIQUE NOT NULL,
creator_id INT4 NOT NULL
REFERENCES users (node_id)
ON DELETE CASCADE
ON UPDATE CASCADE,
reason TEXT NOT NULL
) INHERITS (node);
CREATE TABLE itemvote (
vote_date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
target_id INT4 NOT NULL
REFERENCES item (node_id)
ON DELETE CASCADE
ON UPDATE CASCADE,
user_id INT4 NOT NULL
REFERENCES users (node_id)
ON DELETE CASCADE
ON UPDATE CASCADE,
nays INT2 NOT NULL
CHECK (nays = 0 OR nays = 1),
PRIMARY KEY (user_id, target_id)
);
CREATE TABLE uservote (
vote_date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
target_id INT4 NOT NULL
REFERENCES users (node_id)
ON DELETE CASCADE
ON UPDATE CASCADE,
user_id INT4 NOT NULL
REFERENCES users (node_id)
ON DELETE CASCADE
ON UPDATE CASCADE,
nays INT2 NOT NULL
CHECK (nays = 0 OR nays = 1),
PRIMARY KEY (user_id, target_id)
);
-- modifies an items nays/yays count totals as appropriate
-- first arg: item number
-- second arg: 1 or 0, nays or yays.
-- third arg: 1 or 0, add a vote, or remove a vote
CREATE FUNCTION mod_node_vote_count (INT4, INT2, INT2) RETURNS INT2 AS '
DECLARE
node_num ALIAS for $1;
nay_status ALIAS for $2;
add ALIAS for $3;
nay_tot INT4 NOT NULL DEFAULT 0;
yay_tot INT4 NOT NULL DEFAULT 0;
BEGIN
IF add = 1
THEN
IF nay_status = 1
THEN
UPDATE node SET nays = nays + 1 WHERE node_id = node_num;
ELSE
UPDATE node SET yays = yays + 1 WHERE node_id = node_num;
END IF;
ELSE
IF nay_status = 1
THEN
UPDATE node SET nays = nays - 1 WHERE node_id = node_num;
ELSE
UPDATE node SET yays = yays - 1 WHERE node_id = node_num;
END IF;
END IF;
SELECT nays INTO nay_tot FROM node WHERE node_id = node_num;
SELECT yays INTO yay_tot FROM node WHERE node_id = node_num;
IF nay_tot + yay_tot != 0
THEN
UPDATE node SET rating = CEIL( (yay_tot * 100)/(yay_tot + nay_tot) ) WHERE node_id = node_num;
ELSE
UPDATE node SET rating = 50 WHERE node_id = node_num;
END IF;
RETURN 1;
END;
' LANGUAGE 'plpgsql';
------------------------------------------------------------------------
-- vote totalling rules
-- vote insertion
CREATE RULE itemvote_insert_item_inc AS
ON INSERT TO itemvote DO
SELECT mod_node_vote_count(NEW.target_id, NEW.nays, 1);
CREATE RULE uservote_insert_item_inc AS
ON INSERT TO uservote DO
SELECT mod_node_vote_count(NEW.target_id, NEW.nays, 1);
-- vote deletion
CREATE RULE itemvote_delete_item_dec AS
ON DELETE TO itemvote DO
SELECT mod_node_vote_count(OLD.target_id, OLD.nays, 0);
CREATE RULE uservote_delete_item_dec AS
ON DELETE TO uservote DO
SELECT mod_node_vote_count(OLD.target_id, OLD.nays, 0);
-- vote updates
CREATE RULE itemvote_update_item_mod AS
ON UPDATE TO itemvote WHERE OLD.nays != NEW.nays DO
(SELECT mod_node_vote_count(OLD.target_id, OLD.nays, 1);
SELECT mod_node_vote_count(NEW.target_id, NEW.nays, 0););
CREATE RULE uservote_update_item_mod AS
ON UPDATE TO uservote WHERE OLD.nays != NEW.nays DO
(SELECT mod_node_vote_count(OLD.target_id, OLD.nays, 1);
SELECT mod_node_vote_count(NEW.target_id, NEW.nays, 0););
-- users
INSERT INTO users (name, pass_hash, realname, email) VALUES ('mosch', 'dafe001b7733b0f3236aa95e00f8ed88', 'Kevin', 'monica@whitehouse.gov');
INSERT INTO users (name, pass_hash, realname, email) VALUES ('Wakko', 'c6ef90fcf92bf703c3cc79a679c192a3', 'Alex', 'wakko@bitey.net');
-- items
INSERT INTO item (name, creator_id, reason) VALUES ('slashdot.org', 2, 'Because it\'s a pile of turd.');
INSERT INTO item (name, creator_id, reason) VALUES ('Yahoo!', 2, 'Because it\'s ugly.');
INSERT INTO item (name, creator_id, reason) VALUES ('memepool', 1, 'Because it\'s phat phat phat phat phat.');
INSERT INTO item (name, creator_id, reason) VALUES ('blow!!??!!', 1, 'this record nays nays nays');
-- item votes
INSERT INTO itemvote (target_id, user_id, nays) VALUES (3, 1, 1);
INSERT INTO itemvote (target_id, user_id, nays) VALUES (4, 1, 0);
INSERT INTO itemvote (target_id, user_id, nays) VALUES (5, 2, 1);
-- user votes
INSERT INTO uservote (target_id, user_id, nays) VALUES (2, 1, 0);
INSERT INTO uservote (target_id, user_id, nays) VALUES (1, 2, 1);
Below is a significantly simplified version of my schema, which
exhibits
the above problem.Unfortunately, even a simplified version of your schema would take me
some hours to understand. As your rule-setting is quite complex, my
first instinct would be to hunt for circular procedural logic in your
rules. Try to pursue, step by step, everything that happens from the
moment you send the insert command to uservotes. You may find that the
logic cascades back to the beginning. I've done this to myself on
occasion, causing the DB to hang on a seemingly simple request.
I'm fairly certain that there's no circular procedural logic.
The errors can be turned on/off by turning on/off the uservote_ series
of rules, which are attached to the uservote table. These rules call
mod_node_vote_count which only touches the node table. There are no
rules or triggers associated with the node table, so there is no circular
logic there.
Additional strangeness is that the itemvote_ series of rules works perfectly
despite the fact that the only difference between uservote_ and itemvote_
rules is the table that triggers them, they both call the same procedure on
the nodes table.
My current thinking is that something is stomping on some memory, because
you can vary the effect of the error from being an incorrectly failed CHECK
constraint, to crashing the database, by varying the number of columns in
the tables in question.
I'm unemployed at the moment and this is a pet project, so I can't offer
much in the way of financial compensation, but I'll start the bidding at
$50 donation in your name to your choice of the EFF, the Red Cross, or the
American Cancer Society, in return for a fix. (If none of these charities
are acceptable, surely one can be found later that is acceptable to both
parties).
Again, I greatly appreciate any help, and I apologize that my test case is
still fairly sizeable, despite being about 10% the size of the original
code.
-Kevin Way
Import Notes
Reply to msg id not found: web-124148@davinci.ethosmedia.com
Kevin Way wrote:
I'm unemployed at the moment and this is a pet project, so I can't offer
much in the way of financial compensation, but I'll start the bidding at
$50 donation in your name to your choice of the EFF, the Red Cross, or the
American Cancer Society, in return for a fix. (If none of these charities
are acceptable, surely one can be found later that is acceptable to both
parties).
Sorry, I missed the original post of the problem. If you can
send it to me again and change your offer into donating blood
at the Red Cross, I would take a look at it.
Jan
--
#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me. #
#================================================== JanWieck@Yahoo.com #
_________________________________________________________
Do You Yahoo!?
Get your free @yahoo.com address at http://mail.yahoo.com
Hi everybody!
I tried, and it works: the current CVS version really runs
happily the query what sent to heaven our 7.1 version of the
backend.
Kevin: your original complex schema also runs smoothly.
Thanks for our mindful developers!
Regards,
Baldvin
I think Jan wrote:
Sorry, I missed the original post of the problem. If you can
send it to me again and change your offer into donating blood
at the Red Cross, I would take a look at it.
Probably the chances for a prize went... :-(( However, is there
still a shortage of blod???
Baldvin
Baldvin,
Probably the chances for a prize went... :-(( However, is there
still a shortage of blod???
Last I checked, the American Red Cross does not want your blood right
now -- they want it two weeks from now. Currently blood stores are
full, but they get depleted pretty fast. Of course, what they really
want is for you to make a commitment to donate twice a year, every year.
-Josh
______AGLIO DATABASE SOLUTIONS___________________________
Josh Berkus
Complete information technology josh@agliodbs.com
and data management solutions (415) 565-7293
for law firms, small businesses fax 621-2533
and non-profit organizations. San Francisco
Kovacs Baldvin wrote:
Hi everybody!
I tried, and it works: the current CVS version really runs
happily the query what sent to heaven our 7.1 version of the
backend.Kevin: your original complex schema also runs smoothly.
Thanks for our mindful developers!
Regards,
BaldvinI think Jan wrote:
Sorry, I missed the original post of the problem. If you can
send it to me again and change your offer into donating blood
at the Red Cross, I would take a look at it.Probably the chances for a prize went... :-(( However, is there
still a shortage of blod???
Well, for the NY disaster they probably have more than enough
- not that many injured people there - sad enough though. But
what's wrong with using the current wave of patriotism to get
as much as they can get?
It help's saving life! Using the victims for that purpose
isn't abuse. It is turning grief, anger and sadness into
help and hope.
Let blood become "Open Source". Give it for free and you'll
get plenty of it when you need some.
Jan
--
#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me. #
#================================================== JanWieck@Yahoo.com #
_________________________________________________________
Do You Yahoo!?
Get your free @yahoo.com address at http://mail.yahoo.com
I tend to follow the mailing list through news.postgresql.org, and it seems
like all the -hackers messages are ending up in the .general group rather
than .hackers.
Did I somehow blow my configuration or are other people experiencing the
same thing?
AZ
August Zajonc:
I tend to follow the mailing list through news.postgresql.org, and it
seems
like all the -hackers messages are ending up in the .general group rather
than .hackers.
I also follow the mailing list(s) through news.postgresql.org and now that
you mention it ...
It hasn't always been like this.
Cheers,
Colin
On Mon, Sep 24, 2001 at 03:23:13PM -0400, Jan Wieck wrote:
It help's saving life! Using the victims for that purpose
isn't abuse. It is turning grief, anger and sadness into
help and hope.Let blood become "Open Source". Give it for free and you'll
get plenty of it when you need some.
I couldn't agree more!
-Roberto
--
+------------| Roberto Mello - http://www.brasileiro.net |------------+
Computer Science, Utah State University - http://www.usu.edu
USU Free Software & GNU/Linux Club - http://fslc.usu.edu
Space Dynamics Lab, Developer - http://www.sdl.usu.edu
OpenACS - Enterprise free web toolkit - http://openacs.org
TAFB -> Text Above Fullquote Below
"Colin 't Hart" <cthart@yahoo.com> wrote in message news:<9oo6en$qr8$1@news.tht.net>...
August Zajonc:
I tend to follow the mailing list through news.postgresql.org, and it
seems
like all the -hackers messages are ending up in the .general group rather
than .hackers.I also follow the mailing list(s) through news.postgresql.org and now that
you mention it ...It hasn't always been like this.
I'm getting the same thing. Almost nothing is going to the Hackers
list on Google groups (old Dejanews). They all seem to be sent to
other lists with the [HACKERS] id in the subject.
-Tony
Kovacs Baldvin <kb136@hszk.bme.hu> writes:
I tried, and it works: the current CVS version really runs
happily the query what sent to heaven our 7.1 version of the
backend.
I believe this traces to a fix I made in May:
2001-05-27 16:48 tgl
* src/: backend/executor/execJunk.c, backend/executor/execMain.c,
include/executor/executor.h, include/nodes/execnodes.h: When using
a junkfilter, the output tuple should NOT be stored back into the
same tuple slot that the raw tuple came from, because that slot has
the wrong tuple descriptor. Store it into its own slot with the
correct descriptor, instead. This repairs problems with SPI
functions seeing inappropriate tuple descriptors --- for example,
plpgsql code failing to cope with SELECT FOR UPDATE.
I didn't realize at the time that the error would also affect updates of
child tables, but tracing through your example with 7.1 shows clearly
that the CHECK is being applied to a slot that contains a four-column
tuple and only a three-column descriptor. Ooops.
regards, tom lane