3
3
* procedural language
4
4
*
5
5
* IDENTIFICATION
6
- * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.71 2004/01/06 23:55:19 tgl Exp $
6
+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.72 2004/01/07 06:20:02 tgl Exp $
7
7
*
8
8
* This software is copyrighted by Jan Wieck - Hamburg.
9
9
*
54
54
#include "parser/gramparse.h"
55
55
#include "parser/parse_type.h"
56
56
#include "tcop/tcopprot.h"
57
+ #include "utils/array.h"
57
58
#include "utils/builtins.h"
58
59
#include "utils/syscache.h"
59
60
@@ -102,6 +103,7 @@ static PLpgSQL_function *do_compile(FunctionCallInfo fcinfo,
102
103
HeapTuple procTup ,
103
104
PLpgSQL_func_hashkey * hashkey );
104
105
static void plpgsql_compile_error_callback (void * arg );
106
+ static char * * fetchArgNames (HeapTuple procTup ,int nargs );
105
107
static PLpgSQL_type * build_datatype (HeapTuple typeTup ,int32 typmod );
106
108
static void compute_function_hashkey (FunctionCallInfo fcinfo ,
107
109
Form_pg_proc procStruct ,
@@ -248,6 +250,7 @@ do_compile(FunctionCallInfo fcinfo,
248
250
ErrorContextCallback plerrcontext ;
249
251
int parse_rc ;
250
252
Oid rettypeid ;
253
+ char * * argnames ;
251
254
252
255
/*
253
256
* Setup the scanner input and error info.We assume that this
@@ -408,12 +411,16 @@ do_compile(FunctionCallInfo fcinfo,
408
411
/*
409
412
* Create the variables for the procedure's parameters
410
413
*/
414
+ argnames = fetchArgNames (procTup ,procStruct -> pronargs );
415
+
411
416
for (i = 0 ;i < procStruct -> pronargs ;i ++ )
412
417
{
413
418
char buf [32 ];
414
419
Oid argtypeid ;
420
+ PLpgSQL_datum * argdatum ;
421
+ int argitemtype ;
415
422
416
- /* name for variable */
423
+ /*Create $n name for variable */
417
424
snprintf (buf ,sizeof (buf ),"$%d" ,i + 1 );
418
425
419
426
/*
@@ -424,7 +431,7 @@ do_compile(FunctionCallInfo fcinfo,
424
431
argtypeid = hashkey -> argtypes [i ];
425
432
426
433
/*
427
- * Get theparameters type
434
+ * Get theparameter type
428
435
*/
429
436
typeTup = SearchSysCache (TYPEOID ,
430
437
ObjectIdGetDatum (argtypeid ),
@@ -448,14 +455,10 @@ do_compile(FunctionCallInfo fcinfo,
448
455
* that type
449
456
*/
450
457
row = plpgsql_build_rowtype (typeStruct -> typrelid );
451
-
452
458
row -> refname = strdup (buf );
453
459
454
- plpgsql_adddatum ((PLpgSQL_datum * )row );
455
- plpgsql_ns_additem (PLPGSQL_NSTYPE_ROW ,row -> rowno ,
456
- row -> refname );
457
-
458
- arg_varnos [i ]= row -> rowno ;
460
+ argdatum = (PLpgSQL_datum * )row ;
461
+ argitemtype = PLPGSQL_NSTYPE_ROW ;
459
462
}
460
463
else
461
464
{
@@ -473,12 +476,22 @@ do_compile(FunctionCallInfo fcinfo,
473
476
var -> notnull = false;
474
477
var -> default_val = NULL ;
475
478
476
- plpgsql_adddatum ((PLpgSQL_datum * )var );
477
- plpgsql_ns_additem (PLPGSQL_NSTYPE_VAR ,var -> varno ,
478
- var -> refname );
479
-
480
- arg_varnos [i ]= var -> varno ;
479
+ argdatum = (PLpgSQL_datum * )var ;
480
+ argitemtype = PLPGSQL_NSTYPE_VAR ;
481
481
}
482
+
483
+ /* Add it to datum list, and remember datum number */
484
+ plpgsql_adddatum (argdatum );
485
+ arg_varnos [i ]= argdatum -> dno ;
486
+
487
+ /* Add to namespace under the $n name */
488
+ plpgsql_ns_additem (argitemtype ,argdatum -> dno ,buf );
489
+
490
+ /* If there's a name for the argument, make an alias */
491
+ if (argnames && argnames [i ]&& argnames [i ][0 ])
492
+ plpgsql_ns_additem (argitemtype ,argdatum -> dno ,
493
+ argnames [i ]);
494
+
482
495
ReleaseSysCache (typeTup );
483
496
}
484
497
break ;
@@ -730,6 +743,44 @@ plpgsql_compile_error_callback(void *arg)
730
743
}
731
744
732
745
746
+ /*
747
+ * Fetch the argument names, if any, from the proargnames field of the
748
+ * pg_proc tuple. Results are palloc'd.
749
+ */
750
+ static char * *
751
+ fetchArgNames (HeapTuple procTup ,int nargs )
752
+ {
753
+ Datum argnamesDatum ;
754
+ bool isNull ;
755
+ Datum * elems ;
756
+ int nelems ;
757
+ char * * result ;
758
+ int i ;
759
+
760
+ if (nargs == 0 )
761
+ return NULL ;
762
+
763
+ argnamesDatum = SysCacheGetAttr (PROCOID ,procTup ,Anum_pg_proc_proargnames ,
764
+ & isNull );
765
+ if (isNull )
766
+ return NULL ;
767
+
768
+ deconstruct_array (DatumGetArrayTypeP (argnamesDatum ),
769
+ TEXTOID ,-1 , false,'i' ,
770
+ & elems ,& nelems );
771
+
772
+ if (nelems != nargs )/* should not happen */
773
+ elog (ERROR ,"proargnames must have the same number of elements as the function has arguments" );
774
+
775
+ result = (char * * )palloc (sizeof (char * )* nargs );
776
+
777
+ for (i = 0 ;i < nargs ;i ++ )
778
+ result [i ]= DatumGetCString (DirectFunctionCall1 (textout ,elems [i ]));
779
+
780
+ return result ;
781
+ }
782
+
783
+
733
784
/* ----------
734
785
* plpgsql_parse_wordThe scanner calls this to postparse
735
786
*any single word not found by a