Skip to content

Instantly share code, notes, and snippets.

@danielleevandenbosch
Last active November 14, 2019 19:09
Show Gist options
  • Save danielleevandenbosch/fd715175bc03681ab084c090c8e5d0e9 to your computer and use it in GitHub Desktop.
Save danielleevandenbosch/fd715175bc03681ab084c090c8e5d0e9 to your computer and use it in GitHub Desktop.
Point at and swap any value in an ltree. Kinda like the REPLACE() function.
CREATE OR REPLACE FUNCTION ltree_swap (_ltree ltree, _old_val LTREE, _new_val LTREE, _position INT) RETURNS LTREE LANGUAGE plpgsql AS
$$
/*
==================================================
Author: dvandenbosch
Created At: 11/14/2019
Use: SELECT '44.22.23'::TEXT::LTREE AS orginal, ltree_swap('44.22.23'::TEXT::LTREE,'23'::TEXT::LTREE,'fish'::TEXT::LTREE,2) AS swap
Note: _position parameter is zero based
==================================================
*/
DECLARE
--===========try catch vars===========
_returned_sqlstate TEXT;
_message_text TEXT;
_pg_exception_detail TEXT;
_pg_exception_hint TEXT;
_pg_exception_context TEXT;
--====================================
retval LTREE;
BEGIN
--try code goes here
IF nlevel(_ltree) = 0 THEN --empty ltree
retval = ''::ltree;
ELSIF nlevel(_ltree)<(_position + 1) THEN --Position out of scope for this particular ltree.
retval = _ltree; --return orginal value
ELSIF nlevel(_ltree) = 1 THEN --single value ltree
IF _position = 0 AND _ltree = _old_val AND nlevel(_ltree) = 1 THEN
retval = _new_val;
ELSE
retval = _ltree;
END IF;
ELSIF nlevel(_ltree)=(_position + 1) THEN --replace at the end
raise notice 'bravo';
SELECT COALESCE(foo.tree,_ltree) AS tree
FROM (
SELECT tree.tree
FROM (
SELECT subpath(_ltree,0,(_position)) || _new_val AS tree
) AS tree(tree)
WHERE 1=1
AND subpath(_ltree,_position,1) = _old_val
AND nlevel(_ltree) > _position
UNION ALL
SELECT NULL::LTREE
) AS foo
LIMIT 1 INTO retval
;
ELSIF (nlevel(_ltree)>(_position + 1)) THEN
SELECT COALESCE(foo.tree,_ltree) AS tree
FROM (
SELECT tree.tree
FROM (
SELECT subpath(_ltree,0,(_position)) || _new_val || subpath(_ltree,(_position+1)) AS tree
) AS tree(tree)
WHERE 1=1
AND subpath(_ltree,_position,1) = _old_val
AND nlevel(_ltree) > _position
UNION ALL
SELECT NULL::LTREE
) AS foo
LIMIT 1 INTO retval
;
ELSE
retval = 'senereo not determined'::TEXT::LTREE;
END IF;
RETURN retval;
EXCEPTION WHEN others THEN
GET STACKED DIAGNOSTICS
_returned_sqlstate = RETURNED_SQLSTATE
, _message_text = MESSAGE_TEXT
, _pg_exception_detail = PG_EXCEPTION_DETAIL
, _pg_exception_hint = PG_EXCEPTION_HINT
, _pg_exception_context = PG_EXCEPTION_CONTEXT;
PERFORM it.pg_func_exceptions_insert (
_returned_sqlstate
, _message_text
, _pg_exception_detail
, _pg_exception_hint
, _pg_exception_context
, current_query()
, FALSE --false -> email will be sent to DBA upon function failure
);
RAISE EXCEPTION E'Got exception:
state : %
message: %
detail : %
hint : %
context: %', _returned_sqlstate, _message_text, _pg_exception_detail, _pg_exception_hint, _pg_exception_context;
END;
$$;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment