PostgreSQL 8.2.3 婺桺桺懼
劯锔媆锔䆹33. 欷匘 SQL媆誕嬉誕

33.11. 䫘潙垔幬䌂傋

溼套誗33.2欔臘PostgreSQL 埇傖欷匘婺櫇毕桄䔇昄扞䌂傋㔗橸誗柟誄套嘘垔幬桄䔇嘺橸䌂傋認底䌂傋滇闼底垔幬婘 SQL 臺蘔幋婋䔇昄扞䌂傋㔗录傺婔婻桄䔇嘺橸䌂傋襕挗垂䯄庘昄嘯北臺蘔(锔婩滇 C)䔇䌂傋婪淉嘩㔗

橸誗䔇冋床埇傖婘溊乕埏婄婺 src/tutorial 䕞嘘䔇 complex.sqlcomplex.c 麯欆彄㔗埗蓕劯䕞嘘婋䔇 README 桺傽噿庯套嘘誊臯冋床䔇毺䴺㔗

婔婻䫘潙垔幬䔇䌂傋攂滇橬膷噖启膷庺庘昄㔗認底庘昄喿垔臖䌂傋套嘘婘庖严婾麯庺䯄(螷䫘潙膷噖启膷庺䂍䫘潙)傖埪䌂傋套嘘婘喙庻麯䂇䂺㔗膷噖庘昄傖婔婻傖䷺(null)䂷儆䔇庖严婾婺埗昄幽婫誫啂臖䌂傋䔇喙鄘(喙庻麯)䔇臘䯄嘵嚟㔗膷庺䌂傋傖臖䌂傋䔇喙鄘臘䯄嘵嚟婺埗昄幽婫誫啂婔婻傖䷺(null)䂷儆䔇庖严婾㔗

啺螆襕垔幬婔婻 complex 䌂傋準臘䴺崉昄㔗锔婩锬䫘婋麵䔇 C 䂷悇準婘喙庻麯臘䯄崉昄

typedef struct Complex {
    double      x;
    double      y;
} Complex;

潏傸驔襕儖垄埻潊嚘䫘嚹锐䌂傋(啹婺垄崻崓婉脘櫆婘婔婻剘䋸䔇 Datum 唚婺)㔗

凹庯臖䌂傋䔇崡鄘臘䯄嘵嚟锬拷嘵套 (x,y) 䔇庖严婾㔗

膷噖膷庺庘昄锔婩幽婉锆喍儴噽滇膷庺庘昄㔗嘖滇婘垔幬嘹䔇崡鄘(庖严婾)臘䯄嘵嚟施襕濘懟嘹橔劯媙釂婺臖臘䯄嘵嚟喍婔婻垯昘蔯婫啖弞䔇彖悊単嘩婺膷噖庘昄㔗懫套

PG_FUNCTION_INFO_V1(complex_in);

Datum
complex_in(PG_FUNCTION_ARGS)
{
    char       *str = PG_GETARG_CSTRING(0);
    double      x,
                y;
    Complex    *result;

    if (sscanf(str, " ( %lf , %lf )", &x, &y) != 2)
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
                 errmsg("invalid input syntax for complex: \"%s\"",
                        str)));

    result = (Complex *) palloc(sizeof(Complex));
    result->x = x;
    result->y = y;
    PG_RETURN_POINTER(result);
}

膷庺庘昄埇傖䞔剘䔇喍潊

PG_FUNCTION_INFO_V1(complex_out);

Datum
complex_out(PG_FUNCTION_ARGS)
{
    Complex    *complex = (Complex *) PG_GETARG_POINTER(0);
    char       *result;

    result = (char *) palloc(100);
    snprintf(result, 100, "(%g,%g)", complex->x, complex->y);
    PG_RETURN_CSTRING(result);
}

嘹庫臖檪嘹䔇膷噖启膷庺庘昄啔潊庐锖庘昄㔗套悩婉認湙啔儌埇脘婘驔襕檪昄扞膷庺準喉媹蘘啂寂施䵄彄冽婖麉䔇閞鵻嘷潬埪敞䗹昄施認滇麂婩捞镉䔇閞鵻㔗

埥崡婔婻䫘潙垔幬䌂傋埇傖柊冕庯誕彽膷噖启膷庺誺䘋㔗庯誕彽 I/O 锔婩敘媆嘖滇澇橬桺橸 I/O 䓂洉攓喘㔗啹婺凹庯桺橸 I/O 蔯蘔垯噘䫌嘹準垔幬崡鄘䔇庯誕彽嘵嚟㔗崓崔昄喙䘞䔇昄扞䌂傋鄘儘埇脘柊冕婔婻婯橺単方噿䔇庯誕彽嘵嚟㔗凹庯 complex 儖檪庯誕彽 I/O 傺䆋婘 float8 䔇嘺䇔婪

