7. È®Àå SQL : ÇÔ¼ö

ÇÔ¼ö¸¦ Á¤ÀÇÇÏ´Â °ÍÀº »õ·Î¿î Çü(type)À» Á¤ÀÇÇÏ´Â °ÍÁß ÀϺκÐÀÌ´Ù. »õ·Î¿î Çü(type)À» Á¤ÀÇÇÏÁö ¾Ê°í ÇÔ¼ö¸¦ Á¤ÀÇÇÏ´Â °ÍÀº °¡´ÉÇÏÁö¸¸, ±× ¿ªÀº ºÒ°¡´É ÇÏ´Ù. µû¶ó¼­ ¿©±â¼­´Â »õ·Î¿î Çü(type)À» Ãß°¡ÇÏ´Â ¹æ¹ýÀ» ¼³¸íÇϱ⿡ ¾Õ¼­ »õ·Î¿î ÇÔ¼ö¸¦ Ãß°¡ÇÏ´Â ¹æ¹ýºÎÅÍ ¸ÕÀú ¼³¸íÇÒ °ÍÀÌ´Ù.

ÀÌÀå¿¡¼­ ³ª¿À´Â ¿¹Á¦µéÀº funcs.sql °ú C-code/funcs.c ¿¡¼­ ãÀ» ¼ö ÀÖ´Ù.

7.1 ÁúÀǾî (SQL) ÇÔ¼ö

7.1.1 ±âº»Çü SQL ÇÔ¼ö

°¡Àå °£´ÜÇÑ SQL ÇÔ¼ö´Â ¸Å°³ÀÎÀÚ´Â ¾ø°í, int4 ¿Í °°Àº ±âº»ÇüÀ» ¹ÝȯÇÏ´Â °ÍÀÌ ¾Æ´Ò±î?

    CREATE FUNCTION one() RETURNS int4
         AS 'SELECT 1 as RESULT' LANGUAGE 'sql';
 
    SELECT one() AS answer;
 
 
    answer
    ------
         1

¿©±â¿¡¼­ ´ë»ó ¸®½ºÆ®¸¦ RESULT ¶ó´Â À̸§À¸·Î ÇÔ¼ö¸¦ À§ÇØ Á¤ÀÇÇÏ¿´À¸³ª, ÇÔ¼ö¸¦ ºÒ·¯¿À´Â ÁúÀÇ¿¡¼­ÀÇ ´ë»ó ¸®½ºÆ®´Â ÇÔ¼öÀÇ ´ë»ó ¸®½ºÆ®¸¦ ¹«È¿È­ÇÑ´Ù. µû¶ó¼­, ±× °á°ú¿¡´Â one ´ë½Å answer À̶ó´Â À̸§ÀÇ ¶óº§ÀÌ ºÙ´Â´Ù.

ÀÌÁ¦ ¸Å°³ÀÎÀÚ·Î ±âº»ÇüÀ» °¡Áö´Â SQL ÇÔ¼ö¸¦ Á¤ÀÇÇØº¸ÀÚ. ¾Æ·¡ÀÇ ¿¹¿¡¼­, ÇÔ¼ö³» ºÎ¿¡¼­ ¸Å°³ÀÎÀÚ¸¦ ÂüÁ¶ÇÒ ¶§´Â $1, $2 ¿Í °°ÀÌ »ç¿ëÇÑ´Ù´Â Á¡¿¡ ÁÖÀÇÇ϶ó.

    CREATE FUNCTION add_em(int4, int4) RETURNS int4
         AS 'SELECT $1 + $2;' LANGUAGE 'sql';
 
    SELECT add_em(1, 2) AS answer;
    
 
    answer
    ------
         3

7.1.2 º¹ÇÕÇü SQL ÇÔ¼ö

