38.5. PL/Tcl·ÎºÎÅÍÀÇ µ¥ÀÌÅͺ£À̽º Á¢±Ù

¾Æ·¡¿Í °°Àº ¸í·É´Â, PL/Tcl ÇÔ¼ö³»·ÎºÎÅÍ µ¥ÀÌÅͺ£À̽º Á¢±ÙÀ» ½Ç½ÃÇÒ ¶§¿¡ »ç¿ëÇÒ ¼ö ÀÖ´Â ¸í·ÉÀÔ´Ï´Ù.

spi_exec ?-count n ? ?-array name ? command ? loop-body ?

¹®ÀÚ¿­À¸·Î¼­ ÁÖ¾îÁø SQL Äõ¸®¸¦ ½ÇÇàÇÕ´Ï´Ù. ¸í·É³»ÀÇ ¿¡·¯´Â, ¿¡·¯ÀÇ ¹ß»ýÀÌ µË´Ï´Ù. ¾ÆÁÖ ¾øÀ¸¸é, ÀÌ spi_execÀÇ ¹Ýȯ°ªÀº ¸í·É¿¡ ÀÇÇØ ó¸®(¼±ÅÃ, »ðÀÔ, °»½Å, »èÁ¦)µÈ Çà¼ö, ¶Ç´Â, ¸í·ÉÀÌ À¯Æ¿¸®Æ¼ Äõ¸® °æ¿ì´Â Á¦·Î°¡ µË´Ï´Ù. °Ô´Ù°¡ ¸í·ÉÀÌ SELECTÄõ¸® °æ¿ì, ¼±ÅÃµÈ ¿­ÀÇ °ªÀº ÀÌÇÏ¿Í °°ÀÌ TclÀÇ º¯¼ö¿¡ ÀúÀåµË´Ï´Ù.

-count¿É¼ÇÀÇ °ªÀº, spi_exec¿¡ ´ëÇØ, ±× ¸í·ÉÀ¸·Î ó¸®ÇÏ´Â ÃÖ´ëÇà¼ö¸¦ Áö½ÃÇÕ´Ï´Ù. À̰Ϳ¡ ÀÇÇØ, Äõ¸®¸¦ Ä¿¼­·Î¼­ ¼³Á¤ÇØ, FETCH n ¸¦ ½ÇÇàÇÏ´Â °ÍÀ¸·Î °°Àº °ÍÀÌ »ý±é´Ï´Ù.

¸í·ÉÀÌ SELECTÄõ¸® °æ¿ì, ±× °á°ú ¾òÀ» ¼ö ÀÖ´ø ¿­ÀÇ °ªÀº, ·Ä¸í¿¡ ¿¬°üµÈ À̸§ÀÇ Tcl º¯¼ö¿¡ ÀúÀåµË´Ï´Ù. -array¿É¼ÇÀÌ ºÎ¿©µÇ¾úÀ» °æ¿ì´Â, ¿­ÀÇ °ªÀº ÁöÁ¤ÇÑ À̸§ÀÇ ¿¬»ó ¹è¿­¿¡ ÀúÀåµÇ¾î ±× ¹è¿­ÀÇ À妽º·Î¼­ ·Ä¸íÀÌ »ç¿ëµË´Ï´Ù.

¸í·ÉÀÌ SELECT¹®, ÇÑÆí, loop-body ½ºÅ©¸³Æ®°¡ ºÎ¿©µÇÁö ¾Ê¾Ò´ø °æ¿ì, °á°ú Áß ÃÖÃÊÀÇ ÇุÀÌ Tcl º¯¼ö¿¡ ÀúÀåµË´Ï´Ù. ±× ¹Û¿¡µµ ÇàÀÌ ÀÖ¾ú´Ù°í ÇØµµ, ±×°ÍµéÀº ¹«½ÃµË´Ï´Ù. Äõ¸®°¡ ÇàÀ» µ¹·ÁÁÖÁö ¾Ê¾Ò´ø °æ¿ì´Â, º¯¼ö¿¡ÀÇ ÀúÀåÀº ¹ß»ýÇÏÁö ¾Ê½À´Ï´Ù (spi_execÀÇ ¹Ýȯ°ªÀ» °Ë»çÇÏ´Â °ÍÀ¸·Î, À̰ÍÀ» °ËÃâÇÒ ¼ö°¡ ÀÖ½À´Ï´Ù). ÀÌÇÏ¿¡ ¿¹¸¦ ³ªÅ¸³À´Ï´Ù.

