CREATE OR REPLACE FUNCTION sputnik.guessinit(t TIMESTAMP WITH TIME ZONE, sequence BIGINT, slope DOUBLE PRECISION) RETURNS VOID VOLATILE RETURNS NULL ON NULL INPUT SECURITY DEFINER LANGUAGE 'plpythonu' AS $$ GD["time"] = t GD["sequence"] = sequence GD["slope"] = slope $$; CREATE OR REPLACE FUNCTION sputnik.guessbest(state BIGINT, t TIMESTAMP WITH TIME ZONE, sequence BIGINT) RETURNS BIGINT VOLATILE CALLED ON NULL INPUT SECURITY DEFINER LANGUAGE 'plpythonu' AS $$ if (not GD.has_key("time")) or (not GD.has_key("sequence")) or (not GD.has_key("slope")): return None if (t is None) or (sequence is None): return None plan = plpy.prepare(""" SELECT (extract('epoch' FROM ($1::TIMESTAMP WITH TIME ZONE-$2::TIMESTAMP WITH TIME ZONE)))::float/($3::BIGINT-$4::BIGINT)::float AS slope """, ["timestamptz", "timestamptz", "int8", "int8"]) result = sequence if state is not None: r0 = plpy.execute(plan, [t, GD["time"], sequence, GD["sequence"]], 1) r1 = plpy.execute(plan, [t, GD["time"], state, GD["sequence"]], 1) if abs(r0[0]["slope"]-GD["slope"]) >= abs(r1[0]["slope"]-GD["slope"]): result = sequence else: result = state return result $$; CREATE AGGREGATE sputnik.guesser (TIMESTAMP WITH TIME ZONE, BIGINT) ( SFUNC = sputnik.guessbest, STYPE = BIGINT );