ÇÔ¼ö¿¡¼­ÀÇ ¸Å°³ÀÎÀÚ°¡ º¹ÇÕÇü (EMP ó·³)ÀÏ °æ¿ì¿¡´Â, ¿øÇÏ´Â (À§¿¡¼­ $1, $2 ¶ó°í Çß´ø °Íó·³) ÀÎÀÚ¸¦ ¸í½Ã¸¸ ÇØ¼­´Â ¾ÈµÇ°í ÀÎÀÚÀÇ ¼Ó¼º±îÁö ¸í½ÃÇØ¾ß ÇÑ´Ù. ¿¹¸¦ µé¾î, »ç¿øÀÇ ±Þ·á¸¦ µÎ¹è·Î °è»êÇÏ´Â double_salary ÇÔ¼ö¸¦ »ìÆìº¸ÀÚ.

    CREATE FUNCTION double_salary(EMP) RETURNS int4
         AS 'SELECT $1.salary * 2 AS salary;' LANGUAGE 'sql';
 
    SELECT name, double_salary(EMP) AS dream
        FROM EMP
        WHERE EMP.dept = 'toy';
 
 
   name|dream
   ----+-----
   Sam | 2400

$1.salary ¹®¹ýÀÇ »ç¿ë¿¡ ÁÖÀÇÇÏÀÚ. º¹ÇÕÇüÀ» ¹ÝȯÇÏ´Â ÇÔ¼ö·Î µé¾î°¡±â Àü¿¡, ¸ÕÀú ¼Ó¼º°ú °ü·ÃµÈ ÇÔ¼ö½Ä Ç¥±â¹ýºÎÅÍ ¾Ë ¾Æº¸ÀÚ. ÀÌ·¯ÇÑ Ç¥±â¹æ½Ä¿¡´Â attribute(class) ¿Í class.attribute ÀÇ µÎ°¡Áö°¡ ÀÖÀ¸¸ç ¼­·Î ¹Ù²Ù¾î »ç¿ëÇÒ ¼ö ÀÖ´Ù.

   --
   -- À̰ÍÀº ´ÙÀ½ÀÇ »ç¿ë°ú µ¿ÀÏÇÏ´Ù:
   --    SELECT EMP.name AS youngster FROM EMP WHERE EMP.age < 30
   --
   SELECT name(EMP) AS youngster
   FROM EMP 
   WHERE age(EMP) < 30;
 
 
   youngster
   ---------
   Sam      

°á°ú°¡ Ç×»ó ÀÌ¿Í °°Áö´Â ¾Ê´Ù. ÀÌ ÇÔ¼ö½Ä Ç¥±â¹ýÀº ÇϳªÀÇ ÀνºÅϽº¸¦ ¹ÝȯÇÏ´Â ÇÔ¼ö¸¦ »ç¿ëÇÒ ¶§ Áß¿äÇÏ´Ù. ÀÌ·¯ÇÑ ÀÛ¾÷Àº ÇÔ¼ö³»ÀÇ Àüü ÀνºÅϽº¸¦ ¼Ó¼ºÀ» Çϳª¾¿ ²ø¾î¸ðÀ½À¸·Î½á ÇÒ ¼ö ÀÖ´Ù. ´ÙÀ½Àº ÇϳªÀÇ EMP ÀνºÅϽº¸¦ ¹ÝȯÇÏ´Â ÇÔ¼öÀÇ ¿¹ÀÌ´Ù.

   CREATE FUNCTION new_emp() RETURNS EMP
      AS 'SELECT \'None\'::text AS name,
         1000 AS salary,
                  25 AS age,
                  \'none\'::char16 AS dept;'
      LANGUAGE 'sql';

¿©±â¼­´Â °¢°¢ÀÇ ¼Ó¼ºÀ» »ó¼ö°ªÀ¸·Î ÁöÁ¤ÇÏ¿´À¸³ª, ¾î¶°ÇÑ °è»ê°ªÀ̳ª Ç¥Çö½Äµµ ÀÌ·¯ÇÑ »ó¼ö°ªÀ» ´ëüÇÒ ¼ö ÀÖ´Ù. ÀÌ¿Í °°ÀÌ ÇÔ¼ö¸¦ Á¤ÀÇÇÏ´Â °ÍÀº ÀÏÁ¾ÀÇ Æ®¸¯ÀÏ °ÍÀÌ´Ù. ¸î°¡Áö ÁÖÀÇÇØ¾ßÇÒ Áß¿ä ÇÑ »çÇ×Àº ´ÙÀ½°ú °°´Ù.

    SELECT name(new_emp()) AS nobody;

    nobody
    ------
    None

