--
-- Rozdzia 2.: Poznawanie bazy danych
--
-- Kod mona wykona za pomoc polecenia:
-- 		psql -f r02.txt
--

CREATE OR REPLACE FUNCTION estimated_row_count(text) 
RETURNS bigint 
LANGUAGE sql 
AS $$

SELECT (CASE WHEN reltuples > 0 THEN 
					pg_relation_size($1)/(8192*relpages/reltuples) 
				ELSE 0 
				END)::bigint 
FROM pg_class 
WHERE oid = $1::regclass;

$$;

CREATE OR REPLACE FUNCTION
   pg_relation_size_nolock(tablename regclass)
RETURNS BIGINT
LANGUAGE plpgsql
AS $$
DECLARE
   classoutput   RECORD;
   tsid          INTEGER;
   rid           INTEGER;
   dbid          INTEGER;
   filepath      TEXT;
   filename      TEXT;
   datadir       TEXT;
   i             INTEGER := 0;
   tablesize     BIGINT;
BEGIN
   --
   -- uzyskuje katalog danych
   --
   EXECUTE 'SHOW data_directory' INTO datadir;
   --
   -- uzyskuje wartoci relfilenode i reltablespace
   --
   SELECT
   reltablespace as tsid
   ,relfilenode as rid
         INTO classoutput
   FROM pg_class
   WHERE oid = tablename
   AND relkind = 'r';
   -
   - generuje bd, jeli nie mona znale nazwy tabeli
   --
   IF NOT FOUND THEN
         RAISE EXCEPTION 'tablename % not found', tablename;
   END IF;
   tsid := classoutput.tsid;
   rid := classoutput.rid;
   --
   -- uzyskuje identyfikator obiektu bazy danych (oid)
   --
   SELECT oid INTO dbid
   FROM pg_database
   WHERE datname = current_database();
   --
   -- wykorzystuje wiedz o mechanizmach wewntrznych do skonstruowania cieki do pliku
   -
   IF tsid = 0 THEN
         filepath := datadir || '/base/' || dbid || '/' || rid;
   ELSE
         filepath := datadir || '/pg_tblspc/'
                             || tsid || '/'
                             || dbid || '/'
                             || rid;
   END IF;
   --
   -- szuka pierwszego pliku i generuje stosowny raport w razie jego braku
   --
   SELECT (pg_stat_file(filepath)).size
   INTO tablesize;
   --
   -- sumuje rozmiary ewentualnych dodatkowych plikw
   --
   WHILE FOUND LOOP
         i := i + 1;
         filename := filepath || '.' || i;
         --
         -- funkcja pg_stat_file zwraca ERROR, jeli nie moe znale pliku,
         -- zatem musimy przechwyci ten bd i przerwa wykonywanie ptli
         --
         BEGIN
               SELECT tablesize + (pg_stat_file(filename)).size
               INTO tablesize;
         EXCEPTION
               WHEN OTHERS THEN
                     EXIT;
         END;
   END LOOP;
   RETURN tablesize;
END;
$$;

