I have PL/PgSQL
function that performs quite similar queries (the only thing that they have different is column names) and converts the output into JSON object.
CREATE OR REPLACE FUNCTION get_observations(kind varchar, site_id integer, var varchar) RETURNS TABLE (fc json) AS
$func$
BEGIN
IF kind = 'raw' THEN
IF var = 'o2_abs' THEN
RETURN QUERY SELECT array_to_json(array_agg(row_to_json(obs))) FROM (
SELECT observation_date AS date, o2_abs AS value FROM oxygen WHERE new_id = site_id) AS obs;
ELSIF var = 'o2_rel' THEN
RETURN QUERY SELECT array_to_json(array_agg(row_to_json(obs))) FROM (
SELECT observation_date AS date, o2_rel AS value FROM oxygen WHERE new_id = site_id) AS obs;
ELSIF var = 'temp' THEN
RETURN QUERY SELECT array_to_json(array_agg(row_to_json(obs))) FROM (
SELECT observation_date AS date, t AS value FROM oxygen WHERE new_id = site_id) AS obs;
END IF;
ELSIF kind = 'averaged' THEN
IF var = 'o2_abs' THEN
RETURN QUERY SELECT array_to_json(array_agg(row_to_json(obs))) FROM (
SELECT month AS month, o2_abs AS value FROM oxygen_month_average WHERE new_id = site_id) AS obs;
ELSIF var = 'o2_rel' THEN
RETURN QUERY SELECT array_to_json(array_agg(row_to_json(obs))) FROM (
SELECT month AS month, o2_rel AS value FROM oxygen_month_average WHERE new_id = site_id) AS obs;
ELSIF var = 'temp' THEN
RETURN QUERY SELECT array_to_json(array_agg(row_to_json(obs))) FROM (
SELECT month AS month, t AS value FROM oxygen_month_average WHERE new_id = site_id) AS obs;
END IF;
END IF;
END;
$func$ LANGUAGE plpgsql;
The body of function contains a lots of repeated code. I see several methods to improve it, but don't know if PL/PgSQL
allows these tricks:
- Store
obs
query result in the intermediate variable and convert it into JSON witharray_to_json(array_agg(row_to_json(obs)))
in the end of function. - Cast
var varchar
into column name definition in query in order to avoid the most ofIF
/ELSE
statements;
PostgreSQL server version is 9.3.6.
Table schemas:
oxygen=# \d+ oxygen
Table "public.oxygen"
Column | Type | Modifiers (...)
-------------------------+---------+----------------------------------------------------
old_id | text | not null
observation_date_string | text | not null
t | real | not null
o2_abs | real | not null
o2_sat | real |
o2_rel | real |
observation_date | date |
new_id | integer |
id | bigint | not null default nextval('oxygen_id_seq'::regclass)
Indexes:
"oxygen_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
"oxygen_new_id_fkey" FOREIGN KEY (new_id) REFERENCES unique_geoms(new_id)
"oxygen_old_id_fkey" FOREIGN KEY (old_id) REFERENCES location(old_id)
oxygen=# \d+ oxygen_month_average
Table "public.oxygen_month_average"
Column | Type | Modifiers (...)
--------+------------------+-------------------------------------------------------------------
new_id | integer |
month | integer |
t | double precision |
o2_abs | double precision |
o2_rel | double precision |
id | bigint | not null default nextval('oxygen_month_average_id_seq'::regclass)
Indexes:
"oxygen_month_average_pkey" PRIMARY KEY, btree (id)