I have a table, voucher_redemption
, that has the following columns:
id
, user_id
, voucher_id
, inseted_at
, updated_at
I’m trying to create a constraint that prevents the same user redeeming a voucher more than once in 24 hours. Or in other words, I want postgres to reject the record if there is another with a matching user_id created within 24 hours.
This doesn’t seem to be possible using constraints, after asking on Stack Overflow I was pointed towards creating a custom function and calling that by a trigger, which is what I’m attempting below:
Ecto.Adapters.SQL.query!(
Kraken.Repo, "
CREATE FUNCTION check_one_redemption_per_user_per_day(integer, date)
RETURNS BOOLEAN
LANGUAGE plpgsql VOLATILE
AS $$
declare clashing_record boolean;
BEGIN
SELECT EXISTS into clashing_record(
SELECT user_id FROM voucher_redemption
WHERE user_id = $1
AND inserted_at >= ($2 + INTERVAL '1 day')
);
END;
$$
"
)
Ecto.Adapters.SQL.query!(
Kraken.Repo, "
CREATE TRIGGER one_redemption_per_user_per_day
AFTER INSERT ON voucher_redemption
FOR EACH ROW
EXECUTE FUNCTION check_one_redemption_per_user_per_day(user_id, inserted_at)
"
)
These are stored in sequential migrations, however when I execute them, the first succeeds, and the second fails with (Postgrex.Error) ERROR 42883 (undefined_function) function check_one_redemption_per_user_per_day() does not exist
I guess the first obvious question is, is this approach the right one? These transactions happen rarely so performance isn’t hugely important. And if this approach isn’t the correct one, is there a way to do this using Ecto?
Thanks in advance