* ÇÔ¼ö¿¡¼­ÀÇ ¹Ýȯ°ª¿¡¼­ ¼Ó¼ºÀ» ÃëÇÒ ¶§´Â ¹Ýµå½Ã ÇÔ¼ö½Ä Ç¥±â¹ýÀ» »ç¿ëÇØ¾ß ÇÏ´Â µ¥, ±× ÀÌÀ¯´Â ÇÔ¼öÈ£ÃâÀ» °áÇÕÇØ¼­ »ç¿ëÇÒ ¶§ ÆÄ¼­´Â Á¡('.')ÀÌ ºÙÀº ´Ù¸¥ ¹®¹ý À» ÀÌÇØÇÏÁö ¸øÇϱ⠶§¹®ÀÌ´Ù.

    SELECT new_emp().name AS nobody;
    WARN:parser: syntax error at or near "."

SQL ÁúÀǾ¼­ ¾î¶°ÇÑ ¸í·ÉÀÇ Á¶ÇÕµµ ÇÔ²² ¹­À» ¼ö ÀÖÀ¸¸ç ÇÔ¼ö·Î Á¤ÀÇÇÒ ¼ö ÀÖ´Ù. SQL ·Î ÀÛ¼ºµÇ´Â ÇÔ¼ö¿¡¼­ select ÁúÀÇ¿Í ¸¶Âù°¡Áö·Î °»½Å(insert, update, delete µî) ¸í·ÉÀ» Æ÷ÇÔÇÒ ¼ö ÀÖ´Ù. ±×·¯³ª, ¸¶Áö¸· ¸í·ÉÀº ¹Ýµå½Ã select ¿©¾ß Çϸç, ÇÔ¼öÀÇ returntype À¸·Î ÁöÁ¤µÈ ¾î¶°ÇÑ °ªÀ» ¹ÝȯÇÏ¿©¾ß ÇÑ´Ù.

   CREATE FUNCTION clean_EMP () RETURNS int4
     AS 'DELETE FROM EMP WHERE EMP.salary <= 0;
         SELECT 1 AS ignore_this'
     LANGUAGE'sql';
 
   SELECT clean_EMP();
 
   x
   -
   1

7.2 ÇÁ·Î±×·¡¹Ö ¾ð¾î ÇÔ¼ö

7.2.1 ±âº»Çü ÇÁ·Î±×·¡¹Ö ¾ð¾î ÇÔ¼ö

POSTGRES ´Â ³»ºÎÀûÀ¸·Î ±âº»ÇüÀ» ¸Þ¸ð¸®ÀÇ ÆÄÆíÀ¸·Î ÀνÄÇÑ´Ù. ÇϳªÀÇ ÇüÀ» ³Ñ¾î Á¤ÀÇÇÑ »ç¿ëÀÚ Á¤ÀÇ ÇÔ¼ö´Â POSTGRES ÇÔ¼ö»ó¿¡¼­ ÀÛµ¿ÇÒ ¼ö ÀÖ´Â ¹æ¹ýÀ» Á¤ÀÇÇÏ´Â °ÍÀÌ´Ù. POSTGRES ´Â ÇÔ¼ö¸¦ ÀúÀåÇÏ°í µð½ºÅ©¿¡¼­ Àоî¿Ã »ÓÀ̸ç, µ¥ÀÌÅÍ ÀÔ·Â. ó¸®.Ãâ·ÂÀ» À§ÇØ »ç¿ëÀÚ Á¤ÀÇÇÔ¼ö¸¦ »ç¿ëÇÒ »ÓÀÌ´Ù.

±âº»ÇüÀº ´ÙÀ½ÀÇ ¼¼°¡Áö ³»ºÎÀûÀÎ Çü½ÄÁß Çϳª¸¦ °¡Áú ¼ö ÀÖ´Ù.

