| PostgreSQL 8.0.0 �����ĵ���PostgreSQL �й� ������ | ||||
|---|---|---|---|---|
| Prev | Fast Backward | Chapter 31. ��չ SQL | Fast Forward | Next | 
�û�����ĺ��������� C д����������Щ������ C ���ݵ����ԣ����� C++���� �����ĺ����DZ�����ɶ�̬װ�صĶ���ģ�Ҳ��������⣩�������ɷ�����������Ҫװ�صġ� ��̬װ�ص������� "C ����" ������"�ڲ�"����֮�������ĵط� — ʵ�ʵı���ϰ��������֮��ʵ������һ���ġ� ����ˣ������ڲ�������Ϊд�û����� C �����ṩ�˴�����õ���������
Ŀǰ�� C ���������ֵ��ô�ͳ���µ�"�汾 1"�ĵ��ô�ͳ��ͨ��Ϊ�ú�����дһ�� PG_FUNCTION_INFO_V1() ������ʶ�ģ���������ʾ��������ȱ��������ʶһ���Ϸ��ģ�"�汾 0"�������� ���ַ������CREATE FUNCTION�������Ķ��� C�� �����Ϸ��ĺ����Ѿ������ˣ���Ҫ����Ϊ��ֲ��ԭ���ȱ�����ܣ� �������ڼ�����ԭ��ϵͳ��Ȼ֧������
��ij���ض��Ŀ�װ�ض����ļ�����û�����ĺ�����һ�α��������Ự����ʱ�� ��̬װ�����Ѻ�����Ŀ����װ�����ڴ档 ��ˣ������û������ C ������ CREATE FUNCTION����Ϊ����������������Ϣ�� ��װ�ض����ļ����֣��������������Ǹ�Ŀ���ļ�����õĺ����� C ���֣����ӷ��ţ��� ���û����ȷ����C���֣���ô�ͼ�������SQL��������ͬ��
������ CREATE FUNCTION �����и���������, ������㷨���ڶ�λ��������ļ���
���������һ������·��������װ�ظ������ļ���
����������ִ� $libdir ��ͷ�� ��ô�ò��ֽ���PostgreSQL��Ŀ¼�����棬 ��Ŀ¼����������ʱ���ж��ġ�
������ֲ�����Ŀ¼���֣���ô�����ñ��� dynamic_library_path ��������·������ҡ�
����û����·�����ҵ����ļ�������������һ���Ǿ���Ŀ¼���֣��� ��ô��̬װ�����ͻ���ͼ�����������װ�أ������������Կ϶���Ҫʧ�ܵġ���������ǰ����Ŀ¼�Dz��ɿ��ġ���
������˳���ã���ô��������������ָ�����ƽ̨��صĹ�����ļ�����չ��ͨ���� .so���� Ȼ�������°�������Ĺ�����һ�㡣�������ʧ�ܣ���ôװ��ʧ�ܡ�
ע��: PostgreSQL ����������ʱ���û� ID ������Ա���·����������װ�ص��ļ���һ�������Ĵ�����ǰѸ��ļ�����һ���߲�Ŀ¼��Ȩ������Ϊ postgres �û����ɶ���/����ִ�С�
���κ�����£��� CREATE FUNCTION ������������ļ�������ϵͳ���ﰴ���ı���¼�ģ���ˣ� �����Ҫ�ٴ�װ�أ���ô���ٴ�����������̡�
ע��: PostgreSQL �����Զ�����һ�������� ��ʹ�� CREATE FUNCTION ����֮ǰ������������ ���� Section 31.9.6 ��ȡ������Ϣ��
ע��: �ڵ�һ��ʹ��֮�����ڴ��ж�̬װ����һ��Ŀ���ļ��� ��ͬһ�λỰ�еĺ�̵ĺ������ý�ֻ�������С�ķ��ű��ѯ�Ĺ��ȡ� �������Ҫǿ�ƶ����ļ������أ����������±����˸��ļ�����ô����ʹ�� LOAD ������߿�ʼһ���µĻỰ��
���ǽ���ʹ���� $libdir ��Ե�Ŀ¼����ͨ����̬��·����λ����⡣����������°汾��װ��һ����ͬ�� λ�ã���ô�Ϳ��Լ汾������$libdir ��ʾ��ʵ��Ŀ¼λ�ÿ��������� pg_config --pkglibdir �ҵ���
�� PostgreSQL �汾 7.2 ֮ǰ�� ����ֻ���� CREATE FUNCTION ������Ŀ���ļ���ȷ�ľ���·���� Ŀǰ��������Ѿ���ʱ�ˣ���Ϊ������������������IJ�����ֲ�� �����ֻ�������������֣�����·����Ҳû����չ����Ȼ�������������ṩ��Щ��Ϣ��
Ҫ֪�����д C ���Եĺ���������Ҫ֪�� PostgreSQL ���ڲ�����α��ֻ����������͵ģ��Լ���������δ��뺯���Լ����������ġ� PostgreSQL �ڲ��ѻ������͵���"һƬ�ڴ�"������ ������ij�������ϵ��û����庯��ʵ���϶����� PostgreSQL �ԣ����������ͣ����ܵIJ����� Ҳ����˵��PostgreSQL ֻ�ǴӴ��̶�ȡ�ʹ洢���������ͣ� ��ʹ���㶨��ĺ��������룬�����������ݡ��������Ϳ��������������ڲ���̬����ʽ��֮һ��
������ֵ������
�����������
�������ã��䳤
������ֵ�����͵ij���ֻ����1��2 �� 4 �ֽڡ� ������ 8 �ֽڣ���� sizeof(Datum) ����Ļ������� 8 �Ļ������� ��Ҫ��ϸ����������ͣ�ȷ���������κ���ϵƽ̨�϶�����ͬ�ߴ磨�ֽڣ��� ���磬long ����һ��Σ�յ�������Ϊ��һЩ���������� 4 �ֽڶ�������һЩ�������� 8 �ֽڣ� �� int���ڴ���� Unix �����϶���4�ֽڵġ� ��һ�� Unix �����ϵ� integer �����ʵ�ֿ����ǣ�
/* 4-�ֽ���������ֵ */ typedef int integer;
���⣬�κγߴ�Ķ������Ͷ������Ǵ��������͡����磬������һ�� PostgreSQL ���͵�ʵ�֣�
/* 16-�ֽڽṹ���������� */
typedef struct
{
    double  x, y;
} Point;
ֻ��ʹ��ָ����Щ���͵�ָ������ PostgreSQL �����ﴫ��ʹ������ݡ� Ҫ�������������͵�ֵ���� palloc() ������ȷ�����Ĵ洢���������Щ�洢����Ȼ��һ��ָ������ָ�롣 �����⣬�����ͨ������ָ��ķ�������һ������������ͬ���͵�ֵ�� ���ǣ����Բ�Ҫ �Ĵ������õ�������ֵ����
������б䳤����ͬ��Ҳֻ��ͨ���������õķ��������ݡ� ���б䳤���ͱ�����һ������ 4 �ֽڳ��ij�����ʼ�� �������д洢�ڸ����͵����ݱ�����ڽ����ų�����Ĵ洢�ռ�� �������ǽṹ��ȫ����Ҳ����˵��������������ij��ȡ�
���磬���ǿ��������淽������һ�� text ���ͣ�
typedef struct {
    integer length;
    char data[1];
} text;��Ȼ������������������ij��Ȳ����Դ洢�κο��ܵ��ִ�����Ϊ�� C�в����������䳤�ȵĽṹ�� ������������������֪ʶ��C ����������������±���з�Χ��顣 ����ֻ��Ҫ�����㹻�Ŀռ䣬Ȼ������鵱���Ѿ�����Ϊ���ʳ��ȵı������ʡ� ������һ�����õļ��ɣ����������� C �Ľ̿����ж�������
������䳤����ʱ�����DZ�����ϸ������ȷ�Ĵ洢����������ȷ���ó����� ���磬�����������һ�� text �ṹ��洢 40 �ֽڣ� ���ǿ��ܻ�ʹ��������Ĵ���Ƭ�Σ�
#include "postgres.h" ... char buffer[40]; /* ���ǵ�Դ���� */ ... text *destination = (text *) palloc(VARHDRSZ + 40); destination->length = VARHDRSZ + 40; memcpy(destination->data, buffer, 40); ...
VARHDRSZ �� sizeof(int4) һ���� ����������Ϊ�ú� VARHDRSZ ��ʾ���ӳߴ������ڱ䳤���͵ĸ��õķ��
��Table 31-1 �г�����дһ��ʹ���� PostgreSQL �������͵� C ��������Ҫ��֪�����ĸ� SQL ���Ͷ�Ӧ�ĸ� C ���͡� "������" �и�������Ҫ�����Ի�ȡ�����Ͷ����ͷ�ļ���ʵ�ʵĶ���������ڰ������г����ļ����������ļ��С� ���ǽ����û�ֻʹ�����ﶨ��Ľӿڡ��� ע�⣬��Ӧ���������Ȱ��� postgres.h�� ��Ϊ���������������Ҫ�Ķ�����
Table 31-1. ���ڽ������͵�Ч�� C ����
| �ڽ����� | C ���� | ������ | 
|---|---|---|
| abstime | AbsoluteTime | utils/nabstime.h | 
| boolean | bool | postgres.h �������DZ��������ã� | 
| box | BOX* | utils/geo_decls.h | 
| bytea | bytea* | postgres.h | 
| "char" | char | �����������ã� | 
| character | BpChar* | postgres.h | 
| cid | CommandId | postgres.h | 
| date | DateADT | utils/date.h | 
| smallint (int2) | int2 �� int16 | postgres.h | 
| int2vector | int2vector* | postgres.h | 
| integer (int4) | int4 �� 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 | 
��Ȼ�����Ѿ������˻����������еĿ��ܽṹ�� ���DZ������ʵ�ʵĺ�����һЩ���ӡ�
�������ṩ"�Ϸ��"�ĵ��÷�� — �����������������Ѿ����ᳫ�ˣ� �������DZȽ�����������һ�����ڰ汾-0����� C �����IJ����ͽ��ֻ������ͨ C �������������ҪС��ʹ��������ʾ��SQL�������͵� C ������ʽ��
������һЩ���ӣ�
#include "postgres.h"
#include <string.h>
/* ������ֵ */
int
add_one(int arg)
{
    return arg + 1;
}
/* ����������� */
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;
}
/* �������ã��䳤 */
text *
copytext(text *t)
{
    /*
     * VARSIZE �ǽṹ���ֽڼƵ��ܳ���
     */
    text *new_t = (text *) palloc(VARSIZE(t));
    VARATT_SIZEP(new_t) = VARSIZE(t);
    /*
     * VARDATA �ǽṹ��һ��ָ����������ָ��
     */
    memcpy((void *) VARDATA(new_t), /* Ŀ�� */
           (void *) VARDATA(t),     /* Դ */
           VARSIZE(t)-VARHDRSZ);    /* �����ֽ� */
    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;
}
��������Ĵ�������ļ� funcs.c ���ұ�����˹���Ŀ�꣬ ���ǿ��������������Ϊ PostgreSQL ������Щ������
CREATE FUNCTION add_one(integer) RETURNS integer
     AS 'DIRECTORY/funcs', 'add_one'
     LANGUAGE C STRICT;
