Re: [PATCH] 8.5 plpgsql change for named notation: treat word following AS keyword as label v3

From: Steve Prentice <prentice(at)cisco(dot)com>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: pgsql-hackers(at)postgresql(dot)org
Subject: Re: [PATCH] 8.5 plpgsql change for named notation: treat word following AS keyword as label v3
Date: 2009-05-21 18:46:24
Message-ID: 1B96769F-91E7-4AB9-84C8-0F3E1A796E9B@cisco.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: 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; }

In response to

Responses

Browse pgsql-hackers by date

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