-- STEP 3: Create Procedures
-- sudo -u postgres psql pingtraceroutedb <procedures.sql
--
-- =================================================================
--          #     #                 #     #
--          ##    #   ####   #####  ##    #  ######   #####
--          # #   #  #    #  #    # # #   #  #          #
--          #  #  #  #    #  #    # #  #  #  #####      #
--          #   # #  #    #  #####  #   # #  #          #
--          #    ##  #    #  #   #  #    ##  #          #
--          #     #   ####   #    # #     #  ######     #
--
--       ---   The NorNet Testbed for Multi-Homed Systems  ---
--                       https://www.nntb.no
-- =================================================================
--
-- High-Performance Connectivity Tracer (HiPerConTracer)
-- Copyright (C) 2015-2022 by Thomas Dreibholz
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program.  If not, see <http://www.gnu.org/licenses/>.
--
-- Contact: dreibh@simula.no


-- ###### Median calculation ################################################
-- From: https://wiki.postgresql.org/wiki/Aggregate_Median
DROP FUNCTION IF EXISTS _final_median(NUMERIC[]) CASCADE;
CREATE FUNCTION _final_median(NUMERIC[])
   RETURNS NUMERIC AS
$$
   SELECT AVG(val)
   FROM (
     SELECT val
     FROM unnest($1) val
     ORDER BY 1
     LIMIT  2 - MOD(array_upper($1, 1), 2)
     OFFSET CEIL(array_upper($1, 1) / 2.0) - 1
   ) sub;
$$
LANGUAGE 'sql' IMMUTABLE;

DROP AGGREGATE IF EXISTS median(NUMERIC);
CREATE AGGREGATE median(NUMERIC) (
  SFUNC=array_append,
  STYPE=NUMERIC[],
  FINALFUNC=_final_median,
  INITCOND='{}'
);


-- ###### Round timestamp down into given n-minute bucket ###################
DROP FUNCTION IF EXISTS dateToBucket(TIMESTAMP WITHOUT TIME ZONE, INTEGER) CASCADE;
CREATE FUNCTION dateToBucket(TIMESTAMP WITHOUT TIME ZONE, INTEGER)
   RETURNS TIMESTAMP WITHOUT TIME ZONE AS
$$
   SELECT date_trunc('hour', $1) + ((date_part('minute', $1)::integer / $2) * $2) * interval '1 min';
$$
LANGUAGE 'sql' IMMUTABLE;
