mirror of
https://github.com/postgres/postgres.git
synced 2025-08-18 12:22:09 +03:00
Repair problems with the result of lookup_rowtype_tupdesc() possibly being
discarded by cache flush while still in use. This is a minimal patch that just copies the tupdesc anywhere it could be needed across a flush. Applied to back branches only; Neil Conway is working on a better long-term solution for HEAD.
This commit is contained in:
@@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.47 2005/01/01 05:43:06 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.47.4.1 2006/01/17 17:33:34 tgl Exp $
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* INTERFACE ROUTINES
|
* INTERFACE ROUTINES
|
||||||
@@ -820,6 +820,7 @@ toast_flatten_tuple_attribute(Datum value,
|
|||||||
if (tupleDesc == NULL)
|
if (tupleDesc == NULL)
|
||||||
return value; /* not a composite type */
|
return value; /* not a composite type */
|
||||||
|
|
||||||
|
tupleDesc = CreateTupleDescCopy(tupleDesc);
|
||||||
att = tupleDesc->attrs;
|
att = tupleDesc->attrs;
|
||||||
numAttrs = tupleDesc->natts;
|
numAttrs = tupleDesc->natts;
|
||||||
|
|
||||||
@@ -866,7 +867,10 @@ toast_flatten_tuple_attribute(Datum value,
|
|||||||
* If nothing to untoast, just return the original tuple.
|
* If nothing to untoast, just return the original tuple.
|
||||||
*/
|
*/
|
||||||
if (!need_change)
|
if (!need_change)
|
||||||
|
{
|
||||||
|
FreeTupleDesc(tupleDesc);
|
||||||
return value;
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calculate the new size of the tuple. Header size should not
|
* Calculate the new size of the tuple. Header size should not
|
||||||
@@ -903,6 +907,7 @@ toast_flatten_tuple_attribute(Datum value,
|
|||||||
for (i = 0; i < numAttrs; i++)
|
for (i = 0; i < numAttrs; i++)
|
||||||
if (toast_free[i])
|
if (toast_free[i])
|
||||||
pfree(DatumGetPointer(toast_values[i]));
|
pfree(DatumGetPointer(toast_values[i]));
|
||||||
|
FreeTupleDesc(tupleDesc);
|
||||||
|
|
||||||
return PointerGetDatum(new_data);
|
return PointerGetDatum(new_data);
|
||||||
}
|
}
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.126.4.1 2006/01/12 22:29:22 neilc Exp $
|
* $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.126.4.2 2006/01/17 17:33:34 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@@ -700,7 +700,7 @@ coerce_record_to_complex(ParseState *pstate, Node *node,
|
|||||||
format_type_be(RECORDOID),
|
format_type_be(RECORDOID),
|
||||||
format_type_be(targetTypeId))));
|
format_type_be(targetTypeId))));
|
||||||
|
|
||||||
tupdesc = lookup_rowtype_tupdesc(targetTypeId, -1);
|
tupdesc = CreateTupleDescCopy(lookup_rowtype_tupdesc(targetTypeId, -1));
|
||||||
newargs = NIL;
|
newargs = NIL;
|
||||||
ucolno = 1;
|
ucolno = 1;
|
||||||
arg = list_head(args);
|
arg = list_head(args);
|
||||||
@@ -758,6 +758,8 @@ coerce_record_to_complex(ParseState *pstate, Node *node,
|
|||||||
format_type_be(targetTypeId)),
|
format_type_be(targetTypeId)),
|
||||||
errdetail("Input has too many columns.")));
|
errdetail("Input has too many columns.")));
|
||||||
|
|
||||||
|
FreeTupleDesc(tupdesc);
|
||||||
|
|
||||||
rowexpr = makeNode(RowExpr);
|
rowexpr = makeNode(RowExpr);
|
||||||
rowexpr->args = newargs;
|
rowexpr->args = newargs;
|
||||||
rowexpr->row_typeid = targetTypeId;
|
rowexpr->row_typeid = targetTypeId;
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.129.4.1 2005/12/14 16:30:20 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.129.4.2 2006/01/17 17:33:34 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@@ -839,6 +839,7 @@ ExpandIndirectionStar(ParseState *pstate, A_Indirection *ind)
|
|||||||
|
|
||||||
/* Verify it's a composite type, and get the tupdesc */
|
/* Verify it's a composite type, and get the tupdesc */
|
||||||
tupleDesc = lookup_rowtype_tupdesc(exprType(expr), exprTypmod(expr));
|
tupleDesc = lookup_rowtype_tupdesc(exprType(expr), exprTypmod(expr));
|
||||||
|
tupleDesc = CreateTupleDescCopy(tupleDesc);
|
||||||
|
|
||||||
/* Generate a list of references to the individual fields */
|
/* Generate a list of references to the individual fields */
|
||||||
numAttrs = tupleDesc->natts;
|
numAttrs = tupleDesc->natts;
|
||||||
@@ -889,6 +890,8 @@ ExpandIndirectionStar(ParseState *pstate, A_Indirection *ind)
|
|||||||
te_list = lappend(te_list, te);
|
te_list = lappend(te_list, te);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FreeTupleDesc(tupleDesc);
|
||||||
|
|
||||||
return te_list;
|
return te_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/utils/adt/rowtypes.c,v 1.8.4.2 2005/04/30 20:04:46 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/utils/adt/rowtypes.c,v 1.8.4.3 2006/01/17 17:33:34 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@@ -79,6 +79,7 @@ record_in(PG_FUNCTION_ARGS)
|
|||||||
errmsg("input of anonymous composite types is not implemented")));
|
errmsg("input of anonymous composite types is not implemented")));
|
||||||
tupTypmod = -1; /* for all non-anonymous types */
|
tupTypmod = -1; /* for all non-anonymous types */
|
||||||
tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
|
tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
|
||||||
|
tupdesc = CreateTupleDescCopy(tupdesc);
|
||||||
ncolumns = tupdesc->natts;
|
ncolumns = tupdesc->natts;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -257,6 +258,7 @@ record_in(PG_FUNCTION_ARGS)
|
|||||||
pfree(buf.data);
|
pfree(buf.data);
|
||||||
pfree(values);
|
pfree(values);
|
||||||
pfree(nulls);
|
pfree(nulls);
|
||||||
|
FreeTupleDesc(tupdesc);
|
||||||
|
|
||||||
PG_RETURN_HEAPTUPLEHEADER(result);
|
PG_RETURN_HEAPTUPLEHEADER(result);
|
||||||
}
|
}
|
||||||
@@ -284,6 +286,7 @@ record_out(PG_FUNCTION_ARGS)
|
|||||||
tupType = HeapTupleHeaderGetTypeId(rec);
|
tupType = HeapTupleHeaderGetTypeId(rec);
|
||||||
tupTypmod = HeapTupleHeaderGetTypMod(rec);
|
tupTypmod = HeapTupleHeaderGetTypMod(rec);
|
||||||
tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
|
tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
|
||||||
|
tupdesc = CreateTupleDescCopy(tupdesc);
|
||||||
ncolumns = tupdesc->natts;
|
ncolumns = tupdesc->natts;
|
||||||
|
|
||||||
/* Build a temporary HeapTuple control structure */
|
/* Build a temporary HeapTuple control structure */
|
||||||
@@ -408,6 +411,7 @@ record_out(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
pfree(values);
|
pfree(values);
|
||||||
pfree(nulls);
|
pfree(nulls);
|
||||||
|
FreeTupleDesc(tupdesc);
|
||||||
|
|
||||||
PG_RETURN_CSTRING(buf.data);
|
PG_RETURN_CSTRING(buf.data);
|
||||||
}
|
}
|
||||||
@@ -444,6 +448,7 @@ record_recv(PG_FUNCTION_ARGS)
|
|||||||
errmsg("input of anonymous composite types is not implemented")));
|
errmsg("input of anonymous composite types is not implemented")));
|
||||||
tupTypmod = -1; /* for all non-anonymous types */
|
tupTypmod = -1; /* for all non-anonymous types */
|
||||||
tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
|
tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
|
||||||
|
tupdesc = CreateTupleDescCopy(tupdesc);
|
||||||
ncolumns = tupdesc->natts;
|
ncolumns = tupdesc->natts;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -593,6 +598,7 @@ record_recv(PG_FUNCTION_ARGS)
|
|||||||
heap_freetuple(tuple);
|
heap_freetuple(tuple);
|
||||||
pfree(values);
|
pfree(values);
|
||||||
pfree(nulls);
|
pfree(nulls);
|
||||||
|
FreeTupleDesc(tupdesc);
|
||||||
|
|
||||||
PG_RETURN_HEAPTUPLEHEADER(result);
|
PG_RETURN_HEAPTUPLEHEADER(result);
|
||||||
}
|
}
|
||||||
@@ -620,6 +626,7 @@ record_send(PG_FUNCTION_ARGS)
|
|||||||
tupType = HeapTupleHeaderGetTypeId(rec);
|
tupType = HeapTupleHeaderGetTypeId(rec);
|
||||||
tupTypmod = HeapTupleHeaderGetTypMod(rec);
|
tupTypmod = HeapTupleHeaderGetTypMod(rec);
|
||||||
tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
|
tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
|
||||||
|
tupdesc = CreateTupleDescCopy(tupdesc);
|
||||||
ncolumns = tupdesc->natts;
|
ncolumns = tupdesc->natts;
|
||||||
|
|
||||||
/* Build a temporary HeapTuple control structure */
|
/* Build a temporary HeapTuple control structure */
|
||||||
@@ -722,6 +729,7 @@ record_send(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
pfree(values);
|
pfree(values);
|
||||||
pfree(nulls);
|
pfree(nulls);
|
||||||
|
FreeTupleDesc(tupdesc);
|
||||||
|
|
||||||
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
|
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
* back to source text
|
* back to source text
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.188.4.2 2005/07/15 18:40:20 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.188.4.3 2006/01/17 17:33:34 tgl Exp $
|
||||||
*
|
*
|
||||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||||
*
|
*
|
||||||
@@ -3245,6 +3245,7 @@ get_rule_expr(Node *node, deparse_context *context,
|
|||||||
if (rowexpr->row_typeid != RECORDOID)
|
if (rowexpr->row_typeid != RECORDOID)
|
||||||
{
|
{
|
||||||
tupdesc = lookup_rowtype_tupdesc(rowexpr->row_typeid, -1);
|
tupdesc = lookup_rowtype_tupdesc(rowexpr->row_typeid, -1);
|
||||||
|
tupdesc = CreateTupleDescCopy(tupdesc);
|
||||||
Assert(list_length(rowexpr->args) <= tupdesc->natts);
|
Assert(list_length(rowexpr->args) <= tupdesc->natts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
src/backend/utils/cache/typcache.c
vendored
4
src/backend/utils/cache/typcache.c
vendored
@@ -36,7 +36,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/utils/cache/typcache.c,v 1.11 2004/12/31 22:01:25 pgsql Exp $
|
* $PostgreSQL: pgsql/src/backend/utils/cache/typcache.c,v 1.11.4.1 2006/01/17 17:33:35 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@@ -383,6 +383,8 @@ lookup_default_opclass(Oid type_id, Oid am_id)
|
|||||||
*
|
*
|
||||||
* Note: returned TupleDesc points to cached copy; caller must copy it
|
* Note: returned TupleDesc points to cached copy; caller must copy it
|
||||||
* if intending to scribble on it or keep a reference for a long time.
|
* if intending to scribble on it or keep a reference for a long time.
|
||||||
|
* ("A long time" basically means "across any possible cache flush",
|
||||||
|
* which typically could occur at any relation open or catalog lookup.)
|
||||||
*/
|
*/
|
||||||
TupleDesc
|
TupleDesc
|
||||||
lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
|
lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
|
||||||
|
@@ -33,7 +33,7 @@
|
|||||||
* ENHANCEMENTS, OR MODIFICATIONS.
|
* ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.67.4.4 2006/01/08 15:51:18 adunstan Exp $
|
* $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.67.4.5 2006/01/17 17:33:35 tgl Exp $
|
||||||
*
|
*
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
@@ -705,12 +705,14 @@ plperl_call_perl_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo)
|
|||||||
tupType = HeapTupleHeaderGetTypeId(td);
|
tupType = HeapTupleHeaderGetTypeId(td);
|
||||||
tupTypmod = HeapTupleHeaderGetTypMod(td);
|
tupTypmod = HeapTupleHeaderGetTypMod(td);
|
||||||
tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
|
tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
|
||||||
|
tupdesc = CreateTupleDescCopy(tupdesc);
|
||||||
/* Build a temporary HeapTuple control structure */
|
/* Build a temporary HeapTuple control structure */
|
||||||
tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
|
tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
|
||||||
tmptup.t_data = td;
|
tmptup.t_data = td;
|
||||||
|
|
||||||
hashref = plperl_hash_from_tuple(&tmptup, tupdesc);
|
hashref = plperl_hash_from_tuple(&tmptup, tupdesc);
|
||||||
XPUSHs(sv_2mortal(hashref));
|
XPUSHs(sv_2mortal(hashref));
|
||||||
|
FreeTupleDesc(tupdesc);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1009,7 +1011,7 @@ plperl_func_handler(PG_FUNCTION_ARGS)
|
|||||||
*/
|
*/
|
||||||
td = get_function_tupdesc(prodesc->result_oid,
|
td = get_function_tupdesc(prodesc->result_oid,
|
||||||
(ReturnSetInfo *) fcinfo->resultinfo);
|
(ReturnSetInfo *) fcinfo->resultinfo);
|
||||||
/* td = CreateTupleDescCopy(td); */
|
td = CreateTupleDescCopy(td);
|
||||||
attinmeta = TupleDescGetAttInMetadata(td);
|
attinmeta = TupleDescGetAttInMetadata(td);
|
||||||
|
|
||||||
tup = plperl_build_tuple_result(perlhash, attinmeta);
|
tup = plperl_build_tuple_result(perlhash, attinmeta);
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
* procedural language
|
* procedural language
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.127.4.4 2006/01/03 22:48:28 tgl Exp $
|
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.127.4.5 2006/01/17 17:33:36 tgl Exp $
|
||||||
*
|
*
|
||||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||||
*
|
*
|
||||||
@@ -273,12 +273,14 @@ plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo)
|
|||||||
tupType = HeapTupleHeaderGetTypeId(td);
|
tupType = HeapTupleHeaderGetTypeId(td);
|
||||||
tupTypmod = HeapTupleHeaderGetTypMod(td);
|
tupTypmod = HeapTupleHeaderGetTypMod(td);
|
||||||
tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
|
tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
|
||||||
|
tupdesc = CreateTupleDescCopy(tupdesc);
|
||||||
/* Build a temporary HeapTuple control structure */
|
/* Build a temporary HeapTuple control structure */
|
||||||
tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
|
tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
|
||||||
ItemPointerSetInvalid(&(tmptup.t_self));
|
ItemPointerSetInvalid(&(tmptup.t_self));
|
||||||
tmptup.t_tableOid = InvalidOid;
|
tmptup.t_tableOid = InvalidOid;
|
||||||
tmptup.t_data = td;
|
tmptup.t_data = td;
|
||||||
exec_move_row(&estate, NULL, row, &tmptup, tupdesc);
|
exec_move_row(&estate, NULL, row, &tmptup, tupdesc);
|
||||||
|
FreeTupleDesc(tupdesc);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -2948,12 +2950,14 @@ exec_assign_value(PLpgSQL_execstate *estate,
|
|||||||
tupType = HeapTupleHeaderGetTypeId(td);
|
tupType = HeapTupleHeaderGetTypeId(td);
|
||||||
tupTypmod = HeapTupleHeaderGetTypMod(td);
|
tupTypmod = HeapTupleHeaderGetTypMod(td);
|
||||||
tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
|
tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
|
||||||
|
tupdesc = CreateTupleDescCopy(tupdesc);
|
||||||
/* Build a temporary HeapTuple control structure */
|
/* Build a temporary HeapTuple control structure */
|
||||||
tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
|
tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
|
||||||
ItemPointerSetInvalid(&(tmptup.t_self));
|
ItemPointerSetInvalid(&(tmptup.t_self));
|
||||||
tmptup.t_tableOid = InvalidOid;
|
tmptup.t_tableOid = InvalidOid;
|
||||||
tmptup.t_data = td;
|
tmptup.t_data = td;
|
||||||
exec_move_row(estate, NULL, row, &tmptup, tupdesc);
|
exec_move_row(estate, NULL, row, &tmptup, tupdesc);
|
||||||
|
FreeTupleDesc(tupdesc);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2990,12 +2994,14 @@ exec_assign_value(PLpgSQL_execstate *estate,
|
|||||||
tupType = HeapTupleHeaderGetTypeId(td);
|
tupType = HeapTupleHeaderGetTypeId(td);
|
||||||
tupTypmod = HeapTupleHeaderGetTypMod(td);
|
tupTypmod = HeapTupleHeaderGetTypMod(td);
|
||||||
tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
|
tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
|
||||||
|
tupdesc = CreateTupleDescCopy(tupdesc);
|
||||||
/* Build a temporary HeapTuple control structure */
|
/* Build a temporary HeapTuple control structure */
|
||||||
tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
|
tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
|
||||||
ItemPointerSetInvalid(&(tmptup.t_self));
|
ItemPointerSetInvalid(&(tmptup.t_self));
|
||||||
tmptup.t_tableOid = InvalidOid;
|
tmptup.t_tableOid = InvalidOid;
|
||||||
tmptup.t_data = td;
|
tmptup.t_data = td;
|
||||||
exec_move_row(estate, rec, NULL, &tmptup, tupdesc);
|
exec_move_row(estate, rec, NULL, &tmptup, tupdesc);
|
||||||
|
FreeTupleDesc(tupdesc);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@@ -29,7 +29,7 @@
|
|||||||
* MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
* MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.58.4.4 2006/01/10 00:33:48 neilc Exp $
|
* $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.58.4.5 2006/01/17 17:33:37 tgl Exp $
|
||||||
*
|
*
|
||||||
*********************************************************************
|
*********************************************************************
|
||||||
*/
|
*/
|
||||||
@@ -861,6 +861,7 @@ PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure * proc)
|
|||||||
tupType = HeapTupleHeaderGetTypeId(td);
|
tupType = HeapTupleHeaderGetTypeId(td);
|
||||||
tupTypmod = HeapTupleHeaderGetTypMod(td);
|
tupTypmod = HeapTupleHeaderGetTypMod(td);
|
||||||
tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
|
tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
|
||||||
|
tupdesc = CreateTupleDescCopy(tupdesc);
|
||||||
|
|
||||||
/* Set up I/O funcs if not done yet */
|
/* Set up I/O funcs if not done yet */
|
||||||
if (proc->args[i].is_rowtype != 1)
|
if (proc->args[i].is_rowtype != 1)
|
||||||
@@ -871,6 +872,7 @@ PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure * proc)
|
|||||||
tmptup.t_data = td;
|
tmptup.t_data = td;
|
||||||
|
|
||||||
arg = PLyDict_FromTuple(&(proc->args[i]), &tmptup, tupdesc);
|
arg = PLyDict_FromTuple(&(proc->args[i]), &tmptup, tupdesc);
|
||||||
|
FreeTupleDesc(tupdesc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@@ -31,7 +31,7 @@
|
|||||||
* ENHANCEMENTS, OR MODIFICATIONS.
|
* ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/pl/tcl/pltcl.c,v 1.94 2004/11/21 21:17:05 tgl Exp $
|
* $PostgreSQL: pgsql/src/pl/tcl/pltcl.c,v 1.94.4.1 2006/01/17 17:33:37 tgl Exp $
|
||||||
*
|
*
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
@@ -533,6 +533,7 @@ pltcl_func_handler(PG_FUNCTION_ARGS)
|
|||||||
tupType = HeapTupleHeaderGetTypeId(td);
|
tupType = HeapTupleHeaderGetTypeId(td);
|
||||||
tupTypmod = HeapTupleHeaderGetTypMod(td);
|
tupTypmod = HeapTupleHeaderGetTypMod(td);
|
||||||
tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
|
tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
|
||||||
|
tupdesc = CreateTupleDescCopy(tupdesc);
|
||||||
/* Build a temporary HeapTuple control structure */
|
/* Build a temporary HeapTuple control structure */
|
||||||
tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
|
tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
|
||||||
tmptup.t_data = td;
|
tmptup.t_data = td;
|
||||||
@@ -541,6 +542,7 @@ pltcl_func_handler(PG_FUNCTION_ARGS)
|
|||||||
pltcl_build_tuple_argument(&tmptup, tupdesc, &list_tmp);
|
pltcl_build_tuple_argument(&tmptup, tupdesc, &list_tmp);
|
||||||
Tcl_DStringAppendElement(&tcl_cmd,
|
Tcl_DStringAppendElement(&tcl_cmd,
|
||||||
Tcl_DStringValue(&list_tmp));
|
Tcl_DStringValue(&list_tmp));
|
||||||
|
FreeTupleDesc(tupdesc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
Reference in New Issue
Block a user