Last active
November 14, 2019 19:09
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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