-- ע�⣺����������Ϊ add_one() �� SQL ����
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;
����� DIRECTORY ��������ļ���Ŀ¼ ������PostgreSQL�̳�Ŀ¼�������������ʹ�õ����ӵĴ��롣�� �����õķ��Ӧ�����ڼ��� DIRECTORY ������·��֮�� �� AS �Ӿ���ֻʹ�� 'funcs'�� �������������Ƕ�����ʡ�Ժ�ϵͳ��صĹ������չ��ͨ���� .so �� .sl����
��ע�����ǰѺ�������Ϊ"strict"���ϸ���˼��˵����κ�����ֵΪ NULL�� ��ôϵͳӦ���Զ�����һ�� NULL �Ľ��������������������DZ����ں������������� NULL ���롣 ����������������Ǿ͵���ȷ����ֵ�� ����Ϊÿ���������õIJ�������ָ�롣�����ڴ�ֵ���͵IJ�������������û�а취��飡��
���������Ϸ��ĵ��÷������������ȷ��̫������ֲ����һЩϵͳ�ϣ� ���������ַ������ݱ� int С���������;ͻ��������ѡ� ���ң�����û�кܺõķ��� NULL ����İ취�� Ҳû�г��˰Ѻ����ϸ�����Ĵ��� NULL �����ķ���������Ҫ���İ汾-1�ķ�����������Щ���⡣
�汾-1 ���÷����������������������ݲ����ͽ���ĸ����ԡ��汾-1 ������� C ����������������
Datum funcname(PG_FUNCTION_ARGS)
���⣬����ĺ�
PG_FUNCTION_INFO_V1(funcname);
Ҳ���������ͬһ��Դ�ļ��ͨ���Ϳ���д�ں�������ǰ�棩�� ����Щ�ڲ�-���Ժ������ԣ�����Ҫ��������꣬ ��ΪPostgreSQLĿǰ�����ڲ��������ǰ汾-1�� ���������ڶ�̬���ӵĺ��������������ġ�
�ڰ汾-1����� ÿ��ʵ�ʲ���������һ����Ӧ�ò������������͵� PG_GETARG_xxx()��ץȡ�ģ�������÷������͵� PG_RETURN_xxx()�귵�صġ� PG_GETARG_xxx() ����Ҫץȡ�ĺ��������ı����Ϊ�����������Ǵ� 0 ��ʼ�ġ� PG_RETURN_xxx() ����ʵ��Ҫ���ص���ֵΪ����IJ�����
�����Ǻ�����һ���ĺ������������ð汾-1����ģ�
#include "postgres.h"
#include <string.h>
#include "fmgr.h"
/* ������ֵ */
PG_FUNCTION_INFO_V1(add_one);
         
