diff options
Diffstat (limited to 'src/pl')
-rw-r--r-- | src/pl/plperl/plperl.c | 69 | ||||
-rw-r--r-- | src/pl/plpgsql/src/pl_exec.c | 36 | ||||
-rw-r--r-- | src/pl/plpython/plpython.c | 98 | ||||
-rw-r--r-- | src/pl/tcl/pltcl.c | 81 |
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 |