PostgreSQL RelationBuildTupleDesc 分解

/**		RelationBuildTupleDesc**		Form the relation's tuple descriptor from information in*		the pg_attribute, pg_attrdef & pg_constraint system catalogs.*///从pg_attribute,pg_attrdef和pg_constraint 获取字段信息以填充relation->rd_att
static void
//用到的结构体
/* This structure contains constraints of a tuple */
typedef struct TupleConstr
{AttrDefault *defval;		/* array */ConstrCheck *check;			/* array */struct AttrMissing *missing;	/* missing attributes values, NULL if none */uint16		num_defval;uint16		num_check;bool		has_not_null;bool		has_generated_stored;
} TupleConstr;RelationBuildTupleDesc(Relation relation)
{HeapTuple	pg_attribute_tuple;Relation	pg_attribute_desc;SysScanDesc pg_attribute_scan;ScanKeyData skey[2];int			need;TupleConstr *constr;AttrMissing *attrmiss = NULL;int			ndef = 0;/* fill rd_att's type ID fields (compare heap.c's AddNewRelationTuple) *///初始化赋予了RECORDOID,也就是2249relation->rd_att->tdtypeid =relation->rd_rel->reltype ? relation->rd_rel->reltype : RECORDOID;relation->rd_att->tdtypmod = -1;	/* just to be sure */constr = (TupleConstr *) MemoryContextAllocZero(CacheMemoryContext,sizeof(TupleConstr));constr->has_not_null = false;constr->has_generated_stored = false;/** Form a scan key that selects only user attributes (attnum > 0).* (Eliminating system attribute rows at the index level is lots faster* than fetching them.)*///类似执行select * from pg_attribute where attrelid='poly100w'::regclass and attnum>0; //初始化查询条件 attrelid='poly100w'::regclassScanKeyInit(&skey[0],Anum_pg_attribute_attrelid,BTEqualStrategyNumber, F_OIDEQ,ObjectIdGetDatum(RelationGetRelid(relation)));// attnum>0ScanKeyInit(&skey[1],Anum_pg_attribute_attnum,BTGreaterStrategyNumber, F_INT2GT,Int16GetDatum(0));/** Open pg_attribute and begin a scan.  Force heap scan if we haven't yet* built the critical relcache entries (this includes initdb and startup* without a pg_internal.init file).*/pg_attribute_desc = table_open(AttributeRelationId, AccessShareLock);pg_attribute_scan = systable_beginscan(pg_attribute_desc,AttributeRelidNumIndexId,criticalRelcachesBuilt,NULL,2, skey);/** add attribute data to relation->rd_att*///从pg_class的relnatts字段获取到的值need = RelationGetNumberOfAttributes(relation);while (HeapTupleIsValid(pg_attribute_tuple = systable_getnext(pg_attribute_scan))){Form_pg_attribute attp;int			attnum;//获取pg_attrubte获取一条记录attp = (Form_pg_attribute) GETSTRUCT(pg_attribute_tuple);attnum = attp->attnum;if (attnum <= 0 || attnum > RelationGetNumberOfAttributes(relation))elog(ERROR, "invalid attribute number %d for relation \"%s\"",attp->attnum, RelationGetRelationName(relation));#define ATTRIBUTE_FIXED_PART_SIZE \(offsetof(FormData_pg_attribute,attcollation) + sizeof(Oid))//拷贝固定大小部分到relation->rd_att[attnum-1]中memcpy(TupleDescAttr(relation->rd_att, attnum - 1),attp,ATTRIBUTE_FIXED_PART_SIZE);/* Update constraint/default info */if (attp->attnotnull)   //not null限制constr->has_not_null = true;if (attp->attgenerated == ATTRIBUTE_GENERATED_STORED)  //generated限制constr->has_generated_stored = true;if (attp->atthasdef)  //默认值ndef++;/* If the column has a "missing" value, put it in the attrmiss array *///是否有missing value,可以参考https://zhuanlan.zhihu.com/p/671012588if (attp->atthasmissing){Datum		missingval;bool		missingNull;/* Do we have a missing value? */missingval = heap_getattr(pg_attribute_tuple,Anum_pg_attribute_attmissingval,pg_attribute_desc->rd_att,&missingNull);if (!missingNull){/* Yes, fetch from the array */MemoryContext oldcxt;bool		is_null;int			one = 1;Datum		missval;if (attrmiss == NULL)attrmiss = (AttrMissing *)MemoryContextAllocZero(CacheMemoryContext,relation->rd_rel->relnatts *sizeof(AttrMissing));missval = array_get_element(missingval,1,&one,-1,attp->attlen,attp->attbyval,attp->attalign,&is_null);Assert(!is_null);if (attp->attbyval){/* for copy by val just copy the datum direct */attrmiss[attnum - 1].am_value = missval;}else{/* otherwise copy in the correct context */oldcxt = MemoryContextSwitchTo(CacheMemoryContext);attrmiss[attnum - 1].am_value = datumCopy(missval,attp->attbyval,attp->attlen);MemoryContextSwitchTo(oldcxt);}attrmiss[attnum - 1].am_present = true;}}need--;if (need == 0)break;}/** end the scan and close the attribute relation*/systable_endscan(pg_attribute_scan);table_close(pg_attribute_desc, AccessShareLock);if (need != 0)elog(ERROR, "pg_attribute catalog is missing %d attribute(s) for relation OID %u",need, RelationGetRelid(relation));/** The attcacheoff values we read from pg_attribute should all be -1* ("unknown").  Verify this if assert checking is on.  They will be* computed when and if needed during tuple access.*/
#ifdef USE_ASSERT_CHECKING{int			i;for (i = 0; i < RelationGetNumberOfAttributes(relation); i++)Assert(TupleDescAttr(relation->rd_att, i)->attcacheoff == -1);}
#endif/** However, we can easily set the attcacheoff value for the first* attribute: it must be zero.  This eliminates the need for special cases* for attnum=1 that used to exist in fastgetattr() and index_getattr().*/if (RelationGetNumberOfAttributes(relation) > 0)TupleDescAttr(relation->rd_att, 0)->attcacheoff = 0;/** Set up constraint/default info*/if (constr->has_not_null ||constr->has_generated_stored ||ndef > 0 ||attrmiss ||relation->rd_rel->relchecks > 0){relation->rd_att->constr = constr;//如果有default值,从pg_attrdef中获取//看代码2部分if (ndef > 0)			/* DEFAULTs */AttrDefaultFetch(relation, ndef);elseconstr->num_defval = 0;constr->missing = attrmiss;//如果有check(pg_class的relchecks的值),从pg_constraint中获取,具体见代码3if (relation->rd_rel->relchecks > 0)	/* CHECKs */CheckConstraintFetch(relation);elseconstr->num_check = 0;}else{pfree(constr);relation->rd_att->constr = NULL;}
}

