Thread

  1. PL/pgSQL - for discussion

    Jan Wieck <jwieck@debis.com> — 1998-03-12T15:38:32Z

    Hi,
    
        as  I  proposed,  I'm  now  starting on the PL/pgSQL loadable
        procedural language. As far as I'm now I  have  a  pl_handler
        with  an  independent  flex/bison  parser  that  can  parse a
        rudimentary implementation of the language. The next step  is
        to  start  on the PL/pgSQL executor and look if the generated
        instruction tree can be used (up to now the  pl_handler  only
        dumps the instruction tree and returns a 0 Datum.
    
        If  that  works  I'll  expand  the scanner/parser to the full
        PL/plSQL language including trigger procedures.
    
        But I would like to have some discussion on language  itself.
        So  I wrote down what I had in mind. The document is appended
        below.
    
        Please comment/suggest !
    
        Someone gave a hint about global variables existing during  a
        session.   What  is  a  session  than?  One  transaction? The
        backends lifetime?  And should global variables be visible by
        more  than one function?  I vote for NO! In that case we need
        something like packages of functions that share globals.
    
    
    Jan
    
    --
    
    #======================================================================#
    # It's easier to get forgiveness for being wrong than for being right. #
    # Let's break this rule - forgive me.                                  #
    #======================================== jwieck@debis.com (Jan Wieck) #
    
    
                                    PL/pgSQL
                 A procedural language for the PostgreSQL RDBMS
                                    1st draft
    
                          Jan Wieck <jwieck@debis.com>
    
    
    
        Notice
    
            This  document  is  for  the postgresql-hackers community for
            completing  the  syntax  specification   of   PL/pgSQL.   The
            extension module described here doesn't exist up to now!
    
    
        Preface
    
            PL/pgSQL  is  a procedural language based on SQL designed for
            the PostgreSQL database system.
    
            The extensibility features of PostgreSQL are mostly based  on
            the  ability  to  define  functions  for  various operations.
            Functions could have been written in PostgreSQL's SQL dialect
            or  in the C programming language. Functions written in C are
            compiled into a shared object  and  loaded  by  the  database
            backend  process  on  demand.   Also  the trigger features of
            PostgreSQL are based on functions but required the use of the
            C language.
    
            Since  version  6.3  PostgreSQL  supports  the  definition of
            procedural languages. In the case of a  function  or  trigger
            procedure  defined in a procedural language, the database has
            no builtin knowlege how to  interpret  the  functions  source
            text. Instead, the function and trigger calls are passed into
            a handler that  knows  the  details  of  the  language.   The
            handler  itself is function compiled into a shared object and
            loaded on demand.
    
    
        Overview
    
            The PL/pgSQL language is case insensitive. All  keywords  and
            identifiers can be used in upper-/lowercase mixed.
    
            PL/pgSQL is a block oriented language. A block is defined as
    
                [<<label>>]
                [DECLARE
                    -- declarations]
                BEGIN
                    -- statements
                END;
    
            There  can  be  any  number  of  subblocks  in the statements
            section of a block. Subblocks can be used to  hide  variables
            from  outside a block of statements (see Scope and visability
            below).
    
    
        Comments
    
            There are two types of comments in PL/pgSQL.  A  double  dash
            '--'  starts a comment that extends to the end of the line. A
            '/*' starts a block comment that extends to  the  next  '*/'.
            Block comments cannot be nested, but double dash comments can
            be enclosed into a block comment.
    
    
        Declarations
    
            All variables, rows and records  used  in  a  block  or  it's
            subblocks must be declared in the declarations section of the
            block.   The   parameters   given   to   the   function   are
            automatically  declared  with  the usual identifiers $n.  The
            declarations have the following syntax:
    
                <name> [CONSTANT] <type> [NOT NULL]
                                         [DEFAULT | := <value>];
    
                    Declares a variable of the  specified  type.  If  the
                    variable is declared as CONSTANT, the value cannot be
                    changed. If NOT NULL is specified, an assignment of a
                    NULL  value  results  in  a  runtime error. Since the
                    default value of a variable is the  SQL  NULL  value,
                    all  variables  declared as NOT NULL must also have a
                    default value.
    
                    The default value is evaluated at the actual function
                    call. So assigning 'now' to an abstime varable causes
                    the variable to have the time of the actual  function
                    call, not when the function was compiled.
    
                <name> <class>%ROWTYPE;
    
                    Declares a row with the structure of the given class.
                    Class must be an existing table- or viewname  of  the
                    database.  The  fields of the row are accessed in the
                    dot notation. Parameters  to  a  procedure  could  be
                    tuple   types.   In   that   case  the  corresponding
                    identifier $n  will  be  a  rowtype.  Only  the  user
                    attributes  and  the oid of a tuple are accessible in
                    the row. There must be  no  whitespaces  between  the
                    classname, the percent and the ROWTYPE keyword.
    
                <name> RECORD;
    
                    Records  are  similar  to  rowtypes, but they have no
                    predefined structure and it's impossible to assign  a
                    value  into them. They are used in selections and FOR
                    loops to hold one actual database tuple from a select
                    operation.  One  and  the  same record can be used in
                    different selections (but not in nested ones).
    
                <name> ALIAS FOR $n;
    
                    For better readability of the code it's  possible  to
                    define  an  alias  for  a positional parameter to the
                    function.
    
        Datatypes
    
            The type of a variable can be any of the existing data  types
            of the database. <type> above is defined as:
    
                    postgesql-basetype
                or  variable%TYPE
                or  rowtype.field%TYPE
                or  class.field%TYPE
    
            As  for the rowtype declaration, there must be no whitespaces
            between the classname, the percent and the TYPE keyword.
    
        Expressions
    
            All expressions used in  PL/pgSQL  statements  are  processed
            using  the  backends  executor. Since even a constant looking
            expression  can  have  a  totally  different  meaning  for  a
            particular data type (as 'now' for abstime), it is impossible
            for the PL/pgSQL parser  to  identify  real  constant  values
            other than the NULL keyword. The expressions are evaluated by
            internally executing a query
    
                SELECT <expr>
    
            over the  SPI  manager.  In  the  expression,  occurences  of
            variable  identifiers  are  substituted by parameters and the
            actual values from the variables are passed to  the  executor
            as  query  parameters. All the expressions used in a PL/pgSQL
            function are only prepared and saved once.
    
        Statements
    
            Anything not understood by the parser as specified below will
            be  put  into a query and sent down to the database engine to
            execute.  The resulting query should not return any data.
    
            Assignment
    
                An assignment of a value to a variable or  rowtype  field
                is written as:
    
                    <identifier> := <expr>;
    
                If  the  expressions  result  data type doesn't match the
                variables data type, or the variables atttypmod value  is
                known  (as  for  char(20)),  the  result  value  will  be
                implicitly casted by  the  PL/pgSQL  executor  using  the
                result  types  output-  and  the  variables  type  input-
                functions.  Note that this could  potentially  result  in
                runtime errors generated by the types input functions.
    
                An  assignment  of  a complete selection into a record or
                rowtype can be done as:
    
                    SELECT targetlist INTO <recname|rowname> FROM fromlist;
    
                If a rowtype is used as target, the  selected  targetlist
                must  exactly  match  the  structure  of the rowtype or a
                runtime error occurs.  The fromlist can  be  followed  by
                any  valid qualification, grouping, sorting etc. There is
                a  special  condition  [NOT]  FOUND  that  can  be   used
                immediately  after a SELECT INTO to check if the data has
                been found.
    
                    SELECT * INTO myrec FROM EMP WHERE empname = myname;
                    IF NOT FOUND THEN
                        ELOG ERROR 'employee %s not found' myname;
                    END IF;
    
                In addition, the select statement must  not  return  more
                that  one  row.  If multiple rows are returned, a runtime
                error will be generated.
    
    
            Returning from the function
    
                    RETURN <expr>;
    
                The function terminates and the value of <expr>  will  be
                returned  to  the  upper executor.  The return value of a
                function cannot be undefined.  If control reaches the end
                of  the  toplevel block of the function without hitting a
                RETURN statement, a runtime error will occur.
    
    
            Aborting and messages
    
                As indicated above there is an ELOG  statement  that  can
                throw messages into the PostgreSQL elog mechanism.
    
                    ELOG level 'format' [identifiers];
    
                Inside the format, only %s might be used as a placeholder
                for  the  following  identifiers.  The  identifiers  must
                specify an existing variable or row/record field.
    
    
            Conditionals
    
                    IF <expr> THEN
                        -- statements
                    [ELSE
                        -- statements]
                    END IF;
    
                The  expression  <expr> must return a value that at least
                can be casted into a boolean.
    
    
            Loops
    
                There are multiple types of loops.
    
                    [<<label>>]
                    LOOP
                        -- statements
                    END LOOP;
    
                An unconditional loop that must be terminated  explicitly
                by  an  EXIT statement. The optional label can be used by
                EXIT statements of nested loops to specify which level of
                nesting should be terminated.
    
                    [<<label>>]
                    WHILE <expr> LOOP
                        -- statements
                    END LOOP;
    
                A  conditional  loop  that  is  executed  as  long as the
                evaluation of <expr> returns true.
    
                    [<<label>>]
                    FOR <name> IN [REVERSE] <expr>..<expr> LOOP
                        -- statements
                    END LOOP.
    
                A loop that iterates over a range of integer values.  The
                variable  <name> is automatically created as type integer
                and exists only inside  the  loop.  The  two  expressions
                giving  the  lower  and  upper  bound  of  the  range are
                evaluated only when entering the loop. The iteration step
                is 1.
    
                    FOR <recname|rowname> IN <select_clause> LOOP
                        -- statements
                    END LOOP;
    
                The record or row is assigned all the rows resulting from
                the select clause and the statements executed  for  each.
                If  the  loop  is  terminated with an EXIT statement, the
                last accessed row is still accessible in  the  record  or
                rowtype.
    
                    EXIT [label] [WHEN <expr>];
    
                If  no  label given, the innermost loop is terminated and
                the statement following END LOOP  is  executed  next.  If
                label is given, it must be the label of the current or an
                upper level of nested loops or blocks.   Then  the  named
                loop  or  block  is terminated and control continues with
                the statement after the loops/blocks corresponding END.
    
    
    
  2. Re: [HACKERS] PL/pgSQL - for discussion

    Thomas Lockhart <lockhart@alumni.caltech.edu> — 1998-03-12T16:21:08Z

    >     as  I  proposed,  I'm  now  starting on the PL/pgSQL loadable
    >     procedural language.
    >     Please comment/suggest !
    >     Someone gave a hint about global variables existing during  a
    >     session.   What  is  a  session  than?  One  transaction? The
    >     backends lifetime?  And should global variables be visible by
    >     more  than one function?  I vote for NO! In that case we need
    >     something like packages of functions that share globals.
    
    This looks nice. SQL92 (and presumably SQL3) has the concept of global
    and local, temporary and permanent, tables. I believe that it also has
    the concept of variables with the same possible combinations of
    behaviors, but I'm not finding that in my books at the moment.
    
    Clearly if we have these features in the backend someday, then there
    would need to be hooks for your PL to use also. No need for you to
    provide these if the backend doesn't help you imho.
    
    I haven't had a chance to read the main portion of your document yet...
    
                          - Tom
    
    
  3. Re: [HACKERS] PL/pgSQL - for discussion

    Bruce Momjian <maillist@candle.pha.pa.us> — 1998-03-12T17:40:44Z

    > 
    > Hi,
    > 
    >     as  I  proposed,  I'm  now  starting on the PL/pgSQL loadable
    >     procedural language. As far as I'm now I  have  a  pl_handler
    >     with  an  independent  flex/bison  parser  that  can  parse a
    >     rudimentary implementation of the language. The next step  is
    >     to  start  on the PL/pgSQL executor and look if the generated
    >     instruction tree can be used (up to now the  pl_handler  only
    >     dumps the instruction tree and returns a 0 Datum.
    > 
    >     If  that  works  I'll  expand  the scanner/parser to the full
    >     PL/plSQL language including trigger procedures.
    > 
    >     But I would like to have some discussion on language  itself.
    >     So  I wrote down what I had in mind. The document is appended
    >     below.
    > 
    >     Please comment/suggest !
    
    Gee, it looks really nice.  I have never used such an advanced language
    INSIDE a database engine.
    
    -- 
    Bruce Momjian                          |  830 Blythe Avenue
    maillist@candle.pha.pa.us              |  Drexel Hill, Pennsylvania 19026
      +  If your life is a hard drive,     |  (610) 353-9879(w)
      +  Christ can be your backup.        |  (610) 853-3000(h)
    
    
  4. Re: [HACKERS] PL/pgSQL - for discussion

    ocie@paracel.com — 1998-03-12T20:16:13Z

    Jan Wieck wrote:
    > 
    > Hi,
    > 
    >     as  I  proposed,  I'm  now  starting on the PL/pgSQL loadable
    >     procedural language. As far as I'm now I  have  a  pl_handler
    >     with  an  independent  flex/bison  parser  that  can  parse a
    >     rudimentary implementation of the language. The next step  is
    >     to  start  on the PL/pgSQL executor and look if the generated
    >     instruction tree can be used (up to now the  pl_handler  only
    >     dumps the instruction tree and returns a 0 Datum.
    > 
    >     If  that  works  I'll  expand  the scanner/parser to the full
    >     PL/plSQL language including trigger procedures.
    > 
    >     But I would like to have some discussion on language  itself.
    >     So  I wrote down what I had in mind. The document is appended
    >     below.
    > 
    >     Please comment/suggest !
    > 
    >     Someone gave a hint about global variables existing during  a
    >     session.   What  is  a  session  than?  One  transaction? The
    >     backends lifetime?  And should global variables be visible by
    >     more  than one function?  I vote for NO! In that case we need
    >     something like packages of functions that share globals.
    > 
    > 
    > Jan
    
    This looks good.  
    
    I especially like the "for x in select ..." part, it looks a lot more
    elegant than cursors, but we might want to provide a cursor with a
    "get next row" and "get previous row" function, as the for loop only
    goes one way.
    
    Another suggestion related to parameters:
    
    >             <name> ALIAS FOR $n;
    > 
    >                 For better readability of the code it's  possible  to
    >                 define  an  alias  for  a positional parameter to the
    >                 function.
    > 
    
    What is the defined behavior if the user leaves out this parameter?
    Do we generate a runtime error?  If I might suggest the following:
    
    <name> ALIAS FOR $n;
    sets up name as an alias for $n, name is null if that parameter was
    not given.
    
    <name> REQUIRED ALIAS FOR $n;
    sets up name as an alias for $n, generate a runtime error if that
    parameter was not given.
    
    Actually, an assignment might be a better way to do this.  I.E. Define
    foo as int not null, assign $2 to foo and if there is an error, the user is notified.
    
    Ocie
    
    
  5. Re: [HACKERS] PL/pgSQL - for discussion

    David Gould <dg@illustra.com> — 1998-03-12T21:31:33Z

    I haven't read the PL/SQL proposal yet so please do not take this as
    criticism of the proposal. It is just that I have sometimes wondered (having
    used and maintained a couple of them) if there is a real need to invent
    another procedural language inside a dbms. Who really needs yet another
    language that only works in certain special circumstances? Why not just
    adapt an existing language implementation and graft SQL integration into
    it? For example in Perl:
    
    sub find_prospects_to_contact ()
       # note that sql select looks like a file handle/split() combo to perl
       while (<select ($name, $phone) from prospects p, 
                  where prospect.interests ~= /computer/ or /electronics/;
              >) {
          # some stuff to be done per row
          ...
          if ($should_contact) {
             insert into contacts_todo values ($name, $phone);
          }
       }
    
    
    Of course there are probably a zillion great reasons why this would be hard
    or the wrong thing to do, but still...
    
     Wouldn't it be cool?
    
    -dg
    
    
    David Gould            dg@illustra.com           510.628.3783 or 510.305.9468 
    Informix Software  (No, really)         300 Lakeside Drive  Oakland, CA 94612
     - I realize now that irony has no place in business communications.
    
    
    
  6. Re: [HACKERS] PL/pgSQL - for discussion

    Michal Mosiewicz <mimo@interdata.com.pl> — 1998-03-12T21:54:20Z

    David Gould wrote:
    > 
    > I haven't read the PL/SQL proposal yet so please do not take this as
    > criticism of the proposal. It is just that I have sometimes wondered (having
    > used and maintained a couple of them) if there is a real need to invent
    > another procedural language inside a dbms. Who really needs yet another
    > language that only works in certain special circumstances?
    
    But Jan has already adopted an existing language interpreter (i.e. TCL).
    Now he speaks about server side programing using native SQL.
    
    Actually existance of SQL server programming in SQL database seems to be
    quite expected feature. You may consider that most SQL developers
    doesn't really need other languages but SQL, so it's not inventing
    another language. It's just a wider, more flexible implementation of
    internal SQL.
    
    Mike
    
    -- 
    WWW: http://www.lodz.pdi.net/~mimo  tel: Int. Acc. Code + 48 42 148340
    add: Michal Mosiewicz  *  Bugaj 66 m.54 *  95-200 Pabianice  *  POLAND
    
    
  7. Re: [HACKERS] PL/pgSQL - for discussion

    Vadim B. Mikheev <vadim@sable.krasnoyarsk.su> — 1998-03-13T04:40:07Z

    Jan Wieck wrote:
    > 
    > Hi,
    > 
    >     as  I  proposed,  I'm  now  starting on the PL/pgSQL loadable
    >     procedural language. As far as I'm now I  have  a  pl_handler
    >     with  an  independent  flex/bison  parser  that  can  parse a
    >     rudimentary implementation of the language. The next step  is
    >     to  start  on the PL/pgSQL executor and look if the generated
    >     instruction tree can be used (up to now the  pl_handler  only
    >     dumps the instruction tree and returns a 0 Datum.
    > 
    >     If  that  works  I'll  expand  the scanner/parser to the full
    >     PL/plSQL language including trigger procedures.
    
    Why PL/pgSQL should be loadable PL? Why not built-in ?
    Would it be possible to add dirrect support for PL/pgSQL syntax
    to current parser ?
    Typing procedure body inside ' is not nice thing, imho.
    
    >     Someone gave a hint about global variables existing during  a
    >     session.   What  is  a  session  than?  One  transaction? The
    >     backends lifetime?  And should global variables be visible by
          ^^^^^^^^^^^^^^^^^
    This.
    
    >     more  than one function?  I vote for NO! In that case we need
    >     something like packages of functions that share globals.
    
    Let's leave packages for future, but why session-level variables
    shouldn't be visible inside procedures right now? 
    
    > 
    >         PL/pgSQL is a block oriented language. A block is defined as
    > 
    >             [<<label>>]
    >             [DECLARE
    >                 -- declarations]
    >             BEGIN
    >                 -- statements
    >             END;
    
    Someday we'll have nested transactions...
    How about disallow using BEGIN/END as transaction control statements
    right now ?
    START/COMMIT/ROLLBACK/ABORT and nothing more...
    
    >             <name> <class>%ROWTYPE;
    > 
    >                 Declares a row with the structure of the given class.
    >                 Class must be an existing table- or viewname  of  the
    >                 database.  The  fields of the row are accessed in the
    >                 dot notation. Parameters  to  a  procedure  could  be
    >                 tuple   types.   In   that   case  the  corresponding
    >                 identifier $n  will  be  a  rowtype.  Only  the  user
    >                 attributes  and  the oid of a tuple are accessible in
    >                 the row. There must be  no  whitespaces  between  the
    >                 classname, the percent and the ROWTYPE keyword.
    > 
    >             <name> RECORD;
    > 
    >                 Records  are  similar  to  rowtypes, but they have no
    >                 predefined structure and it's impossible to assign  a
    >                 value  into them. They are used in selections and FOR
    >                 loops to hold one actual database tuple from a select
    >                 operation.  One  and  the  same record can be used in
    >                 different selections (but not in nested ones).
    
    Do we really need in both ROWTYPE & RECORD ?
    I would get rid of RECORD and let ROWTYPE variables be 
    'with yet undefined type of row' (make <class> optional). More of that,
    why not treat ROWTYPE like structures in C and let the following:
    
    name %ROWTYPE {a	int4, b text};
    
    ?
    
    >                 SELECT * INTO myrec FROM EMP WHERE empname = myname;
                                    ^^^^^                          ^^^^^^
    How about $-prefix ?
    
    >             As indicated above there is an ELOG  statement  that  can
    >             throw messages into the PostgreSQL elog mechanism.
    > 
    >                 ELOG level 'format' [identifiers];
                      ^^^^^^^^^^
    NO, pls - too postgres-ish! Just let ABORT to have 'format' etc and add 
    PRINT (or something like this) to put some messages to application (via NOTICE).
    What are used in Oracle, Sybase etc here ?
    
    Vadim
    
    
  8. Re: [HACKERS] PL/pgSQL - for discussion

    Jan Wieck <jwieck@debis.com> — 1998-03-13T08:59:36Z

    Ocie wrote:
    >
    > This looks good.
    >
    > I especially like the "for x in select ..." part, it looks a lot more
    > elegant than cursors, but we might want to provide a cursor with a
    > "get next row" and "get previous row" function, as the for loop only
    > goes one way.
    
        We  don't  have  real  cursors  up to now. The SPI_exec() and
        SPI_execp() functions  return  the  complete  set  of  tuples
        selected.   And  I'm not sure if that what PostgreSQL calls a
        cursor can be used in the backend over SPI. It requires named
        portals  and  them in turn require a transaction block (BEGIN
        ... COMMIT).  But I think it would be easy to build something
        that looks like cursors on top of the complete set of tuples.
    
    >
    > Another suggestion related to parameters:
    >
    > >             <name> ALIAS FOR $n;
    > >
    > >                 For better readability of the code it's  possible  to
    > >                 define  an  alias  for  a positional parameter to the
    > >                 function.
    > >
    >
    > What is the defined behavior if the user leaves out this parameter?
    > Do we generate a runtime error?  If I might suggest the following:
    >
    > <name> ALIAS FOR $n;
    > sets up name as an alias for $n, name is null if that parameter was
    > not given.
    
        The backends main parser chooses functions not only by  name.
        The  number  and  datatypes of the given parameters must also
        match  (function  overloading  -   possible   with   our   PL
        implementation).  If  a  query execution reaches the function
        call, be sure that all parameters are given.
    
        I thought about it just as  a  way  to  make  the  code  more
        readable.  The parameters might also be accessed by the usual
        $n notation.  So if you have
    
            empname ALIAS FOR $n;
    
        in the declarations, empname and $n are identical. Thats  how
        I understand the word ALIAS.
    
    >
    > <name> REQUIRED ALIAS FOR $n;
    > sets up name as an alias for $n, generate a runtime error if that
    > parameter was not given.
    >
    > Actually, an assignment might be a better way to do this.  I.E. Define
    > foo as int not null, assign $2 to foo and if there is an error, the user is notified.
    
        Does  make  sense.  But for sake a function cannot identify a
        null value in one of the parameters.  The  passed  in  isNull
        flag  only says that one of all parameters is null. Not which
        one. We have to change this someday, and I have already  some
        ideas on that. But that's another topic.
    
    
    Jan
    
    --
    
    #======================================================================#
    # It's easier to get forgiveness for being wrong than for being right. #
    # Let's break this rule - forgive me.                                  #
    #======================================== jwieck@debis.com (Jan Wieck) #
    
    
    
    
  9. Re: [HACKERS] PL/pgSQL - for discussion

    Jan Wieck <jwieck@debis.com> — 1998-03-13T09:31:01Z

    Mike wrote:
    >
    > David Gould wrote:
    > >
    > > I haven't read the PL/SQL proposal yet so please do not take this as
    > > criticism of the proposal. It is just that I have sometimes wondered (having
    > > used and maintained a couple of them) if there is a real need to invent
    > > another procedural language inside a dbms. Who really needs yet another
    > > language that only works in certain special circumstances?
    >
    > But Jan has already adopted an existing language interpreter (i.e. TCL).
    > Now he speaks about server side programing using native SQL.
    
        For version 6.3 look into .../pgsql/src/pl/tcl.
    
    >
    > Actually existance of SQL server programming in SQL database seems to be
    > quite expected feature. You may consider that most SQL developers
    > doesn't really need other languages but SQL, so it's not inventing
    > another language. It's just a wider, more flexible implementation of
    > internal SQL.
    
        Even  if  "most  SQL  developers don't need (or know) another
        language" is reason enough for  an  SQL  based  PL,  my  main
        reason is another one.
    
        PL/Tcl  at least requires that the Tcl library got built on a
        system.  And I have tested only that it works with Tcl7.5 and
        Tcl8.0.   I  expect  that  the PL/perl implementation (I hope
        Brett McCormick is still working on that) will  need  a  perl
        library too.
    
        So  there  is  no  PL  implementation  up  to  now,  that  is
        independent from another software package. PL/pgSQL will  be!
        PL/pgSQL  will  be  the first language that can get installed
        and  enabled  by  default  and  then  be  available  in   all
        PostgreSQL installations.
    
    
    Jan
    
    --
    
    #======================================================================#
    # It's easier to get forgiveness for being wrong than for being right. #
    # Let's break this rule - forgive me.                                  #
    #======================================== jwieck@debis.com (Jan Wieck) #
    
    
    
    
  10. Re: [HACKERS] PL/pgSQL - for discussion

    Jan Wieck <jwieck@debis.com> — 1998-03-13T12:10:30Z

    Vadim wrote:
    >
    > Jan Wieck wrote:
    > >
    > > Hi,
    > >
    > >     as  I  proposed,  I'm  now  starting on the PL/pgSQL loadable
    > >     procedural language. As far as I'm now I  have  a  pl_handler
    > >     with  an  independent  flex/bison  parser  that  can  parse a
    > >     rudimentary implementation of the language. The next step  is
    > >     to  start  on the PL/pgSQL executor and look if the generated
    > >     instruction tree can be used (up to now the  pl_handler  only
    > >     dumps the instruction tree and returns a 0 Datum.
    > >
    > >     If  that  works  I'll  expand  the scanner/parser to the full
    > >     PL/plSQL language including trigger procedures.
    >
    > Why PL/pgSQL should be loadable PL? Why not built-in ?
    > Would it be possible to add dirrect support for PL/pgSQL syntax
    > to current parser ?
    > Typing procedure body inside ' is not nice thing, imho.
    
        Well,  PL/pgSQL  could  be  compiled  in  and  the pl_handler
        function  and  language  tuples   set   at   bootstrap.   But
        incorporating  the parser into the backends main parser isn't
        nesseccary then either. Not that I think it's impossible, but
        the current main parser is complex enough for me.
    
        The  typing  of  the  procedure body inside of ' is damned. I
        know :-) I think it might be possible to allow {} or the like
        to  be  used  instead and then only quote \} inside the body.
        This stuff might be easy done in the scanner (haven't  looked
        at the code yet).
    
    >
    > >     Someone gave a hint about global variables existing during  a
    > >     session.   What  is  a  session  than?  One  transaction? The
    > >     backends lifetime?  And should global variables be visible by
    >       ^^^^^^^^^^^^^^^^^
    > This.
    
        OK.
    
    >
    > >     more  than one function?  I vote for NO! In that case we need
    > >     something like packages of functions that share globals.
    >
    > Let's leave packages for future, but why session-level variables
    > shouldn't be visible inside procedures right now?
    
        For  security. At least I would like the visibility of global
        variables depend on the functions owner. So users A and B can
        use the same global name in their functions but the variables
        are different.
    
    >
    > >
    > >         PL/pgSQL is a block oriented language. A block is defined as
    > >
    > >             [<<label>>]
    > >             [DECLARE
    > >                 -- declarations]
    > >             BEGIN
    > >                 -- statements
    > >             END;
    >
    > Someday we'll have nested transactions...
    > How about disallow using BEGIN/END as transaction control statements
    > right now ?
    > START/COMMIT/ROLLBACK/ABORT and nothing more...
    
        Right now!
    
    >
    > Do we really need in both ROWTYPE & RECORD ?
    > I would get rid of RECORD and let ROWTYPE variables be
    > 'with yet undefined type of row' (make <class> optional). More of that,
    > why not treat ROWTYPE like structures in C and let the following:
    >
    > name %ROWTYPE {a  int4, b text};
    
        Hmmm. Or doing it the Oracle way
    
            DECLARE
              TYPE myrectype IS RECORD (
                field1  integer NOT NULL,
                field2  text);
    
              myrec   myrectype;
            BEGIN
              ...
            END
    
        But I would like to let the RECORD of  unspecified  structure
        in.  It doesn't need much declarations typing.
    
    >
    > ?
    >
    > >                 SELECT * INTO myrec FROM EMP WHERE empname = myname;
    >                                 ^^^^^                          ^^^^^^
    > How about $-prefix ?
    
        I  don't  like  the  $'s.  But  I  have seen the problem that
        without blowing up my parser I cannot do it  the  oracle  way
        where  a  field  name  of  a  selected table precedes a local
        varname and the  local  varname  if  identical  to  a  tables
        fieldname  must be prefixed with the label of the block. This
        is what Oracle does:
    
            <<outer>>
            DECLARE
              emp emp%ROWTYPE;
              empname  emp.empname%TYPE
              salary   emp.salary%TYPE
            BEGIN
              ...
              SELECT * INTO outer.emp FROM emp WHERE empname = outer.empname;
              --            ^^^^^^^^^      ^^^       ^^^^^^^   ^^^^^^^^^^^^^
              --            PLs rowtype    table     table-    PLs variable
              --                                     field
    
              salary := emp.salary;
              -- ^^^^^^^^^^^^^^^^^
              -- Outside of SELECT stmt - all identifiers in PL
    
              ...
            END
    
    
    >
    > >             As indicated above there is an ELOG  statement  that  can
    > >             throw messages into the PostgreSQL elog mechanism.
    > >
    > >                 ELOG level 'format' [identifiers];
    >                   ^^^^^^^^^^
    > NO, pls - too postgres-ish! Just let ABORT to have 'format' etc and add
    > PRINT (or something like this) to put some messages to application (via NOTICE).
    > What are used in Oracle, Sybase etc here ?
    
        Oracle uses RAISE EXCEPTION ... with some numbers  specifying
        the message in the message catalog and other information.
    
        What about
    
            RAISE EXCEPTION 'format' [identifiers];     -- elog(ERROR, ...)
            RAISE NOTICE 'format' [identifiers];        -- elog(NOTICE, ...)
            RAISE DEBUG 'format' [identifiers];         -- elog(DEBUG, ...)
    
        The  first  is somewhat compatible and the two otheres can be
        easyly  commented  out.  Since  the  language   is   somewhat
        PostgreSQL   specific   anyway  (arguments  are  unnamed  and
        identified by position with $n), PL procedures must be ported
        when  moving to another DB. But who ever wants to use another
        DB, once he used PostgreSQL?
    
    
    Jan
    
    --
    
    #======================================================================#
    # It's easier to get forgiveness for being wrong than for being right. #
    # Let's break this rule - forgive me.                                  #
    #======================================== jwieck@debis.com (Jan Wieck) #
    
    
    
    
  11. Re: [HACKERS] PL/pgSQL - for discussion

    David Gould <dg@illustra.com> — 1998-03-14T07:41:44Z

    Jan and Vadim (I think) discuss:
    > >
    > > Why PL/pgSQL should be loadable PL? Why not built-in ?
    > > Would it be possible to add dirrect support for PL/pgSQL syntax
    > > to current parser ?
    ...
    >     Well,  PL/pgSQL  could  be  compiled  in  and  the pl_handler
    >     function  and  language  tuples   set   at   bootstrap.   But
    >     incorporating  the parser into the backends main parser isn't
    >     nesseccary then either. Not that I think it's impossible, but
    >     the current main parser is complex enough for me.
    
    I agree, for a language this simple, it would be nice to have it
    in the main parser. This might not be too hard since the existing statements
    are not really changing, only some new ones are added. eg:
    
    Select_Stmt := SELECT _name_list FROM _from_clause WHERE _where_clause_
    ...
    
    + If_Stmt := IF _expression_ THEN _statement_list END
    + Loop_Stmt := ...
    
    Or whatever the grammar looks like.
    
    A bit harder is that the executor now has to sequence through the statements
    and handle branches and storing variables etc.
    
    > > >     Someone gave a hint about global variables existing during  a
    > > >     session.   What  is  a  session  than?  One  transaction? The
    > > >     backends lifetime?  And should global variables be visible by
    > >       ^^^^^^^^^^^^^^^^^
    > > This.
    
    Agree. 
    
    >     OK.
    > 
    > > >     more  than one function?  I vote for NO! In that case we need
    > > >     something like packages of functions that share globals.
    > >
    > > Let's leave packages for future, but why session-level variables
    > > shouldn't be visible inside procedures right now?
    > 
    >     For  security. At least I would like the visibility of global
    >     variables depend on the functions owner. So users A and B can
    >     use the same global name in their functions but the variables
    >     are different.
    
    Not a problem. If the global variables are global only to the session they
    can be stored in allocated memory, not in the shared memory. Automatically
    then they are private to the user of that session and are destroyed when
    the session ends.
    
    > > >             [<<label>>]
    > > >             [DECLARE
    > > >                 -- declarations]
    > > >             BEGIN
    > > >                 -- statements
    > > >             END;
    > >
    > > Someday we'll have nested transactions...
    > > How about disallow using BEGIN/END as transaction control statements
    > > right now ?
    > > START/COMMIT/ROLLBACK/ABORT and nothing more...
    > 
    >     Right now!
    
    Hmmm, I like BEGIN TRAN/END TRAN/ABORT TRAN. I suppose there is a standard
    we should be following... Also, we probably should not start breaking
    existing applications, users get very fussy about that.
     
    > > >             throw messages into the PostgreSQL elog mechanism.
    > > >
    > > >                 ELOG level 'format' [identifiers];
    > >                   ^^^^^^^^^^
    > > NO, pls - too postgres-ish! Just let ABORT to have 'format' etc and add
    > > PRINT (or something like this) to put some messages to application (via NOTICE).
    
    What is wrong with ELOG? It seems concise and does what is wanted, yes?
    Why add syntax?
    
    -dg
    
    David Gould            dg@illustra.com           510.628.3783 or 510.305.9468 
    Informix Software  (No, really)         300 Lakeside Drive  Oakland, CA 94612
     - I realize now that irony has no place in business communications.