-
+
PL/pgSQL - SQL Procedural Language
+
+ There is actually a hidden outer block> surrounding the body
+ of any
PL/pgSQL> function. This block provides the
+ declarations of the function's parameters (if any), as well as some
+ special variables such as FOUND (see
+ ). The outer block is
+ labeled with the function's name, meaning that parameters and special
+ variables can be qualified with the function's name.
+
+
+
It is important not to confuse the use of
BEGIN>/END> for grouping statements in
-
PL/pgSQL> with the database commands for transaction
+
PL/pgSQL> with the similarly-named SQL commands
+ for transaction
control.
PL/pgSQL>'s BEGIN>/END>
are only for grouping; they do not start or end a transaction.
Functions and trigger procedures are always executed within a transaction
END;
$$ LANGUAGE plpgsql;
+
+
+
+ These two examples are not perfectly equivalent. In the first case,
+ subtotal> could be referenced as
+ sales_tax.subtotal>, but in the second case it could not.
+ (Had we attached a label to the block, subtotal> could
+ be qualified with that label, instead.)
+
+
+
Some more examples:
CREATE FUNCTION instr(varchar, integer) RETURNS integer AS $$
- You cannot use parameter names that are the same as columns
- that are referenced in the function. Oracle allows you to do this
- if you qualify the parameter name using
- <literal>function_name.parameter_name>.
- In
PL/pgSQL>, you can instead avoid a conflict by
- qualifying the column or table name.
+ If a name used in a SQL command could be either a column name of a
+ table or a reference to a variable of the function,
+
PL/SQL> treats it as a column name, while
+ <application>PL/pgSQL> treats it as a variable name. It's best
+ to avoid such ambiguities in the first place, but if necessary you
+ can fix them by properly qualifying the ambiguous name.
(See .)
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.103 2007/07/15 02:15:04 tgl Exp $
+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.104 2007/07/16 17:01:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
plpgsql_ns_rename($2, $4);
}
| decl_varname opt_scrollable K_CURSOR
- { plpgsql_ns_push(NULL); }
+ { plpgsql_ns_push($1.name); }
decl_cursor_args decl_is_for decl_cursor_query
{
PLpgSQL_var *new;
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.116 2007/06/26 16:48:09 alvherre Exp $
+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.117 2007/07/16 17:01:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
error_context_stack = &plerrcontext;
/*
- * Initialize the compiler
+ * Initialize the compiler, particularly the namespace stack. The
+ * outermost namespace contains function parameters and other special
+ * variables (such as FOUND), and is named after the function itself.
*/
plpgsql_ns_init();
- plpgsql_ns_push(NULL);
+ plpgsql_ns_push(NameStr(procStruct->proname));
plpgsql_DumpExecTree = false;
datums_alloc = 128;
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.60 2007/07/15 02:15:04 tgl Exp $
+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.61 2007/07/16 17:01:11 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* ----------
*/
void
-plpgsql_ns_push(char *label)
+plpgsql_ns_push(const char *label)
{
PLpgSQL_ns *new;
if (label == NULL)
label = "";
- new = palloc(sizeof(PLpgSQL_ns));
- memset(new, 0, sizeof(PLpgSQL_ns));
+ new = palloc0(sizeof(PLpgSQL_ns));
new->upper = ns_current;
ns_current = new;
* ----------
*/
PLpgSQL_nsitem *
-plpgsql_ns_lookup(char *name, char *label)
+plpgsql_ns_lookup(const char *name, const char *label)
{
PLpgSQL_ns *ns;
int i;
{
for (ns = ns_current; ns != NULL; ns = ns->upper)
{
- if (!strcmp(ns->items[0]->name, label))
+ if (strcmp(ns->items[0]->name, label) == 0)
{
for (i = 1; i < ns->items_used; i++)
{
- if (!strcmp(ns->items[i]->name, name))
+ if (strcmp(ns->items[i]->name, name) == 0)
return ns->items[i];
}
return NULL; /* name not found in specified label */
*/
for (ns = ns_current; ns != NULL; ns = ns->upper)
{
- if (!strcmp(ns->items[0]->name, name))
+ if (strcmp(ns->items[0]->name, name) == 0)
return ns->items[0];
}
{
for (i = 1; i < ns->items_used; i++)
{
- if (!strcmp(ns->items[i]->name, name))
+ if (strcmp(ns->items[i]->name, name) == 0)
return ns->items[i];
}
if (ns_localmode)
int i;
/*
- * Lookup name in the namestack; do the lookup in the current namespace
- * only.
+ * Lookup name in the namestack
*/
for (ns = ns_current; ns != NULL; ns = ns->upper)
{
for (i = 1; i < ns->items_used; i++)
{
- if (!strcmp(ns->items[i]->name, oldname))
+ if (strcmp(ns->items[i]->name, oldname) == 0)
{
newitem = palloc(sizeof(PLpgSQL_nsitem) + strlen(newname));
newitem->itemtype = ns->items[i]->itemtype;
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.89 2007/07/15 02:15:04 tgl Exp $
+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.90 2007/07/16 17:01:11 tgl Exp $
*
*-------------------------------------------------------------------------
*/
*/
extern void plpgsql_ns_init(void);
extern bool plpgsql_ns_setlocal(bool flag);
-extern void plpgsql_ns_push(char *label);
+extern void plpgsql_ns_push(const char *label);
extern void plpgsql_ns_pop(void);
extern void plpgsql_ns_additem(int itemtype, int itemno, const char *name);
-extern PLpgSQL_nsitem *plpgsql_ns_lookup(char *name, char *nsname);
+extern PLpgSQL_nsitem *plpgsql_ns_lookup(const char *name, const char *nsname);
extern void plpgsql_ns_rename(char *oldname, char *newname);
/* ----------
(3 rows)
drop function sc_test();
+-- test qualified variable names
+create function pl_qual_names (param1 int) returns void as $$
+<>
+declare
+ param1 int := 1;
+begin
+ <>
+ declare
+ param1 int := 2;
+ begin
+ raise notice 'param1 = %', param1;
+ raise notice 'pl_qual_names.param1 = %', pl_qual_names.param1;
+ raise notice 'outerblock.param1 = %', outerblock.param1;
+ raise notice 'innerblock.param1 = %', innerblock.param1;
+ end;
+end;
+$$ language plpgsql;
+select pl_qual_names(42);
+NOTICE: param1 = 2
+NOTICE: pl_qual_names.param1 = 42
+NOTICE: outerblock.param1 = 1
+NOTICE: innerblock.param1 = 2
+ pl_qual_names
+---------------
+
+(1 row)
+
+drop function pl_qual_names(int);
drop function sc_test();
+-- test qualified variable names
+
+create function pl_qual_names (param1 int) returns void as $$
+<>
+declare
+ param1 int := 1;
+begin
+ <>
+ declare
+ param1 int := 2;
+ begin
+ raise notice 'param1 = %', param1;
+ raise notice 'pl_qual_names.param1 = %', pl_qual_names.param1;
+ raise notice 'outerblock.param1 = %', outerblock.param1;
+ raise notice 'innerblock.param1 = %', innerblock.param1;
+ end;
+end;
+$$ language plpgsql;
+
+select pl_qual_names(42);
+
+drop function pl_qual_names(int);