BEGIN;

DROP FUNCTION IF EXISTS memory_used(OUT TIMESTAMP WITH TIME ZONE,
                                    OUT NUMERIC,
                                    OUT NUMERIC,
                                    OUT NUMERIC);
                         
CREATE FUNCTION memory_used(OUT measurement_time TIMESTAMP WITH TIME ZONE,
                            OUT free_pct NUMERIC,
                            OUT used_pct NUMERIC,
                            OUT cach_pct NUMERIC) RETURNS SETOF RECORD AS
$memory_used$
BEGIN

    RETURN QUERY
        SELECT mem.measurement_time,
               100*(mem.kbmemfree / total_mem) AS free_pct,
               100*(mem.kbmemused / total_mem) AS used_pct,
               100*(mem.kbcached / total_mem) AS cach_pct
            FROM (
                SELECT memory.measurement_time,
                       memory.kbmemfree,
                       memory.kbmemused - (memory.kbcached + COALESCE(memory.kbbuffers, 0)) AS kbmemused,
                       memory.kbcached + COALESCE(memory.kbbuffers, 0) AS kbcached,
                       memory.kbmemfree + memory.kbmemused AS total_mem
                FROM memory
                ) AS mem
            ORDER BY measurement_time;

END;
$memory_used$
    LANGUAGE 'plpgsql';

DROP FUNCTION IF EXISTS swap_used(OUT TIMESTAMP WITH TIME ZONE,
                                  OUT NUMERIC,
                                  OUT NUMERIC);
                         
CREATE FUNCTION swap_used(OUT measurement_time TIMESTAMP WITH TIME ZONE,
                          OUT kbswpfree NUMERIC,
                          OUT kbswpused NUMERIC) RETURNS SETOF RECORD AS
$swap_used$
BEGIN

    RETURN QUERY
        SELECT memory.measurement_time, memory.kbswpfree, memory.kbswpused
            FROM memory
            ORDER BY measurement_time;

END;
$swap_used$
    LANGUAGE 'plpgsql';

COMMIT;