Datum
add_one(PG_FUNCTION_ARGS)
{
    int32   arg = PG_GETARG_INT32(0);
    PG_RETURN_INT32(arg + 1);
}
/* ����������� */
PG_FUNCTION_INFO_V1(add_one_double precision);
Datum
add_one_float8 precision(PG_FUNCTION_ARGS)
{
    /* ���� FLOAT8 �ĺ꣬�����䴫�����õı��� */
    float8   arg = PG_GETARG_FLOAT8(0);
    PG_RETURN_FLOAT8(arg + 1.0);
}
PG_FUNCTION_INFO_V1(makepoint);
Datum
makepoint(PG_FUNCTION_ARGS)
{
    /* �������û������ Point �Ĵ������õı��� */
    Point     *pointx = PG_GETARG_POINT_P(0);
    Point     *pointy = PG_GETARG_POINT_P(1);
    Point     *new_point = (Point *) palloc(sizeof(Point));
    new_point->x = pointx->x;
    new_point->y = pointy->y;
       
    PG_RETURN_POINT_P(new_point);
}
/* �������ã��䳤 */
PG_FUNCTION_INFO_V1(copytext);
Datum
copytext(PG_FUNCTION_ARGS)
{
    text     *t = PG_GETARG_TEXT_P(0);
    /*
     * VARSIZE �ǽṹ���ֽڼƵ��ܳ���
     */
    text     *new_t = (text *) palloc(VARSIZE(t));
    VARATT_SIZEP(new_t) = VARSIZE(t);
    /*
     * VARDATA �ǽṹ��ָ����������һ��ָ��
     */
    memcpy((void *) VARDATA(new_t), /* Ŀ�� */
           (void *) VARDATA(t),     /* Դ */
           VARSIZE(t)-VARHDRSZ);    /* �����ֽ� */
    PG_RETURN_TEXT_P(new_t);
}
PG_FUNCTION_INFO_V1(concat_text);
Datum
concat_text(PG_FUNCTION_ARGS)
{
    text  *arg1 = PG_GETARG_TEXT_P(0);
    text  *arg2 = PG_GETARG_TEXT_P(1);
    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);
    PG_RETURN_TEXT_P(new_text);
}
�õ��� CREATE FUNCTION ����������Ϸ��ĵ�Ч������һ����
�͵�һ�����汾-1�ı������ֻ����Ŀ�ĵ����ˡ��������ǵ�ȷ���������Ľ�����Ϊ�������������Ҫ��ϸ�ڡ� һ��������add_one_float8�ı�����������Dz�����Ҫ��ͣ�����Լ� float8 �Ǵ����������͡� ����һ�����������ڱ䳤���͵ĺ� GETARG ������ץȡ"toasted"����¯����ѹ���Ļ��߳����ģ�ֵ��Ҫ���Ĵ���
�汾-1�ĺ�����һ����ĸĽ��Ƕ� NULL ����ͽ���Ĵ��� �� PG_ARGISNULL(n) ����һ����������ÿ�������Ƿ�Ϊ NULL ����Ȼ�������ֻ�Ƕ���Щû������Ϊ "strict" �ĺ����б�Ҫ���� ��Ϊ�����PG_GETARG_xxx() �꣬��������Ǵ��㿪ʼ����ġ���ע�����Dz�Ӧ��ִ�� PG_GETARG_xxx()�� �������������˲������� NULL�� Ҫ����һ�� NULL �����ִ��һ�� PG_RETURN_NULL()���������ϸ�ĺͲ��ϸ�ĺ�������Ч��
���·��Ľӿ����ṩ��������ѡ���� PG_GETARG_xxx() ����������֡���һ���� PG_GETARG_xxx_COPY() ��֤����һ��ָ�������ĸ������ø����ǿ���ȫ��д��ġ� ����ͨ�ĺ���ʱ��᷵��һ��ָ������洢�ڱ��е�ijֵ��ָ�룬������Dz���д���ָ�롣 �� PG_GETARG_xxx_COPY() �걣֤��ȡһ����д�Ľ������ �ڶ��������� PG_GETARG_xxx_SLICE() ����ɣ�������������������һ���Dz����ĸ���������ͬ���� �ڶ����͵�������Ҫ���ص�ƫ���������ݶεij��ȡ� ƫ���Ǵ��㿪ʼ����ģ�һ�������ij�����Ҫ�ظ�ֵ��ʣ��ȵ����ݡ� ��Щ�����ṩ�˷��ʴ�����ֵ���в��ֵĸ���Ч�ķ������ر������ݵĴ洢������"external"��ʱ�� ��һ���ֶεĴ洢���Ϳ����� ALTER TABLE tablename ALTER COLUMN colname SET STORAGE storagetypeָ����storagetype �� plain��external�� extended �� main ֮һ����
�汾-1�ĺ������÷��Ҳ�����ǿ��ܷ���һ"��"��� ��Section 31.9.10������ʵ�ִ�����������Chapter 32���������Ե��þ����Chapter 45���� �汾-1 �Ĵ���Ҳ�Ȱ汾-0�ĸ�������ֲ����Ϊ��û��Υ�� C ���Ժ�������Э������ơ������ϸ������� Դ�����е�src/backend/utils/fmgr/README��
������ת������Ļ���֮ǰ������Ҫ������һЩPostgreSQLC ���Ժ����ı������ ��Ȼ������ C �����������������д����PostgreSQL �Ĺ������� ��ͨ�����鷳����Ȼ����ȫ���ܵģ�����Ϊ������ C++��FORTRAN������ Pascal ���������Բ�����ѭ�� C һ���ĵ���ϰ�ߡ� Ҳ����˵������������C�Ĵ��ݲ����ͷ���ֵ�ķ�ʽ��һ���� ������Ǽ�����ı�����Ժ������� C д�ġ�
��д������ C �����Ļ����������£�
ʹ�� pg_config --includedir-server �ҳ�PostgreSQL��������ͷ�ļ���װ�����ϵͳ������������û������е�ϵͳ���ĺδ��� ���ѡ����PostgreSQL7.2 �����ġ����� PostgreSQL7.1�� ��Ӧ��ʹ��ѡ�� --includedir�� ���������δ֪ѡ�pg_config �����ŷ���״̬�˳����� �������� 7.1 �İ汾�����ֻ���Լ����ˣ�������Ϊ����������Ŀǰ�ĵ��÷�ʽ֮ǰ�������㲻����ܻ�ȥ֧����Щ�汾��
������洢��ʱ���� PostgreSQL �ĺ���palloc�� pfree ȡ����Ӧ�� C �⺯�� malloc��free�� ��palloc����Ĵ洢����ÿ���������ʱ���Զ��ͷţ��������ڴ�й¶��
�ǵ���memset ����Ľṹ�ֽ����㡣 �������ô�����ͺ���֧�� hash ������ hash ���ӣ���Ϊ���DZ�����Լ������ݽṹ��ѡ�����������λ������ hash�� ��ʹ���ʼ������Ľṹ����������Ȼ�п����м��������ֽڣ��ṹ�еĶ�����������ֵ��
������� PostgreSQL �ڲ����Ͷ����� postgres.h�� �������������ӿڣ�PG_FUNCTION_ARGS �ȵȡ��� ���� fmgr.h������������Ӧ�ð����������ļ��� ������ֲ��ԭ����������� postgres.h��Ȼ���ٰ�������ϵͳ�����û�ͷ�ļ��� ������ postgres.h ���Զ����� c.h�� elog.h �� palloc.h��
��Ŀ���ļ��ﶨ��ķ���һ���������ͻ��Ҳ���ܺͶ����� PostgreSQL ��������ִ�д����еķ������ֳ�ͻ�� ����㿴���������صĴ�����Ϣ����ô��������ĺ������߱�����������
�����Ŀ��������װ�سɿ��Զ�̬װ�� PostgreSQL �Ŀ��ļ�������ҪһЩ����ı�ǡ����� Section 31.9.6 ��ȡ��������ƽ̨��������µ���ϸ˵����
�����ܹ�ʹ���� C д PostgreSQL ��չ����֮ǰ�� �������һ������ķ���������������ǣ������������ɿ��Ա���������̬��װ�ص��ļ��� ȷ��˵��������Ҫ����һ���������
�����Ҫ����������������Χ����Ϣ����ô��Ӧ���Ķ���IJ���ϵͳ���ĵ��� �ر��� C ��������cc ���������� ld ���ֲ�ҳ�� ���⣬PostgreSQL Դ��������������������е����ӣ� ������ contrib Ŀ¼� �����������������Щ���ӣ���ô���Ҫ���Լ���ģ�����ú� PostgreSQL Դ�����ز��С�
�������������ӿ�ִ���ļ����ƣ����Ȱ�Դ��������Ŀ���ļ��� Ȼ���Ŀ���ļ�����������Ŀ���ļ���Ҫ������λ�����루position-independent code�� ��PIC���������Ͼ����ڿ�ִ�г���װ�����ǵ�ʱ�� ���ǿ��Է��ڿ�ִ�г�����ڴ�����κεط��� �����ڿ�ִ���ļ���Ŀ���ļ�ͨ�������������ʽ����ġ��� ���Ӷ�̬���������������־�������ӿ�ִ���ļ���������������ġ� ��������������� — ��һЩϵͳ���ʵ�����ġ���
���������������Ǽ������Դ��������� foo.c �ļ��ﲢ�ҽ����������ֽ� foo.so�Ĺ���⡣�н�Ķ����ļ������� foo.o��������������ע����һ��������������������ļ�����������������ֻ��һ����
���� PIC �ı�������־�� -fpic��������������������־�� -shared��
gcc -fpic -c foo.c ld -shared -o foo.so foo.o
���淽�������ڰ汾 4.0 �� BSD/OS��
���� PIC �ı�������־�� -fpic��������������������־�� -shared��
gcc -fpic -c foo.c gcc -shared -o foo.so foo.o
���淽�������ڰ汾 3.0 �� FreeBSD.
���� PIC ��ϵͳ��������־�� +z�����ʹ�� GCC ���� -fpic�� ������������������־�� -b�����
cc +z -c foo.c
��
gcc -fpic -c foo.c
Ȼ��
ld -b -o foo.sl foo.o
HP-UX ʹ�� .sl ���������չ����������ϵͳ��ͬ��
PIC ��ȱʡ������Ҫʹ������ı�����ѡ� ���ɹ�����������ѡ���� -shared.
cc -c foo.c ld -shared -o foo.so foo.o
���� PIC �ı�������־�� -fpic����һЩƽ̨�ϵ�һЩ�����£� ��� -fpic ��������ô����ʹ��-fPIC�� �ο� GCC ���ֲ��ȡ������Ϣ�� ���������ı�������־�� -shared��һ�����������ӿ�������
cc -fpic -c foo.c cc -shared -o foo.so foo.o
������һ�����ӡ�������迪�������Ѿ���װ���ˡ�
cc -c foo.c cc -bundle -flat_namespace -undefined suppress -o foo.so foo.o
���� PIC �ı�������־�� -fpic������ ELF ϵͳ�� �� -shared ��־�ı��������������ӹ���⡣ ���ϵķ� ELF ϵͳ�ʹ��ld -Bshareable��
gcc -fpic -c foo.c gcc -shared -o foo.so foo.o
���� PIC �ı�������־�� -fpic. ld -Bshareable �������ӹ���⡣
gcc -fpic -c foo.c ld -Bshareable -o foo.so foo.o
���� PIC �ı������������� Sun ������ʱΪ -KPIC ���� GCC ʱΪ -fpic�����ӹ����ʱ������������������ -G ������ GCC ʱ�������� -shared��
cc -KPIC -c foo.c cc -G -o foo.so foo.o
��
gcc -fpic -c foo.c gcc -G -o foo.so foo.o
PIC ��ȱʡ����˱����������ƽ�����Ǹ��� ������ѡ��� ld �������ӣ�
cc -c foo.c ld -shared -expect_unresolved '*' -o foo.so foo.o
�� GCC ����ϵͳ������ʱ�Ĺ�����һ���ģ�����Ҫ�����ѡ�
SCO ���������� PIC �ı�־��-KPIC GCC �� -fpic�� ���ӹ����ʱ SCO �������� -G �� GCC ��-shared��
cc -K PIC -c foo.c cc -G -o foo.so foo.o
or
gcc -fpic -c foo.c gcc -shared -o foo.so foo.o
����: ����������Щ����ʵ��̫���ӣ���ô��Ӧ�ÿ���ʹ�� GNU Libtool������ƽ̨�IJ�����������һ��ͳһ�Ľӿ��
���ɵĹ�����ļ�Ȼ��Ϳ���װ�ص� PostgreSQL����ȥ�ˡ��ڸ� CREATE FUNCTION ���������ļ�����ʱ�����DZ������� ������ļ������ֶ������м�Ŀ���ļ������֡���ע��������� CREATE FUNCTION �����Ϻ��� ϵͳ���Ĺ������չ (ͨ����.so��.sl)�� ���ҳ�����ѵļ����Կ���ҲӦ�ú��ԡ�
��ȥ���� Section 31.9.1 ��ȡ�йط����� Ԥ���������ҵ���������Ϣ��
������ڿ��Ƿ������PostgreSQL��չģ�飬��ô����������һ������ֲ������ϵͳ���ܻ��൱���ѡ� ���PostgreSQL��װ�ṩ��һ��������չ�������ܹ������� PGXS�� ����������չģ�������һ���Ѿ���װ�˵ķ������������ˡ� ��ע������ܹ���������ͼ����ʵ��һ��ͳһ�ġ�������������������PostgreSQL��ص�����ļܹ��� ��ֻ�������Զ�����Щ�ķ�������չģ������������ڸ����ӵİ����㻹����Ҫ��д�Լ�������ϵͳ��
Ҫ�������չ��ʹ�øüܹ��������дһ���� makefile�� �ڸ�makefile�����Ҫ����һЩ��������������ȫ�ֵ� PGXS makefile�� ������һ������һ������һ������⣬һ�� SQL �ű�����һ���ĵ��ı��ļ��Ľ��� isbn_issn �����ӣ�
MODULES = isbn_issn DATA_built = isbn_issn.sql DOCS = README.isbn_issn PGXS := $(shell pg_config --pgxs) include $(PGXS)
�������Ӧ������һ���ġ����ļ���ǰ�棬�㸳������������ӿͻ����� make ����
���������������
һ����Ҫ��ͬ������Դ�����������Ĺ��������б���Ҫ������б����������
��װ�� prefix/share/contrib ������ļ�
��Ҫ�������ģ���װ�� prefix/share/contrib ���������ļ���
��װ�� prefix/doc/contrib ���������ļ�
��װ�� prefix/bin ����Ľű��ļ����Ƕ����ƣ�
��װ�� prefix/bin ����ģ���Ҫ�������Ľű��ļ����Ƕ����ƣ���
�ع���������б�û�к���
�������������������֮һ��
һ����Ҫ�����Ķ������ļ����� OBJS �����г�Ŀ���ļ���
һ����Ҫ�����Ĺ�������� OBJS ���г�Ŀ���ļ���
�����������������
�� make clean ��ɾ���Ķ�����ļ�
�����ӵ� CPPFLAGS
�����ӵ� PROGRAM ��������
�����ӵ� MODULE_big ��������
����� makefile �� Makefile �����ַ��ڱ��������չ��Ŀ¼� Ȼ����Ϳ������� make �����룬Ȼ���� make install ��װ���ģ�顣 �����չ��Ϊ pg_config ���������·�����ҵ��ĵ�һ�� PostgreSQL ��װ����Ͱ�װ�ġ�
�������Ͳ��� C �ṹ�����й̶��IJ��֡� �������͵�ʵ�����ܰ����գ�null���� ���⣬һ�����ڼ̳в��һ���ֵĸ����� �Ϳ��ܺ�ͬһ�̳з����������Ա�в�ͬ����/�ֶΡ� ��ˣ�PostgreSQL �ṩһ�����̽ӿ����ڴ� C ������ʸ������͡�
��������Ϊ�����ѯдһ������
SELECT name, c_overpaid(emp, 1500) AS overpaid FROM emp WHERE name = 'Bill' OR name = 'Sam';
������IJ�ѯ��ð汾 0 �ĵ��ýӿڣ����ǿ�����������c_overpaid��
#include "postgres.h"
#include "executor/executor.h"  /* �� GetAttributeByName() */
bool
c_overpaid(HeapTupleHeader t, /* emp �ĵ�ǰ��*/
           int32 limit)
{
    bool isnull;
    int32 salary;
    salary = DatumGetInt32(GetAttributeByName(t, "salary", &isnull));
    if (isnull)
        return (false);
    return salary > limit;
}�ڰ汾-1���룬����Ķ�����д������������
#include "postgres.h"
#include "executor/executor.h"  /* �� GetAttributeByName() */
PG_FUNCTION_INFO_V1(c_overpaid);
Datum
c_overpaid(PG_FUNCTION_ARGS)
{
    HeapTupleHeader  t = PG_GETARG_HEAPTUPLEHEADER(0);
    int32            limit = PG_GETARG_INT32(1);
    bool isnull;
    Datum salary;
    salary = GetAttributeByName(t, "salary", &isnull);
    if (isnull)
        PG_RETURN_BOOL(false);
    /* ���⣬���ǿ��ܸ�ϣ���� PG_RETURN_NULL() ���ڿ�нˮ�� */
    PG_RETURN_BOOL(DatumGetInt32(salary) > limit);
}
GetAttributeByName �� PostgreSQL ϵͳ������ �������ص�ǰ��¼���ֶΡ�������������������Ϊ HeapTupleHeader �Ĵ��뺯���IJ���������Ҫ���ֶ����ƣ� �Լ�һ������ȷ���ֶ��Ƿ�Ϊ�գ�null���ķ��ز����� GetAttributeByName ��������һ��Datumֵ�� ������ö�Ӧ�� DatumGetXXX() �����ת���ɺ��ʵ��������͡� ��ע�⣬��������˿ձ�־����ô����ֵ��������ģ� �����Խ�����κδ���֮ǰ������Ҫ�ȼ��ձ�־��
����һ�� GetAttributeByNum�������ֶα�Ŷ������ֶ���ѡȡĿ���ֶΡ�
����������� SQL ������ c_overpaid ������
CREATE FUNCTION c_overpaid(emp, integer) RETURNS bool AS 'DIRECTORY/funcs', 'c_overpaid' LANGUAGE C STRICT;
��ע������ʹ���� STRICT���������ǾͲ���Ҫ�����������Ƿ��� NULL��
Ҫ��һ�� C ���Ժ����ﷵ��һ���л���һ���������͵���ֵ�����ǿ���ʹ��һ������� API�� ���ṩ������ͺ�����������������������������͵ĸ����ԡ� Ҫʹ�ø� API��Դ������������
#include "funcapi.h"
����һ��������������ֵ��Ҳ����һ��"Ԫ��"�������ַ����� ����Դ�һ�� Datum ֵ������������Ҳ���Դ�һ�����Դ��ݸ���Ԫ����ֶ����͵�����ת�������� C �ִ������������� ���������ַ�ʽ�������ȶ���ҪΪԪ��ṹ��ȡ��������һ�� TupleDesc �������� ��ʹ�� Datum ��ʱ����� BlessTupleDesc ������� TupleDesc Ȼ��Ϊÿ�е��� heap_formtuple�� ��ʹ�� C �ִ���ʱ����� TupleDescGetAttInMetadata ���� TupleDesc�� Ȼ��Ϊÿ�е��� BuildTupleFromCStrings�� �����һ����������һ��Ԫ�鼯�ϵij��ϣ��������ò��趼�����ڵ�һ�ε��øú�����ʱ��һ������ɡ�
�м�����㺯�������������ó�ʼ�� TupleDesc�� �������ʹ�������ĸ������ͣ�����Դ�ϵͳ�����ȡ��Ϣ����
TupleDesc RelationNameGetTupleDesc(const char *relname)
����һ�����ֻ�ȡ TupleDesc������
TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases)
һ������һ������ OID ��ȡTupleDesc�� ����������Ϊһ�����������������ͻ��߸��ϣ���ϵ�����ͻ�ȡһ�� TupleDesc�� ����дһ������ record �ĺ�����ʱ����ôԤ�ڵ� TupleDesc �����ɵ����ߴ��ݽ�����
һ��������һ�� TupleDesc���������ʹ�� Datum����ô����
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
��������� C �ִ�����ô����
AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc)
�������дһ�����ؼ��ϵĺ�������ô�������Щ�����Ľ�������� FuncCallContext �ṹ�� — �ֱ�ʹ�� tuple_desc ���� attinmeta �ֶΡ�
��ʹ�� Datum ��ʱ��ʹ��
HeapTuple heap_formtuple(TupleDesc tupdesc, Datum *values, char *nulls)
����һ�� HeapTuple������������ Datum ����ʽ�����û���
��ʹ�� C �ִ���ʱ����
HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
����һ�� HeapTuple���� C �ִ�����ʽ�����û����ݡ� "values" ��һ�� C �ִ������飬�����е�ÿ���ֶζ�Ӧ����һ���� ÿ�� C �ִ���Ӧ�����ֶ��������͵����뺯��Ԥ�ڵ���ʽ��Ϊ�˴�����һ���ֶ��з���һ����ֵ�� values �����ж�Ӧ��ָ��Ӧ������Ϊ NULL���������������ҪΪ�㷵�ص�ÿ��Ԫ�����һ�Ρ�
һ����������һ������ĺ����з��ص�Ԫ�飬��ô��Ԫ�����ת����һ�� Datum��ʹ��
HeapTupleGetDatum(HeapTuple tuple)
��һ�� HeapTuple ת��Ϊһ����Ч�� Datum�� �������ֻ����һ�У���ô��� Datum ��������ֱ�ӷ��أ� ������������������һ�����ؼ��ϵĺ�����ĵ�ǰ����ֵ��
���������������
����һ������� API �����ṩ�� C ���Ժ����з��ؼ��ϣ����У���֧�֡� һ�����ؼ��ϵĺ���������ѭ�汾��1�ĵ��÷�ʽ��ͬ����Դ���������� funcapi.h����������˵��������
һ�����ؼ��ϵĺ�����SRF��ͨ��Ϊ�����ص�ÿ�������һ�Ρ� ��� SRF ���뱣���㹻��״̬���ڼ�ס���������������Լ���ÿ�ε��õ�ʱ����һ��� ���� API �ṩ�� FuncCallContext �ṹ���ڰ�������������̡� fcinfo->flinfo->fn_extra ���ڱ���һ����Խ��ε��õ�ָ�� FuncCallContext ��ָ�롣
typedef struct
{
    /*
     * ����ǰ���Ѿ������õĴ���
     *
     * ��ʼ��ʱ��call_cntr �� SRF_FIRSTCALL_INIT() ��Ϊ�� 0������
     * ÿ������� SRF_RETURN_NEXT() ��ʱ����
     */
    uint32 call_cntr;
    /*
     * ��ѡ������������
     *
     * ����� max_calls ֻ��Ϊ�˷��㣬������Ҳ�ǿ�ѡ��
     * ���û�����ã�������ṩ��ѡ�ķ�����֪��������ʱ����
     * 
     */
    uint32 max_calls;
    /*
     * ָ������λ�Ŀ�ѡָ��
     *
     * ������������Ѿ���ʱ��ֻ�������¼��ݡ�Ҳ������Щʹ��
     * ������ TupleDescGetSlot() ���û����� SRF
     */
    TupleTableSlot *slot;
    /*
     * ��ѡ��ָ���û��ṩ���������Ϣ��ָ��
     *
     * user_fctx ����һ��ָ�����Լ��Ľṹ��ָ�룬���������ṩ����ĺ����ĵ��ü�Ļ�����Ϣ
     * 
     */
    void *user_fctx;
    /*
     * ��ѡ��ָ�����������������Ԫ��Ϣ�Ľṹ�����ָ��
     * 
     *
     * attinmeta �����ڷ���Ԫ���ʱ��Ҳ����˵���ظ����������ͣ�
     * ��ֻ���ػ�����Ҳ���DZ������������͵�ʱ����Ҫ��
     * ֻ���������� BuildTupleFromCStrings() ��������Ԫ���ʱ�����Ҫ��
     * 
     */
    AttInMetadata *attinmeta;
    /*
     * ���ڱ����ڶ�ε��ü���Ľṹ���ڴ滷��
     *
     * multi_call_memory_ctx ���� SRF_FIRSTCALL_INIT() Ϊ�����õģ�������
     * SRF_RETURN_DONE() ���������������ڴ���κ���Ҫ��Խ��ε��� SRF ֮���ظ�ʹ�õ��ڴ�
     * 
     * 
     */
    MemoryContext multi_call_memory_ctx;
    /*
     * ��ѡ��ָ�룬ָ�����Ԫ�������Ľṹ
     *
     * tuple_desc ���ڷ���Ԫ�飨Ҳ����˵�����������ͣ�
     * ����ֻ��������ʹ�� heap_formtuple() ������  BuildTupleFromCStrings() ����Ԫ���
     * ʱ����Ҫ����ע������洢�� TupleDesc ָ��ͨ��Ӧ������heap_formtuple()
     * BlessTupleDesc() ����
     */
    TupleDesc tuple_desc;
} FuncCallContext;
һ�� SRF ʹ���Զ����� FuncCallContext �ṹ�����ǿ���ͨ�� fn_extra �ҵ����������ɸ������ͺꡣ��
SRF_IS_FIRSTCALL()
���ж���ĺ����ǵ�һ�ε��û��Ǻ�̵ĵ��á���ֻ�У��ڵ�һ�ε��õ�ʱ����
SRF_FIRSTCALL_INIT()
��ʼ�� FuncCallContext����ÿ�κ�������ʱ��������һ�Σ���ʹ��
SRF_PERCALL_SETUP()
Ϊʹ�� FuncCallContext ��ǡ���������Լ������κ�ǰ��Ļغ�����ʣ�µ��ѷ��ص����ݡ�
�����ĺ���������Ҫ���أ�ʹ��
SRF_RETURN_NEXT(funcctx, result)
���ظ������ߡ���result �����Ǹ� Datum�� Ҫô�ǵ���ֵ��Ҫô����ǰ����ܵ���������Ԫ�顣����������ĺ������������ݷ��أ�ʹ��
SRF_RETURN_DONE(funcctx)
��������SRF��
�� SRF �����õ�ʱ����ڴ滷����һ����ʱ�Ļ����� �ڵ���֮�佫�ᱻ�����������ζ���㲻��Ҫ pfree ������ palloc �Ķ����������Զ���ʧ�ġ������������������κο�Խ���ô��ڵ����ݽṹ�� �������Ҫ�����Ƿ�������ʲô�ط����� multi_call_memory_ctx ���õĻ����ʺ����ڱ�����Щ��Ҫֱ�� SRF ����ǰ���������ݡ� �ڴ��������£�����ζ����������һ�ε��õ����õ�ʱ��Ӧ���л��� multi_call_memory_ctx��
һ��������α�������ӿ�����������������
Datum
my_Set_Returning_Function(PG_FUNCTION_ARGS)
{
    FuncCallContext  *funcctx;
    Datum             result;
    MemoryContext     oldcontext;
    ����������
    if (SRF_IS_FIRSTCALL())
    {
        funcctx = SRF_FIRSTCALL_INIT();
        oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
        /* ����ų���һ�ε����ô��룺*/
        �û��������
        if ���ظ���
            ���� TupleDesc���Լ����ܻ��� AttInMetadata
        endif ���ظ���
        �û��������
        MemoryContextSwitchTo(oldcontext);
    }
    /* ÿ�ζ�ִ�е����ô�����������֣�*/
    �û��������
    funcctx = SRF_PERCALL_SETUP();
    �û��������
    /* ����ֻ���������������Ƿ���ɵ�һ��������*/
    if (funcctx->call_cntr < funcctx->max_calls)
    {
        /* ���������뷵������һ����Ŀ��*/
         �û�����
         ��ȡ��� Datum
         SRF_RETURN_NEXT(funcctx, result);
     }
     else
     {
         /* ����������ɷ�����Ŀ�Ĺ����ˣ�ֻ��Ҫ�����OK�ˣ�*/
         �û�����
         SRF_RETURN_DONE(funcctx);
     }
 }
 
