Forum OpenACS Q&A: Bookmarks Module

Collapse
Posted by David Kuczek on
Alex Sokoloff said something about porting the bookmarks module on
September 25th. Is it available somewhere yet?
Collapse
Posted by Don Baccus on
Yeah,  it's sitting in my mailbox (thanks, Alex!).  I'm going to test it and check it in "real soon now" - I'm in Boston at the moment, and pretty busy.  I may try to get to it this weekend, but no promises...
Collapse
Posted by Bob Fuller on
The tables and sequences in bookmarks.sql are OK, and can be loaded "as is". Here's a blow by blow of FUNCTIONS, etc., that I've successfully ported and tested:

CREATE function inc_char_for_sort_key (char)
  returns char(2)
AS '
DECLARE
   old_char char(2);
   carry_p  integer;
   old_code INTEGER;
   new_code INTEGER;
BEGIN
   old_char := $1;
   old_code := ascii(old_char);
   IF old_code = 57 THEN
      -- skip from 9 to A
      new_code := 65;
      carry_p := 0;
   ELSE IF old_code = 90 THEN
      -- skip from Z to a
      new_code := 97;
      carry_p := 0;
   ELSE IF old_code = 122 THEN
      -- wrap around
      new_code := 48;
      carry_p := 1;
   ELSE
      new_code := old_code + 1;
      carry_p := 0;
   END IF;
   END IF;
   END IF;
   --old_char := chr(new_code);
   old_char := ichar(new_code) || cast(carry_p as char(1));
   return old_char;
END;
--END inc_char_for_sort_key;
' language 'plpgsql';


CREATE FUNCTION new_sort_key (CHAR(3)) RETURNS CHAR(3)
AS '
DECLARE
   v_old_sort_key char(3);
   v_chr_1 char(2);
   v_chr_2 char(2);
   v_chr_3 char(2);
   v_carry INTEGER;
BEGIN
   v_old_sort_key := $1;
   IF v_old_sort_key IS null or v_old_sort_key = '''' THEN
      RETURN ''000'';
   END IF;

   v_chr_1 := substr(v_old_sort_key, 1, 1);
   v_chr_2 := substr(v_old_sort_key, 2, 1);
   v_chr_3 := substr(v_old_sort_key, 3, 1);

   v_chr_3 := inc_char_for_sort_key(v_chr_3);
   v_carry := cast(substr(v_chr_3, 2, 1) as integer);
   v_chr_3 := substr(v_chr_3, 1, 1);
   IF v_carry = 1 THEN
      v_chr_2 := inc_char_for_sort_key(v_chr_2);
      v_carry := cast(substr(v_chr_2, 2, 1) as integer);
      v_chr_2 := substr(v_chr_2, 1, 1);
      IF v_carry = 1 THEN
         v_chr_1 := inc_char_for_sort_key(v_chr_1);
         v_carry := cast(substr(v_chr_1, 2, 1) as integer);
         v_chr_1 := substr(v_chr_1, 1, 1);
      END IF;
   END IF;

   RETURN trim(v_chr_1) || trim(v_chr_2) || trim(v_chr_3);
END;
--END new_sort_key;
' language 'plpgsql';
 

create function trig_bm_list_sort_key_i_tr() returns opaque
as '
DECLARE
  v_last_sort_key bm_list.local_sort_key%TYPE;
  v_parent_sort_key bm_list.parent_sort_key%TYPE;
BEGIN
   IF NEW.parent_id IS NULL THEN
      SELECT max(local_sort_key) INTO v_last_sort_key
        FROM bm_list
        WHERE parent_id IS NULL;
      v_parent_sort_key := null;
   ELSE
      SELECT max(local_sort_key) INTO v_last_sort_key
        FROM bm_list
        WHERE parent_id = NEW.parent_id;
      SELECT parent_sort_key || local_sort_key INTO v_parent_sort_key
        FROM bm_list WHERE bookmark_id = NEW.parent_id;
   END IF;

   NEW.local_sort_key := new_sort_key(v_last_sort_key);
   NEW.parent_sort_key := v_parent_sort_key;
    RETURN NEW;
END;
' language 'plpgsql';
 
CREATE trigger bm_list_sort_key_i_tr
before INSERT ON bm_list
FOR each row
execute procedure trig_bm_list_sort_key_i_tr();

I've also started on the rest of the (SQL) code, but last night ran into a problem because of the lack of cursors in pgplsql. Interestingly enough, I actually found a cursor in one of the other modules, but I'll bet you it doesn't work...

Moving forward in the SQL part of the module, I think bm_list_pkg has to be done as a table, and I've figured out how that should interface with the update functions and triggers that are used to update parent_row_key and local_row_key when the parent_id of a bookmark is changed. However, without cursors available, the implementation of the remaining items is a bit of a challenge, since the existing Oracle stuff is recursive.

I also did a preliminary check on the Tcl side of the equation, and there are definitely at least a few OUTER JOIN / UNION type things that need to be fixed.

I'll send a further update once I get past the hurdle of not having cursors...

-- Bob

Collapse
Posted by Mike Slack on
PostgeSQL has cursors.  See the FETCH and DECLARE CURSOR FOR commands in the PG documentation.