spi_exec "SELECT count(*) AS cnt FROM pg_proc"

À̰ÍÀº, $cnt Tcl º¯¼ö¸¦, pg_proc½Ã½ºÅÛ ¸ñ·ÏÀÇ Çà¼ö·Î ¼³Á¤ÇÕ´Ï´Ù.

loop-body ¿É¼Ç ÀÎÀÚ°¡ ºÎ¿©µÇ¾úÀ» °æ¿ì, ±×°ÍÀº, Äõ¸®ÀÇ °á°ú ³»ÀÇ Çà °¢°¢ ´ëÇØ ÇÑ ¹ø¸¸ ½ÇÇàµÇ´Â ÀÛÀº Tcl ½ºÅ©¸³Æ®ÀÔ´Ï´Ù ( loop-body ´Â SELECTÀÌ¿ÜÀÇ Äõ¸®·Î ºÎ¿©µÇ¾úÀ» °æ¿ì´Â ¹«½ÃµË´Ï´Ù). ó¸®ÁßÀÇ ÇàÀÇ ·Ä°ª´Â, °¢ ¹Ýº¹Àü¿¡ Tcl º¯¼ö¿¡ ÀúÀåµË´Ï´Ù. ÀÌÇÏ¿¡ ¿¹¸¦ ³ªÅ¸³À´Ï´Ù.

spi_exec -array C "SELECT * FROM pg_class" {
    elog DEBUG "have table $C(relname)"
}

À̰ÍÀº, pg_classÀÇ °¢ Çà¿¡ ´ëÇØ¼­ ·Î±× ¸Þ¼¼Áö¸¦ Ãâ·ÂÇÕ´Ï´Ù. ÀÌ ±â´ÉÀº ´Ù¸¥ TclÀÇ ¹Ýº¹ ±¸¹®¿¡¼­µµ¿Í °°ÀÌ µ¿ÀÛÇÕ´Ï´Ù. ƯÈ÷ ·çÇÁ º»Ã¼³»ÀÇ continue¿Í break´Â Åë»ó ´ë·Î µ¿ÀÛÇÕ´Ï´Ù.

Äõ¸®ÀÇ °á°ú, ¿­ÀÌ NULL¿´À» °æ¿ì, ´ë»óÀÌ µÇ´Â º¯¼ö´Â ´ëÀÔµÇÁö ¾Ê°í, "»èÁ¦(unset)"µË´Ï´Ù.

spi_prepare query typelist

ÈÄÀÇ ½ÇÇàÀ» À§Çؼ­ Äõ¸® °èȹÀÇ Áغñ, º¸Á¸À» ½Ç½ÃÇÕ´Ï´Ù. º¸Á¸µÈ °èȹÀº ÇöÀçÀÇ ¼¼¼ÇÀÌ Á¾·áÇÒ ¶§±îÁö º¸°ü À¯ÁöµË´Ï´Ù.

Äõ¸®´Â ¸Å°³º¯¼ö, Áï, °èȹÀÌ ½ÇÁ¦·Î ½ÇÇàµÉ ¶§¿¡ Ç×»ó ÁÖ¾îÁö´Â °ª¿ëÀÇ Ç÷¹À̽ºÈ¦´õ¸¦ °¡Áú ¼ö°¡ ÀÖ½À´Ï´Ù. Äõ¸® ¹®ÀÚ¿­ Áß¿¡¼­´Â, $1 ... $ n ¶ó°í ÇÏ´Â ½Éº¼À» »ç¿ëÇØ ÀÎÀÚ¸¦ ÂüÁ¶ÇØ ÁÖ¼¼¿ä. Äõ¸®°¡ ¸Å°³º¯¼ö¸¦ »ç¿ëÇÏ´Â °æ¿ì, TclÀÇ ¸®½ºÆ®·Î¼­ ¸Å°³º¯¼öÀÇ Çü¸íÀ» ÁöÁ¤ÇÒ Çʿ䰡 ÀÖ½À´Ï´Ù (ÆÄ¶ó¹ÌÅ͸¦ »ç¿ëÇÏÁö ¾Ê´Â °æ¿ì´Â typelist ¿¡´Â ºó ¸®½ºÆ®¸¦ ÁöÁ¤ÇØ ÁÖ¼¼¿ä).