°ª¿¡ ÀÇÇÑ Çü(type)Àº »ç¿ëÀÚÀÇ ÄÄÇ»ÅͰ¡ ´Ù¸¥ Å©±âÀÇ º¯¼ö ÇüŸ¦ Á¦°øÇÑ´Ù ÇÒÁö ¶óµµ, ±× ±æÀÌ´Â 1,2,4 ¹ÙÀÌÆ®¸¸ µÉ ¼ö ÀÖ´Ù. POSTGRES ´Â ±×ÀÚü·Î´Â °ª¿¡ ÀÇÇÑ Àü´Þ¹æ½ÄÀ¸·Î Á¤¼öÇü¸¸ ³Ñ°ÜÁÙ ¼ö ÀÖ´Ù. »õ·Î¿î Çü(type)À» Á¤ÀÇÇÒ ¶§´Â ¸ðµç ¾Æ ŰŨÃÄ¿¡¼­ °°Àº Å©±â(¹ÙÀÌÆ®¼ö·Î)°¡ µÇ¾î¾ß ÇÑ´Ù´Â Á¡¿¡ ÁÖÀÇÇØ¾ß ÇÑ´Ù. ¿¹¸¦ µé ¾î, long ÇüÀº À§ÇèÇѵ¥, ±× ÀÌÀ¯´Â int ÇüÀÌ 4¹ÙÀÌÆ®ÀÎ ´ëºÎºÐÀÇ À¯´Ð½º ¸Ó½®»ó¿¡ ÀÇ ¾î¶°ÇÑ ¸Ó½®¿¡¼­´Â 4¹ÙÀÌÆ®ÀÌ°í ´Ù¸¥ ¸Ó½®¿¡¼­´Â 8¹ÙÀÌÆ®°¡ µÉ ¼ö Àֱ⠶§¹®ÀÌ ´Ù (´ë°³ÀÇ PC ¿¡¼­´Â ±×·¸Áö ¾Ê°ÚÁö¸¸). À¯´Ð½º ¸Ó½®»ó¿¡¼­ int4´Â ´ÙÀ½°ú °°´Ù.

    /* 4-byte integer, passwd by value */
    typedef int int4;

±×¿ÜÀÇ °æ¿ì¿¡, °íÁ¤±æÀÌ ÇüÀº ÂüÁ¶¿¡ ÀÇÇÑ Àü´ÞÀÌ µÈ´Ù. ¿¹¸¦ µé¾î, POSTGRES ÀÇ char16 ÇüÀº ´ÙÀ½°ú °°´Ù.

    /* 16-byte structure, passed by reference */
    typedef struct {
        char data[16];
    } char16;

char16°ú °°Àº ÇüÀ» POSTGRES ·Î ³Ñ°ÜÁְųª ¹ÞÀ» ¶§¿¡´Â ÀÌ Çü¿¡ ´ëÇÑ Æ÷ÀÎÅ͸¸À» »ç¿ëÇÒ ¼ö ÀÖ´Ù.

¸¶Áö¸·À¸·Î, ¸ðµç °¡º¯±æÀÌ µ¥ÀÌÅÍ ÇüÀº ÂüÁ¶¿¡ ÀÇÇÑ Àü´ÞÀ̾î¾ß ÇÑ´Ù. ¾Æ¿ï·¯, ¸ðµç °¡º¯±æÀÌ µ¥ÀÌÅÍ ÇüÀº Á¤È®È÷ 4¹ÙÀÌÆ®ÀÇ ±æÀ̸¦ ³ªÅ¸³»´Â Çʵå·Î ½ÃÀ۵Ǿî¾ß Çϸç, ÇØ´ç µ¥ÀÌÅÍ Çü¿¡ ÀúÀåµÉ ¸ðµç µ¥ÀÌÅÍ´Â ±æÀÌÇ¥½Ã ÇÊµå ¹Ù·Î ´ÙÀ½ÀÇ ¸Þ¸ð¸® À§Ä¡»ó¿¡ ¿Àµµ·Ï ÇØ¾ß ÇÑ´Ù. ±æÀÌ Çʵå´Â ±æÀÌ ÇÊµå ±× ÀÚüÀÇ ±æÀ̸¦ Æ÷ÇÔÇÑ, ±¸Á¶Ã¼ ±æÀÌÀÇ ÇÕ°èÀÌ´Ù. 'text' µ¥ÀÌÅÍ ÇüÀ» ´ÙÀ½°ú °°ÀÌ Á¤ÀÇÇÒ ¼ö ÀÖ´Ù.

    typedef struct {
        int4 length;
        char data[1];
    } text;

