Before this patch, pl/python will not do the right thing if OUT
parameters are present

----------------
Hannu

Index: plpython/plpython.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/pl/plpython/plpython.c,v
retrieving revision 1.106
diff -c -r1.106 plpython.c
*** plpython/plpython.c	2 Jan 2008 03:10:27 -0000	1.106
--- plpython/plpython.c	29 Apr 2008 20:40:53 -0000
***************
*** 1159,1167 ****
  	bool		isnull;
  	int			i,
  				rv;
- 	Datum		argnames;
- 	Datum	   *elems;
- 	int			nelems;
  
  	procStruct = (Form_pg_proc) GETSTRUCT(procTup);
  
--- 1159,1164 ----
***************
*** 1250,1304 ****
  		 * now get information required for input conversion of the
  		 * procedure's arguments.
  		 */
! 		proc->nargs = procStruct->pronargs;
! 		if (proc->nargs)
! 		{
! 			argnames = SysCacheGetAttr(PROCOID, procTup, Anum_pg_proc_proargnames, &isnull);
! 			if (!isnull)
! 			{
! 				/* XXX this code is WRONG if there are any output arguments */
! 				deconstruct_array(DatumGetArrayTypeP(argnames), TEXTOID, -1, false, 'i',
! 								  &elems, NULL, &nelems);
! 				if (nelems != proc->nargs)
! 					elog(ERROR,
! 						 "proargnames must have the same number of elements "
! 						 "as the function has arguments");
! 				proc->argnames = (char **) PLy_malloc(sizeof(char *) * proc->nargs);
! 				memset(proc->argnames, 0, sizeof(char *) * proc->nargs);
! 			}
! 		}
! 		for (i = 0; i < proc->nargs; i++)
! 		{
  			HeapTuple	argTypeTup;
  			Form_pg_type argTypeStruct;
  
! 			argTypeTup = SearchSysCache(TYPEOID,
! 						 ObjectIdGetDatum(procStruct->proargtypes.values[i]),
! 										0, 0, 0);
! 			if (!HeapTupleIsValid(argTypeTup))
! 				elog(ERROR, "cache lookup failed for type %u",
! 					 procStruct->proargtypes.values[i]);
! 			argTypeStruct = (Form_pg_type) GETSTRUCT(argTypeTup);
  
! 			/* Disallow pseudotype argument */
! 			if (argTypeStruct->typtype == TYPTYPE_PSEUDO)
! 				ereport(ERROR,
! 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
! 						 errmsg("plpython functions cannot take type %s",
! 						format_type_be(procStruct->proargtypes.values[i]))));
! 
! 			if (argTypeStruct->typtype != TYPTYPE_COMPOSITE)
! 				PLy_input_datum_func(&(proc->args[i]),
! 									 procStruct->proargtypes.values[i],
! 									 argTypeTup);
! 			else
! 				proc->args[i].is_rowtype = 2;	/* still need to set I/O funcs */
  
! 			ReleaseSysCache(argTypeTup);
  
! 			/* Fetch argument name */
! 			if (proc->argnames)
! 				proc->argnames[i] = PLy_strdup(DatumGetCString(DirectFunctionCall1(textout, elems[i])));
  		}
  
  		/*
--- 1247,1309 ----
  		 * now get information required for input conversion of the
  		 * procedure's arguments.
  		 */