spi_prepareÀÇ ¹Ýȯ°ªÀº Äõ¸® IDÀÔ´Ï´Ù. ÀÌ ID´Â ÈÄÀÇ spi_execp·Î »ç¿ëµË´Ï´Ù. »ç¿ë¿¹¿¡ ´ëÇØ¼­´Â spi_execp¸¦ ÂüÁ¶ÇØ ÁÖ¼¼¿ä.

spi_execp ?-count n ? ?-array name ? ?-nulls string ? queryid ? value-list ? ? loop-body ?

spi_prepare¿¡ ÀÇÇØ »çÀü¿¡ ÁغñµÈ Äõ¸®¸¦ ½ÇÇàÇÕ´Ï´Ù. queryid ´Â spi_prepare¿¡ ÀÇÇØ µ¹·ÁÁÖ¾îÁø IDÀÔ´Ï´Ù. ±× Äõ¸®°¡ ¸Å°³º¯¼ö¸¦ ÂüÁ¶ÇÏ´Â °æ¿ì, value-list ¸¦ ÁÙ Çʿ䰡 ÀÖ½À´Ï´Ù. À̰ÍÀº, ±× ¸Å°³º¯¼öÀÇ ½ÇÁ¦ÀÇ °ªÀ» °¡Áö´Â TclÀÇ ¸®½ºÆ®ÀÔ´Ï´Ù. ÀÌ ¸®½ºÆ®ÀÇ ±æÀÌ´Â, »çÀü¿¡ spi_prepare·Î ÁöÁ¤ÇÑ ÀÎÀÚÇüÀÇ ¸®½ºÆ®ÀÇ ±æÀÌ¿Í °°Áö ¾ÊÀ¸¸é ¾ÈµË´Ï´Ù. Äõ¸®¿¡ ¸Å°³º¯¼ö°¡ ¾ø´Â °æ¿ì´Â, value-list ¸¦ »ý·« ÇØ ÁÖ¼¼¿ä.

-nulls¿É¼ÇÀÇ °ªÀº, °ø¹é ¹®ÀÚ¿Í 'n'¶ó°í ÇÏ´Â ¹®ÀڷκÎÅÍ µÇ´Â ¹®ÀÚ¿­À¸·Î, spi_execp¿¡ ´ëÇØ, ¾î´À ÀÎÀÚ°¡ NULL°ªÀÎÁö¸¦ ³ªÅ¸³À´Ï´Ù. ÁöÁ¤µÇ¾úÀ» °æ¿ì, ±× ¹®ÀÚ¿­ÀÇ ±æÀÌ´Â value-list ÀÇ ±æÀÌ¿Í Á¤È®ÇÏ°Ô ÀÏÄ¡Çϰí ÀÖÁö ¾ÊÀ¸¸é ¾ÈµË´Ï´Ù. ÁöÁ¤µÇÁö ¾Ê´Â °æ¿ì´Â, ¸ðµç ¸Å°³º¯¼öÀÇ °ªÀº ºñNULLÀÔ´Ï´Ù.

Äõ¸®¿Í ±× ¸Å°³º¯¼ö¸¦ ¾îµð¼­ ÁöÁ¤Çϴ°¡ ÇÏ´Â Á¡À» Á¦¿ÜÇØ, spi_execp´Â spi_exec¿Í °°°Ô µ¿ÀÛÇÕ´Ï´Ù. -count, -array, loop-body ¿É¼Çµµ, ±×¸®°í, °á°úÀÇ °ªµµ °°½À´Ï´Ù.

