From a65f4746b9cde8f19192d720d78c2edece5d26c2 Mon Sep 17 00:00:00 2001 From: "yizhi.fzh" Date: Mon, 4 Dec 2023 14:22:03 +0800 Subject: [PATCH v1] A PoC code to show the benefit of eagerly detoast code path. How to avoid this code path for the normal toast designed case needs more discussion. --- src/backend/executor/execExprInterp.c | 17 +++++++++++++++++ src/backend/executor/execTuples.c | 16 ++++++++++++++++ src/include/executor/tuptable.h | 3 +++ 3 files changed, 36 insertions(+) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 24c2b60c62..062b3d884a 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -56,6 +56,7 @@ */ #include "postgres.h" +#include "access/detoast.h" #include "access/heaptoast.h" #include "catalog/pg_type.h" #include "commands/sequence.h" @@ -567,6 +568,12 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) * have an Assert to check that that did happen. */ Assert(attnum >= 0 && attnum < innerslot->tts_nvalid); + + if (bms_is_member(attnum, innerslot->detoast_attrs) && + !innerslot->tts_isnull[attnum]) + innerslot->tts_values[attnum] = (Datum) pg_detoast_datum( + (struct varlena *) innerslot->tts_values[attnum]); + *op->resvalue = innerslot->tts_values[attnum]; *op->resnull = innerslot->tts_isnull[attnum]; @@ -580,6 +587,11 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) /* See EEOP_INNER_VAR comments */ Assert(attnum >= 0 && attnum < outerslot->tts_nvalid); + if (bms_is_member(attnum, outerslot->detoast_attrs) && + !outerslot->tts_isnull[attnum]) + outerslot->tts_values[attnum] = (Datum) pg_detoast_datum( + (struct varlena *) outerslot->tts_values[attnum]); + *op->resvalue = outerslot->tts_values[attnum]; *op->resnull = outerslot->tts_isnull[attnum]; @@ -593,6 +605,11 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) /* See EEOP_INNER_VAR comments */ Assert(attnum >= 0 && attnum < scanslot->tts_nvalid); + if (bms_is_member(attnum, scanslot->detoast_attrs) && + !scanslot->tts_isnull[attnum]) + scanslot->tts_values[attnum] = (Datum) pg_detoast_datum( + (struct varlena *) scanslot->tts_values[attnum]); + *op->resvalue = scanslot->tts_values[attnum]; *op->resnull = scanslot->tts_isnull[attnum]; diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c index 2c2712ceac..629c45fb52 100644 --- a/src/backend/executor/execTuples.c +++ b/src/backend/executor/execTuples.c @@ -62,6 +62,7 @@ #include "access/tupdesc_details.h" #include "catalog/pg_type.h" #include "funcapi.h" +#include "jit/jit.h" #include "nodes/nodeFuncs.h" #include "storage/bufmgr.h" #include "utils/builtins.h" @@ -1143,6 +1144,7 @@ MakeTupleTableSlot(TupleDesc tupleDesc, if (tupleDesc != NULL) { + int i; slot->tts_values = (Datum *) (((char *) slot) + MAXALIGN(basesz)); @@ -1152,6 +1154,20 @@ MakeTupleTableSlot(TupleDesc tupleDesc, + MAXALIGN(tupleDesc->natts * sizeof(Datum))); PinTupleDesc(tupleDesc); + + /* not ready jit so far, it's OK for a poc patch. */ + if (!jit_enabled) + { + for (i = 0; i < tupleDesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(tupleDesc, i); + if (attr->attlen == -1 && attr->attstorage != TYPSTORAGE_PLAIN) + { + slot->detoast_attrs = bms_add_member(slot->detoast_attrs, + attr->attnum - 1); + } + } + } } /* diff --git a/src/include/executor/tuptable.h b/src/include/executor/tuptable.h index 4210d6d838..75779ed31f 100644 --- a/src/include/executor/tuptable.h +++ b/src/include/executor/tuptable.h @@ -18,6 +18,7 @@ #include "access/htup_details.h" #include "access/sysattr.h" #include "access/tupdesc.h" +#include "nodes/bitmapset.h" #include "storage/buf.h" /*---------- @@ -128,6 +129,8 @@ typedef struct TupleTableSlot MemoryContext tts_mcxt; /* slot itself is in this context */ ItemPointerData tts_tid; /* stored tuple's tid */ Oid tts_tableOid; /* table oid of tuple */ + + Bitmapset *detoast_attrs; /* Index start from 0. */ } TupleTableSlot; /* routines for a TupleTableSlot implementation */ -- 2.34.1