From 2cd70845240087da205695baedab6412342d1dbe Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Sun, 20 Aug 2017 11:19:07 -0700 Subject: [PATCH] Change tupledesc->attrs[n] to TupleDescAttr(tupledesc, n). This is a mechanical change in preparation for a later commit that will change the layout of TupleDesc. Introducing a macro to abstract the details of where attributes are stored will allow us to change that in separate step and revise it in future. Author: Thomas Munro, editorialized by Andres Freund Reviewed-By: Andres Freund Discussion: https://postgr.es/m/CAEepm=0ZtQ-SpsgCyzzYpsXS6e=kZWqk3g5Ygn3MDV7A8dabUA@mail.gmail.com --- contrib/dblink/dblink.c | 31 +++-- contrib/file_fdw/file_fdw.c | 6 +- contrib/hstore/hstore_io.c | 22 +-- contrib/pageinspect/heapfuncs.c | 8 +- contrib/pageinspect/rawpage.c | 2 +- contrib/postgres_fdw/deparse.c | 6 +- contrib/postgres_fdw/postgres_fdw.c | 10 +- contrib/spi/timetravel.c | 2 +- contrib/tablefunc/tablefunc.c | 42 +++--- contrib/tcn/tcn.c | 3 +- contrib/test_decoding/test_decoding.c | 2 +- src/backend/access/brin/brin.c | 10 +- src/backend/access/brin/brin_inclusion.c | 6 +- src/backend/access/brin/brin_minmax.c | 6 +- src/backend/access/brin/brin_tuple.c | 2 +- src/backend/access/common/heaptuple.c | 95 ++++++------- src/backend/access/common/indextuple.c | 58 ++++---- src/backend/access/common/printsimple.c | 4 +- src/backend/access/common/printtup.c | 22 +-- src/backend/access/common/tupconvert.c | 47 ++++--- src/backend/access/common/tupdesc.c | 40 +++--- src/backend/access/gin/ginbulk.c | 3 +- src/backend/access/gin/ginget.c | 2 +- src/backend/access/gin/ginutil.c | 14 +- src/backend/access/gist/gistbuild.c | 4 +- src/backend/access/heap/heapam.c | 8 +- src/backend/access/heap/tuptoaster.c | 38 +++--- src/backend/access/spgist/spgutils.c | 2 +- src/backend/bootstrap/bootstrap.c | 8 +- src/backend/catalog/heap.c | 24 ++-- src/backend/catalog/index.c | 15 +- src/backend/catalog/toasting.c | 24 ++-- src/backend/commands/analyze.c | 2 +- src/backend/commands/cluster.c | 2 +- src/backend/commands/copy.c | 56 ++++---- src/backend/commands/createas.c | 2 +- src/backend/commands/indexcmds.c | 4 +- src/backend/commands/matview.c | 3 +- src/backend/commands/tablecmds.c | 57 +++++--- src/backend/commands/typecmds.c | 8 +- src/backend/commands/view.c | 4 +- src/backend/executor/execExpr.c | 11 +- src/backend/executor/execExprInterp.c | 14 +- src/backend/executor/execJunk.c | 2 +- src/backend/executor/execMain.c | 18 +-- src/backend/executor/execReplication.c | 2 +- src/backend/executor/execSRF.c | 4 +- src/backend/executor/execScan.c | 2 +- src/backend/executor/execTuples.c | 13 +- src/backend/executor/execUtils.c | 6 +- src/backend/executor/functions.c | 4 +- src/backend/executor/nodeAgg.c | 6 +- src/backend/executor/nodeModifyTable.c | 3 +- src/backend/executor/nodeSubplan.c | 4 +- src/backend/executor/nodeTableFuncscan.c | 15 +- src/backend/executor/nodeValuesscan.c | 6 +- src/backend/executor/spi.c | 14 +- src/backend/executor/tqueue.c | 4 +- src/backend/executor/tstoreReceiver.c | 13 +- src/backend/optimizer/prep/preptlist.c | 2 +- src/backend/optimizer/prep/prepunion.c | 6 +- src/backend/optimizer/util/clauses.c | 2 +- src/backend/optimizer/util/plancat.c | 9 +- src/backend/parser/analyze.c | 2 +- src/backend/parser/parse_coerce.c | 9 +- src/backend/parser/parse_func.c | 2 +- src/backend/parser/parse_relation.c | 32 ++--- src/backend/parser/parse_target.c | 14 +- src/backend/parser/parse_utilcmd.c | 15 +- src/backend/replication/logical/proto.c | 8 +- src/backend/replication/logical/relation.c | 5 +- .../replication/logical/reorderbuffer.c | 2 +- src/backend/replication/logical/worker.c | 6 +- src/backend/replication/pgoutput/pgoutput.c | 2 +- src/backend/rewrite/rewriteDefine.c | 2 +- src/backend/rewrite/rewriteHandler.c | 8 +- src/backend/utils/adt/json.c | 8 +- src/backend/utils/adt/jsonb.c | 8 +- src/backend/utils/adt/jsonfuncs.c | 2 +- src/backend/utils/adt/orderedsetaggs.c | 6 +- src/backend/utils/adt/rowtypes.c | 129 ++++++++++-------- src/backend/utils/adt/ruleutils.c | 16 ++- src/backend/utils/adt/tid.c | 6 +- src/backend/utils/adt/xml.c | 15 +- src/backend/utils/cache/catcache.c | 5 +- src/backend/utils/cache/relcache.c | 55 ++++---- src/backend/utils/cache/typcache.c | 7 +- src/backend/utils/fmgr/funcapi.c | 15 +- src/backend/utils/misc/pg_config.c | 4 +- src/include/access/htup_details.h | 6 +- src/include/access/itup.h | 6 +- src/include/access/tupdesc.h | 2 + src/pl/plperl/plperl.c | 26 ++-- src/pl/plpgsql/src/pl_comp.c | 2 +- src/pl/plpgsql/src/pl_exec.c | 50 ++++--- src/pl/plpython/plpy_exec.c | 6 +- src/pl/plpython/plpy_resultobject.c | 18 ++- src/pl/plpython/plpy_typeio.c | 41 +++--- src/pl/tcl/pltcl.c | 23 ++-- src/test/regress/regress.c | 4 +- 100 files changed, 805 insertions(+), 626 deletions(-) diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c index 81136b131c..3113b07ab8 100644 --- a/contrib/dblink/dblink.c +++ b/contrib/dblink/dblink.c @@ -2172,14 +2172,16 @@ get_sql_insert(Relation rel, int *pkattnums, int pknumatts, char **src_pkattvals needComma = false; for (i = 0; i < natts; i++) { - if (tupdesc->attrs[i]->attisdropped) + Form_pg_attribute att = TupleDescAttr(tupdesc, i); + + if (att->attisdropped) continue; if (needComma) appendStringInfoChar(&buf, ','); appendStringInfoString(&buf, - quote_ident_cstr(NameStr(tupdesc->attrs[i]->attname))); + quote_ident_cstr(NameStr(att->attname))); needComma = true; } @@ -2191,7 +2193,7 @@ get_sql_insert(Relation rel, int *pkattnums, int pknumatts, char **src_pkattvals needComma = false; for (i = 0; i < natts; i++) { - if (tupdesc->attrs[i]->attisdropped) + if (TupleDescAttr(tupdesc, i)->attisdropped) continue; if (needComma) @@ -2237,12 +2239,13 @@ get_sql_delete(Relation rel, int *pkattnums, int pknumatts, char **tgt_pkattvals for (i = 0; i < pknumatts; i++) { int pkattnum = pkattnums[i]; + Form_pg_attribute attr = TupleDescAttr(tupdesc, pkattnum); if (i > 0) appendStringInfoString(&buf, " AND "); appendStringInfoString(&buf, - quote_ident_cstr(NameStr(tupdesc->attrs[pkattnum]->attname))); + quote_ident_cstr(NameStr(attr->attname))); if (tgt_pkattvals[i] != NULL) appendStringInfo(&buf, " = %s", @@ -2289,14 +2292,16 @@ get_sql_update(Relation rel, int *pkattnums, int pknumatts, char **src_pkattvals needComma = false; for (i = 0; i < natts; i++) { - if (tupdesc->attrs[i]->attisdropped) + Form_pg_attribute attr = TupleDescAttr(tupdesc, i); + + if (attr->attisdropped) continue; if (needComma) appendStringInfoString(&buf, ", "); appendStringInfo(&buf, "%s = ", - quote_ident_cstr(NameStr(tupdesc->attrs[i]->attname))); + quote_ident_cstr(NameStr(attr->attname))); key = get_attnum_pk_pos(pkattnums, pknumatts, i); @@ -2320,12 +2325,13 @@ get_sql_update(Relation rel, int *pkattnums, int pknumatts, char **src_pkattvals for (i = 0; i < pknumatts; i++) { int pkattnum = pkattnums[i]; + Form_pg_attribute attr = TupleDescAttr(tupdesc, pkattnum); if (i > 0) appendStringInfoString(&buf, " AND "); appendStringInfoString(&buf, - quote_ident_cstr(NameStr(tupdesc->attrs[pkattnum]->attname))); + quote_ident_cstr(NameStr(attr->attname))); val = tgt_pkattvals[i]; @@ -2409,14 +2415,16 @@ get_tuple_of_interest(Relation rel, int *pkattnums, int pknumatts, char **src_pk for (i = 0; i < natts; i++) { + Form_pg_attribute attr = TupleDescAttr(tupdesc, i); + if (i > 0) appendStringInfoString(&buf, ", "); - if (tupdesc->attrs[i]->attisdropped) + if (attr->attisdropped) appendStringInfoString(&buf, "NULL"); else appendStringInfoString(&buf, - quote_ident_cstr(NameStr(tupdesc->attrs[i]->attname))); + quote_ident_cstr(NameStr(attr->attname))); } appendStringInfo(&buf, " FROM %s WHERE ", relname); @@ -2424,12 +2432,13 @@ get_tuple_of_interest(Relation rel, int *pkattnums, int pknumatts, char **src_pk for (i = 0; i < pknumatts; i++) { int pkattnum = pkattnums[i]; + Form_pg_attribute attr = TupleDescAttr(tupdesc, pkattnum); if (i > 0) appendStringInfoString(&buf, " AND "); appendStringInfoString(&buf, - quote_ident_cstr(NameStr(tupdesc->attrs[pkattnum]->attname))); + quote_ident_cstr(NameStr(attr->attname))); if (src_pkattvals[i] != NULL) appendStringInfo(&buf, " = %s", @@ -2894,7 +2903,7 @@ validate_pkattnums(Relation rel, for (j = 0; j < natts; j++) { /* dropped columns don't count */ - if (tupdesc->attrs[j]->attisdropped) + if (TupleDescAttr(tupdesc, j)->attisdropped) continue; if (++lnum == pkattnum) diff --git a/contrib/file_fdw/file_fdw.c b/contrib/file_fdw/file_fdw.c index 2396bd442f..94e50e92f7 100644 --- a/contrib/file_fdw/file_fdw.c +++ b/contrib/file_fdw/file_fdw.c @@ -430,7 +430,7 @@ get_file_fdw_attribute_options(Oid relid) /* Retrieve FDW options for all user-defined attributes. */ for (attnum = 1; attnum <= natts; attnum++) { - Form_pg_attribute attr = tupleDesc->attrs[attnum - 1]; + Form_pg_attribute attr = TupleDescAttr(tupleDesc, attnum - 1); List *options; ListCell *lc; @@ -898,7 +898,7 @@ check_selective_binary_conversion(RelOptInfo *baserel, /* Get user attributes. */ if (attnum > 0) { - Form_pg_attribute attr = tupleDesc->attrs[attnum - 1]; + Form_pg_attribute attr = TupleDescAttr(tupleDesc, attnum - 1); char *attname = NameStr(attr->attname); /* Skip dropped attributes (probably shouldn't see any here). */ @@ -912,7 +912,7 @@ check_selective_binary_conversion(RelOptInfo *baserel, numattrs = 0; for (i = 0; i < tupleDesc->natts; i++) { - Form_pg_attribute attr = tupleDesc->attrs[i]; + Form_pg_attribute attr = TupleDescAttr(tupleDesc, i); if (attr->attisdropped) continue; diff --git a/contrib/hstore/hstore_io.c b/contrib/hstore/hstore_io.c index e03005c923..a44c1b2235 100644 --- a/contrib/hstore/hstore_io.c +++ b/contrib/hstore/hstore_io.c @@ -855,15 +855,16 @@ hstore_from_record(PG_FUNCTION_ARGS) for (i = 0, j = 0; i < ncolumns; ++i) { ColumnIOData *column_info = &my_extra->columns[i]; - Oid column_type = tupdesc->attrs[i]->atttypid; + Form_pg_attribute att = TupleDescAttr(tupdesc, i); + Oid column_type = att->atttypid; char *value; /* Ignore dropped columns in datatype */ - if (tupdesc->attrs[i]->attisdropped) + if (att->attisdropped) continue; - pairs[j].key = NameStr(tupdesc->attrs[i]->attname); - pairs[j].keylen = hstoreCheckKeyLen(strlen(NameStr(tupdesc->attrs[i]->attname))); + pairs[j].key = NameStr(att->attname); + pairs[j].keylen = hstoreCheckKeyLen(strlen(NameStr(att->attname))); if (!nulls || nulls[i]) { @@ -1034,21 +1035,22 @@ hstore_populate_record(PG_FUNCTION_ARGS) for (i = 0; i < ncolumns; ++i) { ColumnIOData *column_info = &my_extra->columns[i]; - Oid column_type = tupdesc->attrs[i]->atttypid; + Form_pg_attribute att = TupleDescAttr(tupdesc, i); + Oid column_type = att->atttypid; char *value; int idx; int vallen; /* Ignore dropped columns in datatype */ - if (tupdesc->attrs[i]->attisdropped) + if (att->attisdropped) { nulls[i] = true; continue; } idx = hstoreFindKey(hs, 0, - NameStr(tupdesc->attrs[i]->attname), - strlen(NameStr(tupdesc->attrs[i]->attname))); + NameStr(att->attname), + strlen(NameStr(att->attname))); /* * we can't just skip here if the key wasn't found since we might have @@ -1082,7 +1084,7 @@ hstore_populate_record(PG_FUNCTION_ARGS) */ values[i] = InputFunctionCall(&column_info->proc, NULL, column_info->typioparam, - tupdesc->attrs[i]->atttypmod); + att->atttypmod); nulls[i] = true; } else @@ -1094,7 +1096,7 @@ hstore_populate_record(PG_FUNCTION_ARGS) values[i] = InputFunctionCall(&column_info->proc, value, column_info->typioparam, - tupdesc->attrs[i]->atttypmod); + att->atttypmod); nulls[i] = false; } } diff --git a/contrib/pageinspect/heapfuncs.c b/contrib/pageinspect/heapfuncs.c index 72d1776a4a..ca4d3f530f 100644 --- a/contrib/pageinspect/heapfuncs.c +++ b/contrib/pageinspect/heapfuncs.c @@ -316,7 +316,7 @@ tuple_data_split_internal(Oid relid, char *tupdata, bool is_null; bytea *attr_data = NULL; - attr = tupdesc->attrs[i]; + attr = TupleDescAttr(tupdesc, i); is_null = (t_infomask & HEAP_HASNULL) && att_isnull(i, t_bits); /* @@ -334,7 +334,7 @@ tuple_data_split_internal(Oid relid, char *tupdata, if (attr->attlen == -1) { - off = att_align_pointer(off, tupdesc->attrs[i]->attalign, -1, + off = att_align_pointer(off, attr->attalign, -1, tupdata + off); /* @@ -353,7 +353,7 @@ tuple_data_split_internal(Oid relid, char *tupdata, } else { - off = att_align_nominal(off, tupdesc->attrs[i]->attalign); + off = att_align_nominal(off, attr->attalign); len = attr->attlen; } @@ -371,7 +371,7 @@ tuple_data_split_internal(Oid relid, char *tupdata, memcpy(VARDATA(attr_data), tupdata + off, len); } - off = att_addlength_pointer(off, tupdesc->attrs[i]->attlen, + off = att_addlength_pointer(off, attr->attlen, tupdata + off); } diff --git a/contrib/pageinspect/rawpage.c b/contrib/pageinspect/rawpage.c index e9d3131bda..25af22f453 100644 --- a/contrib/pageinspect/rawpage.c +++ b/contrib/pageinspect/rawpage.c @@ -253,7 +253,7 @@ page_header(PG_FUNCTION_ARGS) lsn = PageGetLSN(page); /* pageinspect >= 1.2 uses pg_lsn instead of text for the LSN field. */ - if (tupdesc->attrs[0]->atttypid == TEXTOID) + if (TupleDescAttr(tupdesc, 0)->atttypid == TEXTOID) { char lsnchar[64]; diff --git a/contrib/postgres_fdw/deparse.c b/contrib/postgres_fdw/deparse.c index 285cf1b2ee..0876589fe5 100644 --- a/contrib/postgres_fdw/deparse.c +++ b/contrib/postgres_fdw/deparse.c @@ -1115,7 +1115,7 @@ deparseTargetList(StringInfo buf, first = true; for (i = 1; i <= tupdesc->natts; i++) { - Form_pg_attribute attr = tupdesc->attrs[i - 1]; + Form_pg_attribute attr = TupleDescAttr(tupdesc, i - 1); /* Ignore dropped attributes. */ if (attr->attisdropped) @@ -1851,7 +1851,7 @@ deparseAnalyzeSql(StringInfo buf, Relation rel, List **retrieved_attrs) for (i = 0; i < tupdesc->natts; i++) { /* Ignore dropped columns. */ - if (tupdesc->attrs[i]->attisdropped) + if (TupleDescAttr(tupdesc, i)->attisdropped) continue; if (!first) @@ -1859,7 +1859,7 @@ deparseAnalyzeSql(StringInfo buf, Relation rel, List **retrieved_attrs) first = false; /* Use attribute name or column_name option. */ - colname = NameStr(tupdesc->attrs[i]->attname); + colname = NameStr(TupleDescAttr(tupdesc, i)->attname); options = GetForeignColumnOptions(relid, i + 1); foreach(lc, options) diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c index a30afca1d6..32dc4e6301 100644 --- a/contrib/postgres_fdw/postgres_fdw.c +++ b/contrib/postgres_fdw/postgres_fdw.c @@ -1575,7 +1575,7 @@ postgresPlanForeignModify(PlannerInfo *root, for (attnum = 1; attnum <= tupdesc->natts; attnum++) { - Form_pg_attribute attr = tupdesc->attrs[attnum - 1]; + Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1); if (!attr->attisdropped) targetAttrs = lappend_int(targetAttrs, attnum); @@ -1675,6 +1675,7 @@ postgresBeginForeignModify(ModifyTableState *mtstate, Oid typefnoid; bool isvarlena; ListCell *lc; + TupleDesc tupdesc = RelationGetDescr(rel); /* * Do nothing in EXPLAIN (no ANALYZE) case. resultRelInfo->ri_FdwState @@ -1719,7 +1720,7 @@ postgresBeginForeignModify(ModifyTableState *mtstate, /* Prepare for input conversion of RETURNING results. */ if (fmstate->has_returning) - fmstate->attinmeta = TupleDescGetAttInMetadata(RelationGetDescr(rel)); + fmstate->attinmeta = TupleDescGetAttInMetadata(tupdesc); /* Prepare for output conversion of parameters used in prepared stmt. */ n_params = list_length(fmstate->target_attrs) + 1; @@ -1748,7 +1749,7 @@ postgresBeginForeignModify(ModifyTableState *mtstate, foreach(lc, fmstate->target_attrs) { int attnum = lfirst_int(lc); - Form_pg_attribute attr = RelationGetDescr(rel)->attrs[attnum - 1]; + Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1); Assert(!attr->attisdropped); @@ -5090,9 +5091,10 @@ conversion_error_callback(void *arg) { /* error occurred in a scan against a foreign table */ TupleDesc tupdesc = RelationGetDescr(errpos->rel); + Form_pg_attribute attr = TupleDescAttr(tupdesc, errpos->cur_attno - 1); if (errpos->cur_attno > 0 && errpos->cur_attno <= tupdesc->natts) - attname = NameStr(tupdesc->attrs[errpos->cur_attno - 1]->attname); + attname = NameStr(attr->attname); else if (errpos->cur_attno == SelfItemPointerAttributeNumber) attname = "ctid"; else if (errpos->cur_attno == ObjectIdAttributeNumber) diff --git a/contrib/spi/timetravel.c b/contrib/spi/timetravel.c index f7905e20db..2c66d888df 100644 --- a/contrib/spi/timetravel.c +++ b/contrib/spi/timetravel.c @@ -328,7 +328,7 @@ timetravel(PG_FUNCTION_ARGS) for (i = 1; i <= natts; i++) { ctypes[i - 1] = SPI_gettypeid(tupdesc, i); - if (!(tupdesc->attrs[i - 1]->attisdropped)) /* skip dropped columns */ + if (!(TupleDescAttr(tupdesc, i - 1)->attisdropped)) /* skip dropped columns */ { snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%c$%d", separ, i); separ = ','; diff --git a/contrib/tablefunc/tablefunc.c b/contrib/tablefunc/tablefunc.c index 0bc8177b61..7369c71351 100644 --- a/contrib/tablefunc/tablefunc.c +++ b/contrib/tablefunc/tablefunc.c @@ -1421,7 +1421,7 @@ build_tuplestore_recursively(char *key_fld, * Check expected (query runtime) tupdesc suitable for Connectby */ static void -validateConnectbyTupleDesc(TupleDesc tupdesc, bool show_branch, bool show_serial) +validateConnectbyTupleDesc(TupleDesc td, bool show_branch, bool show_serial) { int serial_column = 0; @@ -1431,7 +1431,7 @@ validateConnectbyTupleDesc(TupleDesc tupdesc, bool show_branch, bool show_serial /* are there the correct number of columns */ if (show_branch) { - if (tupdesc->natts != (CONNECTBY_NCOLS + serial_column)) + if (td->natts != (CONNECTBY_NCOLS + serial_column)) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("invalid return type"), @@ -1440,7 +1440,7 @@ validateConnectbyTupleDesc(TupleDesc tupdesc, bool show_branch, bool show_serial } else { - if (tupdesc->natts != CONNECTBY_NCOLS_NOBRANCH + serial_column) + if (td->natts != CONNECTBY_NCOLS_NOBRANCH + serial_column) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("invalid return type"), @@ -1449,14 +1449,14 @@ validateConnectbyTupleDesc(TupleDesc tupdesc, bool show_branch, bool show_serial } /* check that the types of the first two columns match */ - if (tupdesc->attrs[0]->atttypid != tupdesc->attrs[1]->atttypid) + if (TupleDescAttr(td, 0)->atttypid != TupleDescAttr(td, 1)->atttypid) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("invalid return type"), errdetail("First two columns must be the same type."))); /* check that the type of the third column is INT4 */ - if (tupdesc->attrs[2]->atttypid != INT4OID) + if (TupleDescAttr(td, 2)->atttypid != INT4OID) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("invalid return type"), @@ -1464,7 +1464,7 @@ validateConnectbyTupleDesc(TupleDesc tupdesc, bool show_branch, bool show_serial format_type_be(INT4OID)))); /* check that the type of the fourth column is TEXT if applicable */ - if (show_branch && tupdesc->attrs[3]->atttypid != TEXTOID) + if (show_branch && TupleDescAttr(td, 3)->atttypid != TEXTOID) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("invalid return type"), @@ -1472,7 +1472,8 @@ validateConnectbyTupleDesc(TupleDesc tupdesc, bool show_branch, bool show_serial format_type_be(TEXTOID)))); /* check that the type of the fifth column is INT4 */ - if (show_branch && show_serial && tupdesc->attrs[4]->atttypid != INT4OID) + if (show_branch && show_serial && + TupleDescAttr(td, 4)->atttypid != INT4OID) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("query-specified return tuple not valid for Connectby: " @@ -1480,7 +1481,8 @@ validateConnectbyTupleDesc(TupleDesc tupdesc, bool show_branch, bool show_serial format_type_be(INT4OID)))); /* check that the type of the fifth column is INT4 */ - if (!show_branch && show_serial && tupdesc->attrs[3]->atttypid != INT4OID) + if (!show_branch && show_serial && + TupleDescAttr(td, 3)->atttypid != INT4OID) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("query-specified return tuple not valid for Connectby: " @@ -1514,10 +1516,10 @@ compatConnectbyTupleDescs(TupleDesc ret_tupdesc, TupleDesc sql_tupdesc) * These columns must match the result type indicated by the calling * query. */ - ret_atttypid = ret_tupdesc->attrs[0]->atttypid; - sql_atttypid = sql_tupdesc->attrs[0]->atttypid; - ret_atttypmod = ret_tupdesc->attrs[0]->atttypmod; - sql_atttypmod = sql_tupdesc->attrs[0]->atttypmod; + ret_atttypid = TupleDescAttr(ret_tupdesc, 0)->atttypid; + sql_atttypid = TupleDescAttr(sql_tupdesc, 0)->atttypid; + ret_atttypmod = TupleDescAttr(ret_tupdesc, 0)->atttypmod; + sql_atttypmod = TupleDescAttr(sql_tupdesc, 0)->atttypmod; if (ret_atttypid != sql_atttypid || (ret_atttypmod >= 0 && ret_atttypmod != sql_atttypmod)) ereport(ERROR, @@ -1528,10 +1530,10 @@ compatConnectbyTupleDescs(TupleDesc ret_tupdesc, TupleDesc sql_tupdesc) format_type_with_typemod(ret_atttypid, ret_atttypmod), format_type_with_typemod(sql_atttypid, sql_atttypmod)))); - ret_atttypid = ret_tupdesc->attrs[1]->atttypid; - sql_atttypid = sql_tupdesc->attrs[1]->atttypid; - ret_atttypmod = ret_tupdesc->attrs[1]->atttypmod; - sql_atttypmod = sql_tupdesc->attrs[1]->atttypmod; + ret_atttypid = TupleDescAttr(ret_tupdesc, 1)->atttypid; + sql_atttypid = TupleDescAttr(sql_tupdesc, 1)->atttypid; + ret_atttypmod = TupleDescAttr(ret_tupdesc, 1)->atttypmod; + sql_atttypmod = TupleDescAttr(sql_tupdesc, 1)->atttypmod; if (ret_atttypid != sql_atttypid || (ret_atttypmod >= 0 && ret_atttypmod != sql_atttypmod)) ereport(ERROR, @@ -1562,8 +1564,8 @@ compatCrosstabTupleDescs(TupleDesc ret_tupdesc, TupleDesc sql_tupdesc) return false; /* check the rowid types match */ - ret_atttypid = ret_tupdesc->attrs[0]->atttypid; - sql_atttypid = sql_tupdesc->attrs[0]->atttypid; + ret_atttypid = TupleDescAttr(ret_tupdesc, 0)->atttypid; + sql_atttypid = TupleDescAttr(sql_tupdesc, 0)->atttypid; if (ret_atttypid != sql_atttypid) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), @@ -1576,10 +1578,10 @@ compatCrosstabTupleDescs(TupleDesc ret_tupdesc, TupleDesc sql_tupdesc) * attribute [2] of the sql tuple should match attributes [1] to [natts] * of the return tuple */ - sql_attr = sql_tupdesc->attrs[2]; + sql_attr = TupleDescAttr(sql_tupdesc, 2); for (i = 1; i < ret_tupdesc->natts; i++) { - ret_attr = ret_tupdesc->attrs[i]; + ret_attr = TupleDescAttr(ret_tupdesc, i); if (ret_attr->atttypid != sql_attr->atttypid) return false; diff --git a/contrib/tcn/tcn.c b/contrib/tcn/tcn.c index 0b9acbf848..88674901bb 100644 --- a/contrib/tcn/tcn.c +++ b/contrib/tcn/tcn.c @@ -153,9 +153,10 @@ triggered_change_notification(PG_FUNCTION_ARGS) for (i = 0; i < numatts; i++) { int colno = index->indkey.values[i]; + Form_pg_attribute attr = TupleDescAttr(tupdesc, colno - 1); appendStringInfoCharMacro(payload, ','); - strcpy_quoted(payload, NameStr((tupdesc->attrs[colno - 1])->attname), '"'); + strcpy_quoted(payload, NameStr(attr->attname), '"'); appendStringInfoCharMacro(payload, '='); strcpy_quoted(payload, SPI_getvalue(trigtuple, tupdesc, colno), '\''); } diff --git a/contrib/test_decoding/test_decoding.c b/contrib/test_decoding/test_decoding.c index a1a7c2ae0c..135b3b7638 100644 --- a/contrib/test_decoding/test_decoding.c +++ b/contrib/test_decoding/test_decoding.c @@ -330,7 +330,7 @@ tuple_to_stringinfo(StringInfo s, TupleDesc tupdesc, HeapTuple tuple, bool skip_ Datum origval; /* possibly toasted Datum */ bool isnull; /* column is null? */ - attr = tupdesc->attrs[natt]; + attr = TupleDescAttr(tupdesc, natt); /* * don't print dropped columns, we can't be sure everything is diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c index efebeb035a..b3aa6d1ced 100644 --- a/src/backend/access/brin/brin.c +++ b/src/backend/access/brin/brin.c @@ -473,7 +473,8 @@ bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm) */ Assert((key->sk_flags & SK_ISNULL) || (key->sk_collation == - bdesc->bd_tupdesc->attrs[keyattno - 1]->attcollation)); + TupleDescAttr(bdesc->bd_tupdesc, + keyattno - 1)->attcollation)); /* First time this column? look up consistent function */ if (consistentFn[keyattno - 1].fn_oid == InvalidOid) @@ -622,6 +623,7 @@ brinbuildCallback(Relation index, { FmgrInfo *addValue; BrinValues *col; + Form_pg_attribute attr = TupleDescAttr(state->bs_bdesc->bd_tupdesc, i); col = &state->bs_dtuple->bt_columns[i]; addValue = index_getprocinfo(index, i + 1, @@ -631,7 +633,7 @@ brinbuildCallback(Relation index, * Update dtuple state, if and as necessary. */ FunctionCall4Coll(addValue, - state->bs_bdesc->bd_tupdesc->attrs[i]->attcollation, + attr->attcollation, PointerGetDatum(state->bs_bdesc), PointerGetDatum(col), values[i], isnull[i]); @@ -1019,12 +1021,12 @@ brin_build_desc(Relation rel) for (keyno = 0; keyno < tupdesc->natts; keyno++) { FmgrInfo *opcInfoFn; + Form_pg_attribute attr = TupleDescAttr(tupdesc, keyno); opcInfoFn = index_getprocinfo(rel, keyno + 1, BRIN_PROCNUM_OPCINFO); opcinfo[keyno] = (BrinOpcInfo *) - DatumGetPointer(FunctionCall1(opcInfoFn, - tupdesc->attrs[keyno]->atttypid)); + DatumGetPointer(FunctionCall1(opcInfoFn, attr->atttypid)); totalstored += opcinfo[keyno]->oi_nstored; } diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c index 9c0a058ccb..449ce5ea4c 100644 --- a/src/backend/access/brin/brin_inclusion.c +++ b/src/backend/access/brin/brin_inclusion.c @@ -157,7 +157,7 @@ brin_inclusion_add_value(PG_FUNCTION_ARGS) } attno = column->bv_attno; - attr = bdesc->bd_tupdesc->attrs[attno - 1]; + attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1); /* * If the recorded value is null, copy the new value (which we know to be @@ -516,7 +516,7 @@ brin_inclusion_union(PG_FUNCTION_ARGS) PG_RETURN_VOID(); attno = col_a->bv_attno; - attr = bdesc->bd_tupdesc->attrs[attno - 1]; + attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1); /* * Adjust "allnulls". If A doesn't have values, just copy the values from @@ -675,7 +675,7 @@ inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno, Oid subtype, bool isNull; opfamily = bdesc->bd_index->rd_opfamily[attno - 1]; - attr = bdesc->bd_tupdesc->attrs[attno - 1]; + attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1); tuple = SearchSysCache4(AMOPSTRATEGY, ObjectIdGetDatum(opfamily), ObjectIdGetDatum(attr->atttypid), ObjectIdGetDatum(subtype), diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c index 62fd90aabe..ce503972f8 100644 --- a/src/backend/access/brin/brin_minmax.c +++ b/src/backend/access/brin/brin_minmax.c @@ -90,7 +90,7 @@ brin_minmax_add_value(PG_FUNCTION_ARGS) } attno = column->bv_attno; - attr = bdesc->bd_tupdesc->attrs[attno - 1]; + attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1); /* * If the recorded value is null, store the new value (which we know to be @@ -260,7 +260,7 @@ brin_minmax_union(PG_FUNCTION_ARGS) PG_RETURN_VOID(); attno = col_a->bv_attno; - attr = bdesc->bd_tupdesc->attrs[attno - 1]; + attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1); /* * Adjust "allnulls". If A doesn't have values, just copy the values from @@ -347,7 +347,7 @@ minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno, Oid subtype, bool isNull; opfamily = bdesc->bd_index->rd_opfamily[attno - 1]; - attr = bdesc->bd_tupdesc->attrs[attno - 1]; + attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1); tuple = SearchSysCache4(AMOPSTRATEGY, ObjectIdGetDatum(opfamily), ObjectIdGetDatum(attr->atttypid), ObjectIdGetDatum(subtype), diff --git a/src/backend/access/brin/brin_tuple.c b/src/backend/access/brin/brin_tuple.c index ed5b4b108d..5c035fb203 100644 --- a/src/backend/access/brin/brin_tuple.c +++ b/src/backend/access/brin/brin_tuple.c @@ -559,7 +559,7 @@ brin_deconstruct_tuple(BrinDesc *brdesc, datumno < brdesc->bd_info[attnum]->oi_nstored; datumno++) { - Form_pg_attribute thisatt = diskdsc->attrs[stored]; + Form_pg_attribute thisatt = TupleDescAttr(diskdsc, stored); if (thisatt->attlen == -1) { diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c index 584a202ab5..13ee528e26 100644 --- a/src/backend/access/common/heaptuple.c +++ b/src/backend/access/common/heaptuple.c @@ -89,7 +89,6 @@ heap_compute_data_size(TupleDesc tupleDesc, Size data_length = 0; int i; int numberOfAttributes = tupleDesc->natts; - Form_pg_attribute *att = tupleDesc->attrs; for (i = 0; i < numberOfAttributes; i++) { @@ -100,7 +99,7 @@ heap_compute_data_size(TupleDesc tupleDesc, continue; val = values[i]; - atti = att[i]; + atti = TupleDescAttr(tupleDesc, i); if (ATT_IS_PACKABLE(atti) && VARATT_CAN_MAKE_SHORT(DatumGetPointer(val))) @@ -152,7 +151,6 @@ heap_fill_tuple(TupleDesc tupleDesc, int bitmask; int i; int numberOfAttributes = tupleDesc->natts; - Form_pg_attribute *att = tupleDesc->attrs; #ifdef USE_ASSERT_CHECKING char *start = data; @@ -174,6 +172,7 @@ heap_fill_tuple(TupleDesc tupleDesc, for (i = 0; i < numberOfAttributes; i++) { + Form_pg_attribute att = TupleDescAttr(tupleDesc, i); Size data_length; if (bit != NULL) @@ -201,14 +200,14 @@ heap_fill_tuple(TupleDesc tupleDesc, * an offset. This is a bit of a hack. */ - if (att[i]->attbyval) + if (att->attbyval) { /* pass-by-value */ - data = (char *) att_align_nominal(data, att[i]->attalign); - store_att_byval(data, values[i], att[i]->attlen); - data_length = att[i]->attlen; + data = (char *) att_align_nominal(data, att->attalign); + store_att_byval(data, values[i], att->attlen); + data_length = att->attlen; } - else if (att[i]->attlen == -1) + else if (att->attlen == -1) { /* varlena */ Pointer val = DatumGetPointer(values[i]); @@ -225,7 +224,7 @@ heap_fill_tuple(TupleDesc tupleDesc, ExpandedObjectHeader *eoh = DatumGetEOHP(values[i]); data = (char *) att_align_nominal(data, - att[i]->attalign); + att->attalign); data_length = EOH_get_flat_size(eoh); EOH_flatten_into(eoh, data, data_length); } @@ -243,7 +242,7 @@ heap_fill_tuple(TupleDesc tupleDesc, data_length = VARSIZE_SHORT(val); memcpy(data, val, data_length); } - else if (VARLENA_ATT_IS_PACKABLE(att[i]) && + else if (VARLENA_ATT_IS_PACKABLE(att) && VARATT_CAN_MAKE_SHORT(val)) { /* convert to short varlena -- no alignment */ @@ -255,25 +254,25 @@ heap_fill_tuple(TupleDesc tupleDesc, { /* full 4-byte header varlena */ data = (char *) att_align_nominal(data, - att[i]->attalign); + att->attalign); data_length = VARSIZE(val); memcpy(data, val, data_length); } } - else if (att[i]->attlen == -2) + else if (att->attlen == -2) { /* cstring ... never needs alignment */ *infomask |= HEAP_HASVARWIDTH; - Assert(att[i]->attalign == 'c'); + Assert(att->attalign == 'c'); data_length = strlen(DatumGetCString(values[i])) + 1; memcpy(data, DatumGetPointer(values[i]), data_length); } else { /* fixed-length pass-by-reference */ - data = (char *) att_align_nominal(data, att[i]->attalign); - Assert(att[i]->attlen > 0); - data_length = att[i]->attlen; + data = (char *) att_align_nominal(data, att->attalign); + Assert(att->attlen > 0); + data_length = att->attlen; memcpy(data, DatumGetPointer(values[i]), data_length); } @@ -354,7 +353,6 @@ nocachegetattr(HeapTuple tuple, TupleDesc tupleDesc) { HeapTupleHeader tup = tuple->t_data; - Form_pg_attribute *att = tupleDesc->attrs; char *tp; /* ptr to data part of tuple */ bits8 *bp = tup->t_bits; /* ptr to null bitmap in tuple */ bool slow = false; /* do we have to walk attrs? */ @@ -404,15 +402,15 @@ nocachegetattr(HeapTuple tuple, if (!slow) { + Form_pg_attribute att; + /* * If we get here, there are no nulls up to and including the target * attribute. If we have a cached offset, we can use it. */ - if (att[attnum]->attcacheoff >= 0) - { - return fetchatt(att[attnum], - tp + att[attnum]->attcacheoff); - } + att = TupleDescAttr(tupleDesc, attnum); + if (att->attcacheoff >= 0) + return fetchatt(att, tp + att->attcacheoff); /* * Otherwise, check for non-fixed-length attrs up to and including @@ -425,7 +423,7 @@ nocachegetattr(HeapTuple tuple, for (j = 0; j <= attnum; j++) { - if (att[j]->attlen <= 0) + if (TupleDescAttr(tupleDesc, j)->attlen <= 0) { slow = true; break; @@ -448,29 +446,32 @@ nocachegetattr(HeapTuple tuple, * fixed-width columns, in hope of avoiding future visits to this * routine. */ - att[0]->attcacheoff = 0; + TupleDescAttr(tupleDesc, 0)->attcacheoff = 0; /* we might have set some offsets in the slow path previously */ - while (j < natts && att[j]->attcacheoff > 0) + while (j < natts && TupleDescAttr(tupleDesc, j)->attcacheoff > 0) j++; - off = att[j - 1]->attcacheoff + att[j - 1]->attlen; + off = TupleDescAttr(tupleDesc, j - 1)->attcacheoff + + TupleDescAttr(tupleDesc, j - 1)->attlen; for (; j < natts; j++) { - if (att[j]->attlen <= 0) + Form_pg_attribute att = TupleDescAttr(tupleDesc, j); + + if (att->attlen <= 0) break; - off = att_align_nominal(off, att[j]->attalign); + off = att_align_nominal(off, att->attalign); - att[j]->attcacheoff = off; + att->attcacheoff = off; - off += att[j]->attlen; + off += att->attlen; } Assert(j > attnum); - off = att[attnum]->attcacheoff; + off = TupleDescAttr(tupleDesc, attnum)->attcacheoff; } else { @@ -490,6 +491,8 @@ nocachegetattr(HeapTuple tuple, off = 0; for (i = 0;; i++) /* loop exit is at "break" */ { + Form_pg_attribute att = TupleDescAttr(tupleDesc, i); + if (HeapTupleHasNulls(tuple) && att_isnull(i, bp)) { usecache = false; @@ -497,9 +500,9 @@ nocachegetattr(HeapTuple tuple, } /* If we know the next offset, we can skip the rest */ - if (usecache && att[i]->attcacheoff >= 0) - off = att[i]->attcacheoff; - else if (att[i]->attlen == -1) + if (usecache && att->attcacheoff >= 0) + off = att->attcacheoff; + else if (att->attlen == -1) { /* * We can only cache the offset for a varlena attribute if the @@ -508,11 +511,11 @@ nocachegetattr(HeapTuple tuple, * either an aligned or unaligned value. */ if (usecache && - off == att_align_nominal(off, att[i]->attalign)) - att[i]->attcacheoff = off; + off == att_align_nominal(off, att->attalign)) + att->attcacheoff = off; else { - off = att_align_pointer(off, att[i]->attalign, -1, + off = att_align_pointer(off, att->attalign, -1, tp + off); usecache = false; } @@ -520,23 +523,23 @@ nocachegetattr(HeapTuple tuple, else { /* not varlena, so safe to use att_align_nominal */ - off = att_align_nominal(off, att[i]->attalign); + off = att_align_nominal(off, att->attalign); if (usecache) - att[i]->attcacheoff = off; + att->attcacheoff = off; } if (i == attnum) break; - off = att_addlength_pointer(off, att[i]->attlen, tp + off); + off = att_addlength_pointer(off, att->attlen, tp + off); - if (usecache && att[i]->attlen <= 0) + if (usecache && att->attlen <= 0) usecache = false; } } - return fetchatt(att[attnum], tp + off); + return fetchatt(TupleDescAttr(tupleDesc, attnum), tp + off); } /* ---------------- @@ -935,7 +938,6 @@ heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, { HeapTupleHeader tup = tuple->t_data; bool hasnulls = HeapTupleHasNulls(tuple); - Form_pg_attribute *att = tupleDesc->attrs; int tdesc_natts = tupleDesc->natts; int natts; /* number of atts to extract */ int attnum; @@ -959,7 +961,7 @@ heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, for (attnum = 0; attnum < natts; attnum++) { - Form_pg_attribute thisatt = att[attnum]; + Form_pg_attribute thisatt = TupleDescAttr(tupleDesc, attnum); if (hasnulls && att_isnull(attnum, bp)) { @@ -1039,7 +1041,6 @@ slot_deform_tuple(TupleTableSlot *slot, int natts) bool *isnull = slot->tts_isnull; HeapTupleHeader tup = tuple->t_data; bool hasnulls = HeapTupleHasNulls(tuple); - Form_pg_attribute *att = tupleDesc->attrs; int attnum; char *tp; /* ptr to tuple data */ long off; /* offset in tuple data */ @@ -1068,7 +1069,7 @@ slot_deform_tuple(TupleTableSlot *slot, int natts) for (; attnum < natts; attnum++) { - Form_pg_attribute thisatt = att[attnum]; + Form_pg_attribute thisatt = TupleDescAttr(tupleDesc, attnum); if (hasnulls && att_isnull(attnum, bp)) { @@ -1209,7 +1210,7 @@ slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull) * This case should not happen in normal use, but it could happen if we * are executing a plan cached before the column was dropped. */ - if (tupleDesc->attrs[attnum - 1]->attisdropped) + if (TupleDescAttr(tupleDesc, attnum - 1)->attisdropped) { *isnull = true; return (Datum) 0; diff --git a/src/backend/access/common/indextuple.c b/src/backend/access/common/indextuple.c index 37a21057d0..138671410a 100644 --- a/src/backend/access/common/indextuple.c +++ b/src/backend/access/common/indextuple.c @@ -63,7 +63,7 @@ index_form_tuple(TupleDesc tupleDescriptor, #ifdef TOAST_INDEX_HACK for (i = 0; i < numberOfAttributes; i++) { - Form_pg_attribute att = tupleDescriptor->attrs[i]; + Form_pg_attribute att = TupleDescAttr(tupleDescriptor, i); untoasted_values[i] = values[i]; untoasted_free[i] = false; @@ -209,7 +209,6 @@ nocache_index_getattr(IndexTuple tup, int attnum, TupleDesc tupleDesc) { - Form_pg_attribute *att = tupleDesc->attrs; char *tp; /* ptr to data part of tuple */ bits8 *bp = NULL; /* ptr to null bitmap in tuple */ bool slow = false; /* do we have to walk attrs? */ @@ -271,15 +270,15 @@ nocache_index_getattr(IndexTuple tup, if (!slow) { + Form_pg_attribute att; + /* * If we get here, there are no nulls up to and including the target * attribute. If we have a cached offset, we can use it. */ - if (att[attnum]->attcacheoff >= 0) - { - return fetchatt(att[attnum], - tp + att[attnum]->attcacheoff); - } + att = TupleDescAttr(tupleDesc, attnum); + if (att->attcacheoff >= 0) + return fetchatt(att, tp + att->attcacheoff); /* * Otherwise, check for non-fixed-length attrs up to and including @@ -292,7 +291,7 @@ nocache_index_getattr(IndexTuple tup, for (j = 0; j <= attnum; j++) { - if (att[j]->attlen <= 0) + if (TupleDescAttr(tupleDesc, j)->attlen <= 0) { slow = true; break; @@ -315,29 +314,32 @@ nocache_index_getattr(IndexTuple tup, * fixed-width columns, in hope of avoiding future visits to this * routine. */ - att[0]->attcacheoff = 0; + TupleDescAttr(tupleDesc, 0)->attcacheoff = 0; /* we might have set some offsets in the slow path previously */ - while (j < natts && att[j]->attcacheoff > 0) + while (j < natts && TupleDescAttr(tupleDesc, j)->attcacheoff > 0) j++; - off = att[j - 1]->attcacheoff + att[j - 1]->attlen; + off = TupleDescAttr(tupleDesc, j - 1)->attcacheoff + + TupleDescAttr(tupleDesc, j - 1)->attlen; for (; j < natts; j++) { - if (att[j]->attlen <= 0) + Form_pg_attribute att = TupleDescAttr(tupleDesc, j); + + if (att->attlen <= 0) break; - off = att_align_nominal(off, att[j]->attalign); + off = att_align_nominal(off, att->attalign); - att[j]->attcacheoff = off; + att->attcacheoff = off; - off += att[j]->attlen; + off += att->attlen; } Assert(j > attnum); - off = att[attnum]->attcacheoff; + off = TupleDescAttr(tupleDesc, attnum)->attcacheoff; } else { @@ -357,6 +359,8 @@ nocache_index_getattr(IndexTuple tup, off = 0; for (i = 0;; i++) /* loop exit is at "break" */ { + Form_pg_attribute att = TupleDescAttr(tupleDesc, i); + if (IndexTupleHasNulls(tup) && att_isnull(i, bp)) { usecache = false; @@ -364,9 +368,9 @@ nocache_index_getattr(IndexTuple tup, } /* If we know the next offset, we can skip the rest */ - if (usecache && att[i]->attcacheoff >= 0) - off = att[i]->attcacheoff; - else if (att[i]->attlen == -1) + if (usecache && att->attcacheoff >= 0) + off = att->attcacheoff; + else if (att->attlen == -1) { /* * We can only cache the offset for a varlena attribute if the @@ -375,11 +379,11 @@ nocache_index_getattr(IndexTuple tup, * either an aligned or unaligned value. */ if (usecache && - off == att_align_nominal(off, att[i]->attalign)) - att[i]->attcacheoff = off; + off == att_align_nominal(off, att->attalign)) + att->attcacheoff = off; else { - off = att_align_pointer(off, att[i]->attalign, -1, + off = att_align_pointer(off, att->attalign, -1, tp + off); usecache = false; } @@ -387,23 +391,23 @@ nocache_index_getattr(IndexTuple tup, else { /* not varlena, so safe to use att_align_nominal */ - off = att_align_nominal(off, att[i]->attalign); + off = att_align_nominal(off, att->attalign); if (usecache) - att[i]->attcacheoff = off; + att->attcacheoff = off; } if (i == attnum) break; - off = att_addlength_pointer(off, att[i]->attlen, tp + off); + off = att_addlength_pointer(off, att->attlen, tp + off); - if (usecache && att[i]->attlen <= 0) + if (usecache && att->attlen <= 0) usecache = false; } } - return fetchatt(att[attnum], tp + off); + return fetchatt(TupleDescAttr(tupleDesc, attnum), tp + off); } /* diff --git a/src/backend/access/common/printsimple.c b/src/backend/access/common/printsimple.c index c863e859fe..b3e9a26b03 100644 --- a/src/backend/access/common/printsimple.c +++ b/src/backend/access/common/printsimple.c @@ -38,7 +38,7 @@ printsimple_startup(DestReceiver *self, int operation, TupleDesc tupdesc) for (i = 0; i < tupdesc->natts; ++i) { - Form_pg_attribute attr = tupdesc->attrs[i]; + Form_pg_attribute attr = TupleDescAttr(tupdesc, i); pq_sendstring(&buf, NameStr(attr->attname)); pq_sendint(&buf, 0, 4); /* table oid */ @@ -71,7 +71,7 @@ printsimple(TupleTableSlot *slot, DestReceiver *self) for (i = 0; i < tupdesc->natts; ++i) { - Form_pg_attribute attr = tupdesc->attrs[i]; + Form_pg_attribute attr = TupleDescAttr(tupdesc, i); Datum value; if (slot->tts_isnull[i]) diff --git a/src/backend/access/common/printtup.c b/src/backend/access/common/printtup.c index a2ca2d74ae..20d20e623e 100644 --- a/src/backend/access/common/printtup.c +++ b/src/backend/access/common/printtup.c @@ -187,7 +187,6 @@ printtup_startup(DestReceiver *self, int operation, TupleDesc typeinfo) void SendRowDescriptionMessage(TupleDesc typeinfo, List *targetlist, int16 *formats) { - Form_pg_attribute *attrs = typeinfo->attrs; int natts = typeinfo->natts; int proto = PG_PROTOCOL_MAJOR(FrontendProtocol); int i; @@ -199,10 +198,11 @@ SendRowDescriptionMessage(TupleDesc typeinfo, List *targetlist, int16 *formats) for (i = 0; i < natts; ++i) { - Oid atttypid = attrs[i]->atttypid; - int32 atttypmod = attrs[i]->atttypmod; + Form_pg_attribute att = TupleDescAttr(typeinfo, i); + Oid atttypid = att->atttypid; + int32 atttypmod = att->atttypmod; - pq_sendstring(&buf, NameStr(attrs[i]->attname)); + pq_sendstring(&buf, NameStr(att->attname)); /* column ID info appears in protocol 3.0 and up */ if (proto >= 3) { @@ -228,7 +228,7 @@ SendRowDescriptionMessage(TupleDesc typeinfo, List *targetlist, int16 *formats) /* If column is a domain, send the base type and typmod instead */ atttypid = getBaseTypeAndTypmod(atttypid, &atttypmod); pq_sendint(&buf, (int) atttypid, sizeof(atttypid)); - pq_sendint(&buf, attrs[i]->attlen, sizeof(attrs[i]->attlen)); + pq_sendint(&buf, att->attlen, sizeof(att->attlen)); pq_sendint(&buf, atttypmod, sizeof(atttypmod)); /* format info appears in protocol 3.0 and up */ if (proto >= 3) @@ -268,18 +268,19 @@ printtup_prepare_info(DR_printtup *myState, TupleDesc typeinfo, int numAttrs) { PrinttupAttrInfo *thisState = myState->myinfo + i; int16 format = (formats ? formats[i] : 0); + Form_pg_attribute attr = TupleDescAttr(typeinfo, i); thisState->format = format; if (format == 0) { - getTypeOutputInfo(typeinfo->attrs[i]->atttypid, + getTypeOutputInfo(attr->atttypid, &thisState->typoutput, &thisState->typisvarlena); fmgr_info(thisState->typoutput, &thisState->finfo); } else if (format == 1) { - getTypeBinaryOutputInfo(typeinfo->attrs[i]->atttypid, + getTypeBinaryOutputInfo(attr->atttypid, &thisState->typsend, &thisState->typisvarlena); fmgr_info(thisState->typsend, &thisState->finfo); @@ -513,14 +514,13 @@ void debugStartup(DestReceiver *self, int operation, TupleDesc typeinfo) { int natts = typeinfo->natts; - Form_pg_attribute *attinfo = typeinfo->attrs; int i; /* * show the return type of the tuples */ for (i = 0; i < natts; ++i) - printatt((unsigned) i + 1, attinfo[i], NULL); + printatt((unsigned) i + 1, TupleDescAttr(typeinfo, i), NULL); printf("\t----\n"); } @@ -545,12 +545,12 @@ debugtup(TupleTableSlot *slot, DestReceiver *self) attr = slot_getattr(slot, i + 1, &isnull); if (isnull) continue; - getTypeOutputInfo(typeinfo->attrs[i]->atttypid, + getTypeOutputInfo(TupleDescAttr(typeinfo, i)->atttypid, &typoutput, &typisvarlena); value = OidOutputFunctionCall(typoutput, attr); - printatt((unsigned) i + 1, typeinfo->attrs[i], value); + printatt((unsigned) i + 1, TupleDescAttr(typeinfo, i), value); } printf("\t----\n"); diff --git a/src/backend/access/common/tupconvert.c b/src/backend/access/common/tupconvert.c index 57e44375ea..3d1bc0635b 100644 --- a/src/backend/access/common/tupconvert.c +++ b/src/backend/access/common/tupconvert.c @@ -84,7 +84,7 @@ convert_tuples_by_position(TupleDesc indesc, same = true; for (i = 0; i < n; i++) { - Form_pg_attribute att = outdesc->attrs[i]; + Form_pg_attribute att = TupleDescAttr(outdesc, i); Oid atttypid; int32 atttypmod; @@ -95,7 +95,7 @@ convert_tuples_by_position(TupleDesc indesc, atttypmod = att->atttypmod; for (; j < indesc->natts; j++) { - att = indesc->attrs[j]; + att = TupleDescAttr(indesc, j); if (att->attisdropped) continue; nincols++; @@ -122,7 +122,7 @@ convert_tuples_by_position(TupleDesc indesc, /* Check for unused input columns */ for (; j < indesc->natts; j++) { - if (indesc->attrs[j]->attisdropped) + if (TupleDescAttr(indesc, j)->attisdropped) continue; nincols++; same = false; /* we'll complain below */ @@ -149,6 +149,9 @@ convert_tuples_by_position(TupleDesc indesc, { for (i = 0; i < n; i++) { + Form_pg_attribute inatt; + Form_pg_attribute outatt; + if (attrMap[i] == (i + 1)) continue; @@ -157,10 +160,12 @@ convert_tuples_by_position(TupleDesc indesc, * also dropped, we needn't convert. However, attlen and attalign * must agree. */ + inatt = TupleDescAttr(indesc, i); + outatt = TupleDescAttr(outdesc, i); if (attrMap[i] == 0 && - indesc->attrs[i]->attisdropped && - indesc->attrs[i]->attlen == outdesc->attrs[i]->attlen && - indesc->attrs[i]->attalign == outdesc->attrs[i]->attalign) + inatt->attisdropped && + inatt->attlen == outatt->attlen && + inatt->attalign == outatt->attalign) continue; same = false; @@ -228,6 +233,9 @@ convert_tuples_by_name(TupleDesc indesc, same = true; for (i = 0; i < n; i++) { + Form_pg_attribute inatt; + Form_pg_attribute outatt; + if (attrMap[i] == (i + 1)) continue; @@ -236,10 +244,12 @@ convert_tuples_by_name(TupleDesc indesc, * also dropped, we needn't convert. However, attlen and attalign * must agree. */ + inatt = TupleDescAttr(indesc, i); + outatt = TupleDescAttr(outdesc, i); if (attrMap[i] == 0 && - indesc->attrs[i]->attisdropped && - indesc->attrs[i]->attlen == outdesc->attrs[i]->attlen && - indesc->attrs[i]->attalign == outdesc->attrs[i]->attalign) + inatt->attisdropped && + inatt->attlen == outatt->attlen && + inatt->attalign == outatt->attalign) continue; same = false; @@ -292,26 +302,27 @@ convert_tuples_by_name_map(TupleDesc indesc, attrMap = (AttrNumber *) palloc0(n * sizeof(AttrNumber)); for (i = 0; i < n; i++) { - Form_pg_attribute att = outdesc->attrs[i]; + Form_pg_attribute outatt = TupleDescAttr(outdesc, i); char *attname; Oid atttypid; int32 atttypmod; int j; - if (att->attisdropped) + if (outatt->attisdropped) continue; /* attrMap[i] is already 0 */ - attname = NameStr(att->attname); - atttypid = att->atttypid; - atttypmod = att->atttypmod; + attname = NameStr(outatt->attname); + atttypid = outatt->atttypid; + atttypmod = outatt->atttypmod; for (j = 0; j < indesc->natts; j++) { - att = indesc->attrs[j]; - if (att->attisdropped) + Form_pg_attribute inatt = TupleDescAttr(indesc, j); + + if (inatt->attisdropped) continue; - if (strcmp(attname, NameStr(att->attname)) == 0) + if (strcmp(attname, NameStr(inatt->attname)) == 0) { /* Found it, check type */ - if (atttypid != att->atttypid || atttypmod != att->atttypmod) + if (atttypid != inatt->atttypid || atttypmod != inatt->atttypmod) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg_internal("%s", _(msg)), diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c index 9fd7b4e019..a5df2d64e2 100644 --- a/src/backend/access/common/tupdesc.c +++ b/src/backend/access/common/tupdesc.c @@ -175,7 +175,9 @@ CreateTupleDescCopyConstr(TupleDesc tupdesc) for (i = 0; i < desc->natts; i++) { - memcpy(desc->attrs[i], tupdesc->attrs[i], ATTRIBUTE_FIXED_PART_SIZE); + memcpy(TupleDescAttr(desc, i), + TupleDescAttr(tupdesc, i), + ATTRIBUTE_FIXED_PART_SIZE); } if (constr) @@ -230,6 +232,9 @@ void TupleDescCopyEntry(TupleDesc dst, AttrNumber dstAttno, TupleDesc src, AttrNumber srcAttno) { + Form_pg_attribute dstAtt = TupleDescAttr(dst, dstAttno - 1); + Form_pg_attribute srcAtt = TupleDescAttr(src, srcAttno - 1); + /* * sanity checks */ @@ -240,8 +245,7 @@ TupleDescCopyEntry(TupleDesc dst, AttrNumber dstAttno, AssertArg(dstAttno >= 1); AssertArg(dstAttno <= dst->natts); - memcpy(dst->attrs[dstAttno - 1], src->attrs[srcAttno - 1], - ATTRIBUTE_FIXED_PART_SIZE); + memcpy(dstAtt, srcAtt, ATTRIBUTE_FIXED_PART_SIZE); /* * Aside from updating the attno, we'd better reset attcacheoff. @@ -252,13 +256,13 @@ TupleDescCopyEntry(TupleDesc dst, AttrNumber dstAttno, * by other uses of this function or TupleDescInitEntry. So we cheat a * bit to avoid a useless O(N^2) penalty. */ - dst->attrs[dstAttno - 1]->attnum = dstAttno; - dst->attrs[dstAttno - 1]->attcacheoff = -1; + dstAtt->attnum = dstAttno; + dstAtt->attcacheoff = -1; /* since we're not copying constraints or defaults, clear these */ - dst->attrs[dstAttno - 1]->attnotnull = false; - dst->attrs[dstAttno - 1]->atthasdef = false; - dst->attrs[dstAttno - 1]->attidentity = '\0'; + dstAtt->attnotnull = false; + dstAtt->atthasdef = false; + dstAtt->attidentity = '\0'; } /* @@ -366,8 +370,8 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2) for (i = 0; i < tupdesc1->natts; i++) { - Form_pg_attribute attr1 = tupdesc1->attrs[i]; - Form_pg_attribute attr2 = tupdesc2->attrs[i]; + Form_pg_attribute attr1 = TupleDescAttr(tupdesc1, i); + Form_pg_attribute attr2 = TupleDescAttr(tupdesc2, i); /* * We do not need to check every single field here: we can disregard @@ -515,7 +519,7 @@ TupleDescInitEntry(TupleDesc desc, /* * initialize the attribute fields */ - att = desc->attrs[attributeNumber - 1]; + att = TupleDescAttr(desc, attributeNumber - 1); att->attrelid = 0; /* dummy value */ @@ -580,7 +584,7 @@ TupleDescInitBuiltinEntry(TupleDesc desc, AssertArg(attributeNumber <= desc->natts); /* initialize the attribute fields */ - att = desc->attrs[attributeNumber - 1]; + att = TupleDescAttr(desc, attributeNumber - 1); att->attrelid = 0; /* dummy value */ /* unlike TupleDescInitEntry, we require an attribute name */ @@ -664,7 +668,7 @@ TupleDescInitEntryCollation(TupleDesc desc, AssertArg(attributeNumber >= 1); AssertArg(attributeNumber <= desc->natts); - desc->attrs[attributeNumber - 1]->attcollation = collationid; + TupleDescAttr(desc, attributeNumber - 1)->attcollation = collationid; } @@ -704,6 +708,7 @@ BuildDescForRelation(List *schema) { ColumnDef *entry = lfirst(l); AclResult aclresult; + Form_pg_attribute att; /* * for each entry in the list, get the name and type information from @@ -730,17 +735,18 @@ BuildDescForRelation(List *schema) TupleDescInitEntry(desc, attnum, attname, atttypid, atttypmod, attdim); + att = TupleDescAttr(desc, attnum - 1); /* Override TupleDescInitEntry's settings as requested */ TupleDescInitEntryCollation(desc, attnum, attcollation); if (entry->storage) - desc->attrs[attnum - 1]->attstorage = entry->storage; + att->attstorage = entry->storage; /* Fill in additional stuff not handled by TupleDescInitEntry */ - desc->attrs[attnum - 1]->attnotnull = entry->is_not_null; + att->attnotnull = entry->is_not_null; has_not_null |= entry->is_not_null; - desc->attrs[attnum - 1]->attislocal = entry->is_local; - desc->attrs[attnum - 1]->attinhcount = entry->inhcount; + att->attislocal = entry->is_local; + att->attinhcount = entry->inhcount; } if (has_not_null) diff --git a/src/backend/access/gin/ginbulk.c b/src/backend/access/gin/ginbulk.c index 4ff149e59a..c76f504295 100644 --- a/src/backend/access/gin/ginbulk.c +++ b/src/backend/access/gin/ginbulk.c @@ -127,9 +127,10 @@ ginInitBA(BuildAccumulator *accum) static Datum getDatumCopy(BuildAccumulator *accum, OffsetNumber attnum, Datum value) { - Form_pg_attribute att = accum->ginstate->origTupdesc->attrs[attnum - 1]; + Form_pg_attribute att; Datum res; + att = TupleDescAttr(accum->ginstate->origTupdesc, attnum - 1); if (att->attbyval) res = value; else diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c index 56a5bf47b8..9895080685 100644 --- a/src/backend/access/gin/ginget.c +++ b/src/backend/access/gin/ginget.c @@ -129,7 +129,7 @@ collectMatchBitmap(GinBtreeData *btree, GinBtreeStack *stack, /* Locate tupdesc entry for key column (for attbyval/attlen data) */ attnum = scanEntry->attnum; - attr = btree->ginstate->origTupdesc->attrs[attnum - 1]; + attr = TupleDescAttr(btree->ginstate->origTupdesc, attnum - 1); for (;;) { diff --git a/src/backend/access/gin/ginutil.c b/src/backend/access/gin/ginutil.c index 91e4a8cf70..136ea27718 100644 --- a/src/backend/access/gin/ginutil.c +++ b/src/backend/access/gin/ginutil.c @@ -96,6 +96,8 @@ initGinState(GinState *state, Relation index) for (i = 0; i < origTupdesc->natts; i++) { + Form_pg_attribute attr = TupleDescAttr(origTupdesc, i); + if (state->oneCol) state->tupdesc[i] = state->origTupdesc; else @@ -105,11 +107,11 @@ initGinState(GinState *state, Relation index) TupleDescInitEntry(state->tupdesc[i], (AttrNumber) 1, NULL, INT2OID, -1, 0); TupleDescInitEntry(state->tupdesc[i], (AttrNumber) 2, NULL, - origTupdesc->attrs[i]->atttypid, - origTupdesc->attrs[i]->atttypmod, - origTupdesc->attrs[i]->attndims); + attr->atttypid, + attr->atttypmod, + attr->attndims); TupleDescInitEntryCollation(state->tupdesc[i], (AttrNumber) 2, - origTupdesc->attrs[i]->attcollation); + attr->attcollation); } /* @@ -126,13 +128,13 @@ initGinState(GinState *state, Relation index) { TypeCacheEntry *typentry; - typentry = lookup_type_cache(origTupdesc->attrs[i]->atttypid, + typentry = lookup_type_cache(attr->atttypid, TYPECACHE_CMP_PROC_FINFO); if (!OidIsValid(typentry->cmp_proc_finfo.fn_oid)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), errmsg("could not identify a comparison function for type %s", - format_type_be(origTupdesc->attrs[i]->atttypid)))); + format_type_be(attr->atttypid)))); fmgr_info_copy(&(state->compareFn[i]), &(typentry->cmp_proc_finfo), CurrentMemoryContext); diff --git a/src/backend/access/gist/gistbuild.c b/src/backend/access/gist/gistbuild.c index 4756a70ae6..b4cb364869 100644 --- a/src/backend/access/gist/gistbuild.c +++ b/src/backend/access/gist/gistbuild.c @@ -295,10 +295,10 @@ gistInitBuffering(GISTBuildState *buildstate) itupMinSize = (Size) MAXALIGN(sizeof(IndexTupleData)); for (i = 0; i < index->rd_att->natts; i++) { - if (index->rd_att->attrs[i]->attlen < 0) + if (TupleDescAttr(index->rd_att, i)->attlen < 0) itupMinSize += VARHDRSZ; else - itupMinSize += index->rd_att->attrs[i]->attlen; + itupMinSize += TupleDescAttr(index->rd_att, i)->attlen; } /* Calculate average and maximal number of index tuples which fit to page */ diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 8792f1453c..ff03c68fcd 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -1066,11 +1066,11 @@ fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, (*(isnull) = false), HeapTupleNoNulls(tup) ? ( - (tupleDesc)->attrs[(attnum) - 1]->attcacheoff >= 0 ? + TupleDescAttr((tupleDesc), (attnum) - 1)->attcacheoff >= 0 ? ( - fetchatt((tupleDesc)->attrs[(attnum) - 1], + fetchatt(TupleDescAttr((tupleDesc), (attnum) - 1), (char *) (tup)->t_data + (tup)->t_data->t_hoff + - (tupleDesc)->attrs[(attnum) - 1]->attcacheoff) + TupleDescAttr((tupleDesc), (attnum) - 1)->attcacheoff) ) : nocachegetattr((tup), (attnum), (tupleDesc)) @@ -4422,7 +4422,7 @@ heap_tuple_attr_equals(TupleDesc tupdesc, int attrnum, else { Assert(attrnum <= tupdesc->natts); - att = tupdesc->attrs[attrnum - 1]; + att = TupleDescAttr(tupdesc, attrnum - 1); return datumIsEqual(value1, value2, att->attbyval, att->attlen); } } diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c index 458180bc95..5a8f1dab83 100644 --- a/src/backend/access/heap/tuptoaster.c +++ b/src/backend/access/heap/tuptoaster.c @@ -464,7 +464,6 @@ void toast_delete(Relation rel, HeapTuple oldtup, bool is_speculative) { TupleDesc tupleDesc; - Form_pg_attribute *att; int numAttrs; int i; Datum toast_values[MaxHeapAttributeNumber]; @@ -489,7 +488,6 @@ toast_delete(Relation rel, HeapTuple oldtup, bool is_speculative) * least one varlena column, by the way.) */ tupleDesc = rel->rd_att; - att = tupleDesc->attrs; numAttrs = tupleDesc->natts; Assert(numAttrs <= MaxHeapAttributeNumber); @@ -501,7 +499,7 @@ toast_delete(Relation rel, HeapTuple oldtup, bool is_speculative) */ for (i = 0; i < numAttrs; i++) { - if (att[i]->attlen == -1) + if (TupleDescAttr(tupleDesc, i)->attlen == -1) { Datum value = toast_values[i]; @@ -538,7 +536,6 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup, { HeapTuple result_tuple; TupleDesc tupleDesc; - Form_pg_attribute *att; int numAttrs; int i; @@ -579,7 +576,6 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup, * Get the tuple descriptor and break down the tuple(s) into fields. */ tupleDesc = rel->rd_att; - att = tupleDesc->attrs; numAttrs = tupleDesc->natts; Assert(numAttrs <= MaxHeapAttributeNumber); @@ -606,6 +602,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup, for (i = 0; i < numAttrs; i++) { + Form_pg_attribute att = TupleDescAttr(tupleDesc, i); struct varlena *old_value; struct varlena *new_value; @@ -621,7 +618,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup, * If the old value is stored on disk, check if it has changed so * we have to delete it later. */ - if (att[i]->attlen == -1 && !toast_oldisnull[i] && + if (att->attlen == -1 && !toast_oldisnull[i] && VARATT_IS_EXTERNAL_ONDISK(old_value)) { if (toast_isnull[i] || !VARATT_IS_EXTERNAL_ONDISK(new_value) || @@ -668,12 +665,12 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup, /* * Now look at varlena attributes */ - if (att[i]->attlen == -1) + if (att->attlen == -1) { /* * If the table's attribute says PLAIN always, force it so. */ - if (att[i]->attstorage == 'p') + if (att->attstorage == 'p') toast_action[i] = 'p'; /* @@ -687,7 +684,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup, if (VARATT_IS_EXTERNAL(new_value)) { toast_oldexternal[i] = new_value; - if (att[i]->attstorage == 'p') + if (att->attstorage == 'p') new_value = heap_tuple_untoast_attr(new_value); else new_value = heap_tuple_fetch_attr(new_value); @@ -749,13 +746,15 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup, */ for (i = 0; i < numAttrs; i++) { + Form_pg_attribute att = TupleDescAttr(tupleDesc, i); + if (toast_action[i] != ' ') continue; if (VARATT_IS_EXTERNAL(DatumGetPointer(toast_values[i]))) continue; /* can't happen, toast_action would be 'p' */ if (VARATT_IS_COMPRESSED(DatumGetPointer(toast_values[i]))) continue; - if (att[i]->attstorage != 'x' && att[i]->attstorage != 'e') + if (att->attstorage != 'x' && att->attstorage != 'e') continue; if (toast_sizes[i] > biggest_size) { @@ -771,7 +770,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup, * Attempt to compress it inline, if it has attstorage 'x' */ i = biggest_attno; - if (att[i]->attstorage == 'x') + if (TupleDescAttr(tupleDesc, i)->attstorage == 'x') { old_value = toast_values[i]; new_value = toast_compress_datum(old_value); @@ -841,11 +840,13 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup, */ for (i = 0; i < numAttrs; i++) { + Form_pg_attribute att = TupleDescAttr(tupleDesc, i); + if (toast_action[i] == 'p') continue; if (VARATT_IS_EXTERNAL(DatumGetPointer(toast_values[i]))) continue; /* can't happen, toast_action would be 'p' */ - if (att[i]->attstorage != 'x' && att[i]->attstorage != 'e') + if (att->attstorage != 'x' && att->attstorage != 'e') continue; if (toast_sizes[i] > biggest_size) { @@ -896,7 +897,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup, continue; /* can't happen, toast_action would be 'p' */ if (VARATT_IS_COMPRESSED(DatumGetPointer(toast_values[i]))) continue; - if (att[i]->attstorage != 'm') + if (TupleDescAttr(tupleDesc, i)->attstorage != 'm') continue; if (toast_sizes[i] > biggest_size) { @@ -959,7 +960,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup, continue; if (VARATT_IS_EXTERNAL(DatumGetPointer(toast_values[i]))) continue; /* can't happen, toast_action would be 'p' */ - if (att[i]->attstorage != 'm') + if (TupleDescAttr(tupleDesc, i)->attstorage != 'm') continue; if (toast_sizes[i] > biggest_size) { @@ -1084,7 +1085,6 @@ HeapTuple toast_flatten_tuple(HeapTuple tup, TupleDesc tupleDesc) { HeapTuple new_tuple; - Form_pg_attribute *att = tupleDesc->attrs; int numAttrs = tupleDesc->natts; int i; Datum toast_values[MaxTupleAttributeNumber]; @@ -1104,7 +1104,7 @@ toast_flatten_tuple(HeapTuple tup, TupleDesc tupleDesc) /* * Look at non-null varlena attributes */ - if (!toast_isnull[i] && att[i]->attlen == -1) + if (!toast_isnull[i] && TupleDescAttr(tupleDesc, i)->attlen == -1) { struct varlena *new_value; @@ -1193,7 +1193,6 @@ toast_flatten_tuple_to_datum(HeapTupleHeader tup, int32 new_data_len; int32 new_tuple_len; HeapTupleData tmptup; - Form_pg_attribute *att = tupleDesc->attrs; int numAttrs = tupleDesc->natts; int i; bool has_nulls = false; @@ -1222,7 +1221,7 @@ toast_flatten_tuple_to_datum(HeapTupleHeader tup, */ if (toast_isnull[i]) has_nulls = true; - else if (att[i]->attlen == -1) + else if (TupleDescAttr(tupleDesc, i)->attlen == -1) { struct varlena *new_value; @@ -1307,7 +1306,6 @@ toast_build_flattened_tuple(TupleDesc tupleDesc, bool *isnull) { HeapTuple new_tuple; - Form_pg_attribute *att = tupleDesc->attrs; int numAttrs = tupleDesc->natts; int num_to_free; int i; @@ -1327,7 +1325,7 @@ toast_build_flattened_tuple(TupleDesc tupleDesc, /* * Look at non-null varlena attributes */ - if (!isnull[i] && att[i]->attlen == -1) + if (!isnull[i] && TupleDescAttr(tupleDesc, i)->attlen == -1) { struct varlena *new_value; diff --git a/src/backend/access/spgist/spgutils.c b/src/backend/access/spgist/spgutils.c index 8656af453c..22f64b0103 100644 --- a/src/backend/access/spgist/spgutils.c +++ b/src/backend/access/spgist/spgutils.c @@ -112,7 +112,7 @@ spgGetCache(Relation index) * tupdesc. We pass this to the opclass config function so that * polymorphic opclasses are possible. */ - atttype = index->rd_att->attrs[0]->atttypid; + atttype = TupleDescAttr(index->rd_att, 0)->atttypid; /* Call the config function to get config info for the opclass */ in.attType = atttype; diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index b3f0b3cc92..0453fd4ac1 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -609,7 +609,7 @@ boot_openrel(char *relname) if (attrtypes[i] == NULL) attrtypes[i] = AllocateAttribute(); memmove((char *) attrtypes[i], - (char *) boot_reldesc->rd_att->attrs[i], + (char *) TupleDescAttr(boot_reldesc->rd_att, i), ATTRIBUTE_FIXED_PART_SIZE); { @@ -816,7 +816,7 @@ InsertOneValue(char *value, int i) elog(DEBUG4, "inserting column %d value \"%s\"", i, value); - typoid = boot_reldesc->rd_att->attrs[i]->atttypid; + typoid = TupleDescAttr(boot_reldesc->rd_att, i)->atttypid; boot_get_type_io_data(typoid, &typlen, &typbyval, &typalign, @@ -843,10 +843,10 @@ InsertOneNull(int i) { elog(DEBUG4, "inserting column %d NULL", i); Assert(i >= 0 && i < MAXATTR); - if (boot_reldesc->rd_att->attrs[i]->attnotnull) + if (TupleDescAttr(boot_reldesc->rd_att, i)->attnotnull) elog(ERROR, "NULL value specified for not-null column \"%s\" of relation \"%s\"", - NameStr(boot_reldesc->rd_att->attrs[i]->attname), + NameStr(TupleDescAttr(boot_reldesc->rd_att, i)->attname), RelationGetRelationName(boot_reldesc)); values[i] = PointerGetDatum(NULL); Nulls[i] = true; diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index a376b99f1e..45ee9ac8b9 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -431,12 +431,14 @@ CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind, { for (i = 0; i < natts; i++) { - if (SystemAttributeByName(NameStr(tupdesc->attrs[i]->attname), + Form_pg_attribute attr = TupleDescAttr(tupdesc, i); + + if (SystemAttributeByName(NameStr(attr->attname), tupdesc->tdhasoid) != NULL) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_COLUMN), errmsg("column name \"%s\" conflicts with a system column name", - NameStr(tupdesc->attrs[i]->attname)))); + NameStr(attr->attname)))); } } @@ -447,12 +449,12 @@ CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind, { for (j = 0; j < i; j++) { - if (strcmp(NameStr(tupdesc->attrs[j]->attname), - NameStr(tupdesc->attrs[i]->attname)) == 0) + if (strcmp(NameStr(TupleDescAttr(tupdesc, j)->attname), + NameStr(TupleDescAttr(tupdesc, i)->attname)) == 0) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_COLUMN), errmsg("column name \"%s\" specified more than once", - NameStr(tupdesc->attrs[j]->attname)))); + NameStr(TupleDescAttr(tupdesc, j)->attname)))); } } @@ -461,9 +463,9 @@ CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind, */ for (i = 0; i < natts; i++) { - CheckAttributeType(NameStr(tupdesc->attrs[i]->attname), - tupdesc->attrs[i]->atttypid, - tupdesc->attrs[i]->attcollation, + CheckAttributeType(NameStr(TupleDescAttr(tupdesc, i)->attname), + TupleDescAttr(tupdesc, i)->atttypid, + TupleDescAttr(tupdesc, i)->attcollation, NIL, /* assume we're creating a new rowtype */ allow_system_table_mods); } @@ -545,7 +547,7 @@ CheckAttributeType(const char *attname, for (i = 0; i < tupdesc->natts; i++) { - Form_pg_attribute attr = tupdesc->attrs[i]; + Form_pg_attribute attr = TupleDescAttr(tupdesc, i); if (attr->attisdropped) continue; @@ -678,7 +680,7 @@ AddNewAttributeTuples(Oid new_rel_oid, */ for (i = 0; i < natts; i++) { - attr = tupdesc->attrs[i]; + attr = TupleDescAttr(tupdesc, i); /* Fill in the correct relation OID */ attr->attrelid = new_rel_oid; /* Make sure these are OK, too */ @@ -2245,7 +2247,7 @@ AddRelationNewConstraints(Relation rel, foreach(cell, newColDefaults) { RawColumnDefault *colDef = (RawColumnDefault *) lfirst(cell); - Form_pg_attribute atp = rel->rd_att->attrs[colDef->attnum - 1]; + Form_pg_attribute atp = TupleDescAttr(rel->rd_att, colDef->attnum - 1); Oid defOid; expr = cookDefault(pstate, colDef->raw_default, diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 25c5bead9f..c7b2f031f0 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -307,7 +307,7 @@ ConstructTupleDescriptor(Relation heapRelation, for (i = 0; i < numatts; i++) { AttrNumber atnum = indexInfo->ii_KeyAttrNumbers[i]; - Form_pg_attribute to = indexTupDesc->attrs[i]; + Form_pg_attribute to = TupleDescAttr(indexTupDesc, i); HeapTuple tuple; Form_pg_type typeTup; Form_pg_opclass opclassTup; @@ -333,7 +333,8 @@ ConstructTupleDescriptor(Relation heapRelation, */ if (atnum > natts) /* safety check */ elog(ERROR, "invalid column number %d", atnum); - from = heapTupDesc->attrs[AttrNumberGetAttrOffset(atnum)]; + from = TupleDescAttr(heapTupDesc, + AttrNumberGetAttrOffset(atnum)); } /* @@ -495,7 +496,7 @@ InitializeAttributeOids(Relation indexRelation, tupleDescriptor = RelationGetDescr(indexRelation); for (i = 0; i < numatts; i += 1) - tupleDescriptor->attrs[i]->attrelid = indexoid; + TupleDescAttr(tupleDescriptor, i)->attrelid = indexoid; } /* ---------------------------------------------------------------- @@ -524,14 +525,16 @@ AppendAttributeTuples(Relation indexRelation, int numatts) for (i = 0; i < numatts; i++) { + Form_pg_attribute attr = TupleDescAttr(indexTupDesc, i); + /* * There used to be very grotty code here to set these fields, but I * think it's unnecessary. They should be set already. */ - Assert(indexTupDesc->attrs[i]->attnum == i + 1); - Assert(indexTupDesc->attrs[i]->attcacheoff == -1); + Assert(attr->attnum == i + 1); + Assert(attr->attcacheoff == -1); - InsertPgAttributeTuple(pg_attribute, indexTupDesc->attrs[i], indstate); + InsertPgAttributeTuple(pg_attribute, attr, indstate); } CatalogCloseIndexes(indstate); diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c index 29756eb14e..6f517bbcda 100644 --- a/src/backend/catalog/toasting.c +++ b/src/backend/catalog/toasting.c @@ -235,9 +235,9 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid, * toast :-(. This is essential for chunk_data because type bytea is * toastable; hit the other two just to be sure. */ - tupdesc->attrs[0]->attstorage = 'p'; - tupdesc->attrs[1]->attstorage = 'p'; - tupdesc->attrs[2]->attstorage = 'p'; + TupleDescAttr(tupdesc, 0)->attstorage = 'p'; + TupleDescAttr(tupdesc, 1)->attstorage = 'p'; + TupleDescAttr(tupdesc, 2)->attstorage = 'p'; /* * Toast tables for regular relations go in pg_toast; those for temp @@ -402,33 +402,33 @@ needs_toast_table(Relation rel) bool maxlength_unknown = false; bool has_toastable_attrs = false; TupleDesc tupdesc; - Form_pg_attribute *att; int32 tuple_length; int i; tupdesc = rel->rd_att; - att = tupdesc->attrs; for (i = 0; i < tupdesc->natts; i++) { - if (att[i]->attisdropped) + Form_pg_attribute att = TupleDescAttr(tupdesc, i); + + if (att->attisdropped) continue; - data_length = att_align_nominal(data_length, att[i]->attalign); - if (att[i]->attlen > 0) + data_length = att_align_nominal(data_length, att->attalign); + if (att->attlen > 0) { /* Fixed-length types are never toastable */ - data_length += att[i]->attlen; + data_length += att->attlen; } else { - int32 maxlen = type_maximum_size(att[i]->atttypid, - att[i]->atttypmod); + int32 maxlen = type_maximum_size(att->atttypid, + att->atttypmod); if (maxlen < 0) maxlength_unknown = true; else data_length += maxlen; - if (att[i]->attstorage != 'p') + if (att->attstorage != 'p') has_toastable_attrs = true; } } diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index 2b638271b3..fbad13ea94 100644 --- a/src/backend/commands/analyze.c +++ b/src/backend/commands/analyze.c @@ -871,7 +871,7 @@ compute_index_stats(Relation onerel, double totalrows, static VacAttrStats * examine_attribute(Relation onerel, int attnum, Node *index_expr) { - Form_pg_attribute attr = onerel->rd_att->attrs[attnum - 1]; + Form_pg_attribute attr = TupleDescAttr(onerel->rd_att, attnum - 1); HeapTuple typtuple; VacAttrStats *stats; int i; diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index f51f8b9492..48f1e6e2ad 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -1714,7 +1714,7 @@ reform_and_rewrite_tuple(HeapTuple tuple, /* Be sure to null out any dropped columns */ for (i = 0; i < newTupDesc->natts; i++) { - if (newTupDesc->attrs[i]->attisdropped) + if (TupleDescAttr(newTupDesc, i)->attisdropped) isnull[i] = true; } diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index 375a25fbcf..cfa3f059c2 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -1583,12 +1583,13 @@ BeginCopy(ParseState *pstate, foreach(cur, attnums) { int attnum = lfirst_int(cur); + Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1); if (!list_member_int(cstate->attnumlist, attnum)) ereport(ERROR, (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), errmsg("FORCE_QUOTE column \"%s\" not referenced by COPY", - NameStr(tupDesc->attrs[attnum - 1]->attname)))); + NameStr(attr->attname)))); cstate->force_quote_flags[attnum - 1] = true; } } @@ -1605,12 +1606,13 @@ BeginCopy(ParseState *pstate, foreach(cur, attnums) { int attnum = lfirst_int(cur); + Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1); if (!list_member_int(cstate->attnumlist, attnum)) ereport(ERROR, (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), errmsg("FORCE_NOT_NULL column \"%s\" not referenced by COPY", - NameStr(tupDesc->attrs[attnum - 1]->attname)))); + NameStr(attr->attname)))); cstate->force_notnull_flags[attnum - 1] = true; } } @@ -1627,12 +1629,13 @@ BeginCopy(ParseState *pstate, foreach(cur, attnums) { int attnum = lfirst_int(cur); + Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1); if (!list_member_int(cstate->attnumlist, attnum)) ereport(ERROR, (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), errmsg("FORCE_NULL column \"%s\" not referenced by COPY", - NameStr(tupDesc->attrs[attnum - 1]->attname)))); + NameStr(attr->attname)))); cstate->force_null_flags[attnum - 1] = true; } } @@ -1650,12 +1653,13 @@ BeginCopy(ParseState *pstate, foreach(cur, attnums) { int attnum = lfirst_int(cur); + Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1); if (!list_member_int(cstate->attnumlist, attnum)) ereport(ERROR, (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), errmsg_internal("selected column \"%s\" not referenced by COPY", - NameStr(tupDesc->attrs[attnum - 1]->attname)))); + NameStr(attr->attname)))); cstate->convert_select_flags[attnum - 1] = true; } } @@ -1919,7 +1923,6 @@ CopyTo(CopyState cstate) { TupleDesc tupDesc; int num_phys_attrs; - Form_pg_attribute *attr; ListCell *cur; uint64 processed; @@ -1927,7 +1930,6 @@ CopyTo(CopyState cstate) tupDesc = RelationGetDescr(cstate->rel); else tupDesc = cstate->queryDesc->tupDesc; - attr = tupDesc->attrs; num_phys_attrs = tupDesc->natts; cstate->null_print_client = cstate->null_print; /* default */ @@ -1941,13 +1943,14 @@ CopyTo(CopyState cstate) int attnum = lfirst_int(cur); Oid out_func_oid; bool isvarlena; + Form_pg_attribute attr = TupleDescAttr(tupDesc, attnum - 1); if (cstate->binary) - getTypeBinaryOutputInfo(attr[attnum - 1]->atttypid, + getTypeBinaryOutputInfo(attr->atttypid, &out_func_oid, &isvarlena); else - getTypeOutputInfo(attr[attnum - 1]->atttypid, + getTypeOutputInfo(attr->atttypid, &out_func_oid, &isvarlena); fmgr_info(out_func_oid, &cstate->out_functions[attnum - 1]); @@ -2004,7 +2007,7 @@ CopyTo(CopyState cstate) CopySendChar(cstate, cstate->delim[0]); hdr_delim = true; - colname = NameStr(attr[attnum - 1]->attname); + colname = NameStr(TupleDescAttr(tupDesc, attnum - 1)->attname); CopyAttributeOutCSV(cstate, colname, false, list_length(cstate->attnumlist) == 1); @@ -2969,7 +2972,6 @@ BeginCopyFrom(ParseState *pstate, CopyState cstate; bool pipe = (filename == NULL); TupleDesc tupDesc; - Form_pg_attribute *attr; AttrNumber num_phys_attrs, num_defaults; FmgrInfo *in_functions; @@ -3004,7 +3006,6 @@ BeginCopyFrom(ParseState *pstate, cstate->range_table = pstate->p_rtable; tupDesc = RelationGetDescr(cstate->rel); - attr = tupDesc->attrs; num_phys_attrs = tupDesc->natts; num_defaults = 0; volatile_defexprs = false; @@ -3022,16 +3023,18 @@ BeginCopyFrom(ParseState *pstate, for (attnum = 1; attnum <= num_phys_attrs; attnum++) { + Form_pg_attribute att = TupleDescAttr(tupDesc, attnum - 1); + /* We don't need info for dropped attributes */ - if (attr[attnum - 1]->attisdropped) + if (att->attisdropped) continue; /* Fetch the input function and typioparam info */ if (cstate->binary) - getTypeBinaryInputInfo(attr[attnum - 1]->atttypid, + getTypeBinaryInputInfo(att->atttypid, &in_func_oid, &typioparams[attnum - 1]); else - getTypeInputInfo(attr[attnum - 1]->atttypid, + getTypeInputInfo(att->atttypid, &in_func_oid, &typioparams[attnum - 1]); fmgr_info(in_func_oid, &in_functions[attnum - 1]); @@ -3273,7 +3276,6 @@ NextCopyFrom(CopyState cstate, ExprContext *econtext, Datum *values, bool *nulls, Oid *tupleOid) { TupleDesc tupDesc; - Form_pg_attribute *attr; AttrNumber num_phys_attrs, attr_count, num_defaults = cstate->num_defaults; @@ -3287,7 +3289,6 @@ NextCopyFrom(CopyState cstate, ExprContext *econtext, ExprState **defexprs = cstate->defexprs; tupDesc = RelationGetDescr(cstate->rel); - attr = tupDesc->attrs; num_phys_attrs = tupDesc->natts; attr_count = list_length(cstate->attnumlist); nfields = file_has_oids ? (attr_count + 1) : attr_count; @@ -3349,12 +3350,13 @@ NextCopyFrom(CopyState cstate, ExprContext *econtext, { int attnum = lfirst_int(cur); int m = attnum - 1; + Form_pg_attribute att = TupleDescAttr(tupDesc, m); if (fieldno >= fldct) ereport(ERROR, (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), errmsg("missing data for column \"%s\"", - NameStr(attr[m]->attname)))); + NameStr(att->attname)))); string = field_strings[fieldno++]; if (cstate->convert_select_flags && @@ -3388,12 +3390,12 @@ NextCopyFrom(CopyState cstate, ExprContext *econtext, } } - cstate->cur_attname = NameStr(attr[m]->attname); + cstate->cur_attname = NameStr(att->attname); cstate->cur_attval = string; values[m] = InputFunctionCall(&in_functions[m], string, typioparams[m], - attr[m]->atttypmod); + att->atttypmod); if (string != NULL) nulls[m] = false; cstate->cur_attname = NULL; @@ -3472,14 +3474,15 @@ NextCopyFrom(CopyState cstate, ExprContext *econtext, { int attnum = lfirst_int(cur); int m = attnum - 1; + Form_pg_attribute att = TupleDescAttr(tupDesc, m); - cstate->cur_attname = NameStr(attr[m]->attname); + cstate->cur_attname = NameStr(att->attname); i++; values[m] = CopyReadBinaryAttribute(cstate, i, &in_functions[m], typioparams[m], - attr[m]->atttypmod, + att->atttypmod, &nulls[m]); cstate->cur_attname = NULL; } @@ -4709,13 +4712,12 @@ CopyGetAttnums(TupleDesc tupDesc, Relation rel, List *attnamelist) if (attnamelist == NIL) { /* Generate default column list */ - Form_pg_attribute *attr = tupDesc->attrs; int attr_count = tupDesc->natts; int i; for (i = 0; i < attr_count; i++) { - if (attr[i]->attisdropped) + if (TupleDescAttr(tupDesc, i)->attisdropped) continue; attnums = lappend_int(attnums, i + 1); } @@ -4735,11 +4737,13 @@ CopyGetAttnums(TupleDesc tupDesc, Relation rel, List *attnamelist) attnum = InvalidAttrNumber; for (i = 0; i < tupDesc->natts; i++) { - if (tupDesc->attrs[i]->attisdropped) + Form_pg_attribute att = TupleDescAttr(tupDesc, i); + + if (att->attisdropped) continue; - if (namestrcmp(&(tupDesc->attrs[i]->attname), name) == 0) + if (namestrcmp(&(att->attname), name) == 0) { - attnum = tupDesc->attrs[i]->attnum; + attnum = att->attnum; break; } } diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c index 97f9c55d6e..e60210cb24 100644 --- a/src/backend/commands/createas.c +++ b/src/backend/commands/createas.c @@ -468,7 +468,7 @@ intorel_startup(DestReceiver *self, int operation, TupleDesc typeinfo) lc = list_head(into->colNames); for (attnum = 0; attnum < typeinfo->natts; attnum++) { - Form_pg_attribute attribute = typeinfo->attrs[attnum]; + Form_pg_attribute attribute = TupleDescAttr(typeinfo, attnum); ColumnDef *col; char *colname; diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 620704ec49..b61aaac284 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -242,7 +242,7 @@ CheckIndexCompatible(Oid oldId, for (i = 0; i < old_natts; i++) { if (IsPolymorphicType(get_opclass_input_type(classObjectId[i])) && - irel->rd_att->attrs[i]->atttypid != typeObjectId[i]) + TupleDescAttr(irel->rd_att, i)->atttypid != typeObjectId[i]) { ret = false; break; @@ -270,7 +270,7 @@ CheckIndexCompatible(Oid oldId, op_input_types(indexInfo->ii_ExclusionOps[i], &left, &right); if ((IsPolymorphicType(left) || IsPolymorphicType(right)) && - irel->rd_att->attrs[i]->atttypid != typeObjectId[i]) + TupleDescAttr(irel->rd_att, i)->atttypid != typeObjectId[i]) { ret = false; break; diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c index 7d57f97442..d2e0376511 100644 --- a/src/backend/commands/matview.c +++ b/src/backend/commands/matview.c @@ -727,6 +727,7 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner, for (i = 0; i < numatts; i++) { int attnum = indexStruct->indkey.values[i]; + Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1); Oid type; Oid op; const char *colname; @@ -745,7 +746,7 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner, if (foundUniqueIndex) appendStringInfoString(&querybuf, " AND "); - colname = quote_identifier(NameStr((tupdesc->attrs[attnum - 1])->attname)); + colname = quote_identifier(NameStr(attr->attname)); appendStringInfo(&querybuf, "newdata.%s ", colname); type = attnumTypeId(matviewRel, attnum); op = lookup_type_cache(type, TYPECACHE_EQ_OPR)->eq_opr; diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 83cb460164..0f08245a67 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -685,8 +685,10 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, foreach(listptr, stmt->tableElts) { ColumnDef *colDef = lfirst(listptr); + Form_pg_attribute attr; attnum++; + attr = TupleDescAttr(descriptor, attnum - 1); if (colDef->raw_default != NULL) { @@ -698,7 +700,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, rawEnt->attnum = attnum; rawEnt->raw_default = colDef->raw_default; rawDefaults = lappend(rawDefaults, rawEnt); - descriptor->attrs[attnum - 1]->atthasdef = true; + attr->atthasdef = true; } else if (colDef->cooked_default != NULL) { @@ -715,11 +717,11 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, cooked->inhcount = 0; /* ditto */ cooked->is_no_inherit = false; cookedDefaults = lappend(cookedDefaults, cooked); - descriptor->attrs[attnum - 1]->atthasdef = true; + attr->atthasdef = true; } if (colDef->identity) - descriptor->attrs[attnum - 1]->attidentity = colDef->identity; + attr->attidentity = colDef->identity; } /* @@ -1833,7 +1835,8 @@ MergeAttributes(List *schema, List *supers, char relpersistence, for (parent_attno = 1; parent_attno <= tupleDesc->natts; parent_attno++) { - Form_pg_attribute attribute = tupleDesc->attrs[parent_attno - 1]; + Form_pg_attribute attribute = TupleDescAttr(tupleDesc, + parent_attno - 1); char *attributeName = NameStr(attribute->attname); int exist_attno; ColumnDef *def; @@ -4417,8 +4420,9 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode) */ for (i = 0; i < newTupDesc->natts; i++) { - if (newTupDesc->attrs[i]->attnotnull && - !newTupDesc->attrs[i]->attisdropped) + Form_pg_attribute attr = TupleDescAttr(newTupDesc, i); + + if (attr->attnotnull && !attr->attisdropped) notnull_attrs = lappend_int(notnull_attrs, i); } if (notnull_attrs) @@ -4482,7 +4486,7 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode) */ for (i = 0; i < newTupDesc->natts; i++) { - if (newTupDesc->attrs[i]->attisdropped) + if (TupleDescAttr(newTupDesc, i)->attisdropped) dropped_attrs = lappend_int(dropped_attrs, i); } @@ -4556,11 +4560,15 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode) int attn = lfirst_int(l); if (heap_attisnull(tuple, attn + 1)) + { + Form_pg_attribute attr = TupleDescAttr(newTupDesc, attn); + ereport(ERROR, (errcode(ERRCODE_NOT_NULL_VIOLATION), errmsg("column \"%s\" contains null values", - NameStr(newTupDesc->attrs[attn]->attname)), + NameStr(attr->attname)), errtablecol(oldrel, attn + 1))); + } } foreach(l, tab->constraints) @@ -4927,7 +4935,7 @@ find_composite_type_dependencies(Oid typeOid, Relation origRelation, continue; rel = relation_open(pg_depend->objid, AccessShareLock); - att = rel->rd_att->attrs[pg_depend->objsubid - 1]; + att = TupleDescAttr(rel->rd_att, pg_depend->objsubid - 1); if (rel->rd_rel->relkind == RELKIND_RELATION || rel->rd_rel->relkind == RELKIND_MATVIEW || @@ -5693,7 +5701,7 @@ ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode) AttrNumber parent_attnum; parent_attnum = get_attnum(parentId, colName); - if (tupDesc->attrs[parent_attnum - 1]->attnotnull) + if (TupleDescAttr(tupDesc, parent_attnum - 1)->attnotnull) ereport(ERROR, (errcode(ERRCODE_INVALID_TABLE_DEFINITION), errmsg("column \"%s\" is marked NOT NULL in parent table", @@ -7286,13 +7294,15 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel, CoercionPathType new_pathtype; Oid old_castfunc; Oid new_castfunc; + Form_pg_attribute attr = TupleDescAttr(tab->oldDesc, + fkattnum[i] - 1); /* * Identify coercion pathways from each of the old and new FK-side * column types to the right (foreign) operand type of the pfeqop. * We may assume that pg_constraint.conkey is not changing. */ - old_fktype = tab->oldDesc->attrs[fkattnum[i] - 1]->atttypid; + old_fktype = attr->atttypid; new_fktype = fktype; old_pathtype = findFkeyCast(pfeqop_right, old_fktype, &old_castfunc); @@ -8963,7 +8973,8 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, ColumnDef *def = (ColumnDef *) cmd->def; TypeName *typeName = def->typeName; HeapTuple heapTup; - Form_pg_attribute attTup; + Form_pg_attribute attTup, + attOldTup; AttrNumber attnum; HeapTuple typeTuple; Form_pg_type tform; @@ -8989,10 +9000,11 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, colName, RelationGetRelationName(rel)))); attTup = (Form_pg_attribute) GETSTRUCT(heapTup); attnum = attTup->attnum; + attOldTup = TupleDescAttr(tab->oldDesc, attnum - 1); /* Check for multiple ALTER TYPE on same column --- can't cope */ - if (attTup->atttypid != tab->oldDesc->attrs[attnum - 1]->atttypid || - attTup->atttypmod != tab->oldDesc->attrs[attnum - 1]->atttypmod) + if (attTup->atttypid != attOldTup->atttypid || + attTup->atttypmod != attOldTup->atttypmod) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot alter type of column \"%s\" twice", @@ -11209,7 +11221,8 @@ MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel) for (parent_attno = 1; parent_attno <= parent_natts; parent_attno++) { - Form_pg_attribute attribute = tupleDesc->attrs[parent_attno - 1]; + Form_pg_attribute attribute = TupleDescAttr(tupleDesc, + parent_attno - 1); char *attributeName = NameStr(attribute->attname); /* Ignore dropped columns in the parent. */ @@ -11822,7 +11835,7 @@ ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode) *table_attname; /* Get the next non-dropped type attribute. */ - type_attr = typeTupleDesc->attrs[type_attno - 1]; + type_attr = TupleDescAttr(typeTupleDesc, type_attno - 1); if (type_attr->attisdropped) continue; type_attname = NameStr(type_attr->attname); @@ -11835,7 +11848,8 @@ ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode) (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("table is missing column \"%s\"", type_attname))); - table_attr = tableTupleDesc->attrs[table_attno++ - 1]; + table_attr = TupleDescAttr(tableTupleDesc, table_attno - 1); + table_attno++; } while (table_attr->attisdropped); table_attname = NameStr(table_attr->attname); @@ -11860,7 +11874,8 @@ ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode) /* Any remaining columns at the end of the table had better be dropped. */ for (; table_attno <= tableTupleDesc->natts; table_attno++) { - Form_pg_attribute table_attr = tableTupleDesc->attrs[table_attno - 1]; + Form_pg_attribute table_attr = TupleDescAttr(tableTupleDesc, + table_attno - 1); if (!table_attr->attisdropped) ereport(ERROR, @@ -12147,7 +12162,7 @@ ATExecReplicaIdentity(Relation rel, ReplicaIdentityStmt *stmt, LOCKMODE lockmode errmsg("index \"%s\" cannot be used as replica identity because column %d is a system column", RelationGetRelationName(indexRel), attno))); - attr = rel->rd_att->attrs[attno - 1]; + attr = TupleDescAttr(rel->rd_att, attno - 1); if (!attr->attnotnull) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), @@ -13451,7 +13466,7 @@ PartConstraintImpliedByRelConstraint(Relation scanrel, for (i = 1; i <= natts; i++) { - Form_pg_attribute att = scanrel->rd_att->attrs[i - 1]; + Form_pg_attribute att = TupleDescAttr(scanrel->rd_att, i - 1); if (att->attnotnull && !att->attisdropped) { @@ -13733,7 +13748,7 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd) natts = tupleDesc->natts; for (attno = 1; attno <= natts; attno++) { - Form_pg_attribute attribute = tupleDesc->attrs[attno - 1]; + Form_pg_attribute attribute = TupleDescAttr(tupleDesc, attno - 1); char *attributeName = NameStr(attribute->attname); /* Ignore dropped */ diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index 29ac5d569d..7ed16aeff4 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -2324,6 +2324,7 @@ AlterDomainNotNull(List *names, bool notNull) for (i = 0; i < rtc->natts; i++) { int attnum = rtc->atts[i]; + Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1); if (heap_attisnull(tuple, attnum)) { @@ -2338,7 +2339,7 @@ AlterDomainNotNull(List *names, bool notNull) ereport(ERROR, (errcode(ERRCODE_NOT_NULL_VIOLATION), errmsg("column \"%s\" of table \"%s\" contains null values", - NameStr(tupdesc->attrs[attnum - 1]->attname), + NameStr(attr->attname), RelationGetRelationName(testrel)), errtablecol(testrel, attnum))); } @@ -2722,6 +2723,7 @@ validateDomainConstraint(Oid domainoid, char *ccbin) Datum d; bool isNull; Datum conResult; + Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1); d = heap_getattr(tuple, attnum, tupdesc, &isNull); @@ -2745,7 +2747,7 @@ validateDomainConstraint(Oid domainoid, char *ccbin) ereport(ERROR, (errcode(ERRCODE_CHECK_VIOLATION), errmsg("column \"%s\" of table \"%s\" contains values that violate the new constraint", - NameStr(tupdesc->attrs[attnum - 1]->attname), + NameStr(attr->attname), RelationGetRelationName(testrel)), errtablecol(testrel, attnum))); } @@ -2930,7 +2932,7 @@ get_rels_with_domain(Oid domainOid, LOCKMODE lockmode) */ if (pg_depend->objsubid > RelationGetNumberOfAttributes(rtc->rel)) continue; - pg_att = rtc->rel->rd_att->attrs[pg_depend->objsubid - 1]; + pg_att = TupleDescAttr(rtc->rel->rd_att, pg_depend->objsubid - 1); if (pg_att->attisdropped || pg_att->atttypid != domainOid) continue; diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c index f25a5658d6..076e2a3a40 100644 --- a/src/backend/commands/view.c +++ b/src/backend/commands/view.c @@ -283,8 +283,8 @@ checkViewTupleDesc(TupleDesc newdesc, TupleDesc olddesc) for (i = 0; i < olddesc->natts; i++) { - Form_pg_attribute newattr = newdesc->attrs[i]; - Form_pg_attribute oldattr = olddesc->attrs[i]; + Form_pg_attribute newattr = TupleDescAttr(newdesc, i); + Form_pg_attribute oldattr = TupleDescAttr(olddesc, i); /* XXX msg not right, but we don't support DROP COL on view anyway */ if (newattr->attisdropped != oldattr->attisdropped) diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c index 7496189fab..be9d23bc32 100644 --- a/src/backend/executor/execExpr.c +++ b/src/backend/executor/execExpr.c @@ -347,7 +347,7 @@ ExecBuildProjectionInfo(List *targetList, isSafeVar = true; /* can't check, just assume OK */ else if (attnum <= inputDesc->natts) { - Form_pg_attribute attr = inputDesc->attrs[attnum - 1]; + Form_pg_attribute attr = TupleDescAttr(inputDesc, attnum - 1); /* * If user attribute is dropped or has a type mismatch, don't @@ -1492,7 +1492,6 @@ ExecInitExprRec(Expr *node, PlanState *parent, ExprState *state, RowExpr *rowexpr = (RowExpr *) node; int nelems = list_length(rowexpr->args); TupleDesc tupdesc; - Form_pg_attribute *attrs; int i; ListCell *l; @@ -1539,13 +1538,13 @@ ExecInitExprRec(Expr *node, PlanState *parent, ExprState *state, memset(scratch.d.row.elemnulls, true, sizeof(bool) * nelems); /* Set up evaluation, skipping any deleted columns */ - attrs = tupdesc->attrs; i = 0; foreach(l, rowexpr->args) { + Form_pg_attribute att = TupleDescAttr(tupdesc, i); Expr *e = (Expr *) lfirst(l); - if (!attrs[i]->attisdropped) + if (!att->attisdropped) { /* * Guard against ALTER COLUMN TYPE on rowtype since @@ -1553,12 +1552,12 @@ ExecInitExprRec(Expr *node, PlanState *parent, ExprState *state, * typmod too? Not sure we can be sure it'll be the * same. */ - if (exprType((Node *) e) != attrs[i]->atttypid) + if (exprType((Node *) e) != att->atttypid) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("ROW() column has type %s instead of type %s", format_type_be(exprType((Node *) e)), - format_type_be(attrs[i]->atttypid)))); + format_type_be(att->atttypid)))); } else { diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index f2a52f6213..83e04471e4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -1553,7 +1553,7 @@ CheckVarSlotCompatibility(TupleTableSlot *slot, int attnum, Oid vartype) elog(ERROR, "attribute number %d exceeds number of columns %d", attnum, slot_tupdesc->natts); - attr = slot_tupdesc->attrs[attnum - 1]; + attr = TupleDescAttr(slot_tupdesc, attnum - 1); if (attr->attisdropped) ereport(ERROR, @@ -2081,7 +2081,7 @@ ExecEvalRowNullInt(ExprState *state, ExprEvalStep *op, for (att = 1; att <= tupDesc->natts; att++) { /* ignore dropped columns */ - if (tupDesc->attrs[att - 1]->attisdropped) + if (TupleDescAttr(tupDesc, att - 1)->attisdropped) continue; if (heap_attisnull(&tmptup, att)) { @@ -2494,7 +2494,7 @@ ExecEvalFieldSelect(ExprState *state, ExprEvalStep *op, ExprContext *econtext) if (fieldnum > tupDesc->natts) /* should never happen */ elog(ERROR, "attribute number %d exceeds number of columns %d", fieldnum, tupDesc->natts); - attr = tupDesc->attrs[fieldnum - 1]; + attr = TupleDescAttr(tupDesc, fieldnum - 1); /* Check for dropped column, and force a NULL result if so */ if (attr->attisdropped) @@ -3441,8 +3441,8 @@ ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext) for (i = 0; i < var_tupdesc->natts; i++) { - Form_pg_attribute vattr = var_tupdesc->attrs[i]; - Form_pg_attribute sattr = slot_tupdesc->attrs[i]; + Form_pg_attribute vattr = TupleDescAttr(var_tupdesc, i); + Form_pg_attribute sattr = TupleDescAttr(slot_tupdesc, i); if (vattr->atttypid == sattr->atttypid) continue; /* no worries */ @@ -3540,8 +3540,8 @@ ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext) for (i = 0; i < var_tupdesc->natts; i++) { - Form_pg_attribute vattr = var_tupdesc->attrs[i]; - Form_pg_attribute sattr = tupleDesc->attrs[i]; + Form_pg_attribute vattr = TupleDescAttr(var_tupdesc, i); + Form_pg_attribute sattr = TupleDescAttr(tupleDesc, i); if (!vattr->attisdropped) continue; /* already checked non-dropped cols */ diff --git a/src/backend/executor/execJunk.c b/src/backend/executor/execJunk.c index a422327c88..7fcd940fdb 100644 --- a/src/backend/executor/execJunk.c +++ b/src/backend/executor/execJunk.c @@ -168,7 +168,7 @@ ExecInitJunkFilterConversion(List *targetList, t = list_head(targetList); for (i = 0; i < cleanLength; i++) { - if (cleanTupType->attrs[i]->attisdropped) + if (TupleDescAttr(cleanTupType, i)->attisdropped) continue; /* map entry is already zero */ for (;;) { diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 4582a3caa0..2946a0edee 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -1950,8 +1950,9 @@ ExecConstraints(ResultRelInfo *resultRelInfo, for (attrChk = 1; attrChk <= natts; attrChk++) { - if (tupdesc->attrs[attrChk - 1]->attnotnull && - slot_attisnull(slot, attrChk)) + Form_pg_attribute att = TupleDescAttr(tupdesc, attrChk - 1); + + if (att->attnotnull && slot_attisnull(slot, attrChk)) { char *val_desc; Relation orig_rel = rel; @@ -1994,7 +1995,7 @@ ExecConstraints(ResultRelInfo *resultRelInfo, ereport(ERROR, (errcode(ERRCODE_NOT_NULL_VIOLATION), errmsg("null value in column \"%s\" violates not-null constraint", - NameStr(orig_tupdesc->attrs[attrChk - 1]->attname)), + NameStr(att->attname)), val_desc ? errdetail("Failing row contains %s.", val_desc) : 0, errtablecol(orig_rel, attrChk))); } @@ -2261,9 +2262,10 @@ ExecBuildSlotValueDescription(Oid reloid, bool column_perm = false; char *val; int vallen; + Form_pg_attribute att = TupleDescAttr(tupdesc, i); /* ignore dropped columns */ - if (tupdesc->attrs[i]->attisdropped) + if (att->attisdropped) continue; if (!table_perm) @@ -2274,9 +2276,9 @@ ExecBuildSlotValueDescription(Oid reloid, * for the column. If not, omit this column from the error * message. */ - aclresult = pg_attribute_aclcheck(reloid, tupdesc->attrs[i]->attnum, + aclresult = pg_attribute_aclcheck(reloid, att->attnum, GetUserId(), ACL_SELECT); - if (bms_is_member(tupdesc->attrs[i]->attnum - FirstLowInvalidHeapAttributeNumber, + if (bms_is_member(att->attnum - FirstLowInvalidHeapAttributeNumber, modifiedCols) || aclresult == ACLCHECK_OK) { column_perm = any_perm = true; @@ -2286,7 +2288,7 @@ ExecBuildSlotValueDescription(Oid reloid, else write_comma_collist = true; - appendStringInfoString(&collist, NameStr(tupdesc->attrs[i]->attname)); + appendStringInfoString(&collist, NameStr(att->attname)); } } @@ -2299,7 +2301,7 @@ ExecBuildSlotValueDescription(Oid reloid, Oid foutoid; bool typisvarlena; - getTypeOutputInfo(tupdesc->attrs[i]->atttypid, + getTypeOutputInfo(att->atttypid, &foutoid, &typisvarlena); val = OidOutputFunctionCall(foutoid, slot->tts_values[i]); } diff --git a/src/backend/executor/execReplication.c b/src/backend/executor/execReplication.c index 3819de28ad..fbb8108512 100644 --- a/src/backend/executor/execReplication.c +++ b/src/backend/executor/execReplication.c @@ -247,7 +247,7 @@ tuple_equals_slot(TupleDesc desc, HeapTuple tup, TupleTableSlot *slot) if (isnull[attrnum]) continue; - att = desc->attrs[attrnum]; + att = TupleDescAttr(desc, attrnum); typentry = lookup_type_cache(att->atttypid, TYPECACHE_EQ_OPR_FINFO); if (!OidIsValid(typentry->eq_opr_finfo.fn_oid)) diff --git a/src/backend/executor/execSRF.c b/src/backend/executor/execSRF.c index 138e86ac67..8bc90a6c7e 100644 --- a/src/backend/executor/execSRF.c +++ b/src/backend/executor/execSRF.c @@ -903,8 +903,8 @@ tupledesc_match(TupleDesc dst_tupdesc, TupleDesc src_tupdesc) for (i = 0; i < dst_tupdesc->natts; i++) { - Form_pg_attribute dattr = dst_tupdesc->attrs[i]; - Form_pg_attribute sattr = src_tupdesc->attrs[i]; + Form_pg_attribute dattr = TupleDescAttr(dst_tupdesc, i); + Form_pg_attribute sattr = TupleDescAttr(src_tupdesc, i); if (IsBinaryCoercible(sattr->atttypid, dattr->atttypid)) continue; /* no worries */ diff --git a/src/backend/executor/execScan.c b/src/backend/executor/execScan.c index 4f131b3ee0..47a34a044a 100644 --- a/src/backend/executor/execScan.c +++ b/src/backend/executor/execScan.c @@ -269,7 +269,7 @@ tlist_matches_tupdesc(PlanState *ps, List *tlist, Index varno, TupleDesc tupdesc /* Check the tlist attributes */ for (attrno = 1; attrno <= numattrs; attrno++) { - Form_pg_attribute att_tup = tupdesc->attrs[attrno - 1]; + Form_pg_attribute att_tup = TupleDescAttr(tupdesc, attrno - 1); Var *var; if (tlist_item == NULL) diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c index 7ae70a877a..31f814c0f0 100644 --- a/src/backend/executor/execTuples.c +++ b/src/backend/executor/execTuples.c @@ -997,7 +997,8 @@ ExecTypeSetColNames(TupleDesc typeInfo, List *namesList) /* Guard against too-long names list */ if (colno >= typeInfo->natts) break; - attr = typeInfo->attrs[colno++]; + attr = TupleDescAttr(typeInfo, colno); + colno++; /* Ignore empty aliases (these must be for dropped columns) */ if (cname[0] == '\0') @@ -1090,13 +1091,15 @@ TupleDescGetAttInMetadata(TupleDesc tupdesc) for (i = 0; i < natts; i++) { + Form_pg_attribute att = TupleDescAttr(tupdesc, i); + /* Ignore dropped attributes */ - if (!tupdesc->attrs[i]->attisdropped) + if (!att->attisdropped) { - atttypeid = tupdesc->attrs[i]->atttypid; + atttypeid = att->atttypid; getTypeInputInfo(atttypeid, &attinfuncid, &attioparams[i]); fmgr_info(attinfuncid, &attinfuncinfo[i]); - atttypmods[i] = tupdesc->attrs[i]->atttypmod; + atttypmods[i] = att->atttypmod; } } attinmeta->attinfuncs = attinfuncinfo; @@ -1127,7 +1130,7 @@ BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values) /* Call the "in" function for each non-dropped attribute */ for (i = 0; i < natts; i++) { - if (!tupdesc->attrs[i]->attisdropped) + if (!TupleDescAttr(tupdesc, i)->attisdropped) { /* Non-dropped attributes */ dvalues[i] = InputFunctionCall(&attinmeta->attinfuncs[i], diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c index c398846879..9528393976 100644 --- a/src/backend/executor/execUtils.c +++ b/src/backend/executor/execUtils.c @@ -917,9 +917,11 @@ GetAttributeByName(HeapTupleHeader tuple, const char *attname, bool *isNull) attrno = InvalidAttrNumber; for (i = 0; i < tupDesc->natts; i++) { - if (namestrcmp(&(tupDesc->attrs[i]->attname), attname) == 0) + Form_pg_attribute att = TupleDescAttr(tupDesc, i); + + if (namestrcmp(&(att->attname), attname) == 0) { - attrno = tupDesc->attrs[i]->attnum; + attrno = att->attnum; break; } } diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c index 3630f5d966..b7ac5f7432 100644 --- a/src/backend/executor/functions.c +++ b/src/backend/executor/functions.c @@ -1759,7 +1759,7 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList, errmsg("return type mismatch in function declared to return %s", format_type_be(rettype)), errdetail("Final statement returns too many columns."))); - attr = tupdesc->attrs[colindex - 1]; + attr = TupleDescAttr(tupdesc, colindex - 1); if (attr->attisdropped && modifyTargetList) { Expr *null_expr; @@ -1816,7 +1816,7 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList, /* remaining columns in tupdesc had better all be dropped */ for (colindex++; colindex <= tupnatts; colindex++) { - if (!tupdesc->attrs[colindex - 1]->attisdropped) + if (!TupleDescAttr(tupdesc, colindex - 1)->attisdropped) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("return type mismatch in function declared to return %s", diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index 6a26773a49..0ae5873868 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -724,12 +724,16 @@ initialize_aggregate(AggState *aggstate, AggStatePerTrans pertrans, * process_ordered_aggregate_single.) */ if (pertrans->numInputs == 1) + { + Form_pg_attribute attr = TupleDescAttr(pertrans->sortdesc, 0); + pertrans->sortstates[aggstate->current_set] = - tuplesort_begin_datum(pertrans->sortdesc->attrs[0]->atttypid, + tuplesort_begin_datum(attr->atttypid, pertrans->sortOperators[0], pertrans->sortCollations[0], pertrans->sortNullsFirst[0], work_mem, false); + } else pertrans->sortstates[aggstate->current_set] = tuplesort_begin_heap(pertrans->sortdesc, diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c index 70a6b847a0..e12721a9b6 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -95,7 +95,8 @@ ExecCheckPlanOutput(Relation resultRel, List *targetList) (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("table row type and query-specified row type do not match"), errdetail("Query has too many columns."))); - attr = resultDesc->attrs[attno++]; + attr = TupleDescAttr(resultDesc, attno); + attno++; if (!attr->attisdropped) { diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c index fe10e809df..77ef6f3df1 100644 --- a/src/backend/executor/nodeSubplan.c +++ b/src/backend/executor/nodeSubplan.c @@ -360,7 +360,7 @@ ExecScanSubPlan(SubPlanState *node, found = true; /* stash away current value */ - Assert(subplan->firstColType == tdesc->attrs[0]->atttypid); + Assert(subplan->firstColType == TupleDescAttr(tdesc, 0)->atttypid); dvalue = slot_getattr(slot, 1, &disnull); astate = accumArrayResultAny(astate, dvalue, disnull, subplan->firstColType, oldcontext); @@ -992,7 +992,7 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) found = true; /* stash away current value */ - Assert(subplan->firstColType == tdesc->attrs[0]->atttypid); + Assert(subplan->firstColType == TupleDescAttr(tdesc, 0)->atttypid); dvalue = slot_getattr(slot, 1, &disnull); astate = accumArrayResultAny(astate, dvalue, disnull, subplan->firstColType, oldcontext); diff --git a/src/backend/executor/nodeTableFuncscan.c b/src/backend/executor/nodeTableFuncscan.c index b03d2ef762..165fae8c83 100644 --- a/src/backend/executor/nodeTableFuncscan.c +++ b/src/backend/executor/nodeTableFuncscan.c @@ -202,7 +202,7 @@ ExecInitTableFuncScan(TableFuncScan *node, EState *estate, int eflags) { Oid in_funcid; - getTypeInputInfo(tupdesc->attrs[i]->atttypid, + getTypeInputInfo(TupleDescAttr(tupdesc, i)->atttypid, &in_funcid, &scanstate->typioparams[i]); fmgr_info(in_funcid, &scanstate->in_functions[i]); } @@ -390,6 +390,7 @@ tfuncInitialize(TableFuncScanState *tstate, ExprContext *econtext, Datum doc) foreach(lc1, tstate->colexprs) { char *colfilter; + Form_pg_attribute att = TupleDescAttr(tupdesc, colno); if (colno != ordinalitycol) { @@ -403,11 +404,11 @@ tfuncInitialize(TableFuncScanState *tstate, ExprContext *econtext, Datum doc) (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("column filter expression must not be null"), errdetail("Filter for column \"%s\" is null.", - NameStr(tupdesc->attrs[colno]->attname)))); + NameStr(att->attname)))); colfilter = TextDatumGetCString(value); } else - colfilter = NameStr(tupdesc->attrs[colno]->attname); + colfilter = NameStr(att->attname); routine->SetColumnFilter(tstate, colfilter, colno); } @@ -453,6 +454,8 @@ tfuncLoadRows(TableFuncScanState *tstate, ExprContext *econtext) */ for (colno = 0; colno < natts; colno++) { + Form_pg_attribute att = TupleDescAttr(tupdesc, colno); + if (colno == ordinalitycol) { /* Fast path for ordinality column */ @@ -465,8 +468,8 @@ tfuncLoadRows(TableFuncScanState *tstate, ExprContext *econtext) values[colno] = routine->GetValue(tstate, colno, - tupdesc->attrs[colno]->atttypid, - tupdesc->attrs[colno]->atttypmod, + att->atttypid, + att->atttypmod, &isnull); /* No value? Evaluate and apply the default, if any */ @@ -484,7 +487,7 @@ tfuncLoadRows(TableFuncScanState *tstate, ExprContext *econtext) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("null is not allowed in column \"%s\"", - NameStr(tupdesc->attrs[colno]->attname)))); + NameStr(att->attname)))); nulls[colno] = isnull; } diff --git a/src/backend/executor/nodeValuesscan.c b/src/backend/executor/nodeValuesscan.c index 6eacaed8bb..1a72bfe160 100644 --- a/src/backend/executor/nodeValuesscan.c +++ b/src/backend/executor/nodeValuesscan.c @@ -95,7 +95,6 @@ ValuesNext(ValuesScanState *node) List *exprstatelist; Datum *values; bool *isnull; - Form_pg_attribute *att; ListCell *lc; int resind; @@ -131,12 +130,13 @@ ValuesNext(ValuesScanState *node) */ values = slot->tts_values; isnull = slot->tts_isnull; - att = slot->tts_tupleDescriptor->attrs; resind = 0; foreach(lc, exprstatelist) { ExprState *estate = (ExprState *) lfirst(lc); + Form_pg_attribute attr = TupleDescAttr(slot->tts_tupleDescriptor, + resind); values[resind] = ExecEvalExpr(estate, econtext, @@ -150,7 +150,7 @@ ValuesNext(ValuesScanState *node) */ values[resind] = MakeExpandedObjectReadOnly(values[resind], isnull[resind], - att[resind]->attlen); + attr->attlen); resind++; } diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c index cd00a6d9f2..afe231fca9 100644 --- a/src/backend/executor/spi.c +++ b/src/backend/executor/spi.c @@ -765,8 +765,10 @@ SPI_fnumber(TupleDesc tupdesc, const char *fname) for (res = 0; res < tupdesc->natts; res++) { - if (namestrcmp(&tupdesc->attrs[res]->attname, fname) == 0 && - !tupdesc->attrs[res]->attisdropped) + Form_pg_attribute attr = TupleDescAttr(tupdesc, res); + + if (namestrcmp(&attr->attname, fname) == 0 && + !attr->attisdropped) return res + 1; } @@ -793,7 +795,7 @@ SPI_fname(TupleDesc tupdesc, int fnumber) } if (fnumber > 0) - att = tupdesc->attrs[fnumber - 1]; + att = TupleDescAttr(tupdesc, fnumber - 1); else att = SystemAttributeDefinition(fnumber, true); @@ -823,7 +825,7 @@ SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber) return NULL; if (fnumber > 0) - typoid = tupdesc->attrs[fnumber - 1]->atttypid; + typoid = TupleDescAttr(tupdesc, fnumber - 1)->atttypid; else typoid = (SystemAttributeDefinition(fnumber, true))->atttypid; @@ -865,7 +867,7 @@ SPI_gettype(TupleDesc tupdesc, int fnumber) } if (fnumber > 0) - typoid = tupdesc->attrs[fnumber - 1]->atttypid; + typoid = TupleDescAttr(tupdesc, fnumber - 1)->atttypid; else typoid = (SystemAttributeDefinition(fnumber, true))->atttypid; @@ -901,7 +903,7 @@ SPI_gettypeid(TupleDesc tupdesc, int fnumber) } if (fnumber > 0) - return tupdesc->attrs[fnumber - 1]->atttypid; + return TupleDescAttr(tupdesc, fnumber - 1)->atttypid; else return (SystemAttributeDefinition(fnumber, true))->atttypid; } diff --git a/src/backend/executor/tqueue.c b/src/backend/executor/tqueue.c index a4cfe9685a..4c4fcf530d 100644 --- a/src/backend/executor/tqueue.c +++ b/src/backend/executor/tqueue.c @@ -551,7 +551,7 @@ TQSendRecordInfo(TQueueDestReceiver *tqueue, int32 typmod, TupleDesc tupledesc) appendBinaryStringInfo(&buf, (char *) &tupledesc->tdhasoid, sizeof(bool)); for (i = 0; i < tupledesc->natts; i++) { - appendBinaryStringInfo(&buf, (char *) tupledesc->attrs[i], + appendBinaryStringInfo(&buf, (char *) TupleDescAttr(tupledesc, i), sizeof(FormData_pg_attribute)); } @@ -1253,7 +1253,7 @@ BuildFieldRemapInfo(TupleDesc tupledesc, MemoryContext mycontext) tupledesc->natts * sizeof(TupleRemapInfo *)); for (i = 0; i < tupledesc->natts; i++) { - Form_pg_attribute attr = tupledesc->attrs[i]; + Form_pg_attribute attr = TupleDescAttr(tupledesc, i); if (attr->attisdropped) { diff --git a/src/backend/executor/tstoreReceiver.c b/src/backend/executor/tstoreReceiver.c index eda38b1de1..027fa72f10 100644 --- a/src/backend/executor/tstoreReceiver.c +++ b/src/backend/executor/tstoreReceiver.c @@ -49,7 +49,6 @@ tstoreStartupReceiver(DestReceiver *self, int operation, TupleDesc typeinfo) { TStoreState *myState = (TStoreState *) self; bool needtoast = false; - Form_pg_attribute *attrs = typeinfo->attrs; int natts = typeinfo->natts; int i; @@ -58,9 +57,11 @@ tstoreStartupReceiver(DestReceiver *self, int operation, TupleDesc typeinfo) { for (i = 0; i < natts; i++) { - if (attrs[i]->attisdropped) + Form_pg_attribute attr = TupleDescAttr(typeinfo, i); + + if (attr->attisdropped) continue; - if (attrs[i]->attlen == -1) + if (attr->attlen == -1) { needtoast = true; break; @@ -109,7 +110,6 @@ tstoreReceiveSlot_detoast(TupleTableSlot *slot, DestReceiver *self) { TStoreState *myState = (TStoreState *) self; TupleDesc typeinfo = slot->tts_tupleDescriptor; - Form_pg_attribute *attrs = typeinfo->attrs; int natts = typeinfo->natts; int nfree; int i; @@ -127,10 +127,9 @@ tstoreReceiveSlot_detoast(TupleTableSlot *slot, DestReceiver *self) for (i = 0; i < natts; i++) { Datum val = slot->tts_values[i]; + Form_pg_attribute attr = TupleDescAttr(typeinfo, i); - if (!attrs[i]->attisdropped && - attrs[i]->attlen == -1 && - !slot->tts_isnull[i]) + if (!attr->attisdropped && attr->attlen == -1 && !slot->tts_isnull[i]) { if (VARATT_IS_EXTERNAL(DatumGetPointer(val))) { diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c index afc733f183..9d75e8612a 100644 --- a/src/backend/optimizer/prep/preptlist.c +++ b/src/backend/optimizer/prep/preptlist.c @@ -248,7 +248,7 @@ expand_targetlist(List *tlist, int command_type, for (attrno = 1; attrno <= numattrs; attrno++) { - Form_pg_attribute att_tup = rel->rd_att->attrs[attrno - 1]; + Form_pg_attribute att_tup = TupleDescAttr(rel->rd_att, attrno - 1); TargetEntry *new_tle = NULL; if (tlist_item != NULL) diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index f43c3f3007..e73c819901 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -1648,7 +1648,7 @@ make_inh_translation_list(Relation oldrelation, Relation newrelation, Oid attcollation; int new_attno; - att = old_tupdesc->attrs[old_attno]; + att = TupleDescAttr(old_tupdesc, old_attno); if (att->attisdropped) { /* Just put NULL into this list entry */ @@ -1686,7 +1686,7 @@ make_inh_translation_list(Relation oldrelation, Relation newrelation, * notational device to include the assignment into the if-clause. */ if (old_attno < newnatts && - (att = new_tupdesc->attrs[old_attno]) != NULL && + (att = TupleDescAttr(new_tupdesc, old_attno)) != NULL && !att->attisdropped && att->attinhcount != 0 && strcmp(attname, NameStr(att->attname)) == 0) new_attno = old_attno; @@ -1694,7 +1694,7 @@ make_inh_translation_list(Relation oldrelation, Relation newrelation, { for (new_attno = 0; new_attno < newnatts; new_attno++) { - att = new_tupdesc->attrs[new_attno]; + att = TupleDescAttr(new_tupdesc, new_attno); if (!att->attisdropped && att->attinhcount != 0 && strcmp(attname, NameStr(att->attname)) == 0) break; diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 602d17dfb4..93add27dbe 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -2366,7 +2366,7 @@ rowtype_field_matches(Oid rowtypeid, int fieldnum, ReleaseTupleDesc(tupdesc); return false; } - attr = tupdesc->attrs[fieldnum - 1]; + attr = TupleDescAttr(tupdesc, fieldnum - 1); if (attr->attisdropped || attr->atttypid != expectedtype || attr->atttypmod != expectedtypmod || diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index dc0b0b0706..a1ebd4acc8 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -1072,7 +1072,7 @@ get_rel_data_width(Relation rel, int32 *attr_widths) for (i = 1; i <= RelationGetNumberOfAttributes(rel); i++) { - Form_pg_attribute att = rel->rd_att->attrs[i - 1]; + Form_pg_attribute att = TupleDescAttr(rel->rd_att, i - 1); int32 item_width; if (att->attisdropped) @@ -1208,7 +1208,7 @@ get_relation_constraints(PlannerInfo *root, for (i = 1; i <= natts; i++) { - Form_pg_attribute att = relation->rd_att->attrs[i - 1]; + Form_pg_attribute att = TupleDescAttr(relation->rd_att, i - 1); if (att->attnotnull && !att->attisdropped) { @@ -1489,7 +1489,8 @@ build_physical_tlist(PlannerInfo *root, RelOptInfo *rel) numattrs = RelationGetNumberOfAttributes(relation); for (attrno = 1; attrno <= numattrs; attrno++) { - Form_pg_attribute att_tup = relation->rd_att->attrs[attrno - 1]; + Form_pg_attribute att_tup = TupleDescAttr(relation->rd_att, + attrno - 1); if (att_tup->attisdropped) { @@ -1609,7 +1610,7 @@ build_index_tlist(PlannerInfo *root, IndexOptInfo *index, att_tup = SystemAttributeDefinition(indexkey, heapRelation->rd_rel->relhasoids); else - att_tup = heapRelation->rd_att->attrs[indexkey - 1]; + att_tup = TupleDescAttr(heapRelation->rd_att, indexkey - 1); indexvar = (Expr *) makeVar(varno, indexkey, diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 4fb793cfbf..757a4a8fd1 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -1050,7 +1050,7 @@ transformOnConflictClause(ParseState *pstate, */ for (attno = 0; attno < targetrel->rd_rel->relnatts; attno++) { - Form_pg_attribute attr = targetrel->rd_att->attrs[attno]; + Form_pg_attribute attr = TupleDescAttr(targetrel->rd_att, attno); char *name; if (attr->attisdropped) diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c index 0bc7dba6a0..e95cee1ebf 100644 --- a/src/backend/parser/parse_coerce.c +++ b/src/backend/parser/parse_coerce.c @@ -982,9 +982,10 @@ coerce_record_to_complex(ParseState *pstate, Node *node, Node *expr; Node *cexpr; Oid exprtype; + Form_pg_attribute attr = TupleDescAttr(tupdesc, i); /* Fill in NULLs for dropped columns in rowtype */ - if (tupdesc->attrs[i]->attisdropped) + if (attr->attisdropped) { /* * can't use atttypid here, but it doesn't really matter what type @@ -1008,8 +1009,8 @@ coerce_record_to_complex(ParseState *pstate, Node *node, cexpr = coerce_to_target_type(pstate, expr, exprtype, - tupdesc->attrs[i]->atttypid, - tupdesc->attrs[i]->atttypmod, + attr->atttypid, + attr->atttypmod, ccontext, COERCE_IMPLICIT_CAST, -1); @@ -1021,7 +1022,7 @@ coerce_record_to_complex(ParseState *pstate, Node *node, format_type_be(targetTypeId)), errdetail("Cannot cast type %s to %s in column %d.", format_type_be(exprtype), - format_type_be(tupdesc->attrs[i]->atttypid), + format_type_be(attr->atttypid), ucolno), parser_coercion_errposition(pstate, location, expr))); newargs = lappend(newargs, cexpr); diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index 8487edaa95..2f2f2c7fb0 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -1834,7 +1834,7 @@ ParseComplexProjection(ParseState *pstate, char *funcname, Node *first_arg, for (i = 0; i < tupdesc->natts; i++) { - Form_pg_attribute att = tupdesc->attrs[i]; + Form_pg_attribute att = TupleDescAttr(tupdesc, i); if (strcmp(funcname, NameStr(att->attname)) == 0 && !att->attisdropped) diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index 684a50d3df..88b3e88a21 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -1052,7 +1052,7 @@ buildRelationAliases(TupleDesc tupdesc, Alias *alias, Alias *eref) for (varattno = 0; varattno < maxattrs; varattno++) { - Form_pg_attribute attr = tupdesc->attrs[varattno]; + Form_pg_attribute attr = TupleDescAttr(tupdesc, varattno); Value *attrname; if (attr->attisdropped) @@ -2026,19 +2026,18 @@ addRangeTableEntryForENR(ParseState *pstate, rte->colcollations = NIL; for (attno = 1; attno <= tupdesc->natts; ++attno) { - if (tupdesc->attrs[attno - 1]->atttypid == InvalidOid && - !(tupdesc->attrs[attno - 1]->attisdropped)) + Form_pg_attribute att = TupleDescAttr(tupdesc, attno - 1); + + if (att->atttypid == InvalidOid && + !(att->attisdropped)) elog(ERROR, "atttypid was invalid for column which has not been dropped from \"%s\"", rv->relname); rte->coltypes = - lappend_oid(rte->coltypes, - tupdesc->attrs[attno - 1]->atttypid); + lappend_oid(rte->coltypes, att->atttypid); rte->coltypmods = - lappend_int(rte->coltypmods, - tupdesc->attrs[attno - 1]->atttypmod); + lappend_int(rte->coltypmods, att->atttypmod); rte->colcollations = - lappend_oid(rte->colcollations, - tupdesc->attrs[attno - 1]->attcollation); + lappend_oid(rte->colcollations, att->attcollation); } /* @@ -2514,7 +2513,7 @@ expandTupleDesc(TupleDesc tupdesc, Alias *eref, int count, int offset, Assert(count <= tupdesc->natts); for (varattno = 0; varattno < count; varattno++) { - Form_pg_attribute attr = tupdesc->attrs[varattno]; + Form_pg_attribute attr = TupleDescAttr(tupdesc, varattno); if (attr->attisdropped) { @@ -2749,7 +2748,7 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum, Assert(tupdesc); Assert(attnum <= tupdesc->natts); - att_tup = tupdesc->attrs[attnum - 1]; + att_tup = TupleDescAttr(tupdesc, attnum - 1); /* * If dropped column, pretend it ain't there. See @@ -2953,7 +2952,8 @@ get_rte_attribute_is_dropped(RangeTblEntry *rte, AttrNumber attnum) Assert(tupdesc); Assert(attnum - atts_done <= tupdesc->natts); - att_tup = tupdesc->attrs[attnum - atts_done - 1]; + att_tup = TupleDescAttr(tupdesc, + attnum - atts_done - 1); return att_tup->attisdropped; } /* Otherwise, it can't have any dropped columns */ @@ -3042,7 +3042,7 @@ attnameAttNum(Relation rd, const char *attname, bool sysColOK) for (i = 0; i < rd->rd_rel->relnatts; i++) { - Form_pg_attribute att = rd->rd_att->attrs[i]; + Form_pg_attribute att = TupleDescAttr(rd->rd_att, i); if (namestrcmp(&(att->attname), attname) == 0 && !att->attisdropped) return i + 1; @@ -3102,7 +3102,7 @@ attnumAttName(Relation rd, int attid) } if (attid > rd->rd_att->natts) elog(ERROR, "invalid attribute number %d", attid); - return &rd->rd_att->attrs[attid - 1]->attname; + return &TupleDescAttr(rd->rd_att, attid - 1)->attname; } /* @@ -3124,7 +3124,7 @@ attnumTypeId(Relation rd, int attid) } if (attid > rd->rd_att->natts) elog(ERROR, "invalid attribute number %d", attid); - return rd->rd_att->attrs[attid - 1]->atttypid; + return TupleDescAttr(rd->rd_att, attid - 1)->atttypid; } /* @@ -3142,7 +3142,7 @@ attnumCollationId(Relation rd, int attid) } if (attid > rd->rd_att->natts) elog(ERROR, "invalid attribute number %d", attid); - return rd->rd_att->attrs[attid - 1]->attcollation; + return TupleDescAttr(rd->rd_att, attid - 1)->attcollation; } /* diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index 0a70539fb1..c3cb0357ca 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -484,8 +484,8 @@ transformAssignedExpr(ParseState *pstate, colname), parser_errposition(pstate, location))); attrtype = attnumTypeId(rd, attrno); - attrtypmod = rd->rd_att->attrs[attrno - 1]->atttypmod; - attrcollation = rd->rd_att->attrs[attrno - 1]->attcollation; + attrtypmod = TupleDescAttr(rd->rd_att, attrno - 1)->atttypmod; + attrcollation = TupleDescAttr(rd->rd_att, attrno - 1)->attcollation; /* * If the expression is a DEFAULT placeholder, insert the attribute's @@ -959,19 +959,21 @@ checkInsertTargets(ParseState *pstate, List *cols, List **attrnos) /* * Generate default column list for INSERT. */ - Form_pg_attribute *attr = pstate->p_target_relation->rd_att->attrs; int numcol = pstate->p_target_relation->rd_rel->relnatts; int i; for (i = 0; i < numcol; i++) { ResTarget *col; + Form_pg_attribute attr; - if (attr[i]->attisdropped) + attr = TupleDescAttr(pstate->p_target_relation->rd_att, i); + + if (attr->attisdropped) continue; col = makeNode(ResTarget); - col->name = pstrdup(NameStr(attr[i]->attname)); + col->name = pstrdup(NameStr(attr->attname)); col->indirection = NIL; col->val = NULL; col->location = -1; @@ -1407,7 +1409,7 @@ ExpandRowReference(ParseState *pstate, Node *expr, numAttrs = tupleDesc->natts; for (i = 0; i < numAttrs; i++) { - Form_pg_attribute att = tupleDesc->attrs[i]; + Form_pg_attribute att = TupleDescAttr(tupleDesc, i); FieldSelect *fselect; if (att->attisdropped) diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index 495ba3dffc..20586797cc 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -969,7 +969,8 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla for (parent_attno = 1; parent_attno <= tupleDesc->natts; parent_attno++) { - Form_pg_attribute attribute = tupleDesc->attrs[parent_attno - 1]; + Form_pg_attribute attribute = TupleDescAttr(tupleDesc, + parent_attno - 1); char *attributeName = NameStr(attribute->attname); ColumnDef *def; @@ -1219,7 +1220,7 @@ transformOfType(CreateStmtContext *cxt, TypeName *ofTypename) tupdesc = lookup_rowtype_tupdesc(ofTypeId, -1); for (i = 0; i < tupdesc->natts; i++) { - Form_pg_attribute attr = tupdesc->attrs[i]; + Form_pg_attribute attr = TupleDescAttr(tupdesc, i); ColumnDef *n; if (attr->attisdropped) @@ -1256,7 +1257,6 @@ generateClonedIndexStmt(CreateStmtContext *cxt, Relation source_idx, const AttrNumber *attmap, int attmap_length) { Oid source_relid = RelationGetRelid(source_idx); - Form_pg_attribute *attrs = RelationGetDescr(source_idx)->attrs; HeapTuple ht_idxrel; HeapTuple ht_idx; HeapTuple ht_am; @@ -1434,6 +1434,8 @@ generateClonedIndexStmt(CreateStmtContext *cxt, Relation source_idx, { IndexElem *iparam; AttrNumber attnum = idxrec->indkey.values[keyno]; + Form_pg_attribute attr = TupleDescAttr(RelationGetDescr(source_idx), + keyno); int16 opt = source_idx->rd_indoption[keyno]; iparam = makeNode(IndexElem); @@ -1481,7 +1483,7 @@ generateClonedIndexStmt(CreateStmtContext *cxt, Relation source_idx, } /* Copy the original index column name */ - iparam->indexcolname = pstrdup(NameStr(attrs[keyno]->attname)); + iparam->indexcolname = pstrdup(NameStr(attr->attname)); /* Add the collation name, if non-default */ iparam->collation = get_collation(indcollation->values[keyno], keycoltype); @@ -1921,7 +1923,7 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt) if (attnum > 0) { Assert(attnum <= heap_rel->rd_att->natts); - attform = heap_rel->rd_att->attrs[attnum - 1]; + attform = TupleDescAttr(heap_rel->rd_att, attnum - 1); } else attform = SystemAttributeDefinition(attnum, @@ -2040,7 +2042,8 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt) inh->relname))); for (count = 0; count < rel->rd_att->natts; count++) { - Form_pg_attribute inhattr = rel->rd_att->attrs[count]; + Form_pg_attribute inhattr = TupleDescAttr(rel->rd_att, + count); char *inhname = NameStr(inhattr->attname); if (inhattr->attisdropped) diff --git a/src/backend/replication/logical/proto.c b/src/backend/replication/logical/proto.c index 94dfee0b24..f19649b113 100644 --- a/src/backend/replication/logical/proto.c +++ b/src/backend/replication/logical/proto.c @@ -398,7 +398,7 @@ logicalrep_write_tuple(StringInfo out, Relation rel, HeapTuple tuple) for (i = 0; i < desc->natts; i++) { - if (desc->attrs[i]->attisdropped) + if (TupleDescAttr(desc, i)->attisdropped) continue; nliveatts++; } @@ -415,7 +415,7 @@ logicalrep_write_tuple(StringInfo out, Relation rel, HeapTuple tuple) { HeapTuple typtup; Form_pg_type typclass; - Form_pg_attribute att = desc->attrs[i]; + Form_pg_attribute att = TupleDescAttr(desc, i); char *outputstr; /* skip dropped columns */ @@ -518,7 +518,7 @@ logicalrep_write_attrs(StringInfo out, Relation rel) /* send number of live attributes */ for (i = 0; i < desc->natts; i++) { - if (desc->attrs[i]->attisdropped) + if (TupleDescAttr(desc, i)->attisdropped) continue; nliveatts++; } @@ -533,7 +533,7 @@ logicalrep_write_attrs(StringInfo out, Relation rel) /* send the attributes */ for (i = 0; i < desc->natts; i++) { - Form_pg_attribute att = desc->attrs[i]; + Form_pg_attribute att = TupleDescAttr(desc, i); uint8 flags = 0; if (att->attisdropped) diff --git a/src/backend/replication/logical/relation.c b/src/backend/replication/logical/relation.c index a7ea16d714..408143ae95 100644 --- a/src/backend/replication/logical/relation.c +++ b/src/backend/replication/logical/relation.c @@ -278,15 +278,16 @@ logicalrep_rel_open(LogicalRepRelId remoteid, LOCKMODE lockmode) for (i = 0; i < desc->natts; i++) { int attnum; + Form_pg_attribute attr = TupleDescAttr(desc, i); - if (desc->attrs[i]->attisdropped) + if (attr->attisdropped) { entry->attrmap[i] = -1; continue; } attnum = logicalrep_rel_att_by_name(remoterel, - NameStr(desc->attrs[i]->attname)); + NameStr(attr->attname)); entry->attrmap[i] = attnum; if (attnum >= 0) diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c index 5567bee061..657bafae57 100644 --- a/src/backend/replication/logical/reorderbuffer.c +++ b/src/backend/replication/logical/reorderbuffer.c @@ -2800,7 +2800,7 @@ ReorderBufferToastReplace(ReorderBuffer *rb, ReorderBufferTXN *txn, for (natt = 0; natt < desc->natts; natt++) { - Form_pg_attribute attr = desc->attrs[natt]; + Form_pg_attribute attr = TupleDescAttr(desc, natt); ReorderBufferToastEnt *ent; struct varlena *varlena; diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c index 7c2df57645..041f3873b9 100644 --- a/src/backend/replication/logical/worker.c +++ b/src/backend/replication/logical/worker.c @@ -247,7 +247,7 @@ slot_fill_defaults(LogicalRepRelMapEntry *rel, EState *estate, { Expr *defexpr; - if (desc->attrs[attnum]->attisdropped) + if (TupleDescAttr(desc, attnum)->attisdropped) continue; if (rel->attrmap[attnum] >= 0) @@ -323,7 +323,7 @@ slot_store_cstrings(TupleTableSlot *slot, LogicalRepRelMapEntry *rel, /* Call the "in" function for each non-dropped attribute */ for (i = 0; i < natts; i++) { - Form_pg_attribute att = slot->tts_tupleDescriptor->attrs[i]; + Form_pg_attribute att = TupleDescAttr(slot->tts_tupleDescriptor, i); int remoteattnum = rel->attrmap[i]; if (!att->attisdropped && remoteattnum >= 0 && @@ -388,7 +388,7 @@ slot_modify_cstrings(TupleTableSlot *slot, LogicalRepRelMapEntry *rel, /* Call the "in" function for each replaced attribute */ for (i = 0; i < natts; i++) { - Form_pg_attribute att = slot->tts_tupleDescriptor->attrs[i]; + Form_pg_attribute att = TupleDescAttr(slot->tts_tupleDescriptor, i); int remoteattnum = rel->attrmap[i]; if (remoteattnum >= 0 && !replaces[remoteattnum]) diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c index 370b74f232..67c1d3b246 100644 --- a/src/backend/replication/pgoutput/pgoutput.c +++ b/src/backend/replication/pgoutput/pgoutput.c @@ -303,7 +303,7 @@ pgoutput_change(LogicalDecodingContext *ctx, ReorderBufferTXN *txn, */ for (i = 0; i < desc->natts; i++) { - Form_pg_attribute att = desc->attrs[i]; + Form_pg_attribute att = TupleDescAttr(desc, i); if (att->attisdropped) continue; diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c index 9e6865bef6..d03984a2de 100644 --- a/src/backend/rewrite/rewriteDefine.c +++ b/src/backend/rewrite/rewriteDefine.c @@ -676,7 +676,7 @@ checkRuleResultList(List *targetList, TupleDesc resultDesc, bool isSelect, errmsg("SELECT rule's target list has too many entries") : errmsg("RETURNING list has too many entries"))); - attr = resultDesc->attrs[i - 1]; + attr = TupleDescAttr(resultDesc, i - 1); attname = NameStr(attr->attname); /* diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index 6b79c69795..ef52dd5b95 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -751,7 +751,7 @@ rewriteTargetListIU(List *targetList, attrno = old_tle->resno; if (attrno < 1 || attrno > numattrs) elog(ERROR, "bogus resno %d in targetlist", attrno); - att_tup = target_relation->rd_att->attrs[attrno - 1]; + att_tup = TupleDescAttr(target_relation->rd_att, attrno - 1); /* put attrno into attrno_list even if it's dropped */ if (attrno_list) @@ -794,7 +794,7 @@ rewriteTargetListIU(List *targetList, TargetEntry *new_tle = new_tles[attrno - 1]; bool apply_default; - att_tup = target_relation->rd_att->attrs[attrno - 1]; + att_tup = TupleDescAttr(target_relation->rd_att, attrno - 1); /* We can (and must) ignore deleted attributes */ if (att_tup->attisdropped) @@ -1112,7 +1112,7 @@ Node * build_column_default(Relation rel, int attrno) { TupleDesc rd_att = rel->rd_att; - Form_pg_attribute att_tup = rd_att->attrs[attrno - 1]; + Form_pg_attribute att_tup = TupleDescAttr(rd_att, attrno - 1); Oid atttype = att_tup->atttypid; int32 atttypmod = att_tup->atttypmod; Node *expr = NULL; @@ -1247,7 +1247,7 @@ rewriteValuesRTE(RangeTblEntry *rte, Relation target_relation, List *attrnos) Form_pg_attribute att_tup; Node *new_expr; - att_tup = target_relation->rd_att->attrs[attrno - 1]; + att_tup = TupleDescAttr(target_relation->rd_att, attrno - 1); if (!att_tup->attisdropped) new_expr = build_column_default(target_relation, attrno); diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c index 4dd7d977e8..1ddb42b4d0 100644 --- a/src/backend/utils/adt/json.c +++ b/src/backend/utils/adt/json.c @@ -1714,15 +1714,16 @@ composite_to_json(Datum composite, StringInfo result, bool use_line_feeds) char *attname; JsonTypeCategory tcategory; Oid outfuncoid; + Form_pg_attribute att = TupleDescAttr(tupdesc, i); - if (tupdesc->attrs[i]->attisdropped) + if (att->attisdropped) continue; if (needsep) appendStringInfoString(result, sep); needsep = true; - attname = NameStr(tupdesc->attrs[i]->attname); + attname = NameStr(att->attname); escape_json(result, attname); appendStringInfoChar(result, ':'); @@ -1734,8 +1735,7 @@ composite_to_json(Datum composite, StringInfo result, bool use_line_feeds) outfuncoid = InvalidOid; } else - json_categorize_type(tupdesc->attrs[i]->atttypid, - &tcategory, &outfuncoid); + json_categorize_type(att->atttypid, &tcategory, &outfuncoid); datum_to_json(val, isnull, result, tcategory, outfuncoid, false); } diff --git a/src/backend/utils/adt/jsonb.c b/src/backend/utils/adt/jsonb.c index 49f41f9f99..1eb7f3d6f9 100644 --- a/src/backend/utils/adt/jsonb.c +++ b/src/backend/utils/adt/jsonb.c @@ -1075,11 +1075,12 @@ composite_to_jsonb(Datum composite, JsonbInState *result) JsonbTypeCategory tcategory; Oid outfuncoid; JsonbValue v; + Form_pg_attribute att = TupleDescAttr(tupdesc, i); - if (tupdesc->attrs[i]->attisdropped) + if (att->attisdropped) continue; - attname = NameStr(tupdesc->attrs[i]->attname); + attname = NameStr(att->attname); v.type = jbvString; /* don't need checkStringLen here - can't exceed maximum name length */ @@ -1096,8 +1097,7 @@ composite_to_jsonb(Datum composite, JsonbInState *result) outfuncoid = InvalidOid; } else - jsonb_categorize_type(tupdesc->attrs[i]->atttypid, - &tcategory, &outfuncoid); + jsonb_categorize_type(att->atttypid, &tcategory, &outfuncoid); datum_to_jsonb(val, isnull, result, tcategory, outfuncoid, false); } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 4779e74895..d92ffa83d9 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -3087,7 +3087,7 @@ populate_record(TupleDesc tupdesc, for (i = 0; i < ncolumns; ++i) { - Form_pg_attribute att = tupdesc->attrs[i]; + Form_pg_attribute att = TupleDescAttr(tupdesc, i); char *colname = NameStr(att->attname); JsValue field = {0}; bool found; diff --git a/src/backend/utils/adt/orderedsetaggs.c b/src/backend/utils/adt/orderedsetaggs.c index 8502fcfc82..25905a3287 100644 --- a/src/backend/utils/adt/orderedsetaggs.c +++ b/src/backend/utils/adt/orderedsetaggs.c @@ -1125,13 +1125,15 @@ hypothetical_check_argtypes(FunctionCallInfo fcinfo, int nargs, /* check that we have an int4 flag column */ if (!tupdesc || (nargs + 1) != tupdesc->natts || - tupdesc->attrs[nargs]->atttypid != INT4OID) + TupleDescAttr(tupdesc, nargs)->atttypid != INT4OID) elog(ERROR, "type mismatch in hypothetical-set function"); /* check that direct args match in type with aggregated args */ for (i = 0; i < nargs; i++) { - if (get_fn_expr_argtype(fcinfo->flinfo, i + 1) != tupdesc->attrs[i]->atttypid) + Form_pg_attribute attr = TupleDescAttr(tupdesc, i); + + if (get_fn_expr_argtype(fcinfo->flinfo, i + 1) != attr->atttypid) elog(ERROR, "type mismatch in hypothetical-set function"); } } diff --git a/src/backend/utils/adt/rowtypes.c b/src/backend/utils/adt/rowtypes.c index 44acd13c6b..98fe00ff39 100644 --- a/src/backend/utils/adt/rowtypes.c +++ b/src/backend/utils/adt/rowtypes.c @@ -159,12 +159,13 @@ record_in(PG_FUNCTION_ARGS) for (i = 0; i < ncolumns; i++) { + Form_pg_attribute att = TupleDescAttr(tupdesc, i); ColumnIOData *column_info = &my_extra->columns[i]; - Oid column_type = tupdesc->attrs[i]->atttypid; + Oid column_type = att->atttypid; char *column_data; /* Ignore dropped columns in datatype, but fill with nulls */ - if (tupdesc->attrs[i]->attisdropped) + if (att->attisdropped) { values[i] = (Datum) 0; nulls[i] = true; @@ -252,7 +253,7 @@ record_in(PG_FUNCTION_ARGS) values[i] = InputFunctionCall(&column_info->proc, column_data, column_info->typioparam, - tupdesc->attrs[i]->atttypmod); + att->atttypmod); /* * Prep for next column @@ -367,15 +368,16 @@ record_out(PG_FUNCTION_ARGS) for (i = 0; i < ncolumns; i++) { + Form_pg_attribute att = TupleDescAttr(tupdesc, i); ColumnIOData *column_info = &my_extra->columns[i]; - Oid column_type = tupdesc->attrs[i]->atttypid; + Oid column_type = att->atttypid; Datum attr; char *value; char *tmp; bool nq; /* Ignore dropped columns in datatype */ - if (tupdesc->attrs[i]->attisdropped) + if (att->attisdropped) continue; if (needComma) @@ -519,7 +521,7 @@ record_recv(PG_FUNCTION_ARGS) validcols = 0; for (i = 0; i < ncolumns; i++) { - if (!tupdesc->attrs[i]->attisdropped) + if (!TupleDescAttr(tupdesc, i)->attisdropped) validcols++; } if (usercols != validcols) @@ -531,8 +533,9 @@ record_recv(PG_FUNCTION_ARGS) /* Process each column */ for (i = 0; i < ncolumns; i++) { + Form_pg_attribute att = TupleDescAttr(tupdesc, i); ColumnIOData *column_info = &my_extra->columns[i]; - Oid column_type = tupdesc->attrs[i]->atttypid; + Oid column_type = att->atttypid; Oid coltypoid; int itemlen; StringInfoData item_buf; @@ -540,7 +543,7 @@ record_recv(PG_FUNCTION_ARGS) char csave; /* Ignore dropped columns in datatype, but fill with nulls */ - if (tupdesc->attrs[i]->attisdropped) + if (att->attisdropped) { values[i] = (Datum) 0; nulls[i] = true; @@ -605,7 +608,7 @@ record_recv(PG_FUNCTION_ARGS) values[i] = ReceiveFunctionCall(&column_info->proc, bufptr, column_info->typioparam, - tupdesc->attrs[i]->atttypmod); + att->atttypmod); if (bufptr) { @@ -712,20 +715,21 @@ record_send(PG_FUNCTION_ARGS) validcols = 0; for (i = 0; i < ncolumns; i++) { - if (!tupdesc->attrs[i]->attisdropped) + if (!TupleDescAttr(tupdesc, i)->attisdropped) validcols++; } pq_sendint(&buf, validcols, 4); for (i = 0; i < ncolumns; i++) { + Form_pg_attribute att = TupleDescAttr(tupdesc, i); ColumnIOData *column_info = &my_extra->columns[i]; - Oid column_type = tupdesc->attrs[i]->atttypid; + Oid column_type = att->atttypid; Datum attr; bytea *outputbytes; /* Ignore dropped columns in datatype */ - if (tupdesc->attrs[i]->attisdropped) + if (att->attisdropped) continue; pq_sendint(&buf, column_type, sizeof(Oid)); @@ -873,18 +877,20 @@ record_cmp(FunctionCallInfo fcinfo) i1 = i2 = j = 0; while (i1 < ncolumns1 || i2 < ncolumns2) { + Form_pg_attribute att1; + Form_pg_attribute att2; TypeCacheEntry *typentry; Oid collation; /* * Skip dropped columns */ - if (i1 < ncolumns1 && tupdesc1->attrs[i1]->attisdropped) + if (i1 < ncolumns1 && TupleDescAttr(tupdesc1, i1)->attisdropped) { i1++; continue; } - if (i2 < ncolumns2 && tupdesc2->attrs[i2]->attisdropped) + if (i2 < ncolumns2 && TupleDescAttr(tupdesc2, i2)->attisdropped) { i2++; continue; @@ -892,24 +898,26 @@ record_cmp(FunctionCallInfo fcinfo) if (i1 >= ncolumns1 || i2 >= ncolumns2) break; /* we'll deal with mismatch below loop */ + att1 = TupleDescAttr(tupdesc1, i1); + att2 = TupleDescAttr(tupdesc2, i2); + /* * Have two matching columns, they must be same type */ - if (tupdesc1->attrs[i1]->atttypid != - tupdesc2->attrs[i2]->atttypid) + if (att1->atttypid != att2->atttypid) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("cannot compare dissimilar column types %s and %s at record column %d", - format_type_be(tupdesc1->attrs[i1]->atttypid), - format_type_be(tupdesc2->attrs[i2]->atttypid), + format_type_be(att1->atttypid), + format_type_be(att2->atttypid), j + 1))); /* * If they're not same collation, we don't complain here, but the * comparison function might. */ - collation = tupdesc1->attrs[i1]->attcollation; - if (collation != tupdesc2->attrs[i2]->attcollation) + collation = att1->attcollation; + if (collation != att2->attcollation) collation = InvalidOid; /* @@ -917,9 +925,9 @@ record_cmp(FunctionCallInfo fcinfo) */ typentry = my_extra->columns[j].typentry; if (typentry == NULL || - typentry->type_id != tupdesc1->attrs[i1]->atttypid) + typentry->type_id != att1->atttypid) { - typentry = lookup_type_cache(tupdesc1->attrs[i1]->atttypid, + typentry = lookup_type_cache(att1->atttypid, TYPECACHE_CMP_PROC_FINFO); if (!OidIsValid(typentry->cmp_proc_finfo.fn_oid)) ereport(ERROR, @@ -1111,6 +1119,8 @@ record_eq(PG_FUNCTION_ARGS) i1 = i2 = j = 0; while (i1 < ncolumns1 || i2 < ncolumns2) { + Form_pg_attribute att1; + Form_pg_attribute att2; TypeCacheEntry *typentry; Oid collation; FunctionCallInfoData locfcinfo; @@ -1119,12 +1129,12 @@ record_eq(PG_FUNCTION_ARGS) /* * Skip dropped columns */ - if (i1 < ncolumns1 && tupdesc1->attrs[i1]->attisdropped) + if (i1 < ncolumns1 && TupleDescAttr(tupdesc1, i1)->attisdropped) { i1++; continue; } - if (i2 < ncolumns2 && tupdesc2->attrs[i2]->attisdropped) + if (i2 < ncolumns2 && TupleDescAttr(tupdesc2, i2)->attisdropped) { i2++; continue; @@ -1132,24 +1142,26 @@ record_eq(PG_FUNCTION_ARGS) if (i1 >= ncolumns1 || i2 >= ncolumns2) break; /* we'll deal with mismatch below loop */ + att1 = TupleDescAttr(tupdesc1, i1); + att2 = TupleDescAttr(tupdesc2, i2); + /* * Have two matching columns, they must be same type */ - if (tupdesc1->attrs[i1]->atttypid != - tupdesc2->attrs[i2]->atttypid) + if (att1->atttypid != att2->atttypid) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("cannot compare dissimilar column types %s and %s at record column %d", - format_type_be(tupdesc1->attrs[i1]->atttypid), - format_type_be(tupdesc2->attrs[i2]->atttypid), + format_type_be(att1->atttypid), + format_type_be(att2->atttypid), j + 1))); /* * If they're not same collation, we don't complain here, but the * equality function might. */ - collation = tupdesc1->attrs[i1]->attcollation; - if (collation != tupdesc2->attrs[i2]->attcollation) + collation = att1->attcollation; + if (collation != att2->attcollation) collation = InvalidOid; /* @@ -1157,9 +1169,9 @@ record_eq(PG_FUNCTION_ARGS) */ typentry = my_extra->columns[j].typentry; if (typentry == NULL || - typentry->type_id != tupdesc1->attrs[i1]->atttypid) + typentry->type_id != att1->atttypid) { - typentry = lookup_type_cache(tupdesc1->attrs[i1]->atttypid, + typentry = lookup_type_cache(att1->atttypid, TYPECACHE_EQ_OPR_FINFO); if (!OidIsValid(typentry->eq_opr_finfo.fn_oid)) ereport(ERROR, @@ -1370,15 +1382,18 @@ record_image_cmp(FunctionCallInfo fcinfo) i1 = i2 = j = 0; while (i1 < ncolumns1 || i2 < ncolumns2) { + Form_pg_attribute att1; + Form_pg_attribute att2; + /* * Skip dropped columns */ - if (i1 < ncolumns1 && tupdesc1->attrs[i1]->attisdropped) + if (i1 < ncolumns1 && TupleDescAttr(tupdesc1, i1)->attisdropped) { i1++; continue; } - if (i2 < ncolumns2 && tupdesc2->attrs[i2]->attisdropped) + if (i2 < ncolumns2 && TupleDescAttr(tupdesc2, i2)->attisdropped) { i2++; continue; @@ -1386,24 +1401,25 @@ record_image_cmp(FunctionCallInfo fcinfo) if (i1 >= ncolumns1 || i2 >= ncolumns2) break; /* we'll deal with mismatch below loop */ + att1 = TupleDescAttr(tupdesc1, i1); + att2 = TupleDescAttr(tupdesc2, i2); + /* * Have two matching columns, they must be same type */ - if (tupdesc1->attrs[i1]->atttypid != - tupdesc2->attrs[i2]->atttypid) + if (att1->atttypid != att2->atttypid) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("cannot compare dissimilar column types %s and %s at record column %d", - format_type_be(tupdesc1->attrs[i1]->atttypid), - format_type_be(tupdesc2->attrs[i2]->atttypid), + format_type_be(att1->atttypid), + format_type_be(att2->atttypid), j + 1))); /* * The same type should have the same length (or both should be * variable). */ - Assert(tupdesc1->attrs[i1]->attlen == - tupdesc2->attrs[i2]->attlen); + Assert(att1->attlen == att2->attlen); /* * We consider two NULLs equal; NULL > not-NULL. @@ -1426,7 +1442,7 @@ record_image_cmp(FunctionCallInfo fcinfo) } /* Compare the pair of elements */ - if (tupdesc1->attrs[i1]->attlen == -1) + if (att1->attlen == -1) { Size len1, len2; @@ -1449,9 +1465,9 @@ record_image_cmp(FunctionCallInfo fcinfo) if ((Pointer) arg2val != (Pointer) values2[i2]) pfree(arg2val); } - else if (tupdesc1->attrs[i1]->attbyval) + else if (att1->attbyval) { - switch (tupdesc1->attrs[i1]->attlen) + switch (att1->attlen) { case 1: if (GET_1_BYTE(values1[i1]) != @@ -1495,7 +1511,7 @@ record_image_cmp(FunctionCallInfo fcinfo) { cmpresult = memcmp(DatumGetPointer(values1[i1]), DatumGetPointer(values2[i2]), - tupdesc1->attrs[i1]->attlen); + att1->attlen); } if (cmpresult < 0) @@ -1647,15 +1663,18 @@ record_image_eq(PG_FUNCTION_ARGS) i1 = i2 = j = 0; while (i1 < ncolumns1 || i2 < ncolumns2) { + Form_pg_attribute att1; + Form_pg_attribute att2; + /* * Skip dropped columns */ - if (i1 < ncolumns1 && tupdesc1->attrs[i1]->attisdropped) + if (i1 < ncolumns1 && TupleDescAttr(tupdesc1, i1)->attisdropped) { i1++; continue; } - if (i2 < ncolumns2 && tupdesc2->attrs[i2]->attisdropped) + if (i2 < ncolumns2 && TupleDescAttr(tupdesc2, i2)->attisdropped) { i2++; continue; @@ -1663,16 +1682,18 @@ record_image_eq(PG_FUNCTION_ARGS) if (i1 >= ncolumns1 || i2 >= ncolumns2) break; /* we'll deal with mismatch below loop */ + att1 = TupleDescAttr(tupdesc1, i1); + att2 = TupleDescAttr(tupdesc2, i2); + /* * Have two matching columns, they must be same type */ - if (tupdesc1->attrs[i1]->atttypid != - tupdesc2->attrs[i2]->atttypid) + if (att1->atttypid != att2->atttypid) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("cannot compare dissimilar column types %s and %s at record column %d", - format_type_be(tupdesc1->attrs[i1]->atttypid), - format_type_be(tupdesc2->attrs[i2]->atttypid), + format_type_be(att1->atttypid), + format_type_be(att2->atttypid), j + 1))); /* @@ -1687,7 +1708,7 @@ record_image_eq(PG_FUNCTION_ARGS) } /* Compare the pair of elements */ - if (tupdesc1->attrs[i1]->attlen == -1) + if (att1->attlen == -1) { Size len1, len2; @@ -1716,9 +1737,9 @@ record_image_eq(PG_FUNCTION_ARGS) pfree(arg2val); } } - else if (tupdesc1->attrs[i1]->attbyval) + else if (att1->attbyval) { - switch (tupdesc1->attrs[i1]->attlen) + switch (att1->attlen) { case 1: result = (GET_1_BYTE(values1[i1]) == @@ -1746,7 +1767,7 @@ record_image_eq(PG_FUNCTION_ARGS) { result = (memcmp(DatumGetPointer(values1[i1]), DatumGetPointer(values2[i2]), - tupdesc1->attrs[i1]->attlen) == 0); + att1->attlen) == 0); } if (!result) break; diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 7469ec773c..43646d2c4f 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -3698,10 +3698,12 @@ set_relation_column_names(deparse_namespace *dpns, RangeTblEntry *rte, for (i = 0; i < ncolumns; i++) { - if (tupdesc->attrs[i]->attisdropped) + Form_pg_attribute attr = TupleDescAttr(tupdesc, i); + + if (attr->attisdropped) real_colnames[i] = NULL; else - real_colnames[i] = pstrdup(NameStr(tupdesc->attrs[i]->attname)); + real_colnames[i] = pstrdup(NameStr(attr->attname)); } relation_close(rel, AccessShareLock); } @@ -5391,7 +5393,7 @@ get_target_list(List *targetList, deparse_context *context, * Otherwise, just use what we can find in the TLE. */ if (resultDesc && colno <= resultDesc->natts) - colname = NameStr(resultDesc->attrs[colno - 1]->attname); + colname = NameStr(TupleDescAttr(resultDesc, colno - 1)->attname); else colname = tle->resname; @@ -6741,7 +6743,7 @@ get_name_for_var_field(Var *var, int fieldno, Assert(tupleDesc); /* Got the tupdesc, so we can extract the field name */ Assert(fieldno >= 1 && fieldno <= tupleDesc->natts); - return NameStr(tupleDesc->attrs[fieldno - 1]->attname); + return NameStr(TupleDescAttr(tupleDesc, fieldno - 1)->attname); } /* Find appropriate nesting depth */ @@ -7051,7 +7053,7 @@ get_name_for_var_field(Var *var, int fieldno, Assert(tupleDesc); /* Got the tupdesc, so we can extract the field name */ Assert(fieldno >= 1 && fieldno <= tupleDesc->natts); - return NameStr(tupleDesc->attrs[fieldno - 1]->attname); + return NameStr(TupleDescAttr(tupleDesc, fieldno - 1)->attname); } /* @@ -8180,7 +8182,7 @@ get_rule_expr(Node *node, deparse_context *context, Node *e = (Node *) lfirst(arg); if (tupdesc == NULL || - !tupdesc->attrs[i]->attisdropped) + !TupleDescAttr(tupdesc, i)->attisdropped) { appendStringInfoString(buf, sep); /* Whole-row Vars need special treatment here */ @@ -8193,7 +8195,7 @@ get_rule_expr(Node *node, deparse_context *context, { while (i < tupdesc->natts) { - if (!tupdesc->attrs[i]->attisdropped) + if (!TupleDescAttr(tupdesc, i)->attisdropped) { appendStringInfoString(buf, sep); appendStringInfoString(buf, "NULL"); diff --git a/src/backend/utils/adt/tid.c b/src/backend/utils/adt/tid.c index 8453b65e78..083f7d60a7 100644 --- a/src/backend/utils/adt/tid.c +++ b/src/backend/utils/adt/tid.c @@ -273,9 +273,11 @@ currtid_for_view(Relation viewrel, ItemPointer tid) for (i = 0; i < natts; i++) { - if (strcmp(NameStr(att->attrs[i]->attname), "ctid") == 0) + Form_pg_attribute attr = TupleDescAttr(att, i); + + if (strcmp(NameStr(attr->attname), "ctid") == 0) { - if (att->attrs[i]->atttypid != TIDOID) + if (attr->atttypid != TIDOID) elog(ERROR, "ctid isn't of type TID"); tididx = i; break; diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c index c47624eff6..24229c2dff 100644 --- a/src/backend/utils/adt/xml.c +++ b/src/backend/utils/adt/xml.c @@ -3099,13 +3099,15 @@ map_sql_table_to_xmlschema(TupleDesc tupdesc, Oid relid, bool nulls, for (i = 0; i < tupdesc->natts; i++) { - if (tupdesc->attrs[i]->attisdropped) + Form_pg_attribute att = TupleDescAttr(tupdesc, i); + + if (att->attisdropped) continue; appendStringInfo(&result, " \n", - map_sql_identifier_to_xml_name(NameStr(tupdesc->attrs[i]->attname), + map_sql_identifier_to_xml_name(NameStr(att->attname), true, false), - map_sql_type_to_xml_name(tupdesc->attrs[i]->atttypid, -1), + map_sql_type_to_xml_name(att->atttypid, -1), nulls ? " nillable=\"true\"" : " minOccurs=\"0\""); } @@ -3392,10 +3394,11 @@ map_sql_typecoll_to_xmlschema_types(List *tupdesc_list) for (i = 0; i < tupdesc->natts; i++) { - if (tupdesc->attrs[i]->attisdropped) + Form_pg_attribute att = TupleDescAttr(tupdesc, i); + + if (att->attisdropped) continue; - uniquetypes = list_append_unique_oid(uniquetypes, - tupdesc->attrs[i]->atttypid); + uniquetypes = list_append_unique_oid(uniquetypes, att->atttypid); } } diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c index f894053d80..e092801025 100644 --- a/src/backend/utils/cache/catcache.c +++ b/src/backend/utils/cache/catcache.c @@ -797,7 +797,7 @@ do { \ if (cache->cc_key[i] > 0) { \ elog(DEBUG2, "CatalogCacheInitializeCache: load %d/%d w/%d, %u", \ i+1, cache->cc_nkeys, cache->cc_key[i], \ - tupdesc->attrs[cache->cc_key[i] - 1]->atttypid); \ + TupleDescAttr(tupdesc, cache->cc_key[i] - 1)->atttypid); \ } else { \ elog(DEBUG2, "CatalogCacheInitializeCache: load %d/%d w/%d", \ i+1, cache->cc_nkeys, cache->cc_key[i]); \ @@ -862,7 +862,8 @@ CatalogCacheInitializeCache(CatCache *cache) if (cache->cc_key[i] > 0) { - Form_pg_attribute attr = tupdesc->attrs[cache->cc_key[i] - 1]; + Form_pg_attribute attr = TupleDescAttr(tupdesc, + cache->cc_key[i] - 1); keytype = attr->atttypid; /* cache key columns should always be NOT NULL */ diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 2150fe9a39..b8e37809b0 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -546,7 +546,7 @@ RelationBuildTupleDesc(Relation relation) elog(ERROR, "invalid attribute number %d for %s", attp->attnum, RelationGetRelationName(relation)); - memcpy(relation->rd_att->attrs[attp->attnum - 1], + memcpy(TupleDescAttr(relation->rd_att, attp->attnum - 1), attp, ATTRIBUTE_FIXED_PART_SIZE); @@ -590,7 +590,7 @@ RelationBuildTupleDesc(Relation relation) int i; for (i = 0; i < relation->rd_rel->relnatts; i++) - Assert(relation->rd_att->attrs[i]->attcacheoff == -1); + Assert(TupleDescAttr(relation->rd_att, i)->attcacheoff == -1); } #endif @@ -600,7 +600,7 @@ RelationBuildTupleDesc(Relation relation) * for attnum=1 that used to exist in fastgetattr() and index_getattr(). */ if (relation->rd_rel->relnatts > 0) - relation->rd_att->attrs[0]->attcacheoff = 0; + TupleDescAttr(relation->rd_att, 0)->attcacheoff = 0; /* * Set up constraint/default info @@ -958,9 +958,11 @@ RelationBuildPartitionKey(Relation relation) /* Collect type information */ if (attno != 0) { - key->parttypid[i] = relation->rd_att->attrs[attno - 1]->atttypid; - key->parttypmod[i] = relation->rd_att->attrs[attno - 1]->atttypmod; - key->parttypcoll[i] = relation->rd_att->attrs[attno - 1]->attcollation; + Form_pg_attribute att = TupleDescAttr(relation->rd_att, attno - 1); + + key->parttypid[i] = att->atttypid; + key->parttypmod[i] = att->atttypmod; + key->parttypcoll[i] = att->attcollation; } else { @@ -1977,16 +1979,16 @@ formrdesc(const char *relationName, Oid relationReltype, has_not_null = false; for (i = 0; i < natts; i++) { - memcpy(relation->rd_att->attrs[i], + memcpy(TupleDescAttr(relation->rd_att, i), &attrs[i], ATTRIBUTE_FIXED_PART_SIZE); has_not_null |= attrs[i].attnotnull; /* make sure attcacheoff is valid */ - relation->rd_att->attrs[i]->attcacheoff = -1; + TupleDescAttr(relation->rd_att, i)->attcacheoff = -1; } /* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */ - relation->rd_att->attrs[0]->attcacheoff = 0; + TupleDescAttr(relation->rd_att, 0)->attcacheoff = 0; /* mark not-null status */ if (has_not_null) @@ -2000,7 +2002,7 @@ formrdesc(const char *relationName, Oid relationReltype, /* * initialize relation id from info in att array (my, this is ugly) */ - RelationGetRelid(relation) = relation->rd_att->attrs[0]->attrelid; + RelationGetRelid(relation) = TupleDescAttr(relation->rd_att, 0)->attrelid; /* * All relations made with formrdesc are mapped. This is necessarily so @@ -3274,9 +3276,12 @@ RelationBuildLocalRelation(const char *relname, has_not_null = false; for (i = 0; i < natts; i++) { - rel->rd_att->attrs[i]->attidentity = tupDesc->attrs[i]->attidentity; - rel->rd_att->attrs[i]->attnotnull = tupDesc->attrs[i]->attnotnull; - has_not_null |= tupDesc->attrs[i]->attnotnull; + Form_pg_attribute satt = TupleDescAttr(tupDesc, i); + Form_pg_attribute datt = TupleDescAttr(rel->rd_att, i); + + datt->attidentity = satt->attidentity; + datt->attnotnull = satt->attnotnull; + has_not_null |= satt->attnotnull; } if (has_not_null) @@ -3346,7 +3351,7 @@ RelationBuildLocalRelation(const char *relname, RelationGetRelid(rel) = relid; for (i = 0; i < natts; i++) - rel->rd_att->attrs[i]->attrelid = relid; + TupleDescAttr(rel->rd_att, i)->attrelid = relid; rel->rd_rel->reltablespace = reltablespace; @@ -3971,13 +3976,13 @@ BuildHardcodedDescriptor(int natts, const FormData_pg_attribute *attrs, for (i = 0; i < natts; i++) { - memcpy(result->attrs[i], &attrs[i], ATTRIBUTE_FIXED_PART_SIZE); + memcpy(TupleDescAttr(result, i), &attrs[i], ATTRIBUTE_FIXED_PART_SIZE); /* make sure attcacheoff is valid */ - result->attrs[i]->attcacheoff = -1; + TupleDescAttr(result, i)->attcacheoff = -1; } /* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */ - result->attrs[0]->attcacheoff = 0; + TupleDescAttr(result, 0)->attcacheoff = 0; /* Note: we don't bother to set up a TupleConstr entry */ @@ -4044,6 +4049,7 @@ AttrDefaultFetch(Relation relation) while (HeapTupleIsValid(htup = systable_getnext(adscan))) { Form_pg_attrdef adform = (Form_pg_attrdef) GETSTRUCT(htup); + Form_pg_attribute attr = TupleDescAttr(relation->rd_att, adform->adnum - 1); for (i = 0; i < ndef; i++) { @@ -4051,7 +4057,7 @@ AttrDefaultFetch(Relation relation) continue; if (attrdef[i].adbin != NULL) elog(WARNING, "multiple attrdef records found for attr %s of rel %s", - NameStr(relation->rd_att->attrs[adform->adnum - 1]->attname), + NameStr(attr->attname), RelationGetRelationName(relation)); else found++; @@ -4061,7 +4067,7 @@ AttrDefaultFetch(Relation relation) adrel->rd_att, &isnull); if (isnull) elog(WARNING, "null adbin for attr %s of rel %s", - NameStr(relation->rd_att->attrs[adform->adnum - 1]->attname), + NameStr(attr->attname), RelationGetRelationName(relation)); else { @@ -5270,7 +5276,7 @@ errtablecol(Relation rel, int attnum) /* Use reldesc if it's a user attribute, else consult the catalogs */ if (attnum > 0 && attnum <= reldesc->natts) - colname = NameStr(reldesc->attrs[attnum - 1]->attname); + colname = NameStr(TupleDescAttr(reldesc, attnum - 1)->attname); else colname = get_relid_attribute_name(RelationGetRelid(rel), attnum); @@ -5460,14 +5466,16 @@ load_relcache_init_file(bool shared) has_not_null = false; for (i = 0; i < relform->relnatts; i++) { + Form_pg_attribute attr = TupleDescAttr(rel->rd_att, i); + if (fread(&len, 1, sizeof(len), fp) != sizeof(len)) goto read_failed; if (len != ATTRIBUTE_FIXED_PART_SIZE) goto read_failed; - if (fread(rel->rd_att->attrs[i], 1, len, fp) != len) + if (fread(attr, 1, len, fp) != len) goto read_failed; - has_not_null |= rel->rd_att->attrs[i]->attnotnull; + has_not_null |= attr->attnotnull; } /* next read the access method specific field */ @@ -5848,7 +5856,8 @@ write_relcache_init_file(bool shared) /* next, do all the attribute tuple form data entries */ for (i = 0; i < relform->relnatts; i++) { - write_item(rel->rd_att->attrs[i], ATTRIBUTE_FIXED_PART_SIZE, fp); + write_item(TupleDescAttr(rel->rd_att, i), + ATTRIBUTE_FIXED_PART_SIZE, fp); } /* next, do the access method specific field */ diff --git a/src/backend/utils/cache/typcache.c b/src/backend/utils/cache/typcache.c index 7ec31eb3e3..20567a394b 100644 --- a/src/backend/utils/cache/typcache.c +++ b/src/backend/utils/cache/typcache.c @@ -1176,11 +1176,12 @@ cache_record_field_properties(TypeCacheEntry *typentry) for (i = 0; i < tupdesc->natts; i++) { TypeCacheEntry *fieldentry; + Form_pg_attribute attr = TupleDescAttr(tupdesc, i); - if (tupdesc->attrs[i]->attisdropped) + if (attr->attisdropped) continue; - fieldentry = lookup_type_cache(tupdesc->attrs[i]->atttypid, + fieldentry = lookup_type_cache(attr->atttypid, TYPECACHE_EQ_OPR | TYPECACHE_CMP_PROC); if (!OidIsValid(fieldentry->eq_opr)) @@ -1340,7 +1341,7 @@ assign_record_type_typmod(TupleDesc tupDesc) { if (i >= REC_HASH_KEYS) break; - hashkey[i] = tupDesc->attrs[i]->atttypid; + hashkey[i] = TupleDescAttr(tupDesc, i)->atttypid; } recentry = (RecordCacheEntry *) hash_search(RecordCacheHash, (void *) hashkey, diff --git a/src/backend/utils/fmgr/funcapi.c b/src/backend/utils/fmgr/funcapi.c index be47d411c5..9c3f4510ce 100644 --- a/src/backend/utils/fmgr/funcapi.c +++ b/src/backend/utils/fmgr/funcapi.c @@ -419,7 +419,7 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args, /* See if there are any polymorphic outputs; quick out if not */ for (i = 0; i < natts; i++) { - switch (tupdesc->attrs[i]->atttypid) + switch (TupleDescAttr(tupdesc, i)->atttypid) { case ANYELEMENTOID: have_anyelement_result = true; @@ -548,13 +548,15 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args, /* And finally replace the tuple column types as needed */ for (i = 0; i < natts; i++) { - switch (tupdesc->attrs[i]->atttypid) + Form_pg_attribute att = TupleDescAttr(tupdesc, i); + + switch (att->atttypid) { case ANYELEMENTOID: case ANYNONARRAYOID: case ANYENUMOID: TupleDescInitEntry(tupdesc, i + 1, - NameStr(tupdesc->attrs[i]->attname), + NameStr(att->attname), anyelement_type, -1, 0); @@ -562,7 +564,7 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args, break; case ANYARRAYOID: TupleDescInitEntry(tupdesc, i + 1, - NameStr(tupdesc->attrs[i]->attname), + NameStr(att->attname), anyarray_type, -1, 0); @@ -570,7 +572,7 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args, break; case ANYRANGEOID: TupleDescInitEntry(tupdesc, i + 1, - NameStr(tupdesc->attrs[i]->attname), + NameStr(att->attname), anyrange_type, -1, 0); @@ -1344,9 +1346,10 @@ TypeGetTupleDesc(Oid typeoid, List *colaliases) for (varattno = 0; varattno < natts; varattno++) { char *label = strVal(list_nth(colaliases, varattno)); + Form_pg_attribute attr = TupleDescAttr(tupdesc, varattno); if (label != NULL) - namestrcpy(&(tupdesc->attrs[varattno]->attname), label); + namestrcpy(&(attr->attname), label); } /* The tuple type is now an anonymous record type */ diff --git a/src/backend/utils/misc/pg_config.c b/src/backend/utils/misc/pg_config.c index 468c7cc9e1..a84878994c 100644 --- a/src/backend/utils/misc/pg_config.c +++ b/src/backend/utils/misc/pg_config.c @@ -54,8 +54,8 @@ pg_config(PG_FUNCTION_ARGS) * Check to make sure we have a reasonable tuple descriptor */ if (tupdesc->natts != 2 || - tupdesc->attrs[0]->atttypid != TEXTOID || - tupdesc->attrs[1]->atttypid != TEXTOID) + TupleDescAttr(tupdesc, 0)->atttypid != TEXTOID || + TupleDescAttr(tupdesc, 1)->atttypid != TEXTOID) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("query-specified return tuple and " diff --git a/src/include/access/htup_details.h b/src/include/access/htup_details.h index 3e1676c7e6..fa04a63b76 100644 --- a/src/include/access/htup_details.h +++ b/src/include/access/htup_details.h @@ -722,11 +722,11 @@ struct MinimalTupleData (*(isnull) = false), \ HeapTupleNoNulls(tup) ? \ ( \ - (tupleDesc)->attrs[(attnum)-1]->attcacheoff >= 0 ? \ + TupleDescAttr((tupleDesc), (attnum)-1)->attcacheoff >= 0 ? \ ( \ - fetchatt((tupleDesc)->attrs[(attnum)-1], \ + fetchatt(TupleDescAttr((tupleDesc), (attnum)-1), \ (char *) (tup)->t_data + (tup)->t_data->t_hoff + \ - (tupleDesc)->attrs[(attnum)-1]->attcacheoff) \ + TupleDescAttr((tupleDesc), (attnum)-1)->attcacheoff)\ ) \ : \ nocachegetattr((tup), (attnum), (tupleDesc)) \ diff --git a/src/include/access/itup.h b/src/include/access/itup.h index a94e7948b4..c178ae91a9 100644 --- a/src/include/access/itup.h +++ b/src/include/access/itup.h @@ -103,11 +103,11 @@ typedef IndexAttributeBitMapData * IndexAttributeBitMap; *(isnull) = false, \ !IndexTupleHasNulls(tup) ? \ ( \ - (tupleDesc)->attrs[(attnum)-1]->attcacheoff >= 0 ? \ + TupleDescAttr((tupleDesc), (attnum)-1)->attcacheoff >= 0 ? \ ( \ - fetchatt((tupleDesc)->attrs[(attnum)-1], \ + fetchatt(TupleDescAttr((tupleDesc), (attnum)-1), \ (char *) (tup) + IndexInfoFindDataOffset((tup)->t_info) \ - + (tupleDesc)->attrs[(attnum)-1]->attcacheoff) \ + + TupleDescAttr((tupleDesc), (attnum)-1)->attcacheoff) \ ) \ : \ nocache_index_getattr((tup), (attnum), (tupleDesc)) \ diff --git a/src/include/access/tupdesc.h b/src/include/access/tupdesc.h index e7065d70ba..31b77a08fa 100644 --- a/src/include/access/tupdesc.h +++ b/src/include/access/tupdesc.h @@ -80,6 +80,8 @@ typedef struct tupleDesc int tdrefcount; /* reference count, or -1 if not counting */ } *TupleDesc; +/* Accessor for the i'th attribute of tupdesc. */ +#define TupleDescAttr(tupdesc, i) ((tupdesc)->attrs[(i)]) extern TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid); diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c index afebec910d..5a575bdbe4 100644 --- a/src/pl/plperl/plperl.c +++ b/src/pl/plperl/plperl.c @@ -1095,6 +1095,7 @@ plperl_build_tuple_result(HV *perlhash, TupleDesc td) SV *val = HeVAL(he); char *key = hek2cstr(he); int attn = SPI_fnumber(td, key); + Form_pg_attribute attr = TupleDescAttr(td, attn - 1); if (attn == SPI_ERROR_NOATTRIBUTE) ereport(ERROR, @@ -1108,8 +1109,8 @@ plperl_build_tuple_result(HV *perlhash, TupleDesc td) key))); values[attn - 1] = plperl_sv_to_datum(val, - td->attrs[attn - 1]->atttypid, - td->attrs[attn - 1]->atttypmod, + attr->atttypid, + attr->atttypmod, NULL, NULL, InvalidOid, @@ -1757,6 +1758,7 @@ plperl_modify_tuple(HV *hvTD, TriggerData *tdata, HeapTuple otup) char *key = hek2cstr(he); SV *val = HeVAL(he); int attn = SPI_fnumber(tupdesc, key); + Form_pg_attribute attr = TupleDescAttr(tupdesc, attn - 1); if (attn == SPI_ERROR_NOATTRIBUTE) ereport(ERROR, @@ -1770,8 +1772,8 @@ plperl_modify_tuple(HV *hvTD, TriggerData *tdata, HeapTuple otup) key))); modvalues[attn - 1] = plperl_sv_to_datum(val, - tupdesc->attrs[attn - 1]->atttypid, - tupdesc->attrs[attn - 1]->atttypmod, + attr->atttypid, + attr->atttypmod, NULL, NULL, InvalidOid, @@ -3014,11 +3016,12 @@ plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc) typisvarlena; char *attname; Oid typoutput; + Form_pg_attribute att = TupleDescAttr(tupdesc, i); - if (tupdesc->attrs[i]->attisdropped) + if (att->attisdropped) continue; - attname = NameStr(tupdesc->attrs[i]->attname); + attname = NameStr(att->attname); attr = heap_getattr(tuple, i + 1, tupdesc, &isnull); if (isnull) @@ -3032,7 +3035,7 @@ plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc) continue; } - if (type_is_rowtype(tupdesc->attrs[i]->atttypid)) + if (type_is_rowtype(att->atttypid)) { SV *sv = plperl_hash_from_datum(attr); @@ -3043,17 +3046,16 @@ plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc) SV *sv; Oid funcid; - if (OidIsValid(get_base_element_type(tupdesc->attrs[i]->atttypid))) - sv = plperl_ref_from_pg_array(attr, tupdesc->attrs[i]->atttypid); - else if ((funcid = get_transform_fromsql(tupdesc->attrs[i]->atttypid, current_call_data->prodesc->lang_oid, current_call_data->prodesc->trftypes))) + if (OidIsValid(get_base_element_type(att->atttypid))) + sv = plperl_ref_from_pg_array(attr, att->atttypid); + else if ((funcid = get_transform_fromsql(att->atttypid, current_call_data->prodesc->lang_oid, current_call_data->prodesc->trftypes))) sv = (SV *) DatumGetPointer(OidFunctionCall1(funcid, attr)); else { char *outputstr; /* XXX should have a way to cache these lookups */ - getTypeOutputInfo(tupdesc->attrs[i]->atttypid, - &typoutput, &typisvarlena); + getTypeOutputInfo(att->atttypid, &typoutput, &typisvarlena); outputstr = OidOutputFunctionCall(typoutput, attr); sv = cstr2sv(outputstr); diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c index 662b3c97d7..e9d7ef55e9 100644 --- a/src/pl/plpgsql/src/pl_comp.c +++ b/src/pl/plpgsql/src/pl_comp.c @@ -2012,7 +2012,7 @@ build_row_from_class(Oid classOid) /* * Get the attribute and check for dropped column */ - attrStruct = row->rowtupdesc->attrs[i]; + attrStruct = TupleDescAttr(row->rowtupdesc, i); if (!attrStruct->attisdropped) { diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index 616f5e30f8..9716697259 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -2841,6 +2841,7 @@ exec_stmt_return_next(PLpgSQL_execstate *estate, PLpgSQL_var *var = (PLpgSQL_var *) retvar; Datum retval = var->value; bool isNull = var->isnull; + Form_pg_attribute attr = TupleDescAttr(tupdesc, 0); if (natts != 1) ereport(ERROR, @@ -2858,8 +2859,8 @@ exec_stmt_return_next(PLpgSQL_execstate *estate, &isNull, var->datatype->typoid, var->datatype->atttypmod, - tupdesc->attrs[0]->atttypid, - tupdesc->attrs[0]->atttypmod); + attr->atttypid, + attr->atttypmod); tuplestore_putvalues(estate->tuple_store, tupdesc, &retval, &isNull); @@ -2968,6 +2969,8 @@ exec_stmt_return_next(PLpgSQL_execstate *estate, } else { + Form_pg_attribute attr = TupleDescAttr(tupdesc, 0); + /* Simple scalar result */ if (natts != 1) ereport(ERROR, @@ -2980,8 +2983,8 @@ exec_stmt_return_next(PLpgSQL_execstate *estate, &isNull, rettype, rettypmod, - tupdesc->attrs[0]->atttypid, - tupdesc->attrs[0]->atttypmod); + attr->atttypid, + attr->atttypmod); tuplestore_putvalues(estate->tuple_store, tupdesc, &retval, &isNull); @@ -4588,8 +4591,8 @@ exec_assign_value(PLpgSQL_execstate *estate, * Now insert the new value, being careful to cast it to the * right type. */ - atttype = rec->tupdesc->attrs[fno - 1]->atttypid; - atttypmod = rec->tupdesc->attrs[fno - 1]->atttypmod; + atttype = TupleDescAttr(rec->tupdesc, fno - 1)->atttypid; + atttypmod = TupleDescAttr(rec->tupdesc, fno - 1)->atttypmod; values[0] = exec_cast_value(estate, value, &isNull, @@ -4913,7 +4916,11 @@ exec_eval_datum(PLpgSQL_execstate *estate, rec->refname, recfield->fieldname))); *typeid = SPI_gettypeid(rec->tupdesc, fno); if (fno > 0) - *typetypmod = rec->tupdesc->attrs[fno - 1]->atttypmod; + { + Form_pg_attribute attr = TupleDescAttr(rec->tupdesc, fno - 1); + + *typetypmod = attr->atttypmod; + } else *typetypmod = -1; *value = SPI_getbinval(rec->tup, rec->tupdesc, fno, isnull); @@ -5089,11 +5096,19 @@ plpgsql_exec_get_datum_type_info(PLpgSQL_execstate *estate, rec->refname, recfield->fieldname))); *typeid = SPI_gettypeid(rec->tupdesc, fno); if (fno > 0) - *typmod = rec->tupdesc->attrs[fno - 1]->atttypmod; + { + Form_pg_attribute attr = TupleDescAttr(rec->tupdesc, fno - 1); + + *typmod = attr->atttypmod; + } else *typmod = -1; if (fno > 0) - *collation = rec->tupdesc->attrs[fno - 1]->attcollation; + { + Form_pg_attribute attr = TupleDescAttr(rec->tupdesc, fno - 1); + + *collation = attr->attcollation; + } else /* no system column types have collation */ *collation = InvalidOid; break; @@ -5172,6 +5187,7 @@ exec_eval_expr(PLpgSQL_execstate *estate, { Datum result = 0; int rc; + Form_pg_attribute attr; /* * If first time through, create a plan for this expression. @@ -5211,8 +5227,9 @@ exec_eval_expr(PLpgSQL_execstate *estate, /* * ... and get the column's datatype. */ - *rettype = estate->eval_tuptable->tupdesc->attrs[0]->atttypid; - *rettypmod = estate->eval_tuptable->tupdesc->attrs[0]->atttypmod; + attr = TupleDescAttr(estate->eval_tuptable->tupdesc, 0); + *rettype = attr->atttypid; + *rettypmod = attr->atttypmod; /* * If there are no rows selected, the result is a NULL of that type. @@ -6030,7 +6047,8 @@ exec_move_row(PLpgSQL_execstate *estate, var = (PLpgSQL_var *) (estate->datums[row->varnos[fnum]]); - while (anum < td_natts && tupdesc->attrs[anum]->attisdropped) + while (anum < td_natts && + TupleDescAttr(tupdesc, anum)->attisdropped) anum++; /* skip dropped column in tuple */ if (anum < td_natts) @@ -6042,8 +6060,8 @@ exec_move_row(PLpgSQL_execstate *estate, value = (Datum) 0; isnull = true; } - valtype = tupdesc->attrs[anum]->atttypid; - valtypmod = tupdesc->attrs[anum]->atttypmod; + valtype = TupleDescAttr(tupdesc, anum)->atttypid; + valtypmod = TupleDescAttr(tupdesc, anum)->atttypmod; anum++; } else @@ -6095,7 +6113,7 @@ make_tuple_from_row(PLpgSQL_execstate *estate, Oid fieldtypeid; int32 fieldtypmod; - if (tupdesc->attrs[i]->attisdropped) + if (TupleDescAttr(tupdesc, i)->attisdropped) { nulls[i] = true; /* leave the column as null */ continue; @@ -6106,7 +6124,7 @@ make_tuple_from_row(PLpgSQL_execstate *estate, exec_eval_datum(estate, estate->datums[row->varnos[i]], &fieldtypeid, &fieldtypmod, &dvalues[i], &nulls[i]); - if (fieldtypeid != tupdesc->attrs[i]->atttypid) + if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; /* XXX should we insist on typmod match, too? */ } diff --git a/src/pl/plpython/plpy_exec.c b/src/pl/plpython/plpy_exec.c index c6938d00aa..26f61dd0f3 100644 --- a/src/pl/plpython/plpy_exec.c +++ b/src/pl/plpython/plpy_exec.c @@ -950,6 +950,7 @@ PLy_modify_tuple(PLyProcedure *proc, PyObject *pltd, TriggerData *tdata, char *plattstr; int attn; PLyObToDatum *att; + Form_pg_attribute attr; platt = PyList_GetItem(plkeys, i); if (PyString_Check(platt)) @@ -982,11 +983,12 @@ PLy_modify_tuple(PLyProcedure *proc, PyObject *pltd, TriggerData *tdata, Py_INCREF(plval); + attr = TupleDescAttr(tupdesc, attn - 1); if (plval != Py_None) { modvalues[attn - 1] = (att->func) (att, - tupdesc->attrs[attn - 1]->atttypmod, + attr->atttypmod, plval, false); modnulls[attn - 1] = false; @@ -997,7 +999,7 @@ PLy_modify_tuple(PLyProcedure *proc, PyObject *pltd, TriggerData *tdata, InputFunctionCall(&att->typfunc, NULL, att->typioparam, - tupdesc->attrs[attn - 1]->atttypmod); + attr->atttypmod); modnulls[attn - 1] = true; } modrepls[attn - 1] = true; diff --git a/src/pl/plpython/plpy_resultobject.c b/src/pl/plpython/plpy_resultobject.c index 077bde6dc3..098a366f6f 100644 --- a/src/pl/plpython/plpy_resultobject.c +++ b/src/pl/plpython/plpy_resultobject.c @@ -148,7 +148,11 @@ PLy_result_colnames(PyObject *self, PyObject *unused) list = PyList_New(ob->tupdesc->natts); for (i = 0; i < ob->tupdesc->natts; i++) - PyList_SET_ITEM(list, i, PyString_FromString(NameStr(ob->tupdesc->attrs[i]->attname))); + { + Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i); + + PyList_SET_ITEM(list, i, PyString_FromString(NameStr(attr->attname))); + } return list; } @@ -168,7 +172,11 @@ PLy_result_coltypes(PyObject *self, PyObject *unused) list = PyList_New(ob->tupdesc->natts); for (i = 0; i < ob->tupdesc->natts; i++) - PyList_SET_ITEM(list, i, PyInt_FromLong(ob->tupdesc->attrs[i]->atttypid)); + { + Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i); + + PyList_SET_ITEM(list, i, PyInt_FromLong(attr->atttypid)); + } return list; } @@ -188,7 +196,11 @@ PLy_result_coltypmods(PyObject *self, PyObject *unused) list = PyList_New(ob->tupdesc->natts); for (i = 0; i < ob->tupdesc->natts; i++) - PyList_SET_ITEM(list, i, PyInt_FromLong(ob->tupdesc->attrs[i]->atttypmod)); + { + Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i); + + PyList_SET_ITEM(list, i, PyInt_FromLong(attr->atttypmod)); + } return list; } diff --git a/src/pl/plpython/plpy_typeio.c b/src/pl/plpython/plpy_typeio.c index 91ddcaa7b9..e4af8cc9ef 100644 --- a/src/pl/plpython/plpy_typeio.c +++ b/src/pl/plpython/plpy_typeio.c @@ -152,21 +152,21 @@ PLy_input_tuple_funcs(PLyTypeInfo *arg, TupleDesc desc) for (i = 0; i < desc->natts; i++) { HeapTuple typeTup; + Form_pg_attribute attr = TupleDescAttr(desc, i); - if (desc->attrs[i]->attisdropped) + if (attr->attisdropped) continue; - if (arg->in.r.atts[i].typoid == desc->attrs[i]->atttypid) + if (arg->in.r.atts[i].typoid == attr->atttypid) continue; /* already set up this entry */ - typeTup = SearchSysCache1(TYPEOID, - ObjectIdGetDatum(desc->attrs[i]->atttypid)); + typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(attr->atttypid)); if (!HeapTupleIsValid(typeTup)) elog(ERROR, "cache lookup failed for type %u", - desc->attrs[i]->atttypid); + attr->atttypid); PLy_input_datum_func2(&(arg->in.r.atts[i]), arg->mcxt, - desc->attrs[i]->atttypid, + attr->atttypid, typeTup, exec_ctx->curr_proc->langid, exec_ctx->curr_proc->trftypes); @@ -224,18 +224,18 @@ PLy_output_tuple_funcs(PLyTypeInfo *arg, TupleDesc desc) for (i = 0; i < desc->natts; i++) { HeapTuple typeTup; + Form_pg_attribute attr = TupleDescAttr(desc, i); - if (desc->attrs[i]->attisdropped) + if (attr->attisdropped) continue; - if (arg->out.r.atts[i].typoid == desc->attrs[i]->atttypid) + if (arg->out.r.atts[i].typoid == attr->atttypid) continue; /* already set up this entry */ - typeTup = SearchSysCache1(TYPEOID, - ObjectIdGetDatum(desc->attrs[i]->atttypid)); + typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(attr->atttypid)); if (!HeapTupleIsValid(typeTup)) elog(ERROR, "cache lookup failed for type %u", - desc->attrs[i]->atttypid); + attr->atttypid); PLy_output_datum_func2(&(arg->out.r.atts[i]), arg->mcxt, typeTup, exec_ctx->curr_proc->langid, @@ -306,11 +306,12 @@ PLyDict_FromTuple(PLyTypeInfo *info, HeapTuple tuple, TupleDesc desc) Datum vattr; bool is_null; PyObject *value; + Form_pg_attribute attr = TupleDescAttr(desc, i); - if (desc->attrs[i]->attisdropped) + if (attr->attisdropped) continue; - key = NameStr(desc->attrs[i]->attname); + key = NameStr(attr->attname); vattr = heap_getattr(tuple, (i + 1), desc, &is_null); if (is_null || info->in.r.atts[i].func == NULL) @@ -1183,15 +1184,16 @@ PLyMapping_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *mapping) char *key; PyObject *volatile value; PLyObToDatum *att; + Form_pg_attribute attr = TupleDescAttr(desc, i); - if (desc->attrs[i]->attisdropped) + if (attr->attisdropped) { values[i] = (Datum) 0; nulls[i] = true; continue; } - key = NameStr(desc->attrs[i]->attname); + key = NameStr(attr->attname); value = NULL; att = &info->out.r.atts[i]; PG_TRY(); @@ -1256,7 +1258,7 @@ PLySequence_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *sequence) idx = 0; for (i = 0; i < desc->natts; i++) { - if (!desc->attrs[i]->attisdropped) + if (!TupleDescAttr(desc, i)->attisdropped) idx++; } if (PySequence_Length(sequence) != idx) @@ -1277,7 +1279,7 @@ PLySequence_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *sequence) PyObject *volatile value; PLyObToDatum *att; - if (desc->attrs[i]->attisdropped) + if (TupleDescAttr(desc, i)->attisdropped) { values[i] = (Datum) 0; nulls[i] = true; @@ -1346,15 +1348,16 @@ PLyGenericObject_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *object char *key; PyObject *volatile value; PLyObToDatum *att; + Form_pg_attribute attr = TupleDescAttr(desc, i); - if (desc->attrs[i]->attisdropped) + if (attr->attisdropped) { values[i] = (Datum) 0; nulls[i] = true; continue; } - key = NameStr(desc->attrs[i]->attname); + key = NameStr(attr->attname); value = NULL; att = &info->out.r.atts[i]; PG_TRY(); diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c index ed494e1210..09f87ec791 100644 --- a/src/pl/tcl/pltcl.c +++ b/src/pl/tcl/pltcl.c @@ -1106,11 +1106,13 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS, pltcl_call_state *call_state, Tcl_ListObjAppendElement(NULL, tcl_trigtup, Tcl_NewObj()); for (i = 0; i < tupdesc->natts; i++) { - if (tupdesc->attrs[i]->attisdropped) + Form_pg_attribute att = TupleDescAttr(tupdesc, i); + + if (att->attisdropped) Tcl_ListObjAppendElement(NULL, tcl_trigtup, Tcl_NewObj()); else Tcl_ListObjAppendElement(NULL, tcl_trigtup, - Tcl_NewStringObj(utf_e2u(NameStr(tupdesc->attrs[i]->attname)), -1)); + Tcl_NewStringObj(utf_e2u(NameStr(att->attname)), -1)); } Tcl_ListObjAppendElement(NULL, tcl_cmd, tcl_trigtup); @@ -2952,15 +2954,17 @@ pltcl_set_tuple_values(Tcl_Interp *interp, const char *arrayname, for (i = 0; i < tupdesc->natts; i++) { + Form_pg_attribute att = TupleDescAttr(tupdesc, i); + /* ignore dropped attributes */ - if (tupdesc->attrs[i]->attisdropped) + if (att->attisdropped) continue; /************************************************************ * Get the attribute name ************************************************************/ UTF_BEGIN; - attname = pstrdup(UTF_E2U(NameStr(tupdesc->attrs[i]->attname))); + attname = pstrdup(UTF_E2U(NameStr(att->attname))); UTF_END; /************************************************************ @@ -2978,8 +2982,7 @@ pltcl_set_tuple_values(Tcl_Interp *interp, const char *arrayname, ************************************************************/ if (!isnull) { - getTypeOutputInfo(tupdesc->attrs[i]->atttypid, - &typoutput, &typisvarlena); + getTypeOutputInfo(att->atttypid, &typoutput, &typisvarlena); outputstr = OidOutputFunctionCall(typoutput, attr); UTF_BEGIN; Tcl_SetVar2Ex(interp, *arrptr, *nameptr, @@ -3013,14 +3016,16 @@ pltcl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc) for (i = 0; i < tupdesc->natts; i++) { + Form_pg_attribute att = TupleDescAttr(tupdesc, i); + /* ignore dropped attributes */ - if (tupdesc->attrs[i]->attisdropped) + if (att->attisdropped) continue; /************************************************************ * Get the attribute name ************************************************************/ - attname = NameStr(tupdesc->attrs[i]->attname); + attname = NameStr(att->attname); /************************************************************ * Get the attributes value @@ -3037,7 +3042,7 @@ pltcl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc) ************************************************************/ if (!isnull) { - getTypeOutputInfo(tupdesc->attrs[i]->atttypid, + getTypeOutputInfo(att->atttypid, &typoutput, &typisvarlena); outputstr = OidOutputFunctionCall(typoutput, attr); UTF_BEGIN; diff --git a/src/test/regress/regress.c b/src/test/regress/regress.c index b73bccec3d..3d33b36e66 100644 --- a/src/test/regress/regress.c +++ b/src/test/regress/regress.c @@ -770,9 +770,9 @@ make_tuple_indirect(PG_FUNCTION_ARGS) struct varatt_indirect redirect_pointer; /* only work on existing, not-null varlenas */ - if (tupdesc->attrs[i]->attisdropped || + if (TupleDescAttr(tupdesc, i)->attisdropped || nulls[i] || - tupdesc->attrs[i]->attlen != -1) + TupleDescAttr(tupdesc, i)->attlen != -1) continue; attr = (struct varlena *) DatumGetPointer(values[i]);