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
英文地址,請注明出處:http://en.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

Pro?net Precision Transparent Clock Protocol (PN-PTCP) PN-PTCP&#xff08;精確透明時鐘協議&#xff09;是一種專用于 Profinet 的 二層協議&#xff0c;其作用是為網絡中的設備提供高精度的時間同步。用于實現網絡設備的高精度時間同步。