X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fpostrr.sql.in;h=eb197452a5ca6e1e4a771398854efc0d0d625975;hb=204a47a5eef2694c4e8105ad68e667446bbf36a0;hp=546a9dffa1b5003bf723fe6d1bac71012dca4887;hpb=355393a5307e37b13fc70ef84d651761d236c398;p=postrr.git diff --git a/src/postrr.sql.in b/src/postrr.sql.in index 546a9df..eb19745 100644 --- a/src/postrr.sql.in +++ b/src/postrr.sql.in @@ -108,15 +108,29 @@ CREATE CAST (rrtimeslice AS rrtimeslice) WITH FUNCTION RRTimeslice(rrtimeslice, integer, boolean) AS IMPLICIT; -CREATE OR REPLACE FUNCTION Tstamp(rrtimeslice) - RETURNS timestamp - AS 'postrr-@POSTRR_MAJOR_VERSION@.@POSTRR_MINOR_VERSION@', 'rrtimeslice_to_timestamp' +CREATE OR REPLACE FUNCTION RRTimeslice(timestamptz, integer, boolean) + RETURNS rrtimeslice + AS 'postrr-@POSTRR_MAJOR_VERSION@.@POSTRR_MINOR_VERSION@', 'timestamptz_to_rrtimeslice' + LANGUAGE 'C' IMMUTABLE STRICT; + +CREATE CAST (timestamptz AS rrtimeslice) + WITH FUNCTION RRTimeslice(timestamptz, integer, boolean) + AS IMPLICIT; + +CREATE OR REPLACE FUNCTION Tstamptz(rrtimeslice) + RETURNS timestamptz + AS 'postrr-@POSTRR_MAJOR_VERSION@.@POSTRR_MINOR_VERSION@', 'rrtimeslice_to_timestamptz' LANGUAGE 'C' IMMUTABLE STRICT; -CREATE CAST (rrtimeslice AS timestamp) - WITH FUNCTION Tstamp(rrtimeslice); +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' @@ -302,6 +316,94 @@ CREATE OR REPLACE FUNCTION CData_update(cdata, cdata) AS 'postrr-@POSTRR_MAJOR_VERSION@.@POSTRR_MINOR_VERSION@', 'cdata_update' LANGUAGE 'C' IMMUTABLE; +CREATE OR REPLACE FUNCTION PostRR_update(name, name, name, timestamptz, double precision) + RETURNS cdata + LANGUAGE plpgsql + AS $$ +DECLARE + tbl ALIAS FOR $1; + tscol ALIAS FOR $2; + vcol ALIAS FOR $3; + ts ALIAS FOR $4; + value ALIAS FOR $5; + ts_str text; + v_str text; + update_qry text; + status integer; + newts rrtimeslice; + new cdata; +BEGIN + tscol := quote_ident(tscol); + vcol := quote_ident(vcol); + ts_str := quote_literal(ts); + v_str := quote_literal(value); + + update_qry = 'CData_update(' || vcol || ', ' || v_str || ')'; + + -- 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; + RETURN new; +END; +$$; + +CREATE OR REPLACE FUNCTION PostRR_update(text, timestamptz, double precision) + RETURNS SETOF cdata + LANGUAGE plpgsql + AS $$ +DECLARE + -- $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 + SELECT PostRR_update(adef.tbl, adef.tscol, adef.vcol, $2, $3) + INTO new; + RETURN NEXT new; + END LOOP; + RETURN; +END; +$$; + COMMIT; SET client_min_messages TO DEFAULT;