-- -- Create The Tree Package -- -- @author ben@openforce -- @creation-date 2002-05-17 -- @version $Id: tree-create.sql,v 1.5 2002/09/16 21:47:01 jeffd Exp $ -- -- This does funky sortkey stuff in Oracle, -- similar to DonB's PG varbit stuff, but without varbits -- because Oracle has no varbits. -- -- This scheme is usable in PG, too, but probably not as -- efficient as Don's varbit scheme. So we use it only in Oracle -- create or replace package tree as function hex_to_int ( p_hex in raw ) return integer; function int_to_hex ( p_int in integer ) return raw; function increment_key ( tree_key in raw ) return raw; function next_key ( parent_key in raw, max_child_key in raw ) return raw; function left ( raw_key in raw ) return raw; function right ( raw_key in raw ) return raw; function ancestor_key ( raw_key in raw, tree_level in integer ) return raw; function tree_level ( raw_key in raw ) return integer; function ancestor_p ( ancestor_key in raw, child_key in raw ) return char; end tree; / show errors create or replace package body tree as function hex_to_int ( p_hex in raw ) return integer is v_int integer := 0; v_current_pow integer := 1; v_current_pos integer := length(p_hex); v_current_char integer; begin while v_current_pos > 0 loop v_current_char:= ascii(upper(substr(p_hex, v_current_pos, 1))); if (v_current_char between 48 and 57) then -- between 1 and 9 v_int:= v_int + (v_current_pow * (v_current_char - 48)); else -- between A and F v_int:= v_int + (v_current_pow * (v_current_char - 55)); end if; -- change things v_current_pow:= v_current_pow * 16; v_current_pos:= v_current_pos - 1; end loop; return v_int; end hex_to_int; function int_to_hex ( p_int in integer ) return raw is v_hex raw(9) := ''; v_current_pow integer := 4294967296; v_remainder integer := p_int; v_current_div integer; begin while v_current_pow >= 1 loop v_current_div:= floor(v_remainder/v_current_pow); -- we're not prepending 0's if v_current_div > 0 or length(v_hex) > 0 then -- 0-9 or A-F if v_current_div between 0 and 9 then v_hex:= v_hex || chr(48 + v_current_div); else v_hex:= v_hex || chr(55 + v_current_div); end if; end if; -- adjust for next round v_remainder:= mod(v_remainder, v_current_pow); v_current_pow:= v_current_pow / 16; end loop; return v_hex; end int_to_hex; function increment_key ( tree_key in raw ) return raw is begin if tree_key is null then return '000000'; else return (lpad(int_to_hex(hex_to_int(tree_key) + 1), 6, '0')); end if; end increment_key; function next_key ( parent_key in raw, max_child_key in raw ) return raw is begin return parent_key || increment_key(max_child_key); end next_key; function left ( raw_key in raw ) return raw is begin return raw_key || '000000'; end left; function right ( raw_key in raw ) return raw is begin return raw_key || 'ffffff'; end right; function ancestor_key ( raw_key in raw, tree_level in integer ) return raw is begin return substr(raw_key, 1, 6 * tree_level); end ancestor_key; function tree_level ( raw_key in raw ) return integer is begin return length(raw_key) / 6; end tree_level; function parent_key ( raw_key in raw ) return raw is begin return substr(raw_key, 1, 6 * tree_level(raw_key) - 6); end parent_key; function ancestor_p ( ancestor_key in raw, child_key in raw ) return char is begin if substr(child_key, 1, length(ancestor_key)) = ancestor_key then return 't'; else return 'f'; end if; end ancestor_p; end tree; / show errors