»ç½Ç, data Çʵå´Â °¡´ÉÇÑ ¸ðµç ¹®ÀÚ¿­À» ÀúÀåÇϱ⿡´Â ÃæºÐÇÏÁö ¾Ê´Ù -- C ¿¡¼­µµ ÀÌ·¯ÇÑ ÃæºÐÇÑ ±¸Á¶Ã¼¸¦ ¼±¾ðÇÏ´Â °ÍÀº ºÒ°¡´ÉÇÏ´Ù. °¡º¯±æÀÌ µ¥ÀÌÅÍ ÇüÀ» ó¸®ÇÒ ¶§´Â, ÀûÀýÇÑ ¾çÀÇ ¸Þ¸ð¸®¸¦ ÇÒ´çÇÏ°í ±æÀÌ Çʵ带 ÃʱâÈ­ÇØ¾ß ÇÑ´Ù´Â Á¡¿¡ À¯ÀÇ ÇØ¾ß ÇÑ´Ù. ¿¹¸¦ µé¾î, text ±¸Á¶Ã¼¿¡ 40¹ÙÀÌÆ®¸¦ ÀúÀåÇÏ·Á ÇÒ °æ¿ì, ´ÙÀ½°ú °°Àº ÇüŸ¦ ¶ç°Ô µÉ °ÍÀÌ´Ù.

    #include "postgres.h"
    #include "utils/palloc.h"
    ...
    char buffer[40]; /* our source data */
    ...
    text *destination = (text *)palloc(VARHDRSZ + 40);
    destination->length = VARHDRSZ + 40;
    memmove(destination->data, buffer, 40);
    ...

Áö±Ý±îÁö ±âº»Çü¿¡¼­ »ç¿ë°¡´ÉÇÑ ±¸Á¶¸¦ ¸ðµÎ »ìÆìº¸¾Ò´Ù. ÀÌÁ¦ ½ÇÁ¦ ÇÔ¼öÀÇ ¿¹¸¦ Á¶±Ý »ìÆìº¸µµ·Ï ÇÏÀÚ. C-code/funcs.c ÀÇ ³»¿ëÀº ´ÙÀ½°ú °°´Ù.

    #include <string.h>
    #include "postgres.h" /* for char16, etc. */
    #include "utils/palloc.h" /* for palloc */

    int add_one(int arg) { return(arg + 1); }

    char16 * concat16(char16 *arg1, char16 *arg2)
    {
        char16 *new_c16 = (char16 *) palloc(sizeof(char16));
        memset((void *) new_c16, 0, sizeof(char16));
        (void) strncpy(new_c16, arg1, 16);
        return (char16 *)(strncat(new_c16, arg2, 16));
    }

    text * copytext(text *t)
    {
        /* * VARSIZE is the total size of the struct in bytes. */
        text *new_t = (text *) palloc(VARSIZE(t));
        memset(new_t, 0, VARSIZE(t));
        VARSIZE(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);
    }

OSF/1 ½Ã½ºÅÛ »ó¿¡¼­´Â ´ÙÀ½°ú °°ÀÌ Å¸ÀÌÇÎÇÒ ¼ö ÀÖ´Ù.

    CREATE FUNCTION add_one(int4) RETURNS int4 AS '/usr/local/postgres95/tutorial/obj/funcs.so' LANGUAGE 'c';
    CREATE FUNCTION concat16(char16, char16) RETURNS char16 AS '/usr/local/postgres95/tutorial/obj/funcs.so' LANGUAGE 'c';
    CREATE FUNCTION copytext(text) RETURNS text AS '/usr/local/postgres95/tutorial/obj/funcs.so' LANGUAGE 'c';

´Ù¸¥ ½Ã½ºÅÛ¿¡¼­´Â, ±×°ÍÀÌ °øÀ¯ ¶óÀ̺귯¸®¶ó´Â °ÍÀ» ³ªÅ¸³»±â À§ÇØ ¾Æ¸¶µµ ÆÄÀÏÀ̸§ÀÇ ³¡ÀÌ .sl ÀÌ µÇµµ·Ï ÇØ¾ß ÇÒ °ÍÀÌ´Ù

7.2.2 º¹ÇÕÇü ÇÁ·Î±×·¡¹Ö ¾ð¾î ÇÔ¼ö

