Forum OpenACS Development: FIX ME PLSQL problem

Collapse
Posted by Jack Purswani on
Hi everyone

Just wondering what the accepted method is for the 'declare' section
of a query to be modified in the *-postgresql.xql file.

The probelm I am dealing with is as follows:



  declare

      cursor v_cursor is

      select member_id

      from group_member_map

      where group_id = :group_id;

  begin ...

I appreciate any help.
Jack

Collapse
Posted by Dan Wickstrom on
It depends on how the cursor is used.  If the cursor is used to loop through a bunch of rows, then you can change the cursor to a for loop.  If it is just used to get a single value, then you can simply change it to a  select into statement.
Collapse
Posted by Don Baccus on
Just in case the above isn't absolutely clear, you don't need the cursors at all in PL/pgSQL but can execute the queries directly in the manner described by Dan.
Collapse
Posted by Jack Purswani on
Hi

Thanks for the help. I am still a little unsure as to how to proceed. The cursor is begin used to loop through a bunch of rows as far as I can see.

But how do I change the cursor to a loop? Do I just put a loop outside of the section where the cursor is used using the same format as in the Oracle version?

Here is more of the section of code (I think I put too litle info in my previous mail):

  declare

            cursor v_cursor is

            select member_id

            from group_member_map

            where group_id = :group_id;

    begin

          if :role = 'read' then

              for c in v_cursor loop

                  acs_permission__grant_permission(:pres_item_id,
  c.member_id,  'wp_view_presentation');

              end loop;

So would I say... put a 'for' loop outside the 'for' loop already there?

Thanks for the help.
Jack

Collapse
Posted by Don Baccus on
Check the routine bboard_message__remove_thread in packages/bboard/sql/postgresql/bboard-packages.sql for an example.

You just remove the cursor entirely.  Get rid of it.  Shoot it dead.  Bury it six feet under.

for foo in select something blah blah blah ...

Actually there's a stylistic problem in that example, as the child val
is declared as a RECORD, while it could easily be declared as acs_object%ROWTYPE.  I think the latter form is more efficient as the compiler can compute the attribute (column) offset at compile time while in the record case I believe it has to look up the offsets at runtime (since the RECORD can be assigned a row from any table).

So for looping through a table "foo" you might declare a variable:

one_foo foo%ROWTYPE;

then loop through like this:

for one_foo in select * from foo

loop

  (do something with one_foo.column etc etc)

end;

I see why Luke used "record" above - he only grabs a couple of columns
from each row, rather than the whole row, so that's cool.  Cuts down the number of bytes that need to be extracted and passed out, which may balance the dynamic lookup of the columns within the loop.