第 11 課 PostgreSQL 增加一個(gè)內(nèi)核C函數(shù)

第一步 實(shí)現(xiàn)函數(shù)

增加的函數(shù)都放在src/backend/utils目錄下,我要實(shí)現(xiàn)的函數(shù)是從服務(wù)器查詢,并返回給調(diào)用者。
C函數(shù)原型:

char * sys_test(const uint32 id, const uint32 age)

開發(fā)者需要根據(jù)自己的需要,選擇目錄和文件:


image.png

我需要實(shí)現(xiàn)的功能在現(xiàn)有的文件中不存在相關(guān)性,我在adt目錄下自己創(chuàng)建了一個(gè)文件:test.c,文件內(nèi)容如下:

#include "postgres.h"

#include <sys/file.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>

#include "access/heapam.h"
#include "catalog/pg_type.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "postmaster/syslogger.h"
#include "storage/fd.h"
#include "utils/builtins.h"

/*
 * Read a page, returning it as binary
 */
Datum
sys_test(PG_FUNCTION_ARGS)
{
    uint32      id = PG_GETARG_INT32(0);
        uint32      age = PG_GETARG_INT32(1);

    printf("111111111111111111111\n");
    strcpy(buf, "xxxxxxxxxxxxxxxxxx");
    SET_VARSIZE(buf, nbytes + VARHDRSZ);

    PG_RETURN_TEXT_P(buf);
}

實(shí)際功能還需要實(shí)現(xiàn),我就打個(gè)樣。
修改Makefile,使其可以被編譯。打開文件adt/Makefile,增加文件test

如果你實(shí)現(xiàn)的函數(shù),在現(xiàn)有的文件中實(shí)現(xiàn),就不需要修改Makefile。

第二步 支持外部訪問

打開文件:src/include/utils/builtins.h,在文件尾部增加自己的函數(shù)。
extern Datum sys_test(PG_FUNCTION_ARGS);

第三步 注冊(cè)到名字空間

打開:src/include/catalog/pg_proc.h,找一個(gè)合適的位置增加自己的函數(shù)定義:

DATA(insert OID = 13624 ( sys_test      PGNSP 0 PGUID 12 t f f f t f v 2 17 17 i f i f f "23 23" _null_  _null_ _null_ _null_ _null_ _null_ sys_read_page 2D _null_ ));
DESCR("sys_test");

其中的OID,不可重復(fù),自己YY。

在模板庫(kù)中插入記錄,使任何庫(kù)一創(chuàng)建就有。對(duì)于系統(tǒng)表來(lái)說,在它的頭文件里有對(duì)這個(gè)系統(tǒng)表的詳細(xì)定義說明,在這個(gè)頭文件下面能按格式預(yù)置一些記錄,這些記錄在initdb時(shí)會(huì)插入到模板庫(kù)的對(duì)應(yīng)系統(tǒng)表中。具體來(lái)說,這些預(yù)置的記錄,在編譯過程中,會(huì)被perl腳本轉(zhuǎn)換到postgres.bki中,這個(gè)bki文件在安裝目錄的share文件夾,當(dāng)initdb時(shí),會(huì)加載這個(gè)bki并解析成一條條sql運(yùn)行,創(chuàng)建出一個(gè)個(gè)系統(tǒng)表,插入初始記錄,把初始的信息準(zhǔn)備好。有興趣者可以看看initdb模塊中 bootstrap_template1函數(shù),初始化模塊時(shí)第1件事就是加載postgres.bki文件翻譯解析執(zhí)行。

第四步 編譯和驗(yàn)證函數(shù)可用

重新編譯代碼,使其修改重新編譯。

make && make install

這種函數(shù)如果修改了pg_proc.h就必須要重新初始化數(shù)據(jù)庫(kù),不然不會(huì)生效:

./initdb ../data

在bin目錄下啟動(dòng)服務(wù)進(jìn)程:

./postgres

使用isql連接服務(wù)器:

./psql postgres

查詢函數(shù)定義:

postgres-# \df+ SYS_TEST
                                                        功能列表
   Schema    |     Name      | Result data type | Argument data types  | Owner  | Language |  Source code  | Description 
-------------+---------------+------------------+----------------------+--------+----------+---------------+-------------
 SYS_CATALOG | SYS_TEST | BYTEA            | TEXT, BIGINT, BIGINT | SYSTEM | INTERNAL | sys_test | 

我們仔細(xì)看,函數(shù)參數(shù)“TEXT, BIGINT, BIGINT”,其實(shí)是錯(cuò)誤的,與我們的函數(shù)定義:

char * sys_test(const uint32 id, const uint32 age)

是不一樣的,參數(shù)列表錯(cuò)誤,下面我們要找到原因,并修改。
關(guān)于參數(shù)設(shè)置可以參考:https://blog.csdn.net/postgres20/article/details/53446231

在pg_proc.h中插入的記錄是什么含義?

以第一行為例詳細(xì)說明如下:
DATA(insert OID = 13624 ( sys_read_page PGNSP 0 PGUID 12 t f f f t f v 2 17 17 i f i f f "25 20 20" null null null null null null sys_read_page 2D null ));