º¹ÇÕÇüÀº C ÀÇ ±¸Á¶Ã¼Ã³·³ °íÁ¤µÇ¾î ÀÖÁö´Â ¾Ê´Ù. º¹ÇÕÇüÀÇ ÀνºÅϽº´Â ³Î ÇÊµå ¸¦ Æ÷ÇÔÇÒ ¼ö ÀÖ´Ù. ¾Æ¿ï·¯, °èÃþÀûÀ¸·Î »ó¼ÓµÈ º¹ÇÕÇüÀº °èÃþÀûÀ¸·Î °°Àº »ó¼ÓÀ» ¹ÞÀº ´Ù¸¥ ¸â¹ö¿Í´Â ´Ù¸¥ Çʵ带 °¡Áú ¼ö ÀÖ´Ù. µû¶ó¼­, POSTGRES ´Â C ·ÎºÎÅÍ ¿¢¼¼½º ÇÏ´Â º¹ÇÕÇü Çʵ带 À§ÇØ ÇÁ·Î½ÃÁ® ÀÎÅÍÆäÀ̽º¸¦ Á¦°øÇÑ´Ù.

POSTGRES °¡ ÀνºÅϽºÀÇ ÁýÇÕÀ» ó¸®ÇÏ´Â °Íó·³, °¢°¢ÀÇ ÀνºÅϽº´Â ºÒÅõ¸íÇÑ TUPLE Çü ±¸Á¶Ã¼·Î ÇÔ¼ö¿¡ ³Ñ°ÜÁú °ÍÀÌ´Ù.

¾î¶°ÇÑ ÁúÀǸ¦ ó¸®Çϱâ À§ÇØ ÇÔ¼ö¸¦ »ç¿ëÇÏ·Á ÇÑ´Ù°í °¡Á¤Çغ¸ÀÚ.

    SELECT name, c_overpaid(EMP, 1500) AS overpaid FROM EMP
    WHERE name = 'Bill' or name = 'Sam';

À§ÀÇ ÁúÀÇ¿¡ ³ª¿À´Â c_overpaid ´Â ´ÙÀ½°ú °°ÀÌ Á¤ÀÇÇÒ ¼ö ÀÖ´Ù.

    #include "postgres.h" /* for char16, etc. */
    #include "libpq-fe.h" /* for TUPLE */

    bool c_overpaid(TUPLE t, /* the current instance of EMP */ int4 limit)
    {
        bool isnull = false; int4 salary;
        salary = (int4) GetAttributeByName(t, "salary", &isnull);
        if (isnull) return (false);
        return (salary > limit);
    }

GetAttributeByName Àº POSTGRES ½Ã½ºÅÛ ÇÔ¼ö·Î¼­ ÇöÀç ÀνºÅϽºÀÇ ¼Ó¼ºÀ» ¹ÝȯÇÑ ´Ù. ¿©±â¿¡´Â ¼¼°³ÀÇ ¸Å°³ÀÎÀÚ°¡ ÀÖ´Â µ¥, ±×°¢°¢Àº ÇÔ¼ö·Î ³Ñ°ÜÁø TUPLE Çü ¸Å°³ÀÎÀÚ, ¾ò±â¸¦ ¹Ù¶ó´Â ¼Ó¼ºÀÇ À̸§, ÇØ´ç ¼Ó¼ºÀÌ ³ÎÀÎÁö¸¦ ³ªÅ¸³»´Â ¹Ýȯ°ªÀ» ÀúÀåÇÏ´Â ¸Å°³ÀÎÀÚÀÌ´Ù. GetAttributeByName Àº ¾Æ¸¶µµ µ¥ÀÌÅ͸¦ Á¤·ÄÇÒ °ÍÀ̱⿡ ¹Ýȯ°ªÀ» ¿øÇÏ´Â ÇüÀ¸·Î º¯È¯ ÇÒ ¼ö ÀÖ´Ù. ¿¹¸¦ µé¸é, char16 ÇüÀÎ ¼Ó¼º name ÀÌ ÀÖ´Ù¸é, GetAttributeByName È£ÃâÀº ´ÙÀ½°ú °°À» °ÍÀÌ´Ù.

    char *str; ... str = (char *) GetAttributeByName(t, "name", &isnull)

´ÙÀ½ÀÇ ÁúÀÇ´Â POSTGRES ¿¡°Ô c_overpaid ÇÔ¼ö¸¦ ÀνĽÃ۱â À§ÇÑ °ÍÀÌ´Ù.

    CREATE FUNCTION c_overpaid(EMP, int4) RETURNS bool
    AS '/usr/local/postgres95/tutorial/obj/funcs.so' LANGUAGE 'c';

