PostgreSQL7.0手冊-程序員手冊 -39. 擴展的 SQL: 類型
2019-09-08 23:33:47
供稿:網友
第三十九章. 擴展的 SQL: 類型
正如前面所說,在 Postgres 里有兩種數據類型:基本類型(在編程語言里定義)和復合類型(記錄).本章的關于索引的接口的例子可以在 complex.sql 和 complex.c 里找到.復合例子在 funcs.sql 里.
用戶定義類型
用戶定義類型所需要的函數
一個用戶定義的類型總是有輸入和輸出函數.這些函數決定該類型如何在字串里出現(讓用戶輸入和輸出給用戶)和類型如何在存儲器里組織.輸入函數以一個以空(null)為分隔符的字符串為輸入并且返回該類型的內部(在存儲器里)的表現形式.輸出類型以該類型的內部表現形式為輸入并且返回一個以空(null)為分隔符的字符串.假設我們要定義一個復數類型用來表示復數.通常,我們選用下面的 C 結構來在存儲器里表現復數:
typedef struct Complex {
double x;
double y;
} Complex;
并且以 (x,y) 形式的字串做為外部的表現形式.這些函數通常比較容易寫,尤其是輸出函數.不過,我們還是要注意幾點:
當定義你的外部(字符串)表現形式時,要注意你最后必須為該表現形式寫一個完整而且健壯的分析器作為你的輸入函數!
Complex *
complex_in(char *str)
{
double x, y;
Complex *result;
if (sscanf(str, " ( %lf , %lf )", &x, &y) != 2) {
elog(WARN, "complex_in: error in parsing
return NULL;
}
result = (Complex *)palloc(sizeof(Complex));
result->x = x;
result->y = y;
return (result);
}
輸出函數可以簡單的就是:
char *
complex_out(Complex *complex)
{
char *result;
if (complex == NULL)
return(NULL);
result = (char *) palloc(60);
sprintf(result, "(%g,%g)", complex->x, complex->y);
return(result);
}
你應該把你的輸入和輸出函數做的互為逆(函數).如果你不這樣做,你就可能在需要把數據輸出來在裝載回去時碰到很嚴重的問題(比如,輸入到別人在另外的計算機上的數據庫中去).當涉及到浮點數時,這是非常普遍的問題.
要定義 complex 類型,我們要在創建該類型前先創建兩個用戶定義函數 complex_in 和 complex_out:
CREATE FUNCTION complex_in(opaque)
RETURNS complex
AS 'PGROOT/tutorial/obj/complex.so'
LANGUAGE 'c';
CREATE FUNCTION complex_out(opaque)
RETURNS opaque
AS 'PGROOT/tutorial/obj/complex.so'
LANGUAGE 'c';
CREATE TYPE complex (
internallength = 16,
input = complex_in,
output = complex_out
);
正如我們前面討論的,Postgres 完全支持基本類型的數組.另外,Postgres 同樣還支持用戶定義類型的數組.當你定義類型時,Postgres 自動提供對該類型的數組的支持.因為歷史原因,數組類型的類型名是與類型同名字串前面加個下劃線 _ .不需要為復合類型定義任何函數,因為系統已經知道它們在里面看起來象什么.
大對象
到此為止我們討論的類型都是"小"對象 --也就是說,它們都小于 8KB.
注意:1024 longwords(長字) == 8192 字節.實際上,類型應該是遠比 8192 字節小,因為Postgres 記錄和頁面等附加部分內容也必須放在這個 8KB 限制里面.這部分附加數據量的實際大小取決于機器體系結構.
如果你需要一個更大的類型用于象文檔檢索或存儲位圖等,你將需要使用 Postgres 大對象接口或者需要重新編譯 Postgres 后端以使內部的存儲塊大于 8k 字節.
--------------------------------------------------------------------------------