代码2:AttrDefaultFetch

/** Load any default attribute value definitions for the relation.** ndef is the number of attributes that were marked atthasdef.** Note: we don't make it a hard error to be missing some pg_attrdef records.* We can limp along as long as nothing needs to use the default value.  Code* that fails to find an expected AttrDefault record should throw an error.*/typedef struct AttrDefault
{AttrNumber	adnum;char	   *adbin;			/* nodeToString representation of expr */
} AttrDefault;static void
AttrDefaultFetch(Relation relation, int ndef)
{AttrDefault *attrdef;Relation	adrel;SysScanDesc adscan;ScanKeyData skey;HeapTuple	htup;int			found = 0;/* Allocate array with room for as many entries as expected */attrdef = (AttrDefault *)MemoryContextAllocZero(CacheMemoryContext,ndef * sizeof(AttrDefault));/* Search pg_attrdef for relevant entries *///设置查询条件 adrelid='poly100w'::regclass;ScanKeyInit(&skey,Anum_pg_attrdef_adrelid,BTEqualStrategyNumber, F_OIDEQ,ObjectIdGetDatum(RelationGetRelid(relation)));adrel = table_open(AttrDefaultRelationId, AccessShareLock);adscan = systable_beginscan(adrel, AttrDefaultIndexId, true,NULL, 1, &skey);while (HeapTupleIsValid(htup = systable_getnext(adscan))){Form_pg_attrdef adform = (Form_pg_attrdef) GETSTRUCT(htup);Datum		val;bool		isnull;/* protect limited size of array */if (found >= ndef){elog(WARNING, "unexpected pg_attrdef record found for attribute %d of relation \"%s\"",adform->adnum, RelationGetRelationName(relation));break;}val = fastgetattr(htup,Anum_pg_attrdef_adbin,adrel->rd_att, &isnull);if (isnull)elog(WARNING, "null adbin for attribute %d of relation \"%s\"",adform->adnum, RelationGetRelationName(relation));else{/* detoast and convert to cstring in caller's context */char	   *s = TextDatumGetCString(val);//获取default的表达式attrdef[found].adnum = adform->adnum;attrdef[found].adbin = MemoryContextStrdup(CacheMemoryContext, s);pfree(s);found++;}}systable_endscan(adscan);table_close(adrel, AccessShareLock);if (found != ndef)elog(WARNING, "%d pg_attrdef record(s) missing for relation \"%s\"",ndef - found, RelationGetRelationName(relation));/** Sort the AttrDefault entries by adnum, for the convenience of* equalTupleDescs().  (Usually, they already will be in order, but this* might not be so if systable_getnext isn't using an index.)*/if (found > 1)qsort(attrdef, found, sizeof(AttrDefault), AttrDefaultCmp);/* Install array only after it's fully valid *///赋值rd_att->const->defvalrelation->rd_att->constr->defval = attrdef;relation->rd_att->constr->num_defval = found;
}

