°ø°³ µ¥ÀÌÅͺ£À̽º ¼­¹ö PostgreSQL (7)
- SPI ¿Í Æ®¸®°ÅÀÇ ¹Ð¿ù¿©Çà -

    Çѵ¿ÈÆ / ¸®´ª½º ÄÚ¸®¾Æ
    hoon@linuxkorea.co.kr
    http://www.linuxkorea.co.kr/~hoon

     

 

PostgreSQL 6.3.1 - ¸ÖƼ¹ÙÀÌÆ® ȯ°æÀÇ ±âº» Á¦°ø

    PostgreSQL 6.3.1ÀÇ »õ·Î¿î ¹öÀüÀÌ ¹ßÇ¥µÉ ¶§¸¶´Ù ±â´Ù·ÁÁö´Â ¹ÙÀÌÁö¸¸, À̹ø¸¸Å­Àº ³Ê¹« Á¤½Å¾øÀÌ ¹öÀüÀÌ ¿Ã¶ó°£ °ÍÀÌ ¾Æ´Ò±î »ý°¢ÇÑ´Ù. 3¿ù 1ÀÏ, 6.3 ¹öÀüÀÌ ³ª¿ÂÁö°¡ ä ÇÑ ´Þµµ µÇÁö ¾Ê¾Æ¼­ ¹ö±× ÆÐÄ¡¹öÀüÀÌ ¶Ç ´Ù½Ã ³ª¿Ô´Ù´Â ¼Ò½ÄÀ» ÁÖº¯ÀÇ Àß ¾Æ´Â µ¿·á·ÎºÎÅÍ µè°í, ȸ»ç ¼³¸³¿¡ Á¤½ÅÀÌ ¾ø´Â ÇÊÀÚ¿¡°Ô ¶Ç ÇϳªÀÇ ÀϰŸ®°¡ µÈ ´À³¦À̾ú´Ù.

    ÀÏ´Ü »õ·Î¿î ¹öÀüÀÌ ³ª¿À¸é ¼³Ä¡ÇÑ ´ÙÀ½ ¸î °¡Áö Å×½ºÆ®¸¦ ÇÏ´Â °ÍÀÌ ½À°üó·³ µÇ¾î ¹ö·È´Ù. ¹öÀü 6.3.1¿¡¼­ ´Þ¶óÁø ³»¿ë Áß °¡Àå Áß¿äÇÑ »çÇ×Àº ±× µ¿¾È ÆÐÄ¡ ÆÄÀÏ·Î º°µµ·Î Á¦°øµÇ´ø ¸ÖƼ¹ÙÀÌÆ®(ÇѱÛ, ÀϾî, Áß±¹¾î µîÀÇ 2¹ÙÀÌÆ®, ¼­¾ç±Ç 1¹ÙÀÌÆ®) Áö¿øÀÌ PostgreSQL ³»¿¡ ÀÚü Æ÷ÇԵǾú´Ù´Â °ÍÀÌ´Ù. ¼³Ä¡½Ã¿¡ ÀÚ±¹ÀÇ »ç¿ë¾ð¾î¸¦ À§ÇÑ ¼±Åø¸ ÇØÁÖ¸é µÈ´Ù. PostgreSQL ¼Ò½º ¹èÆ÷ÆÇÀ» Ǭ µð·ºÅ丮¸¦ Áß½ÉÀ¸·Î º»´Ù¸é, ÇÑ±Û »ç¿ëÀ» À§ÇÑ ¸ÖƼ¹ÙÀÌÆ® ¼±ÅÃÀº ´ÙÀ½°ú°°ÀÌ ÇÏ¸é µÈ´Ù.

      #  echo MB=EUC_KR > src/Makefile.custom

 

SPI ¿Í Æ®¸®°Å¶õ ¹«¾ùÀΰ¡?

    SPI´Â ¼­¹ö ÇÁ·Î±×·¡¹Ö ÀÎÅÍÆäÀ̽º(Server Programming Interface)ÀÌ´Ù. psqlÀº postmaster ¼­¹ö¿¡ Á¢¼ÓÇÏ¿© ÁúÀǸ¦ ó¸®Çϴ Ŭ¶óÀ̾ðÆ® À¯Æ¿¸®Æ¼¶ó°í º¼ ¼ö ÀÖ´Ù.

    SPI´Â SQL ÁúÀǸ¦ »ç¿ëÀÚ Á¤ÀÇ CÇÔ¼ö ³»ºÎ¿¡¼­ ½ÇÇàÇÒ ¼ö ÀÖ´Â ´É·ÂÀ» »ç¿ëÀÚ¿¡°Ô Á¦°øÇÑ´Ù. ÇöÀç ¹öÀüÀÇ PostgreSQL¿¡¼­ ¼­¹öÃø¿¡ ÀúÀåµÇ´Â ÇÁ·Î½ÃÀú¿Í Æ®¸®°Å¸¦ ÀÛ¼ºÇÒ ¼ö ÀÖ´Â À¯ÀÏÇÑ ¹æ¹ýÀÌ SPIÀÌ´Ù. »ç½Ç SPI´Â µ¥ÀÌÅͺ£À̽º ¼­¹ö ³»ÀÇ ºÐ¼®±â(Parser), °èȹ±â(Planner), ÃÖÀûÈ­±â(Optimizer), ½ÇÇà±â(Executor)¿¡ °£ÆíÇÏ°Ô Á¢±ºÇÒ ¼ö ÀÖ´Â ÀÎÅÍÆäÀ̽º ÇÔ¼öÀÇ ÁýÇÕÀÏ »ÓÀÌ´Ù. SPI ¿¡¼­´Â ¶ÇÇÑ ¾à°£ÀÇ ¸Þ¸ð¸® °ü¸®¸¦ ÇÔ²² ¼öÇàÇÑ´Ù.

 

