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);

Sun, 23 Sep 2001 07:09:46 +0000
Kevin Way <kevin.way@overtone.org>
confounding, incorrect constraint error
> > 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
Sun, 23 Sep 2001 20:54:01 +0000
Kevin Way <kevin.way@overtone.org>
Re: confounding, incorrect constraint error
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


Mon, 24 Sep 2001 14:12:03 -0400 (EDT)
Jan Wieck <JanWieck@Yahoo.com>
Re: confounding, incorrect constraint error
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



Mon, 24 Sep 2001 20:38:20 +0200 (MEST)
Kovacs Baldvin <kb136@hszk.bme.hu>
CHECK problem really OK now...
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

Mon, 24 Sep 2001 12:18:04 -0700
"Josh Berkus" <josh@agliodbs.com>
Re: CHECK problem really OK now...
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,
> 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???

    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


Mon, 24 Sep 2001 15:23:13 -0400 (EDT)
Jan Wieck <JanWieck@Yahoo.com>
Re: CHECK problem really OK now...
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



Mon, 24 Sep 2001 13:38:27 -0700
"August Zajonc" <junk-pgsql@aontic.com>
[HACKERS] not on .hackers
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



Mon, 24 Sep 2001 22:51:14 +0200
"Colin 't Hart" <cthart@yahoo.com>
Re: [HACKERS] not on .hackers
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 

Mon, 24 Sep 2001 22:49:57 -0600
Roberto Mello <rmello@cc.usu.edu>
Re: CHECK problem really OK now...
"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

25 Sep 2001 11:59:20 -0700
reina@nsi.edu (Tony Reina)
Re: [HACKERS] not on .hackers
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

Wed, 26 Sep 2001 14:36:58 -0400
Tom Lane <tgl@sss.pgh.pa.us>
Re: [SQL] CHECK problem really OK now... 