0

I'm using PostgreSQL (8.3+) and have defined an enum and a table as follows:

CREATE TYPE "viewer_action" AS ENUM ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H');

CREATE TABLE "preferences"  ( 
    "user_id"       integer NOT NULL,
    "item_id"       integer NOT NULL,
    "rating"        viewer_action NOT NULL,
    "time_created"  timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY ("user_id","video_id")
);

I've also created a stored procedure to upsert new rows into the preferences table, using the example from http://www.postgresql.org/docs/current/static/plpgsql-control-structures.html#PLPGSQL-UPSERT-EXAMPLE:

CREATE OR REPLACE FUNCTION add_preference(u INT, i INT, r viewer_action) RETURNS VOID AS $add_preference$
    BEGIN
        LOOP
            -- first try to update the key
            UPDATE preferences SET rating = r WHERE user_id = u AND item_id = i;
            IF found THEN
                RETURN;
            END IF;
            -- not there, so try to insert the key
            -- if someone else inserts the same key concurrently,
            -- we could get a unique-key failure
            BEGIN
                INSERT INTO preferences(user_id,item_id,rating) VALUES (u,i,r);
                RETURN;
            EXCEPTION WHEN unique_violation THEN
                -- do nothing, and loop to try the UPDATE again
            END;
        END LOOP;
    END;
$add_preference$ LANGUAGE plpgsql;

I need to add some additional logic to the upsert to prevent some values from overwriting other values. Specifically:

  • A can be overwritten by B, which can by overwritten by C, which can be overwritten by D, and so on through F. But B cannot by overwritten by A, nor C overwritten by B, etc.
  • F, G, or H can overwrite any value, regardless if an existing value is lower or higher.

In pseudocode, this might look like:

if (rating >= F) {
    insert;
} else if (rating > existing_rating) {
    insert;
} else {
    return;
}
1
  • 3
    Control flow is supported in plpgsql. It seems as if you can implement your code almost directly. Commented Dec 20, 2010 at 22:39

3 Answers 3

1

Create a trigger ON BEFORE INSERT OR UPDATE on this table. For that you could use your function, with small changes like changing the return type to TRIGGER.

The BEFORE triggers are fired before inserting rows into tables, so you can check the data before writing them.

More information on triggers you can find here:
http://www.postgresql.org/docs/9.0/interactive/plpgsql-trigger.html

Sign up to request clarification or add additional context in comments.

Comments

0

The way to look is CASE http://www.postgresql.org/docs/8.2/static/functions-conditional.html#AEN13066 it shouldn't be so difficult to implement it. And as @szymon-guz suggested, place it in trigger.

Comments

0

Can't you do something with a case statement?

Something like this.

--If new rating is greater than existing rating update it else update to current value.
    UPDATE preferences
    SET rating = CASE WHEN r > rating THEN r ELSE rating END;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.