mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-24 18:55:04 +08:00
Move generic slot support functions from heaptuple.c into execTuples.c.
heaptuple.c was never a particular good fit for slot_getattr(), slot_getsomeattrs() and slot_getmissingattrs(), but in upcoming changes slots will be made more abstract (allowing slots that contain different types of tuples), making it clearly the wrong place. Note that slot_deform_tuple() remains in it's current place, as it clearly deals with a HeapTuple. getmissingattrs() also remains, but it's less clear that that's correct - but execTuples.c wouldn't be the right place. Author: Ashutosh Bapat. Discussion: https://postgr.es/m/20180220224318.gw4oe5jadhpmcdnm@alap3.anarazel.de
This commit is contained in:
parent
e73ca79fc7
commit
9d906f1119
@ -80,7 +80,7 @@
|
||||
/*
|
||||
* Return the missing value of an attribute, or NULL if there isn't one.
|
||||
*/
|
||||
static Datum
|
||||
Datum
|
||||
getmissingattr(TupleDesc tupleDesc,
|
||||
int attnum, bool *isnull)
|
||||
{
|
||||
@ -111,43 +111,6 @@ getmissingattr(TupleDesc tupleDesc,
|
||||
return PointerGetDatum(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in missing values for a TupleTableSlot.
|
||||
*
|
||||
* This is only exposed because it's needed for JIT compiled tuple
|
||||
* deforming. That exception aside, there should be no callers outside of this
|
||||
* file.
|
||||
*/
|
||||
void
|
||||
slot_getmissingattrs(TupleTableSlot *slot, int startAttNum, int lastAttNum)
|
||||
{
|
||||
AttrMissing *attrmiss = NULL;
|
||||
int missattnum;
|
||||
|
||||
if (slot->tts_tupleDescriptor->constr)
|
||||
attrmiss = slot->tts_tupleDescriptor->constr->missing;
|
||||
|
||||
if (!attrmiss)
|
||||
{
|
||||
/* no missing values array at all, so just fill everything in as NULL */
|
||||
memset(slot->tts_values + startAttNum, 0,
|
||||
(lastAttNum - startAttNum) * sizeof(Datum));
|
||||
memset(slot->tts_isnull + startAttNum, 1,
|
||||
(lastAttNum - startAttNum) * sizeof(bool));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if there is a missing values array we must process them one by one */
|
||||
for (missattnum = startAttNum;
|
||||
missattnum < lastAttNum;
|
||||
missattnum++)
|
||||
{
|
||||
slot->tts_values[missattnum] = attrmiss[missattnum].am_value;
|
||||
slot->tts_isnull[missattnum] = !attrmiss[missattnum].am_present;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* heap_compute_data_size
|
||||
* Determine size of the data area of a tuple to be constructed
|
||||
@ -1398,7 +1361,7 @@ heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc,
|
||||
* re-computing information about previously extracted attributes.
|
||||
* slot->tts_nvalid is the number of attributes already extracted.
|
||||
*/
|
||||
static void
|
||||
void
|
||||
slot_deform_tuple(TupleTableSlot *slot, int natts)
|
||||
{
|
||||
HeapTuple tuple = slot->tts_tuple;
|
||||
@ -1492,153 +1455,6 @@ slot_deform_tuple(TupleTableSlot *slot, int natts)
|
||||
slot->tts_slow = slow;
|
||||
}
|
||||
|
||||
/*
|
||||
* slot_getattr
|
||||
* This function fetches an attribute of the slot's current tuple.
|
||||
* It is functionally equivalent to heap_getattr, but fetches of
|
||||
* multiple attributes of the same tuple will be optimized better,
|
||||
* because we avoid O(N^2) behavior from multiple calls of
|
||||
* nocachegetattr(), even when attcacheoff isn't usable.
|
||||
*
|
||||
* A difference from raw heap_getattr is that attnums beyond the
|
||||
* slot's tupdesc's last attribute will be considered NULL even
|
||||
* when the physical tuple is longer than the tupdesc.
|
||||
*/
|
||||
Datum
|
||||
slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
|
||||
{
|
||||
HeapTuple tuple = slot->tts_tuple;
|
||||
TupleDesc tupleDesc = slot->tts_tupleDescriptor;
|
||||
HeapTupleHeader tup;
|
||||
|
||||
/*
|
||||
* system attributes are handled by heap_getsysattr
|
||||
*/
|
||||
if (attnum <= 0)
|
||||
{
|
||||
if (tuple == NULL) /* internal error */
|
||||
elog(ERROR, "cannot extract system attribute from virtual tuple");
|
||||
if (tuple == &(slot->tts_minhdr)) /* internal error */
|
||||
elog(ERROR, "cannot extract system attribute from minimal tuple");
|
||||
return heap_getsysattr(tuple, attnum, tupleDesc, isnull);
|
||||
}
|
||||
|
||||
/*
|
||||
* fast path if desired attribute already cached
|
||||
*/
|
||||
if (attnum <= slot->tts_nvalid)
|
||||
{
|
||||
*isnull = slot->tts_isnull[attnum - 1];
|
||||
return slot->tts_values[attnum - 1];
|
||||
}
|
||||
|
||||
/*
|
||||
* return NULL if attnum is out of range according to the tupdesc
|
||||
*/
|
||||
if (attnum > tupleDesc->natts)
|
||||
{
|
||||
*isnull = true;
|
||||
return (Datum) 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* otherwise we had better have a physical tuple (tts_nvalid should equal
|
||||
* natts in all virtual-tuple cases)
|
||||
*/
|
||||
if (tuple == NULL) /* internal error */
|
||||
elog(ERROR, "cannot extract attribute from empty tuple slot");
|
||||
|
||||
/*
|
||||
* return NULL or missing value if attnum is out of range according to the
|
||||
* tuple
|
||||
*
|
||||
* (We have to check this separately because of various inheritance and
|
||||
* table-alteration scenarios: the tuple could be either longer or shorter
|
||||
* than the tupdesc.)
|
||||
*/
|
||||
tup = tuple->t_data;
|
||||
if (attnum > HeapTupleHeaderGetNatts(tup))
|
||||
return getmissingattr(slot->tts_tupleDescriptor, attnum, isnull);
|
||||
|
||||
/*
|
||||
* check if target attribute is null: no point in groveling through tuple
|
||||
*/
|
||||
if (HeapTupleHasNulls(tuple) && att_isnull(attnum - 1, tup->t_bits))
|
||||
{
|
||||
*isnull = true;
|
||||
return (Datum) 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the attribute's column has been dropped, we force a NULL result.
|
||||
* 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 (TupleDescAttr(tupleDesc, attnum - 1)->attisdropped)
|
||||
{
|
||||
*isnull = true;
|
||||
return (Datum) 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract the attribute, along with any preceding attributes.
|
||||
*/
|
||||
slot_deform_tuple(slot, attnum);
|
||||
|
||||
/*
|
||||
* The result is acquired from tts_values array.
|
||||
*/
|
||||
*isnull = slot->tts_isnull[attnum - 1];
|
||||
return slot->tts_values[attnum - 1];
|
||||
}
|
||||
|
||||
/*
|
||||
* slot_getsomeattrs
|
||||
* This function forces the entries of the slot's Datum/isnull
|
||||
* arrays to be valid at least up through the attnum'th entry.
|
||||
*/
|
||||
void
|
||||
slot_getsomeattrs(TupleTableSlot *slot, int attnum)
|
||||
{
|
||||
HeapTuple tuple;
|
||||
int attno;
|
||||
|
||||
/* Quick out if we have 'em all already */
|
||||
if (slot->tts_nvalid >= attnum)
|
||||
return;
|
||||
|
||||
/* Check for caller error */
|
||||
if (attnum <= 0 || attnum > slot->tts_tupleDescriptor->natts)
|
||||
elog(ERROR, "invalid attribute number %d", attnum);
|
||||
|
||||
/*
|
||||
* otherwise we had better have a physical tuple (tts_nvalid should equal
|
||||
* natts in all virtual-tuple cases)
|
||||
*/
|
||||
tuple = slot->tts_tuple;
|
||||
if (tuple == NULL) /* internal error */
|
||||
elog(ERROR, "cannot extract attribute from empty tuple slot");
|
||||
|
||||
/*
|
||||
* load up any slots available from physical tuple
|
||||
*/
|
||||
attno = HeapTupleHeaderGetNatts(tuple->t_data);
|
||||
attno = Min(attno, attnum);
|
||||
|
||||
slot_deform_tuple(slot, attno);
|
||||
|
||||
attno = slot->tts_nvalid;
|
||||
|
||||
/*
|
||||
* If tuple doesn't have all the atts indicated by attnum, read the rest
|
||||
* as NULLs or missing values
|
||||
*/
|
||||
if (attno < attnum)
|
||||
slot_getmissingattrs(slot, attno, attnum);
|
||||
|
||||
slot->tts_nvalid = attnum;
|
||||
}
|
||||
|
||||
/*
|
||||
* slot_attisnull
|
||||
* Detect whether an attribute of the slot is null, without
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/htup_details.h"
|
||||
#include "access/tupdesc_details.h"
|
||||
#include "access/tuptoaster.h"
|
||||
#include "funcapi.h"
|
||||
#include "catalog/pg_type.h"
|
||||
@ -959,6 +960,195 @@ ExecInitNullTupleSlot(EState *estate, TupleDesc tupType)
|
||||
return ExecStoreAllNullTuple(slot);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------
|
||||
* Routines for setting/accessing attributes in a slot.
|
||||
* ---------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* Fill in missing values for a TupleTableSlot.
|
||||
*
|
||||
* This is only exposed because it's needed for JIT compiled tuple
|
||||
* deforming. That exception aside, there should be no callers outside of this
|
||||
* file.
|
||||
*/
|
||||
void
|
||||
slot_getmissingattrs(TupleTableSlot *slot, int startAttNum, int lastAttNum)
|
||||
{
|
||||
AttrMissing *attrmiss = NULL;
|
||||
int missattnum;
|
||||
|
||||
if (slot->tts_tupleDescriptor->constr)
|
||||
attrmiss = slot->tts_tupleDescriptor->constr->missing;
|
||||
|
||||
if (!attrmiss)
|
||||
{
|
||||
/* no missing values array at all, so just fill everything in as NULL */
|
||||
memset(slot->tts_values + startAttNum, 0,
|
||||
(lastAttNum - startAttNum) * sizeof(Datum));
|
||||
memset(slot->tts_isnull + startAttNum, 1,
|
||||
(lastAttNum - startAttNum) * sizeof(bool));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if there is a missing values array we must process them one by one */
|
||||
for (missattnum = startAttNum;
|
||||
missattnum < lastAttNum;
|
||||
missattnum++)
|
||||
{
|
||||
slot->tts_values[missattnum] = attrmiss[missattnum].am_value;
|
||||
slot->tts_isnull[missattnum] = !attrmiss[missattnum].am_present;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* slot_getattr
|
||||
* This function fetches an attribute of the slot's current tuple.
|
||||
* It is functionally equivalent to heap_getattr, but fetches of
|
||||
* multiple attributes of the same tuple will be optimized better,
|
||||
* because we avoid O(N^2) behavior from multiple calls of
|
||||
* nocachegetattr(), even when attcacheoff isn't usable.
|
||||
*
|
||||
* A difference from raw heap_getattr is that attnums beyond the
|
||||
* slot's tupdesc's last attribute will be considered NULL even
|
||||
* when the physical tuple is longer than the tupdesc.
|
||||
*/
|
||||
Datum
|
||||
slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
|
||||
{
|
||||
HeapTuple tuple = slot->tts_tuple;
|
||||
TupleDesc tupleDesc = slot->tts_tupleDescriptor;
|
||||
HeapTupleHeader tup;
|
||||
|
||||
/*
|
||||
* system attributes are handled by heap_getsysattr
|
||||
*/
|
||||
if (attnum <= 0)
|
||||
{
|
||||
if (tuple == NULL) /* internal error */
|
||||
elog(ERROR, "cannot extract system attribute from virtual tuple");
|
||||
if (tuple == &(slot->tts_minhdr)) /* internal error */
|
||||
elog(ERROR, "cannot extract system attribute from minimal tuple");
|
||||
return heap_getsysattr(tuple, attnum, tupleDesc, isnull);
|
||||
}
|
||||
|
||||
/*
|
||||
* fast path if desired attribute already cached
|
||||
*/
|
||||
if (attnum <= slot->tts_nvalid)
|
||||
{
|
||||
*isnull = slot->tts_isnull[attnum - 1];
|
||||
return slot->tts_values[attnum - 1];
|
||||
}
|
||||
|
||||
/*
|
||||
* return NULL if attnum is out of range according to the tupdesc
|
||||
*/
|
||||
if (attnum > tupleDesc->natts)
|
||||
{
|
||||
*isnull = true;
|
||||
return (Datum) 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* otherwise we had better have a physical tuple (tts_nvalid should equal
|
||||
* natts in all virtual-tuple cases)
|
||||
*/
|
||||
if (tuple == NULL) /* internal error */
|
||||
elog(ERROR, "cannot extract attribute from empty tuple slot");
|
||||
|
||||
/*
|
||||
* return NULL or missing value if attnum is out of range according to the
|
||||
* tuple
|
||||
*
|
||||
* (We have to check this separately because of various inheritance and
|
||||
* table-alteration scenarios: the tuple could be either longer or shorter
|
||||
* than the tupdesc.)
|
||||
*/
|
||||
tup = tuple->t_data;
|
||||
if (attnum > HeapTupleHeaderGetNatts(tup))
|
||||
return getmissingattr(slot->tts_tupleDescriptor, attnum, isnull);
|
||||
|
||||
/*
|
||||
* check if target attribute is null: no point in groveling through tuple
|
||||
*/
|
||||
if (HeapTupleHasNulls(tuple) && att_isnull(attnum - 1, tup->t_bits))
|
||||
{
|
||||
*isnull = true;
|
||||
return (Datum) 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the attribute's column has been dropped, we force a NULL result.
|
||||
* 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 (TupleDescAttr(tupleDesc, attnum - 1)->attisdropped)
|
||||
{
|
||||
*isnull = true;
|
||||
return (Datum) 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract the attribute, along with any preceding attributes.
|
||||
*/
|
||||
slot_deform_tuple(slot, attnum);
|
||||
|
||||
/*
|
||||
* The result is acquired from tts_values array.
|
||||
*/
|
||||
*isnull = slot->tts_isnull[attnum - 1];
|
||||
return slot->tts_values[attnum - 1];
|
||||
}
|
||||
|
||||
/*
|
||||
* slot_getsomeattrs
|
||||
* This function forces the entries of the slot's Datum/isnull
|
||||
* arrays to be valid at least up through the attnum'th entry.
|
||||
*/
|
||||
void
|
||||
slot_getsomeattrs(TupleTableSlot *slot, int attnum)
|
||||
{
|
||||
HeapTuple tuple;
|
||||
int attno;
|
||||
|
||||
/* Quick out if we have 'em all already */
|
||||
if (slot->tts_nvalid >= attnum)
|
||||
return;
|
||||
|
||||
/* Check for caller error */
|
||||
if (attnum <= 0 || attnum > slot->tts_tupleDescriptor->natts)
|
||||
elog(ERROR, "invalid attribute number %d", attnum);
|
||||
|
||||
/*
|
||||
* otherwise we had better have a physical tuple (tts_nvalid should equal
|
||||
* natts in all virtual-tuple cases)
|
||||
*/
|
||||
tuple = slot->tts_tuple;
|
||||
if (tuple == NULL) /* internal error */
|
||||
elog(ERROR, "cannot extract attribute from empty tuple slot");
|
||||
|
||||
/*
|
||||
* load up any slots available from physical tuple
|
||||
*/
|
||||
attno = HeapTupleHeaderGetNatts(tuple->t_data);
|
||||
attno = Min(attno, attnum);
|
||||
|
||||
slot_deform_tuple(slot, attno);
|
||||
|
||||
attno = slot->tts_nvalid;
|
||||
|
||||
/*
|
||||
* If tuple doesn't have all the atts indicated by attnum, read the rest
|
||||
* as NULLs or missing values
|
||||
*/
|
||||
if (attno < attnum)
|
||||
slot_getmissingattrs(slot, attno, attnum);
|
||||
|
||||
slot->tts_nvalid = attnum;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecTypeFromTL
|
||||
*
|
||||
|
@ -835,5 +835,7 @@ extern MinimalTuple minimal_tuple_from_heap_tuple(HeapTuple htup);
|
||||
extern size_t varsize_any(void *p);
|
||||
extern HeapTuple heap_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc);
|
||||
extern MinimalTuple minimal_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc);
|
||||
struct TupleTableSlot;
|
||||
extern void slot_deform_tuple(struct TupleTableSlot *slot, int natts);
|
||||
|
||||
#endif /* HTUP_DETAILS_H */
|
||||
|
@ -173,14 +173,18 @@ extern Datum ExecFetchSlotTupleDatum(TupleTableSlot *slot);
|
||||
extern HeapTuple ExecMaterializeSlot(TupleTableSlot *slot);
|
||||
extern TupleTableSlot *ExecCopySlot(TupleTableSlot *dstslot,
|
||||
TupleTableSlot *srcslot);
|
||||
extern void slot_getmissingattrs(TupleTableSlot *slot, int startAttNum,
|
||||
int lastAttNum);
|
||||
extern Datum slot_getattr(TupleTableSlot *slot, int attnum,
|
||||
bool *isnull);
|
||||
extern void slot_getsomeattrs(TupleTableSlot *slot, int attnum);
|
||||
|
||||
/* in access/common/heaptuple.c */
|
||||
extern Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull);
|
||||
extern void slot_getsomeattrs(TupleTableSlot *slot, int attnum);
|
||||
extern bool slot_attisnull(TupleTableSlot *slot, int attnum);
|
||||
extern bool slot_getsysattr(TupleTableSlot *slot, int attnum,
|
||||
Datum *value, bool *isnull);
|
||||
extern void slot_getmissingattrs(TupleTableSlot *slot, int startAttNum, int lastAttNum);
|
||||
extern Datum getmissingattr(TupleDesc tupleDesc,
|
||||
int attnum, bool *isnull);
|
||||
|
||||
#ifndef FRONTEND
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user