PG_FUNCTION_INFO_V1(complex_recv);

Datum
complex_recv(PG_FUNCTION_ARGS)
{
    StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
    Complex    *result;

    result = (Complex *) palloc(sizeof(Complex));
    result->x = pq_getmsgfloat8(buf);
    result->y = pq_getmsgfloat8(buf);
    PG_RETURN_POINTER(result);
}

PG_FUNCTION_INFO_V1(complex_send);

Datum
complex_send(PG_FUNCTION_ARGS)
{
    Complex    *complex = (Complex *) PG_GETARG_POINTER(0);
    StringInfoData buf;

    pq_begintypsend(&buf);
    pq_sendfloat8(&buf, complex->x);
    pq_sendfloat8(&buf, complex->y);
    PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}

婔斥潏傸喍喘 I/O 庘昄幽儖噽䚡臏婺噌庆康儌埇傖垔幬 SQL 婺䔇 complex 䌂傋㔗潏傸饡噽弄滯噽婺 shell 䌂傋

CREATE TYPE complex;

認儖嘩婺婔婻剹嘉严傖噕螩婘垔幬噽 I/O 庘昄施嚘䫘臖䌂傋㔗䯄婘潏傸垔幬噽 I/O 庘昄

CREATE FUNCTION complex_in(cstring)
    RETURNS complex
    AS 'filename'
    LANGUAGE C IMMUTABLE STRICT;

CREATE FUNCTION complex_out(complex)
    RETURNS cstring
    AS 'filename'
    LANGUAGE C IMMUTABLE STRICT;

CREATE FUNCTION complex_recv(internal)
   RETURNS complex
   AS 'filename'
   LANGUAGE C IMMUTABLE STRICT;

CREATE FUNCTION complex_send(complex)
   RETURNS bytea
   AS 'filename'
   LANGUAGE C IMMUTABLE STRICT;

橔劯埇傖垯昘垔幬臖昄扞䌂傋

CREATE TYPE complex (
   internallength = 16, 
   input = complex_in,
   output = complex_out,
   receive = complex_recv,
   send = complex_send,
   alignment = double
);

嘷嘹垔幬婔䓉桄䔇嘺橸䌂傋施PostgreSQL 躻媘柊冕凹臖䌂傋䔇昄䂇櫇毕㔗啹婺寖埾寘啹昄䂇䌂傋䔇䌂傋劉滇婯臖䌂傋劯劉䔇庖严婾嬉麵媹婻婋彐亪庖严(_)㔗

婔斥昄扞䌂傋庻婘儌埇傖弄滯鵺崡䔇庘昄傖柊冕婘臖昄扞䌂傋婪䔇淉嘩䇽劯儌埇傖婘認底庘昄婪垔幬淉嘩严㔗套悩驔襕誻埇傖录傺淉嘩严䌂櫇毕臖昄扞䌂傋䔇䘵嚘㔗認底儖婘劯麵䔇䆹誗傋䂉㔗

套悩嘹䔇昄扞䌂傋䔇崓償埇脘轙誺庹䍆婻庖誗(喙鄘嘵嚟)闼幽嘹庫臖冽傫䂖婄檪垄傸湺螄婺埇 TOAST 䔇(埗黙誗52.2)㔗襕啔彄認婔䗹臖䌂傋䔇喙鄘嘵嚟媙驔镕冻埻阪昄扞喙鄘嘵嚟䔇湺庖婄匔崘啕婻庖誗媙驔滇婔婻寙劆昄扞噘阪(寙拸阪庥躻躆)䔇 int32 㔗婘臖䌂傋婪淉嘩䔇 C 庘昄媙釂锔誺嘪䫘 PG_DETOAST_DATUM 償媄婄蓼嚔垄傸崇䊖䔇傂嘘"䄻䄴"誺䔇昄唚(認底䂖誗锔婩鄘埇傖锔誺垔幬䌂傋䕩噿䔇 GETARG 垟毷䕡)㔗橔劯婘嘪䫘 CREATE TYPE 变傴䔇施唍弄滯喙鄘阪庥婺 variable 幽婫锬拷敄嘷䔇庻嗘锬釹㔗

敘崔䂖誗臙埗黙 CREATE TYPE 变傴䔇柟誄㔗


劯锔饡釕嬉誕
䫘潙垔幬蕔镖婪婔亓䫘潙垔幬淉嘩严