¿©±â¼­, ÁغñµÈ °èȹÀ» »ç¿ëÇÑ, PL/Tcl ÇÔ¼öÀÇ ¿¹¸¦ ³ªÅ¸³À´Ï´Ù.

CREATE FUNCTION t1_count(integer, integer) RETURNS integer AS $$
    if {![ info exists GD(plan) ]} {
        # ÃÖÃÊÀÇ È£Ãâ¿¡¼­´Â º¸Á¸ÇÒ °èȹÀ» ÁغñÇÕ´Ï´Ù.
        set GD(plan) [ spi_prepare \
                "SELECT count(*) AS cnt FROM t1 WHERE num >= \$1 AND num <= \$2" \
                [ list int4 int4 ] ]
    }
    spi_execp -count 1 $GD(plan) [ list $1 $2 ]
    return $cnt
$$ LANGUAGE pltcl;

spi_prepare¿¡°Ô ÁÖ´Â Äõ¸® ¹®ÀÚ¿­ÀÇ ¾ÈÂÊ¿¡¼­´Â, $ n Ç¥°¡ È®½ÇÈ÷ ±×´ë·Î spi_prepare¿¡°Ô °Ç³×Á® Tcl º¯¼öÀÇ ´ëÀÔ¿¡ ÀÇÇÑ Ä¡È¯ÀÌ ÀϾÁö ¾Ê°Ô backslash°¡ ÇÊ¿äÇÕ´Ï´Ù.

spi_lastoid

Á÷ÀüÀÇ spi_exec ¶Ç´Â spi_execp¿¡ ÀÇÇÑ ¸í·É°¡ ´ÜÀÏÇàÀÇ INSERT¹®, ÇÑÆí, °»½ÅµÇ´Â Å×À̺íÀÌ OID¸¦ °¡Áö´Â °æ¿ì, ±× ¸í·É¿¡ ÀÇÇØ »ðÀÔµÈ ÇàÀÇ OID¸¦ µ¹·ÁÁÝ´Ï´Ù(¾Æ¿¹ ¾øÀ¸¸é, Á¦·Î¸¦ µ¹·ÁÁÝ´Ï´Ù).

quote string

ÁöÁ¤µÈ ¹®ÀÚ¿­ ³»ÀÇ ¸ðµç ´ÜÀÏ ÀοëºÎÈ£¿Í backslash ¹®ÀÚ¸¦ ÀÌÁßÈ­ÇÕ´Ï´Ù. spi_exec³ª spi_prepare·Î ÁÖ¾îÁø SQL Äõ¸®¿¡ »ðÀ﵃ ¿¹Á¤ÀÇ ¹®ÀÚ¿­À» ¾ÈÀüÇÏ°Ô ÀοëÇϱâ À§Çؼ­ À̰ÍÀ» »ç¿ëÇÒ ¼ö°¡ ÀÖ½À´Ï´Ù. ¿¹¸¦ µé¸é, ÀÌÇÏ¿Í °°Àº Äõ¸® ¹®ÀÚ¿­À» »ý°¢ÇÕ´Ï´Ù.

"SELECT '$val' AS ret"

¿©±â¼­, val Tcl º¯¼ö¿¡ doesn't°¡ ½ÇÁ¦·Î Æ÷ÇԵǾî ÀÖ´Â °ÍÀ¸·Î ÇÕ´Ï´Ù. À̰ÍÀº ÃÖÁ¾ÀûÀ¸·Î ÀÌÇÏÀÇ Äõ¸® ¹®ÀÚ¿­ÀÌ µÇ¾î ¹ö¸³´Ï´Ù.

SELECT 'doesn't' AS ret

À̰ÍÀ¸·Î´Â, spi_exec ¶Ç´Â spi_prepareÀÇ ½ÇÇàÁß¿¡ ÇØ¼® ¿¡·¯°¡ ¹ß»ýÇØ ¹ö¸³´Ï´Ù. ¿Ã¹Ù¸£°Ô °¡µ¿½ÃŰ·Á¸é, ½ÇÇàÇÏ°í ½ÍÀº Äõ¸®´Â ÀÌÇÏ¿Í °°ÀÌ ÇÏÁö ¾ÊÀ¸¸é ¾ÈµË´Ï´Ù.