13624–OID使用內(nèi)核中未使用的OID即可(src/include/catalog下unused_oids,可以顯示未使用的oid) postgres內(nèi)部預(yù)留了1W多個(gè)oid給系統(tǒng)用,選一個(gè)沒有的就行,如果不知道哪些可用,在\src\include\catalog\ 下有個(gè)腳本文件unused_oids,運(yùn)行一下就能找出哪些oid可用,但要這是一個(gè)linux腳本,需要在linux下運(yùn)行。

PGNSP–函數(shù)所屬的名字空間的OID,PGNSP即pg_catalog(oid=11),內(nèi)置函數(shù)添加此值固定

PGUID–函數(shù)的擁有者OID,PGUID及initdb時(shí)指定用戶(oid=10),內(nèi)置函數(shù)添加此值固定

12–實(shí)現(xiàn)語(yǔ)言或該函數(shù)的調(diào)用接口,內(nèi)置函數(shù)使用12(internal),SQL用14

t–函數(shù)是否為一個(gè)聚集函數(shù)
f–函數(shù)是否為一個(gè)窗口函數(shù)
f–函數(shù)是一個(gè)安全性定義者(即,一個(gè)”setuid”函數(shù))
f–該函數(shù)沒有副作用。除了通過返回值,沒有關(guān)于參數(shù)的信息被傳播。任何會(huì)拋出基于其參數(shù)值的錯(cuò)誤信息的函數(shù)都不是泄露驗(yàn)證的。
t–當(dāng)任意調(diào)用函數(shù)為空時(shí),函數(shù)是否會(huì)返回空值。在那種情況下函數(shù)實(shí)際上根本不會(huì)被調(diào)用。非”strict”函數(shù)必須準(zhǔn)備好處理空值輸入。
f–函數(shù)是否返回一個(gè)集合(即,指定數(shù)據(jù)類型的多個(gè)值)
v–未知

2–輸入?yún)?shù)的個(gè)數(shù),對(duì)應(yīng)后面的""25 20 20""兩個(gè)參數(shù),明顯我們這里寫錯(cuò)了,找到了原因,我們修改為我們對(duì)應(yīng)的參數(shù)個(gè)數(shù)和類型:

"25 20 20" 改為 “23 23”,
23表示int4,繼續(xù)往下看,有說明。

17–具有默認(rèn)值的參數(shù)個(gè)數(shù)
17–返回值的數(shù)據(jù)類型

“25 20 20”–函數(shù)參數(shù)的數(shù)據(jù)類型的數(shù)組,這只包括輸入?yún)?shù)(含INOUT和VARIADIC參數(shù)),因此也表現(xiàn)了函數(shù)的調(diào)用特征 重載函數(shù)也憑這區(qū)別,如果有多個(gè),參數(shù)肯定不同,這個(gè)不同即可以是數(shù)量不同,也可以是類型不同,25 20 20 就是代表類型,如下:

TEST=# select oid,typname from pg_type where oid in (1082,23,1114,1184,17,25);
 OID  |   TYPNAME   
------+-------------
   17 | BYTEA
   23 | INT4
   25 | TEXT
 1082 | DATE
 1114 | TIMESTAMP
 1184 | TIMESTAMPTZ

null–函數(shù)參數(shù)的數(shù)據(jù)類型的數(shù)組,這包括所有參數(shù)(含OUT和INOUT參數(shù))。但是,如果所有參數(shù)都是IN參數(shù),這個(gè)域?qū)榭?。注意下?biāo)是從1開始 ,然而由于歷史原因proargtypes的下標(biāo)是從0開始

null–函數(shù)參數(shù)的模式的數(shù)組。編碼為: i表示IN參數(shù) , o表示OUT參數(shù), b表示INOUT參數(shù), v表示VARIADIC參數(shù), t表示TABLE參數(shù)。 如果所有的參數(shù)都是IN參數(shù),這個(gè)域?yàn)榭铡W⒁膺@里的下標(biāo)對(duì)應(yīng)著proallargtypes而不是proargtypes中的位置

null–函數(shù)參數(shù)的名字的數(shù)組。沒有名字的參數(shù)在數(shù)組中設(shè)置為空字符串。如果沒有一個(gè)參數(shù)有名字,這個(gè)域?yàn)榭铡W⒁膺@里的下標(biāo)對(duì)應(yīng)著proallargtypes而不是proargtypes中的位置

null–默認(rèn)值的表達(dá)式樹(按照nodeToString()的表現(xiàn)方式)。這是一個(gè)pronargdefaults元素的列表,對(duì)應(yīng)于最后N個(gè)input參數(shù)(即最后N個(gè)proargtypes位置)。如果沒有一個(gè)參數(shù)具有默認(rèn)值,這個(gè)域?yàn)榭?/p>

null–數(shù)據(jù)類型OID為了應(yīng)用轉(zhuǎn)換

我們?cè)俅蝸?lái)看看,是不是都對(duì)了

postgres=# \df sys_test
                               功能列表
   Schema    |     Name      | Result data type | Argument data types 
