This can be solved with pure SQL in modern Postgres using WITH RECURSIVE
.
For PostgreSQL 8.3, this plpgsql function does the job while it is also a decent solution for modern PostgreSQL. You want to ..
get the original value and the modified value for a field
The demo picks first_name
as filed:
CREATE OR REPLACE FUNCTION f_get_org_val(integer
, OUT first_name_curr text
, OUT first_name_org text) AS
$func$
DECLARE
_parent_id int;
BEGIN
SELECT INTO first_name_curr, first_name_org, _parent_id
first_name, first_name, audit_parent_id
FROM tbl
WHERE id = $1;
WHILE _parent_id <> 0
LOOP
SELECT INTO first_name_org, _parent_id
first_name, audit_parent_id
FROM tbl
WHERE id = _parent_id;
END LOOP;
END
$func$ LANGUAGE plpgsql;
COMMENT ON FUNCTION f_get_org_val(int) IS 'Get current and original values for id.
$1 .. id';
Call:
SELECT * FROM f_get_org_val(123);
This assumes that all trees have a root node with parent_id = 0
. No circular references, or you will end up with an endless loop. You might want to add a counter and exit the loop after x iterations.