From 303a4dd46705aa9aef49d0cc92ed66a49c16cd79 Mon Sep 17 00:00:00 2001 From: Matthias van de Meent Date: Fri, 8 Apr 2022 14:51:01 +0200 Subject: [PATCH v5 5/8] Add a function whose task it is to populate all attcacheoff-s of a TupleDesc's attributes It fills uncacheable offsets with -2; as opposed to -1 which signals "unknown", thus allowing users of the API to determine the cache-ability of an attribute at O(1) complexity after this one-time O(n) cost, as opposed to the repeated O(n) cost that currently applies. --- src/backend/access/common/tupdesc.c | 97 +++++++++++++++++++++++++++++ src/include/access/tupdesc.h | 2 + 2 files changed, 99 insertions(+) diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c index d6fb261e20..af4ef00f2b 100644 --- a/src/backend/access/common/tupdesc.c +++ b/src/backend/access/common/tupdesc.c @@ -919,3 +919,100 @@ BuildDescFromLists(List *names, List *types, List *typmods, List *collations) return desc; } + +/* + * PopulateTupleDescCacheOffsets + * + * Populate the attcacheoff fields of a TupleDesc, returning the last + * attcacheoff with a valid value. + * + * Sets attcacheoff to -2 for uncacheable attributes (i.e. attributes after a + * variable length attributes). + */ +AttrNumber +PopulateTupleDescCacheOffsets(TupleDesc desc) +{ + int numberOfAttributes = desc->natts; + AttrNumber i, j; + + if (TupleDescAttr(desc, desc->natts - 1)->attcacheoff != -1) + { + /* + * Already done the calculations, find the last attribute that has + * cache offset. + */ + for (i = (AttrNumber) numberOfAttributes; i > 1; i--) + { + if (TupleDescAttr(desc, i - 1)->attcacheoff != -2) + return i; + } + + return 1; + } + + /* + * First attribute always starts at offset zero. + */ + TupleDescAttr(desc, 0)->attcacheoff = 0; + + i = 1; + /* + * Someone might have set some offsets previously. + * Skip all positive offsets to get to the first attribute without + * attcacheoff. + */ + while (i < numberOfAttributes && TupleDescAttr(desc, i)->attcacheoff > 0) + i++; + + /* Cache offset is undetermined. Start calculating offsets if possible */ + if (i < numberOfAttributes && + TupleDescAttr(desc, i)->attcacheoff == -1) + { + Form_pg_attribute att = TupleDescAttr(desc, i - 1); + Size off = att->attcacheoff; + + if (att->attlen >= 0) { + off += att->attlen; + + while (i < numberOfAttributes) + { + att = TupleDescAttr(desc, i); + + if (att->attlen < 0) + { + if (off == att_align_nominal(off, att->attalign)) + att->attcacheoff = off; + else + att->attcacheoff = -2; + i++; + break; + } + + off = att_align_nominal(off, att->attalign); + att->attcacheoff = off; + off += att->attlen; + i++; + } + } else { + if (off == att_align_nominal(off, att->attalign)) + att->attcacheoff = off; + else + att->attcacheoff = -2; + i++; + } + } + + /* + * No cacheable offsets left. Fill the rest with -2s, but return the latest + * cached offset. + */ + j = i; + + while (i < numberOfAttributes) + { + TupleDescAttr(desc, i)->attcacheoff = -2; + i++; + } + + return j; +} diff --git a/src/include/access/tupdesc.h b/src/include/access/tupdesc.h index 28dd6de18b..219f837875 100644 --- a/src/include/access/tupdesc.h +++ b/src/include/access/tupdesc.h @@ -151,4 +151,6 @@ extern TupleDesc BuildDescForRelation(List *schema); extern TupleDesc BuildDescFromLists(List *names, List *types, List *typmods, List *collations); +extern AttrNumber PopulateTupleDescCacheOffsets(TupleDesc desc); + #endif /* TUPDESC_H */ -- 2.30.2