-------------+---------------+------------------+---------------------
 SYS_CATALOG | SYS_TEST | BYTEA            | INTEGER, INTEGER

第五步 調(diào)用函數(shù)

postgres=# select SYS_TEST(1,2);

其他可用輸出參數(shù):

信息報(bào)告
  \d [NAME]      描述表, 索引, 序列, 或者視圖
  \d{t|i|s|v|S} [PATTERN] (附加 "+" 獲取更多信息)
                 列出表/索引/序列/視圖/系統(tǒng)表
  \da [PATTERN]  列出聚集函數(shù)
  \db [PATTERN]  列出表空間(附加 "+" 獲取更多信息)
  \dc [PATTERN]  列出編碼轉(zhuǎn)換
  \dC            列出定義的轉(zhuǎn)換
  \dd [PATTERN]  列出對(duì)象的注釋
  \dD [PATTERN]  列出域
  \df [PATTERN]  列出函數(shù)(附加 "+" 獲得更多信息)
 \dF [PATTERN]  列出全文搜索配置(附加 "+" 獲得更多信息)
  \dFd [PATTERN] 列出全文搜索詞典(附加 "+" 獲得更多信息)
  \dFt [PATTERN] 列出全文搜索模板
 \dFp [PATTERN] 列出全文搜索分析器(附加 "+" 獲得更多信息)
  \dm[S+] [PATTERN]      list materialized views
  \dn [PATTERN]  列出模式(附加 "+" 獲得更多信息)
  \do [NAME]     列出操作符
  \dp [PATTERN]  列出表, 視圖, 及序列的訪問權(quán)限
  \dP [PATTERN]  列出包(附加 "+" 獲得更多信息)
 \dr [PATTERN]  列出角色
  \dT [PATTERN]  列出數(shù)據(jù)類型(附加 "+" 獲得更多信息)
  \du [PATTERN]  列出用戶

  \l             列出所有數(shù)據(jù)庫(kù)(附加 "+" 獲得更多信息)
  \ll [PATTERN]  列出鎖
  \llc           列出鎖總數(shù)
  \lx            列出xid最大值
  \lredolog      列出當(dāng)前的重做日志

  \lc [PATTERN]          列出所有連接
  \lac [PATTERN]         列出活動(dòng)連接
  \lfc [PATTERN]         列出空閑連接
  \lwc [PATTERN]         列出等待連接
  \lmc                   列出最大連接數(shù)

  \lstatdb [PATTERN]     列出數(shù)據(jù)庫(kù)統(tǒng)計(jì)信息
  \lstatidx [PATTERN]    列出索引統(tǒng)計(jì)信息
  \lstatseq [PATTERN]    列出序列統(tǒng)計(jì)信息
  \lstattable [PATTERN]  列出表格統(tǒng)計(jì)信息

發(fā)現(xiàn)更多寶藏

我在喜馬拉雅上分享聲音

《PostgreSQL數(shù)據(jù)庫(kù)內(nèi)核分析》,點(diǎn)開鏈接可以聽聽,有點(diǎn)意思。

《數(shù)據(jù)庫(kù)系統(tǒng)概論(第4版)》,點(diǎn)開鏈接可以聽聽,有點(diǎn)意思。

更多IT有聲課程,點(diǎn)我發(fā)現(xiàn)更多

第 0 課 PostgreSQL 系列文章列表

其他相關(guān)文章分享列表:

第 23 課 PostgreSQL 創(chuàng)建自己的數(shù)據(jù)庫(kù)、模式、用戶
第 22 課 PostgreSQL 控制文件
第 21 課 PostgreSQL 日志系統(tǒng)
第 16 課 查詢過程源碼分析
第 15 課 PostgreSQL 系統(tǒng)參數(shù)配置
第 14 課 PostgreSQL 數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)
第 13 課 PostgreSQL 存儲(chǔ)之Page(頁(yè)面)源碼分析
第 12 課 PostgreSQL 認(rèn)證方式
第 11 課 PostgreSQL 增加一個(gè)內(nèi)核C函數(shù)
第 10 課 PostgreSQL 在內(nèi)核增加一個(gè)配置參數(shù)
第 09 課 PostgreSQL 4種進(jìn)程啟動(dòng)方式
第 08 課 PostgreSQL 事務(wù)介紹
第 07 課 PostgreSQL 數(shù)據(jù)庫(kù)、模式、表、空間、用戶間的關(guān)系
第 06 課 PostgreSQL 系統(tǒng)表介紹
第 05 課 PostgreSQL 編譯源代碼進(jìn)行開發(fā)
第 04 課 PostgreSQL 安裝最新的版本
第 03 課 PostgreSQL 代碼結(jié)構(gòu)
第 02 課 PostgreSQL 的特性、應(yīng)用、安裝
第 01 課 PostgreSQL 簡(jiǎn)介及發(fā)展歷程

上面文章都在專輯中:PostgreSQL專輯鏈接,點(diǎn)我查看

如果有用,可以收藏這篇文件,隨時(shí)在更新....

更多交流加群: PostgreSQL內(nèi)核開發(fā)群 876673220

親,記得點(diǎn)贊、留言、打賞額?。?!

上一課
下一課

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容