Postgresql内核源码分析-如何向client发送tuple格式

 


目录

前言

概述

步骤分解

结尾


前言

本文是基于postgresql 15的代码进行分析解读,演示是在centos8系统上进行。


概述

当我们在客户端查询时,除了表中的数据之外,还有一个状态信息,看到的也是以tuple的形式展示出来,其实这此数据是临时组成tuple格式,而不是存储在表中的数据。

下面我们就来看下,这类型数据是如何拼装成tuple格式的,需要那些步骤。

步骤分解

  • 需要一个接收者
DestReceiver *dest;

dest = CreateDestReceiver(DestRemoteSimple);

  • tuple描述符,来记录tuple信息
TupleDesc  tupdesc;

/* need a tuple descriptor representing four columns */

    tupdesc = CreateTemplateTupleDesc(4);

    TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 1, "systemid",

                              TEXTOID, -1, 0);

    TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 2, "timeline",

                              INT4OID, -1, 0);

    TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 3, "xlogpos",

                              TEXTOID, -1, 0);

    TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 4, "dbname",

                              TEXTOID, -1, 0);

这里是一个有4列的tuple,然后定义每列的表头和类型,对应的参数分别为:

attributeNumber, 列的序号,从1开始

attributeName, 列名称,也就是表头显示

oidtypeid,列的类型ID,对应pg_type中的oid

typmod, 对应于pg_attribute中的atttypmod,记录了在表创建时提供的类型相关数据(例如一个varchar列的最大长度)。它会被传递给类型相关的输入函数和长度强制函数。对于那些不需要atttypmod的类型,这个值通常总是为-1。

attdim,如果该列是一个数组类型,这里就是其维度数;否则为0。

  • 输出状态,将接收者和tuple描述符关联起来
TupOutputState *tstate;

/* prepare for projection of tuples */

 tstate = begin_tup_output_tupdesc(dest, tupdesc, &TTSOpsVirtual);

通过定义的一组通用操作TTSOpsVirtual,将两者联系起来。

  • 开始准备数据
Datum      values[4];

bool        nulls[4];

 

/* column 1: system identifier */

    values[0] = CStringGetTextDatum(sysid);

    /* column 2: timeline */

    values[1] = Int32GetDatum(ThisTimeLineID);

    /* column 3: wal location */

    values[2] = CStringGetTextDatum(xloc);

    /* column 4: database name, or NULL if none */

    if (dbname)

        values[3] = CStringGetTextDatum(dbname);

    else

        nulls[3] = true;

 

此处需要定义两个数组,一个是存储数据,另一个是无数据时的null有效;

  • 发送数据 

先将数据填加到发送slot中;

/* insert data */

memcpy(slot->tts_values, values, natts * sizeof(Datum));

memcpy(slot->tts_isnull, isnull, natts * sizeof(bool));

 

修改slot的标志

slot->tts_flags &= ~TTS_FLAG_EMPTY;

slot->tts_nvalid = slot->tts_tupleDescriptor->natts;

调用接收者的发送接口进行处理

/* send the tuple to the receiver */

(void) tstate->dest->receiveSlot(slot, tstate->dest);
  • 结束发送

主要作用是清理现场,一是关闭当前接收者;二是释放过程中申请的内存资源

slot->tts_ops->clear(slot);

tstate->dest->rShutdown(tstate->dest);

最后再获后释放内存空间。


结尾

作者邮箱:[email protected]
如有错误或者疏漏欢迎指出,互相学习。

注:未经同意,不得转载!

猜你喜欢

转载自blog.csdn.net/senllang/article/details/129783558