使用 Go 編寫 PostgreSQL 觸發器 【已翻譯100%】

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

怎樣應用 PostgreSQL 函數和 Golang 中的觸發器?

PostgreSQL 中的觸發器是一種簡單卻功能強大的機制,它能反應表(table)中所正在發生的變化。

下文描述了怎樣在 Go 中編寫 PostgreSQL 觸發器。

POSTGRESQL函數和觸發器

通過使用 CREATE FUNCTION SQL 陳述式,PostgreSQL 可以讓你建立使用者自訂函數。 函數本質上就是 PostgreSQL 怎樣管理邏輯的使用者自訂部分。

可以用多種語言編寫函數 – 最常見的很可能就是 PL/pgSQL, 它即為編寫“stored procedures”時所使用的函數。你也可以用其它語言編寫,如 Python 和 Perl。

你也可以用 C 代碼來編寫它們。因此必須將 C 代碼編譯進一個可動態載入的共用庫 (*.so)中。 PostgreSQL 則會被告知,在某個 *.so檔中,某個函數會以某個符號名稱存在。 這種方式有點類似於Apache 或 Nginx 中模組的工作方式。

函數可以用作觸發器,而這點正是我們感興趣的部分。

JaneTrans 翻譯於 2個月前 0人頂 頂  翻譯得不錯哦!

觸發器

觸發器是事件處理常式的一種形式——它們是當指定對象發生特定事件時可以執行的邏輯塊。 通常,它們涉及的對象是表,但它們也可以是視圖或外部表格。

這些事件通常是:

  • insert (rows)

  • update (rows)

  • delete (rows)

  • truncate (table)

PostgreSQL 觸發器用處廣泛:

  • 他們可以每行調用一次或每個語句調用一次。例如,如果一條語句更新5行,則可以執行這條語句時調用一次,或者每5行調用,或者每行調用。

  • 可以在實際變化發生之前或之後調用它們。

  • “before”觸發器可以更改修改的值或取消更改.

  • 觸發器可用於對錶施加任意約束。

最受歡迎的觸發器的使用可能是建立審計日誌(或更具體地說是修改日誌)。 您可以在這裡和這裡閱讀更多有關觸發器的資訊。

總長 翻譯於 1個月前 0人頂 頂  翻譯得不錯哦!

使用 Go 語言動態載入模組

Go 語言從 1.5 版本開始支援建立 C 語言風格的共用庫。這樣一來,就可以將任意的 Go 函數匯出給其他語言使用,就類似其他語言,例如 C 用的 dlopen/dlysm、Python 的 ctypes,還有 Java 的 JNI 一樣。

可以用下面的指令來建立一個 C 風格的共用庫:

go build -o myso.so -buildmode=c-shared myso.go

這裡的 myso.go 是一個用 Go 寫的主包,代碼如下:

package mainimport "C"//export MyNamefunc MyName(x int) int {return 42 + x}func main() {// 未實現}

注意看匯出函數 MyName 上面有一條修飾性注釋。另外,如果要匯出,代碼裡還得寫 import "C"。

AzureSora 翻譯於 1個月前 0人頂 頂  翻譯得不錯哦!

使用 Go 語言編寫 PostgreSQL 函數

可以建立一個包含到處方法的 *.so 檔案,然後在裡面寫要匯出的 PostgreSQL 函數。

在寫這類函數時,必須遵守一定的規則,詳情請點擊這裡。

那麼現在,我們先來定義我們的模組,然後寫一個叫做 mytrigger 的匯出函數。

// file module.gopackage main/*#include "postgres.h"#include "fmgr.h"#cgo LDFLAGS: -Wl,--unresolved-symbols=ignore-all#ifdef PG_MODULE_MAGICPG_MODULE_MAGIC;#endifPG_FUNCTION_INFO_V1(mytrigger);*/import "C"func main() {}

注意代碼裡的 LDFLAGS 聲明。用了之後,連結器在產生 so 檔案時,就不會提示遇到了無法解析的符號。因為,我們現在用的是 PostgreSQL,並沒有需要連結的外部庫;而那些符號,也只在 PostgreSQL 載入 so 檔案時才來檢查是否存在。

AzureSora 翻譯於 1個月前 0人頂 頂  翻譯得不錯哦!

