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 the parameters type
434
+ * Get the parameter 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_word The scanner calls this to postparse
735
786
* any single word not found by a
0 commit comments