¸ÕÀú SPI¸¦ ¹è¿ìÀÚ! - SPI ÀÎÅÍÆäÀ̽º ÇÔ¼ö

    SPI¸¦ ÀÍÈ÷´Â °ÍÀº LIBPQ¸¦ ÀÍÈú ¶§¿Í À¯»çÇÏ´Ù. ´Ù¸¸,  LIBPQ´Â ÇÁ·ÐÆ®¿£µå ÀÎÅÍÆäÀ̽º(¶Ç´Â Ŭ¶óÀ̾ðÆ®ÀÇ ¼­¹ö Á¢¼Ó ÀÎÅÍÆäÀ̽º)ÀÌ°í, SPI ´Â ¼­¹ö³»¿¡¼­ÀÇ ÇÁ·Î±×·¡¹Ö ÀÎÅÍÆäÀ̽º¶ó´Â Á¡¿¡ À¯ÀÇÇÏ¸é µÈ´Ù. SPI¸¦ ÀÛ¼ºÇÏ´Â ¾ð¾î´Â ´Ü¿¬ CÀÌ´Ù. ÀÛ¼ºÇÏ´Â ¹æ¹ýÀº SPIÁ¦°ø ÇÔ¼ö¸¦ »ç¿ëÇÏ¿© CÇÔ¼ö·Î ÀÛ¼ºÇÑ ´ÙÀ½, ÀÌ ÇÔ¼ö¸¦ PostgreSQL ³»ºÎ¿¡ µî·ÏÇϱâ À§Çؼ­ psql¿¡¼­ ÇÔ¼ö µî·Ï ÁúÀǸ¦ »ç¿ëÇÏ¸é µÈ´Ù. ¿øÇÏ´Â ±â´ÉÀ» SPIÇÔ¼ö¿Í Æ®¸®°Å µ¥ÀÌÅͱ¸Á¶¸¦ »ç¿ëÇÏ¿© C ÇÔ¼ö·Î ÀÛ¼ºÇÑ ´ÙÀ½, PSQL¿¡¼­ ÇÔ¼ö µî·Ï ÀýÂ÷¸¦ °ÅÄ£´Ù. ´ÙÀ½ Æ®¸®°Å »ý¼º ÁúÀǹ®À» »ç¿ëÇÏ¿© µî·ÏÇÑ´Ù. ¸ÕÀú, SPI ¿ëÀ¸·Î ÁغñµÇ¾î ÀÖ´Â ÇÔ¼ö¸¦ »ìÆ캸ÀÚ. À̵é ÇÔ¼ö´Â ¼­¹öÃø¿¡¼­ ±¸µ¿µÈ´Ù´Â Á¡À» »©¸é, LIBPQ¿Í ¿Ü¾çÀÌ À¯»çÇϹǷΠÀÍÈ÷±â ½¬¿ï °ÍÀÌ´Ù.

     

    SPI_connect

    int SPI_connect(void) ;

    ÀÌ ÇÔ¼ö´Â »ç¿ëÀÚÀÇ ÇÁ·Î½ÃÀú¸¦ SPI °ü¸®ÀÚ¿¡ ¿¬°á½ÃŲ´Ù. SPI_connect´Â Postgres ¹é¿£µå¿Í ¿¬°áÀ» ¼º¸³ÇÑ´Ù. ÁúÀǸ¦ ½ÇÇàÇϱâ À§Çؼ­´Â ¸ÕÀú ÀÌ ÇÔ¼ö¸¦ È£ÃâÇÏ¿©¾ß ÇÑ´Ù. SPI ÇÔ¼ö Áß¿¡´Â Á¢¼ÓÀÌ µÇÁö ¾ÊÀº »óÅ¿¡¼­ È£ÃâÇÒ ¼ö ÀÖ´Â °ÍÀÌ ´õ·¯ ÀÖ´Ù. ÀÌ¹Ì Á¢¼ÓÀÌ µÇ¾îÀÖ´Â »óÅ¿¡¼­ SPI_connect¸¦ ´Ù½Ã È£ÃâÇϸé SPI_ERROR_CONNECT¸¦ ¹ÝȯÇÑ´Ù. ¿¬°áÀÌ ¼º°øÀûÀÏ ¶§¿¡´Â, SPI_OK_CONNECT °¡ ¹ÝȯµÈ´Ù. ³»ºÎÀûÀ¸·Î ÀÌ ÇÔ¼ö´Â ÁúÀÇ ½ÇÇà°ú ¸Þ¸ð¸® °ü¸®¸¦ À§ÇÑ ³»ºÎÀûÀÎ ±¸Á¶Ã¼¸¦ ÃÖ±âÈ­ ÇÑ´Ù.

    SPI_finish

    int SPI_finish(void) ;

    ÀÌ ÇÔ¼ö´Â SPI °ü¸®ÀÚ¿Í »ç¿ëÀÚÀÇ ÇÁ·Î½ÃÀú¸¦ ºÐ¸®½ÃŲ´Ù. »ç¿ëÀÚ´Â SPI °ü¸®ÀÚ¸¦ ÅëÇØ ÀÛ¾÷À» ¸¶ÃÆ´Ù¸é ÀÌ ÇÔ¼ö¸¦ È£ÃâÇÏ¿©¾ß ÇÑ´Ù. ÇöÀç Á¢¼ÓÀÌ µÇ¾îÀÖÁö ¾ÊÀº »óÅ¿¡¼­ ÀÌ ÇÔ¼ö¸¦ È£ÃâÇÑ´Ù¸é, SPI_ERROR_UNCONNECTED¸¦ ¹ÝȯÇÑ´Ù. ±× ¿Ü¿¡´Â SPI_OK_UNCONNECTED¸¦ ¹ÝȯÇÑ´Ù. ³»ºÎÀûÀ¸·Î´Â SPI_connect¿¡¼­ palloc¸¦ ÅëÇØ ÇÒ´çµÈ ¸ðµç ¸Þ¸ð¸®¸¦ ÇØÁ¦ÇÑ´Ù.

    SPI_exec

    int SPI_exec(char  *query,  int tcount) ;

    ÀÌ ÇÔ¼ö´Â ÁúÀǽÇÇà °èȹÀ» ¼ö¸³ÇÏ¿©, ÁúÀǸ¦ ¼öÇàÇÑ´Ù. ¼­¹öÀÇ ºÐ¼®±â, °èȹ±â, ÃÖÀûÈ­±â°¡ ÀÌ ÇÔ¼öÀÇ °èȹ¼ö¸³½Ã¿¡ °ü¿©ÇÑ´Ù. char *query ´Â ÁúÀÇ °èȹÀ» Æ÷ÇÔÇÏ´Â ¹®ÀÚ¿­ÀÌ°í, int tcount ´Â ¹ÝȯµÉ Æ©ÇÃÀÇ ÃÖ´ë °¹¼öÀÌ´Ù. ÁúÀÇ°¡ ¼º°øÀûÀ¸·Î ¼öÇàµÇ¸é ´ÙÀ½ÀÇ ¾ç¼ö°¡ ¹ÝȯµÈ´Ù.

      SPI_OK_UTILITY  : À¯Æ¿¸®Æ¼ ÁúÀÇ(CREATE TABLE µî) °¡ ½ÇÇàµÇ¾úÀ» ¶§
      SPI_OK_SELECT  : SELECT °¡ ½ÇÇàµÇ¾úÀ» ¶§
      SPI_OK_SELINTO : SELINTO ... INTO °¡ ½ÇÇàµÇ¾úÀ» ¶§
      SPI_OK_INSERT   : INSERT °¡ ½ÇÇàµÇ¾úÀ» ¶§
      SPI_OK_DELETE  : DELETE °¡ ½ÇÇàµÇ¾úÀ» ¶§
      SPI_OK_UPDATE : UPDATE °¡ ½ÇÇàµÇ¾úÀ» ¶§

    ¿¡·¯°¡ ¹ß»ýÇÏ¸é ´ÙÀ½ Áß ÇϳªÀÇ À½¼ö¸¦ ¹ÝȯÇÑ´Ù.

      SPI_ERROR_ARGUMENT        : query °¡ NULLÀ̰ųª tcount <0
      SPI_ERROR_UNCOMMECTED : ÇÁ·Î½ÃÀú°¡ Á¢¼ÓÀÌ µÇÁö ¾Ê¾ÒÀ» ¶§
      SPI_ERROR_COPY                : COPY TO/FROM stdin°¡ ½ÇÇàµÉ ¶§
      SPI_ERROR_CURSOR            : DECLARE/CLOSE CURSOR, FETCH°¡ ½ÇÇàµÉ ¶§
      SPI_ERROR_TRANSACTION    : BEGIN/ABORT/END °¡ ½ÇÇàµÉ ¶§
      SPI_ERROR_OPUNKNOWN     : ÁúÀÇ Å¸ÀÔÀÌ ºÒ¸íÈ®ÇÒ ¶§

    SPI_exec´Â ¿¬°áµÈ ÇÁ·Î½ÃÀú¿¡¼­ È£ÃâµÇ¾î¾ß ÇÑ´Ù. tcount °¡ 0 À̸é, ÁúÀÇ °Ë»ö¿¡¼­ ÇØ´çÇÏ´Â ¸ðµç Æ©ÇÃÀ» ¹ÝȯÇÑ´Ù. tcount >0 À̸é, tcount ¸¸Å­¸¸ ¹ÝȯÇÑ´Ù. ¿¹¸¦ µé¾îº¸ÀÚ.

      SPI-exec ("insert into table select * from table", 5) ;

    À§ ÇÔ¼ö´Â Àû¾îµµ 5°³ÀÇ Æ©ÇÃÀ» ÇØ´ç Å×ÀÌºí¿¡ »ðÀÔÇÒ °ÍÀÌ´Ù.

    ÁÖÀÇ : ÇϳªÀÇ query ¾È¿¡ ¿©·¯°³ÀÇ º¹ÇÕ ÁúÀǸ¦ Àü´ÞÇÒ ¼ö ÀÖ´Ù.
             ÀÌ °æ¿ì¿¡ ¹Ýȯ°ªÀº ¸¶Áö¸· ÁúÀÇ°¡ ½ÇÇàµÈ °á°úÀÌ´Ù.

    ÁúÀÇ ¼öÇà°á°ú·Î ½ÇÁ¦ ¹ÝȯµÈ Æ©ÇÃÀÇ °¹¼ö´Â SPI_processed Àü¿ª º¯¼ö¿¡ ÀúÀåµÈ´Ù. SPI_OK_SELECT°¡ ¹ÝȯµÇ°í, SPI_processed °¡ 0º¸´Ù Å©´Ù¸é, Àü¿ª Æ÷ÀÎÅÍ SPITupleTable *SPI_tuptable¸¦ »ç¿ëÇÏ¿© ¼±ÅÃµÈ Æ©Çÿ¡ Á¢±ÙÇÒ ¼ö ÀÖ´Ù. SPI_finish ´Â SPITupleTable¿¡ ÇÒ´çµÈ ¸Þ¸ð¸®¸¦ ¸ðµÎ ÇØÁ¦Çϱ⠶§¹®¿¡ »ç¿ëºÒ°¡´É ÇØÁø´Ù´Â Á¡¿¡ ÁÖÀÇÇÏÀÚ!
    SPI-exec °¡ °¡Àå Áß¿äÇÏ°Ô Ãë±ÞµÇ¹Ç·Î ´«¿©°Ü ºÁµÎ´Â °ÍÀÌ ÁÁ´Ù.

     

    Âü°í

    SPITupletable ±¸Á¶Ã¼´Â ¸Å¿ì Áß¿äÇÏ´Ù. ¿Ö³ÄÇÏ¸é ½ÇÁ¦·Î ȸ¼öµÈ Æ©Çÿ¡ Á¢±ÙÇÒ ¼ö ÀÖ´Â ¹æ¹ýÀ» Á¦°øÇÏ°í Àֱ⠶§¹®ÀÌ´Ù. ³ªÁß¿¡ ¿¹Á¦¿¡¼­µµ ÀÌ ±¸Á¶Ã¼ À̾߱Ⱑ ³ª¿À¹Ç·Î ÀÚ¼¼È÷ ¾Ë¾Æº¸µµ·Ï ÇÑ´Ù. SPITupletable¿¡ ´ëÇÑ ±¸Á¶Ã¼ Á¤ÀÇ´Â PostgreSQLÀÌ ¼³Ä¡µÈ µð·ºÅ丮¸¦ ±âÁØÀ¸·Î include/executor/spi.h¿¡ ÀÖ´Ù.

      typedef struct
      {
         uint32            alloced ;     /* ÇÒ´çµÈ °ªÀÇ °³¼ö */
         uint32            free ;          /* ÀÚÀ¯·Î¿î °ªÀÇ °³¼ö*/ 
         TupleDesc      tupdesc ;    /* Æ©Çà ±â¼úÀÚ*/ 
         HeadTuple     * vals ;        /* ½ÇÁ¦ Æ©ÇÃÀ» ´ã°í ÀÖ´Â Æ÷ÀÎÅÍ*/ 
      } SPITupleTable ;

    ³ªÁßÀÇ ¿¹Á¦¿¡ ³ª¿À´Â SPI_tuptable Àº SPITupleTable¿¡ ´ëÇÑ Æ÷ÀÎÅÍÀÌ´Ù.

      SPITupleTable   *SPI_tuptable ;

    ·Î ¹Ì¸® SPI°ü¸®ÀÚ¿¡¼­ Á¤ÀǵǾî ÀÖ´Ù. ÀÌ ±¸Á¶Ã¼´Â SPI_tuptable ->vals

     

    SPI_prepare

    void  *SPI_prepare(char  *query,  int nargs, argtypes) ;

    SPI_ prepare´Â ½ÇÇà°èȹÀ» ¼ö¸³ÇÏ¿© ¹ÝȯÇÑ´Ù. ÇÏÁö¸¸ ÁúÀǸ¦ ½ÇÇàÇÏÁö´Â ¾Ê´Â´Ù. query´Â ÁúÀÇÇÒ ¹®ÀÚ¿­ÀÌ°í, nargs´Â ¸Å°³ÀÎÀÚ(SQLÇÔ¼ö¿¡¼­ $1... $nargs¿Í °°À½)ÀÇ °³¼öÀ̸ç, ÁúÀÇ ¾È¿¡ ¸Å°³ ÀÎÀÚ°¡ ¾øÀ» °æ¿ì¿¡ nargs´Â 0 ÀÌ µÉ ¼ö ÀÖ´Ù. SPI_prepare¿¡¼­ ¹ÝȯµÈ ÁúÀÇ °èȹÀº ÇöÀç ¼¼¼Ç¿¡¼­¸¸ »ç¿ëÇÒ ¼ö ÀÖ´Ù. SPI_finish¸¦ »ç¿ëÇϸé ÁúÀÇ °èȹ¿¡ ÇÒ´çµÈ ¸Þ¸ð¸®¸¦ ÇØÁ¦Çϱ⠶§¹®¿¡, ÀÌÈÄ¿¡µµ »ç¿ëÇÏ·Á¸é SPI_saveplanÀ» »ç¿ëÇÏ¿© º°µµ·Î ÀúÀåÇÏ¿©¾ß ÇÑ´Ù.

    SPI_prepare ÇÔ¼ö´Â Àß »ç¿ëÇÏÁö´Â ¾ÊÁö¸¸, ƯÁ¤ÇÑ °æ¿ì¿¡ À¯¿ëÇÒ ¼ö ÀÖ´Ù. °¡·É ÁغñµÈ ½ÇÇà°èȹÀ» ¼öÇàÇÏ´Â °ÍÀÌ À̵û±Ý ±×³É ½ÇÇàÇÏ´Â °Íº¸´Ù ºü¸¦ ¼ö ÀÖ´Ù. °°Àº ÁúÀǸ¦ ¿©·¯¹ø ¼öÇàÇÒ ¶§°¡ ÁÁÀº ¿¹ÀÌ´Ù. SPI_prepare°¡ ¼º°øÀûÀ¸·Î ¼öÇàµÇ¸é ³ÎÀÌ ¾Æ´Ñ Æ÷ÀÎÅÍ°¡ ¹ÝȯµÇ°í, ½ÇÆÐÇÏ¸é ³ÎÀÌ ¹ÝȯµÈ´Ù. ÀÌ ÇÔ¼öÀÇ ¼öÇà »óÅ °á°ú´Â SPI_result Àü¿ª ÇÔ¼ö¿¡ ¼³Á¤µÈ´Ù. ³»¿ëÀº SPI_exec¿¡¼­ ¹ÝȯÇÏ´Â °ª°ú µ¿ÀÏÇϸç, query°¡ NULLÀ̰ųª nargs < 0 À̰ųª, nargs >0 && argtypes °¡ NULLÀÏ °æ¿ì¿¡´Â SPI_ERROR_ARGUMENT°¡ ¼¼Æ®µÈ´Ù´Â Á¡¸¸ ´Ù¸£´Ù.

     

    SPI_saveplan

    void  *SPI_saveplan (void *plan) ;

    ÀÌ ÇÔ¼ö´Â SPI_prepare¿¡¼­ ¼ö¸³µÈ °èȹÀ» ¾ÈÀüÇÑ ¿µ¿ª¿¡ ÀúÀåÇÑ´Ù. °èȹÀÌ ¹é¾÷µÇ´Â ¿µ¿ªÀº SPI_finish ³ª Æ®·£Àè¼Ç °ü¸®ÀÚÀÇ ¿µÇâÀ» ¹ÞÁö ¾Ê´Â º¸È£ ±¸¿ªÀÌ´Ù. ÀÌÈÄÀÇ SPI ¹öÀü¿¡¼­´Â ¼ö¸³µÈ °èȹÀ» ½Ã½ºÅÛ Ä«Å»·Î±×(µ¥ÀÌÅÍ »çÀü)¿¡ ÀúÀåÇϰųª ºÒ·¯¿À´Â °ÍÀÌ °¡´ÉÇØÁú °ÍÀ¸·Î º¸ÀδÙ. ¼ö¸³µÈ °èȹÀº SPI_execp ÇÔ¼ö¸¦ »ç¿ëÇÏ¿© ¼öÇàÇÒ ¼ö ÀÖ´Ù. ¹Ýȯ°ªÀ» ½ÇÆнÿ¡´Â NULLÀ» ¹ÝȯÇÏ°í, ¼º°ø½Ã¿¡´Â ÀúÀåµÈ ¸Þ¸ð¸® À§Ä¡¸¦ µ¹·ÁÁØ´Ù. Àü¿ª º¯¼ö SPI_result¿¡ ¼¼Æ®µÇ´Â °ªÀº ´ÙÀ½°ú °°´Ù.

      SPI_ERROR_ARGUMENT        : plan ÀÌ NULL ÀÏ °æ¿ì
      SPI_ERROR_UNCONNECTED  : ÇÁ·Î½ÃÀú°¡ SPI °ü¸®ÀÚ¿Í ¿¬°áµÇÁö ¾Ê¾ÒÀ» ¶§

    ÁÖÀÇ : ÁغñµÈ °èȹÀÌ ÂüÁ¶ÇÏ´Â Å×À̺íÀ̳ª ÇÔ¼ö µîÀÇ °´Ã¼Áß Çϳª°¡, »ç¿ëÀÚÀÇ ½ÇÇà ¼¼¼Ç µ¿¾È¿¡ »ç¶óÁø´Ù¸é SPI_execp ÀÇ °á°ú´Â ¿¹ÃøÇÒ ¼ö ¾ø°Ô µÉ °ÍÀÌ´Ù.

     

    SPI_execp

    int SPI_execp (void *plan, Datum *values, char *nulls, int tcount) ;

    ÀÌ ÇÔ¼ö´Â ÁغñµÈ °èȹÀ̳ª SPI_saveplan ÀÌ ¹ÝȯÇÑ °èȹÀ» ½ÇÇàÇÑ´Ù. ÇÔ¼öÀÇ ÀÎÀÚÁß planÀº ½ÇÇàÇÒ °èȹÀ̸ç, values´Â ½ÇÁ¦ ¸Å°³ ÀÎÀÚÀÇ °ªÀ̸ç, nulls´Â ¸Å°³ÀÎÀÚ°¡ NULLÀ» °¡Áö´Â °ÍÀ» Çã¿ëÇÒ °ÍÀΰ¡¸¦ ¼³¸íÇÏ´Â ¹è¿­ÀÌ´Ù. nulls°¡ 'n' À̸é NULL ÀÌ Çã¿ëµÇ°í, ' ' À̸é NULL ÀÌ Çã¿ëµÇÁö ¾Ê´Â´Ù. tcount ´Â °èȹÀÌ ½ÇÇàµÈ °á°ú·Î µ¹·Á¹ÞÀ» Æ©ÇÃÀÇ °¹¼ö¸¦ ÁöÁ¤ÇÑ´Ù. plan ÀÌ NULL À̰ųª tcount <0 À̸é SPI_ERROR_ARGUMENT¸¦ µ¹·ÁÁÖ°í, values °¡ NULL ÀÌ°í planÀÇ ¸Å°³ÀÎÀÚ¿Í ½ÇÁ¦ ¸Å°³ÀÎÀÚÀÎ values °¡ ¸ÂÁö ¾Ê´Â´Ù¸é SPI_ERROR_ARGUMENT¸¦ µ¹·ÁÁØ´Ù. ±× ¿Ü¿¡´Â SPI_exec¿Í µ¿ÀÏÇÏ´Ù. ±× ¿Ü¿¡ SPI_execp ÀÇ °á°ú¿¡ µû¶ó SPI_tuptable Àº ¹ÝȯµÈ ½ÇÁ¦ Æ©ÇÃÀÇ °ªÀ¸·Î ¼³Á¤µÇ°í, SPI_processed´Â ¹ÝȯµÈ Æ©ÇÃÀÇ °¹¼ö¸¦ ÀúÀåÇÏ°Ô µÈ´Ù. nulls°¡ NULL À̸é SPI_execp ´Â ½ÇÁ¦ ¸Å°³ÀÎÀÚÀÇ ¸ðµç °ªµéÀÌ NOT NULLÀ̶ó°í °¡Á¤ÇÑ´Ù.

    ÁÖÀÇ : ÁغñµÈ °èȹÀÌ ÂüÁ¶ÇÏ´Â Å×À̺íÀ̳ª ÇÔ¼öµîÀÇ °´Ã¼ Áß Çϳª°¡, »ç¿ëÀÚÀÇ ½ÇÇà ¼¼¼Çµ¿¾È¿¡ »ç¶óÁø´Ù¸é SPI_execpÀÇ °á°ú´Â ¿¹ÃøÇÒ ¼ö ¾ø°Ô µÉ °ÍÀÌ´Ù.

    ´ÙÀ½ ÇÔ¼öºÎÅÍ´Â ½ÇÁ¦·Î Æ©ÇÃÀ» ´Ù·ç´Âµ¥ »ç¿ëÇÏ´Â À¯Æ¿¸®Æ¼ÀÌ´Ù.

     

    [index]ÀÇ ÇüÅ·Π»ç¿ëÇϴµ¥, ÁַΠȸ¼öµÈ Æ©ÇÃÀÇ °ªÀ» ¾ò±â À§ÇØ ¸¹ÀÌ »ç¿ëµÈ´Ù. HeapTuple Àº ÇϳªÀÇ Æ©ÇÃÀ» ¼³¸íÇÏ´Â ÀÚ·áÇüÀÌ´Ù. ¿©±â¿¡¼­ ¶Ç Áß¿äÇÑ ±¸Á¶Ã¼°¡ TupleDesc ÀÌ´Ù. ÀÌ ±¸Á¶Ã¼´Â PostgreSQL ÀÇ ¼Ò½º¸¦ Ǭ µð·ºÅ丮¸¦ ±âÁØÀ¸·Î src/include/access/tupdesc.h ¿¡ Á¤ÀǵǾî ÀÖ´Ù.

      typedef struct tupleDesc
      {
         /* Æ©Çÿ¡¼­ ¼Ó¼ºÀÇ °³¼ö */
         int     natts ;
         /* attrs [N]Àº ¼Ó¼º ¹øÈ£ N+1ÀÇ ±â¼úÀÚ¿¡ ´ëÇÑ Æ÷ÀÎÅÍÀÌ´Ù. */
         AttributeTupleForm *attrs ;
         TupleConstr *constr ;
      } *TupleDesc ;

    TupleDesc ±¸Á¶Ã¼´Â SPI_getvalue µîÀÇ ÇÔ¼ö¿¡¼­ Æ©Çà ±â¼úÀÚÀÇ ÀÎÀÚ·Î »ç¿ëµÇ¸ç, TupleDesc->natts ´Â ÇØ´ç Æ©ÇÃÀÇ ¼Ó¼ºÀÇ °³¼ö¸¦ È®ÀÎÇϴµ¥ »ç¿ëµÈ´Ù.

     

    SPI_copytuple

    HeapTuple SPI_copytuple (HeapTuple tuple) ;

    ÀÌ ÇÔ¼ö´Â »óÀ§ ½ÇÇà±â ¼öÁØ¿¡¼­Æ©ÇÃÀ» º¹»çÇÑ´Ù. ÀÔ·Â °ªÀº º¹»çÇÒ Æ©ÇÃÀÌ°í ¹Ýȯ °ªÀº º¹»çµÈ Æ©ÇÃÀÌ´Ù. ÀÔ·Â °ªÀÎ tupleÀÌ NULLÀÏ °æ¿ì ¹Ýȯ °ªÀº NULLÀÌ°í, ±× ¿ÜÀÇ °æ¿ì¿¡´Â NOT NULL ÀÌ´Ù.

     

    SPI_modifytuple

    HeapTuple SPI_modifytuple (Relation rel, HeapTuple tuple, int nattrs,int *attnum,
    >> *values, chr *nulls) ;

    ÀÌ ÇÔ¼ö´Â »óÀ§ ½ÇÇà±â ¼öÁØ¿¡¼­ Å×À̺íÀÇ Æ©ÇÃÀ» ¼öÁ¤ÇÑ´Ù. rel°ú tupleÀº ¼öÁ¤µÉ ÀÔ·Â Æ©ÇÃÀ» ÁöÁ¤ÇÏ°í, nattrs ´Â attnum¿¡ Æ÷ÇԵǾî ÀÖ´Â ¼Ó¼º¹øÈ£ÀÇ °³¼öÀÌ´Ù. attnumÀº ¼öÁ¤ÇÒ ¼Ó¼º¹øÈ£·Î ÀÌ·ç¾îÁø ¹è¿­À̸ç, values´Â ÀÌÀüÀÇ °ªÀ» ´ëüÇÒ »õ·Î¿î °ªÀ̸ç, nulls´Â ¼Ó¼ºÀÌ NULL ÀÏ ¼ö Àִ°¡¸¦ ¼³¸íÇÑ´Ù. ¹Ýȯ°ªÀº NULLÀÌ µÇ°í, tuple ÀÌ NULL ÀÌ ¾Æ´Ï°í ¼öÁ¤ÀÌ ¼º°øÇÏ¿´À» °æ¿ì¿¡´Â NOT NULL ÀÌ µÈ´Ù.

    ÀÌ ÇÔ¼öÀÇ ÀÚ¼¼ÇÑ °á°ú´Â Àü¿ª º¯¼öÀÎ SPI_result ¿¡ ÀúÀåµÈ´Ù. rel ÀÌ NULL À̰ųª tupleÀÌ NULLÀ̰ųª natts<=0 À̰ųª attnum ÀÌ NULLÀ̰ųª values °¡ NULL À̸é SPI_result ÀÇ °ªÀº SPI_ERROR_ARGUMENT °¡ µÈ´Ù. attnum¿¡¼­ À¯È¿ÇÏÁö ¾ÊÀº ¼Ó¼º ¹øÈ£°¡ ÀÖÀ» °æ¿ì(attnumÀÌ 0º¸´Ù À۰ųª Æ©ÇÃÀÇ ¼Ó¼º °³¼öº¸´Ù Ŭ °æ¿ì) ¿¡´Â SPI_ERROR_NOAT_TRIBUTE ·Î ¼¼Æ®µÈ´Ù. ¾ÖÃÊ¿¡ Àü´ÞµÈ Æ©ÇÃÀº ÀÌ ÇÔ¼ö ¼öÇàÀÌÈÄ¿¡µµ º¯È­ÇÏÁö ¾Ê´Â´Ù.

     

    SPI_fnumber

    int SPI_fnumber (TupleDesc tupdesc, char *fname) ;

    ÀÌ ÇÔ¼ö´Â ÁöÁ¤ÇÑ ¼Ó¼ºÀÇ ¼Ó¼º¹øÈ£¸¦ µ¹·ÁÁØ´Ù. fnameÀº ãÀ» ¼Ó¼ºÀÇ À̸§ÀÌ°í, tupdesc´Â ÀÔ·Â Æ©Çà ±â¼úÀÚÀÌ´Ù. ¹Ýȯ°ªÀº ÇØ´ç ¼Ó¼ºÀÇ ¹øÈ£ÀÌ´Ù. fname À¸·Î ÁöÁ¤ÇÑ ¼Ó¼ºÀÌ ¾øÀ» °æ¿ì¿¡´Â SPI_ERROR_NOATTRIBUTE¸¦ µ¹·ÁÁÖ¸ç, ¼Ó¼º¹øÈ£´Â 1ºÎÅÍ ½ÃÀÛÇÑ´Ù.

     

    SPI_fname

    char *SPI_fname (TupleDesc tupdesc, int fnumber) ;

    ÀÌ ÇÔ¼ö´Â ÁöÁ¤ÇÑ ¼Ó¼ºÀÇ ¼Ó¼º À̸§À» µ¹·ÁÁØ´Ù. fnumber´Â ãÀ» ¼Ó¼ºÀÇ ¹øÈ£ÀÌ°í, tupdesc´Â ÀÔ·Â Æ©Çà ±â¼úÀÚÀÌ´Ù. ¹Ýȯ °ªÀº ÇØ´ç ¼Ó¼ºÀÇ À̸§ÀÌ´Ù. fnumber°¡ ¹üÀ§¸¦ ¹þ¾î³ª¸é NULLÀÌ ¹ÝȯµÇ°í, ¿¡·¯½Ã¿¡´Â SPI_resultÀü¿ª º¯¼ö°¡ SPI_ERROR_NOATTRIBUTE ·Î ¼³Á¤µÈ´Ù. ¼º°ø½Ã¿¡ ¹ÝȯµÇ´Â ¼Ó¼º À̸§Àº »õ·Î¿î ¸Þ¸ð¸®¿¡ ÇÒ´çµÈ º¹»çº»ÀÌ´Ù.

     

    SPI_getvalue

    char *SPI_getvalue (HeapTuple tuple, TupleDesc tupdesc, int fnumber) ;

    ÀÌ ÇÔ¼ö´Â ÁöÁ¤ÇÑ ¼Ó¼ºÀÇ °ªÀ» ¹®ÀÚ¿­·Î ¹ÝȯÇÑ´Ù. tuple Àº °ªÀ» ¾ò¾î³¾ ÀÔ·Â Æ©ÇÃÀÌ°í, tupdesc´Â ÀÔ·Â Æ©ÇÃÀÇ ±â¼úÀÚÀÌ´Ù. fnumber´Â ¼Ó¼º¹øÈ£ÀÌ´Ù. ¹Ýȯ °ªÀº ¼º°øÀûÀÏ °æ¿ì¿¡´Â ¼Ó¼º °ªÀ̸ç, ±× ¿ÜÀÇ °æ¿ì¿¡´Â NULLÀÌ´Ù. ÀÌ °æ¿ì¿¡ ÀÚ¼¼ÇÑ »óÅ °ªÀº SPI_result ¿¡ ¼³Á¤µÈ´Ù. fnumber °¡ ¹üÀ§¸¦ ¹þ¾î³ª¸é SPI_ERROR_NOATTRIBUTE ·Î ¼³Á¤µÇ¸ç, Ãâ·Â ÇÔ¼ö°¡ À¯È¿ÇÏÁö ¾Ê´Ù¸é SPI_ERROR_NOOUTFUNC ·Î ¼³Á¤µÈ´Ù. ¼º°ø½Ã¿¡ ¹ÝȯµÈ ¼Ó¼º °ªÀº »õ·Î¿î ¸Þ¸ð¸®¿¡ ÇÒ´çµÈ º¹»çº»ÀÌ´Ù.

     

    SPI_getbinval

    Datum SPI_getbinval (HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool *isnull) ;

    ÀÌ ÇÔ¼ö´Â ÁöÁ¤ÇÑ ¼Ó¼ºÀÇ °ªÀ» ÀÌÁø°ªÀ¸·Î µ¹·ÁÁØ´Ù. tupleÀº °ªÀ» ¾ò¾î³¾ ÀÔ·Â Æ©ÇÃÀÌ°í, tupdesc´Â ÀÔ·Â Æ©ÇÃÀÇ ±â¼úÀÚÀÌ´Ù. fnumber´Â ¼Ó¼º ¹øÈ£ÀÌ´Ù. ¹Ýȯ°ªÀº ¹ÙÀ̳ʸ® °ªÀ¸·Î, ¹Ýȯ °ªÀ» À§Çؼ­ »õ·Î¿î °ø°£À» ÇÒ´çÇÏÁö ¾Ê´Â´Ù´Â Á¡¿¡ ÁÖÀÇÇØ¾ß ÇÑ´Ù. ¸¸ÀÏ ¼Ó¼º°ªÀÌ NULL ÀÏ °æ¿ì¿¡ isnull ÀÌ 1·Î ¼³Á¤µÈ´Ù. fnumber °¡ ¹üÀ§¸¦ ¹þ¾î³ª¸é SPI_result ´Â SPI_ERROR_NOATTRIBUTE·Î ¼³Á¤µÈ´Ù.

     

    SPI_gettype

    OID *SPI_gettype (TupleDesc tupdesc, int fnumber) ;

    ÀÌ ÇÔ¼ö´Â ÁöÁ¤ÇÑ ¼Ó¼ºÀÇ Å¸ÀÔ À̸§ÀÇ º¹»çº»À» ¹ÝȯÇÑ´Ù. tupdesc´Â Æ©Çà ±â¼úÀÚÀÌ°í, fnumber ´Â ¼Ó¼º ¹øÈ£ÀÌ´Ù. ¹Ýȯ°ªÀº ¹øÈ£·Î ÁöÁ¤ÇÑ ¼Ó¼ºÀÇ Å¸ÀÔ À̸§ÀÌ´Ù. ¼Ó¼º ¹øÈ£°¡ ¾Ë¸ÂÁö ¾ÊÀ» °æ¿ì¿¡ SPI_result ´Â SPI_ERROR_NOATTRIBUTE·Î ¼³Á¤µÈ´Ù.

     

    SPI_gettypeid

    OID SPI_gettypeid (TupleDesc tupdesc, int fnumber) ;

    ÀÌ ÇÔ¼ö´Â ÁöÁ¤ÇÑ ¼Ó¼ºÀÌ Å¸ÀÔ ¾ÆÀ̵𸦠¹ÝȯÇÑ´Ù. ¼Ó¼º ¹øÈ£°¡ ¾Ë¸ÂÁö ¾ÊÀ» °æ¿ì¿¡ SPI_result °ªÀÌ »ó±â¿Í °°ÀÌ ¼³Á¤µÈ´Ù.

     

    SPI_getrelname

    char *SPI_getrelname (Relation rel) ;

    ÀÌ ÇÔ¼ö´Â ÁöÁ¤ÇÑ Å×À̺íÀÇ À̸§À» ÇѺΠº¹»çÇؼ­ µ¹·ÁÁØ´Ù. relÀº ÀÔ·Â Å×À̺íÀ» ³ªÅ¸³½´Ù.

     

    SPI_palloc

    void *SPI_palloc (Size size) ;

    ÀÌ ÇÔ¼ö´Â »çÀ§ ½ÇÇà±â ¼öÁØ¿¡¼­ ¸Þ¸ð¸®¸¦ ÇÒ´çÇÑ´Ù. size´Â ÇÒ´çÇÒ °ø°£À» ÁöÁ¤ÇÏ´Â 8 Áø¼öÀ̾î¾ß ÇÑ´Ù. ¹°·Ð ¹Ýȯ°ªÀº »õ·Ó°Ô ÇÒ´çÇÑ ¸Þ¸ð¸®ÀÇ ÁÖ¼ÒÀÌ´Ù.

     

    SPI_repalloc

    void *SPI_repalloc (void *pointer, Size size) ;

    ÀÌ ÇÔ¼ö´Â »óÀ§ ½ÇÇà±â ¼öÁØ¿¡¼­ ¸Þ¸ð¸®¸¦ ´Ù½Ã ÇÒ´çÇÑ´Ù. pointer´Â ÀÌ¹Ì Á¸ÀçÇÏ´Â ¸Þ¸ð¸® ÁÖ¼ÒÀÌ°í, Size´Â »õ·Ó°Ô ÇÒ´çÇÒ ¸Þ¸ð¸®ÀÇ Å©±â¸¦ 8 Áø¼ö·Î ÁöÁ¤ÇÑ °ÍÀ̾î¾ß ÇÑ´Ù. ¹Ýȯ °ªÀº ´ç¿¬È÷ ÀÌ¹Ì Á¸ÀçÇÏ´Â ¸Þ¸ð¸®¿¡ ´ã±ä ³»¿ëÀ» º¹»çÇÑ ³»¿ëÀ» ´ã°í ÀÖ´Â ÁöÁ¤ÇÑ Å©±âÀÇ °ø°£ÀÇ ÁÖ¼ÒÀÌ´Ù.

     

    SPI_pfree

    void SPI_pfree (void *pointer) ;

    ÀÌ ÇÔ¼ö´Â »óÀ§ ½ÇÇà±â ¼öÁØ¿¡¼­ ¸Þ¸ð¸®¸¦ ÇØÁ¦ÇÑ´Ù. pointer´Â ÇØÁ¦ÇÒ ¸Þ¸ð¸® ÁÖ¼ÒÀÌ´Ù.

     

