33.11. »ç¿ëÀÚ Á¤ÀÇÀÇ ÇüÅÂ

Section 33.2¿¡ Áø¼úµÇ°í ÀÖµíÀÌ, PostgreSQL´Â »õ·Î¿î µ¥ÀÌÅÍÇüÀ» Áö¿øÇϵµ·Ï È®ÀåÇÒ ¼ö°¡ ÀÖ½À´Ï´Ù. º»Àý¿¡¼­´Â, SQL¾ð¾î ÀÌÇÏÀÇ ·¹º§·Î Á¤ÀǵǴ µ¥ÀÌÅÍÇüÀÎ, ±âº»ÇüÀ» »õ·Ó°Ô Á¤ÀÇÇÏ´Â ¹æ¹ý¿¡ ´ëÇØ ¼³¸íÇÕ´Ï´Ù. »õ·Î¿î ±âº»ÇüÀÇ ÀÛ¼º¿¡´Â, Àú·¹º§ ¾ð¾î, º¸Åë C·Î ÀÛ¼ºµÈ, ÇüŸ¦ Á¶ÀÛÇÏ´Â ÇÔ¼öÀÇ ±¸ÇöÀÌ ÇÊ¿äÇÕ´Ï´Ù.

º» ¼½¼Ç¿¡¼­ »ç¿ëÇÏ´Â ¿¹´Â, ¼Ò½º ¹èÆ÷¹° ³»ÀÇ src/tutorialµð·ºÅ丮¿¡ complex.sql¿Í complex.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);
}

ÀÔÃâ·Â ÇÔ¼ö´Â, °¢°¢ÀÇ ¿ªÇÔ¼ö°¡ µÇµµ·Ï ÇØ¾ß ÇÕ´Ï´Ù. ±×·¸°Ô ÇÏÁö ¾ÊÀ¸¸é, µ¥ÀÌÅ͸¦ ÆÄÀÏ¿¡ ¹ö¸®°í ±×°ÍÀ» ´Ù½Ã Àоî¿À·Á ÇÒ ¶§¿¡, ½É°¢ÇÑ ¹®Á¦°¡ ¹ß»ýÇϰÚÁö¿ä. À̰ÍÀº, ºÎµ¿ ¼Ò¼ö°¡ °ü°èµÉ ¶§ ÀÚÁÖ ¹ß»ýÇÏ´Â ¹®Á¦ÀÔ´Ï´Ù.

¿É¼ÇÀ¸·Î¼­, »ç¿ëÀÚ Á¤ÀÇÇüÀº ¹ÙÀ̳ʸ® ÀÔÃâ·Â ÇÔ¼ö¸¦ Á¦°øÇÒ ¼ö°¡ ÀÖ½À´Ï´Ù. º¸Åë, ¹ÙÀ̳ʸ® ÀÔÃâ·ÂÀº ºü¸£Áö¸¸, ÅØ½ºÆ® ÀÔÃâ·Âº¸´Ù À̽ļºÀÌ ¾ø½À´Ï´Ù. ÅØ½ºÆ® ÀÔÃâ·Â°ú °°°Ô, ¿ÜºÎ ¹ÙÀ̳ʸ® Ç¥ÇöÀ» Á¤È®ÇÏ°Ô Á¤ÀÇÇÏ´Â °ÍÀº ÀÛ¼ºÀÚÀÇ Ã¥ÀÓÀÔ´Ï´Ù. ´ëºÎºÐÀÇ ³»Àå µ¥ÀÌÅÍÇüÀº, ¸Ó½Å¿¡ ÀÇÁ¸ÇÏÁö ¾Ê´Â ¹ÙÀ̳ʸ® Ç¥ÇöÀ» Á¦°øÇÏ·Á°í ÇÕ´Ï´Ù. complexÇüÀº, 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));
}

ÀÔÃâ·Â ÇÔ¼ö¸¦ ÀÛ¼ºÇØ °øÀ¯ ¶óÀ̺귯¸®³»¿¡ ÄÄÆÄÀÏ Çϸé, SQLÀÇ complexÇüÀ» Á¤ÀÇÇÒ ¼ö ÀÖ½À´Ï´Ù. ¿ì¼± ½©ÇüÀ¸·Î¼­ ¼±¾ðÇÕ´Ï´Ù.

CREATE TYPE complex;

À̰ÍÀº Ç÷¹À̽ºÈ¦´õ(ÀÚ¸®)ÀÇ ¿ªÇÒÀ» ÇØ, ÀÔÃâ·Â ÇÔ¼ö¸¦ Á¤ÀÇÇÒ ¶§¿¡ ±× ÇüŸ¦ ÂüÁ¶ÇÒ ¼ö ÀÖ½À´Ï´Ù. ÀÌ ÈÄ ÀÌÇÏ¿Í °°ÀÌ, ÀÔÃâ·Â ÇÔ¼ö¸¦ Á¤ÀÇÇÒ ¼ö°¡ ÀÖ½À´Ï´Ù.

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°¡´ÉÇÏ°Ô ¸¸µé¾î¾ß ÇÕ´Ï´Ù. (Section 52.2¸¦ ÂüÁ¶ÇØ ÁÖ¼¼¿ä. ) À̸¦ À§Çؼ­, ³»ºÎ Ç¥ÇöÀÌ º¯¼ö ±æÀÌ µ¥ÀÌÅÍÀÇ Ç¥ÁØ ·¹À̾ƿô¿¡ µû¶ó¾ßÇÕ´Ï´Ù. óÀ½ÀÇ 4¹ÙÀÌÆ®´Â, ÀÚ·áÀÇ ¹ÙÀÌÆ®(±× ÀÚü¸¦ Æ÷ÇÔ)¿¡¼­ Àüü ±æÀ̸¦ Æ÷ÇÔÇÏ´Â int32°¡ µÇ¾î¾ß ÇÕ´Ï´Ù. ±× µ¥ÀÌÅÍÇüÀ» Ãë±ÞÇÏ´Â CÇÔ¼ö´Â, PG_DETOAST_DATUM¸¦ »ç¿ëÇØ, °Ç³×¹ÞÀº TOASTÈ­µÈ °ªÀ» ÁÖÀÇ ±í°Ô Àü°³ÇÏÁö ¾ÊÀ¸¸é ¾ÈµË´Ï´Ù (Åë»ó, ÀÚ¼¼ÇÑ °ÍÀº ÇüÅ µ¶ÀÚÀûÀÎ GETARG_DATATYPE_P¸ÅÅ©·Î¸¦ Á¤ÀÇÇØ ÀºÆóÇÕ´Ï´Ù). ±× ÈÄ, CREATE TYPE¸í·ÉÀ» ½ÇÇàÇÒ ¶§¿¡, variable¿¡ ³»ºÎ ±æÀ̸¦ ÁöÁ¤ÇØ, ¶Ç, ÀûÀýÇÑ ÀúÀå ¿É¼ÇÀ» ¼±ÅÃÇØ ÁÖ¼¼¿ä.

--> For further details see the description of the CREATE TYPE command. --> »ó¼¼ÇÑ °Í¿¡ ´ëÇØ¼­´Â CREATE TYPE ¸í·ÉÀÇ ¼³¸íÀ» ÂüÁ¶ÇØ ÁÖ¼¼¿ä.