diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml index 07078e6..ce1676b 100644 --- a/doc/src/sgml/plpgsql.sgml +++ b/doc/src/sgml/plpgsql.sgml @@ -3510,7 +3510,7 @@ PREPARE statement_name(text, timestamp) AS - The substitution mechanism will replace any token that matches a + 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 - Variable substitution does not happen in the command string given + There are two places where variable substitution does not happen. + + + + 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, + + 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; + + All occurances of v_logtxt in the function are replaced except the one + following "AS". + + + + Variable substitution also does not happen in the command string given to 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 5572cf7..fe432d7 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,14 @@ 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 5d7f497..d67bd3d 100644 --- a/src/pl/plpgsql/src/scan.l +++ b/src/pl/plpgsql/src/scan.l @@ -147,6 +147,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; }