Alexander Farber
Alexander Farber

Reputation: 22988

Update 1 of 2 columns - depending on a condition

In a game for 2 players I am trying to allow skipping a player's turn by calling the following stored function:

CREATE OR REPLACE FUNCTION skip_game(
        IN in_uid integer, -- player id
        IN in_gid integer) -- game id
        RETURNS void AS
$func$
BEGIN
        UPDATE games
        SET stamp1 = extract('epoch' from current_timestamp)
        WHERE gid = in_gid
        AND player1 = in_uid
        AND stamp1 < stamp2; -- it is player1's turn

        IF NOT FOUND THEN
                UPDATE games
                SET stamp2 = extract('epoch' from current_timestamp)
                WHERE gid = in_gid
                AND player2 = in_uid
                AND stamp2 < stamp1; -- it is player2's turn
        END IF;

END
$func$  LANGUAGE plpgsql;

Is it please possible to combine the two above UPDATE-statements to a single one - and set either stamp1 or stamp2 to current epoch time, depending on the condition?

Also, I don't understand, why does PostgreSQL 9.5 always report 1 row being updated - event if I call that function with invalid arguments?

# select skip_game(1, 1);
 skip_game
-----------------

(1 row)

# select skip_game(95, 95);
 skip_game
-----------------

(1 row)

Here is the games table (I use epoch integers for the stamp columns for easier communication with the mobile app at the client side - which uses SQLite):

CREATE TABLE games (
        gid SERIAL PRIMARY KEY,
        created TIMESTAMP NOT NULL,

        player1 INTEGER REFERENCES users(uid) ON DELETE CASCADE NOT NULL,
        player2 INTEGER REFERENCES users(uid) ON DELETE CASCADE,

        stamp1 INTEGER, -- timestamp of the last turn
        stamp2 INTEGER, -- timestamp of the last turn

        letters1 VARCHAR(7) NOT NULL,
        letters2 VARCHAR(7) NOT NULL,
        letters  VARCHAR(116) NOT NULL,

        board VARCHAR(225) NOT NULL,
        style INTEGER NOT NULL CHECK (1 <= style AND style <= 4)
);

Upvotes: 0

Views: 45

Answers (2)

Lukasz Szozda
Lukasz Szozda

Reputation: 175756

Using single UPDATE:

UPDATE games
SET stamp1 = CASE WHEN stamp1 < stamp2 THEN extract('epoch' from current_timestamp) 
                  ELSE stamp1 END
   ,stamp2 = CASE WHEN stamp2 < stamp1 THEN extract('epoch' from current_timestamp) 
                  ELSE stamp2 END
WHERE gid = in_gid AND (player1 = in_uid OR player2 = in_uid);

Upvotes: 1

Abhishek Ginani
Abhishek Ginani

Reputation: 4751

Add condition in query:

UPDATE games
SET stamp1 = CASE  WHEN stamp1 < stamp2 THEN extract('epoch' from current_timestamp) ELSE stamp1 END,
    stamp2 = CASE  WHEN stamp2 < stamp1 THEN extract('epoch' from current_timestamp) ELSE stamp2 END
WHERE gid = in_gid
AND (player1 = in_uid OR player2 = in_uid); 

Upvotes: 1

Related Questions