C ÇÔ¼ö³»ºÎ¿¡¼­ºÎÅÍ »õ·Î¿î ÀνºÅϽº¸¦ »ý¼ºÇϰųª Á¸ÀçÇÏ´Â ÀνºÅϽº¸¦ º¯°æÇÒ ¼öµµ ÀÖÁö¸¸, ÀÌ ¸Þ´º¾ó¿¡¼­ ³íÀÇÇϱ⿡´Â ³Ê¹« º¹ÀâÇÏ´Ù.

7.3 ¸î°¡Áö ÁÖÀÇ»çÇ×

ÀÌÁ¦ Á» ´õ ±î´Ù·Î¿î ÇÁ·Î±×·¡¹Ö ¾ð¾î ÇÔ¼ö¸¦ ÀÛ¼ºÇÏ´Â ÀÓ¹«·Î µ¹¾Æ¿Íº¸ÀÚ. °æ°íÇÏÁö¸¸ ÀÌ ³»¿ëÀº ¿©·¯ºÐÀ» ÇÁ·Î±×·¡¸Ó·Î ¸¸µé±â À§ÇÑ °ÍÀÌ ¾Æ´Ï´Ù. ¿©·¯ºÐµé Àº POSTGRES ·Î ½ÇÁ¦·Î »ç¿ëÇÒ ÇÔ¼ö¸¦ C ·Î ÀÛ¼ºÇÏ·Á°í Çϱ⿡ ¾Õ¼­ C (Æ÷ÀÎÅÍÀÇ »ç¿ë, malloc ¸Þ¸ð¸® °ü¸® µîÀ» Æ÷ÇÔ)¸¦ Á¦´ë·Î ÀÌÇØÇϰí ÀÖ¾î¾ß ÇÑ´Ù.

C °¡ ¾Æ´Ñ ´Ù¸¥ ÇÁ·Î±×·¡¹Ö ¾ð¾î¸¦ »ç¿ëÇÏ¿© ÀÛ¼ºÇÑ ÇÔ¼ö¸¦ POSTGRES ·Î ÀûÀçÇÒ ¼ö ÀÖ±ä ÇÏÁö¸¸, ÀÌ ÀÛ¾÷Àº Á¾Á¾ ±î´Ù·Ó´Ù. ¿Ö³ÄÇÏ¸é Æ÷Æ®¶õÀ̳ª ÆÄ½ºÄ®°ú °°Àº ´Ù¸¥ ¾ð¾î´Â Á¾Á¾ "È£Ãâ °ü½À" ÀÌ C ¿Í´Â ´Ù¸£±â ¶§¹®ÀÌ´Ù. ÀÌÁ¡Àº, ´Ù¸¥ ¾ð¾î´Â °°Àº ¹æ¹ýÀ¸·Î ÇÔ¼ö»çÀÌ¿¡ ¸Å°³ÀÎÀÚ¸¦ Àü´ÞÇϰųª °ªÀ» ¹ÝȯÇÒ ¼ö ¾ø´Ù´Â °ÍÀÌ´Ù. ÀÌ·¯ÇÑ ÀÌÀ¯·Î, ¿©·¯ºÐÀÇ ÇÁ·Î±×·¡¹Ö ¾ð¾î ÇÔ¼ö´Â C ·Î ÀÛ¼ºµÇ¾ú´Ù°í °¡Á¤ÇÑ´Ù.

C ·Î ÇÔ¼ö¸¦ ÀÛ¼ºÇÒ ¶§ÀÇ ±âº»ÀûÀÎ ±ÔÄ¢Àº ´ÙÀ½°ú °°´Ù.

(1) POSTGRES ¿¡ À־ ´ëºÎºÐÀÇ Çì´õÆÄÀÏÀº /usr/local/postgres95/include ¿¡ ¼³Ä¡µÇ¾î ÀÖ¾î¾ß ÇÑ´Ù(±×¸² 2¿¡¼­ º¸µíÀÌ). cc ¸í·ÉÇà¿¡¼­ -I/usr/local/postgres95/include ¸¦ ¸í½ÃÇÏ¿© Çì´õÆÄÀÏÀ» Ç×»ó Æ÷ÇÔÇÏ¿©¾ß ÇÑ´Ù. °¡²û, ´ç½ÅÀÌ Ã£´Â Çì´õÆÄÀÏÀÌ ¼­¹ö ¼Ò½º Áß¿¡ ÀÖÀ» ¼öµµ ÀÖ´Ù (¿ì¸®°¡ °ÔÀ»·¯¼­ ¼³Ä¡¿¡ ºü¶ß¸° Çì´õÆÄÀÏÀº ¿©·¯ºÐµéÀÌ Á÷Á¢ include ¿¡ ¼³Ä¡ÇÒ Çʿ伺ÀÌ ÀÖ´Ù). ÀÌ·¯ÇÑ °æ¿ì¿¡ ´ÙÀ½ Áß ÇϳªÀÌ»óÀ» Ãß°¡ÇÒ ¼öµµ ÀÖ´Ù.

    -I/usr/local/postgres95/src/backend -I/usr/local/postgres95/src/backend/include
    -I/usr/local/postgres95/src/backend/port/<PORTNAME> -I/usr/local/postgres95/src/backend/obj

