From: Tom Lane Date: Tue, 17 Jan 2006 17:33:23 +0000 (+0000) Subject: Repair problems with the result of lookup_rowtype_tupdesc() possibly being X-Git-Tag: REL8_1_3~49 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7b3d9367b449f160fd4597094b0e18054d555b09;p=postgresql 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. --- diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c index 2292f69651..bdd9bc100a 100644 --- a/src/backend/access/heap/tuptoaster.c +++ b/src/backend/access/heap/tuptoaster.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.53.2.2 2005/11/22 18:23:04 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.53.2.3 2006/01/17 17:33:20 tgl Exp $ * * * INTERFACE ROUTINES @@ -847,6 +847,7 @@ toast_flatten_tuple_attribute(Datum value, if (tupleDesc == NULL) return value; /* not a composite type */ + tupleDesc = CreateTupleDescCopy(tupleDesc); att = tupleDesc->attrs; numAttrs = tupleDesc->natts; @@ -893,7 +894,10 @@ toast_flatten_tuple_attribute(Datum value, * If nothing to untoast, just return the original tuple. */ if (!need_change) + { + FreeTupleDesc(tupleDesc); return value; + } /* * Calculate the new size of the tuple. Header size should not change, @@ -930,6 +934,7 @@ toast_flatten_tuple_attribute(Datum value, for (i = 0; i < numAttrs; i++) if (toast_free[i]) pfree(DatumGetPointer(toast_values[i])); + FreeTupleDesc(tupleDesc); return PointerGetDatum(new_data); } diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c index 407744005f..56229fd8c9 100644 --- a/src/backend/parser/parse_coerce.c +++ b/src/backend/parser/parse_coerce.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.132.2.2 2006/01/12 22:29:11 neilc Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.132.2.3 2006/01/17 17:33:20 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -705,7 +705,7 @@ coerce_record_to_complex(ParseState *pstate, Node *node, format_type_be(RECORDOID), format_type_be(targetTypeId)))); - tupdesc = lookup_rowtype_tupdesc(targetTypeId, -1); + tupdesc = CreateTupleDescCopy(lookup_rowtype_tupdesc(targetTypeId, -1)); newargs = NIL; ucolno = 1; arg = list_head(args); @@ -763,6 +763,8 @@ coerce_record_to_complex(ParseState *pstate, Node *node, format_type_be(targetTypeId)), errdetail("Input has too many columns."))); + FreeTupleDesc(tupdesc); + rowexpr = makeNode(RowExpr); rowexpr->args = newargs; rowexpr->row_typeid = targetTypeId; diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index 4290045baa..e32ad22551 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.138.2.1 2005/11/22 18:23:14 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.138.2.2 2006/01/17 17:33:20 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -816,7 +816,8 @@ ExpandIndirectionStar(ParseState *pstate, A_Indirection *ind) ((Var *) expr)->vartype == RECORDOID) tupleDesc = expandRecordVariable(pstate, (Var *) expr, 0); else if (get_expr_result_type(expr, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE) - tupleDesc = lookup_rowtype_tupdesc(exprType(expr), exprTypmod(expr)); + tupleDesc = CreateTupleDescCopy(lookup_rowtype_tupdesc(exprType(expr), + exprTypmod(expr))); Assert(tupleDesc); /* Generate a list of references to the individual fields */ @@ -993,7 +994,8 @@ expandRecordVariable(ParseState *pstate, Var *var, int levelsup) * appropriate error message while failing. */ if (get_expr_result_type(expr, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE) - tupleDesc = lookup_rowtype_tupdesc(exprType(expr), exprTypmod(expr)); + tupleDesc = CreateTupleDescCopy(lookup_rowtype_tupdesc(exprType(expr), + exprTypmod(expr))); return tupleDesc; } diff --git a/src/backend/utils/adt/rowtypes.c b/src/backend/utils/adt/rowtypes.c index 1a12185b04..04756db10c 100644 --- a/src/backend/utils/adt/rowtypes.c +++ b/src/backend/utils/adt/rowtypes.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/rowtypes.c,v 1.13 2005/10/15 02:49:29 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/rowtypes.c,v 1.13.2.1 2006/01/17 17:33:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -83,6 +83,7 @@ record_in(PG_FUNCTION_ARGS) errmsg("input of anonymous composite types is not implemented"))); tupTypmod = -1; /* for all non-anonymous types */ tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod); + tupdesc = CreateTupleDescCopy(tupdesc); ncolumns = tupdesc->natts; /* @@ -261,6 +262,7 @@ record_in(PG_FUNCTION_ARGS) pfree(buf.data); pfree(values); pfree(nulls); + FreeTupleDesc(tupdesc); PG_RETURN_HEAPTUPLEHEADER(result); } @@ -288,6 +290,7 @@ record_out(PG_FUNCTION_ARGS) tupType = HeapTupleHeaderGetTypeId(rec); tupTypmod = HeapTupleHeaderGetTypMod(rec); tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod); + tupdesc = CreateTupleDescCopy(tupdesc); ncolumns = tupdesc->natts; /* Build a temporary HeapTuple control structure */ @@ -409,6 +412,7 @@ record_out(PG_FUNCTION_ARGS) pfree(values); pfree(nulls); + FreeTupleDesc(tupdesc); PG_RETURN_CSTRING(buf.data); } @@ -449,6 +453,7 @@ record_recv(PG_FUNCTION_ARGS) errmsg("input of anonymous composite types is not implemented"))); tupTypmod = -1; /* for all non-anonymous types */ tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod); + tupdesc = CreateTupleDescCopy(tupdesc); ncolumns = tupdesc->natts; /* @@ -597,6 +602,7 @@ record_recv(PG_FUNCTION_ARGS) heap_freetuple(tuple); pfree(values); pfree(nulls); + FreeTupleDesc(tupdesc); PG_RETURN_HEAPTUPLEHEADER(result); } @@ -624,6 +630,7 @@ record_send(PG_FUNCTION_ARGS) tupType = HeapTupleHeaderGetTypeId(rec); tupTypmod = HeapTupleHeaderGetTypMod(rec); tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod); + tupdesc = CreateTupleDescCopy(tupdesc); ncolumns = tupdesc->natts; /* Build a temporary HeapTuple control structure */ @@ -724,6 +731,7 @@ record_send(PG_FUNCTION_ARGS) pfree(values); pfree(nulls); + FreeTupleDesc(tupdesc); PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); } diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 3e6e2ffac4..8283022399 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -3,7 +3,7 @@ * back to source text * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.207.2.3 2005/12/30 18:34:27 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.207.2.4 2006/01/17 17:33:21 tgl Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -2699,7 +2699,7 @@ get_name_for_var_field(Var *var, int fieldno, /* Got the tupdesc, so we can extract the field name */ Assert(fieldno >= 1 && fieldno <= tupleDesc->natts); - return NameStr(tupleDesc->attrs[fieldno - 1]->attname); + return pstrdup(NameStr(tupleDesc->attrs[fieldno - 1]->attname)); } @@ -3493,6 +3493,7 @@ get_rule_expr(Node *node, deparse_context *context, if (rowexpr->row_typeid != RECORDOID) { tupdesc = lookup_rowtype_tupdesc(rowexpr->row_typeid, -1); + tupdesc = CreateTupleDescCopy(tupdesc); Assert(list_length(rowexpr->args) <= tupdesc->natts); } diff --git a/src/backend/utils/cache/typcache.c b/src/backend/utils/cache/typcache.c index b681892ca9..16025e2c6f 100644 --- a/src/backend/utils/cache/typcache.c +++ b/src/backend/utils/cache/typcache.c @@ -36,7 +36,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/cache/typcache.c,v 1.15.2.1 2005/11/22 18:23:23 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/typcache.c,v 1.15.2.2 2006/01/17 17:33:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -377,6 +377,8 @@ lookup_default_opclass(Oid type_id, Oid am_id) * * 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. + * ("A long time" basically means "across any possible cache flush", + * which typically could occur at any relation open or catalog lookup.) */ TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod) diff --git a/src/backend/utils/fmgr/funcapi.c b/src/backend/utils/fmgr/funcapi.c index 0a51f7ae0f..565eb11102 100644 --- a/src/backend/utils/fmgr/funcapi.c +++ b/src/backend/utils/fmgr/funcapi.c @@ -7,7 +7,7 @@ * Copyright (c) 2002-2005, PostgreSQL Global Development Group * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/fmgr/funcapi.c,v 1.26 2005/10/15 02:49:32 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/fmgr/funcapi.c,v 1.26.2.1 2006/01/17 17:33:21 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -246,7 +246,7 @@ get_expr_result_type(Node *expr, *resultTupleDesc = NULL; result = get_type_func_class(typid); if (result == TYPEFUNC_COMPOSITE && resultTupleDesc) - *resultTupleDesc = lookup_rowtype_tupdesc(typid, -1); + *resultTupleDesc = CreateTupleDescCopy(lookup_rowtype_tupdesc(typid, -1)); } return result; @@ -363,7 +363,7 @@ internal_get_result_type(Oid funcid, { case TYPEFUNC_COMPOSITE: if (resultTupleDesc) - *resultTupleDesc = lookup_rowtype_tupdesc(rettype, -1); + *resultTupleDesc = CreateTupleDescCopy(lookup_rowtype_tupdesc(rettype, -1)); /* Named composite types can't have any polymorphic columns */ break; case TYPEFUNC_SCALAR: diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c index 6a5d1546ff..57343fe21d 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.94.2.2 2006/01/08 15:50:00 adunstan Exp $ + * $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.94.2.3 2006/01/17 17:33:22 tgl Exp $ * **********************************************************************/ @@ -796,12 +796,14 @@ plperl_call_perl_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo) tupType = HeapTupleHeaderGetTypeId(td); tupTypmod = HeapTupleHeaderGetTypMod(td); tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod); + tupdesc = CreateTupleDescCopy(tupdesc); /* Build a temporary HeapTuple control structure */ tmptup.t_len = HeapTupleHeaderGetDatumLength(td); tmptup.t_data = td; hashref = plperl_hash_from_tuple(&tmptup, tupdesc); XPUSHs(sv_2mortal(hashref)); + FreeTupleDesc(tupdesc); } else { diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index 39e7ae510c..7fc4f8e0be 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.154.2.2 2006/01/03 22:48:21 tgl Exp $ + * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.154.2.3 2006/01/17 17:33:22 tgl Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -253,12 +253,14 @@ plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo) tupType = HeapTupleHeaderGetTypeId(td); tupTypmod = HeapTupleHeaderGetTypMod(td); tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod); + tupdesc = CreateTupleDescCopy(tupdesc); /* 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); + FreeTupleDesc(tupdesc); } else { @@ -3110,12 +3112,14 @@ exec_assign_value(PLpgSQL_execstate *estate, tupType = HeapTupleHeaderGetTypeId(td); tupTypmod = HeapTupleHeaderGetTypMod(td); tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod); + tupdesc = CreateTupleDescCopy(tupdesc); /* 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); + FreeTupleDesc(tupdesc); } break; } @@ -3152,12 +3156,14 @@ exec_assign_value(PLpgSQL_execstate *estate, tupType = HeapTupleHeaderGetTypeId(td); tupTypmod = HeapTupleHeaderGetTypMod(td); tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod); + tupdesc = CreateTupleDescCopy(tupdesc); /* 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, rec, NULL, &tmptup, tupdesc); + FreeTupleDesc(tupdesc); } break; } diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c index 329387b428..e9b9c5958d 100644 --- a/src/pl/plpython/plpython.c +++ b/src/pl/plpython/plpython.c @@ -29,7 +29,7 @@ * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * * IDENTIFICATION - * $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.66.2.2 2006/01/10 00:33:30 neilc Exp $ + * $PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.66.2.3 2006/01/17 17:33:23 tgl Exp $ * ********************************************************************* */ @@ -862,6 +862,7 @@ PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure * proc) tupType = HeapTupleHeaderGetTypeId(td); tupTypmod = HeapTupleHeaderGetTypMod(td); tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod); + tupdesc = CreateTupleDescCopy(tupdesc); /* Set up I/O funcs if not done yet */ if (proc->args[i].is_rowtype != 1) @@ -872,6 +873,7 @@ PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure * proc) tmptup.t_data = td; arg = PLyDict_FromTuple(&(proc->args[i]), &tmptup, tupdesc); + FreeTupleDesc(tupdesc); } } else diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c index 3f3d6acd45..a84e5d438a 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.98.2.1 2005/11/22 18:23:31 momjian Exp $ + * $PostgreSQL: pgsql/src/pl/tcl/pltcl.c,v 1.98.2.2 2006/01/17 17:33:23 tgl Exp $ * **********************************************************************/ @@ -531,6 +531,7 @@ pltcl_func_handler(PG_FUNCTION_ARGS) tupType = HeapTupleHeaderGetTypeId(td); tupTypmod = HeapTupleHeaderGetTypMod(td); tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod); + tupdesc = CreateTupleDescCopy(tupdesc); /* Build a temporary HeapTuple control structure */ tmptup.t_len = HeapTupleHeaderGetDatumLength(td); tmptup.t_data = td; @@ -539,6 +540,7 @@ pltcl_func_handler(PG_FUNCTION_ARGS) pltcl_build_tuple_argument(&tmptup, tupdesc, &list_tmp); Tcl_DStringAppendElement(&tcl_cmd, Tcl_DStringValue(&list_tmp)); + FreeTupleDesc(tupdesc); } } else