Forum OpenACS Q&A: Rudimentary development method questions

I'm working on part two of my Instant Gratification instructions, Building a Package. It's based on the OpenACS Developer's Guide in the standard documentation, but I've:
  • stripped out all example code from previous versions
  • removed almost all theory and reference material
  • re-organized it so that users paste in all the code - ie, build it all themselves, instead of installing and then inspecting a pre-built package.
  • Trying to approach it as a raw beginner. If a newbie does the tutorial, they should next be able to build (and debug?) their own package
  • updated some of the code to match emerging standards (so far, removed sql from .tcl, working on properly named end statements and show errors for sql)
To that end, I have a few questions for the developer community:
  1. How do you execute stored procedures in psql directly in order to debug them? Right now, the pg/plsql is very unpleasant to work on because I can't really see what I'm doing, where my commands go (ie, when I call a function, exactly what table is changed on how, so I can look and see if it was changed the way I intended), how to back up to a clean state, and how to find the bind variables so that I can test functions directly instead of through pages)
  2. Do people use psql at the command line or in emacs, or do you use something else, like a gui tool or working through web pages, to debug sql queries? How about table create scripts?
  3. The notes package makes notes acs_objects. This, I understand, has the advantage of enabling an API for security. Are there other advantages? Is this necessary for full text search?
  4. The fields in the notes object/table are made into acs_attributes. What is the benefit to doing this?
  5. Why are the commands in notes-create.sql wrapped in "inline" functions?
  6. Debugging web pages by tailing the Aolserver error log means looking through several hundred lines of code per error to find two or three lines that you need. Is there any way to improve this ratio?
  7. Getting my .xql files recognized and used seems to require some combination of restarting the server and having APM scan, load, and reload my xql, and possibly also some waiting. Could someone clarify how this works?
  8. Where is the documentation for the openacs-fts driver api, the one that notes-sc-create.sql calls?
  9. What is the benefit to making new objects content instead of just acs_objects? Are we supposed to be using the content management system?
  10. Are the comments in my document accurate, misleading, or just plain wrong? What else should a newbie know?
Thanks! All your feedback will be incorporated into the tutorial.
Collapse
Posted by Dave Bauer on
1) To execute a pl/pgsql stored procedure in psql just do select functioname(params);

2) I use M-x sql-postgres mode or M-x sql-oracle. sql-oracle mode is nice because you can use C-up/down arrow to scroll back through your previous commands.

3) Yes, to use the search package and service contracts, you must have acs_objects.

4) You can either use generic storage (acs_attributes) or type specific storage, which means creating a table with the object_id as the foreign key.

5) That is how they are executed when the sql script is loaded. It is only necessary for postgresql.

6) I use less error.log. Use F to mimic tail -f. Use C-c to stop and F to start it up again. G goes to the end. ? searches  backward / searches forward. I usually hit G after I get an error in the browser and then ?error to search for the error message and scroll back until I see the query that caused it.

7) Reloading the package should read in the xql files if they are registered in the .info file for the package.

8) in packages/search/www/doc/ or browse to yourserver/search/doc/ (or https://openacs.org/search/doc/)

9) pass
10) I am not done reading it yet.

Collapse
Posted by Bart Teeuwisse on
Joel,

here's my initial response. From the top of my head I can answer a few of your questions.

- I personally use the 'sql-postgres mode in emacs to execute pg/plsql. Combined with an auto-revert on the error log I can quickly re-execute (parts) of database queries that failed and test new queries as well.

- For the OpenFTS search to work the item to be searched has to be an acs-object.

- You'll find the openacs-driver-api in the doc section of your OpenACS instance.

- Inline functions are used for temporary pg/plsql procedures. They most often are used in installation script to create new objects or to initialize or upgrade a package.

- Advantages of the content repository include version management and automatic inclusing the OpenFTS search.

Hope this helps,

/Bart

Collapse
Posted by xx xx on
Great. I hope it will find a place on this website's project-section.

I'm no expert, but this is my view.

3/4. Defining acs_Objects and/or acs_Attributes is arbitrary. You just do it if you think there is a need to be able to identify your "code" uniquely. Granting permissions (to read/write/edit/admin the result of your code), is just one (important) example. For me this thread was important.

5. The use of 'Inline_..' is a naming convention in OpenACS to indicate a temporary plpgSQL function. The name has no other specific meaning in postgresql. The temporary function, called Inline_.. is Created, Selected (executed) and Dropped. I concluded that these temporary functions are used to execute SQL and plpgSQL statements in one block.

A normal temporary plpsql function (case insensitive) looks like this:

CREATE FUNCTION #name of function for example Inline_0# () RETURNS #return value for example INTEGER# AS '
  DECLARE
    declarations of variables used between Begin/End;
    [...]
  BEGIN
    SQL and plpgSQL statements;
    [...]
  END;
' LANGUAGE 'plpgsql';

SELECT Inline_0();
DROP FUNCTION Inline_0; 
Perform is used instead of Select to execute a plpqSQL function when a return value of the function is not needed.
Opaque is a special return value for Trigger-functions
The advantage of plpqSQL functions is that you can use conditional statements and variables within the function.

Collapse
Posted by Joel Aufrecht on
Thanks for the great answers. I have followup questions :)
  • When I try to call functions in psql, it demans all of the variables, exactly typed. How do I call a function directly in psql without specifying all of the parameters?
  • The notes create script defines a function:
    create function note__new (integer,integer,varchar,varchar,varchar,timestamp,integer,varchar,integer)
    returns integer as '
    declare
      p_note_id					alias for $1;       -- default null
      p_owner_id				alias for $2;       -- default null
      p_title					alias for $3;
      p_body					alias for $4;
      p_object_type				alias for $5;       -- default ''note''
      p_creation_date			alias for $6;		-- default now()
      p_creation_user			alias for $7;		-- default null
      p_creation_ip				alias for $8;		-- default null
      p_context_id				alias for $9;		-- default null
      v_note_id					notes.note_id%TYPE;
    begin
    
    etc. Where are all of those defaults actually set? In the acs_object__new call?
  • In this the forum thread on attributes, it looks like attributes currently aren't really used, and a tutorial aimed at beginners should ignore attributes. Any vehement disagreement to this?
Collapse
Posted by Tom Jackson on
  • You have to specify all the parameters to a plpgsql function call. The name of the function, plus the number and type of the parameters are used to determine which function body to use, since you can overload functions.
  • Plpgsql doesn't support default values like Oracle pl/sql does.
  • I think the attributes you are directed to 'ignore' are the use of acs_attributes. I don't know for sure, but you obviously can't ignore actual table or function attributes.
  • Collapse
    Posted by Tilmann Singer on
    Plpgsql doesn't support default values like Oracle pl/sql does.

    Just a clarification: when porting from oracle to postgresql the default values have been preserved as inline comments, so that the caller knows which values to set if the defaults are desired, kludging around the fact that plpgsql doesn't support default values like plsql. In plpgsql you would have to call the proc above somehow like this:

    select note__new(
      null,
      null,
      :title,
      :body,
      'note',
      now(),
      null,
      null,
      null
    )
    
    when you only want to specify the two required arguments, title and body.

    If that's a common way to call that procedure then the package author could provide an overloaded variant of the procedure that only takes these two arguments for convenience, like:

    note__new(varchar, varchar)