第一步 實(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ù)自己的需要,選擇目錄和文件:

我需要實(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)更多
其他相關(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)贊、留言、打賞額?。?!