Re: [PATCH] 8.5 plpgsql change for named notation: treat word following AS keyword as label v3 - Mailing list pgsql-hackers

From Steve Prentice
Subject Re: [PATCH] 8.5 plpgsql change for named notation: treat word following AS keyword as label v3
Date
Msg-id 1B96769F-91E7-4AB9-84C8-0F3E1A796E9B@cisco.com
Whole thread Raw
In response to Re: [PATCH] 8.5 plpgsql change for named notation: treat word following AS keyword as label v2  (Tom Lane <tgl@sss.pgh.pa.us>)
Responses Re: [PATCH] 8.5 plpgsql change for named notation: treat word following AS keyword as label v3
Re: [PATCH] 8.5 plpgsql change for named notation: treat word following AS keyword as label v3
List pgsql-hackers
On May 21, 2009, at 10:52 AM, Tom Lane wrote:
> It's probably time to bite the bullet and redo the parser as has been
> suggested in the past, ie fix things so that the main parser is used.
> Ideally I'd like to switch the name resolution priority to be more
> Oracle-like, but even if we don't do that it would be a great
> improvement to have actual syntactic knowledge behind the lookups.

That kind of refactoring is beyond my experience-level with the code,  
but I can't say I disagree with your analysis.

> Just for the record, you'd have to put the same kluge into the  
> T_RECORD
> and T_ROW cases if we wanted to do it like this.

Patch updated.

diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml
index 80dbf45..f8e8ce4 100644
--- a/doc/src/sgml/plpgsql.sgml
+++ b/doc/src/sgml/plpgsql.sgml
@@ -3510,7 +3510,7 @@ PREPARE <replaceable>statement_name</>(text,  
timestamp) AS    </para>
    <para>
-    <emphasis>The substitution mechanism will replace any token that  
matches a
+    <emphasis>The substitution mechanism will replace most tokens  
that match a     known variable's name.</>  This poses various traps for the  
unwary.     For example, it is a bad idea     to use a variable name that is the same as any table or column  
name
@@ -3603,7 +3603,27 @@ CONTEXT:  SQL statement in PL/PgSQL function  
"logfunc2" near line 5    </para>
    <para>
-    Variable substitution does not happen in the command string given
+    There are two places where variable substitution does not happen.
+   </para>
+
+   <para>
+    Any label following the "AS" keyword is not replaced. This allows  
passing
+    parameters by name to functions that have parameters of the same  
name as
+    the calling function. For example,
+<programlisting>
+    CREATE FUNCTION logfunc(v_logtxt text) RETURNS void AS $$
+        BEGIN
+            INSERT INTO logtable (logtxt) VALUES (v_logtxt);
+            PERFORM tracefunc(v_logtxt AS v_logtxt);
+        END;
+     $$ LANGUAGE plpgsql;
+</programlisting>
+   All occurances of v_logtxt in the function are replaced except the  
one
+   following "AS".
+   </para>
+
+   <para>
+    Variable substitution also does not happen in the command string  
given     to <command>EXECUTE</> or one of its variants.  If you need to     insert a varying value into such a
command,do so as part of     constructing the string value, as illustrated in
 
diff --git a/src/pl/plpgsql/src/gram.y b/src/pl/plpgsql/src/gram.y
index 06704cf..3b4e9b8 100644
--- a/src/pl/plpgsql/src/gram.y
+++ b/src/pl/plpgsql/src/gram.y
@@ -177,6 +177,7 @@ static List                          
*read_raise_options(void);                 * Keyword tokens                 */ %token K_ALIAS
+%token K_AS %token K_ASSIGN %token K_BEGIN %token K_BY
@@ -1977,6 +1978,7 @@ read_sql_construct(int until,                                   int *endtoken) {        int
                             tok;
 
+       int                                     prevtok = 0;        int                                     lno;
PLpgSQL_dstring        ds;        int                                     parenlevel = 0;
 
@@ -1989,7 +1991,7 @@ read_sql_construct(int until,        plpgsql_dstring_init(&ds);
plpgsql_dstring_append(&ds,sqlstart);
 

-       for (;;)
+       for (;;prevtok = tok)        {                tok = yylex();                if (tok == until && parenlevel ==
0)
@@ -2031,6 +2033,16 @@ read_sql_construct(int until,                if (plpgsql_SpaceScanned)
plpgsql_dstring_append(&ds," ");
 

+               /* A variable following AS is treated as a label */
+               if (prevtok == K_AS &&
+                               (tok == T_SCALAR || tok == T_ROW ||  
tok == T_RECORD))
+               {
+                       plpgsql_dstring_append(&ds, yytext);
+                       continue;
+               }
+                switch (tok)                {                        case T_SCALAR:
diff --git a/src/pl/plpgsql/src/scan.l b/src/pl/plpgsql/src/scan.l
index 1917eef..e3a5c45 100644
--- a/src/pl/plpgsql/src/scan.l
+++ b/src/pl/plpgsql/src/scan.l
@@ -149,6 +149,7 @@ param                       \${digit}+ =                              { return  
K_ASSIGN;                      } \.\.                   { return K_DOTDOT;                      } alias
{ return K_ALIAS;                       }
 
+as                             { return  
K_AS;                          } begin                  { return K_BEGIN;                       } by
        { return  
 
K_BY;                          } case                   { return K_CASE;                        }



pgsql-hackers by date:

Previous
From: Greg Stark
Date:
Subject: Re: Fast ALTER TABLE ... ADD COLUMN ... DEFAULT xxx?
Next
From: Josh Berkus
Date:
Subject: Re: [PATCH] 8.5 plpgsql change for named notation: treat word following AS keyword as label v2