! 
! 		if (procStruct->pronargs) {
  			HeapTuple	argTypeTup;
  			Form_pg_type argTypeStruct;
  
! 			Oid		*types;
! 			char   **names,
! 					*modes;
! 			int		 i,
! 					 pos,
! 					 total;
! 
! 			total = get_func_arg_info(procTup, &types, &names, &modes);
! 			if (modes == NULL) 
! 				proc->nargs = procStruct->pronargs;
! 			else 
! 			/* count number of 'i?' args into proc->nargs*/
! 				for (i = 0;i < total;i++) {
! 					if (modes[i] != 'o') (proc->nargs)++;
! 				}
  
! 			proc->argnames = (char **) PLy_malloc(sizeof(char *) * proc->nargs);
! 			for (i = pos = 0;i < total;i++) {
! 				if (modes && modes[i] == 'o') /* skip OUT arguments */
! 					continue;
! 
! 				Assert(types[i] == procStruct->proargtypes.values[i]);
! 
! 				argTypeTup = SearchSysCache(TYPEOID,ObjectIdGetDatum(types[i]), 0, 0, 0);
! 				if (!HeapTupleIsValid(argTypeTup))
! 					elog(ERROR, "cache lookup failed for type %u",
! 						 procStruct->proargtypes.values[i]);
! 				argTypeStruct = (Form_pg_type) GETSTRUCT(argTypeTup);
! 
! 				switch (argTypeStruct->typtype) {
! 					case TYPTYPE_PSEUDO:
! 						ereport(ERROR,
! 								(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
! 								 errmsg("plpython functions cannot take type %s",
! 								 format_type_be(types[i]))));
! 					case TYPTYPE_COMPOSITE:
! 						proc->args[pos].is_rowtype = 2; /* set IO funcs at first call*/
! 						break;
! 					default:
! 						PLy_input_datum_func(&(proc->args[pos]),
! 											 types[i],
! 											 argTypeTup);
! 				}
  
! 				ReleaseSysCache(argTypeTup);
  
! 				/* get argument name */
! 				proc->argnames[pos] = names ? PLy_strdup(names[i]) : NULL; 
! 
! 				pos++;
! 
! 			}
  		}
  
  		/*
Index: plpython/expected/plpython_function.out
===================================================================
RCS file: /projects/cvsroot/pgsql/src/pl/plpython/expected/plpython_function.out,v
retrieving revision 1.10
diff -c -r1.10 plpython_function.out
*** plpython/expected/plpython_function.out	16 Oct 2006 21:13:57 -0000	1.10
--- plpython/expected/plpython_function.out	29 Apr 2008 20:40:59 -0000
***************
*** 436,438 ****
--- 436,447 ----
  	type_record.second = second
  	return type_record
  $$ LANGUAGE plpythonu;
+ CREATE FUNCTION test_in_out_params(first in text, second out text) AS $$
+ return first + '_in_to_out';
+ $$ LANGUAGE plpythonu;
+ CREATE FUNCTION test_in_out_params_record(first in text, second out text) RETURNS text AS $$
+ return first + '_record_in_to_out';
+ $$ LANGUAGE plpythonu;
+ CREATE FUNCTION test_inout_params(first inout text) AS $$
+ return first + '_inout';
+ $$ LANGUAGE plpythonu;
Index: plpython/expected/plpython_test.out
===================================================================
RCS file: /projects/cvsroot/pgsql/src/pl/plpython/expected/plpython_test.out,v
retrieving revision 1.5
diff -c -r1.5 plpython_test.out
*** plpython/expected/plpython_test.out	2 Sep 2006 12:30:01 -0000	1.5
--- plpython/expected/plpython_test.out	29 Apr 2008 20:41:00 -0000
***************
*** 539,541 ****
--- 539,559 ----
         |       
  (1 row)
  
+ SELECT * FROM test_in_out_params('test_in');
+       second       
+ -------------------
+  test_in_in_to_out
+ (1 row)
+ 
+ SELECT * FROM test_in_out_params_record('test_in');
+           second          
+ --------------------------
+  test_in_record_in_to_out
+ (1 row)
+ 
+ SELECT * FROM test_inout_params('test_in');
+      first     
+ ---------------
+  test_in_inout
+ (1 row)
+ 
Index: plpython/sql/plpython_function.sql
===================================================================
RCS file: /projects/cvsroot/pgsql/src/pl/plpython/sql/plpython_function.sql,v
retrieving revision 1.10
diff -c -r1.10 plpython_function.sql
*** plpython/sql/plpython_function.sql	16 Oct 2006 21:13:57 -0000	1.10
--- plpython/sql/plpython_function.sql	29 Apr 2008 20:41:02 -0000
***************
*** 480,482 ****
--- 480,494 ----
  	return type_record
  $$ LANGUAGE plpythonu;
  
+ CREATE FUNCTION test_in_out_params(first in text, second out text) AS $$
+ return first + '_in_to_out';
+ $$ LANGUAGE plpythonu;
+ 
+ CREATE FUNCTION test_in_out_params_record(first in text, second out text) RETURNS text AS $$
+ return first + '_record_in_to_out';
+ $$ LANGUAGE plpythonu;
+ 
+ CREATE FUNCTION test_inout_params(first inout text) AS $$
+ return first + '_inout';
+ $$ LANGUAGE plpythonu;
+ 
Index: plpython/sql/plpython_test.sql
===================================================================
RCS file: /projects/cvsroot/pgsql/src/pl/plpython/sql/plpython_test.sql,v
retrieving revision 1.3
diff -c -r1.3 plpython_test.sql
*** plpython/sql/plpython_test.sql	2 Sep 2006 12:30:01 -0000	1.3
--- plpython/sql/plpython_test.sql	29 Apr 2008 20:41:02 -0000
***************
*** 143,145 ****
--- 143,152 ----
  SELECT * FROM test_type_record_as('obj', null, 2, false);
  SELECT * FROM test_type_record_as('obj', 'three', 3, false);
  SELECT * FROM test_type_record_as('obj', null, null, true);
+ 
+ SELECT * FROM test_in_out_params('test_in');
+ SELECT * FROM test_in_out_params_record('test_in');
+ SELECT * FROM test_inout_params('test_in');
+ 
+ 
+ 
-- 
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches

Reply via email to