接著我們在檔案 mytrigger.go 中細化觸發器函數:

// file mytrigger.gopackage main/*#include "postgres.h"#include "commands/trigger.h"//...*/import "C"import ("fmt""unsafe")//export mytriggerfunc mytrigger(fcInfo *C.FunctionCallInfoData) C.Datum {trigdata := (*C.TriggerData)(unsafe.Pointer(fcInfo.context))//...}

匯出的 Go 函數名 mytrigger 由 PostgreSQL 函數管理機制保證唯一。在觸發器中,行資料被傳入,它可能修改行資料(例如在“before”觸發器中),然後將修改後的資料透傳下去。

這裡我們寫一個簡單的函數體,在執行 INSERT 和 UPDATE 操作時觸發,該函數將不修改資料,唯讀取和列印它,假設行資料的第一列是“text”類型的。

現在正好看一下觸發器函數的代碼在 C 中是怎樣的,請看 PostgreSQL 文檔網址中的這個執行個體。

函數體中,我們先取行資料,因為函數被 INSERT 和 UPDATE 調用:

var rettuple *C.HeapTupleDataif C.trigger_fired_by_update(trigdata.tg_event) != 0 {rettuple = (*C.HeapTupleData)(trigdata.tg_newtuple)} else {rettuple = (*C.HeapTupleData)(trigdata.tg_trigtuple)}

然後我們取第一列資料(順序從1開始),假設資料是 “text” 類型的(沒有 NULL 列):

url := C.GoString(C.getarg_text(trigdata, rettuple, 1))

我們只將它列印出來,並不進行修改處理:

C.elog_info(C.CString(fmt.Sprintf("got url=%s", url)))fmt.Println(url)

最後返回原始的未修改過的資料:

return C.pointer_get_datum(rettuple)

完整的代碼可以看這裡。下面部分是 github 庫的連結和如何產生目標程式的過程指導。

s張利民z 翻譯於 1個月前 0人頂 頂  翻譯得不錯哦!

運行觸發器

在觸發器運行之前,先建立表:

$ sudo -u postgres psql -d testpsql (9.6.2)Type "help" for help.test=# CREATE TABLE urls ( url TEXT );CREATE TABLEtest=#

之後,是建立我們的函數(你需要有 C 語言的 USAGE 許可權,像這樣):

test=# CREATE FUNCTION mytrigger()test-# RETURNS TRIGGER AS '/home/alice/ptgo/ptgo.so'test-# LANGUAGE C;CREATE FUNCTIONtest=#

下一步,讓我們建立一個在表路徑上的 INSERT 和 UPDATE 觸發器,並讓它來調用我們的函數:

test=# CREATE TRIGGER trig_1test-# AFTER INSERT OR UPDATEtest-# ON urlstest-# FOR EACH ROWtest-# EXECUTE PROCEDURE mytrigger();CREATE TRIGGERtest=#

現在,讓我們插入兩行。“got url=” 通過我們的函數被列印出來:

test=# INSERT INTO urls VALUES ('http://example.com/');INFO:  got url=http://example.com/INSERT 0 1test=#test=# INSERT INTO urls VALUES ('http://mydomain.com/');INFO:  got url=http://mydomain.com/INSERT 0 1test=#

當行被更新的時候,函數接收更新後的值,因為它是一個 AFTER 觸發器:

test=# UPDATE urls SET url='http://www.test.com/';INFO:  got url=http://www.test.com/INFO:  got url=http://www.test.com/UPDATE 2test=#

就是這樣!我們有了我們自己的用 Go 編寫的 PostgreSQL 觸發器!

無若 翻譯於 1個月前 0人頂 頂  翻譯得不錯哦!

代碼

所有代碼可以在GitHub上訪問,連結如下:github.com/rapidloop/ptgo。你可隨意 fork 並修改以實現你自己的觸發器。它僅在 Linux 上測試過。請按照下面步驟擷取源碼:

git clone https://github.com/rapidloop/ptgocd ptgomake

你可能需要首先安裝 Postgres 開發包。對於基於 Debian 的系統,可以使用下面命令:

sudo apt-get install postgresql-server-dev-9.6
Tocy 翻譯於 2個月前 0人頂 頂  翻譯得不錯哦!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.