aboutsummaryrefslogtreecommitdiff
path: root/src/pl
diff options
context:
space:
mode:
Diffstat (limited to 'src/pl')
-rw-r--r--src/pl/plperl/plperl.c69
-rw-r--r--src/pl/plpgsql/src/pl_exec.c36
-rw-r--r--src/pl/plpython/plpython.c98
-rw-r--r--src/pl/tcl/pltcl.c81
4 files changed, 173 insertions, 111 deletions
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index f7b690f71ce..8c3680ae19c 100644
--- a/src/pl/plperl/plperl.c
+++ b/src/pl/plperl/plperl.c
@@ -33,7 +33,7 @@
* ENHANCEMENTS, OR MODIFICATIONS.
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.42 2004/01/06 23:55:19 tgl Exp $
+ * $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.43 2004/04/01 21:28:46 tgl Exp $
*
**********************************************************************/
@@ -45,15 +45,16 @@
#include <setjmp.h>
/* postgreSQL stuff */
-#include "executor/spi.h"
-#include "commands/trigger.h"
-#include "fmgr.h"
#include "access/heapam.h"
-#include "tcop/tcopprot.h"
-#include "utils/syscache.h"
#include "catalog/pg_language.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
+#include "commands/trigger.h"
+#include "executor/spi.h"
+#include "fmgr.h"
+#include "tcop/tcopprot.h"
+#include "utils/syscache.h"
+#include "utils/typcache.h"
/* perl stuff */
#include "EXTERN.h"
@@ -82,7 +83,7 @@ typedef struct plperl_proc_desc
int nargs;
FmgrInfo arg_out_func[FUNC_MAX_ARGS];
Oid arg_out_elem[FUNC_MAX_ARGS];
- int arg_is_rel[FUNC_MAX_ARGS];
+ bool arg_is_rowtype[FUNC_MAX_ARGS];
SV *reference;
} plperl_proc_desc;
@@ -388,19 +389,34 @@ plperl_call_perl_func(plperl_proc_desc * desc, FunctionCallInfo fcinfo)
PUSHMARK(SP);
for (i = 0; i < desc->nargs; i++)
{
- if (desc->arg_is_rel[i])
+ if (desc->arg_is_rowtype[i])
{
- TupleTableSlot *slot = (TupleTableSlot *) fcinfo->arg[i];
- SV *hashref;
-
- Assert(slot != NULL && !fcinfo->argnull[i]);
-
- /*
- * plperl_build_tuple_argument better return a mortal SV.
- */
- hashref = plperl_build_tuple_argument(slot->val,
- slot->ttc_tupleDescriptor);
- XPUSHs(hashref);
+ if (fcinfo->argnull[i])
+ XPUSHs(&PL_sv_undef);
+ else
+ {
+ HeapTupleHeader td;
+ Oid tupType;
+ int32 tupTypmod;
+ TupleDesc tupdesc;
+ HeapTupleData tmptup;
+ SV *hashref;
+
+ td = DatumGetHeapTupleHeader(fcinfo->arg[i]);
+ /* Extract rowtype info and find a tupdesc */
+ tupType = HeapTupleHeaderGetTypeId(td);
+ tupTypmod = HeapTupleHeaderGetTypMod(td);
+ tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
+ /* Build a temporary HeapTuple control structure */
+ tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
+ tmptup.t_data = td;
+
+ /*
+ * plperl_build_tuple_argument better return a mortal SV.
+ */
+ hashref = plperl_build_tuple_argument(&tmptup, tupdesc);
+ XPUSHs(hashref);
+ }
}
else
{
@@ -645,7 +661,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
}
}
- if (typeStruct->typrelid != InvalidOid)
+ if (typeStruct->typtype == 'c')
{
free(prodesc->proname);
free(prodesc);
@@ -692,13 +708,16 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
format_type_be(procStruct->proargtypes[i]))));
}
- if (typeStruct->typrelid != InvalidOid)
- prodesc->arg_is_rel[i] = 1;
+ if (typeStruct->typtype == 'c')
+ prodesc->arg_is_rowtype[i] = true;
else
- prodesc->arg_is_rel[i] = 0;
+ {
+ prodesc->arg_is_rowtype[i] = false;
+ perm_fmgr_info(typeStruct->typoutput,
+ &(prodesc->arg_out_func[i]));
+ prodesc->arg_out_elem[i] = typeStruct->typelem;
+ }
- perm_fmgr_info(typeStruct->typoutput, &(prodesc->arg_out_func[i]));
- prodesc->arg_out_elem[i] = typeStruct->typelem;
ReleaseSysCache(typeTup);
}
}
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index b984f0932bb..b71a71bbaac 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.98 2004/03/17 20:48:43 tgl Exp $
+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.99 2004/04/01 21:28:46 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -52,6 +52,7 @@
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
+#include "utils/typcache.h"
static const char *const raise_skip_msg = "RAISE";
@@ -258,16 +259,26 @@ plpgsql_exec_function(PLpgSQL_function * func, FunctionCallInfo fcinfo)
case PLPGSQL_DTYPE_ROW:
{
PLpgSQL_row *row = (PLpgSQL_row *) estate.datums[n];
- TupleTableSlot *slot = (TupleTableSlot *) fcinfo->arg[i];
- HeapTuple tup;
- TupleDesc tupdesc;
if (!fcinfo->argnull[i])
{
- Assert(slot != NULL);
- tup = slot->val;
- tupdesc = slot->ttc_tupleDescriptor;
- exec_move_row(&estate, NULL, row, tup, tupdesc);
+ HeapTupleHeader td;
+ Oid tupType;
+ int32 tupTypmod;
+ TupleDesc tupdesc;
+ HeapTupleData tmptup;
+
+ td = DatumGetHeapTupleHeader(fcinfo->arg[i]);
+ /* Extract rowtype info and find a tupdesc */
+ tupType = HeapTupleHeaderGetTypeId(td);
+ tupTypmod = HeapTupleHeaderGetTypMod(td);
+ tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
+ /* Build a temporary HeapTuple control structure */
+ tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
+ ItemPointerSetInvalid(&(tmptup.t_self));
+ tmptup.t_tableOid = InvalidOid;
+ tmptup.t_data = td;
+ exec_move_row(&estate, NULL, row, &tmptup, tupdesc);
}
else
{
@@ -371,11 +382,10 @@ plpgsql_exec_function(PLpgSQL_function * func, FunctionCallInfo fcinfo)
{
if (estate.retistuple)
{
- /* Copy tuple to upper executor memory */
- /* Here we need to return a TupleTableSlot not just a tuple */
- estate.retval = (Datum)
- SPI_copytupleintoslot((HeapTuple) (estate.retval),
- estate.rettupdesc);
+ /* Copy tuple to upper executor memory, as a tuple Datum */
+ estate.retval =
+ PointerGetDatum(SPI_returntuple((HeapTuple) (estate.retval),
+ estate.rettupdesc));
}
else
{
diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c
index 0da1399d836..010f1e1645e 100644
--- a/src/pl/plpython/plpython.c
+++ b/src/pl/plpython/plpython.c
@@ -29,26 +29,19 @@
* MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.45 2004/01/07 18:56:30 neilc Exp $
+ * $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.46 2004/04/01 21:28:46 tgl Exp $
*
*********************************************************************
*/
#include "postgres.h"
-/* system stuff
- */
-#include <dlfcn.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
+/* system stuff */
#include <unistd.h>
#include <fcntl.h>
-#include <string.h>
#include <setjmp.h>
-/* postgreSQL stuff
- */
+/* postgreSQL stuff */
#include "access/heapam.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
@@ -59,6 +52,7 @@
#include "parser/parse_type.h"
#include "tcop/tcopprot.h"
#include "utils/syscache.h"
+#include "utils/typcache.h"
#include <Python.h>
#include <compile.h>
@@ -121,7 +115,14 @@ typedef struct PLyTypeInfo
{
PLyTypeInput in;
PLyTypeOutput out;
- int is_rel;
+ int is_rowtype;
+ /*
+ * is_rowtype can be:
+ * -1 not known yet (initial state)
+ * 0 scalar datatype
+ * 1 rowtype
+ * 2 rowtype, but I/O functions not set up yet
+ */
} PLyTypeInfo;
@@ -916,16 +917,40 @@ PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure * proc)
args = PyList_New(proc->nargs);
for (i = 0; i < proc->nargs; i++)
{
- if (proc->args[i].is_rel == 1)
+ if (proc->args[i].is_rowtype > 0)
{
- TupleTableSlot *slot = (TupleTableSlot *) fcinfo->arg[i];
-
- arg = PLyDict_FromTuple(&(proc->args[i]), slot->val,
- slot->ttc_tupleDescriptor);
+ if (fcinfo->argnull[i])
+ arg = NULL;
+ else
+ {
+ HeapTupleHeader td;
+ Oid tupType;
+ int32 tupTypmod;
+ TupleDesc tupdesc;
+ HeapTupleData tmptup;
+
+ td = DatumGetHeapTupleHeader(fcinfo->arg[i]);
+ /* Extract rowtype info and find a tupdesc */
+ tupType = HeapTupleHeaderGetTypeId(td);
+ tupTypmod = HeapTupleHeaderGetTypMod(td);
+ tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
+
+ /* Set up I/O funcs if not done yet */
+ if (proc->args[i].is_rowtype != 1)
+ PLy_input_tuple_funcs(&(proc->args[i]), tupdesc);
+
+ /* Build a temporary HeapTuple control structure */
+ tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
+ tmptup.t_data = td;
+
+ arg = PLyDict_FromTuple(&(proc->args[i]), &tmptup, tupdesc);
+ }
}
else
{
- if (!fcinfo->argnull[i])
+ if (fcinfo->argnull[i])
+ arg = NULL;
+ else
{
char *ct;
Datum dt;
@@ -938,8 +963,6 @@ PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure * proc)
arg = (proc->args[i].in.d.func) (ct);
pfree(ct);
}
- else
- arg = NULL;
}
if (arg == NULL)
@@ -1096,7 +1119,7 @@ PLy_procedure_create(FunctionCallInfo fcinfo, Oid tgreloid,
procStruct->prorettype);
rvTypeStruct = (Form_pg_type) GETSTRUCT(rvTypeTup);
- if (rvTypeStruct->typrelid == InvalidOid)
+ if (rvTypeStruct->typtype != 'c')
PLy_output_datum_func(&proc->result, rvTypeStruct);
else
ereport(ERROR,
@@ -1135,17 +1158,12 @@ PLy_procedure_create(FunctionCallInfo fcinfo, Oid tgreloid,
procStruct->proargtypes[i]);
argTypeStruct = (Form_pg_type) GETSTRUCT(argTypeTup);
- if (argTypeStruct->typrelid == InvalidOid)
+ if (argTypeStruct->typtype != 'c')
PLy_input_datum_func(&(proc->args[i]),
procStruct->proargtypes[i],
argTypeStruct);
else
- {
- TupleTableSlot *slot = (TupleTableSlot *) fcinfo->arg[i];
-
- PLy_input_tuple_funcs(&(proc->args[i]),
- slot->ttc_tupleDescriptor);
- }
+ proc->args[i].is_rowtype = 2; /* still need to set I/O funcs */
ReleaseSysCache(argTypeTup);
}
@@ -1279,7 +1297,7 @@ PLy_procedure_delete(PLyProcedure * proc)
if (proc->pyname)
PLy_free(proc->pyname);
for (i = 0; i < proc->nargs; i++)
- if (proc->args[i].is_rel == 1)
+ if (proc->args[i].is_rowtype == 1)
{
if (proc->args[i].in.r.atts)
PLy_free(proc->args[i].in.r.atts);
@@ -1300,10 +1318,10 @@ PLy_input_tuple_funcs(PLyTypeInfo * arg, TupleDesc desc)
enter();
- if (arg->is_rel == 0)
+ if (arg->is_rowtype == 0)
elog(ERROR, "PLyTypeInfo struct is initialized for a Datum");
- arg->is_rel = 1;
+ arg->is_rowtype = 1;
arg->in.r.natts = desc->natts;
arg->in.r.atts = malloc(desc->natts * sizeof(PLyDatumToOb));
@@ -1338,10 +1356,10 @@ PLy_output_tuple_funcs(PLyTypeInfo * arg, TupleDesc desc)
enter();
- if (arg->is_rel == 0)
+ if (arg->is_rowtype == 0)
elog(ERROR, "PLyTypeInfo struct is initialized for a Datum");
- arg->is_rel = 1;
+ arg->is_rowtype = 1;
arg->out.r.natts = desc->natts;
arg->out.r.atts = malloc(desc->natts * sizeof(PLyDatumToOb));
@@ -1372,9 +1390,9 @@ PLy_output_datum_func(PLyTypeInfo * arg, Form_pg_type typeStruct)
{
enter();
- if (arg->is_rel == 1)
+ if (arg->is_rowtype > 0)
elog(ERROR, "PLyTypeInfo struct is initialized for a Tuple");
- arg->is_rel = 0;
+ arg->is_rowtype = 0;
PLy_output_datum_func2(&(arg->out.d), typeStruct);
}
@@ -1393,9 +1411,9 @@ PLy_input_datum_func(PLyTypeInfo * arg, Oid typeOid, Form_pg_type typeStruct)
{
enter();
- if (arg->is_rel == 1)
+ if (arg->is_rowtype > 0)
elog(ERROR, "PLyTypeInfo struct is initialized for Tuple");
- arg->is_rel = 0;
+ arg->is_rowtype = 0;
PLy_input_datum_func2(&(arg->in.d), typeOid, typeStruct);
}
@@ -1434,7 +1452,7 @@ PLy_input_datum_func2(PLyDatumToOb * arg, Oid typeOid, Form_pg_type typeStruct)
void
PLy_typeinfo_init(PLyTypeInfo * arg)
{
- arg->is_rel = -1;
+ arg->is_rowtype = -1;
arg->in.r.natts = arg->out.r.natts = 0;
arg->in.r.atts = NULL;
arg->out.r.atts = NULL;
@@ -1443,7 +1461,7 @@ PLy_typeinfo_init(PLyTypeInfo * arg)
void
PLy_typeinfo_dealloc(PLyTypeInfo * arg)
{
- if (arg->is_rel == 1)
+ if (arg->is_rowtype == 1)
{
if (arg->in.r.atts)
PLy_free(arg->in.r.atts);
@@ -1515,7 +1533,7 @@ PLyDict_FromTuple(PLyTypeInfo * info, HeapTuple tuple, TupleDesc desc)
enter();
- if (info->is_rel != 1)
+ if (info->is_rowtype != 1)
elog(ERROR, "PLyTypeInfo structure describes a datum");
dict = PyDict_New();
@@ -2009,7 +2027,7 @@ PLy_spi_prepare(PyObject * self, PyObject * args)
plan->types[i] = HeapTupleGetOid(typeTup);
typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
- if (typeStruct->typrelid == InvalidOid)
+ if (typeStruct->typtype != 'c')
PLy_output_datum_func(&plan->args[i], typeStruct);
else
{
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
index 37e515ff66b..d9382aff83b 100644
--- a/src/pl/tcl/pltcl.c
+++ b/src/pl/tcl/pltcl.c
@@ -31,7 +31,7 @@
* ENHANCEMENTS, OR MODIFICATIONS.
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/pl/tcl/pltcl.c,v 1.82 2004/01/24 23:06:29 tgl Exp $
+ * $PostgreSQL: pgsql/src/pl/tcl/pltcl.c,v 1.83 2004/04/01 21:28:46 tgl Exp $
*
**********************************************************************/
@@ -60,6 +60,8 @@
#include "tcop/tcopprot.h"
#include "utils/builtins.h"
#include "utils/syscache.h"
+#include "utils/typcache.h"
+
#if defined(UNICODE_CONVERSION) && TCL_MAJOR_VERSION == 8 \
&& TCL_MINOR_VERSION > 0
@@ -107,7 +109,7 @@ typedef struct pltcl_proc_desc
int nargs;
FmgrInfo arg_out_func[FUNC_MAX_ARGS];
Oid arg_out_elem[FUNC_MAX_ARGS];
- int arg_is_rel[FUNC_MAX_ARGS];
+ bool arg_is_rowtype[FUNC_MAX_ARGS];
} pltcl_proc_desc;
@@ -497,21 +499,35 @@ pltcl_func_handler(PG_FUNCTION_ARGS)
************************************************************/
for (i = 0; i < prodesc->nargs; i++)
{
- if (prodesc->arg_is_rel[i])
+ if (prodesc->arg_is_rowtype[i])
{
/**************************************************
* For tuple values, add a list for 'array set ...'
**************************************************/
- TupleTableSlot *slot = (TupleTableSlot *) fcinfo->arg[i];
-
- Assert(slot != NULL && !fcinfo->argnull[i]);
- Tcl_DStringInit(&list_tmp);
- pltcl_build_tuple_argument(slot->val,
- slot->ttc_tupleDescriptor,
- &list_tmp);
- Tcl_DStringAppendElement(&tcl_cmd, Tcl_DStringValue(&list_tmp));
- Tcl_DStringFree(&list_tmp);
- Tcl_DStringInit(&list_tmp);
+ if (fcinfo->argnull[i])
+ Tcl_DStringAppendElement(&tcl_cmd, "");
+ else
+ {
+ HeapTupleHeader td;
+ Oid tupType;
+ int32 tupTypmod;
+ TupleDesc tupdesc;
+ HeapTupleData tmptup;
+
+ td = DatumGetHeapTupleHeader(fcinfo->arg[i]);
+ /* Extract rowtype info and find a tupdesc */
+ tupType = HeapTupleHeaderGetTypeId(td);
+ tupTypmod = HeapTupleHeaderGetTypMod(td);
+ tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
+ /* Build a temporary HeapTuple control structure */
+ tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
+ tmptup.t_data = td;
+
+ Tcl_DStringSetLength(&list_tmp, 0);
+ pltcl_build_tuple_argument(&tmptup, tupdesc, &list_tmp);
+ Tcl_DStringAppendElement(&tcl_cmd,
+ Tcl_DStringValue(&list_tmp));
+ }
}
else
{
@@ -1041,11 +1057,11 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid)
Form_pg_type typeStruct;
Tcl_DString proc_internal_def;
Tcl_DString proc_internal_body;
- char proc_internal_args[4096];
+ char proc_internal_args[33 * FUNC_MAX_ARGS];
Datum prosrcdatum;
bool isnull;
char *proc_source;
- char buf[512];
+ char buf[32];
/************************************************************
* Allocate a new procedure description block
@@ -1124,7 +1140,7 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid)
}
}
- if (typeStruct->typrelid != InvalidOid)
+ if (typeStruct->typtype == 'c')
{
free(prodesc->proname);
free(prodesc);
@@ -1172,25 +1188,22 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid)
format_type_be(procStruct->proargtypes[i]))));
}
- if (typeStruct->typrelid != InvalidOid)
+ if (typeStruct->typtype == 'c')
{
- prodesc->arg_is_rel[i] = 1;
- if (i > 0)
- strcat(proc_internal_args, " ");
+ prodesc->arg_is_rowtype[i] = true;
snprintf(buf, sizeof(buf), "__PLTcl_Tup_%d", i + 1);
- strcat(proc_internal_args, buf);
- ReleaseSysCache(typeTup);
- continue;
}
else
- prodesc->arg_is_rel[i] = 0;
-
- perm_fmgr_info(typeStruct->typoutput, &(prodesc->arg_out_func[i]));
- prodesc->arg_out_elem[i] = typeStruct->typelem;
+ {
+ prodesc->arg_is_rowtype[i] = false;
+ perm_fmgr_info(typeStruct->typoutput,
+ &(prodesc->arg_out_func[i]));
+ prodesc->arg_out_elem[i] = typeStruct->typelem;
+ snprintf(buf, sizeof(buf), "%d", i + 1);
+ }
if (i > 0)
strcat(proc_internal_args, " ");
- snprintf(buf, sizeof(buf), "%d", i + 1);
strcat(proc_internal_args, buf);
ReleaseSysCache(typeTup);
@@ -1225,11 +1238,13 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid)
{
for (i = 0; i < prodesc->nargs; i++)
{
- if (!prodesc->arg_is_rel[i])
- continue;
- snprintf(buf, sizeof(buf), "array set %d $__PLTcl_Tup_%d\n",
- i + 1, i + 1);
- Tcl_DStringAppend(&proc_internal_body, buf, -1);
+ if (prodesc->arg_is_rowtype[i])
+ {
+ snprintf(buf, sizeof(buf),
+ "array set %d $__PLTcl_Tup_%d\n",
+ i + 1, i + 1);
+ Tcl_DStringAppend(&proc_internal_body, buf, -1);
+ }
}
}
else