Since the function body is procedural, use the plpgsql
language as opposed to SQL:
CREATE FUNCTION messages_add(bigint, bigint, text) RETURNS void AS $$
BEGIN
INSERT INTO chats
SELECT pair($1, $2), $1, $2
WHERE NOT EXISTS (SELECT 1 FROM chats WHERE id = pair($1, $2));
INSERT INTO messages VALUES (pair($1, $2), $1, $3);
END
$$ LANGUAGE plpgsql;
Also, if the result to reuse is pair($1,$2)
you may store it into a variable:
CREATE FUNCTION messages_add(bigint, bigint, text) RETURNS void AS $$
DECLARE
pair bigint := pair($1, $2);
BEGIN
INSERT INTO chats
SELECT pair, $1, $2
WHERE NOT EXISTS (SELECT 1 FROM chats WHERE id = pair);
INSERT INTO messages VALUES (pair, $1, $3);
END
$$ LANGUAGE plpgsql;