1 /*
2  * Python procedure manipulation for plpython
3  *
4  * src/pl/plpython/plpy_procedure.c
5  */
6 
7 #include "postgres.h"
8 
9 #include "access/htup_details.h"
10 #include "access/transam.h"
11 #include "funcapi.h"
12 #include "catalog/pg_proc.h"
13 #include "catalog/pg_type.h"
14 #include "utils/builtins.h"
15 #include "utils/hsearch.h"
16 #include "utils/inval.h"
17 #include "utils/lsyscache.h"
18 #include "utils/memutils.h"
19 #include "utils/syscache.h"
20 
21 #include "plpython.h"
22 
23 #include "plpy_procedure.h"
24 
25 #include "plpy_elog.h"
26 #include "plpy_main.h"
27 
28 
29 static HTAB *PLy_procedure_cache = NULL;
30 
31 static PLyProcedure *PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger);
32 static bool PLy_procedure_valid(PLyProcedure *proc, HeapTuple procTup);
33 static char *PLy_procedure_munge_source(const char *name, const char *src);
34 
35 
36 void
37 init_procedure_caches(void)
38 {
39 	HASHCTL		hash_ctl;
40 
41 	memset(&hash_ctl, 0, sizeof(hash_ctl));
42 	hash_ctl.keysize = sizeof(PLyProcedureKey);
43 	hash_ctl.entrysize = sizeof(PLyProcedureEntry);
44 	PLy_procedure_cache = hash_create("PL/Python procedures", 32, &hash_ctl,
45 									  HASH_ELEM | HASH_BLOBS);
46 }
47 
48 /*
49  * PLy_procedure_name: get the name of the specified procedure.
50  *
51  * NB: this returns the SQL name, not the internal Python procedure name
52  */
53 char *
54 PLy_procedure_name(PLyProcedure *proc)
55 {
56 	if (proc == NULL)
57 		return "<unknown procedure>";
58 	return proc->proname;
59 }
has_focus(&self) -> bool60 
61 /*
62  * PLy_procedure_get: returns a cached PLyProcedure, or creates, stores and
63  * returns a new PLyProcedure.
64  *
65  * fn_oid is the OID of the function requested
66  * fn_rel is InvalidOid or the relation this function triggers on
67  * is_trigger denotes whether the function is a trigger function
68  *
69  * The reason that both fn_rel and is_trigger need to be passed is that when
70  * trigger functions get validated we don't know which relation(s) they'll
71  * be used with, so no sensible fn_rel can be passed.
72  */
73 PLyProcedure *
74 PLy_procedure_get(Oid fn_oid, Oid fn_rel, bool is_trigger)
75 {
76 	bool		use_cache = !(is_trigger && fn_rel == InvalidOid);
77 	HeapTuple	procTup;
78 	PLyProcedureKey key;
79 	PLyProcedureEntry *volatile entry = NULL;
80 	PLyProcedure *volatile proc = NULL;
81 	bool		found = false;
82 
83 	procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(fn_oid));
84 	if (!HeapTupleIsValid(procTup))
85 		elog(ERROR, "cache lookup failed for function %u", fn_oid);
86 
87 	/*
88 	 * Look for the function in the cache, unless we don't have the necessary
89 	 * information (e.g. during validation). In that case we just don't cache
90 	 * anything.
91 	 */
92 	if (use_cache)
93 	{
94 		key.fn_oid = fn_oid;
95 		key.fn_rel = fn_rel;
96 		entry = hash_search(PLy_procedure_cache, &key, HASH_ENTER, &found);
97 		proc = entry->proc;
98 	}
99 
100 	PG_TRY();
101 	{
102 		if (!found)
103 		{
104 			/* Haven't found it, create a new procedure */
105 			proc = PLy_procedure_create(procTup, fn_oid, is_trigger);
106 			if (use_cache)
107 				entry->proc = proc;
108 		}
109 		else if (!PLy_procedure_valid(proc, procTup))
110 		{
111 			/* Found it, but it's invalid, free and reuse the cache entry */
112 			entry->proc = NULL;
113 			if (proc)
114 				PLy_procedure_delete(proc);
115 			proc = PLy_procedure_create(procTup, fn_oid, is_trigger);
116 			entry->proc = proc;
117 		}
118 		/* Found it and it's valid, it's fine to use it */
119 	}
120 	PG_CATCH();
121 	{
122 		/* Do not leave an uninitialized entry in the cache */
123 		if (use_cache)
124 			hash_search(PLy_procedure_cache, &key, HASH_REMOVE, NULL);
125 		PG_RE_THROW();
126 	}
127 	PG_END_TRY();
128 
129 	ReleaseSysCache(procTup);
130 
131 	return proc;
132 }
133 
134 /*
135  * Create a new PLyProcedure structure
136  */
137 static PLyProcedure *
138 PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
139 {
140 	char		procName[NAMEDATALEN + 256];
141 	Form_pg_proc procStruct;
142 	PLyProcedure *volatile proc;
143 	MemoryContext cxt;
144 	MemoryContext oldcxt;
145 	int			rv;
146 	char	   *ptr;
147 
148 	procStruct = (Form_pg_proc) GETSTRUCT(procTup);
149 	rv = snprintf(procName, sizeof(procName),
150 				  "__plpython_procedure_%s_%u",
151 				  NameStr(procStruct->proname),
152 				  fn_oid);
153 	if (rv >= sizeof(procName) || rv < 0)
next_entry_for_deletion(&mut self) -> Option<TreeIndex>154 		elog(ERROR, "procedure name would overrun buffer");
155 
156 	/* Replace any not-legal-in-Python-names characters with '_' */
157 	for (ptr = procName; *ptr; ptr++)
158 	{
159 		if (!((*ptr >= 'A' && *ptr <= 'Z') ||
160 			  (*ptr >= 'a' && *ptr <= 'z') ||
161 			  (*ptr >= '0' && *ptr <= '9')))
162 			*ptr = '_';
163 	}
164 
165 	/* Create long-lived context that all procedure info will live in */
166 	cxt = AllocSetContextCreate(TopMemoryContext,
167 								"PL/Python function",
168 								ALLOCSET_DEFAULT_SIZES);
169 
170 	oldcxt = MemoryContextSwitchTo(cxt);
171 
delete_entry(self) -> Option<Self>172 	proc = (PLyProcedure *) palloc0(sizeof(PLyProcedure));
173 	proc->mcxt = cxt;
174 
set_error_on_marked_item(&mut self, num_errors: usize)175 	PG_TRY();
176 	{
177 		Datum		protrftypes_datum;
178 		Datum		prosrcdatum;
179 		bool		isnull;
180 		char	   *procSource;
181 		int			i;
182 
183 		proc->proname = pstrdup(NameStr(procStruct->proname));
prepare_deletion(mut self, mark: MarkMode) -> (Self, Option<MarkMode>)184 		MemoryContextSetIdentifier(cxt, proc->proname);
185 		proc->pyname = pstrdup(procName);
186 		proc->fn_xmin = HeapTupleHeaderGetRawXmin(procTup->t_data);
187 		proc->fn_tid = procTup->t_self;
188 		proc->fn_readonly = (procStruct->provolatile != PROVOLATILE_VOLATILE);
189 		proc->is_setof = procStruct->proretset;
190 		proc->is_procedure = (procStruct->prokind == PROKIND_PROCEDURE);
remove_selected(mut self) -> Option<Self>191 		proc->src = NULL;
192 		proc->argnames = NULL;
193 		proc->args = NULL;
194 		proc->nargs = 0;
195 		proc->langid = procStruct->prolang;
196 		protrftypes_datum = SysCacheGetAttr(PROCOID, procTup,
197 											Anum_pg_proc_protrftypes,
198 											&isnull);
199 		proc->trftypes = isnull ? NIL : oid_array_to_list(protrftypes_datum);
200 		proc->code = NULL;
201 		proc->statics = NULL;
202 		proc->globals = NULL;
203 		proc->calldepth = 0;
204 		proc->argstack = NULL;
205 
206 		/*
207 		 * get information required for output conversion of the return value,
208 		 * but only if this isn't a trigger.
209 		 */
tree_index_by_list_position(&mut self, selected: usize) -> Option<TreeIndex>210 		if (!is_trigger)
211 		{
212 			Oid			rettype = procStruct->prorettype;
213 			HeapTuple	rvTypeTup;
214 			Form_pg_type rvTypeStruct;
215 
216 			rvTypeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(rettype));
217 			if (!HeapTupleIsValid(rvTypeTup))
218 				elog(ERROR, "cache lookup failed for type %u", rettype);
219 			rvTypeStruct = (Form_pg_type) GETSTRUCT(rvTypeTup);
220 
221 			/* Disallow pseudotype result, except for void or record */
222 			if (rvTypeStruct->typtype == TYPTYPE_PSEUDO)
223 			{
224 				if (rettype == VOIDOID ||
225 					rettype == RECORDOID)
226 					 /* okay */ ;
227 				else if (rettype == TRIGGEROID || rettype == EVTTRIGGEROID)
228 					ereport(ERROR,
229 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
230 							 errmsg("trigger functions can only be called as triggers")));
231 				else
232 					ereport(ERROR,
233 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
234 							 errmsg("PL/Python functions cannot return type %s",
235 									format_type_be(rettype))));
236 			}
237 
238 			/* set up output function for procedure result */
239 			PLy_output_setup_func(&proc->result, proc->mcxt,
240 								  rettype, -1, proc);
241 
242 			ReleaseSysCache(rvTypeTup);
243 		}
244 		else
245 		{
246 			/*
247 			 * In a trigger function, we use proc->result and proc->result_in
248 			 * for converting tuples, but we don't yet have enough info to set
249 			 * them up.  PLy_exec_trigger will deal with it.
250 			 */
251 			proc->result.typoid = InvalidOid;
252 			proc->result_in.typoid = InvalidOid;
253 		}
254 
255 		/*
256 		 * Now get information required for input conversion of the
257 		 * procedure's arguments.  Note that we ignore output arguments here.
258 		 * If the function returns record, those I/O functions will be set up
259 		 * when the function is first called.
260 		 */
261 		if (procStruct->pronargs)
262 		{
263 			Oid		   *types;
264 			char	  **names,
265 					   *modes;
266 			int			pos,
267 						total;
268 
269 			/* extract argument type info from the pg_proc tuple */
270 			total = get_func_arg_info(procTup, &types, &names, &modes);
271 
272 			/* count number of in+inout args into proc->nargs */
273 			if (modes == NULL)
274 				proc->nargs = total;
275 			else
276 			{
277 				/* proc->nargs was initialized to 0 above */
278 				for (i = 0; i < total; i++)
279 				{
280 					if (modes[i] != PROARGMODE_OUT &&
281 						modes[i] != PROARGMODE_TABLE)
282 						(proc->nargs)++;
283 				}
284 			}
285 
286 			/* Allocate arrays for per-input-argument data */
287 			proc->argnames = (char **) palloc0(sizeof(char *) * proc->nargs);
288 			proc->args = (PLyDatumToOb *) palloc0(sizeof(PLyDatumToOb) * proc->nargs);
289 
290 			for (i = pos = 0; i < total; i++)
291 			{
292 				HeapTuple	argTypeTup;
293 				Form_pg_type argTypeStruct;
294 
295 				if (modes &&
296 					(modes[i] == PROARGMODE_OUT ||
297 					 modes[i] == PROARGMODE_TABLE))
298 					continue;	/* skip OUT arguments */
299 
300 				Assert(types[i] == procStruct->proargtypes.values[pos]);
301 
302 				argTypeTup = SearchSysCache1(TYPEOID,
303 											 ObjectIdGetDatum(types[i]));
304 				if (!HeapTupleIsValid(argTypeTup))
305 					elog(ERROR, "cache lookup failed for type %u", types[i]);
306 				argTypeStruct = (Form_pg_type) GETSTRUCT(argTypeTup);
307 
308 				/* disallow pseudotype arguments */
309 				if (argTypeStruct->typtype == TYPTYPE_PSEUDO)
310 					ereport(ERROR,
311 							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
312 							 errmsg("PL/Python functions cannot accept type %s",
313 									format_type_be(types[i]))));
314 
315 				/* set up I/O function info */
316 				PLy_input_setup_func(&proc->args[pos], proc->mcxt,
317 									 types[i], -1,	/* typmod not known */
318 									 proc);
319 
320 				/* get argument name */
321 				proc->argnames[pos] = names ? pstrdup(names[i]) : NULL;
322 
323 				ReleaseSysCache(argTypeTup);
324 
325 				pos++;
326 			}
327 		}
328 
329 		/*
330 		 * get the text of the function.
331 		 */
332 		prosrcdatum = SysCacheGetAttr(PROCOID, procTup,
333 									  Anum_pg_proc_prosrc, &isnull);
334 		if (isnull)
335 			elog(ERROR, "null prosrc");
336 		procSource = TextDatumGetCString(prosrcdatum);
337 
338 		PLy_procedure_compile(proc, procSource);
339 
340 		pfree(procSource);
341 	}
342 	PG_CATCH();
343 	{
344 		MemoryContextSwitchTo(oldcxt);
345 		PLy_procedure_delete(proc);
346 		PG_RE_THROW();
347 	}
348 	PG_END_TRY();
349 
350 	MemoryContextSwitchTo(oldcxt);
351 	return proc;
352 }
353 
354 /*
355  * Insert the procedure into the Python interpreter
356  */
357 void
358 PLy_procedure_compile(PLyProcedure *proc, const char *src)
359 {
360 	PyObject   *crv = NULL;
361 	char	   *msrc;
362 
363 	proc->globals = PyDict_Copy(PLy_interp_globals);
364 
365 	/*
366 	 * SD is private preserved data between calls. GD is global data shared by
367 	 * all functions
368 	 */
369 	proc->statics = PyDict_New();
370 	if (!proc->statics)
371 		PLy_elog(ERROR, NULL);
372 	PyDict_SetItemString(proc->globals, "SD", proc->statics);
373 
374 	/*
375 	 * insert the function code into the interpreter
376 	 */
377 	msrc = PLy_procedure_munge_source(proc->pyname, src);
378 	/* Save the mangled source for later inclusion in tracebacks */
379 	proc->src = MemoryContextStrdup(proc->mcxt, msrc);
380 	crv = PyRun_String(msrc, Py_file_input, proc->globals, NULL);
381 	pfree(msrc);
382 
383 	if (crv != NULL)
384 	{
385 		int			clen;
386 		char		call[NAMEDATALEN + 256];
387 
388 		Py_DECREF(crv);
389 
390 		/*
391 		 * compile a call to the function
392 		 */
393 		clen = snprintf(call, sizeof(call), "%s()", proc->pyname);
394 		if (clen < 0 || clen >= sizeof(call))
395 			elog(ERROR, "string would overflow buffer");
396 		proc->code = Py_CompileString(call, "<string>", Py_eval_input);
397 		if (proc->code != NULL)
398 			return;
399 	}
400 
401 	if (proc->proname)
402 		PLy_elog(ERROR, "could not compile PL/Python function \"%s\"",
403 				 proc->proname);
404 	else
405 		PLy_elog(ERROR, "could not compile anonymous PL/Python code block");
406 }
407 
408 void
409 PLy_procedure_delete(PLyProcedure *proc)
410 {
411 	Py_XDECREF(proc->code);
412 	Py_XDECREF(proc->statics);
413 	Py_XDECREF(proc->globals);
414 	MemoryContextDelete(proc->mcxt);
415 }
416 
417 /*
418  * Decide whether a cached PLyProcedure struct is still valid
419  */
420 static bool
421 PLy_procedure_valid(PLyProcedure *proc, HeapTuple procTup)
422 {
423 	if (proc == NULL)
424 		return false;
425 
426 	/* If the pg_proc tuple has changed, it's not valid */
427 	if (!(proc->fn_xmin == HeapTupleHeaderGetRawXmin(procTup->t_data) &&
428 		  ItemPointerEquals(&proc->fn_tid, &procTup->t_self)))
429 		return false;
430 
431 	return true;
432 }
433 
434 static char *
435 PLy_procedure_munge_source(const char *name, const char *src)
436 {
437 	char	   *mrc,
438 			   *mp;
439 	const char *sp;
440 	size_t		mlen;
441 	int			plen;
442 
443 	/*
444 	 * room for function source and the def statement
445 	 */
446 	mlen = (strlen(src) * 2) + strlen(name) + 16;
447 
448 	mrc = palloc(mlen);
449 	plen = snprintf(mrc, mlen, "def %s():\n\t", name);
450 	Assert(plen >= 0 && plen < mlen);
451 
452 	sp = src;
453 	mp = mrc + plen;
454 
455 	while (*sp != '\0')
456 	{
457 		if (*sp == '\r' && *(sp + 1) == '\n')
458 			sp++;
459 
460 		if (*sp == '\n' || *sp == '\r')
461 		{
462 			*mp++ = '\n';
463 			*mp++ = '\t';
464 			sp++;
465 		}
466 		else
467 			*mp++ = *sp++;
468 	}
469 	*mp++ = '\n';
470 	*mp++ = '\n';
471 	*mp = '\0';
472 
473 	if (mp > (mrc + mlen))
474 		elog(FATAL, "buffer overrun in PLy_munge_source");
475 
476 	return mrc;
477 }
478