(¿©±â¿¡¼­ <PORTNAME> Àº alpha ³ª sparc ¿Í °°Àº Æ÷Æ® ¸íĪÀÌ´Ù. )

(2) ¸Þ¸ð¸® ÇÒ´çÀ» ÇÒ ¶§, C ¶óÀ̺귯¸®ÀÇ malloc ¿Í free ·çƾ ´ë½Å POSTGRES ÀÇ palloc ¿Í pfree ·çƾÀ» »ç¿ëÇÑ´Ù. palloc ¿¡ ÀÇÇØ ÇÒ´çµÈ ¸Þ¸ð¸®´Â ¸Å°³ Æ®·£ Àè¼ÇÀÇ ³¡ºÎºÐ¿¡¼­ ÀÚµ¿ÀûÀ¸·Î ¸Þ¸ð¸®¸¦ ÀÚÀ¯·Ó°Ô Çϸç, ¸Þ¸ð¸® À¯ÃâÀ» ¸·´Â´Ù.

(3) ÇØ´ç ±¸Á¶Ã¼´Â Ç×»ó memset ¶Ç´Â bzero ¸¦ »ç¿ëÇÏ¿© 0À¸·Î ÃʱâÈ­ÇÏ´Â °ÍÀÌ ÁÁ ´Ù. (ÇØ½¬ ¿¢¼¼½º ¸Þ½îµå, ÇØ½¬ °áÇÕ, Á¤·Ä ¾Ë°í¸®Áò µî°ú °°Àº) ¿©·¯ ·çƾÀº ±¸Á¶Ã¼¿¡ ÀÖ´Â ·Î¿ì(raw) ºñÆ®ÀÇ ÀÛ¿ëÀ» ÃßÁ¤ÇÑ´Ù. ±¸Á¶Ã¼ÀÇ Çʵ带 ¸ð µÎ ÃʱâÈ­ÇÑ´Ù ÇÒÁö¶óµµ, ¾²·¹±â °ªÀ» Æ÷ÇÔÇÏ´Â, Á¤·Ä½Ã¿¡ ¹ß»ýÇϴ ä¿ö³Ö±â (±¸Á¶Ã¼¿¡¼­ÀÇ È¦)¹ÙÀÌÆ®°¡ ÀÖÀ» ¼ö ÀÖ´Ù.

(4) ´ë°³ÀÇ ³»Àå POSTGRES µ¥ÀÌÅÍ ÇüÀº postgres.h ¿¡ Æ÷ÇÔµÇ¾î ¼±¾ðµÇ¾î ÀÖÀ¸¹Ç·Î, º¸Åë ÀÌ ÆÄÀÏÀ» Æ÷ÇÔÇÏ´Â °ÍÀÌ ÁÁ´Ù.

(5) POSTGRES ¿¡ µ¿ÀûÀ¸·Î ÀûÀçÇÒ ¸ñÀûÄڵ带 ÄÄÆÄÀÏÇϰí ÀûÀçÇÒ ½Ã¿¡´ÂƯº°ÇÑ Ç÷¡±×¸¦ ÇÊ¿ä·ÎÇÑ´Ù. ƯÁ¤ÇÑ ¿î¿µÃ¼Á¦ »ó¿¡¼­ ÀÌ·¯ÇÑ ÀÛ¾÷À» ÇÏ´Â ¹æ¹ý¿¡ ´ë ÇÑ ÀÚ¼¼ÇÑ Á¤º¸´Â ºÎ·Ï A ¸¦ ÂüÁ¶Ç϶ó.