Speedup Hash Joins with dedicated functions for ExprState hashing
[pgsql.git] / src / pl / plpython / plpy_procedure.c
blobc35a3b801abbfd7672fd735f2406ff6531cd57f5
1 /*
2 * Python procedure manipulation for plpython
4 * src/pl/plpython/plpy_procedure.c
5 */
7 #include "postgres.h"
9 #include "access/htup_details.h"
10 #include "catalog/pg_proc.h"
11 #include "catalog/pg_type.h"
12 #include "funcapi.h"
13 #include "plpy_elog.h"
14 #include "plpy_main.h"
15 #include "plpy_procedure.h"
16 #include "plpython.h"
17 #include "utils/builtins.h"
18 #include "utils/hsearch.h"
19 #include "utils/memutils.h"
20 #include "utils/syscache.h"
22 static HTAB *PLy_procedure_cache = NULL;
24 static PLyProcedure *PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger);
25 static bool PLy_procedure_valid(PLyProcedure *proc, HeapTuple procTup);
26 static char *PLy_procedure_munge_source(const char *name, const char *src);
29 void
30 init_procedure_caches(void)
32 HASHCTL hash_ctl;
34 hash_ctl.keysize = sizeof(PLyProcedureKey);
35 hash_ctl.entrysize = sizeof(PLyProcedureEntry);
36 PLy_procedure_cache = hash_create("PL/Python procedures", 32, &hash_ctl,
37 HASH_ELEM | HASH_BLOBS);
41 * PLy_procedure_name: get the name of the specified procedure.
43 * NB: this returns the SQL name, not the internal Python procedure name
45 char *
46 PLy_procedure_name(PLyProcedure *proc)
48 if (proc == NULL)
49 return "<unknown procedure>";
50 return proc->proname;
54 * PLy_procedure_get: returns a cached PLyProcedure, or creates, stores and
55 * returns a new PLyProcedure.
57 * fn_oid is the OID of the function requested
58 * fn_rel is InvalidOid or the relation this function triggers on
59 * is_trigger denotes whether the function is a trigger function
61 * The reason that both fn_rel and is_trigger need to be passed is that when
62 * trigger functions get validated we don't know which relation(s) they'll
63 * be used with, so no sensible fn_rel can be passed.
65 PLyProcedure *
66 PLy_procedure_get(Oid fn_oid, Oid fn_rel, bool is_trigger)
68 bool use_cache = !(is_trigger && fn_rel == InvalidOid);
69 HeapTuple procTup;
70 PLyProcedureKey key;
71 PLyProcedureEntry *volatile entry = NULL;
72 PLyProcedure *volatile proc = NULL;
73 bool found = false;
75 procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(fn_oid));
76 if (!HeapTupleIsValid(procTup))
77 elog(ERROR, "cache lookup failed for function %u", fn_oid);
80 * Look for the function in the cache, unless we don't have the necessary
81 * information (e.g. during validation). In that case we just don't cache
82 * anything.
84 if (use_cache)
86 key.fn_oid = fn_oid;
87 key.fn_rel = fn_rel;
88 entry = hash_search(PLy_procedure_cache, &key, HASH_ENTER, &found);
89 proc = entry->proc;
92 PG_TRY();
94 if (!found)
96 /* Haven't found it, create a new procedure */
97 proc = PLy_procedure_create(procTup, fn_oid, is_trigger);
98 if (use_cache)
99 entry->proc = proc;
101 else if (!PLy_procedure_valid(proc, procTup))
103 /* Found it, but it's invalid, free and reuse the cache entry */
104 entry->proc = NULL;
105 if (proc)
106 PLy_procedure_delete(proc);
107 proc = PLy_procedure_create(procTup, fn_oid, is_trigger);
108 entry->proc = proc;
110 /* Found it and it's valid, it's fine to use it */
112 PG_CATCH();
114 /* Do not leave an uninitialized entry in the cache */
115 if (use_cache)
116 hash_search(PLy_procedure_cache, &key, HASH_REMOVE, NULL);
117 PG_RE_THROW();
119 PG_END_TRY();
121 ReleaseSysCache(procTup);
123 return proc;
127 * Create a new PLyProcedure structure
129 static PLyProcedure *
130 PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
132 char procName[NAMEDATALEN + 256];
133 Form_pg_proc procStruct;
134 PLyProcedure *volatile proc;
135 MemoryContext cxt;
136 MemoryContext oldcxt;
137 int rv;
138 char *ptr;
140 procStruct = (Form_pg_proc) GETSTRUCT(procTup);
141 rv = snprintf(procName, sizeof(procName),
142 "__plpython_procedure_%s_%u",
143 NameStr(procStruct->proname),
144 fn_oid);
145 if (rv >= sizeof(procName) || rv < 0)
146 elog(ERROR, "procedure name would overrun buffer");
148 /* Replace any not-legal-in-Python-names characters with '_' */
149 for (ptr = procName; *ptr; ptr++)
151 if (!((*ptr >= 'A' && *ptr <= 'Z') ||
152 (*ptr >= 'a' && *ptr <= 'z') ||
153 (*ptr >= '0' && *ptr <= '9')))
154 *ptr = '_';
157 /* Create long-lived context that all procedure info will live in */
158 cxt = AllocSetContextCreate(TopMemoryContext,
159 "PL/Python function",
160 ALLOCSET_DEFAULT_SIZES);
162 oldcxt = MemoryContextSwitchTo(cxt);
164 proc = (PLyProcedure *) palloc0(sizeof(PLyProcedure));
165 proc->mcxt = cxt;
167 PG_TRY();
169 Datum protrftypes_datum;
170 Datum prosrcdatum;
171 bool isnull;
172 char *procSource;
173 int i;
175 proc->proname = pstrdup(NameStr(procStruct->proname));
176 MemoryContextSetIdentifier(cxt, proc->proname);
177 proc->pyname = pstrdup(procName);
178 proc->fn_xmin = HeapTupleHeaderGetRawXmin(procTup->t_data);
179 proc->fn_tid = procTup->t_self;
180 proc->fn_readonly = (procStruct->provolatile != PROVOLATILE_VOLATILE);
181 proc->is_setof = procStruct->proretset;
182 proc->is_procedure = (procStruct->prokind == PROKIND_PROCEDURE);
183 proc->is_trigger = is_trigger;
184 proc->src = NULL;
185 proc->argnames = NULL;
186 proc->args = NULL;
187 proc->nargs = 0;
188 proc->langid = procStruct->prolang;
189 protrftypes_datum = SysCacheGetAttr(PROCOID, procTup,
190 Anum_pg_proc_protrftypes,
191 &isnull);
192 proc->trftypes = isnull ? NIL : oid_array_to_list(protrftypes_datum);
193 proc->code = NULL;
194 proc->statics = NULL;
195 proc->globals = NULL;
196 proc->calldepth = 0;
197 proc->argstack = NULL;
200 * get information required for output conversion of the return value,
201 * but only if this isn't a trigger.
203 if (!is_trigger)
205 Oid rettype = procStruct->prorettype;
206 HeapTuple rvTypeTup;
207 Form_pg_type rvTypeStruct;
209 rvTypeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(rettype));
210 if (!HeapTupleIsValid(rvTypeTup))
211 elog(ERROR, "cache lookup failed for type %u", rettype);
212 rvTypeStruct = (Form_pg_type) GETSTRUCT(rvTypeTup);
214 /* Disallow pseudotype result, except for void or record */
215 if (rvTypeStruct->typtype == TYPTYPE_PSEUDO)
217 if (rettype == VOIDOID ||
218 rettype == RECORDOID)
219 /* okay */ ;
220 else if (rettype == TRIGGEROID || rettype == EVENT_TRIGGEROID)
221 ereport(ERROR,
222 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
223 errmsg("trigger functions can only be called as triggers")));
224 else
225 ereport(ERROR,
226 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
227 errmsg("PL/Python functions cannot return type %s",
228 format_type_be(rettype))));
231 /* set up output function for procedure result */
232 PLy_output_setup_func(&proc->result, proc->mcxt,
233 rettype, -1, proc);
235 ReleaseSysCache(rvTypeTup);
237 else
240 * In a trigger function, we use proc->result and proc->result_in
241 * for converting tuples, but we don't yet have enough info to set
242 * them up. PLy_exec_trigger will deal with it.
244 proc->result.typoid = InvalidOid;
245 proc->result_in.typoid = InvalidOid;
249 * Now get information required for input conversion of the
250 * procedure's arguments. Note that we ignore output arguments here.
251 * If the function returns record, those I/O functions will be set up
252 * when the function is first called.
254 if (procStruct->pronargs)
256 Oid *types;
257 char **names,
258 *modes;
259 int pos,
260 total;
262 /* extract argument type info from the pg_proc tuple */
263 total = get_func_arg_info(procTup, &types, &names, &modes);
265 /* count number of in+inout args into proc->nargs */
266 if (modes == NULL)
267 proc->nargs = total;
268 else
270 /* proc->nargs was initialized to 0 above */
271 for (i = 0; i < total; i++)
273 if (modes[i] != PROARGMODE_OUT &&
274 modes[i] != PROARGMODE_TABLE)
275 (proc->nargs)++;
279 /* Allocate arrays for per-input-argument data */
280 proc->argnames = (char **) palloc0(sizeof(char *) * proc->nargs);
281 proc->args = (PLyDatumToOb *) palloc0(sizeof(PLyDatumToOb) * proc->nargs);
283 for (i = pos = 0; i < total; i++)
285 HeapTuple argTypeTup;
286 Form_pg_type argTypeStruct;
288 if (modes &&
289 (modes[i] == PROARGMODE_OUT ||
290 modes[i] == PROARGMODE_TABLE))
291 continue; /* skip OUT arguments */
293 Assert(types[i] == procStruct->proargtypes.values[pos]);
295 argTypeTup = SearchSysCache1(TYPEOID,
296 ObjectIdGetDatum(types[i]));
297 if (!HeapTupleIsValid(argTypeTup))
298 elog(ERROR, "cache lookup failed for type %u", types[i]);
299 argTypeStruct = (Form_pg_type) GETSTRUCT(argTypeTup);
301 /* disallow pseudotype arguments */
302 if (argTypeStruct->typtype == TYPTYPE_PSEUDO)
303 ereport(ERROR,
304 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
305 errmsg("PL/Python functions cannot accept type %s",
306 format_type_be(types[i]))));
308 /* set up I/O function info */
309 PLy_input_setup_func(&proc->args[pos], proc->mcxt,
310 types[i], -1, /* typmod not known */
311 proc);
313 /* get argument name */
314 proc->argnames[pos] = names ? pstrdup(names[i]) : NULL;
316 ReleaseSysCache(argTypeTup);
318 pos++;
323 * get the text of the function.
325 prosrcdatum = SysCacheGetAttrNotNull(PROCOID, procTup,
326 Anum_pg_proc_prosrc);
327 procSource = TextDatumGetCString(prosrcdatum);
329 PLy_procedure_compile(proc, procSource);
331 pfree(procSource);
333 PG_CATCH();
335 MemoryContextSwitchTo(oldcxt);
336 PLy_procedure_delete(proc);
337 PG_RE_THROW();
339 PG_END_TRY();
341 MemoryContextSwitchTo(oldcxt);
342 return proc;
346 * Insert the procedure into the Python interpreter
348 void
349 PLy_procedure_compile(PLyProcedure *proc, const char *src)
351 PyObject *crv = NULL;
352 char *msrc;
354 proc->globals = PyDict_Copy(PLy_interp_globals);
357 * SD is private preserved data between calls. GD is global data shared by
358 * all functions
360 proc->statics = PyDict_New();
361 if (!proc->statics)
362 PLy_elog(ERROR, NULL);
363 PyDict_SetItemString(proc->globals, "SD", proc->statics);
366 * insert the function code into the interpreter
368 msrc = PLy_procedure_munge_source(proc->pyname, src);
369 /* Save the mangled source for later inclusion in tracebacks */
370 proc->src = MemoryContextStrdup(proc->mcxt, msrc);
371 crv = PyRun_String(msrc, Py_file_input, proc->globals, NULL);
372 pfree(msrc);
374 if (crv != NULL)
376 int clen;
377 char call[NAMEDATALEN + 256];
379 Py_DECREF(crv);
382 * compile a call to the function
384 clen = snprintf(call, sizeof(call), "%s()", proc->pyname);
385 if (clen < 0 || clen >= sizeof(call))
386 elog(ERROR, "string would overflow buffer");
387 proc->code = Py_CompileString(call, "<string>", Py_eval_input);
388 if (proc->code != NULL)
389 return;
392 if (proc->proname)
393 PLy_elog(ERROR, "could not compile PL/Python function \"%s\"",
394 proc->proname);
395 else
396 PLy_elog(ERROR, "could not compile anonymous PL/Python code block");
399 void
400 PLy_procedure_delete(PLyProcedure *proc)
402 Py_XDECREF(proc->code);
403 Py_XDECREF(proc->statics);
404 Py_XDECREF(proc->globals);
405 MemoryContextDelete(proc->mcxt);
409 * Decide whether a cached PLyProcedure struct is still valid
411 static bool
412 PLy_procedure_valid(PLyProcedure *proc, HeapTuple procTup)
414 if (proc == NULL)
415 return false;
417 /* If the pg_proc tuple has changed, it's not valid */
418 if (!(proc->fn_xmin == HeapTupleHeaderGetRawXmin(procTup->t_data) &&
419 ItemPointerEquals(&proc->fn_tid, &procTup->t_self)))
420 return false;
422 return true;
425 static char *
426 PLy_procedure_munge_source(const char *name, const char *src)
428 char *mrc,
429 *mp;
430 const char *sp;
431 size_t mlen;
432 int plen;
435 * room for function source and the def statement
437 mlen = (strlen(src) * 2) + strlen(name) + 16;
439 mrc = palloc(mlen);
440 plen = snprintf(mrc, mlen, "def %s():\n\t", name);
441 Assert(plen >= 0 && plen < mlen);
443 sp = src;
444 mp = mrc + plen;
446 while (*sp != '\0')
448 if (*sp == '\r' && *(sp + 1) == '\n')
449 sp++;
451 if (*sp == '\n' || *sp == '\r')
453 *mp++ = '\n';
454 *mp++ = '\t';
455 sp++;
457 else
458 *mp++ = *sp++;
460 *mp++ = '\n';
461 *mp++ = '\n';
462 *mp = '\0';
464 if (mp > (mrc + mlen))
465 elog(FATAL, "buffer overrun in PLy_procedure_munge_source");
467 return mrc;