SELECT 'doesn''t' AS ret

À̰ÍÀº, PL/Tcl¿¡¼­´Â ÀÌÇÏ¿¡ ÀÇÇØ Çü¼ºÇÒ ¼ö°¡ ÀÖ½À´Ï´Ù.

"SELECT '[ quote $val ]' AS ret"

spi_execp°¡ °¡Áö´Â 1°³ÀÇ ÀÌÁ¡Àº, ¸Å°³º¯¼ö´Â SQL Äõ¸® ¹®ÀÚ¿­ÀÇ ÀϺημ­ ÇØ¼®µÇ´Â ÀÏÀÌ ¾ø±â ¶§¹®¿¡, ÀÌ¿Í °°ÀÌ ¸Å°³º¯¼öÀÇ °ªÀ» ÀοëÇÒ Çʿ䰡 ¾ø´Â °ÍÀÔ´Ï´Ù.

elog level msg

·Î±× ¶Ç´Â ¿¡·¯ ¸Þ¼¼Áö¸¦ ¹ßÇàÇÕ´Ï´Ù. »ç¿ëÇÒ ¼ö ÀÖ´Â ·¹º§Àº, DEBUG, LOG, INFO, NOTICE, WARNING,ERROR, ¹× FATALÀÔ´Ï´Ù. ERROR´Â ¿¡·¯ »óŸ¦ ¹ß»ýÇÕ´Ï´Ù. °Ô´Ù°¡ À§·¹º§ÀÇ Tcl ÄÚµå·Î ¿¹¿Ü°¡ Æ÷ÂøµÇÁö ¾ÊÀ¸¸é, ÀÌ ¿¡·¯´Â Äõ¸®Çϰí È£Ãâ ó¸®ÀÇ ¿ÜºÎ¿¡ ÀüÆÄ µÇ¾î ±× °á°ú, ÇöÀçÀÇ Æ®·£Àè¼Ç ȤÀº ¼­ºêÆ®·£Àè¼Ç´Â Áß´Ü(abort) µË´Ï´Ù. À̰ÍÀº ½ÇÁúÀûÀ¸·Î TclÀÇerror¸í·É¿Í µ¿ÀÏÇÕ´Ï´Ù. FATAL´Â Æ®·£Àè¼Ç¸¦ Áß´Ü(abort)ÇØ, ÇöÀçÀÇ ¼¼¼ÇÀ» Á¤Áö½Ãŵ´Ï´Ù (PL/Tcl ÇÔ¼ö¿¡ ´ëÇØ ÀÌ ¿¡·¯ ·¹º§À» »ç¿ëÇØ¾ß ÇÒ ÀÌÀ¯´Â ¾Æ¸¶ Á¸ÀçÇÕ´Ï´Ù¸¸, ¿ÏÀü¼ºÀ» À§Çؼ­ ÁغñµÇ¾î ÀÖ½À´Ï´Ù). ´Ù¸¥ ·¹º§Àº, ´Ù¸¥ Á߿䵵ÀÇ ¸Þ¼¼Áö¸¦ »ý¼ºÇÒ »ÓÀÔ´Ï´Ù. log_min_messages°ú client_min_messages¼³Á¤ ¸Å°³º¯¼ö´Â, ƯÁ¤ÀÇ Á߿䵵ÀÇ ¸Þ¼¼Áö¸¦ Ŭ¶óÀÌ¾ðÆ®¿¡ º¸°íÇÏ´ÂÁö, ¼­¹öÀÇ ·Î±×¿¡ ½á³»´ÂÁö, ȤÀº ±× ¾çÂÊ ¸ðµÎÀÎÁö¸¦ Á¦¾îÇÕ´Ï´Ù. ÀÚ¼¼ÇÑ °ÍÀº Chapter 17À» ÂüÁ¶ÇØ ÁÖ¼¼¿ä.