代码3:

/** Load any check constraints for the relation.** As with defaults, if we don't find the expected number of them, just warn* here.  The executor should throw an error if an INSERT/UPDATE is attempted.*/typedef struct ConstrCheck
{char	   *ccname;char	   *ccbin;			/* nodeToString representation of expr */bool		ccvalid;bool		ccnoinherit;	/* this is a non-inheritable constraint */
} ConstrCheck;static void
CheckConstraintFetch(Relation relation)
{ConstrCheck *check;int			ncheck = relation->rd_rel->relchecks;Relation	conrel;SysScanDesc conscan;ScanKeyData skey[1];HeapTuple	htup;int			found = 0;/* Allocate array with room for as many entries as expected */check = (ConstrCheck *)MemoryContextAllocZero(CacheMemoryContext,ncheck * sizeof(ConstrCheck));/* Search pg_constraint for relevant entries */// select * from pg_constraint where conrelid='poly100w'::regclass;ScanKeyInit(&skey[0],Anum_pg_constraint_conrelid,BTEqualStrategyNumber, F_OIDEQ,ObjectIdGetDatum(RelationGetRelid(relation)));conrel = table_open(ConstraintRelationId, AccessShareLock);conscan = systable_beginscan(conrel, ConstraintRelidTypidNameIndexId, true,NULL, 1, skey);while (HeapTupleIsValid(htup = systable_getnext(conscan))){Form_pg_constraint conform = (Form_pg_constraint) GETSTRUCT(htup);Datum		val;bool		isnull;/* We want check constraints only */if (conform->contype != CONSTRAINT_CHECK)continue;/* protect limited size of array */if (found >= ncheck){elog(WARNING, "unexpected pg_constraint record found for relation \"%s\"",RelationGetRelationName(relation));break;}check[found].ccvalid = conform->convalidated;check[found].ccnoinherit = conform->connoinherit;check[found].ccname = MemoryContextStrdup(CacheMemoryContext,NameStr(conform->conname));/* Grab and test conbin is actually set */val = fastgetattr(htup,Anum_pg_constraint_conbin,conrel->rd_att, &isnull);if (isnull)elog(WARNING, "null conbin for relation \"%s\"",RelationGetRelationName(relation));else{/* detoast and convert to cstring in caller's context */char	   *s = TextDatumGetCString(val);check[found].ccbin = MemoryContextStrdup(CacheMemoryContext, s);pfree(s);found++;}}systable_endscan(conscan);table_close(conrel, AccessShareLock);if (found != ncheck)elog(WARNING, "%d pg_constraint record(s) missing for relation \"%s\"",ncheck - found, RelationGetRelationName(relation));/** Sort the records by name.  This ensures that CHECKs are applied in a* deterministic order, and it also makes equalTupleDescs() faster.*/if (found > 1)qsort(check, found, sizeof(ConstrCheck), CheckConstraintCmp);/* Install array only after it's fully valid */relation->rd_att->constr->check = check;relation->rd_att->constr->num_check = found;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/916017.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/916017.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在 Alpine Linux 中创建虚拟机时 Cgroup 挂在失败的现象

现象&#xff1a;在 Alpine Linux 中部署 LXD或者incus 服务后&#xff0c;创建 容器或者虚拟机时提示 实例启动失败、退出代码为1&#xff1a;查询启动日志后&#xff0c;发现是 cgroup 挂载失败导致了 container 拉起失败。原因分析&#xff1a;从启动日志上看&#xff0c;是…

让UV管理一切!!!

一、遇到的问题 自己在做AI开发的时候&#xff0c;先用的conda来管理虚拟环境&#xff0c;然后使用pip freeze > reqiurments来打包相关依赖。 优点&#xff0c;conda环境可以让不同的项目有单独的虚拟环境&#xff0c;不会干扰每个项目&#xff0c;还可以多个项目共享一个…

Jmeter使用 - 2

5 参数化 5.1 自定义变量 线程组 --> 配置元件 --> 用户定义的变量 可以自定义变量&#xff0c;通过 ${变量名} 使用 5.2 随机函数 随机数函数 # 生产六位数的随机数字 ${__Random(100000,999999,)} # 生成随机时间: 时间格式yyyy-MM-dd,开始时间,结束时间,设置时区…

部署 Zabbix 企业级分布式监控

目录 一、监控系统的功能概述 1、监控的定义 2、监控的五个层次 &#xff08;1&#xff09;基础设施监控 &#xff08;2&#xff09;系统层监控 &#xff08;3&#xff09;应用层监控 &#xff08;4&#xff09;业务监控 &#xff08;5&#xff09;端用户体验监控 二、…

Silly Tavern 教程②:首次启动与基础设置

本文介绍 Silly Tavern 首次启动后的基础设置&#xff0c;包括语言切换与 AI 后端连接&#xff0c;重点推荐 无需付费即可使用的免费或低成本方案&#xff0c;涵盖 Groq、AI Horde、Gemini 和 OpenRouter。 一、启动 Silly Tavern 并访问界面 完成安装后&#xff0c;执行以下命…

C#解析JSON数据全攻略

还在为C#处理网络API返回的复杂JSON数据头疼吗&#xff1f;据统计&#xff0c;90%的开发者都曾在JSON解析上栽过跟头&#xff01; 本文将手把手教你用C#轻松玩转JSON数据&#xff1a;- HttpClient获取网络JSON数据- System.Text.Json动态解析技巧- 强类型模型转换实战- 特殊字…

8-大语言模型—指令理解:基于 LoRA 的大语言模型指令微调框架

目录 1、模型上下文窗口 1.1、增加上下文窗口的微调&#xff08;Fine-tuning for Longer Context&#xff09; 1.1.1、 核心目标 1.1.2、关键步骤 &#xff08;1&#xff09;数据准备&#xff1a;构建长文本训练集 &#xff08;2&#xff09;微调策略&#xff1a;分阶段适…

工业数据中台:PLC、SCADA、MES 的实时协同架构

在智能制造升级过程中&#xff0c;工业数据的互联互通是突破生产效率瓶颈的关键。PLC&#xff08;可编程逻辑控制器&#xff09;掌控着设备的实时运行参数&#xff0c;SCADA&#xff08;监控与数据采集系统&#xff09;负责车间级的状态监控&#xff0c;MES&#xff08;制造执行…

【Golang】Go语言基础语法

Go语言基础语法 文章目录Go语言基础语法一、Go标记二、行分隔符三、注释四、标识符五、字符串连接六、关键字七、Go语言的空格八、格式化字符串一、Go标记 Go程序可以由多个标记组成吗&#xff0c;可以是关键字、标识符、常量、字符串、符号。如下Go语句由6个标记组成&#xf…

WebRTC指纹——深度分析(中篇)

1. 引言 在上篇中,我们建立了WebRTC审查规避系统分析的理论基础,探讨了技术背景和威胁模型。中篇将深入分析WebRTC协议栈中的具体识别特征,通过对多个主流WebRTC应用的实际协议分析,揭示不同实现之间存在的显著差异。 这些协议层面的特征差异构成了审查系统进行指纹识别的…

谷粒商城篇章13--P340-P360--k8s/KubeSphere【高可用集群篇一】

1 k8s 1.1 简介 Kubernetes 简称 k8s。 是用于自动部署&#xff0c; 扩展和管理容器化应用程序的开源系统。 中文官网&#xff1a; https://kubernetes.io/zh/ 中文社区&#xff1a; https://www.kubernetes.org.cn/ 官方文档&#xff1a; https://kubernetes.io/zh/docs/h…

从零搭建 OpenCV 项目(新手向)-- 第二天 OpenCV图像预处理(一)

目录 一、图像翻转&#xff08;镜像翻转&#xff09; 1. 定义 2. OpenCV 函数 3. 数学表达 二、图像仿射变换 1. 定义 2. 仿射变换的基本原理 3. OpenCV 函数 4. 图像旋转 5. 图像平移 6. 图像缩放 7. 图像剪切 8. 为什么会出现黑色背景&#xff1f; 三、图像色彩…

贪心算法Day6学习心得

第一道&#xff1a;738. 单调递增的数字 - 力扣&#xff08;LeetCode&#xff09; 这道题目暴力算法肯定是最容易想到的&#xff0c;先附上暴力的代码&#xff1a; class Solution { private:// 判断一个数字的各位上是否是递增bool checkNum(int num) {int max 10;while (n…

数据的评估与清洗篇---上手清理索引和列名

重命名索引和列名 在读取数据时,如果我们发现数据的索引或者列名乱七八糟的,可以使用DataFrame的rename方法对它们进行重新命名。 df1.rename(index={...})df1.rename(columns={...}) 重命名索引 如果想改索引就把可选参数index指定为一个字典,针对索引,把要修改…

【ICML2025】时间序列|TimePro:炸裂!线性复杂度实现高效长程多元时间序列预测!

论文地址&#xff1a;https://arxiv.org/pdf/2505.20774 代码地址&#xff1a;https://github.com/xwmaxwma/TimePro 为了更好地理解时间序列模型的理论与实现&#xff0c;推荐参考UP “ThePPP时间序列” 的教学视频。该系列内容系统介绍了时间序列相关知识&#xff0c;并提供配…

2025真实面试试题分析-iOS客户端开发

以下是对iOS客户端开发工程师面试问题的分类整理、领域占比分析及高频问题精选&#xff08;基于​​85道问题&#xff0c;总出现次数118次​​&#xff09;。按技术领域整合为​​7大核心类别​​&#xff0c;按占比排序并精选高频问题标注优先级&#xff08;1-5&#x1f31f;&…

计算机网络简答题(大雪圣期末参考资料)

1、网络性能指标/计算机网络有哪些常用的性能指标&#xff1f;答&#xff1a;速率&#xff0c;带宽&#xff0c;吞吐量&#xff0c;时延&#xff08;发送时延、传播时延、处理时延、排队时延&#xff09;&#xff0c;时延带宽积&#xff0c;往返时间RTT和信道&#xff08;或网络…

红宝书单词学习笔记 list 76-100

list 76NO.WordMeaning1staleadj. 不新鲜的&#xff1b;陈腐的2stalln. 小隔间&#xff1b;摊位&#xff1b;牲畜棚&#xff1b;v. 停顿&#xff1b;(使) 熄火&#xff1b;故意拖延3staplen. 订书钉&#xff1b;主要产品&#xff1b;主要部分&#xff1b;主食&#xff1b;v. 用…

Vue3 学习教程,从入门到精通,Vue 3 计算属性(Computed Properties)知识点详解与案例代码(15)

Vue 3 计算属性&#xff08;Computed Properties&#xff09;知识点详解与案例代码 在 Vue 3 中&#xff0c;计算属性&#xff08;Computed Properties&#xff09; 是用于基于响应式数据派生新数据的一种方式。计算属性具有以下特点&#xff1a; 缓存性&#xff1a;只有在依赖…

2.5 PN-PTCP

Profinet Precision Transparent Clock Protocol (PN-PTCP) PN-PTCP&#xff08;精确透明时钟协议&#xff09;是一种专用于 Profinet 的 二层协议&#xff0c;其作用是为网络中的设备提供高精度的时间同步。用于实现网络设备的高精度时间同步。