X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fpostrr.sql.in;h=9f34f22100cfd04151da1afb56ca23ec2c3538d8;hb=3d39f72435c8664ea9ffce084b1cc8297b6070fd;hp=10aeb777815720620e55c6a71f75ece9504ddadc;hpb=9f6643ebba9ef1a48b4a9e7c90142cfeb3723ddc;p=postrr.git diff --git a/src/postrr.sql.in b/src/postrr.sql.in index 10aeb77..9f34f22 100644 --- a/src/postrr.sql.in +++ b/src/postrr.sql.in @@ -117,6 +117,11 @@ CREATE CAST (rrtimeslice AS timestamptz) WITH FUNCTION Tstamptz(rrtimeslice); -- EXPLICIT +CREATE OR REPLACE FUNCTION rrtimeslice_cmp(rrtimeslice, rrtimeslice) + RETURNS integer + AS 'postrr-@POSTRR_MAJOR_VERSION@.@POSTRR_MINOR_VERSION@', 'rrtimeslice_cmp' + LANGUAGE 'C' IMMUTABLE STRICT; + CREATE OR REPLACE FUNCTION rrtimeslice_seq_eq(rrtimeslice, rrtimeslice) RETURNS boolean AS 'postrr-@POSTRR_MAJOR_VERSION@.@POSTRR_MINOR_VERSION@', 'rrtimeslice_seq_eq' @@ -315,6 +320,7 @@ DECLARE ts_str text; v_str text; update_qry text; + status integer; newts rrtimeslice; new cdata; BEGIN @@ -325,13 +331,13 @@ BEGIN update_qry = 'CData_update(' || vcol || ', ' || v_str || ')'; + -- XXX: handle race conditions + BEGIN - EXECUTE 'UPDATE ' || tbl - || ' SET ' || tscol || ' = ' || ts_str - || ', ' || vcol || ' = ' || update_qry + EXECUTE 'SELECT rrtimeslice_cmp(' || tscol || ', ' || ts_str + || ') AS status FROM ' || tbl || ' WHERE ' || tscol || ' = ' || ts_str - || ' RETURNING ' || tscol || ', ' || vcol - INTO STRICT newts, new; + INTO STRICT status; EXCEPTION WHEN NO_DATA_FOUND THEN @@ -341,9 +347,29 @@ BEGIN || ') 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; RETURN new; END; $$; @@ -353,20 +379,15 @@ CREATE OR REPLACE FUNCTION PostRR_update(text, timestamptz, double precision) LANGUAGE plpgsql AS $$ DECLARE - rraname ALIAS FOR $1; - ts ALIAS FOR $2; - value ALIAS FOR $3; + -- $1: rraname + -- $2: timestamp + -- $3: value adef RECORD; new cdata; BEGIN FOR adef IN SELECT tbl, tscol, vcol FROM postrr.rrarchives WHERE postrr.rrarchives.rraname = $1 LOOP - EXECUTE 'SELECT PostRR_update(' - || quote_literal(adef.tbl) || ', ' - || quote_literal(adef.tscol) || ', ' - || quote_literal(adef.vcol) || ', ' - || quote_literal(ts) || ', ' - || quote_literal(value) || ')' + SELECT PostRR_update(adef.tbl, adef.tscol, adef.vcol, $2, $3) INTO new; RETURN NEXT new; END LOOP;