Header And Logo

PostgreSQL
| The world's most advanced open source database.

plpy_procedure.c

Go to the documentation of this file.
00001 /*
00002  * Python procedure manipulation for plpython
00003  *
00004  * src/pl/plpython/plpy_procedure.c
00005  */
00006 
00007 #include "postgres.h"
00008 
00009 #include "access/htup_details.h"
00010 #include "access/transam.h"
00011 #include "funcapi.h"
00012 #include "catalog/pg_proc.h"
00013 #include "catalog/pg_type.h"
00014 #include "utils/builtins.h"
00015 #include "utils/hsearch.h"
00016 #include "utils/syscache.h"
00017 
00018 #include "plpython.h"
00019 
00020 #include "plpy_procedure.h"
00021 
00022 #include "plpy_elog.h"
00023 #include "plpy_main.h"
00024 
00025 
00026 static HTAB *PLy_procedure_cache = NULL;
00027 
00028 static PLyProcedure *PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger);
00029 static bool PLy_procedure_argument_valid(PLyTypeInfo *arg);
00030 static bool PLy_procedure_valid(PLyProcedure *proc, HeapTuple procTup);
00031 static char *PLy_procedure_munge_source(const char *name, const char *src);
00032 
00033 
00034 void
00035 init_procedure_caches(void)
00036 {
00037     HASHCTL     hash_ctl;
00038 
00039     memset(&hash_ctl, 0, sizeof(hash_ctl));
00040     hash_ctl.keysize = sizeof(PLyProcedureKey);
00041     hash_ctl.entrysize = sizeof(PLyProcedureEntry);
00042     hash_ctl.hash = tag_hash;
00043     PLy_procedure_cache = hash_create("PL/Python procedures", 32, &hash_ctl,
00044                                       HASH_ELEM | HASH_FUNCTION);
00045 }
00046 
00047 /*
00048  * Get the name of the last procedure called by the backend (the
00049  * innermost, if a plpython procedure call calls the backend and the
00050  * backend calls another plpython procedure).
00051  *
00052  * NB: this returns the SQL name, not the internal Python procedure name
00053  */
00054 char *
00055 PLy_procedure_name(PLyProcedure *proc)
00056 {
00057     if (proc == NULL)
00058         return "<unknown procedure>";
00059     return proc->proname;
00060 }
00061 
00062 /*
00063  * PLy_procedure_get: returns a cached PLyProcedure, or creates, stores and
00064  * returns a new PLyProcedure.
00065  *
00066  * fn_oid is the OID of the function requested
00067  * fn_rel is InvalidOid or the relation this function triggers on
00068  * is_trigger denotes whether the function is a trigger function
00069  *
00070  * The reason that both fn_rel and is_trigger need to be passed is that when
00071  * trigger functions get validated we don't know which relation(s) they'll
00072  * be used with, so no sensible fn_rel can be passed.
00073  */
00074 PLyProcedure *
00075 PLy_procedure_get(Oid fn_oid, Oid fn_rel, bool is_trigger)
00076 {
00077     bool        use_cache = !(is_trigger && fn_rel == InvalidOid);
00078     HeapTuple   procTup;
00079     PLyProcedureKey key;
00080     PLyProcedureEntry *volatile entry = NULL;
00081     PLyProcedure *volatile proc = NULL;
00082     bool        found = false;
00083 
00084     procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(fn_oid));
00085     if (!HeapTupleIsValid(procTup))
00086         elog(ERROR, "cache lookup failed for function %u", fn_oid);
00087 
00088     /*
00089      * Look for the function in the cache, unless we don't have the necessary
00090      * information (e.g. during validation). In that case we just don't cache
00091      * anything.
00092      */
00093     if (use_cache)
00094     {
00095         key.fn_oid = fn_oid;
00096         key.fn_rel = fn_rel;
00097         entry = hash_search(PLy_procedure_cache, &key, HASH_ENTER, &found);
00098         proc = entry->proc;
00099     }
00100 
00101     PG_TRY();
00102     {
00103         if (!found)
00104         {
00105             /* Haven't found it, create a new procedure */
00106             proc = PLy_procedure_create(procTup, fn_oid, is_trigger);
00107             if (use_cache)
00108                 entry->proc = proc;
00109         }
00110         else if (!PLy_procedure_valid(proc, procTup))
00111         {
00112             /* Found it, but it's invalid, free and reuse the cache entry */
00113             PLy_procedure_delete(proc);
00114             PLy_free(proc);
00115             proc = PLy_procedure_create(procTup, fn_oid, is_trigger);
00116             entry->proc = proc;
00117         }
00118         /* Found it and it's valid, it's fine to use it */
00119     }
00120     PG_CATCH();
00121     {
00122         /* Do not leave an uninitialised entry in the cache */
00123         if (use_cache)
00124             hash_search(PLy_procedure_cache, &key, HASH_REMOVE, NULL);
00125         PG_RE_THROW();
00126     }
00127     PG_END_TRY();
00128 
00129     ReleaseSysCache(procTup);
00130 
00131     return proc;
00132 }
00133 
00134 /*
00135  * Create a new PLyProcedure structure
00136  */
00137 static PLyProcedure *
00138 PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
00139 {
00140     char        procName[NAMEDATALEN + 256];
00141     Form_pg_proc procStruct;
00142     PLyProcedure *volatile proc;
00143     char       *volatile procSource = NULL;
00144     Datum       prosrcdatum;
00145     bool        isnull;
00146     int         i,
00147                 rv;
00148 
00149     procStruct = (Form_pg_proc) GETSTRUCT(procTup);
00150     rv = snprintf(procName, sizeof(procName),
00151                   "__plpython_procedure_%s_%u",
00152                   NameStr(procStruct->proname),
00153                   fn_oid);
00154     if (rv >= sizeof(procName) || rv < 0)
00155         elog(ERROR, "procedure name would overrun buffer");
00156 
00157     proc = PLy_malloc(sizeof(PLyProcedure));
00158     proc->proname = PLy_strdup(NameStr(procStruct->proname));
00159     proc->pyname = PLy_strdup(procName);
00160     proc->fn_xmin = HeapTupleHeaderGetXmin(procTup->t_data);
00161     proc->fn_tid = procTup->t_self;
00162     /* Remember if function is STABLE/IMMUTABLE */
00163     proc->fn_readonly =
00164         (procStruct->provolatile != PROVOLATILE_VOLATILE);
00165     PLy_typeinfo_init(&proc->result);
00166     for (i = 0; i < FUNC_MAX_ARGS; i++)
00167         PLy_typeinfo_init(&proc->args[i]);
00168     proc->nargs = 0;
00169     proc->code = proc->statics = NULL;
00170     proc->globals = NULL;
00171     proc->is_setof = procStruct->proretset;
00172     proc->setof = NULL;
00173     proc->src = NULL;
00174     proc->argnames = NULL;
00175 
00176     PG_TRY();
00177     {
00178         /*
00179          * get information required for output conversion of the return value,
00180          * but only if this isn't a trigger.
00181          */
00182         if (!is_trigger)
00183         {
00184             HeapTuple   rvTypeTup;
00185             Form_pg_type rvTypeStruct;
00186 
00187             rvTypeTup = SearchSysCache1(TYPEOID,
00188                                    ObjectIdGetDatum(procStruct->prorettype));
00189             if (!HeapTupleIsValid(rvTypeTup))
00190                 elog(ERROR, "cache lookup failed for type %u",
00191                      procStruct->prorettype);
00192             rvTypeStruct = (Form_pg_type) GETSTRUCT(rvTypeTup);
00193 
00194             /* Disallow pseudotype result, except for void or record */
00195             if (rvTypeStruct->typtype == TYPTYPE_PSEUDO)
00196             {
00197                 if (procStruct->prorettype == TRIGGEROID)
00198                     ereport(ERROR,
00199                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00200                              errmsg("trigger functions can only be called as triggers")));
00201                 else if (procStruct->prorettype != VOIDOID &&
00202                          procStruct->prorettype != RECORDOID)
00203                     ereport(ERROR,
00204                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00205                           errmsg("PL/Python functions cannot return type %s",
00206                                  format_type_be(procStruct->prorettype))));
00207             }
00208 
00209             if (rvTypeStruct->typtype == TYPTYPE_COMPOSITE ||
00210                 procStruct->prorettype == RECORDOID)
00211             {
00212                 /*
00213                  * Tuple: set up later, during first call to
00214                  * PLy_function_handler
00215                  */
00216                 proc->result.out.d.typoid = procStruct->prorettype;
00217                 proc->result.out.d.typmod = -1;
00218                 proc->result.is_rowtype = 2;
00219             }
00220             else
00221             {
00222                 /* do the real work */
00223                 PLy_output_datum_func(&proc->result, rvTypeTup);
00224             }
00225 
00226             ReleaseSysCache(rvTypeTup);
00227         }
00228 
00229         /*
00230          * Now get information required for input conversion of the
00231          * procedure's arguments.  Note that we ignore output arguments here.
00232          * If the function returns record, those I/O functions will be set up
00233          * when the function is first called.
00234          */
00235         if (procStruct->pronargs)
00236         {
00237             Oid        *types;
00238             char      **names,
00239                        *modes;
00240             int         i,
00241                         pos,
00242                         total;
00243 
00244             /* extract argument type info from the pg_proc tuple */
00245             total = get_func_arg_info(procTup, &types, &names, &modes);
00246 
00247             /* count number of in+inout args into proc->nargs */
00248             if (modes == NULL)
00249                 proc->nargs = total;
00250             else
00251             {
00252                 /* proc->nargs was initialized to 0 above */
00253                 for (i = 0; i < total; i++)
00254                 {
00255                     if (modes[i] != PROARGMODE_OUT &&
00256                         modes[i] != PROARGMODE_TABLE)
00257                         (proc->nargs)++;
00258                 }
00259             }
00260 
00261             proc->argnames = (char **) PLy_malloc0(sizeof(char *) * proc->nargs);
00262             for (i = pos = 0; i < total; i++)
00263             {
00264                 HeapTuple   argTypeTup;
00265                 Form_pg_type argTypeStruct;
00266 
00267                 if (modes &&
00268                     (modes[i] == PROARGMODE_OUT ||
00269                      modes[i] == PROARGMODE_TABLE))
00270                     continue;   /* skip OUT arguments */
00271 
00272                 Assert(types[i] == procStruct->proargtypes.values[pos]);
00273 
00274                 argTypeTup = SearchSysCache1(TYPEOID,
00275                                              ObjectIdGetDatum(types[i]));
00276                 if (!HeapTupleIsValid(argTypeTup))
00277                     elog(ERROR, "cache lookup failed for type %u", types[i]);
00278                 argTypeStruct = (Form_pg_type) GETSTRUCT(argTypeTup);
00279 
00280                 /* check argument type is OK, set up I/O function info */
00281                 switch (argTypeStruct->typtype)
00282                 {
00283                     case TYPTYPE_PSEUDO:
00284                         /* Disallow pseudotype argument */
00285                         ereport(ERROR,
00286                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00287                           errmsg("PL/Python functions cannot accept type %s",
00288                                  format_type_be(types[i]))));
00289                         break;
00290                     case TYPTYPE_COMPOSITE:
00291                         /* we'll set IO funcs at first call */
00292                         proc->args[pos].is_rowtype = 2;
00293                         break;
00294                     default:
00295                         PLy_input_datum_func(&(proc->args[pos]),
00296                                              types[i],
00297                                              argTypeTup);
00298                         break;
00299                 }
00300 
00301                 /* get argument name */
00302                 proc->argnames[pos] = names ? PLy_strdup(names[i]) : NULL;
00303 
00304                 ReleaseSysCache(argTypeTup);
00305 
00306                 pos++;
00307             }
00308         }
00309 
00310         /*
00311          * get the text of the function.
00312          */
00313         prosrcdatum = SysCacheGetAttr(PROCOID, procTup,
00314                                       Anum_pg_proc_prosrc, &isnull);
00315         if (isnull)
00316             elog(ERROR, "null prosrc");
00317         procSource = TextDatumGetCString(prosrcdatum);
00318 
00319         PLy_procedure_compile(proc, procSource);
00320 
00321         pfree(procSource);
00322         procSource = NULL;
00323     }
00324     PG_CATCH();
00325     {
00326         PLy_procedure_delete(proc);
00327         if (procSource)
00328             pfree(procSource);
00329 
00330         PG_RE_THROW();
00331     }
00332     PG_END_TRY();
00333 
00334     return proc;
00335 }
00336 
00337 /*
00338  * Insert the procedure into the Python interpreter
00339  */
00340 void
00341 PLy_procedure_compile(PLyProcedure *proc, const char *src)
00342 {
00343     PyObject   *crv = NULL;
00344     char       *msrc;
00345 
00346     proc->globals = PyDict_Copy(PLy_interp_globals);
00347 
00348     /*
00349      * SD is private preserved data between calls. GD is global data shared by
00350      * all functions
00351      */
00352     proc->statics = PyDict_New();
00353     PyDict_SetItemString(proc->globals, "SD", proc->statics);
00354 
00355     /*
00356      * insert the function code into the interpreter
00357      */
00358     msrc = PLy_procedure_munge_source(proc->pyname, src);
00359     /* Save the mangled source for later inclusion in tracebacks */
00360     proc->src = PLy_strdup(msrc);
00361     crv = PyRun_String(msrc, Py_file_input, proc->globals, NULL);
00362     pfree(msrc);
00363 
00364     if (crv != NULL)
00365     {
00366         int         clen;
00367         char        call[NAMEDATALEN + 256];
00368 
00369         Py_DECREF(crv);
00370 
00371         /*
00372          * compile a call to the function
00373          */
00374         clen = snprintf(call, sizeof(call), "%s()", proc->pyname);
00375         if (clen < 0 || clen >= sizeof(call))
00376             elog(ERROR, "string would overflow buffer");
00377         proc->code = Py_CompileString(call, "<string>", Py_eval_input);
00378         if (proc->code != NULL)
00379             return;
00380     }
00381 
00382     if (proc->proname)
00383         PLy_elog(ERROR, "could not compile PL/Python function \"%s\"",
00384                  proc->proname);
00385     else
00386         PLy_elog(ERROR, "could not compile anonymous PL/Python code block");
00387 }
00388 
00389 void
00390 PLy_procedure_delete(PLyProcedure *proc)
00391 {
00392     int         i;
00393 
00394     Py_XDECREF(proc->code);
00395     Py_XDECREF(proc->statics);
00396     Py_XDECREF(proc->globals);
00397     if (proc->proname)
00398         PLy_free(proc->proname);
00399     if (proc->pyname)
00400         PLy_free(proc->pyname);
00401     for (i = 0; i < proc->nargs; i++)
00402     {
00403         if (proc->args[i].is_rowtype == 1)
00404         {
00405             if (proc->args[i].in.r.atts)
00406                 PLy_free(proc->args[i].in.r.atts);
00407             if (proc->args[i].out.r.atts)
00408                 PLy_free(proc->args[i].out.r.atts);
00409         }
00410         if (proc->argnames && proc->argnames[i])
00411             PLy_free(proc->argnames[i]);
00412     }
00413     if (proc->src)
00414         PLy_free(proc->src);
00415     if (proc->argnames)
00416         PLy_free(proc->argnames);
00417 }
00418 
00419 /*
00420  * Check if our cached information about a datatype is still valid
00421  */
00422 static bool
00423 PLy_procedure_argument_valid(PLyTypeInfo *arg)
00424 {
00425     HeapTuple   relTup;
00426     bool        valid;
00427 
00428     /* Nothing to cache unless type is composite */
00429     if (arg->is_rowtype != 1)
00430         return true;
00431 
00432     /*
00433      * Zero typ_relid means that we got called on an output argument of a
00434      * function returning a unnamed record type; the info for it can't change.
00435      */
00436     if (!OidIsValid(arg->typ_relid))
00437         return true;
00438 
00439     /* Else we should have some cached data */
00440     Assert(TransactionIdIsValid(arg->typrel_xmin));
00441     Assert(ItemPointerIsValid(&arg->typrel_tid));
00442 
00443     /* Get the pg_class tuple for the data type */
00444     relTup = SearchSysCache1(RELOID, ObjectIdGetDatum(arg->typ_relid));
00445     if (!HeapTupleIsValid(relTup))
00446         elog(ERROR, "cache lookup failed for relation %u", arg->typ_relid);
00447 
00448     /* If it has changed, the cached data is not valid */
00449     valid = (arg->typrel_xmin == HeapTupleHeaderGetXmin(relTup->t_data) &&
00450              ItemPointerEquals(&arg->typrel_tid, &relTup->t_self));
00451 
00452     ReleaseSysCache(relTup);
00453 
00454     return valid;
00455 }
00456 
00457 /*
00458  * Decide whether a cached PLyProcedure struct is still valid
00459  */
00460 static bool
00461 PLy_procedure_valid(PLyProcedure *proc, HeapTuple procTup)
00462 {
00463     int         i;
00464     bool        valid;
00465 
00466     Assert(proc != NULL);
00467 
00468     /* If the pg_proc tuple has changed, it's not valid */
00469     if (!(proc->fn_xmin == HeapTupleHeaderGetXmin(procTup->t_data) &&
00470           ItemPointerEquals(&proc->fn_tid, &procTup->t_self)))
00471         return false;
00472 
00473     /* Else check the input argument datatypes */
00474     valid = true;
00475     for (i = 0; i < proc->nargs; i++)
00476     {
00477         valid = PLy_procedure_argument_valid(&proc->args[i]);
00478 
00479         /* Short-circuit on first changed argument */
00480         if (!valid)
00481             break;
00482     }
00483 
00484     /* if the output type is composite, it might have changed */
00485     if (valid)
00486         valid = PLy_procedure_argument_valid(&proc->result);
00487 
00488     return valid;
00489 }
00490 
00491 static char *
00492 PLy_procedure_munge_source(const char *name, const char *src)
00493 {
00494     char       *mrc,
00495                *mp;
00496     const char *sp;
00497     size_t      mlen,
00498                 plen;
00499 
00500     /*
00501      * room for function source and the def statement
00502      */
00503     mlen = (strlen(src) * 2) + strlen(name) + 16;
00504 
00505     mrc = palloc(mlen);
00506     plen = snprintf(mrc, mlen, "def %s():\n\t", name);
00507     Assert(plen >= 0 && plen < mlen);
00508 
00509     sp = src;
00510     mp = mrc + plen;
00511 
00512     while (*sp != '\0')
00513     {
00514         if (*sp == '\r' && *(sp + 1) == '\n')
00515             sp++;
00516 
00517         if (*sp == '\n' || *sp == '\r')
00518         {
00519             *mp++ = '\n';
00520             *mp++ = '\t';
00521             sp++;
00522         }
00523         else
00524             *mp++ = *sp++;
00525     }
00526     *mp++ = '\n';
00527     *mp++ = '\n';
00528     *mp = '\0';
00529 
00530     if (mp > (mrc + mlen))
00531         elog(FATAL, "buffer overrun in PLy_munge_source");
00532 
00533     return mrc;
00534 }