mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-31 00:03:57 -04:00 
			
		
		
		
	Fix plpython to generate separate cached procedure data for each
relation, when the same function is used as a trigger on more than one relation. This avoids crashes due to differing rowtypes for different relations. Per bug report from Lance Thomas, 7-Feb-03.
This commit is contained in:
		
							parent
							
								
									efebe2605e
								
							
						
					
					
						commit
						96e63199f3
					
				| @ -29,7 +29,7 @@ | |||||||
|  * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |  * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | ||||||
|  * |  * | ||||||
|  * IDENTIFICATION |  * IDENTIFICATION | ||||||
|  *	$Header: /cvsroot/pgsql/src/pl/plpython/plpython.c,v 1.39 2003/08/04 18:40:50 tgl Exp $ |  *	$Header: /cvsroot/pgsql/src/pl/plpython/plpython.c,v 1.40 2003/09/14 17:13:06 tgl Exp $ | ||||||
|  * |  * | ||||||
|  ********************************************************************* |  ********************************************************************* | ||||||
|  */ |  */ | ||||||
| @ -224,13 +224,11 @@ static HeapTuple PLy_modify_tuple(PLyProcedure *, PyObject *, | |||||||
| 
 | 
 | ||||||
| static PyObject *PLy_procedure_call(PLyProcedure *, char *, PyObject *); | static PyObject *PLy_procedure_call(PLyProcedure *, char *, PyObject *); | ||||||
| 
 | 
 | ||||||
| /* returns a cached PLyProcedure, or creates, stores and returns
 | static PLyProcedure *PLy_procedure_get(FunctionCallInfo fcinfo, | ||||||
|  * a new PLyProcedure. | 									   Oid tgreloid); | ||||||
|  */ |  | ||||||
| static PLyProcedure *PLy_procedure_get(FunctionCallInfo fcinfo, bool); |  | ||||||
| 
 | 
 | ||||||
| static PLyProcedure *PLy_procedure_create(FunctionCallInfo fcinfo, | static PLyProcedure *PLy_procedure_create(FunctionCallInfo fcinfo, | ||||||
| 					 bool is_trigger, | 					 Oid tgreloid, | ||||||
| 					 HeapTuple procTup, char *key); | 					 HeapTuple procTup, char *key); | ||||||
| 
 | 
 | ||||||
| static void PLy_procedure_compile(PLyProcedure *, const char *); | static void PLy_procedure_compile(PLyProcedure *, const char *); | ||||||
| @ -326,7 +324,6 @@ plpython_call_handler(PG_FUNCTION_ARGS) | |||||||
| { | { | ||||||
| 	DECLARE_EXC(); | 	DECLARE_EXC(); | ||||||
| 	Datum		retval; | 	Datum		retval; | ||||||
| 	volatile bool is_trigger; |  | ||||||
| 	PLyProcedure *volatile proc = NULL; | 	PLyProcedure *volatile proc = NULL; | ||||||
| 
 | 
 | ||||||
| 	enter(); | 	enter(); | ||||||
| @ -337,7 +334,6 @@ plpython_call_handler(PG_FUNCTION_ARGS) | |||||||
| 		elog(ERROR, "could not connect to SPI manager"); | 		elog(ERROR, "could not connect to SPI manager"); | ||||||
| 
 | 
 | ||||||
| 	CALL_LEVEL_INC(); | 	CALL_LEVEL_INC(); | ||||||
| 	is_trigger = CALLED_AS_TRIGGER(fcinfo); |  | ||||||
| 
 | 
 | ||||||
| 	SAVE_EXC(); | 	SAVE_EXC(); | ||||||
| 	if (TRAP_EXC()) | 	if (TRAP_EXC()) | ||||||
| @ -364,16 +360,21 @@ plpython_call_handler(PG_FUNCTION_ARGS) | |||||||
| 	 * PLy_restart_in_progress); | 	 * PLy_restart_in_progress); | ||||||
| 	 */ | 	 */ | ||||||
| 
 | 
 | ||||||
| 	proc = PLy_procedure_get(fcinfo, is_trigger); | 	if (CALLED_AS_TRIGGER(fcinfo)) | ||||||
| 
 |  | ||||||
| 	if (is_trigger) |  | ||||||
| 	{ | 	{ | ||||||
| 		HeapTuple	trv = PLy_trigger_handler(fcinfo, proc); | 		TriggerData *tdata = (TriggerData *) fcinfo->context; | ||||||
|  | 		HeapTuple	trv; | ||||||
| 
 | 
 | ||||||
|  | 		proc = PLy_procedure_get(fcinfo, | ||||||
|  | 								 RelationGetRelid(tdata->tg_relation)); | ||||||
|  | 		trv = PLy_trigger_handler(fcinfo, proc); | ||||||
| 		retval = PointerGetDatum(trv); | 		retval = PointerGetDatum(trv); | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
|  | 	{ | ||||||
|  | 		proc = PLy_procedure_get(fcinfo, InvalidOid); | ||||||
| 		retval = PLy_function_handler(fcinfo, proc); | 		retval = PLy_function_handler(fcinfo, proc); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	CALL_LEVEL_DEC(); | 	CALL_LEVEL_DEC(); | ||||||
| 	RESTORE_EXC(); | 	RESTORE_EXC(); | ||||||
| @ -962,10 +963,17 @@ PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure * proc) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* PLyProcedure functions
 | /*
 | ||||||
|  |  * PLyProcedure functions | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | /* PLy_procedure_get: returns a cached PLyProcedure, or creates, stores and
 | ||||||
|  |  * returns a new PLyProcedure.  fcinfo is the call info, tgreloid is the | ||||||
|  |  * relation OID when calling a trigger, or InvalidOid (zero) for ordinary | ||||||
|  |  * function calls. | ||||||
|  */ |  */ | ||||||
| static PLyProcedure * | static PLyProcedure * | ||||||
| PLy_procedure_get(FunctionCallInfo fcinfo, bool is_trigger) | PLy_procedure_get(FunctionCallInfo fcinfo, Oid tgreloid) | ||||||
| { | { | ||||||
| 	Oid			fn_oid; | 	Oid			fn_oid; | ||||||
| 	HeapTuple	procTup; | 	HeapTuple	procTup; | ||||||
| @ -983,9 +991,7 @@ PLy_procedure_get(FunctionCallInfo fcinfo, bool is_trigger) | |||||||
| 	if (!HeapTupleIsValid(procTup)) | 	if (!HeapTupleIsValid(procTup)) | ||||||
| 		elog(ERROR, "cache lookup failed for function %u", fn_oid); | 		elog(ERROR, "cache lookup failed for function %u", fn_oid); | ||||||
| 
 | 
 | ||||||
| 	rv = snprintf(key, sizeof(key), "%u%s", | 	rv = snprintf(key, sizeof(key), "%u_%u", fn_oid, tgreloid); | ||||||
| 				  fn_oid, |  | ||||||
| 				  is_trigger ? "_trigger" : ""); |  | ||||||
| 	if ((rv >= sizeof(key)) || (rv < 0)) | 	if ((rv >= sizeof(key)) || (rv < 0)) | ||||||
| 		elog(ERROR, "key too long"); | 		elog(ERROR, "key too long"); | ||||||
| 
 | 
 | ||||||
| @ -1012,7 +1018,7 @@ PLy_procedure_get(FunctionCallInfo fcinfo, bool is_trigger) | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (proc == NULL) | 	if (proc == NULL) | ||||||
| 		proc = PLy_procedure_create(fcinfo, is_trigger, procTup, key); | 		proc = PLy_procedure_create(fcinfo, tgreloid, procTup, key); | ||||||
| 
 | 
 | ||||||
| 	ReleaseSysCache(procTup); | 	ReleaseSysCache(procTup); | ||||||
| 
 | 
 | ||||||
| @ -1020,7 +1026,7 @@ PLy_procedure_get(FunctionCallInfo fcinfo, bool is_trigger) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static PLyProcedure * | static PLyProcedure * | ||||||
| PLy_procedure_create(FunctionCallInfo fcinfo, bool is_trigger, | PLy_procedure_create(FunctionCallInfo fcinfo, Oid tgreloid, | ||||||
| 					 HeapTuple procTup, char *key) | 					 HeapTuple procTup, char *key) | ||||||
| { | { | ||||||
| 	char		procName[NAMEDATALEN + 256]; | 	char		procName[NAMEDATALEN + 256]; | ||||||
| @ -1037,11 +1043,17 @@ PLy_procedure_create(FunctionCallInfo fcinfo, bool is_trigger, | |||||||
| 
 | 
 | ||||||
| 	procStruct = (Form_pg_proc) GETSTRUCT(procTup); | 	procStruct = (Form_pg_proc) GETSTRUCT(procTup); | ||||||
| 
 | 
 | ||||||
| 	rv = snprintf(procName, sizeof(procName), | 	if (OidIsValid(tgreloid)) | ||||||
| 				  "__plpython_procedure_%s_%u%s", | 		rv = snprintf(procName, sizeof(procName), | ||||||
| 				  NameStr(procStruct->proname), | 					  "__plpython_procedure_%s_%u_trigger_%u", | ||||||
| 				  fcinfo->flinfo->fn_oid, | 					  NameStr(procStruct->proname), | ||||||
| 				  is_trigger ? "_trigger" : ""); | 					  fcinfo->flinfo->fn_oid, | ||||||
|  | 					  tgreloid); | ||||||
|  | 	else | ||||||
|  | 		rv = snprintf(procName, sizeof(procName), | ||||||
|  | 					  "__plpython_procedure_%s_%u", | ||||||
|  | 					  NameStr(procStruct->proname), | ||||||
|  | 					  fcinfo->flinfo->fn_oid); | ||||||
| 	if ((rv >= sizeof(procName)) || (rv < 0)) | 	if ((rv >= sizeof(procName)) || (rv < 0)) | ||||||
| 		elog(ERROR, "procedure name would overrun buffer"); | 		elog(ERROR, "procedure name would overrun buffer"); | ||||||
| 
 | 
 | ||||||
| @ -1073,7 +1085,7 @@ PLy_procedure_create(FunctionCallInfo fcinfo, bool is_trigger, | |||||||
| 	 * get information required for output conversion of the return value, | 	 * get information required for output conversion of the return value, | ||||||
| 	 * but only if this isn't a trigger. | 	 * but only if this isn't a trigger. | ||||||
| 	 */ | 	 */ | ||||||
| 	if (!is_trigger) | 	if (!CALLED_AS_TRIGGER(fcinfo)) | ||||||
| 	{ | 	{ | ||||||
| 		HeapTuple	rvTypeTup; | 		HeapTuple	rvTypeTup; | ||||||
| 		Form_pg_type rvTypeStruct; | 		Form_pg_type rvTypeStruct; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user