diff --git a/src/postrr.sql.in b/src/postrr.sql.in
index eb197452a5ca6e1e4a771398854efc0d0d625975..a3bff336ae94ef5288b4ab927a7a3c4704359d83 100644 (file)
--- a/src/postrr.sql.in
+++ b/src/postrr.sql.in
-- XXX: handle race conditions
- BEGIN
- EXECUTE 'SELECT rrtimeslice_cmp(' || tscol || ', ' || ts_str
- || ') AS status FROM ' || tbl
- || ' WHERE ' || tscol || ' = ' || ts_str
- INTO STRICT status;
-
- EXCEPTION
- WHEN NO_DATA_FOUND THEN
- EXECUTE 'INSERT INTO ' || tbl
- || ' (' || tscol || ', ' || vcol
- || ') VALUES (' || ts_str || ', ' || v_str
- || ') RETURNING ' || tscol || ', ' || vcol
- INTO newts, new;
- -- use strict again; on exception retry?
- RETURN new;
- WHEN TOO_MANY_ROWS THEN
- RAISE EXCEPTION '% is not unique in %.%', ts_str, tbl, tscol;
- END;
-
- IF status = 0 THEN
- -- timestamps match
- EXECUTE 'UPDATE ' || tbl
- || ' SET ' || vcol || ' = ' || update_qry
- || ' WHERE ' || tscol || ' = ' || ts_str
- || ' RETURNING ' || tscol || ', ' || vcol
- INTO STRICT newts, new;
- ELSIF status < 0 THEN
- -- given timestamp is newer than in the database
- EXECUTE 'UPDATE ' || tbl
- || ' SET ' || tscol || ' = ' || ts_str
- || ', ' || vcol || ' = ' || v_str
- || ' WHERE ' || tscol || ' = ' || ts_str
- || ' RETURNING ' || tscol || ', ' || vcol
- INTO STRICT newts, new;
- ELSE
- RAISE EXCEPTION '% is too old in %.%', ts_str, tbl, tscol;
- END IF;
+ LOOP
+ BEGIN
+ -- removing matching (by sequence no) old entries
+ EXECUTE 'DELETE FROM ' || tbl
+ || ' WHERE rrtimeslice_cmp(' || tscol || ', ' || ts_str
+ || ') = -1; '
+ || 'SELECT rrtimeslice_cmp(' || tscol || ', ' || ts_str
+ || ') AS status FROM ' || tbl
+ || ' WHERE ' || tscol || ' = ' || ts_str
+ INTO STRICT status;
+
+ EXCEPTION
+ WHEN NO_DATA_FOUND THEN
+ EXECUTE 'INSERT INTO ' || tbl
+ || ' (' || tscol || ', ' || vcol
+ || ') VALUES (' || ts_str || ', ' || v_str
+ || ') RETURNING ' || tscol || ', ' || vcol
+ INTO newts, new;
+ -- use strict again; on exception retry?
+ RETURN new;
+ WHEN TOO_MANY_ROWS THEN
+ RAISE EXCEPTION '% is not unique in %.%',
+ ts_str, tbl, tscol;
+ END;
+
+ IF status = 0 THEN
+ -- timestamps match
+ EXECUTE 'UPDATE ' || tbl
+ || ' SET ' || vcol || ' = ' || update_qry
+ || ' WHERE ' || tscol || ' = ' || ts_str
+ || ' RETURNING ' || tscol || ', ' || vcol
+ INTO STRICT newts, new;
+ ELSIF status < 0 THEN
+ -- someone else inserted older data in the meantime
+ -- => try again
+ CONTINUE;
+ ELSE
+ RAISE EXCEPTION '% is too old in %.%', ts_str, tbl, tscol;
+ END IF;
+ EXIT;
+ END LOOP;
RETURN new;
END;
$$;