Ớ Truyền bởi giá trị, ựộ dài cố ựịnh (pass by value, fixed-length)
Ớ Truyền bởi tham chiếu, ựộ dài cố ựịnh (pass by reference, fixed-length) Ớ Truyền bởi tham chiếu, ựộ dài thay ựổi (pass by reference, variable-
length)
Kiểu by-value chỉ có ựộ dài là 1, 2 hoặc 4 byte (hoặc có thể là 8 nếu
sizeof(Datum) là 8). Cần chú ý ựến kiểu long vì nó có ựộ lớn 4 bytes trong một số máy và 8 bytes trong máy khác, trong khi ựó, kiểu int là 4 bytes trong hầu hết các máy cài ựặt hệ ựiều hành Unix. Một khai báo chấp nhận ựược với kiểu int4 trong một máy Unix có thể ựược thực hiện như sau:
/* 4-byte integer, passed by value */ typedef int int4;
Kiểu có ựộ dài cố ựịnh (fixed-length) cũng có thể ựược truyền bởi tham chiếu như ựịnh nghĩa kiểu Point trong PostgreSQL như sau:
/* 16-byte structure, passed by reference */ typedef struct
{
double x, y; } Point;
Chỉ có các con trỏ tới kiểu dữ liệu này ựược sử dụng khi truyền tham số cho hàm trong PostgreSQL. để trả về một giá trị với kiểu dữ liệu này, người ta phải cấp phát một vùng nhớ phù hợp bằng câu lệnh palloc, ghi vào vùng nhớ ựược chỉ ựịnh và gửi trả về một con trỏ tới vùng nhớ ựó.
Các kiểu có ựộ dài thay ựổi (variable-length) phải ựược truyền bởi tham chiếu và phải ựược bắt ựầu bởi một trường ựộ dài 4 bytes. Dữ liệu ựược lưu trong kiểu này phải ựược phân vùng trong bộ nhớ ngay sau trường ựộ dài. Trường ựộ dài
mang giá trị là ựộ lớn của cấu trúc dữ liệu, bao gồm cả ựộ lớn của ban thân nó (4 bytes).
Chúng ta có thể ựịnh nghĩa kiểu text như sau:
typedef struct { int4 length; char data[1]; } text;
Trong vắ dụ này, trường data ựược khai báo không ựủ lớn nếu muốn chứa các chuỗi có ựộ dài lớn hơn. Trong thực tế, chúng ta không thể khai báo một cấu trúc có kắch thước thay ựổi trong C nên người ta dựa vào việc trình biên dịch C không kiểm tra các chỉ số mảng tại thời ựiểm khai báo ựể cấp phát dung lượng bộ nhớ phù hợp khi cần sử dụng và truy cập ựến mảng như thể nó ựã ựược khai báo ựúng.
Khi sử dụng các kiểu dữ liệu có ựộ dài thay ựổi, chúng ta phải cân nhắc ựể cấp phát dung lượng bộ nhớ phù hợp và thiết lập giá trị chắnh xác cho trường ựộ dài. Vắ dụ, nếu muốn lưu trữ 40 bytes trong cấu trúc text, người ta sử dụng ựoạn mã như sau:
#include "postgres.h" ...
char buffer[40]; /* our source data */ ...
text *destination = (text *) palloc(VARHDRSZ + 40); destination->length = VARHDRSZ + 40;
memcpy(destination->data, buffer, 40); ...
VARHDRSZ cũng giống nhưsizeof(int4), tuy nhiên, ựây ựược xem là phương pháp tốt nhất khi sử dụng marco này ựịnh vị chắnh xác các kiểu dữ liệu có ựộ dài thay ựổi.
Bảng 2.1 miêu tả các kiểu dữ liệu trong C và kiểu dữ liệu trong SQL tương ứng khi viết các hàm C sử dụng kiểu dữ liệu có sẵn trong PostgreSQL. Cột Ộđược ựịnh nghĩa tạiỢ ựưa ra tên file tiêu ựề (header file) cần thiết ựể sử dụng kiểu ựược ựịnh nghĩa. Cần lưu ý rằng, chúng ta luôn luôn phải ựặt thư viện postgres.h trước tiên trong mọi file chương trình bởi vì nó mô tả rất nhiều cấu trúc cần thiết.
Kiểu dữ liệu SQL Kiểu dữ liệu C được ựịnh nghĩa tại
Abstime AbsoluteTime utils/nabstime.h
Boolean bool postgres.h (maybe compiler built-in)
box BOX* utils/geo_decls.h
bytea bytea* postgres.h
"char" char (compiler built-in) character BpChar* postgres.h
cid CommandId postgres.h
date DateADT utils/date.h
smallint (int2) int2 or int16 postgres.h int2vector int2vector* postgres.h integer (int4) int4 or int32 postgres.h real (float4) float4* postgres.h
double precision (float8)
float8* postgres.h
interval Interval* utils/timestamp.h
lseg LSEG* utils/geo_decls.h
name Name postgres.h
oid Oid postgres.h
oidvector oidvector* postgres.h
path PATH* utils/geo_decls.h
point POINT* utils/geo_decls.h
regproc regproc postgres.h
reltime RelativeTime utils/nabstime.h
text text* postgres.h
tid ItemPointer storage/itemptr.h
time TimeADT utils/date.h
time with time zone TimeTzADT utils/date.h timestamp Timestamp* utils/timestamp.h tinterval TimeInterval utils/nabstime.h varchar VarChar* postgres.h xid TransactionId postgres.h
Bảng 2. 1Các kiểu dữ liệu trong C và các kiểu ựược ựịnh nghĩa tương ứng trong SQL