SPI¿¡¼­ ¸Þ¸ð¸® °ü¸®

    µ¥ÀÌÅͺ£À̽º ¼­¹ö´Â ¸Þ¸ð¸®¸¦ ÇÒ´çÇÒ ¶§ »óÈ£ ¹®¸ÆÀÌ ¿µÇâÀ» ¹ÞÁö ¾Êµµ·Ï µ¶¸³ÀûÀ¸·Î ÇÒ´çÇÑ´Ù. Áï, ÇϳªÀÇ ¹®¸Æ¿¡¼­ ¸Þ¸ð¸®¸¦ ÇØÁ¦µÇ´Â °ÍÀº ´Ù¸§ ¹®¸Æ¿¡ ¿µÇâÀ» ÁÖÁö ¾Ê´Â´Ù´Â À̾߱â´Ù. µû¶ó¼­ ÇöÀçÀÇ ¹®¸ÆÀÌ ¾Æ´Ñ ´Ù¸¥ ¹®¸Æ¿¡ ´ëÇÑ ¸Þ¸ð¸® ÇØÁ¦´Â ¿¹ÃøÇÒ ¼ö ¾ø´Â °á°ú¸¦ ¾ß±âÇÒ ¼ö ÀÖ´Ù. SPI ÇÁ·Î½ÃÀú´Â µÎ °³ÀÇ ¸Þ¸ð¸® ¹®¸Æ°ú °ü·ÃÀÌ ÀÖ´Ù. »óÀ§ ½ÇÇà±â ¸Þ¸ð¸® ¹®¸Æ°ú ÇÁ·Î½ÃÀú ¸Þ¸ð¸® ¹®¸ÆÀÌ ±×°ÍÀÌ´Ù. ÀÌ·¯ÇÑ µÎ °³ÀÇ ¸Þ¸ð¸® ¹®¸Æ¿¡¼­ º¯È¯Àº SPI °ü¸®ÀÚÀÇ ¸Þ¸ð¸® °ü¸®¿¡ ÀÇÇØ ÀÌ·ç¾îÁø´Ù.

    SPI °ü¸®ÀÚ¿¡ Á¢¼ÓÇϱâ ÀÌÀüÀº »óÀ§ ½ÇÇà±â ¹®¸Æ¿¡ ³õ¿©Áö°Ô µÇ°í, ¸ðµç ¸Þ¸ð¸® ÇÒ´çÀº ÇÁ·Î½ÃÀú ±× Àڽſ¡ ÀÇÇØ palloc/repalloc¸¦ ÅëÇϰųª SPI À¯Æ¿¸®Æ¼ ÇÔ¼ö¸¦ ÅëÇؼ­ ÀÌ·ç¾îÁø´Ù. SPI_connect °¡ È£ÃâµÈ ÀÌÈÄ¿¡´Â ÇÁ·Î½ÃÀú ¹®¸Æ¿¡ ³õ¿©Áö°Ô µÇ°í, ÀÌÈÄÀÇ ¸ðµç ¸Þ¸ð¸® ÇÒ´çÀº palloc/repalloc ¶Ç´Â SPI À¯Æ¿¸®Æ¼ ÇÔ¼ö(SPI_copytuple, SPImodifytuple, SPI_palloc, SPI_repalloc ´Â Á¦¿ÜµÈ´Ù.)¸¦ ÅëÇØ ÀÌ·ç¾îÁø´Ù. SPI °ü¸®ÀÚ¿Í ¿¬°áÀ» ²÷°Ô µÇ¸é ÇöÀçÀÇ ¹®¸ÆÀº »óÀ§ ½ÇÇà±â ¹®¸ÆÀ¸·Î º¹±ÍÇÏ°Ô µÇ¸ç, ÇÁ·Î½ÃÀú ¸Þ¸ð¸® ¹®¸Æ¿¡¼­ ÇÒ´çµÈ ¸ðµç ¸Þ¸ð¸®´Â ÇØÁ¦µÇ°í ´õ ÀÌ»ó »ç¿ëÇÒ ¼ö ¾ø°Ô µÈ´Ù. »óÀ§ ½ÇÇà±â·Î ¾î¶°ÇÑ °ÍÀ» µÇµ¹¸±·Á¸é »óÀ§ ¹®¸Æ¿¡¼­ À̸¦ À§ÇÑ ¸Þ¸ð¸®¸¦ ÇÒ´çÇØ¾ß ÇÑ´Ù. SPI´Â »óÀ§ ½ÇÇà±â ¹®¸Æ¿¡¼­ ÇÒ´çµÈ ¸Þ¸ð¸®¸¦ ÀÚµ¿ÀûÀ¸·Î ÇØÁ¦ ÇØÁÖÁö´Â ¾Ê´Â´Ù. ÇÏÁö¸¸ SPI´Â ÁúÀÇÀÇ ½ÇÇà µµÁß¿¡ ÇÒ´çµÈ ¸Þ¸ð¸®´Â ÁúÀÇ°¡ ¿Ï·áµÇ¸é ÀÚµ¿À¸·Î ÇØÁ¦ÇØÁØ´Ù.

     

