mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-17 19:13:16 +08:00
Refactor setting attributes in Arrow getsomeattrs()
When populating an Arrow slot's tts_values array with values in the getsomeattrs() function, the function set_attr_value() is called. This function requires passing in an ArrowArray which is acquired via a compression cache lookup. However, that lookup is not necassary for segmentby columns (which aren't compressed) and, to avoid it, a special fast-path was created for segmentby columns outside set_attr_value(). That, unfortunately, created som code duplication. This change moves the cache lookup into set_attr_value() instead, where it can be performed only for the columns that need it. This leads to cleaner code and less code duplication.
This commit is contained in:
parent
e73d0ceb04
commit
ea31d4f5c2
@ -314,7 +314,7 @@ arrow_cache_get_entry(ArrowTupleTableSlot *aslot)
|
|||||||
* are actually referenced in a query), so some returned arrays may be NULL
|
* are actually referenced in a query), so some returned arrays may be NULL
|
||||||
* for this reason.
|
* for this reason.
|
||||||
*/
|
*/
|
||||||
pg_attribute_always_inline ArrowArray **
|
ArrowArray **
|
||||||
arrow_column_cache_read_one(ArrowTupleTableSlot *aslot, AttrNumber attno)
|
arrow_column_cache_read_one(ArrowTupleTableSlot *aslot, AttrNumber attno)
|
||||||
{
|
{
|
||||||
const int16 *attrs_offset_map = arrow_slot_get_attribute_offset_map(&aslot->base.base);
|
const int16 *attrs_offset_map = arrow_slot_get_attribute_offset_map(&aslot->base.base);
|
||||||
|
@ -446,32 +446,20 @@ is_compressed_col(const TupleDesc tupdesc, AttrNumber attno)
|
|||||||
return coltypid == typinfo->type_oid;
|
return coltypid == typinfo->type_oid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static pg_attribute_always_inline ArrowArray *
|
||||||
set_attr_value(TupleTableSlot *slot, ArrowArray **arrow_arrays, const AttrNumber attnum)
|
set_attr_value(TupleTableSlot *slot, const int16 attoff)
|
||||||
{
|
{
|
||||||
ArrowTupleTableSlot *aslot = (ArrowTupleTableSlot *) slot;
|
ArrowTupleTableSlot *aslot = (ArrowTupleTableSlot *) slot;
|
||||||
const int16 *attrs_offset_map = arrow_slot_get_attribute_offset_map(slot);
|
ArrowArray *arrow_array = NULL;
|
||||||
const int16 attoff = AttrNumberGetAttrOffset(attnum);
|
|
||||||
|
|
||||||
TS_DEBUG_LOG("attnum: %d, valid: %s, segmentby: %s, array: %s",
|
TS_DEBUG_LOG("attnum: %d, valid: %s, segmentby: %s",
|
||||||
attnum,
|
AttrOffsetGetAttrNumber(attoff),
|
||||||
yes_no(aslot->valid_attrs[attoff]),
|
yes_no(aslot->valid_attrs[attoff]),
|
||||||
yes_no(aslot->segmentby_attrs[attoff]),
|
yes_no(aslot->segmentby_attrs[attoff]));
|
||||||
yes_no(arrow_arrays[attoff]));
|
|
||||||
|
|
||||||
/* Check if value is already set */
|
|
||||||
if (aslot->valid_attrs[attoff])
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Nothing to do for dropped attribute */
|
|
||||||
if (attrs_offset_map[attoff] == -1)
|
|
||||||
{
|
|
||||||
Assert(TupleDescAttr(slot->tts_tupleDescriptor, attoff)->attisdropped);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aslot->segmentby_attrs[attoff])
|
if (aslot->segmentby_attrs[attoff])
|
||||||
{
|
{
|
||||||
|
const int16 *attrs_offset_map = arrow_slot_get_attribute_offset_map(slot);
|
||||||
const int16 cattoff = attrs_offset_map[attoff]; /* offset in compressed tuple */
|
const int16 cattoff = attrs_offset_map[attoff]; /* offset in compressed tuple */
|
||||||
const AttrNumber cattnum = AttrOffsetGetAttrNumber(cattoff);
|
const AttrNumber cattnum = AttrOffsetGetAttrNumber(cattoff);
|
||||||
|
|
||||||
@ -480,27 +468,37 @@ set_attr_value(TupleTableSlot *slot, ArrowArray **arrow_arrays, const AttrNumber
|
|||||||
slot->tts_values[attoff] =
|
slot->tts_values[attoff] =
|
||||||
slot_getattr(aslot->child_slot, cattnum, &slot->tts_isnull[attoff]);
|
slot_getattr(aslot->child_slot, cattnum, &slot->tts_isnull[attoff]);
|
||||||
}
|
}
|
||||||
else if (arrow_arrays[attoff] == NULL)
|
|
||||||
{
|
|
||||||
/* Since the column is not the segment-by column, and there is no
|
|
||||||
* decompressed data, the column must be NULL. Use the default
|
|
||||||
* value. */
|
|
||||||
slot->tts_values[attoff] =
|
|
||||||
getmissingattr(slot->tts_tupleDescriptor, attnum, &slot->tts_isnull[attoff]);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Value is compressed, so get it from the decompressed arrow array. */
|
const AttrNumber attnum = AttrOffsetGetAttrNumber(attoff);
|
||||||
const Form_pg_attribute attr = TupleDescAttr(slot->tts_tupleDescriptor, attoff);
|
ArrowArray **arrow_arrays = arrow_column_cache_read_one(aslot, attnum);
|
||||||
const Oid typid = attr->atttypid;
|
|
||||||
const int16 typlen = attr->attlen;
|
arrow_array = arrow_arrays[attoff];
|
||||||
const NullableDatum datum =
|
|
||||||
arrow_get_datum(arrow_arrays[attoff], typid, typlen, aslot->tuple_index - 1);
|
if (arrow_array == NULL)
|
||||||
slot->tts_values[attoff] = datum.value;
|
{
|
||||||
slot->tts_isnull[attoff] = datum.isnull;
|
/* Since the column is not the segment-by column, and there is no
|
||||||
|
* decompressed data, the column must be NULL. Use the default
|
||||||
|
* value. */
|
||||||
|
slot->tts_values[attoff] =
|
||||||
|
getmissingattr(slot->tts_tupleDescriptor, attnum, &slot->tts_isnull[attoff]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Value is compressed, so get it from the decompressed arrow array. */
|
||||||
|
const Form_pg_attribute attr = TupleDescAttr(slot->tts_tupleDescriptor, attoff);
|
||||||
|
const Oid typid = attr->atttypid;
|
||||||
|
const int16 typlen = attr->attlen;
|
||||||
|
const NullableDatum datum =
|
||||||
|
arrow_get_datum(arrow_arrays[attoff], typid, typlen, aslot->tuple_index - 1);
|
||||||
|
slot->tts_values[attoff] = datum.value;
|
||||||
|
slot->tts_isnull[attoff] = datum.isnull;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aslot->valid_attrs[attoff] = true;
|
aslot->valid_attrs[attoff] = true;
|
||||||
|
|
||||||
|
return arrow_array;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
@ -545,30 +543,8 @@ tts_arrow_getsomeattrs(TupleTableSlot *slot, int natts)
|
|||||||
/* Build the non-compressed tuple values array from the cached data. */
|
/* Build the non-compressed tuple values array from the cached data. */
|
||||||
for (int attoff = slot->tts_nvalid; attoff < natts; attoff++)
|
for (int attoff = slot->tts_nvalid; attoff < natts; attoff++)
|
||||||
{
|
{
|
||||||
const AttrNumber attno = AttrOffsetGetAttrNumber(attoff);
|
if (!aslot->valid_attrs[attoff] && is_used_attr(slot, attoff))
|
||||||
|
set_attr_value(slot, attoff);
|
||||||
if (!aslot->valid_attrs[attoff])
|
|
||||||
{
|
|
||||||
/* Check if we can do a fast path for segmentby values and avoid a
|
|
||||||
* decompression cache lookup */
|
|
||||||
if (aslot->segmentby_attrs[attoff])
|
|
||||||
{
|
|
||||||
const int16 *attrs_offset_map = arrow_slot_get_attribute_offset_map(slot);
|
|
||||||
const int16 cattoff = attrs_offset_map[attoff]; /* offset in compressed tuple */
|
|
||||||
const AttrNumber cattnum = AttrOffsetGetAttrNumber(cattoff);
|
|
||||||
|
|
||||||
/* Segment-by column. Value is not compressed so get directly from
|
|
||||||
* child slot. */
|
|
||||||
slot->tts_values[attoff] =
|
|
||||||
slot_getattr(aslot->child_slot, cattnum, &slot->tts_isnull[attoff]);
|
|
||||||
aslot->valid_attrs[attoff] = true;
|
|
||||||
}
|
|
||||||
else if (is_used_attr(slot, attoff))
|
|
||||||
{
|
|
||||||
ArrowArray **arrow_arrays = arrow_column_cache_read_one(aslot, attno);
|
|
||||||
set_attr_value(slot, arrow_arrays, attno);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
slot->tts_nvalid = natts;
|
slot->tts_nvalid = natts;
|
||||||
@ -787,11 +763,10 @@ arrow_slot_get_array(TupleTableSlot *slot, AttrNumber attno)
|
|||||||
if (!is_used_attr(slot, attoff))
|
if (!is_used_attr(slot, attoff))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
arrow_arrays = arrow_column_cache_read_one(aslot, attno);
|
|
||||||
|
|
||||||
if (!aslot->valid_attrs[attoff])
|
if (!aslot->valid_attrs[attoff])
|
||||||
set_attr_value(slot, arrow_arrays, attno);
|
return set_attr_value(slot, attoff);
|
||||||
|
|
||||||
|
arrow_arrays = arrow_column_cache_read_one(aslot, attno);
|
||||||
return arrow_arrays[attoff];
|
return arrow_arrays[attoff];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user