2.3. Các hàm mở rộng trong ngôn ngữ C
2.3.3. Chuẩn gọi hàm theo phiên bản cho các hà mC
Trong phương pháp gọi hàm này, các ựối số và kết quả của hàm C chỉ ựược khai báo theo cấu trúc C thông thường, nhưng cũng cần thận trọng khi sử dụng thể hiện C của các kiểu dữ liệu SQL dưới ựây.
Sau ựây là một số vắ dụ:
#include "postgres.h" #include <string.h> /* by value */
int add_one(int arg) {
return arg + 1; }
/* by reference, fixed length */ float8 * add_one_float8(float8 *arg) {
float8 *result = (float8 *) palloc(sizeof(float8)); *result = *arg + 1.0;
return result; }
Point * makepoint(Point *pointx, Point *pointy) {
Point *new_point = (Point *) palloc(sizeof(Point)); new_point->x = pointx->x;
new_point->y = pointy->y; return new_point;
}
/* by reference, variable length */ text * copytext(text *t)
{
// VARSIZE is the total size of the struct in bytes. text *new_t = (text *) palloc(VARSIZE(t)); VARATT_SIZEP(new_t) = VARSIZE(t);
// VARDATA is a pointer to the data region of the struct.
memcpy((void *) VARDATA(new_t), /* destination */ (void *) VARDATA(t), /* source */
VARSIZE(t)-VARHDRSZ); /* how many bytes */ return new_t;
}
text * concat_text(text *arg1, text *arg2) {
int32 new_text_size = VARSIZE(arg1) + VARSIZE(arg2) - VARHDRSZ;
text *new_text = (text *) palloc(new_text_size); VARATT_SIZEP(new_text) = new_text_size;
memcpy(VARDATA(new_text), VARDATA(arg1), VARSIZE(arg1) - VARHDRSZ);
memcpy(VARDATA(new_text) + (VARSIZE(arg1)-VARHDRSZ), VARDATA(arg2), VARSIZE(arg2)-VARHDRSZ);
return new_text; }
Giả sự ựoạn mã trên ựược ựặt trong file funcs.c và biên dịch thành một shared object, chúng ta có thể ựịnh nghĩa các hàm với PostgreSQL như sau:
CREATE FUNCTION add_one(integer) RETURNS integer AS ỖDIRECTORY/funcsỖ, Ỗadd_oneỖ
LANGUAGE C STRICT;
-- note overloading of SQL function name "add_one"
CREATE FUNCTION add_one(double precision) RETURNS double precision
AS ỖDIRECTORY/funcsỖ, Ỗadd_one_float8Ỗ LANGUAGE C STRICT;
CREATE FUNCTION makepoint(point, point) RETURNS point AS ỖDIRECTORY/funcsỖ, ỖmakepointỖ
LANGUAGE C STRICT;
CREATE FUNCTION copytext(text) RETURNS text AS ỖDIRECTORY/funcsỖ, ỖcopytextỖ
LANGUAGE C STRICT;
CREATE FUNCTION concat_text(text, text) RETURNS text AS ỖDIRECTORY/funcsỖ, Ỗconcat_textỖ,
LANGUAGE C STRICT;
Trong vắ dụ này, DIRECTORY là thư mục chứa các shared object. Tuy nhiên, sẽ tốt hơn nếu người ta chỉ giữ lại ỘfuncsỢ sau As và bỏ qua ựường dẫn thư mục sau khi thêm DIRECTORY vào ựường dẫn tìm kiếm. Cũng sẽ tốt hơn nếu chúng ta bỏ qua phần mở rộng của một shared object (.so hoặc .sl) sau tên hàm.
Với các câu lệnh tạo hàm ở trên, chúng ta chỉ rõ hàm là ỘstrictỢ ựể ngụ ý rằng hệ thống sẽ tự ựộng trả về kết quả null nếu bất kỳ giá trị truyền vào là null. Bằng cách khai báo này, chúng ta tránh ựược việc phải kiểm tra các giá trị vào bên trong ựoạn mã hàm.
Mặc dù lời gọi hàm như vậy tương ựối ựơn giản khi sử dụng, nó không có tắnh khả chuyển bởi vì trong một số kiến trúc sẽ xuất hiện lỗi khi người ta ựưa vào các kiểu dữ liệu bé hơn int. Bên cạnh ựó, sẽ không ựơn giản khi người ta muốn trả về kết quả là null khi lập trình hay kiểm tra khi giá trị của tham số có phải là null không khi hàm không ựược mô tả là ỘstrictỢ. Chuẩn gọi hàm theo phiên bản 1 ựược ựưa ra sau ựây sẽ khắc phục ựược nhược ựiểm này.