µ¥ÀÌÅͺ¯È­ÀÇ °¡½Ã¼º ±ÔÄ¢

    PostgreSQL ¿¡¼­ÀÇ °¡½Ã¼º ±ÔÄ¢Àº »ó½ÄÀûÀÎ ¼öÁØÀ» Å©°Ô ¹þ¾î³ªÁö ¾Ê´Â´Ù. °¡½Ã¼º ±ÔÄ¢Àº ÇÁ·Î½ÃÀú ³»ºÎ¿¡¼­ ÁúÀÇ°¡ ó¸®µÉ ¶§¿¡ Áß¿äÇÑ Àǹ̸¦ Áö´Ñ´Ù. Áß¿äÇÑ Àǹ̶ó±â º¸´Ù´Â ÀÛ¾÷Çϱ⿡ µû¶ó¼­ »ç¿ëÀÚÀÇ »ý°¢°ú´Â ´Ù¸£°Ô ÀÛµ¿ÇÒ ¼ö ÀÖ´Ù´Â °ÍÀ» ÀǹÌÇÑ´Ù. ÇÏÁö¸¸ ¸Å¿ì ±ÔÄ¢ÀûÀ̱⠶§¹®¿¡ ³í¸®ÀûÀ¸·Î Àß Ãß·ÐÇÏ¸é ¾Æ¹« ÀÌ»óÀÌ ¾ø´Ù.
    PostgreSQL¿¡¼­ ÁúÀÇ°¡ ½ÇÇàµÇ´Â µµÁß¿¡ ÁúÀÇ ±× ÀÚü¿¡ ÀÇÇØ ÀÌ·ç¾îÁø º¯È­´Â ÁúÀÇ °Ë»ö±â¿¡ ³ªÅ¸³ªÁö ¾Ê´Â´Ù. ÀÌ·¯ÇÑ º¯È­´Â ÁÖ·Î SQL ÇÔ¼ö³ª SPI ÇÔ¼ö, ¶Ç´Â Æ®¸®°Å¿¡ ÀÇÇØ ÁÖ·Î ÀÌ·ç¾îÁø´Ù. °¡·É ¿¹¸¦ µé¾îº¸¸é, "INSERT INTO a SELECT * FROM a" ÁúÀÇ¿¡ ÀÇÇØ »ðÀÔµÈ Æ©ÇÃÀº SELECT °Ë»ö½Ã¿¡ ³ªÅ¸³ªÁö ¾Ê´Â´Ù. Àá½Ã ¼³¸íÀ» ÇÏÀÚ¸é, ÀÌ ÁúÀÇ´Â ÀÚ½ÅÀÇ Å×À̺íÀÇ ³»¿ëÀ» ±×´ë·Î ´Ù½Ã º¹»çÇÑ´Ù. ¹°·Ð Àç±Í´Â ÇÏÁö ¾ÊÀ¸¸ç, unique À妽º ±ÔÄ¢ÀÌ ÀÖ´Ù¸é ÀÌ¿¡ µû¸¥´Ù. ÁúÀÇ AÀÇ ½ÇÇà µµÁß¿¡ »ý¼ºµÇ´Â º¯È­´Â ÁúÀÇ A ÀÌÈÄ¿¡ ½ÃÀÛÇÏ´Â ÁúÀÇ¿¡¼­´Â ³ªÅ¸³­´Ù. ÇÏÁö¸¸ ÁúÀÇ A°¡ ½ÇÇàµÇ°í ÀÖ´Â µµÁß¿¡´Â ¾Æ¹«·± Àϵµ ¾ø´Â °Íó·³ º¸ÀδÙ.

     

 SPIÀÇ ¿¹Á¦

    ÀÌÁ¦ SPI ÀÎÅÍÆäÀ̽º ÇÔ¼ö¸¦ »ç¿ëÇÏ¿© Å×½ºÆ®¸¦ À§ÇÑ ÇÔ¼ö¸¦ ¸¸µé¾î º¸ÀÚ. Àß ÀÌÇØÇÏ·Á¸é ²Ä²ÄÈ÷ ì°ÜºÁ¾ß ÇÒ °ÍÀÌ´Ù. SPI °¡ ¾ÆÁÖ À¯¿ëÇϱä ÇÏÁö¸¸ °ü·ÃµÇ´Â µ¥ÀÌÅÍ Å¸ÀÔ°ú Àü¿ª º¯¼ö, SPI ÇÔ¼ö, SPI »ó¼öµéÀ» ÁÖÀDZí°Ô »ìÆìºÁ¾ß ÇÒ °ÍÀ̸ç, °¡½Ã¼º ±ÔÄ¢¿¡ µû¸¥ °á°ú¿¡µµ ÁÖÀǸ¦ ±â¿ï¿©¾ß ÇÑ´Ù.

     

    #include <stdio.h>
    #include  "executor/spi.h"  /* SPI ÇÔ¼ö¸¦ À§ÇÑ Çì´õ ÆÄÀÏ */
    int execq (text *sql, int cnt) ;
    int execq (text *sql, int cnt) {
       int ret ;
       int proc = 0 ;
       SPI_connect () ;   /* ¸ÕÀú SPI °ü¸®ÀÚ¿¡ Á¢¼ÓÇÑ´Ù */
       /* textout ³»ºÎÇÔ¼ö´Â  text *¸¦ char *·Î º¯È¯ÇÑ´Ù. SPI ¿¡¼­ ±âº» ¹®ÀÚ¿­ÇüÀº
           text ÇüÀ¸·Î, psql¿¡¼­ ÀÔ·ÂÇÏ´Â ¹®ÀÚ¿­Àº text *·Î ¼­¹ö¿¡°Ô Àü´ÞµÈ´Ù. */
       ret = SPI_exec (textout(sql), cnt) ; /* execq ÇÔ¼ö¿¡ Àü´ÞµÇ´Â ÁúÀÇÀÎ sqlÀ»
                                                            ½ÇÇàÇÑ´Ù. */
       proc = SPI_processed ; /* SPI_processed ¿¡´Â ó¸®µÈ Æ©ÇÃÀÇ °¹¼ö°¡
                                             ÀúÀåµÈ´Ù. */
       /* SELECT °¡ ¼º°øÇÏ¿´°í, ¹ÝȯµÈ Æ©ÇÃÀÌ 0°³¸¦ ÃÊ°úÇÑ´Ù¸é */
       if (ret == SPI_OK_SELECT && SPI_processed > 0)  {
          /* SPI_tutable->tupdesc´Â ÇöÀç Æ©Çà ¸®½ºÆ®¿¡ ´ëÇÑ ±â¼úÀÚÀÌ´Ù. */
          TupleDesc tupdesc = SPI_tuptable->tupdesc ;
          /* SPI_tuptable A>> tuptable·Î ¹é¾÷ÇÑ´Ù. */
          SPITuleTable *tuptable = SPI_tuptable ;
          char buf[8192] ;
          int I ;
          for (ret = 0 ; ret < proc ; ret++) {
             /* ÇϳªÀÇ Æ©Çõ¥ÀÌÅÍÇü¿¡ ȸ¼öµÈ Æ©ÇÃÀ» Çϳª¾¿ Â÷·Ê´ë·Î Áý¾î³Ö´Â´Ù. */
             HeapTuple tuple = tuptable->vals[ret] ;
             /* ÇϳªÀÇ Æ©Çÿ¡ ´ëÇØ °¢°¢ÀÇ ¼Ó¼ºÀÇ °ªÀ» Çϳª¾¿ ¾ò¾î³½´Ù. */
             /* tupdesc->natts SPI_tuptable->tupdesc->natts À̸ç, ÇØ´ç Æ©Çÿ¡¼­
                ¼Ó¼ºÀÇ °³¼öÀÌ´Ù. */
             for (i = 1, buf[0] = 0 ; I <= tupdesc->natts ; i++)
                sprintf(buf + strlen(buf), "%s%s",
                   SPI_getvalue(tuple, tupdesc, i),
                   (i == tupdesc->natts) ? " " : "|") ;
             /* ´õ ÀÌ»óÀÇ ¼Ó¼ºÀÌ ¾ø´Ù¸é °ø¹éÀ» Ãâ·ÂÇÏ°í,
                 ¾Æ´Ï¶ó¸é ÇÊµå ±¸ºÐÀÚ·Î |¸¦ Ãâ·ÂÇÑ´Ù. */
             /* ·Î±× ¸Þ½ÃÁö¸¦ Ãâ·ÂÇÑ´Ù. */
                elog(NOTICE, "EXECQ: %s", buf) ;
       }
          /* Á¢¼ÓÀ» Á¾·áÇÑ´Ù. */
          SPI_finish() ;
          /* ½ÇÁ¦·Î ó¸®µÈ Æ©ÇÃÀÇ °³¼ö°¡ ÇÔ¼öÀÇ ¹Ýȯ°ªÀÌ µÈ´Ù. */
          return proc ;
    }

     

    À§ ¼Ò½º ÆÄÀÏÀ» testspi.c·Î ÀúÀåÇÑ´Ù. ÀÏ´Ü ¿©±â¿¡¼­ °³º°ÀûÀÎ ³»¿ë¸¸ ÀÌÇØÇÏ°í ³Ñ¾î°¡ÀÚ. ÀüüÀûÀÎ ÁÙ±â´Â ½ÇÁ¦ »ç¿ë ¿¹¸¦ º¸¸é¼­ ÀÌÇØÇÏ´Â °ÍÀÌ ÁÁ´Ù. ¸ÕÀú À§ÀÇ ÇÔ¼ö¸¦ °øÀ¯ ¶óÀ̺귯¸®·Î ÄÄÆÄÀÏÀ» Çغ¸ÀÚ. Âü°í·Î C ÇÔ¼ö¸¦ °øÀ¯ ¶óÀ̺귯¸®·Î ÄÄÆÄÀÏÇϱâ À§Çؼ­´Â PostgreSQL °¡ ¼³Ä¡µÈ µð·ºÅ丮ÀÇ Çì´õÆÄÀÏ »Ó¸¸ÀÌ ¾Æ´Ï¶ó ¿øº» ¼Ò½º µð·ºÅ丮ÀÇ Çì´õÆÄÀϱîÁö ÇÊ¿äÇÏ´Ù. ÇÊÀÚÀÇ µð·ºÅ丮¿Í ¿©·¯ºÐÀÇ µð·ºÅ丮°¡ ´Ù¸¦ ¼ö ÀÖÀ¸¹Ç·Î Çì´õ ÆÄÀÏ ÂüÁ¶ µð·ºÅ丮´Â ¾Ë¾Æ¼­ ¼öÁ¤ÇÏÀÚ.

      $ gcc -c testspi.c -fPIC -I/usr/local/pgsql/include -I/usr/local/postgresql-6.3.1
          >> /src/include/
      $ gcc -shared -0 testspi.so testspi.0

    ÀÚÁÖ ÀÌ·¸°Ô ±ä ¸í·É ÇàÀ» ŸÀÌÇÎ ÇÏ´Â °ÍÀº Á¤½Å °Ç°­¿¡ ÇØ·Ó´Ù. °£´ÜÈ÷ ½ºÅ©¸³Æ®¸¦ ¸¸µé¾î¼­ ´ëüÇϵµ·Ï ÇÑ´Ù.

     

    # ! /bin/sh
    # name : funcom - Compiling Shared Object function for PostgreSQL
    CC=gcc
    PG_SRC_ROOT=/usr/local/postgersql-6.3.1/
    PG_INS_ROOT=/usr/local/pgsql/
    if [$# -le 0] ; then
       echo "usage : $0 <source>"
       exit
    fi
    PREFIX=${1%.*}
    $CC -c -o ${PREFIX}.o ${PREFIX}.c -fPIC -I${PG_INS_ROOT}/
       include -I${PG_SRC_ROOT}/src/include
    gcc -shared -o ${PREFIX}.so ${PREFIX}.o 

     

    ¾ÕÀ¸·Î´Â ´ÙÀ½°ú °°ÀÌ °£´ÜÇÏ°Ô ÄÄÆÄÀÏÇÑ´Ù.

      $ ./funcom testspi

    ÀÌÁ¦ ÇÔ¼ö¸¦ ¸¸µé¾îº¸ÀÚ. À̸§Àº execq·Î ÇÑ´Ù.

      $ psql -c "create function execq (text, int4) returns int4 as ''pwd'/testspi.so'
          >> language 'c' ; " mydb

    execq ÇÔ¼ö¸¦ Å×½ºÆ®Çϱâ Àü¿¡ execq ÇÔ¼ö¸¦ ÀüüÀûÀÎ ¾È¸ñ¿¡¼­ Àá½Ã »ìÆ캸ÀÚ. ù ¹ø° ifÀ¸·Î ÀÎÇØ SELECT ½Ã¿¡¸¸ execq ÀÇ ³ª¸ÓÁö ºÎºÐÀÌ ½ÇÇàµÈ´Ù. ¾Æ¿ï·¯ °Ë»öµÈ Æ©ÇÃÀÌ 0°³¸¦ ÃÊ°úÇÒ ¶§¿¡¸¸ ½ÇÇàµÈ´Ù´Â °ÍÀ» ¾Ë ¼ö ÀÖ´Ù. execq ÇÔ¼ö¿¡¼­ ¹ÝȯµÇ´Â °ªÀº SELECT ÁúÀÇ°¡ ó¸®ÇÏ´Â Æ©ÇÃÀÇ °³¼ö¿Í µ¿ÀÏÇÔÀ» ¾Ë ¼ö ÀÖ´Ù. ±×¸®°í for ·çÇÁ¾ÈÀ» º¸¸é ¸Å¹ø °¢°¢ÀÇ Æ©Çø¶´Ù ±× Ä®·³À» elog ÇÔ¼ö·Î Ãâ·ÂÇÔÀ» ¾Ë ¼ö ÀÖ´Ù. Áï, a ¶ó´Â Å×ÀÌºí¿¡ 2°³ÀÇ Æ©ÇÃÀÌ ÀÖ´Ù¸é execq('select * from a', 0)À» ½ÇÇàÇÏ¸é µÎ ¹øÀÇ »óÀ§ for ¹®ÀÌ ¼öÇàµÇ¾î µÎ °³ÀÇ ¾Ë¸²±ÛÀÌ Ãâ·ÂµÈ´Ù´Â °ÍÀ» ÁüÀÛÇÒ ¼ö ÀÖ´Ù. ÀÌÁ¦ SPI ÇÔ¼ö·Î ÀÛ¼ºÇÑ execqÇÔ¼ö¸¦ Å×½ºÆ® Çغ¸ÀÚ.

     

    mydb=> select execq('create table a (x int4)', 0) ;
    execq
    -----
          0
    (1 row)

    mydb=> insert into a values (execq('insert into a values (0)', 0) ;
    INSERT 167631 1
    mydb=> select execq('select * from a', 0) ;
    NOTICE : EXECQ :  0 <- execq°¡ »ðÀÔÇÑ °ÍÀÓ 
    NOTICE : EXECQ :  1 <- execq°¡ ¹ÝȯÇÏ°í »óÀ§ INSERT°¡ »ðÀÔÇÑ °ª

    execq
    -----
           2
    (1 row) 

    mydb=> select execq('insert into a select x + 2 from a', 1) ;
    execq
    -----
            1 
    (1 row)  

    mydb=> select execq('select * from a', 10) ;
    NOTICE : EXECQ : 0
    NOTICE : EXECQ : 1
    NOTICE : EXECQ : 2 <- 0+2, ù ¹ø° Æ©Çø¸ »ðÀԵǾúÀ½

    execq
    -----
           3    <- 10 °³°¡ Æ©ÇÃÀÇ ÃÖ´ë Ƚ¼ö Á¦ÇÑ °¹¼öÀε¥, 3°³°¡ ½ÇÁ¦ °¹¼öÀÓ
    (1 row)

    mydb=> delete from a ;
    DELETE 3
    mydb=> insert into a values (execq('select * from a', 0) +1) ;
    INSERT 167712 1
    mydb=> select * from a ;
    x
    -
    1           <<< (0) +1
    (1 row)

    mydb=> insert into a values (execq('select * from a', 0) +1) ; 
    NOTICE : EXECQ : 0
    INSERT 167713 1
    mydb=> select * from a ;
    x
    -
    1
    2              <- (1) +1
    (2 rows)

    -- º¯È­µÈ µ¥ÀÌÅÍÀÇ °¡½Ã¼º ±ÔÄ¢À» ¼³¸íÇÑ´Ù.

    mydb=> insert into a select execq('select * from a', 0) * x from a ; 
    NOTICE : EXECQ : 1
    NOTICE : EXECQ : 2
    NOTICE : EXECQ : 1
    NOTICE : EXECQ : 2
    NOTICE : EXECQ : 2
    INSERT 0 2
    mydb=> select * from a ;
    x
    -
    1
    2
    2            <<< 2°³ Æ©Çà * 1(ù¹ø° Æ©ÇÃÀÇ x°ª)
    6            <<< 3°³ Æ©Çà (¿ø·¡ÀÇ 2°³ + ¹æ±Ý ÀÔ·ÂµÈ 1°³) * 2(µÎ¹ø° Æ©ÇÃÀÇ x°ª), ¼­·Î ´Ù¸¥ ¼¼¼Ç¿¡¼­ execq() ÇÔ¼ö´Â º¯°æµÈ ³»¿ëÀ» º¼ ¼ö ÀÖ´Ù.
    (4 rows)

     

Æ®¸®°Å! ±× À̸§¸¸À¸·Îµµ ¼³·¹ÀÌ´Â ¸¶À½

    PostgreSQL ÀÇ ÇöÀç¹öÀü(6.3.1) ¿¡¼­´Â ´Ù¾çÇÑ ÀÎÅÍÆäÀ̽º·Î Perl °ú Tcl, Python, C µîÀ» Áö¿øÇÑ´Ù. ÇÏÁö¸¸ ¾ÆÁ÷ ½ÇÁ¦ ÇÁ·Î½ÃÀú ¾ð¾îÀÎ PL ¿¡´Â ¾àÁ¡À» °¡Áö°í ÀÖ´Ù. ¸ÖÁö ¾ÊÀº ¼¼¿ù¿¡ Á¦´ë·Î µÈ PL ¾ð¾î°¡ Áö¿øµÉ °ÍÀ¸·Î º¸ÀδÙ. ¹¹ ÇÏÁö¸¸ C ÇÔ¼ö¸¦ È£ÃâÇÏ¿© Æ®¸®°ÅÀÇ ¿ªÇÒÀ» ¼öÇàÇÏ´Â °ÍÀº ÇöÀç·Î¼­µµ °¡´ÉÇÏ´Ù. ±×·¡µµ ¾ÆÁ÷ ÁúÀǾî(±¸¹®/Àý)Â÷¿ø¿¡¼­´Â ¾ÆÁ÷ Æ®¸®°Å »ç°Ç¿¡ ´ëÇÑ Ã³¸®´Â Áö¿øÇÏÁö ¾Ê°í ÀÖ´Ù. Æ®¸®°Å »ç°Ç½ÃÀÇ ÇØ´ç Æ©Çÿ¡ ´ëÇØ INSERT, DELETE, UPDATE ½Ã¿¡ BEFORE ³ª AFTER ±¸¹®À» ÁöÁ¤ÇÏ¿© »ç¿ëÇÒ ¼ö ÀÖ´Ù. C ÇÔ¼ö ³»ºÎ¿¡¼­ÀÇ Æ®¸®°Å´Â ÁÖ·Î SPI ÇÔ¼ö¸¦ »ç¿ëÇÏ¿© 󸮵ȴÙ. SPI ¿Í Æ®¸®°Å¸¦ ¶ª·¡¾ß ¶ª ¼ö ¾ø´Â ÇϳªÀÇ ÀÌÀ¯ÀÌ´Ù.

     

Æ®¸®°ÅÀÇ »ý¼º

    Æ®¸®°Å »ç°ÇÀÌ ÀϾ¸é, Æ®¸®°Å °ü¸®ÀÚ°¡ ½ÇÇà±â¿¡ ÀÇÇØ È£ÃâµÇ¾î¼­ Àü¿ª ±¸Á¶Ã¼ÀÎ TriggerData *CurrentTriggerData¸¦ ÃʱâÈ­ÇÑ´Ù. ±×¸®°í »ç°ÇÀ» ó¸®Çϱâ À§ÇØ ÁöÁ¤ Æ®¸®°Å ÇÔ¼ö¸¦ È£ÃâÇÑ´Ù. Æ®¸®°Å ÇÔ¼ö´Â Æ®¸®°Å ÇÔ¼ö¸¦ µî·ÏÇϱâ Àü¿¡ ¸¸µé¾î¾ß Çϸç, Æ®¸®°Å ÇÔ¼ö´Â Àü´Þ ¸Å°³ ÀÎÀÚ°¡ ¾øÀ¸¸ç, opaque¸¦ ¹ÝȯÇϵµ·Ï ÇØ¾ß ÇÑ´Ù. Æ®¸®°ÅÀÇ »ý¼º ±¸¹®Àº ´ÙÀ½°ú °°´Ù.

      CREATE TRIGGER <Æ®¸®°Å À̸§> <BEFORE|AFTER>
      <INSERT|DELETE|UPDATE>
      ON <> FOR EACH <ROW|STATEMENT>
      EXECUTE PROCEDURRE <ÇÁ·Î½ÃÀú À̸§> (<ÇÔ¼öÀÎÀÚ>) ;

    Æ®¸®°ÅÀÇ À̸§Àº Æ®¸®°Å¸¦ Á¦°ÅÇÒ ¶§ »©°í´Â »ç¿ëÇÒ ÀÏÀÌ ¾øÀ» °ÍÀÌ´Ù. DROP TRIGGER ¸í·É¿¡¼­ Æ®¸®°Å À̸§ÀÌ ÀÎÀÚ·Î »ç¿ëµÈ´Ù.

    ±× ´ÙÀ½ÀÇ BEFORE, AFTER ´Â »ç°ÇÀÇ ¹ß»ý½ÃÁ¡À» ÁöÁ¤ÇÑ´Ù. Áï, »ç°ÇÀÌ ¹ß»ýÇÑ ÀÌÈÄ, ¶Ç´Â ÀÌÀü¿¡ Æ®¸®°Å ÇÔ¼ö¸¦ È£ÃâÇÒ °ÍÀÎÁö¸¦ ÁöÁ¤ÇÑ´Ù. ´ÙÀ½ÀÇ INSERT/DELETE/UPDATE ±¸¹®Àº ¾î¶² »ç°ÇÀÌ ÇÔ¼ö¸¦ Æ®¸®°ÅÇÒ °ÍÀÎÁö¸¦ ÁöÁ¤ÇÑ´Ù. ¿©·¯ °³ÀÇ »ç°ÇÀ» OR ¿¬»êÇÏ¿© ÇÔ²² ÁöÁ¤ÇÒ ¼ö ÀÖ´Ù. Å×À̺í À̸§Àº ÇØ´ç »ç°ÇÀÌ ¾î´À Å×ÀÌºí¿¡ Àû¿ëµÉ °ÍÀÎÁö¸¦ ÁöÁ¤ÇÑ´Ù.

    ´ÙÀ½ÀÇ FOR EACH ±¸¹®Àº Æ®¸®°Å°¡ Å×ÀÌºí¿¡ Àû¿ëµÉ ¶§, °¢°¢ÀÇ ·Î¿ì¸¶´Ù Àû¿ëÇÒ °ÍÀÎÁö, ¾Æ´Ï¸é Àüü ±¸¹® ´ÜÀ§·Î Àû¿ëÇÒ °ÍÀÎÁö¸¦ ÁöÁ¤ÇÑ´Ù. ÇÁ·Î½ÃÀú À̸§Àº È£ÃâÇÒ C ÇÔ¼öÀÇ À̸§ÀÌ´Ù. ÇÔ¼öÀÎÀÚ´Â CurrentTriggerData ±¸Á¶Ã¼ ³»¿¡ ÀÖ´Â ÇÔ¼ö·Î Àü´ÞµÈ´Ù. ÇÔ¼ö¿¡ ¸Å°³ ÀÎÀÚ¸¦ Àü´ÞÇÏ´Â ¸ñÀûÀº °°Àº ÇÔ¼ö¸¦ È£ÃâÇÏ´Â ¼­·Î À¯»çÇÑ ¿äûÀ» ó¸®ÇÏ´Â ´Ù¸¥ Æ®¸®°Å¸¦ Çã¿ëÇϱâ À§Çؼ­ ÀÌ´Ù. ¹°·Ð, ÇÔ¼ö´Â ¼­·Î ´Ù¸¥ Å×À̺íÀ» Æ®¸®°ÅÇÏ´Â µ¥ »ç¿ëµÈ´Ù. ÀÌ·¯ÇÑ ÇÔ¼ö´Â 'ÀÏ¹Ý Æ®¸®°Å ÇÔ¼ö'¶ó°í ºÎ¸¥´Ù.

    Æ®¸®°Å ÇÔ¼ö´Â ÀÚ½ÅÀ» È£ÃâÇÑ ½ÇÇà±â¿¡°Ô HeapTupleÀ» ¹ÝȯÇÒ ¼ö ÀÖ´Ù. ¸¸ÀÏ »ç°Ç ÀÌÈÄ¿¡ (AFTER) Æ®¸®°Å°¡ ¼öÇàµÇµµ·Ï Æ®¸®°Å¸¦ »ý¼ºÇß´Ù¸é, ½ÇÇà±â°¡ INSERT/DELETE/UPDATE¸¦ ¼öÇàÇÑ ÀÌÈÄ¿¡ Æ®¸®°Å ÇÔ¼ö¸¦ È£ÃâÇÏ°Ô µÈ´Ù. ÀÌ Æ®¸®°Å ÇÔ¼ö¿¡¼­ »ç¿ëÀÚ°¡ ¾î¶² Æ©ÇÃ(HeapTuple)À» ¹ÝȯÇÑ´Ù°í Çصµ ½ÇÇà±â ÀÔÀåÀ¸·Î º¼ ¶§´Â ÀÚ½ÅÀº ÀÏÀ» ´Ù ¸¶Ä£ ÀÌÈÄÀ̹ǷΠÇØ´ç Æ©ÇÃÀ» ¹«½ÃÇÑ´Ù. ÇÏÁö¸¸ BEFORE Æ®¸®°Å½Ã¿¡´Â À̾߱Ⱑ ´Þ¶óÁø´Ù. ¸ÕÀú ½ÇÇà±â´Â Àڽſ¡°Ô ¸Ã°ÜÁø Áß¿äÇÑ ÀÛ¾÷(INSERT/DELETE/UPDATE)À» ¼öÇàÇϱâ Àü¿¡ Æ®¸®°ÅÇÔ¼ö¸¦ ¸ÕÀú È£ÃâÇÑ´Ù. »ç¿ëÀÚÀÇ Æ®¸®°Å ÇÔ¼ö¿¡¼­ Àû´çÇÑ Æ©ÇÃÀÌ ¹ÝȯµÇ¸é, ±×°ÍÀ¸·Î ÀÚ½ÅÀÇ ÀÛ¾÷À» ¼öÇàÇÑ´Ù. Áï, »ç¿ëÀÚ°¡ ÀÛ¼ºÇÑ Æ®¸®°Å ÇÔ¼ö¿¡¼­ ¹«¾ùÀ» ³Ñ°ÜÁÖ´À³Ä¿¡ µû¶ó¼­ ½ÇÇà±â°¡ ÀÛ¾÷ÇÏ´Â ³»¿ëÀÌ ´Þ¶óÁø´Ù´Â °ÍÀÌ´Ù.

    Æ®¸®°Å ÇÔ¼ö¿¡¼­ NULLÀ» ¹ÝȯÇϸé, ½ÇÇà±â´Â ¹Ýȯ¹ÞÀº Æ©ÇÃÀÌ NULL À̹ǷΠ¾Æ¹«Àϵµ ÇÏÁö ¾Ê°í ³Ñ¾î°£´Ù. Áï, BEFORE Æ®¸®°Å¿¡¼­ INSERT ½Ã¿¡ NULLÀ» µ¹·ÁÁÖµµ·Ï ÇÏ¿´´Ù¸é, »ç¿ëÀÚ°¡ ÇØ´ç Å×ÀÌºí¿¡ INSERT ÇÏ´õ¶óµµ ½ÇÇà±âÀÇ ÀÛ¾÷¿¡¼­´Â INSERT µÇÁö ¾Ê´Â´Ù´Â °ÍÀÌ´Ù. Æ®¸®°ÅÀÇ ÀÛ¾÷¿¡¼­´Â INSERT¸¦ ÇÒ ¼ö ÀÖÀ» Áö´Â ¸ô¶óµµ. ¸¸ÀÏ BEFORE Æ®¸®°Å¿¡¼­ ´Ù¸¥ Æ©ÇÃÀ» ³Ñ°ÜÁشٸé(INSERT ¿Í UPDATE ½Ã¿¡¸¸ °¡´ÉÇÏ´Ù) ¿ø·¡ÀÇ Æ©Çà ´ë½Å¿¡ ¹ÝȯÇÑ Æ©ÇÃÀÌ »ðÀ﵃ °ÍÀÌ´Ù. ¹°·Ð UPDATE ½Ã¿¡´Â °»½ÅµÈ »õ·Î¿î Æ©ÇÃÀÌ µÉ °ÍÀÌ´Ù.

    PostgreSQLÀÇ ÇöÀç ¹öÀü¿¡¼­´Â Æ®¸®°ÅÀÇ È®À强¿¡¼­ Á¶±Ý ºÎÁ·ÇÑ µíÇÑ ºÎºÐÀÌ ÀÖ´Ù. Áï, CREATE TRIGGER ½Ã¿¡ Æ®¸®°ÅÀÇ ÃʱâÈ­°¡ ¼öÇàµÇÁö ¾Ê´Â´Ù´Â °ÍÀÌ´Ù. ¶ÇÇÑ, µ¿ÀÏÇÑ Å×À̺í»ó¿¡¼­ µ¿ÀÏÇÑ »ç°Ç¿¡ ´ëÇØ Çϳª ÀÌ»óÀÇ Æ®¸®°Å¸¦ Á¤ÀÇÇÒ ½Ã¿¡, Æ®¸®°ÅÀÇ ½ÇÇà ¼ø¼­´Â ¿¹ÃøÇÒ ¼ö ¾ø´Ù´Â °ÍÀÌ´Ù. ÀÌ·¯ÇÑ Á¡µéÀº ¾ÕÀ¸·Î º¸¿ÏµÉ °ÍÀÌ´Ù.

    Æ®¸®°Å ÇÔ¼ö°¡ SPI¸¦ »ç¿ëÇÏ¿© SQL ÁúÀǸ¦ ½ÇÇàÇϸé, ÀÌ ÁúÀÇ´Â ¶Ç´Ù½Ã Æ®¸®°ÅµÈ´Ù. ÀÌ·¯ÇÑ Æ®¸®°Å´Â 'Á¾¼Ó Æ®¸®°Å(cascading trigger)'¶ó ºÎ¸¥´Ù. Á¾¼Ó Ƚ¼öÀÇ ¸í½ÃÀûÀÎ Á¦ÇÑÀº ¾ø´Ù.

    Æ®¸®°Å°¡ INSERT »ç°Ç½Ã¿¡ ¼öÇàµÇ°í, µ¿ÀÏÇÑ Å×ÀÌºí¿¡ »õ·Î¿î Æ©ÇÃÀÌ »ðÀԵȴٸé, ÀÌ·¯ÇÑ Æ®¸®°Å´Â ´Ù½Ã Æ®¸®°ÅµÈ´Ù. ÇöÀç, ÀÌ·¯ÇÑ °æ¿ì¸¦ ´ëºñÇØ Á¦°øµÇ´Â µ¿±âÈ­ ±â´ÉÀº ¾ÆÁ÷ ¾øÁö¸¸, Á¶¸¸°£ Á¦°øµÉ °ÍÀ¸·Î º¸ÀδÙ.

     

Æ®¸®°Å °ü¸®ÀÚ¿ÍÀÇ Áñ°Å¿î ´ëÈ­

    À§¿¡¼­µµ ¾ð±ÞÇßµíÀÌ, Æ®¸®°Å °ü¸®ÀÚ¿¡ ÀÇÇØ ÇÔ¼ö°¡ È£ÃâµÇ¸é,
    TriggerData *CurrentTriggerData ±¸Á¶Ã¼´Â NOT NULL ÀÌ µÇ¸é¼­, ÃʱâÈ­µÈ´Ù. óÀ½¿¡ CurrentTriggerData °¡ NULL ÀÎÁö °Ë»çÇÏ´Â °ÍÀÌ ÁÁ´Ù.

    TriggerData ±¸Á¶Ã¼´Â src/include/commands/trigger.h¿¡ Á¤ÀǵǾî ÀÖ´Ù.

      typedef struct TriggerData
      {
         TriggerEvent  tg_event ;
         Relation  tg_relation ;
         HeapTuple  tg_trigtuple ;
         HeapTuple  tg_newtuple ;
         Trigger      *tg_trigger ;
       } TriggerData

    °¢°¢ÀÇ ¸â¹ö¸¦ Àá½Ã »ìÆ캸ÀÚ.

     

    tg_event

    ÀÌ ¸â¹ö´Â Æ®¸®°ÅÀÇ Á¾·ù¸¦ ¼³¸íÇϴµ¥ »ç¿ëµÈ´Ù. ¾Æ·¡ÀÇ ´Ù¾çÇÑ ¸ÅÅ©·Î¸¦ »ç¿ëÇÏ¿© tg_eventÀÇ Á¾·ù¸¦ È®ÀÎÇÒ ¼ö ÀÖ´Ù.

    TRIGGER_FIRED_BEFORE(event)        Æ®¸®°Å°¡ »ç°ÇÀÇ BEFORE½Ã¿¡ ¼öÇàµÈ´Ù¸é TRUE¹Ýȯ
    TRIGGER_FIRED_AFTER(event)          Æ®¸®°Å°¡ »ç°ÇÀÇ AFTER½Ã¿¡ ¼öÇàµÈ´Ù¸é TRUE¹Ýȯ
    TRIGGER_FIRED_FOR_ROW(event)     Æ®¸®°Å°¡ ¸Å ·Î¿ì¸¶´Ù ¼öÇàµÈ´Ù¸é TRUE¹Ýȯ
    TRIGGER_FIRED_FOR_STATEMENT(event)  Æ®¸®°Å°¡ ¸Å ±¸¹®¸¶´Ù ¼öÇàµÈ´Ù¸é TRUE¹Ýȯ
    TRIGGER_FIRED_BY_INSERT(event)    Æ®¸®°Å°¡ INSERT ½Ã¿¡ ¼öÇàµÈ´Ù¸é TRUE¹Ýȯ
    TRIGGER_FIRED_BY_DELETE(event)   Æ®¸®°Å°¡ DELETE ½Ã¿¡ ¼öÇàµÈ´Ù¸é TRUE¹Ýȯ
    TRIGGER_FIRED_BY_UPDATE(event)   Æ®¸®°Å°¡ UPDATE ½Ã¿¡ ¼öÇàµÈ´Ù¸é TRUE¹Ýȯ

     

    tg_relation

    ÀÌ ¸â¹ö´Â Æ®¸®°ÅµÇ´Â Å×À̺íÀ» ¼³¸íÇÏ´Â ±¸Á¶Ã¼¿¡ ´ëÇÑ Æ÷ÀÎÅÍÀÌ´Ù. src/include/utils/rel.h¿¡ ÀÚ¼¼ÇÑ ³»¿ëÀÌ Á¤ÀǵǾî ÀÖ´Ù. Èï¹Ì·Î¿î Á¡Àº tg_relation->rd_att(Å×À̺í Æ©ÇÃÀÇ ±â¼úÀÚ)¿Í tg_relation->rd_rel->relname(Å×À̺íÀÇ À̸§. ÀÌ°ÍÀº char * °¡ ¾Æ´Ï¶ó NameData ÇüÀÌ´Ù. char * ÀÇ º¹»çº»À» ¾òÀ¸·Á¸é, SPI_getrelname(tg_relation)À» »ç¿ëÇÏ¸é µÈ´Ù.)ÀÌ´Ù.

     

    tg_trigtuple

    ÀÌ ¸â¹ö´Â Æ®¸®°ÅµÇ´Â Æ©ÇÃÀ» °¡¸£Å°´Â Æ÷ÀÎÅÍÀÌ´Ù. ÀÌ Æ©ÇÃÀº INSERT/DELETE/UPDATE ½Ã¿¡ °¢°¢ »ðÀÔ/Á¦°Å/°»½Å µÇ´Â Æ©ÇÃÀÌ´Ù.

     

     tg_newtuple

    ÀÌ ¸â¹ö´Â UPDATE ½Ã¿¡ Æ©ÇÃÀÇ »õ·Î¿î ¹öÀüÀ» °¡¸®Å°´Â Æ÷ÀÎÅÍÀÌ´Ù. ´Ü, INSERT ³ª DELETE ½Ã¿¡ ÀÌ °ªÀº NULLÀÌ µÈ´Ù.

     

    tg_trigger

    ÀÌ ¸â¹ö´Â src/include/utils/rel.h¿¡ Á¤ÀǵǾî ÀÖ´Â Æ®¸®°Å ±¸Á¶Ã¼¸¦ °¡¸®Å°´Â Æ÷ÀÎÅÍÀÌ´Ù.

      typedef struct Trigger
      {
           char       *tgname ;
           Oid          tgfoid ;
           func_ptr   tgfunc ;
           int16        tgtype ;
           int16        tgnargs ;
           int16        tgattr[8] ;
           char      **tgargs ;
      } Trigger ;

    ÀÌ ±¸Á¶Ã¼¿¡¼­ tgname Àº Æ®¸®°ÅÀÇ À̸§ÀÌ°í, tgnargs ´Â tgargs ¿¡ ÀÖ´Â ÀÎÀÚÀÇ °³¼öÀ̸ç, tgargs ´Â CREATE TRIGGER ±¸¹®¿¡¼­ ÁöÁ¤ÇÑ ÀÎÀÚ¸¦ °¡¸®Å°´Â Æ÷ÀÎÅÍÀÇ ¹è¿­ÀÌ´Ù. ´Ù¸¥ ¸â¹ö´Â ³»ºÎÀûÀÎ ¸ñÀûÀ¸·Î¸¸ »ç¿ëµÈ´Ù.

     

Æ®¸®°ÅÀÇ ¿¹Á¦

    Æ®¸®°Å¿¡¼­ÀÇ µ¥ÀÌÅͺ¯È­¿¡ µû¸¥ °¡½Ã¼º ±ÔÄ¢Àº ±âº»ÀûÀ¸·Î SPI ¿¡¼­ÀÇ °¡½Ã¼º ±ÔÄ¢°ú µ¿ÀÏÇÏ´Ù. µ¡ºÙ¿©, BEFORE Æ®¸®°Å¿¡¼­ »ðÀԵǴ ƩÇÃ(tg_trigtuple)Àº ÁúÀǽÿ¡ ³ªÅ¸³ªÁö ¾Ê´Â´Ù. ÀÌ Æ©ÇÃÀº AFTER Æ®¸®°Å½Ã¿¡´Â ³ªÅ¸³­´Ù.

    ÀÌÁ¦ °£´ÜÇÑ Æ®¸®°ÅÀÇ ¿¹Á¦¸¦ »ìÆ캸ÀÚ. Æ®¸®°ÅÀÇ ´ëºÎºÐÀÇ ±â´ÉÀº SPI¸¦ ÅëÇؼ­ ½ÇÇöµÈ´Ù. ¾Æ¿ï·¯ Æ®¸®°Å¿¡¼­¸¸ »ç¿ë µÇ´Â °ÍÀº À§¿¡¼­µµ »ìÆ캻 Æ®¸®°Å °ü·Ã µ¥ÀÌÅÍ ±¸Á¶Ã¼µéÀÌ´Ù. ¿©±â¿¡ µîÀåÇÏ´Â trigf ÇÔ¼ö´Â Æ®¸®°ÅµÇ´Â Å×À̺íÀÎ ttest ¿¡ ÀÖ´Â Æ©ÇÃÀÇ °¹¼ö¸¦ Ãâ·ÂÇÏ°í, ¸¸ÀÏ ÁúÀÇ°¡ NULLÀ» x ¿¡ »ðÀÔÇÏ·Á°í ÇÑ´Ù¸é ÀÛµ¿À» ÇÏÁö ¾Ê°í °Ç³Ê¶Ú´Ù.(ÀÌ ºÎºÐÀº NOT NULL ±ÔÁ¤°ú ¶È°°ÀÌ µ¿ÀÛÇÑ´Ù. ÇÏÁö¸¸ trigf ÇÔ¼ö¿¡¼­´Â Æ®·£Àè¼ÇÀ» Áß´ÜÇÏÁö´Â ¾Ê´Â´Ù.)

     

    #include <stdio.h>
    #include "executor/spi.h"           /* SPI ¿¡ ÇÊ¿äÇÑ Çì´õÆÄÀÏ */
    #include "commands/trigger.h"   /* Æ®¸®°Å¿¡ ÇÊ¿äÇÑ Çì´õÆÄÀÏ */
    HeapTuple     trigf(void) ;
    HeapTuple
    trigf ()
    {
        TupleDesc tupdesc ;  /* Æ©Çà ±â¼úÀÚ */
        HeapTuple rettuple ;  /* ÇϳªÀÇ Æ©Çà ÀúÀå°í */
        char    *when ;
        bool    checknull = false ;
        bool    isnull ;
        int    ret,  I ;
        /* CurrentTriggerData°¡ NULLÀ̶ó¸é ¾ÆÁ÷ ÃʱâÈ­µÇÁö ¾Ê¾Ò´Ù´Â°ÍÀ» ÀÇ¹Ì */
        if (!CurrentTriggerData)
            elog(NOTICE, "trigf : triggers are not initialized") ;
        /* ½ÇÇà±â·Î µÇµ¹¸± Æ©ÇÃÀ» ÁöÁ¤ÇÑ´Ù. UPDATE Æ®¸®°Å½Ã¿¡´Â »õ·Î¿î Æ©ÇÃÀ» */
        /* ÁöÁ¤ÇÏ°í, INSERT/DELETE °æ¿ì¿¡´Â Æ®¸®°ÅµÇ´Â Æ©ÇÃÀ» ÁöÁ¤ÇÑ´Ù. */
           if (TRIGGER_FIRED_BY_UPDATE (!CurrentTriggerData->tg_event))
           rettuple = CurrentTriggerData->tg_newtuple ;
        else
           rettuple = CurrentTriggerData->tg_trigtuple ;
        /* ¸¸ÀÏ, INSERT/DELETE Æ®¸®°ÅÀÌ°í, BEFORE Æ®¸®°ÅÀ̸é NULLÀÌ »ðÀÔµÇÁö
            ¾Êµµ·Ï üũÇÑ´Ù. */
           if (TRIGGER_FIRED_BY_DELETE (!CurrentTriggerData->tg_event)) &&
           TRIGGER_FIRED_BEFORE (!CurrentTriggerData->tg_event))
           checknull = true ;
        /* ´õ ÀÌ»ó Æ®¸®°Å µ¥ÀÌÅÍ ±¸Á¶¿¡ Á¢±ÙÇÒ ÀÏÀÌ ¾øÀ¸¹Ç·Î, NULL·Î ÁöÁ¤ÇÑ´Ù. */
        CurrentTriggerData = NULL ;
        /* SPI °ü¸®ÀÚ·Î Á¢¼ÓÀ» ¼º¸³ÇÑ´Ù. */
        if ((ret = SPI_connect()) < 0)
            elog(NOTICE, "trigf (fired %s) : SPI_connect returned %d", when, ret) ;
        /* Å×ÀÌºí¿¡ ÀÖ´Â Æ©ÇÃÀÇ °¹¼ö¸¦ ¾ò´Â´Ù. */
        ret = SPI_exec("select count (*) from ttest", 0) ;
        if ( ret<0 )
            elog(NOTICE, "trigf (fired %s) : SPI_exec returned %d", when, ret) ;
        /* SPI_tuptable ¿¡´Â ttest Å×À̺íÀÇ Æ©ÇÃÀÇ °¹¼ö°¡ ù ¹ø° Æ©Çÿ¡ µé¾îÀÖ´Ù. */
        /* ÀÌ °¹¼ö´Â ¹Ù·Î À§¿¡¼­ ½ÇÇàÇÑ "select count(*) from ttest" ÀÇ °á°úÀÌ´Ù. */
        I = SPI_ getbinval(SPI_tuptable->vals[0], SPI_tuptale->tupdesc, 1, &isnull) ;
        elog(NOTICE, "trigf (fired %s) : there are %d tuples in ttest", when, i) ;
        SPI_finish() ;
        /* ¸¸ÀÏ Æ©ÇÃÀÇ °ªÀÌ NULL Àΰ¡¸¦ üũÇØ¾ß ÇÒ ÇÊ¿ä°¡ ÀÖ´Ù¸é, ù ¹ø° Ä÷³ÀÇ
            °ªÀ» °Ë»çÇؼ­*/
        /* ±× °ªÀÌ NULL À̶ó¸é, Æ©ÇÃÀÇ °ªÀ» NULL·Î ÇÏ¿© ½ÇÇà±â¿¡¼­ ó¸®ÇÏÁö ¾Êµµ·Ï
            ÇÑ´Ù. */
        if (checknull)
        {
            I = SPI_getbinval(rettuple, tupdesc, 1, &isnull) ;
            if (isnull)
        }
        /* Æ©ÇÃÀ» ½ÇÇà±â·Î ¹ÝȯÇÑ´Ù. */
        return (rettuple) ;
    }

     

    ÀÌ ÇÁ·Î±×·¥À» testtrig.c ·Î ÀúÀåÇÏ°í, ÄÄÆÄÀÏÀ» Çϵµ·Ï ÇÏÀÚ.

      $ ./funcom testtrig

    ¸ÕÀú, Æ®¸®°Å¸¦ »ý¼ºÇϱâ ÀÌÀü¿¡, Æ®¸®°Å°¡ ÀÇÁ¸ÇÏ°í ÀÖ´Â Å×À̺íÀ» ¸¸µé¾î º¸ÀÚ. ¿©±â¼­´Â µ¿½Ã¿¡ Æ®¸®°Å ÇÔ¼ö¸¦ µî·ÏÇÑ´Ù.

      $ psql -c "create table ttest (x int4) ; create function trigf() returns opaque as
        >>''pwd'/testtrig.so' language 'c' ; " mydb

    ¾Æ·¡´Â Æ®¸®°Å¸¦ »ý¼ºÇÏ°í, ½ÇÁ¦·Î Å×½ºÆ®ÇÏ´Â ³»¿ëÀÌ´Ù. Æ®¸®°Å¸¦ »ý¼ºÇÒ ¶§, INSERT/UPDATE/DELETE ¸ðµÎ¸¦ BEFORE/AFTER ¿¡ ÇϳªÀÇ ·Î¿ì¸¶´Ù Æ®¸®°Å µÇµµ·Ï ÇÏ¿´´Ù. Àß µû¶óÇغ¸°í ¿Ö ±×·¸°Ô µÇ´ÂÁö À§ÀÇ ¼Ò½º¿Í ºñ±³Çؼ­ À¯½ÉÈ÷ »ìÆ캸µµ·Ï ÇÏÀÚ.

      mydb=>create trigger tbefore before insert or update or delete on ttest for each
         >> row execute procedure trigf () ;
      CREATE
      mydb=>create trigger tafter after insert or update or delete on ttest for each
         >> row execute procedure trigf () ;
      CREATE 
      mydb=> insert into ttest values(null) ;
      NOTICE : trigf (fired before) : there are 0 tuples in ttest
      INSERT 0 0

      -- nullÀ» INSERT ½ÃµµÇÑ °ü°è·Î BEFORE Æ®¸®°Å¿¡¼­ °É·Á¼­ ½ÇÇà±â¿¡°Ô nullÀ» ¹Ýȯ
           ÇÏ¿© »ðÀÔÀÌ µÇÁö ¾Ê¾Ò´Ù. ¾Æ¿ï·¯ AFTER Æ®¸®°Å¿¡¼­´Â ½ÇÇà±â°¡ ¹Ýȯ °ªÀ» ¹«½Ã
           µÈ´Ù. µû¶ó¼­ ¾Æ·¡¿¡¼­ °Ë»öÇØ º» °á°ú »ðÀÔµÈ µ¥ÀÌÅÍ´Â ¾ø¾ú´Ù.

      mydb=> select * from ttest ;
      x
      -
      (0 row)

      mydb=> insert into ttest values (1) ;
      NOTICE : trigf (fired before) : there are 0 tuples in ttest
      NOTICE : trigf (fired after   ) : there are
      1 tuples in ttest
                                               °¡½Ã¼º ±ÔÄ¢¿¡ µû¸¥ °á°úÀÌ´Ù.
      INSERT 167793 1
      -- SELECT ¿¡´Â Æ®¸®°Å°¡ Àû¿ëµÇÁö ¾Ê´Â´Ù.
      mydb=> select * from ttest ;
      x
      -
      1
      (1 row)

      mydb=> insert into ttest select x * 2 from ttest ;
      NOTICE : trigf (fired before) : there are 1tuples in ttest
      NOTICE : trigf (fired after   ) : there are
      2 tuples in ttest
                                               °¡½Ã¼º ±ÔÄ¢¿¡ µû¸¥ °á°úÀÌ´Ù.
      INSERT 167794 1
      mydb=> select * from ttest ;
      x
      -
      1
      2
      (2 rows) 

      mydb=> update ttest set x = null where x = 2 ;
      NOTICE : trigf (fired before) : there are 2 tuples in ttest
      UPDATE 0
      mydb=> update ttest set x = 4 where x = 2 ;
      NOTICE : trigf (fired before) : there are 2 tuples in ttest
      NOTICE : trigf (fired after   ) : there are 2 tuples in ttest
      UPDATE 1
      mydb=> select * from ttest ;
      x
      -
      1
      4
      (2 rows) 

      mydb=> delete from ttest ;
      NOTICE : trigf (fired before) : there are 2 tuples in ttest
      NOTICE : trigf (fired after   ) : there are 1 tuples in ttest
      NOTICE : trigf (fired before) : there are 1 tuples in ttest
      NOTICE : trigf (fired after   ) : there are
      0 tuples in ttest
                                                       °¡½Ã¼º ±ÔÄ¢¿¡ µû¸¥ °á°ú
      delete 2
      mydb=> select * from ttest ;
      x
      -
      (0 row) 

    À§¿¡¼­ Æ®¸®°ÅµÇ´Â »óȲÀ» »ìÆ캸ÀÚ. ¸ÕÀú trigf¸¦ »ý¼ºÇÒ ¶§, INSERT/UPDATE/DELETE ¿¡ ´ëÇØ BEFORE/AFTER ¿¡ ¸ðµÎ Æ®¸®°Å¸¦ °É¾ú´Ù. ¹°·Ð SELECT »ç°Ç½Ã¿¡´Â Æ®¸®°Å¸¦ °É ¼ö ¾ø´Ù. INSERT ½Ã¿¡ BEFORE Æ®¸®°Å¿¡¼­´Â ¾ÆÁ÷ »ðÀÔÀ» ÇÏÁö ¾Ê¾Æ¼­ »ðÀԵǴ µ¥ÀÌÅÍ°¡ ³ªÅ¸³ªÁö ¾Ê´Â´Ù. ¹°·Ð AFTER Æ®¸®°Å½Ã¿¡´Â ÀÌ¹Ì ¾×¼ÇÀÌ ÀÌ·ç¾îÁø ÈÄÀ̹ǷΠµ¥ÀÌÅÍ°¡ ³ªÅ¸³­´Ù. »ç¿ëÀÚ°¡ nullÀ» INSERT/UPDATEÀ» ÅëÇØ ÀÔ·ÂÇÏ·Á°í Çϸé, BEFORE Æ®¸®°Å¿¡¼­ °Ë»çµÇ¾î¼­ »ðÀÔµÇÁö ¾Ê´Â´Ù. ±×¸®°í ÇϳªÀÇ ·Î¿ì°¡ ó¸®µÉ ¶§ ¸¶´Ù µÎ °³ÀÇ AFTER/BEFORE Æ®¸®°Å°¡ ½ÇÇàµÊÀ» »ó±âÇÏÀÚ. °¡·É, ¸¶Áö¸·ÀÇ "delete from ttest" ÀÌÀü¿¡ ÇöÀç µÎ °³ÀÇ ·Î¿ì°¡ Å×ÀÌºí¿¡ µé¾îÀÖ´Ù. DELETE ±¸¹®¿¡ ÀÇÇØ Ã¹ ¹ø° ·Î¿ì¸¦ Á¦°ÅÇϱâ ÀÌÀü¿¡(BEFORE) Æ®¸®°Å°¡ ½ÇÇàµÇ¾î¼­ ÇöÀç Æ©Çþȿ¡ ÀÖ´Â ·Î¿ì(Æ©ÇÃ)ÀÇ °¹¼ö¸¦ Ãâ·ÂÇÑ´Ù. »èÁ¦°¡ ÀÌ·ç¾îÁø ´ÙÀ½, AFTER Æ®¸®°Å°¡ ½ÇÇàµÇ¾î¼­ 1°³ÀÇ ·Î¿ì°¡ ÀÖÀ½À» ¾Ë¸°´Ù. ´ÙÀ½ ·Î¿ì¸¦ »èÁ¦Çϱâ À§Çؼ­ DELETE °¡ Àû¿ëµÇ¸é ¶Ç´Ù½Ã À§¿Í  °°ÀÌ BEFORE Æ®¸®°Å¿Í AFTERÆ®¸®°Å°¡ ÀÛ¿ëÇÑ´Ù.

     

³ª¿À¸é¼­

    Áö±Ý±îÁö ¼³¸íÇÑ SPI ¿Í Æ®¸®°Å´Â Àú¼öÁØÀÇ ¼­¹ö ÇÁ·Î±×·¡¹Ö ÀÎÅÍÆäÀ̽º¿´´Ù.
    »ç½Ç PostgreSQL ÀÌ Àú¼öÁØ¿¡¼­ ´ë´ÜÇÑ È®Àå °¡´É¼ºÀ» °¡Áö°í ÀÖ´Ù´Â °ÍÀº °ü½ÉÀÖ´Â »ç¶÷À̶ó¸é Àß ¾Ë °ÍÀÌ´Ù. PostgreSQL ³»ºÎ¿¡ Á¤ÀǵǾî ÀÖ´Â µ¥ÀÌÅÍ ±¸Á¶Ã¼±îÁöµµ Á¢±ÙÇÒ ¼ö ÀÖ´Ù´Â Á¡Àº ±íÀÌÀÖ´Â µ¥ÀÌÅͺ£À̽º ½Ã½ºÅÛ °øºÎ¿¡ ¸¹Àº µµ¿òÀÌ µÈ´Ù. ÇÏÁö¸¸ PostgreSQL Àº ¾ÆÁ÷ PL(ÇÁ·Î½ÃÀú¾ð¾î) ÂÊ¿¡¼­´Â ¾àÁ¡À» °¡Áö°í ÀÖ´Ù. ÀÌ°ÍÀº Á¶¸¸°£ PostgreSQL °³¹ßÆÀ¿¡ ÀÇÇØ º¸¿ÏÀÌ µÉ °ÍÀ¸·Î º¸ÀδÙ. Æ®¸®°Å¿Í SPI ´Â ²À ÇÊ¿äÇÑ °÷¿¡ Á¦´ë·Î¸¸ »ç¿ëÇÑ´Ù¸é ¾ÆÁÖ À¯¿ëÇÑ µµ±¸°¡ µÉ ¼ö ÀÖÀ» °ÍÀÌ´Ù. ÀÏ¹Ý SQL ±¸¹®À» ÁÖ·Î »ç¿ëÇÏ´Â À̵鿡°Ô´Â ±×´ÙÁö À¯¿ëÇÒ °Í °°Áö´Â ¾ÊÁö¸¸ ...

    PostgreSQL Àº Æ®¸®°Å¿Í À¯»çÇÑ ±ÔÄ¢(RULE) ½Ã½ºÅÛÀ» °¡Áö°í ÀÖ´Ù. ÀÌ ±ÔÄ¢ ½Ã½ºÅÛÀ» »ç¿ëÇϸé Æ®¸®°ÅÀÇ ¿ªÇÒÀ» SQL ±¸¹® Â÷¿ø¿¡¼­ ¼öÇàÇÒ ¼ö ÀÖ´Ù. Áß¿äÇÑ Å×À̺íÀÇ ³»¿ëÀ» °»½ÅÀÌ ÀÖÀ» ¶§¸¶´Ù ¹é¾÷ÇÑ´ÙµçÁö ÇÏ´Â ÀÛ¾÷¿¡ ÁÖ·Î »ç¿ëµÉ °ÍÀÌ´Ù. ÇÏÁö¸¸ ÇöÀçÀÇ ±ÔÄ¢ ½Ã½ºÅÛÀº ´ë´ÜÈ÷ ºÒ¾ÈÇϱ⠶§¹®¿¡ »ç¿ëÀ» ±ÇÀåÇÏÁö´Â ¾Ê´Â´Ù. ´Ù¸¸ ±×´ÙÁö Áß¿äÇÏÁö ¾ÊÀº °³ÀÎÀûÀÎ ÀÛ¾÷¿¡ ±ÔÄ¢ ½Ã½ºÅÛÀ» »ç¿ëÇÏ´Â °ÍÀº ±¦ÂúÀ»Áö ¸ð¸£Áö¸¸ ȸ»çÀÇ Áß¿äÇÑ ÀÛ¾÷À» ó¸®ÇÏ´Â °÷¿¡´Â ±ÔÄ¢ ½Ã½ºÅÛ ´ë½Å Æ®¸®°Å¿Í SPI¸¦ »ç¿ëÇϵµ·Ï ÇÏÀÚ.

    À̹ø È£ÀÇ °­Á´ ÀÌ°ÍÀ¸·Î ¸¶Ä£´Ù.




¡ã top

homeÀ¸·Î...