һ�����ظ������͵����� SRF ���ӿ�������������
 PG_FUNCTION_INFO_V1(testpassbyval);
 Datum
 testpassbyval(PG_FUNCTION_ARGS)
 {
     FuncCallContext     *funcctx;
     int                  call_cntr;
     int                  max_calls;
     TupleDesc            tupdesc;
     AttInMetadata       *attinmeta;
      /* ֻ���ڵ�һ�ε��ú�����ʱ��ɵ����� */
      if (SRF_IS_FIRSTCALL())
      {
         MemoryContext   oldcontext;
         /* ����һ�����������������ڵ��ü䱣��ס */
         funcctx = SRF_FIRSTCALL_INIT();
         /* �л����ʺ϶�κ������õ��ڴ滷�� */
         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
         /* Ҫ���ص�Ԫ������ */
         funcctx->max_calls = PG_GETARG_UINT32(0);
         /*
          * Ϊ __testpassbyval Ԫ������һ��Ԫ������
          */
         tupdesc = RelationNameGetTupleDesc("__testpassbyval");
         /*
          * �����Ժ���� C �ִ�����Ԫ�������Ԫ����
          * 
          */
         attinmeta = TupleDescGetAttInMetadata(tupdesc);
         funcctx->attinmeta = attinmeta;
         MemoryContextSwitchTo(oldcontext);
     }
     /* ÿ�κ������ö�Ҫ�������� */
     funcctx = SRF_PERCALL_SETUP();
     call_cntr = funcctx->call_cntr;
     max_calls = funcctx->max_calls;
     attinmeta = funcctx->attinmeta;
     if (call_cntr < max_calls)    /* �ڻ�����Ҫ���͵Ķ���ʱ�������� */
     {
         char       **values;
         HeapTuple    tuple;
         Datum        result;
         /*
          * ��һ����ֵ�������ڰ汾�ķ���Ԫ�顣
          * ��Ӧ����һ�� C �ִ����飬�Ժ���Ա����ʵ��������뺯������
          * 
          */
         values = (char **) palloc(3 * sizeof(char *));
         values[0] = (char *) palloc(16 * sizeof(char));
         values[1] = (char *) palloc(16 * sizeof(char));
         values[2] = (char *) palloc(16 * sizeof(char));
         snprintf(values[0], 16, "%d", 1 * PG_GETARG_INT32(1));
         snprintf(values[1], 16, "%d", 2 * PG_GETARG_INT32(1));
         snprintf(values[2], 16, "%d", 3 * PG_GETARG_INT32(1));
         /* ����һ��Ԫ�� */
         tuple = BuildTupleFromCStrings(attinmeta, values);
         /* ��Ԫ������ datum */
	 result = HeapTupleGetDatum(tuple);
         /* ������Щʵ���ϲ��DZ�Ҫ�� */
         pfree(values[0]);
         pfree(values[1]);
         pfree(values[2]);
         pfree(values);
          SRF_RETURN_NEXT(funcctx, result);
     }
     else    /* ��û�����ݲ�����ʱ��ɵ����� */
     {
          SRF_RETURN_DONE(funcctx);
     }
 }
 ����������֧�ֵ� SQL ����
CREATE TYPE __testpassbyval AS (f1 integer, f2 integer, f3 integer); CREATE OR REPLACE FUNCTION testpassbyval(integer, integer) RETURNS setof __testpassbyval AS 'filename','testpassbyval' LANGUAGE 'c' IMMUTABLE STRICT;
����Դ�뷢������� contrib/tablefunc ��ȡ�����йط��ؼ��ϵĺ��������ӡ�
C ���Ժ�����������Ϊ���ܺͷ��ض�̬������ anyelement �� anyarray�� ���� Section 31.2.5 ��ȡ�йض�̬�����ĸ���ϸ�Ľ��͡� ��������������߷������Ͷ���Ϊ��̬���ͣ���ô���������߾���Ԥ��֪�������յ��IJ����� �Լ���Ҫ���ص����ݡ��� fmgr.h �����������̣������ð汾��1�� C ����֪�����IJ�����ȷ�����������Լ�����Ҫ���ص��������͡� ���������̽� get_fn_expr_rettype(FmgrInfo *flinfo) �� get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)�� ���Ƿ��ؽ�����߲��������� OID�������Щ��Ϣ���ɻ�ȡ���� InvalidOid�� �ṹ flinfo ͨ������ fcinfo->flinfo ���з��ʵġ����� argnum ���� 0 Ϊ���ġ�
���磬����������дһ�����������������͵�һ��Ԫ�أ����ҷ��ظ����͵�һ��һά���飺
PG_FUNCTION_INFO_V1(make_array);
Datum
make_array(PG_FUNCTION_ARGS)
{
    ArrayType  *result;
    Oid         element_type = get_fn_expr_argtype(fcinfo->flinfo, 0);
    Datum       element;
    int16       typlen;
    bool        typbyval;
    char        typalign;
    int         ndims;
    int         dims[MAXDIM];
    int         lbs[MAXDIM];
    if (!OidIsValid(element_type))
        elog(ERROR, "could not determine data type of input");
    /* ��ȡ�ṩ��Ԫ�� */
    element = PG_GETARG_DATUM(0);
    /* ���ǵ�ά���� 1 */
    ndims = 1;
    /* ��һ��Ԫ�� */
    dims[0] = 1;
    /* �����½��� 1*/
    lbs[0] = 1;
    /* ��ȡ�й�Ԫ��������Ҫ����Ϣ */
    get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign);
    /* Ȼ���������� */
    result = construct_md_array(&element, ndims, dims, lbs,
                                element_type, typlen, typbyval, typalign);
    PG_RETURN_ARRAYTYPE_P(result);
}
����������� SQL �������� make_array��
CREATE FUNCTION make_array(anyelement) RETURNS anyarray
    AS 'DIRECTORY/funcs', 'make_array'
    LANGUAGE C STRICT;��ע��ʹ�� STRICT����һ��dz���Ҫ����Ϊ����û��������Կ����롣