| PostgreSQL 8.3.3¹®¼ | ||||
|---|---|---|---|---|
| Prev | Fast Backward | Chapter 33. SQL È®Àå | Fast Forward | Next |
»ç¿ëÀÚ Á¤ÀÇÀÇ ÇÔ¼ö´Â C(ȤÀº C++¿Í °°Àº C¿Í ȣȯ¼ºÀÌ ÀÖ´Â ¾ð¾î)·Î ÀÛ¼ºÇÒ ¼ö°¡ ÀÖ½À´Ï´Ù. ±×·¯ÇÑ ÇÔ¼ö´Â µ¿Àû ·Îµå °¡´É ¿ÀºêÁ§Æ®(°øÀ¯ ¶óÀ̺귯¸®¶ó°íµµ ºÒ¸³´Ï´Ù)·Î¼ ÄÄÆÄÀÏ µÇ¾î Çʿ信 µû¶ó¼ ¼¹ö¿¡ ·Îµå µË´Ï´Ù. µ¿Àû ·Îµå ±â´ÉÀÌ, "C¾ð¾î"ÇÔ¼ö¸¦ "³»ºÎ"ÇÔ¼ö¿Í ±¸º°ÇÏ´Â °ÍÀÔ´Ï´Ù. ÄÚµù ¹æ¹ýÀº ±âº»ÀûÀ¸·Î ¾çÂÊ ¸ðµÎ °°½À´Ï´Ù (µû¶ó, Ç¥ÁØ ³»ºÎ ÇÔ¼ö ¶óÀ̺귯¸®´Â, »ç¿ëÀÚ Á¤ÀÇÀÇ CÇÔ¼öÀÇ ÄÚµù ¿¹ÀÇ Ç³ºÎÇÑ Á¤º¸¿øÀÌ µË´Ï´Ù).
ÇöÀç, µÎ °¡ÁöÀÇ ´Ù¸¥ È£Ãâ ±Ô¾àÀÌ CÇÔ¼ö·Î »ç¿ëµÇ°í ÀÖ½À´Ï´Ù. º¸´Ù »õ·Î¿î "Version-1"È£Ãâ ±Ô¾àÀº, ÀÌÇÏ¿¡ ³ªÅ¸³»µíÀÌ, ±× ÇÔ¼ö¿ëÀ¸·Î È£Ãâ ¸ÅÅ©·ÎPG_FUNCTION_INFO_V1()¸¦ ¾²´Â °ÍÀ¸·Î ³ªÅ¸³³´Ï´Ù. ÀÌ ¸ÅÅ©·Î°¡ Á¸ÀçÇÏÁö ¾ÊÀ¸¸é, ±¸Çü½Ä("Version-0")ÀÇ ÇÔ¼öÀÎ °ÍÀ» ³ªÅ¸³À´Ï´Ù. ¾î´À ÂÊÀÇ °æ¿ìµµ CREATE FUNCTION·Î ÁöÁ¤ÇÏ´Â ¾ð¾î¸íÀº CÀÔ´Ï´Ù. ±¸Çü½ÄÀÇ ÇÔ¼ö´Â, À̽ļºÀÇ ¹®Á¦¿Í ±â´ÉÀÇ ºÎÁ·¶§¹®¿¡ ±ÇÀ¯¹ÞÁö ¾Ê½À´Ï´Ù. À̰ÍÀº ÇöÀç, ȣȯ¼ºÀÇ ÀÌÀ¯ ¶§¹®¿¡ Á¸ÀçÇϰí ÀÖ½À´Ï´Ù.
ƯÁ¤ÀÇ ·Îµå °¡´É °´Ã¼ ³»ÀÇ »ç¿ëÀÚ Á¤ÀÇÀÇ ÇÔ¼ö°¡ ¼¼¼ÇÀ¸·Î ÃÖÃÊ·Î ºÒ·Á °¡¸é, µ¿Àû ·Î´õ´Â, ±× ÇÔ¼ö¸¦ È£ÃâÇÒ ¼ö ÀÖµµ·Ï, °´Ã¼ ÆÄÀÏÀ» ¸Þ¸ð¸®³»¿¡ ÀоîµéÀÔ´Ï´Ù. ±× ¶§¹®¿¡, »ç¿ëÀÚ Á¤ÀÇ CÇÔ¼ö¿ëÀÇ CREATE FUNCTION´Â ±× ÇÔ¼ö¿¡ ´ëÇØ, ·Îµå °¡´É °´Ã¼ ÆÄÀÏÀÇ À̸§°ú, °´Ã¼ ÆÄÀÏÀÌ ºÒ·Á °¡´Â ƯÁ¤ÀÇ ÇÔ¼öÀÇ C¸íĪ(¸µÅ© ½Éº¼)À̶ó´Â 2°³ÀÇ Á¤º¸¸¦ ÁöÁ¤ÇؾßÇÕ´Ï´Ù. C¸íĪÀÌ ¸í½ÃÀûÀ¸·Î ÁöÁ¤µÇÁö ¾Ê¾Ò´ø °æ¿ì, SQL¿¡¼ÀÇ ÇÔ¼ö¸í°ú °°Àº °Í°ú °¡Á¤µË´Ï´Ù.
CREATE FUNCTION¸í·ÉÀ¸·Î ÁÖ¾îÁø À̸§¿¡ ±Ù°ÅÇØ, °øÀ¯ °´Ã¼ ÆÄÀÏÀÇ Àå¼Ò¸¦ ã¾Æ³¾ ¶§¿¡ ÀÌÇÏÀÇ ¾Ë°í¸®ÁòÀÌ »ç¿ëµË´Ï´Ù.
À̸§ÀÌ Àý´ë ÆÐ½ºÀÇ °æ¿ì, ÁöÁ¤µÈ ÆÄÀÏÀÌ ÀÐÈü´Ï´Ù.
À̸§ÀÌ $libdir¶ó°í ÇÏ´Â ¹®ÀÚ¿·Î ½ÃÀ۵Ǵ °æ¿ì, ±× ºÎºÐÀº PostgreSQLÆÐŰÁöÀÇ ¶óÀ̺귯¸® µð·ºÅ丮¿¡¼ ¿Å°Ü³õÀ» ¼ö ÀÖ½À´Ï´Ù. ÀÌ µð·ºÅ丮´Â ±¸Ãà ½Ã °áÁ¤µË´Ï´Ù.
À̸§¿¡ µð·ºÅ丮 ºÎºÐÀÌ ¾ø´Â °æ¿ì, ±× ÆÄÀÏÀº dynamic_library_path¼³Á¤ º¯¼ö·Î ÁöÁ¤µÈ ÆÐ½º³»·ÎºÎÅÍ °Ë»öµË´Ï´Ù.
»ó±â ÀÌ¿ÜÀÇ °æ¿ì(ÆÄÀÏÀÌ ÆÐ½º³»¿¡ Á¸ÀçÇÏÁö ¾Ê´Â °æ¿ì³ª »ó´ë µð·ºÅ丮 ºÎºÐÀ» °¡Áö´Â °æ¿ì), µ¿Àû ·Î´õ´Â ÁöÁ¤µÈ À̸§À» ±×´ë·Î »ç¿ëÇØ, ´ëºÎºÐÀÇ °æ¿ì´Â ½ÇÆÐÇÕ´Ï´Ù (À̰ÍÀº ÇöÀçÀÇ ÀÛ¾÷ µð·ºÅ丮¿¡ ÀÇÁ¸Çϱâ À§ÇØ ½Å·ÚÇÒ ¼ö ¾ø½À´Ï´Ù).
¿©±â±îÁöÀÇ È帧ÀÌ Àß µÇÁö ¾Ê¾Ò´ø °æ¿ì, Ç÷§Æû µ¶ÀÚÀûÀÎ °øÀ¯ ¶óÀ̺귯¸® ÆÄÀÏ È®ÀåÀÚ(extension)(¸¹Àº °æ¿ì. so)°¡ ÁöÁ¤µÈ À̸§¿¡ Ãß°¡µÇ¾î ÀçÂ÷ ÀÌ È帧À» ½ÃµµÇÕ´Ï´Ù. ¶Ç ½ÇÆÐÇßÀ» °æ¿ì, ·Îµå°¡ ½ÇÆÐÇÕ´Ï´Ù.
°øÀ¯ ¶óÀ̺귯¸®¸¦ $libdir·ÎºÎÅÍ »ó´ëÀûÀ¸·Î, ȤÀº µ¿Àû ¶óÀ̺귯¸® ÆÐ½º°¡ ´Ù´Ñ °÷¿¡ ¹èÄ¡ÇÏ´Â °ÍÀ» Ãßõ ÇÕ´Ï´Ù. ´Ù¸¥ Àå¼Ò¿¡ »õ·Î¿î ¼³Ä¡¸¦ ¹èÄ¡ÇÏ´Â °æ¿ì¿¡ ¹öÀü ¾÷À» °£´ÜÇÏ°Ô ÇÕ´Ï´Ù. $libdir°¡ °¡¸®Å°´Â ½ÇÁ¦ÀÇ µð·ºÅ丮´Â pg_config --pkglibdir¸í·ÉÀ» »ç¿ëÇÏ´Â °ÍÀ¸·Î ÇÕ´Ï´Ù.
PostgreSQL¼¹öÀÇ ½ÇÈ¿ »ç¿ëÀÚ ID´Â ·Îµå ¿¹Á¤ÀÇ ÆÄÀÏÀÇ ÆÐ½º±îÁö µµ´ÞÇÒ ¼ö ÀÖ¾î¾ß ÇÕ´Ï´Ù. postgres»ç¿ëÀÚ¿¡ ÀÇÇØ ÀÐÀ» ¼ö ÀÖ°í, ½ÇÇà°¡´ÉÇÑ ÆÄÀÏ »Ó¸¸ ¾Æ´Ï¶ó »óÀ§ µð·ºÅ丮¸¦¸¸µéÁö ¸øÇÏ´Â °ÍÀÌ ÀÚÁÖ ÀÖ´Â ½Ç¼öÀÔ´Ï´Ù.
¾î´À °æ¿ì¿¡¼µµ, CREATE FUNCTION¸í·É¿¡°Ô ÁØ ÆÄÀϸíÀº ±×´ë·Î ½Ã½ºÅÛ Ä«Å»·Î±×¿¡ º¸Á¸µË´Ï´Ù. ±×·¯¹Ç·Î, ¸¸¾à ±× ÆÄÀÏÀ» ÀçÂ÷ ÀоîµéÀÏ Çʿ䰡 ÀÖ´Â °æ¿ì, °°Àº 󸮰¡ Àû¿ëµË´Ï´Ù.
Note: PostgreSQL´Â CÇÔ¼ö¸¦ ÀÚµ¿ÀûÀ¸·Î ÄÄÆÄÀÏ ÇÏÁö ¾Ê½À´Ï´Ù. CREATE FUNCTION¸í·ÉÀ¸·Î ÂüÁ¶Çϱâ Àü¿¡, ±× °´Ã¼ ÆÄÀÏÀº ÄÄÆÄÀϵǾî ÀÖÁö ¾ÊÀ¸¸é ¾ÈµË´Ï´Ù. »õ·Î¿î Á¤º¸¿¡ ´ëÇØ¼´Â, Section 33.9.6À» ÂüÁ¶ÇØ ÁÖ¼¼¿ä.
µ¿ÀûÀ¸·Î ·ÎµåµÈ °´Ã¼ ÆÄÀÏÀÌ È£È¯¼ºÀÌ ¾ø´Â ¼¹ö¿¡ ·ÎµåµÇÁö ¾Ê°Ô Çϱâ À§ÇØ, PostgreSQL´Â, ±× ÆÄÀÏ¿¡ ÀûÀýÇÑ ³»¿ëÀ» °¡Áö´Â "¸¶¹ýÀÇ ºí·Ï"ÀÌ Æ÷ÇԵǾî ÀÖ´ÂÁö °Ë»çÇÕ´Ï´Ù. ¸ÞÀÌÀú ¹öÁ¯ÀÌ ´Ù¸¥ PostgreSQL¿ëÀ¸·Î ÄÄÆÄÀÏ µÈ ¸ðµâ µî°ú °°ÀÌ, ¼¹ö°¡ ´«¿¡ ¶ç°Ô ȣȯ¼ºÀÌ ¾ø´Â °ÍÀ» °¨ÁöÇÏ°Ô ÇØÁÝ´Ï´Ù. ¸¶¹ýÀÇ ºí·ÏÀº PostgreSQL 8.2·ÎºÎÅÍ ¿ä±¸µÇ°í ÀÖ½À´Ï´Ù. ¸¶¹ýÀÇ ºí·ÏÀ» Æ÷ÇÔ½ÃŰ·Á¸é,ÀÌÇϸ¦ ¸ðµâÀÇ ¼Ò½º ÆÄÀÏ¿¡ ÇÑ ¹ø(ÇÑ ¹ø¸¸), fmgr.hÇì´õ ÆÄÀÏÀ» Æ÷ÇÔ½ÃŲ ´ÙÀ½¿¡, ±â¼úÇØ ÁÖ¼¼¿ä.
#ifdef PG_MODULE_MAGIC PG_MODULE_MAGIC; #endif
±× Äڵ带 ¸±¸®½º 8.2º¸´Ù ÀÌÀüÀÇ PostgreSQL¿ëÀ¸·Î ÄÄÆÄÀÏ ÇÒ Çʿ䰡 ¾øÀ¸¸é, #ifdefÅ×½ºÆ®¸¦ »ý·« ÇÒ ¼ö ÀÖ½À´Ï´Ù.
ÃÖÃÊ·Î »ç¿ëµÈ ÈÄ¿¡, µ¿ÀûÀ¸·Î ·Îµå µÈ °´Ã¼´Â ¸Þ¸ð¸® ³»¿¡ º¸°ü À¯ÁöµË´Ï´Ù. µ¿ÀÏ ¼¼¼Ç¿¡ ´ëÇØ ±× ÆÄÀÏ ³»ÀÇ ÇÔ¼ö¸¦ ÇâÈÄ¿¡ È£ÃâÇßÀ» °æ¿ì, ½Éº¼ Å×ÀÌºí °Ë»ö¿¡ ÇÊ¿äÇÑ ÀÛÀº ¿À¹öÇìµå ¹Û¿¡ °É¸®Áö ¾Ê½À´Ï´Ù. ¿¹¸¦ µé¸é ÀçÄÄÆÄÀÏ ÇÑ ÈÄ Ã³·³, ±× °´Ã¼ ÆÄÀÏÀ» °Á¦ÀûÀ¸·Î ÀçÂ÷ ·ÎµåÇÏ°Ô ÇÒ Çʿ䰡 ÀÖ´Â °æ¿ì´Â, LOAD ¸í·ÉÀ» »ç¿ëÇϰųª »õ·Î¿î ¼¼¼ÇÀ» ½ÃÀÛÇØ ÁÖ¼¼¿ä.
»ý·« ÇÒ ¼öµµ ÀÖ½À´Ï´Ù¸¸, µ¿ÀûÀ¸·Î ·Îµå µÇ´Â ÆÄÀÏ¿¡, ÃʱâÈ Ã³¸® ÇÔ¼ö¿Í ÃÖÁ¾ ó¸® ÇÔ¼ö¸¦ Æ÷ÇÔÇÒ ¼ö°¡ ÀÖ½À´Ï´Ù.
_PG_init¶ó°í ÇÏ´Â ÇÔ¼ö°¡ ÆÄÀÏ¿¡ Á¸ÀçÇϸé, ÀÌ ÇÔ¼ö´Â ÆÄÀÏÀÌ ·Îµå µÈ Á÷ÈÄ¿¡ ºÒ·Á °©´Ï´Ù.
_PG_fini¶ó°í ÇÏ´Â ÇÔ¼ö°¡ ÆÄÀÏ¿¡ Á¸ÀçÇϸé, ÀÌ ÇÔ¼ö´Â ÆÄÀÏÀÌ ¾ð·ÎµåµÇ±â Á÷Àü¿¡ ºÒ·Á °©´Ï´Ù.
¶Ç, ÀÌ ÇÔ¼ö´Â ÀÎÀÚ¸¦ ÃëÇÏÁö ¾Ê°í ºó °ªÀ» µ¹·ÁÁÖÁö ¾ÊÀ¸¸é ¾ÈµË´Ï´Ù.
_PG_fini°¡ ÆÄÀÏÀÇ ¾ð·Îµå½Ã¿¡¸¸ ºÒ·Á °¡´Â °ÍÀ¸·Î, ó¸®ÀÇ Á¾·á½Ã¿¡ ºÒ·Á °¡´Â °ÍÀÌ ¾Æ´Ñ °Í¿¡ ÁÖÀÇÇØ ÁÖ¼¼¿ä.
(ÇöÀç, ¾ð·Îµå´Â ¸í½ÃÀûÀÎ LOAD¸í·É¿¡ ÀÇÇÑ ÆÄÀÏ Àç·ÎµåÀÇ ¹®¸Æ¿¡¼¸¸ ¹ß»ýÇÕ´Ï´Ù. )
C¾ð¾î ÇÔ¼öÀÇ ÀÛ¼º ¹æ¹ýÀ» ÀÌÇØÇϱâ À§Çؼ´Â, PostgreSQL°¡ ±âº» µ¥ÀÌÅÍÇüÀ» ³»ºÎ¿¡¼ ¾î¶»°Ô Ç¥ÇöÇØ, ¾î¶»°Ô ±×°ÍµéÀ» ÇÔ¼ö·Î ±³È¯Çϰí ÀÖ´ÂÁö¸¦ ÀÌÇØÇÒ Çʿ䰡 ÀÖ½À´Ï´Ù. ³»ºÎÀûÀ¸·Î PostgreSQL´Â ±âº»ÇüÀ» "¸Þ¸ð¸®ÀÇ ÀÛÀº µ¢¾î¸®"·Î °£ÁÖÇÕ´Ï´Ù. ¾î¶°ÇÑ ÇüŸ¦ Á¤ÀÇÇÏ´Â »ç¿ëÀÚ Á¤ÀÇ ÇÔ¼ö´Â, ¹Ù²Ù¾î ¸»Çϸé, PostgreSQL°¡ ±×°ÍÀ» Á¶ÀÛÇÒ ¼ö ÀÖ´Â ¹æ¹ýÀ» Á¤ÀÇÇÕ´Ï´Ù. Áï, PostgreSQL´Â µ¥ÀÌÅÍÀÇ ÀúÀå, µð½ºÅ©·ÎºÎÅÍÀÇ Ãëµæ¸¸À» ½Ç½ÃÇØ, µ¥ÀÌÅÍÀÇ ÀÔ·ÂÀ̳ª ó¸®, Ãâ·Â¿¡´Â »ç¿ëÀÚ Á¤ÀÇ ÇÔ¼ö¸¦ »ç¿ëÇÕ´Ï´Ù.
±âº»ÇüÀº ¾Æ·¡¿Í °°Àº ¼¼ °¡Áö Áß ÇϳªÀÇ ³»ºÎ ¼½ÄÀ» »ç¿ëÇϰí ÀÖ½À´Ï´Ù.
°íÁ¤ ±æÀÌÀÇ °ª Àεµ
°íÁ¤ ±æÀÌÀÇ ÂüÁ¶ Àεµ
°¡º¯ ±æÀÌÀÇ ÂüÁ¶ Àεµ
°ªÀεµ´Â, 1, 2, 4¹ÙÀÌÆ® ±æÀÌÀÇ ÇüŸ¸ÀÌ »ç¿ë °¡´ÉÇÕ´Ï´Ù(»ç¿ëÇÏ´Â ¸Ó½ÅÀÇ sizeof(Datum)°¡ 8ÀÇ °æ¿ì´Â 8¹ÙÀÌÆ®³ª °¡´ÉÇÕ´Ï´Ù). µ¥ÀÌÅÍÇüÀ» Á¤ÀÇÇÒ ¶§, ±× ÇüŰ¡ ¸ðµç ¾ÆÅ°ÅØÃÄ¿¡ ´ëÇØ µ¿ÀÏÇÑ Å©±â(¹ÙÀÌÆ®¼ö)°¡ µÇµµ·Ï Á¤ÀÇÇϵµ·Ï ÁÖÀÇÇØ ÁÖ¼¼¿ä. ¿¹¸¦ µé¸é, longÇüÀº ¸Ó½Å¿¡ µû¶ó¼´Â 4¹ÙÀÌÆ®³ª 8¹ÙÀÌÆ®À̱⠶§¹®¿¡ À§ÇèÇÏÁö¸¸, intÇüÀº ´ëºÎºÐÀÇ Unix ¸Ó½Å¿¡¼´Â 4¹ÙÀÌÆ®ÀÔ´Ï´Ù. Unix ¸Ó½Å¿¡ ÀÖ¾î¼ÀÇ int4ÀÇ ÀÌ·ÐÀûÀÎ ±¸ÇöÀº ÀÌÇÏ¿Í °°ÀÌ µË´Ï´Ù.
/* 4-byte integer, passed by value */ typedef int int4;
ÇÑÆí, ÀÓÀÇÀÇ Å©±âÀÇ °íÁ¤ ±æÀÌÀÇ ÇüÅ´ ÂüÁ¶·Î¼ ÀεµÇÏ´Â °ÍÀÌ °¡´ÉÇÕ´Ï´Ù. ¿¹·Î¼ ÀÌÇÏ¿¡ PostgreSQLÀÇ ÇüÅÂÀÇ ±¸Çö »ùÇÃÀ» ³ªÅ¸³À´Ï´Ù.
/* 16 ¹ÙÀÌÆ® ±¸Á¶Ã¼, ÂüÁ¶ Àεµ */
typedef struct
{
double x, y;
} Point;
±×·¯ÇÑ ÇüÅÂÀÇ Æ÷ÀÎÅ͸¸ÀÌ PostgreSQLÇÔ¼öÀÇ ÀÔÃâ·Â½Ã¿¡ »ç¿ëÇÒ ¼ö ÀÖ½À´Ï´Ù. ±×·¯ÇÑ ÇüÅÂÀÇ °ªÀ» µ¹·ÁÁÖ±â À§Çؼ´Â, palloc()¸¦ »ç¿ëÇØ ¿Ã¹Ù¸¥ Å©±âÀÇ ¸Þ¸ð¸® ¿µ¿ªÀ» ÇÒ´çÇØ ±× ¸Þ¸ð¸® ¿µ¿ª¿¡ °ªÀ» ÀÔ·ÂÇØ, ±×°ÍÀÇ Æ÷ÀÎÅ͸¦ µ¹·ÁÁÝ´Ï´Ù (¶Ç, ÀÔ·Â ÀÎÀÚÀÇ Çϳª¿Í °°Àº ÇüÅÂÀÇ °°Àº °ªÀ» µ¹·ÁÁÖ°í ½ÍÀº °ÍÀ̸é, palloc¸¦ ½Ç½ÃÇÏ´Â ¼ö°í¸¦ »ý·«ÇÒ ¼ö°¡ ÀÖ½À´Ï´Ù. ÀÌ °æ¿ì´Â ÀԷ°ª¿¡ Æ÷ÀÎÅ͸¦ ´ÜÁö µ¹·ÁÁÖ¼¼¿ä).
¸¶Áö¸·À¸·Î, ¸ðµç °¡º¯ ±æÀÌÇüÀº ÂüÁ¶·Î¼ ÀεµÇÒ Çʿ䰡 ÀÖ½À´Ï´Ù. ¶Ç, ¸ðµç °¡º¯ ±æÀÌÇüÀº Á¤È®ÇÏ°Ô 4¹ÙÀÌÆ®ÀÇ length Çʵå·ÎºÎÅÍ ½ÃÀÛµÉ Çʿ䰡 ÀÖ¾î, ±× ÇüÅ¿¡ ÀúÀåµÇ´Â ¸ðµç µ¥ÀÌÅÍ´Â length ÇʵåÀÇ ¹Ù·Î ÈÄÀÇ ¸Þ¸ð¸® ¿µ¿ª¿¡ ³õ¿©Áú Çʿ䰡 ÀÖ½À´Ï´Ù. length Çʵ忡´Â ±× ±¸Á¶ÀÇ ÃÑ ±æÀ̰¡ ÀúÀåµË´Ï´Ù. Áï, length ÇÊµå ±× ÀÚüµµ ±× Å©±â¿¡ Æ÷ÇԵ˴ϴÙ.
| Warning |
|
ÂüÁ¶ ÀεµÀÇ ÀԷ°ªÀÇ ³»¿ëÀ» °áÄÚ º¯°æÇÏÁö ¸»¾Æ ÁÖ¼¼¿ä. ÁöÁ¤ÇÑ Æ÷ÀÎÅͰ¡ µð½ºÅ© ¹öÆÛ¸¦ Á÷Á¢ Áö½ÃÇϰí ÀÖÀ» °¡´É¼ºÀÌ ÀÚÁÖ Àֱ⠶§¹®¿¡, º¯°æÇÏ¸é µð½ºÅ©»óÀÇ µ¥ÀÌÅ͸¦ ÆÄ±«ÇØ ¹ö¸±Áöµµ ¸ð¸¨´Ï´Ù. ÀÌ ±ÔÄ¢ÀÇ À¯ÀÏÇÑ ¿¹¿Ü¿¡ ´ëÇØ Section 33.10·Î ¼³¸íÇÕ´Ï´Ù. |
¿¹¸¦ µé¸é, textÇüÀ» Á¤ÀÇÇÏ·Á¸é, ¾Æ·¡¿Í °°ÀÌ ½Ç½ÃÇÒ ¼ö ÀÖ½À´Ï´Ù.
typedef struct {
int4 length;
char data[1];
} text;
¿©±â¼ ¼±¾ðµÈ µ¥ÀÌÅÍ Çʵå´Â, ºÐ¸íÇÏ°Ô ¸ðµç ÃëÇÒ ¼ö ÀÖ´Â ¹®ÀÚ¿À» º¸°ü À¯ÁöÇÒ ¼ö ÀÖ´Â ±æÀ̰¡ ¾Æ´Õ´Ï´Ù. C¾ð¾î¿¡¼´Â °¡º¯ ±æÀÌÀÇ ±¸Á¶¸¦ Á¤ÀÇÇÏ´Â °ÍÀº ºÒ°¡´ÉÇϹǷÎ, CÄÄÆÄÀÏ·¯´Â ¹è¿ÀÇ Ã·ÀÚÀÇ ¹üÀ§ °Ë»ç¸¦ ½Ç½ÃÇÏÁö ¾Ê´Â´Ù´Â »ç½Ç¿¡ ÀÇÁ¸ÇÕ´Ï´Ù. ÇÊ¿äÇÑ ¿µ¿ª·®À» ÇÒ´çÇØ ¸¶Ä¡ ¿Ã¹Ù¸¥ ±æÀÌ·Î ¼±¾ðµÈ °Í °°ÀÌ, ¹è¿·Î¼ Á¢±Ù ÇÒ »ÓÀÔ´Ï´Ù (ÀÌ ¼ö¹ýÀº ÀÚÁÖ »ç¿ëµË´Ï´Ù. C¾ð¾î¿¡ °üÇÑ ¸¹Àº ¼ÀûÀ¸·Î ¼³¸íµÇ°í ÀÖ½À´Ï´Ù).
°¡º¯ ±æÀÌÇüÀ» Á¶ÀÛÇÒ ¶§, Á¤È®ÇÑ Å©±âÀÇ ¸Þ¸ð¸®¸¦ ÇÒ´çÇØ length Çʵ带 Á¤È®ÇÏ°Ô ¼³Á¤ÇÏ´Â °Í¿¡ ÁÖÀÇÇÒ Çʿ䰡 ÀÖ½À´Ï´Ù. ¿¹¸¦ µé¸é, 40¹ÙÀÌÆ®¸¦ text±¸Á¶¿¡ º¸°ü À¯Áö½ÃŰ°í ½ÍÀº °æ¿ì, ¾Æ·¡¿Í °°Àº Äڵ带 »ç¿ëÇÕ´Ï´Ù.
#include "postgres.h" ... char buffer[40]; /* our source data */ ... text *destination = (text *) palloc(VARHDRSZ + 40); destination->length = VARHDRSZ + 40; memcpy(destination->data, buffer, 40); ...
VARHDRSZ´Â sizeof(int4)¿Í µ¿ÀÏÇÕ´Ï´Ù¸¸, °¡º¯ ±æÀÌÇüÀÇ ¿À¹öÇìµåÀÇ Å©±â¸¦ ÂüÁ¶ÇÒ ¶§¿¡´Â, VARHDRSZ¸ÅÅ©·Î¸¦ »ç¿ëÇÏ´Â ÆíÀÌ ¹Ù¶÷Á÷ÇÑ Çü½ÄÀ¸·Î °£ÁÖÇØÁö°í ÀÖ½À´Ï´Ù.
Table 33-1´Â, PostgreSQLÀÇ ³»ÀåÇüÀ» »ç¿ëÇÏ´Â C¾ð¾î ÇÔ¼ö¸¦ ÀÛ¼ºÇÒ ¶§ÀÇ, CÀÇ ÇüÅÂ¿Í SQLÇü°úÀÇ ´ëÀÀÀ» ÁöÁ¤ÇÑ °ÍÀÔ´Ï´Ù. "Á¤ÀÇ Àå¼Ò"¿¿¡¼´Â, ÇüÅ Á¤ÀǸ¦ ²¨³»±â À§Çؼ Æ÷ÇÔÇØ¾ß ÇÏ´Â Çì´õ ÆÄÀÏÀ» ³ªÅ¸³»°í ÀÖ½À´Ï´Ù (½ÇÁ¦ÀÇ Á¤ÀÇ´Â ÆÄÀÏ¿¡ ¿¶÷µÈ °Í°ú´Â ´Ù¸¦ °¡´É¼ºÀÌ ÀÖ½À´Ï´Ù. »ç¿ëÀÚ°¡ Á¤ÀÇµÈ ÀÎÅÍÆäÀ̽º¸¦ ¾ö¼öÇÏ´Â °ÍÀ» ÃßõµÇ°í ÀÖ½À´Ï´Ù). postgres.h¿¡´Â ¹Ýµå½Ã ÇÊ¿äÇÑ ¸¹Àº °ÍÀÌ ¼±¾ðµÇ°í Àֱ⠶§¹®¿¡, ¹Ýµå½Ã óÀ½¿¡ ¼Ò½º ÆÄÀÏ¿¡ ÀÌ ÆÄÀÏÀ» Æ÷ÇÔÇØ¾ß ÇÏ´Â °Í¿¡ ÁÖÀÇÇØ ÁÖ¼¼¿ä.
Table 33-1. ³»ÀåÇü SQLÇü¿¡ »óÀÀÇÏ´Â CÀÇ ÇüÅÂ
| SQLÇü | C ¾ð¾îÇü | Á¤ÀÇ Àå¼Ò |
|---|---|---|
| abstime | AbsoluteTime | utils/nabstime.h |
| boolean | bool | postgres.h(ÄÄÆÄÀÏ·¯·Î Â¥³Ö¾î ³¡³ °¡´É¼ºÀÌ ÀÖ½À´Ï´Ù) |
| box | BOX* | utils/geo_decls.h |
| bytea | bytea* | postgres.h |
| "char" | char | (ÄÄÆÄÀÏ·¯·Î ³»ÀåÀÌ ³¡³ »óÅÂ) |
| character | BpChar* | postgres.h |
| cid | CommandId | postgres.h |
| date | DateADT | utils/date.h |
| smallint (int2) | int2 or int16 | postgres.h |
| int2vector | int2vector* | postgres.h |
| integer (int4) | int4 or int32 | postgres.h |
| real (float4) | float4* | postgres.h |
| double precision (float8) | float8* | postgres.h |
| interval | Interval* | utils/timestamp.h |
| lseg | LSEG* | utils/geo_decls.h |
| name | Name | postgres.h |
| oid | Oid | postgres.h |
| oidvector | oidvector* | postgres.h |
| path | PATH* | utils/geo_decls.h |
| point | POINT* | utils/geo_decls.h |
| regproc | regproc | postgres.h |
| reltime | RelativeTime | utils/nabstime.h |
| text | text* | postgres.h |
| tid | ItemPointer | storage/itemptr.h |
| time | TimeADT | utils/date.h |
| time with time zone | TimeTzADT | utils/date.h |
| timestamp | Timestamp* | utils/timestamp.h |
| tinterval | TimeInterval | utils/nabstime.h |
| varchar | VarChar* | postgres.h |
| xid | TransactionId | postgres.h |
¿©±â±îÁö ±âº»Çü¿¡ °üÇØ¼ ÀÖÀ» ¼ö ÀÖ´Â ±¸Á¶ÀÇ ¸ðµÎ¸¦ ±â¼úÇßÀ¸¹Ç·Î, ½ÇÁ¦ÀÇ ÇÔ¼öÀÇ ¿¹¸¦ ¸î °³ °¡¸®Å³ ¼ö°¡ ÀÖ½À´Ï´Ù.
ÇöÀç´Â ºñÃßõÇÏÁö¸¸ ÀÌÇØÇϱ⠽±±â ¶§¹®¿¡, ÃÖÃÊ·Î "¿À·¡µÈ ½ºÅ¸ÀÏ"ÀÇ È£Ãâ ±Ô¾àÀ» ±â¼úÇÕ´Ï´Ù. ¹öÀü-0 ¹æ¹ý¿¡¼´Â, CÇÔ¼öÀÇ ÀÎÀÚ¿Í °á°ú´Â, Åë»óÀÇ CÀÇ ¹æ¹ý°ú °°Àº Çü½Ä¿¡¼ ½Ç½ÃÇÕ´Ï´Ù¸¸, »ó±âÀÇ ¼³¸í°ú °°ÀÌ, °¢ SQLÀÇ µ¥ÀÌÅÍÇüÀ» ³ªÅ¸³»´Â C¾ð¾î¸¦ »ç¿ë¿¡´Â ÁÖÀÇÇØ ÁÖ¼¼¿ä.
ÀÌÇÏ¿¡ ¸î °³ÀÇ ¿¹¸¦ ³ªÅ¸³À´Ï´Ù.
#include "postgres.h"
#include <string.h>
/* °ªÀεµ */
int
add_one(int arg)
{
return arg + 1;
}
/* °íÁ¤ÀåÀÇ ÂüÁ¶ Àεµ */
float8 *
add_one_float8(float8 *arg)
{
float8 *result = (float8 *) palloc(sizeof(float8));
*result = *arg + 1.0;
return result;
}
Point *
makepoint(Point *pointx, Point *pointy)
{
Point *new_point = (Point *) palloc(sizeof(Point));
new_point->x = pointx->x;
new_point->y = pointy->y;
return new_point;
}
/* °¡º¯ ±æÀÌÀÇ ÂüÁ¶ Àεµ */
text *
copytext(text *t)
{
/*
* VARSIZE´Â ±¸Á¶ÀÇ ÃÑ »çÀÌÁ ¹ÙÀÌÆ®¼ö·Î ³ªÅ¸³½ °ÍÀÔ´Ï´Ù.
*/
text *new_t = (text *) palloc(VARSIZE(t));
VARATT_SIZEP(new_t) = VARSIZE(t);
/*
* VARDATA´Â ±¸Á¶ÀÇ µ¥ÀÌÅÍ ¿µ¿ª¿¡ÀÇ Æ÷ÀÎÅÍÀÔ´Ï´Ù.
*/
memcpy((void *) VARDATA(new_t), /* destination */
(void *) VARDATA(t), /* source */
VARSIZE(t) - VARHDRSZ); /* how many bytes */
return new_t;
}
text *
concat_text(text *arg1, text *arg2)
{
int32 new_text_size = VARSIZE(arg1) + VARSIZE(arg2) - VARHDRSZ;
text *new_text = (text *) palloc(new_text_size);
VARATT_SIZEP(new_text) = new_text_size;
memcpy(VARDATA(new_text), VARDATA(arg1), VARSIZE(arg1) - VARHDRSZ);
memcpy(VARDATA(new_text) + (VARSIZE(arg1) - VARHDRSZ),
VARDATA(arg2), VARSIZE(arg2) - VARHDRSZ);
return new_text;
}
À§ÀÇ Äڵ尡 funcs.c¶ó´Â ÆÄÀÏ¿¡ ÁغñµÇ¾î °øÀ¯ °´Ã¼·Î¼ ÄÄÆÄÀÏÀÌ ³¡³ »óÅÂÀ̸é, ÀÌÇÏ¿Í °°Àº ¸í·ÉÀ¸·Î PostgreSQLÀÇ ÇÔ¼ö¸¦ Á¤ÀÇÇÒ ¼ö°¡ ÀÖ½À´Ï´Ù.
CREATE FUNCTION add_one(integer) RETURNS integer
AS '
DIRECTORY
/funcs', 'add_one'
LANGUAGE C STRICT;
-- "add_one"À̶ó°í ÇÏ´Â SQL ÇÔ¼ö¸íÀ» ¿À¹ö·ÎµåÇϰí ÀÖ´Â °Í¿¡ ÁÖÀÇ
CREATE FUNCTION add_one(double precision) RETURNS double precision
AS '
DIRECTORY
/funcs', 'add_one_float8'
LANGUAGE C STRICT;
CREATE FUNCTION makepoint(point, point) RETURNS point
AS '
DIRECTORY
/funcs', 'makepoint'
LANGUAGE C STRICT;
CREATE FUNCTION copytext(text) RETURNS text
AS '
DIRECTORY
/funcs', 'copytext'
LANGUAGE C STRICT;
CREATE FUNCTION concat_text(text, text) RETURNS text
AS '
DIRECTORY
/funcs', 'concat_text'
LANGUAGE C STRICT;
¿©±â¼, DIRECTORY ´Â °øÀ¯ ÆÄÀÏÀÇ µð·ºÅ丮 (¿¹¸¦ µé¸é, º»Àý·Î »ç¿ëÇÏ´Â ¿¹ÀÇ Äڵ尡 Æ÷ÇԵǴ PostgreSQLÆ©Å丮¾ó µð·ºÅ丮)¸¦ ³ªÅ¸³À´Ï´Ù (AS±¸Áß¿¡¼´Â ´ÜÁö 'funcs'¸¦ »ç¿ëÇØ, ´ÙÀ½¿¡ DIRECTORY ¸¦ °Ë»ö °æ·Î¿¡ Ãß°¡ÇÏ´Â ÆíÀÌ º¸´Ù ÁÁÀº ¹æ¹ýÀÔ´Ï´Ù. ¾î´À °æ¿ì¿¡¼µµ, ÀϹÝÀûÀ¸·Î . so³ª . sl°¡ »ç¿ëµÇ´Â, °øÀ¯ ¶óÀ̺귯¸®¿ëÀÇ ½Ã½ºÅÛ µ¶Æ¯ÇÑ È®ÀåÀÚ(extension)¸¦ »ý·« ÇÒ ¼ö°¡ ÀÖ½À´Ï´Ù).
¿©±â¼, ÇÔ¼ö¸¦ "¾ö¹Ð(strict)"ÇÏ°Ô ÁöÁ¤Çϰí ÀÖ´Â °Í¿¡ ÁÖ¸ñÇØ ÁÖ¼¼¿ä. À̰ÍÀº, ¸¸¾à ÀÔ·ÂµÈ °ªÀÌ NULL¿´À» °æ¿ì¿¡, ½Ã½ºÅÛÀÌ ÀÚµ¿ÀûÀ¸·Î µ¹¾Æ°¡ °á°úµµ NULLÀ̶ó°í °£ÁÖÇÏ´Â °ÍÀ» ÀǹÌÇÕ´Ï´Ù. À̰ÍÀ» ½Ç½ÃÇÏ´Â °Í¿¡ ÀÇÇØ, ÇÔ¼öÀÇ Äڵ忡 ÀԷ°ªÀÌ NULL°ªÀÎÁö üũ¸¦ ÇÒ Çʿ䰡 ¾ø¾îÁý´Ï´Ù. À̰ÍÀÌ ¾øÀ¸¸é, °¢ ÂüÁ¶ Àεµ ÀÎÀÚÀÇ NULL Æ÷ÀÎÅÍ¿¡ ´ëÇÑ Ã¼Å©¸¦ ½Ç½ÃÇÏ´Â µî, NULL°ªÀÇ ¸í½ÃÀûÀΠüũ¸¦ ½Ç½ÃÇÒ Çʿ䰡 ÀÖ¾î Áý´Ï´Ù. (°ªÀεµ ÀÎÀÚ¿¡ °üÇØ¼, üũ¸¦ ½Ç½ÃÇÏ´Â ¹æ¹ýÀº Á¸ÀçÇÏÁö ¾Ê½À´Ï´Ù).
ÀÌ·¯ÇÑ È£Ãâ ±Ô¾àÀº ¿ëÀÌÇÕ´Ï´Ù¸¸, ÀÌ ¹æ¹ýÀº, À̽ļºÀÇ ¸é¿¡¼ ±×´ÙÁö ¿ì¼öÇÏÁö ¾Ê½À´Ï´Ù. intÇüÀÇ °Íº¸´Ù ÀÛÀº µ¥ÀÌÅÍÇüÀ» ÀεµÇÏ´Â ºÎºÐ¿¡¼ ¹®Á¦¸¦ ¶°¾È°í ÀÖ´Â ¾ÆÅ°ÅØÃĵµ Á¸ÀçÇÕ´Ï´Ù. ¶Ç, ÇÔ¼öÀÇ °á°ú·Î¼ NULL¸¦ µ¹·ÁÁÖ´Â °£´ÜÇÑ ¹æ¹ýÀº ¾ø½À´Ï´Ù. °Ô´Ù°¡, ÀÎÀڷμ NULL¸¦ ó¸®ÇÏ´Â ¹æ¹ýÀ¸·Î¼´Â, ÇÔ¼ö¸¦ ¾ö¹ÐÇÑ °ÍÀ¸·Î ÇÏ´Â ÀÌ¿Ü ¹æ¹ýÀº ¾ø½À´Ï´Ù. ´ÙÀ½¿¡ ¼³¸íÇÏ´Â Version-1 ±Ô¾à¿¡¼´Â ÀÌ·¯ÇÑ ¹®Á¦°¡ ÇØ°áµÇ°í ÀÖ½À´Ï´Ù.
¹öÀü-1 È£Ã⠱Ծ࿡¼´Â, ÀÎÀÚ¿Í °á°úÀÇ ÀεµÀÇ º¹À⼺À» ¾ø¾Ö±â À§Çؼ ¸ÅÅ©·Î¸¦ »ç¿ëÇϰí ÀÖ½À´Ï´Ù. ¹öÀü-1ÇÔ¼öÀÇ C¾ð¾î ¼±¾ðÀº ¹Ýµå½Ã ¾Æ·¡¿Í °°ÀÌ ½Ç½ÃÇÕ´Ï´Ù.
Datum funcname(PG_FUNCTION_ARGS)
¶ÇÇÑ, ¸ÅÅ©·Î È£Ãâ
PG_FUNCTION_INFO_V1(funcname);
´Â, °°Àº ¼Ò½º ÆÄÀÏ¿¡ ¾²¿©Á® ÀÖ¾î¾ß ÇÕ´Ï´Ù (ÀϹÝÀûÀ¸·Î´Â, ÇÔ¼öÀÇ ¹Ù·Î ¾Õ¿¡ ¾²¿©Áý´Ï´Ù). PostgreSQL¿¡¼´Â ¸ðµç ³»ºÎ ÇÔ¼ö´Â ¹öÀü-1À̶ó°í ÀνÄÇϹǷÎ, ÀÌ ¸ÅÅ©·ÎÀÇ È£ÃâÀº internal¾ð¾î ÇÔ¼ö¿¡¼´Â ÇÊ¿ä ¾ø½À´Ï´Ù. ±×·¯³ª, µ¿ÀûÀ¸·Î ·Îµå µÇ´Â ÇÔ¼ö¿¡¼´Â ÇÊ¿äÇÕ´Ï´Ù.
¹öÀü-1ÇÔ¼ö¿¡¼´Â, °¢°¢ÀÇ ¿¸Å ÀÎÀÚ´Â, ÀÎÀÚÀÇ µ¥ÀÌÅÍÇü¿¡ ¸Â´Â PG_GETARG_
xxx
()¸ÅÅ©·Î¸¦ »ç¿ëÇØ
³ªµ· °á°ú´Â ¹Ýȯ°ªÀÇ ÇüÅ¿¡ ¸Â´Â PG_RETURN_
xxx
()¸ÅÅ©·Î¸¦ »ç¿ëÇØ µ¹·ÁÁÖ¾îÁý´Ï´Ù.
PG_GETARG_
xxx
()´Â, ±× ÀÎÀڷμ ²¨³»´Â ÇÔ¼ö ÀÎÀÚÀÇ ¹øÈ£¸¦ ÃëÇÕ´Ï´Ù.
PG_RETURN_
xxx
()´Â, ±× ÀÎÀڷμ ½ÇÁ¦·Î µ¹·ÁÁÖ´Â °ªÀ» ¹Þ½À´Ï´Ù.
»ó±â¿Í °°Àº ÇÔ¼ö¸¦ ¹öÀü-1 Çü½Ä¿¡ ±â¼úÇÑ °ÍÀ» ÀÌÇÏ¿¡ ³ªÅ¸³À´Ï´Ù.
#include "postgres.h"
#include <string.h>
#include "fmgr.h"
/* °ªÀεµ */
PG_FUNCTION_INFO_V1(add_one);
Datum
add_one(PG_FUNCTION_ARGS)
{
int32 arg = PG_GETARG_INT32(0);
PG_RETURN_INT32(arg + 1);
}
/* °íÁ¤ ±æÀÌÀÇ ÂüÁ¶ Àεµ */
PG_FUNCTION_INFO_V1(add_one_float8);
Datum
add_one_float8(PG_FUNCTION_ARGS)
{
/* FLOAT8¿ëÀÇ ¸ÅÅ©·Î´Â ÂüÁ¶ Àεµ¶ó´Â ¼ºÁúÀ» ¼û±é´Ï´Ù */
PG_RETURN_FLOAT8(arg + 1.0);
}
PG_FUNCTION_INFO_V1(makepoint);
Datum
makepoint(PG_FUNCTION_ARGS)
{
/* ¿©±âÀÇ PointÇüÀÇ ÂüÁ¶ Àεµ¶ó´Â ¼ºÁúÀº ¼û°ÜÁö°í ÀÖÁö ¾Ê½À´Ï´Ù */
Point *pointx = PG_GETARG_POINT_P(0);
Point *pointy = PG_GETARG_POINT_P(1);
Point *new_point = (Point *) palloc(sizeof(Point));
new_point->x = pointx->x;
new_point->y = pointy->y;
PG_RETURN_POINT_P(new_point);
}
/* °¡º¯ ±æÀÌÀÇ ÂüÁ¶ Àεµ */
PG_FUNCTION_INFO_V1(copytext);
Datum
copytext(PG_FUNCTION_ARGS)
{
text *t = PG_GETARG_TEXT_P(0);
/*
* VARSIZE´Â ±¸Á¶ÀÇ ÃÑ »çÀÌÁ ¹ÙÀÌÆ®¼ö·Î ³ªÅ¸³½ °ÍÀÔ´Ï´Ù.
*/
text *new_t = (text *) palloc(VARSIZE(t));
VARATT_SIZEP(new_t) = VARSIZE(t);
/*
* VARDATA´Â ±¸Á¶ÀÇ µ¥ÀÌÅÍ ¿µ¿ª¿¡ÀÇ Æ÷ÀÎÅÍÀÔ´Ï´Ù.
*/
memcpy((void *) VARDATA(new_t), /* destination */
(void *) VARDATA(t), /* source */
VARSIZE(t) - VARHDRSZ); /* how many bytes */
PG_RETURN_TEXT_P(new_t);
}
PG_FUNCTION_INFO_V1(concat_text);
Datum
concat_text(PG_FUNCTION_ARGS)
{
text *arg1 = PG_GETARG_TEXT_P(0);
text *arg2 = PG_GETARG_TEXT_P(1);
int32 new_text_size = VARSIZE(arg1) + VARSIZE(arg2) - VARHDRSZ;
text *new_text = (text *) palloc(new_text_size);
VARATT_SIZEP(new_text) = new_text_size;
memcpy(VARDATA(new_text), VARDATA(arg1), VARSIZE(arg1) - VARHDRSZ);
memcpy(VARDATA(new_text) + (VARSIZE(arg1) - VARHDRSZ),
VARDATA(arg2), VARSIZE(arg2) - VARHDRSZ);
PG_RETURN_TEXT_P(new_text);
}
CREATE FUNCTION¸í·ÉÀº, ¹öÀü-0°ú °°Àº °ÍÀÔ´Ï´Ù.
¾ð¶æ º¸±â¿¡, ¹öÀü-1ÀÇ ÄÚµù ±Ô¾àÀº ¹«ÀǹÌÇÑ °ÍÀ¸·Î º¸ÀÏÁöµµ ¸ð¸¨´Ï´Ù.
±×·¯³ª, ¸ÅÅ©·Î°¡ ÇÊ¿ä¾ø´Â Á¤º¸¸¦ ÀºÆóÇϰí ÀÖÀ¸¹Ç·Î, ´Ù¼öÀÇ °³¼±À» Çϰí ÀÖ½À´Ï´Ù.
¿¹¸¦ µé¸é, add_one_float8ÀÇ Äڵ忡¼´Â, float8°¡ ÂüÁ¶ ÀεµÀÎ °ÍÀ» ÀǽÄÇÒ Çʿ䰡 ¾ø¾îÁ³½À´Ï´Ù.
¶Ç ´Ù¸¥ ¿¹·Î¼´Â, °¡º¯ ±æÀÌÇüÀÇ GETARG¸ÅÅ©·Î´Â "TOAST µÈ"°ª(¾ÐÃà, ¶Ç´Â Çà¿Ü)ÀÌ Ãë±ÞÇÏ´Â Çʿ伺À» ÀºÆó ÇÕ´Ï´Ù.
¹öÀü-1ÇÔ¼öÀÇ ÇϳªÀÇ Å« °³¼±Á¡Àº, NULLÀÇ ÀÔ·Â/°á°úÀÇ Ã³¸® ´É·ÂÀÔ´Ï´Ù.
PG_ARGISNULL(
n
)¸ÅÅ©·Î¿¡ ÀÇÇØ ÇÔ¼ö´Â °¢ ÀÔ·ÂÀÌ NULLÀÎÁö ¾Æ´ÑÁö Å×½ºÆ®¸¦ ½Ç½ÃÇÒ ¼ö°¡ ÀÖ½À´Ï´Ù
(¹°·Ð À̰ÍÀº, "¾ö¹Ð"È÷ ¼±¾ðµÇ¾î ÀÖÁö ¾ÊÀº ÇÔ¼ö¿¡¼¸¸ ÇÊ¿äÇÕ´Ï´Ù).
PG_GETARG_
xxx
()¸ÅÅ©·Î¿¡¼´Â, ÀÔ·ÂµÈ ÀÎÀÚ´Â ½ÃÀÛµÇ¾î °ªÀ» 0À¸·Î¼ ¿°ÅÇÒ ¼ö ÀÖ½À´Ï´Ù.
ÀÎÀÚ°¡ NULL°¡ ¾Æ´Ñ °ÍÀ» È®ÀÎÇÒ ¶§±îÁö´Â, PG_GETARG_
xxx
()ÀÇ ½ÇÇàÀº »ï°¡ÇØ¾ß ÇÕ´Ï´Ù.
°á°úÀûÀ¸·Î NULL¸¦ µ¹·ÁÁÖ´Â °æ¿ì´Â, PG_RETURN_NULL()¸¦ ½ÇÇàÇÕ´Ï´Ù.
À̰ÍÀº, ¾ö¹ÐÇÑ ÇÔ¼ö¿Í ¾ö¹ÐÇÏÁö ¾ÊÀº ÇÔ¼öÀÇ ¾çÂÊ ¸ðµÎ·Î »ç¿ë °¡´ÉÇÕ´Ï´Ù.
»õ·Î¿î Çü½ÄÀÇ ÀÎÅÍÆäÀ̽º¿¡¼´Â, ±× ¿ÜÀÇ ¿É¼ÇÀ¸·Î¼ PG_GETARG_
xxx
()¸ÅÅ©·ÎÀÇ º¯ÇüÀ» 2°³ Á¦°øÇϰí ÀÖ½À´Ï´Ù.
ù¹øÂ° PG_GETARG_
xxx
_COPY()¿¡ ÀÇÇØ, ¾ÈÀüÇÏ°Ô ±âÀÔÇÒ ¼ö°¡ ÀÖ´Â ÁöÁ¤ ÀÎÀÚÀÇ º¹»ç°¡ È®½ÇÈ÷ µ¹¾Æ¿É´Ï´Ù
(Åë»óÀÇ ¸ÅÅ©·Î´Â, ¹°¸®ÀûÀ¸·Î Å×ÀÌºí¿¡ ÀúÀåµÇ°í ÀÖ´Â °ª¿¡ÀÇ Æ÷ÀÎÅ͸¦ µ¹·ÁÁÖ´Â ÀÏÀÌ ÀÖÀ¸¹Ç·Î, ±âÀÔµÇÁö ¾Ê½À´Ï´Ù.
PG_GETARG_
xxx
_COPY()¸ÅÅ©·Î¸¦ »ç¿ëÇÏ´Â °ÍÀ¸·Î ¾È½ÉÇØ °á°ú¿¡ ±âÀÔÇÒ ¼ö°¡ ÀÖ½À´Ï´Ù).
µÎ¹øÂ° º¯ÇüÀº, ÀÎÀÚ¸¦ 3°³ ÃëÇÏ´Â PG_GETARG_
xxx
_SLICE()¸ÅÅ©·Î·ÎºÎÅÍ µË´Ï´Ù.
ù¹øÂ°´Â ÇÔ¼öÀÇ ÀÎÀÚÀÇ ¼ö(»ó±â´ë·Î)ÀÔ´Ï´Ù.
µÎ¹øÂ°¿Í ¼¼¹øÂ°´Â, ¿ÀÇÁ¼Â(offset)°ú µ¹·ÁÁÖ¾îÁö´Â ¼¼±×¸ÕÆ®(segment)ÀÇ ±æÀÌÀÔ´Ï´Ù.
¿ÀÇÁ¼Â(offset)Àº Á¦·Î·ÎºÎÅÍ ½ÃÀ۵ǰí, ºÎÀÇ ±æÀÌ´Â ³ª¸ÓÁöÀÇ °ªÀ» µ¹·ÁÁÖ´Â °ÍÀ» ¿ä±¸ÇÕ´Ï´Ù.
ÀÌ·¯ÇÑ ¸ÅÅ©·Î¸¦ »ç¿ëÇϸé, ½ºÅ丮ÁöÀÇ ÇüŰ¡ "external"(¿ÜºÎ)ÀÎ Å« °ªÀÇ ÀϺο¡ Á¢±Ù ÇÒ ¶§¿¡ ¸Å¿ì È¿°úÀûÀÔ´Ï´Ù
(¿ÀÇ ½ºÅ丮ÁöÀÇ ÇüÅ´ ALTER TABLE
tablename
ALTER COLUMN
colname
SET STORAGE
storagetype
¸¦ »ç¿ëÇØ ÁöÁ¤ÇÒ ¼ö ÀÖ½À´Ï´Ù.
½ºÅ丮ÁöÀÇ ÇüÅ´Â, plain, external, extended, ¶Ç´Â main Áß¿¡ ÀÖ½À´Ï´Ù).
¸¶Áö¸·À¸·Î, ¹öÀü-1ÇÔ¼ö È£Ã⠱Ծ࿡¼´Â, °á°ú ÁýÇÕ(Section 33.9.10)À» µ¹·ÁÁÖ´Â °Í, ¹× Æ®¸®°Å ÇÔ¼ö(Chapter 34)¿Í ¼ö¼ÓÇü ¾ð¾îÀÇ È£Ãâ Çڵ鷯(Chapter 47)¸¦ ±¸ÇöÇÒ ¼ö°¡ ÀÖ½À´Ï´Ù. ¶Ç, ¹öÀü-1 ÄÚµå´Â, Ç¥ÁØ CÀÇ ÇÔ¼ö È£Ãâ ÇÁ·ÎÅäÄÝÀÇ Á¦¾àÀ» Áö۱⠶§¹®¿¡, ¹öÀü-0º¸´Ù À̽ļºÀÌ ÀÖ½À´Ï´Ù. ÀÚ¼¼ÇÑ °ÍÀº ¼Ò½º ¹èÆ÷¹° ³»ÀÇ src/backend/utils/fmgr/README¸¦ ÂüÁ¶ÇØ ÁÖ¼¼¿ä.
º¸´Ù ¹ßÀüµÈ ÈÁ¦¿¡ µé¾î°¡±â Àü¿¡, PostgreSQL C¾ð¾î ÇÔ¼öÀÇ ÄÚµù¿¡ ´ëÇÑ ±ÔÄ¢À» ¸î °³ ¼³¸íÇÕ´Ï´Ù. C¾ð¾î ÀÌ¿ÜÀÇ ¾ð¾î·Î ±â¼úÇÑ ÇÔ¼ö¸¦ PostgreSQL¿¡ ³»ÀåÇÏ´Â °ÍÀº °¡´ÉÇÕ´Ï´Ù¸¸, ¿¹¸¦ µé¸é C++, FORTRAN³ª Pascal¶ó°í ÇÏ´Â ¾ð¾î´Â C¾ð¾î¿Í °°Àº È£Ãâ°ú ±Ô¾à¿¡ µû¸£Áö ¾ÊÀ¸¹Ç·Î, ¸¹Àº °æ¿ì, (°¡´ÉÇß´Ù°í ÇØµµ)°ï¶õÇÕ´Ï´Ù. ±×°ÍÀº Áï, ´Ù¸¥ ¾ð¾î¿¡¼´Â °°Àº ¹æ¹ýÀ¸·Î ÇÔ¼ö¿¡ ÀÎÀÚ¸¦ °Ç³×Áְųª ÇÔ¼ö·ÎºÎÅÍ °á°ú¸¦ µ¹·ÁÁÖ´Â °ÍÀ» ½Ç½ÃÇÏÁö ¾Ê´Â´Ù´Â °ÍÀÔ´Ï´Ù. ÀÌ ¶§¹®¿¡, C¾ð¾î ÇÔ¼ö´Â ½ÇÁ¦·Î C¾ð¾î·Î ¾²¿©Á® ÀÖ´Â °ÍÀ¸·Î °¡Á¤ÇÕ´Ï´Ù.
CÇÔ¼öÀÇ ÀÛ¼º°ú ±¸ÃàÀÇ ±âº» ±ÔÄ¢À» ÀÌÇÏ¿¡ ³ªÅ¸³À´Ï´Ù.
pg_config --includedir-server¸¦ »ç¿ëÇØ, »ç¿ëÁßÀÇ ½Ã½ºÅÛ(ȤÀº »ç¿ëÀÚ°¡ ½ÇÇàÇÏ´Â ½Ã½ºÅÛ)¿¡¼ PostgreSQL¼¹öÀÇ Çì´õ ÆÄÀÏÀÌ ¼³Ä¡ µÈ Àå¼Ò¸¦ ã¾Æ³À´Ï´Ù.
PostgreSQL¿¡ µ¿ÀûÀ¸·Î ·ÎµåÇÒ ¼ö ÀÖµµ·Ï, µ¶ÀÚ Äڵ带 ÄÄÆÄÀÏ/¸µÅ©ÇÒ ¶§¿¡´Â Ç×»ó, Ưº°ÇÑ Ç÷¡±×°¡ ÇÊ¿äÇÕ´Ï´Ù. ƯÁ¤ÀÇ ¿î¿µ ½Ã½ºÅÛ¿¡ ÀÖ¾î¼ÀÇ ÄÄÆÄÀÏ/¸µÅ© ¹æ¹ý¿¡ ´ëÇØ¼´Â Section 33.9.6À» ÂüÁ¶ÇØ ÁÖ¼¼¿ä.
ÀØÁö ¸»°í Section 33.9.1·Î ¼³¸íÇÑ "¸¶¹ýÀÇ ºí·Ï"À» °øÀ¯ ¶óÀ̺귯¸®¿¡¼ Á¤ÀÇÇØ ÁÖ¼¼¿ä.
¸Þ¸ð¸®¸¦ ÇÒ´çÇÒ ¶§, C¶óÀ̺귯¸®ÀÇ malloc¿Ífree´Â ¾Æ´Ï°í,
PostgreSQLÀÇ palloc¿Í pfree¸¦ »ç¿ëÇØ ÁÖ¼¼¿ä.
palloc·Î ÇÒ´çÇÒ ¼ö ÀÖ¾ú´ø ¸Þ¸ð¸®´Â °¢ Æ®·£Àè¼ÇÀÇ ¸¶Áö¸·¿¡ ÀÚµ¿ÀûÀ¸·Î ÇØ¹æµÇ¾î ¸Þ¸ð¸® ´©¼ö¸¦ ¸·½À´Ï´Ù.
memset¸¦ »ç¿ëÇØ, ±¸Á¶¸¦ ¹Ýµå½Ã 0 Ŭ¸®¾î·Î ÇØ ÁÖ¼¼¿ä.
ÀÌ·¸°Ô ÇÏÁö ¾ÊÀ¸¸é ÇØ½Ã À妽º³ª ÇØ½Ã °áÇÕÀ» Áö¿øÇÏ´Â °ÍÀÌ °ï¶õÇÕ´Ï´Ù.
ÇØ½Ã¸¦ °è»êÇÏ·Á¸é, µ¥ÀÌÅÍ ±¸Á¶ ³»ÀÇ Àǹ̰¡ ÀÖ´Â ºñÆ®¸¸À» ²¨³¾ Çʿ䰡 Àֱ⠶§¹®¿¡ÀÔ´Ï´Ù.
±¸Á¶ÀÇ ¸ðµç Çʵ带 ÃʱâÈÇß´Ù°í ÇØµµ, ºÒÇÊ¿äÇÑ °ªÀ» °¡Áö´Â, ¿¬°è ÆÐµù(±¸Á¶³»ÀÇ ±¸¸Û)ÀÌ Á¸ÀçÇÒ °¡´É¼ºÀÌ ÀÖ½À´Ï´Ù.
´ëºÎºÐÀÇ PostgreSQLÀÇ ³»ºÎÇüÀº postgres.h¿¡ ¼±¾ðµÇ°í ÀÖ½À´Ï´Ù. ÇÑÆí, ÇÔ¼ö °ü¸® ÀÎÅÍÆäÀ̽º(PG_FUNCTION_ARGSµî)´Â fmgr.h·Î ¼±¾ðµÇ°í ÀÖ½À´Ï´Ù. µû¶ó¼, Àû¾îµµ ÀÌ 2°³ÀÇ ÆÄÀÏÀ» Æ÷ÇÔ ÇÒ Çʿ䰡 ÀÖ½À´Ï´Ù. À̽ļº¿¡ °üÇÑ ÀÌÀ¯¿¡ ÀÇÇØ, postgres.h¸¦ ±× ¿ÜÀÇ ½Ã½ºÅÛ Çì´õ ÆÄÀÏ, »ç¿ëÀÚ Çì´õ ÆÄÀϺ¸´Ù ¸ÕÀú Æ÷ÇÔ ÇØ µÎ´Â °ÍÀÌ ÃÖ¼±ÀÔ´Ï´Ù. postgres.h¸¦ Æ÷ÇÔÇÏ´Â °ÍÀº elog.h, palloc.hµµ Æ÷ÇÔÇÏ°Ô µË´Ï´Ù.
°´Ã¼ ÆÄÀÏ·Î Á¤Àǵǰí ÀÖ´Â ½Éº¼¸íÀº ¼·Î, ȤÀº PostgreSQL¼¹öÀÇ ½ÇÇà ÆÄÀÏ·Î Á¤Àǵǰí ÀÖ´Â °Í°ú ´Ù¸¦ Çʿ䰡 ÀÖ½À´Ï´Ù. À̰Ϳ¡ °üÇÑ ¿¡·¯°¡ Ç¥½ÃµÇ´Â °æ¿ì´Â, ÇÔ¼ö¸í ¶Ç´Â º¯¼ö¸¦ º¯°æÇÒ Çʿ䰡 ÀÖ½À´Ï´Ù.
C·Î ÀÛ¼ºµÈ PostgreSQLÀÇ È®Àå ÇÔ¼ö¸¦ »ç¿ëÇϱâ À§Çؼ´Â ¼¹ö¿¡ ÀÇÇØ µ¿ÀûÀ¸·Î ·ÎµåµÉ ¼ö ÀÖµµ·Ï Ưº°ÇÑ ¹æ¹ýÀ» ÅëÇØ ÄÄÆÄÀϰú ¸µÅ©¸¦ ÇØ¾ßÇÒ Çʿ䰡 ÀÖ½À´Ï´Ù. Á¤È®ÇϰԴ°øÀ¯ ¶óÀ̺귯¸®¸¦ ¸¸µé Çʿ䰡 ÀÖ½À´Ï´Ù.
Ãß°¡ÀûÀÎ Á¤º¸´Â operating systemÀÇ ¹®¼, ƯÈ÷ CÄÄÆÄÀÏ·¯, cc ±×¸®°í ¸µÅ© ¿¡µðÅÍ, ldÀÇ ¸Þ´º¾ó ÆäÀÌÁö¸¦ ÂüÁ¶ÇØ Áֽʽÿä. ¶ÇÇÑ, PostgreSQLÀÇ ¿ø½Ã ÄÚµå´Â contribµð·ºÅ丮 ³»¿¡¼ ½Ç·Ê¸¦ Æ÷ÇÔÇϰí ÀÖ½À´Ï´Ù. ±×·¯³ª ÀÌ·¯ÇÑ ¿¹Á¦¿¡ ÀÇÁ¸À» ÇÏ°Ô µÇ¸é PostgreSQL ¿ø½ÃÄÚµåÀÇ À¯È¿¼º¿¡ ÀÇÁ¸ÇÑ ¸ðµâÀÌ ¸¸µéÁö°Ô µË´Ï´Ù.
°øÀ¯¶óÀ̺귯¸®¸¦ »ý¼ºÇÏ´Â °ÍÀº ÀϹÝÀûÀ¸·Î ½ÇÇà ÇÁ·Î±×·¥ÀÇ ¸µÅ©¿Í À¯»çÇÕ´Ï´Ù. ¿ì¼± ¿ø½Ã ÆÄÀÏÀÌ ¿ÀºêÁ§Æ® ÆÄÀÏ¿¡ ÄÄÆÄÀÏ µÈ ÈÄ ¿ÀºêÁ§Æ® ÆÄÀÏ °£ÀÇ ¸µÅ©°¡ ÀÌ·ç¾îÁý´Ï´Ù. ÀÌ·¯ÇÑ ¿ÀºêÁ§Æ® ÆÄÀÏÀº À§Ä¡¿¡ µ¶¸³ÀûÀÎ ÄÚµå(PIC)·Î¼ ¸¸µé¾îÁ®¾ß ÇÕ´Ï´Ù. ¶õ °³³äÀûÀ¸·Î´Â ½ÇÇàÇÁ·Î±×·¥¿¡ ÀÇÇØ ·ÎµåµÇ¾îÁú ¶§ ¸Þ¸ð¸® »óÀÇ ÀÓÀÇÀÇ Àå¼Ò¿¡ À§Ä¡µÇ¾îÁú ¼ö ÀÖ´Ù´Â °ÍÀ» ÀǹÌÇÕ´Ï´Ù. (½ÇÇà ÇÁ·Î±×·¥¿ëÀ¸·Î ¸¸µé¾îÁø ¿ÀºêÁ§Æ® ÆÄÀÏÀº ÀÌ·¯ÇÑ ¹æ¹ýÀ¸·Î ÄÄÆÄÀϵÇÁö ¾Ê½À´Ï´Ù.) °øÀ¯ ¶óÀ̺귯¸®¸¦ ¸µÅ©ÇÏ´Â ¸í·É¹®Àº ½ÇÇà ÇÁ·Î±×·¥ÀÇ ¸µÅ©¿Í ±¸º°µÇ±â ¿ìÇÑ Æ¯º°ÇÑ Ç÷¡±×¸¦ °¡Áý´Ï´Ù. (À̷лóÀ¸·Î ±×·¯Çϸç, ´Ù¸¥ ½Ã½ºÅÛ¿¡¼ ½ÇÁ¦ Á» ´õ Ãß¾ÇÇÏ°Ô º¸¿©Áý´Ï´Ù.)
´ÙÀ½ÀÇ ¿¹¸¦ ÅëÇØ file foo.c ¾È¿¡ ¿ø½Ã Äڵ尡 ÀÖ´Ù°í °¡Á¤Çϰí, foo.so °øÀ¯ ¶óÀ̺귯¸®¸¦ ¸¸µé °ÍÀÔ´Ï´Ù. Áß°£ÀÇ ¿ÀºêÁ§Æ® ÆÄÀÏÀº Ưº°ÇÑ ¾ð±ÞÀÌ ¾ø´Â ÇÑ foo.oÀ¸·Î ºÒ¸± °ÍÀÔ´Ï´Ù. °øÀ¯ ¶óÀ̺귯¸®´Â ÇÑ °³ ÀÌ»óÀÇ ¿ÀºêÁ§Æ® ÆÄÀÏÀ» °¡Áú ¼ö ÀÖÀ¸³ª, ¿©±â¿¡¼´Â ÇÑ °¡Áö¸¸ »ç¿ëÇÏ¿´½À´Ï´Ù.
PIC¸¦ ¸¸µé±â À§ÇÑ ÄÄÆÄÀÏ·¯ Ç÷¡±×´Â -fpicÀÔ´Ï´Ù. °øÀ¯ ¶óÀ̺귯¸®¸¦ »ý¼ºÇÏ´Â ¸µÅ© Ç÷¡±×´Â-sharedÀÔ´Ï´Ù.
gcc -fpic -c foo.c ld -shared -o foo.so foo.o
À§´Â ¹öÀü 4.0¿¡¼ Àû¿ëµË´Ï´Ù.
PIC¸¦ ¸¸µé±â À§ÇÑ ÄÄÆÄÀÏ·¯ Ç÷¡±×´Â-fpicÀÔ´Ï´Ù. °øÀ¯ ¶óÀ̺귯¸®¸¦ ¸¸µå´Â ÄÄÆÄÀÏ·¯ Ç÷¡±×´Â-sharedÀÔ´Ï´Ù.
gcc -fpic -c foo.c gcc -shared -o foo.so foo.o
À§´Â FreeBSDÀÇ ¹öÀü 3.0¿¡¼ Àû¿ëµË´Ï´Ù.
PIC¸¦ ¸¸µé±â À§ÇÑ ½Ã½ºÅÛ ÄÄÆÄÀÏ·¯ÀÇ ÄÄÆÄÀÏ·¯ Ç÷¡±×´Â+zÀÔ´Ï´Ù. GCC¸¦ »ç¿ëÇÏ´Â °æ¿ì´Â-fpicÀÔ´Ï´Ù. °øÀ¯ ¶óÀ̺귯¸®¸¦ À§ÇÑ ¸µÅ© Ç÷¡±×´Â-bÀÔ´Ï´Ù. µû¶ó¼, ÀÌÇÏ¿Í °°ÀÌ µË´Ï´Ù.
cc +z -c foo.c
or
gcc -fpic -c foo.c
±×¸®°í
ld -b -o foo.sl foo.o
HP-UX´Â ´ëºÎºÐÀÇ ´Ù¸¥ ½Ã½ºÅÛ°ú ´Þ¸® °øÀ¯ ¶óÀ̺귯¸®¿¡ . sl¶ó°í ÇÏ´Â È®ÀåÀÚ(extension)¸¦ »ç¿ëÇÕ´Ï´Ù.
PIC´Â µðÆúÆ®·Î Ưº°ÇÑ ÄÄÆÄÀÏ·¯ ¿É¼ÇÀº ÇÊ¿äÇÏÁö ¾Ê½À´Ï´Ù. °øÀ¯ ¶óÀ̺귯¸®¸¦ ¸¸µé±â À§ÇÑ ¸µÅ© ¿É¼ÇÀº-sharedÀÔ´Ï´Ù.
cc -c foo.c ld -shared -o foo.so foo.o
PIC¸¦ ¸¸µé±â À§ÇÑ ÄÄÆÄÀÏ·¯ Ç÷¡±×´Â-fpicÀÔ´Ï´Ù. ¸î°¡Áö »óȲ¿¡¼ ¸î¸îÀÇ Ç÷§ÆûÀº -fpic°¡ µ¿ÀÛÇÏÁö ¾ÊÀ» °æ¿ì, -fPIC¸¦ »ç¿ëÇØ¾ß¸¸ ÇÕ´Ï´Ù. º¸´Ù ¸¹Àº Á¤º¸¸¦ ¿øÇϽô ºÐÀº GCCÀÇ ¸Þ´º¾óÀ» ÂüÁ¶ÇØ Áֽʽÿä. °øÀ¯ ¶óÀ̺귯¸®¸¦ ¸¸µé±â À§ÇÑ ÄÄÆÄÀÏ·¯ Ç÷¡±×´Â-sharedÀÔ´Ï´Ù. ¿ÏÀüÇÑ ¿¹´Â ´ÙÀ½°ú °°½À´Ï´Ù.
cc -fpic -c foo.c cc -shared -o foo.so foo.o
¾Æ·¡ÀÇ ¿¹´Â °³¹ßÀÚ¿ë ÅøÀÌ ¼³Ä¡µÈ °ÍÀ» ÀüÁ¦·Î Çϰí ÀÖ½À´Ï´Ù.
cc -c foo.c cc -bundle -flat_namespace -undefined suppress -o foo.so foo.o
PIC¸¦ ¸¸µé±â À§ÇÑ ÄÄÆÄÀÏ·¯ Ç÷¡±×´Â-fpicÀÔ´Ï´Ù. ELF½Ã½ºÅÛ¿¡¼´Â ÄÄÆÄÀÏ·¯°¡ -sharedÇ÷¡±×¸¦ »ç¿ëÇØ °øÀ¯ ¶óÀ̺귯¸®¸¦ ¸µÅ©ÇÕ´Ï´Ù. º¸´Ù ¿À·¡µÈ non-ELF ½Ã½ºÅÛ¿¡¼´Â ld -Bshareable¸¦ »ç¿ëÇÕ´Ï´Ù.
gcc -fpic -c foo.c gcc -shared -o foo.so foo.o
PIC¸¦ ¸¸µé±â À§ÇÑ ÄÄÆÄÀÏ·¯ Ç÷¡±×´Â-fpicÀÔ´Ï´Ù. °øÀ¯ ¶óÀ̺귯¸®¿¡ ¸µÅ©ÇÏ·Á¸éld -Bshareable¸¦ »ç¿ëÇÕ´Ï´Ù.
gcc -fpic -c foo.c ld -Bshareable -o foo.so foo.o
PIC¸¦ ¸¸µé±â À§ÇÑ ÄÄÆÄÀÏ·¯ Ç÷¡±×´Â Sun ÄÄÆÄÀÏ·¯¿¡¼´Â-KPICÀ̰í, GCC¿¡¼´Â-fpicÀÔ´Ï´Ù. °øÀ¯ ¶óÀ̺귯¸®¸¦ ¸µÅ©Çϱâ À§Çؼ´Â, µÎ ÄÄÆÄÀÏ·¯¿¡¼ ÄÄÆÄÀÏ·¯ ¿É¼ÇÀ» -G·Î »ç¿ëÇÕ´Ï´Ù. ´ë½Å GCCÀÇ °æ¿ì¿¡´Â -shared¿É¼ÇÀ» »ç¿ëÇÒ ¼ö ÀÖ½À´Ï´Ù.
cc -KPIC -c foo.c cc -G -o foo.so foo.o
¶Ç´Â
gcc -fpic -c foo.c gcc -G -o foo.so foo.o
PIC´Â µðÆúÆ®·Î ÄÄÆÄÀÏ ¸í·É¹®Àº ÀϹÝÀûÀÎ °ÍÀÔ´Ï´Ù. ¸µÅ©¸¦ Çϱâ À§Çؼ´Â Ưº°ÇÑ ¿É¼ÇÀ» °¡Áø ld°¡ »ç¿ëµË´Ï´Ù.
cc -c foo.c ld -shared -expect_unresolved '*' -o foo.so foo.o
½Ã½ºÅÛÀÇ ÄÄÆÄÀÏ·¯¸¦ ´ë½ÅÇØ GCC¸¦ »ç¿ëÇÏ´Â °æ¿ìµµ °°Àº ¼ø¼ÀÔ´Ï´Ù. Ưº°ÇÑ ¿É¼ÇÀº ÇÊ¿äÇÏÁö ¾Ê½À´Ï´Ù.
PIC¸¦ ¸¸µé±â À§ÇÑ ÄÄÆÄÀÏ·¯ Ç÷¡±×´Â SCO ÄÄÆÄÀÏ·¯¿¡¼´Â-KPIC°¡ »ç¿ëµÇ¸ç, GCC¿¡¼´Â -fpicÀÔ´Ï´Ù. °øÀ¯ ¶óÀ̺귯¸®ÀÇ ¸µÅ©Çϱâ À§Çؼ SCO ÄÄÆÄÀÏ·¯¿¡¼´Â ÄÄÆÄÀÏ·¯ ¿É¼ÇÀ¸·Î -GÀÌ »ç¿ëµÇ°í, GCC¿¡¼´Â-shared°¡ »ç¿ëµË´Ï´Ù.
cc -K PIC -c foo.c cc -G -o foo.so foo.o
¶Ç´Â
gcc -fpic -c foo.c gcc -shared -o foo.so foo.o
Tip: À§ÀÇ ³»¿ëÀÌ º¹ÀâÇÏ¿© ÀÌÇØ°¡ ¾î·Á¿ï °æ¿ì, µ¿ÀÏÇÑ ÀÎÅÍÆäÀ̽º¸¦ ÅëÇØ Ç÷¡ÆûÀÇ Â÷À̸¦ °¨ÃçÁÖ´Â GNU Libtool ÀÇ »ç¿ëÀ» °í·ÁÇØ º¸½Ê½Ã¿ä.
¿Ï¼ºµÈ °øÀ¯ ¶óÀ̺귯¸® ÆÄÀÏÀºPostgreSQL¿¡ ·ÎµåÇÒ ¼ö ÀÖ½À´Ï´Ù. CREATE FUNCTION ¸í·É¹®À¸·Î ÆÄÀϸíÀ» ÁöÁ¤ÇÒ ¶§¿¡´Â, Áß°£ ¿ÀºêÁ§Æ® ÆÄÀÏÀÌ ¾Æ´Ñ °øÀ¯ ¶óÀ̺귯¸® ÆÄÀϸíÀÇ À̸§À» Áֽʽÿä. ½Ã½ºÅÛÀÇ Ç¥ÁØ °øÀ¯ ¶óÀ̺귯¸®¿ëÀÇ È®ÀåÀÚ(extension)(Åë»ó. soȤÀº. sl)´Â CREATE FUNCTIONÀ¸·Î »ý·«ÀÌ °¡´ÉÇϸç, ÀϹÝÀûÀ¸·Î À̽ļºÀ» °¡Àå ³ôÀ̱â À§ÇÑ ¹æ¹ýÀ¸·Î »ý·«µÇ¾îÁý´Ï´Ù.
¼¹ö°¡ ¶óÀ̺귯¸® ÆÄÀÏÀ» ¾îµð¿¡ ã¾Æ³¾±î¿¡ °üÇØ Section 33.9.1À» ´Ù½Ã ÂüÁ¶ÇÏ¿© Áֽʽÿä.
PostgreSQLÈ®Àå ¸ðµâÀÇ ¹èÆ÷¸¦ ¿¹Á¤Çϰí ÀÖ´Â °æ¿ì, ±¸Ãà ½Ã½ºÅÛÀ» ÀÌ½Ä °¡´ÉÇÏ°Ô Çϱâ À§ÇÑ ¼³Á¤Àº ²Ï °ï¶õÇÕ´Ï´Ù. ±× ¶§¹®¿¡, PostgreSQLÀÇ ¼³Ä¡¿¡¼´Â, ´Ü¼øÇÑ È®Àå ¸ðµâÀ» ¼³Ä¡°¡ ³¡³ ¼¹ö¿¡ °£´ÜÇÏ°Ô ±¸ÃàÇÒ ¼ö ÀÖµµ·Ï PGXS¶ó´Â È®Àå¿ëÀÇ ±¸Ãà ±â¹ÝÀ» Á¦°øÇϰí ÀÖ½À´Ï´Ù. ÀÌ ±â¹ÝÀº, PostgreSQL¿Í ±³È¯ÇÏ´Â ¸ðµç ¼ÒÇÁÆ®¿þ¾î¸¦ ±¸ÃàÇϱâ À§Çؼ »ç¿ëÇÒ ¼ö ÀÖ´Â °Í °°Àº Á¾ÇÕÀûÀÎ ±¸Ãà ½Ã½ºÅÛ Ã¼Á¦¸¦ ¸ñÀûÀ¸·Î ÇÑ °ÍÀº ¾Æ´Ñ °Í¿¡ ÁÖÀÇÇØ ÁÖ¼¼¿ä. À̰ÍÀº ´ÜÁö ´Ü¼øÇÑ ¼¹ö È®Àå ¸ðµâ·Î °øÅëµÇ´Â ±¸Ãà ¼ø¼¸¦ ÀÚµ¿ÈÇÏ´Â °ÍÀÔ´Ï´Ù. Á» ´õ º¹ÀâÇÑ ÆÐŰÁö¿¡¼´Â, µ¶ÀÚÀûÀ¸·Î ±¸Ãà ½Ã½ºÅÛÀ» ÀÛ¼ºÇÒ Çʿ䰡 ÀÖ½À´Ï´Ù.
µ¶ÀÚÀûÀÎ È®Àå ¸ðµâ¿ëÀ¸·Î ÀÌ ±â¹ÝÀ» »ç¿ëÇÏ·Á¸é, °£´ÜÇÑ Makefile¸¦ ÀÛ¼ºÇÏÁö ¾ÊÀ¸¸é ¾ÈµË´Ï´Ù. ÀÌ Makefile·Î, ¸î °³ÀÇ º¯¼ö¸¦ ¼³Á¤ÇØ, ¸¶Áö¸·¿¡ PGXSÀüüÀÇ Makefile¸¦ Æ÷ÇÔ½ÃÄѾßÇÕ´Ï´Ù. ¿©±â¿¡¼´Â, isbn_issn¶ó´Â À̸§ÀÇ È®Àå ¸ðµâÀ» ±¸ÃàÇϱâ À§ÇÑ ¿¹¸¦ ³ªÅ¸³À´Ï´Ù. ÀÌ ¸ðµâÀº °øÀ¯ ¶óÀ̺귯¸®, SQL ½ºÅ©¸³Æ®, ¹× ¹®¼¿ëÀÇ ÅØ½ºÆ® ÆÄÀϷκÎÅÍ ±¸¼ºµÇ¾î ÀÖ½À´Ï´Ù.
MODULES = isbn_issn DATA_built = isbn_issn.sql DOCS = README.isbn_issn PGXS := $(shell pg_config --pgxs) include $(PGXS)
¸¶Áö¸· 3ÇàÀº Ç×»ó °°À» °ÍÀÔ´Ï´Ù. ±× Àü¿¡, º¯¼öÀÇ ´ëÀÔÀ̳ª µ¶ÀÚÀûÀÎ make±ÔÄ¢ÀÇ Ãß°¡¸¦ ½Ç½ÃÇÕ´Ï´Ù.
ÀÌÇÏÀÇ º¯¼ö¸¦ ¼³Á¤ÇÒ ¼ö ÀÖ½À´Ï´Ù.
°°Àº °èÅëÀÇ ¼Ò½º ÆÄÀϷκÎÅÍ ±¸ÃàµÇ´Â °øÀ¯ °´Ã¼ÀÇ ¸®½ºÆ®ÀÔ´Ï´Ù (ÀÌ ¸®½ºÆ®¿¡´Â È®ÀåÀÚ(extension)¸¦ Æ÷ÇÔÇÏÁö ¸»¾Æ ÁÖ¼¼¿ä).
prefix /share/contrib¿¡ ¼³Ä¡µÇ´Â ¿©·¯°¡Áö ÆÄÀÏÀÔ´Ï´Ù.
ÃÖÃÊ·Î ±¸ÃàµÇÁö ¾ÊÀ¸¸é ¾È µÇ´Â prefix /share/contrib¿¡ ¼³Ä¡µÇ´Â ¿©·¯°¡Áö ÆÄÀÏÀÔ´Ï´Ù.
prefix /doc/contrib¿¡ ¼³Ä¡µÇ´Â ¿©·¯°¡Áö ÆÄÀÏÀÔ´Ï´Ù.
prefix /bin¿¡ ¼³Ä¡ µÇ´Â(¹ÙÀ̳ʸ®°¡ ¾Æ´Ñ) ½ºÅ©¸³Æ® ÆÄÀÏÀÔ´Ï´Ù.
ÃÖÃÊ·Î ±¸ÃàµÇÁö ¾ÊÀ¸¸é ¾È µÇ´Â, prefix /bin¿¡ ¼³Ä¡µÇ´Â(¹ÙÀ̳ʸ®°¡ ¾Æ´Ñ) ½ºÅ©¸³Æ® ÆÄÀÏÀÔ´Ï´Ù.
¸®±×·¿¼ÇÅ×½ºÆ®ÄÉÀ̽ºÀÇ(È®ÀåÀÚ(extension) ¾øÀ½ÀÇ) ¸®½ºÆ®ÀÔ´Ï´Ù. Èļú ÇÕ´Ï´Ù.
ȤÀº, ÀÌÇÏÀÇ 2°³ °¡¿îµ¥, ´ëºÎºÐ 1°³ÀÔ´Ï´Ù.
(OBJSÀÇ °´Ã¼ ÆÄÀÏÀÇ ¸®½ºÆ®·ÎºÎÅÍ) ±¸ÃàµÇ´Â ¹ÙÀ̳ʸ® ÇÁ·Î±×·¥ÀÔ´Ï´Ù.
(OBJSÀÇ °´Ã¼ ÆÄÀÏÀÇ ¸®½ºÆ®·ÎºÎÅÍ) ±¸ÃàµÇ´Â °øÀ¯ °´Ã¼ÀÔ´Ï´Ù.
ÀÌÇÏÀÇ º¯¼öµµ ¼³Á¤ÇÒ ¼ö°¡ ÀÖ½À´Ï´Ù.
make clean·Î »èÁ¦µÇ´Â ºÒÇÊ¿äÇÑ ÆÄÀÏÀÔ´Ï´Ù.
À̰ÍÀº CPPFLAGS¿¡ Ãß°¡µË´Ï´Ù.
À̰ÍÀº PROGRAMÀÇ ¸µÅ©Çà¿¡ Ãß°¡µË´Ï´Ù.
À̰ÍÀº MODULE_bigÀÇ ¸µÅ©Çà¿¡ Ãß°¡µË´Ï´Ù.
ÀÌ Makefile¸¦ È®Àå ¸ðµâÀ» ÀúÀåÇÏ´Â µð·ºÅ丮¿¡ Makefile·Î¼ º¸Á¸ÇØ ÁÖ¼¼¿ä. ±× ÈÄ, make·Î µ¶ÀÚ ¸ðµâÀÇ ÄÄÆÄÀÏÀ», make install·Î µ¶ÀÚ ¸ðµâÀÇ ¼³Ä¡¸¦ ½Ç½ÃÇÒ ¼ö°¡ ÀÖ½À´Ï´Ù. µðÆúÆ®·Î È®Àå ¸ðµâÀº, °Ë»ö °æ·Î³»¿¡¼ ÃÖÃÊ·Î ¹ß°ßµÇ´Â pg_config¸í·É¿¡ ´ëÀÀÇÏ´Â PostgreSQL¼³Ä¡ Àü¿ëÀ¸·Î ÄÄÆÄÀÏ µÇ¾î ¼³Ä¡µË´Ï´Ù. Makefile³» ¶Ç´Â makeÀÇ ¸í·É ¶óÀλ󿡼 PG_CONFIG¸¦ ´Ù¸¥ ¼³Ä¡ÀÇ pg_configÇÁ·Î±×·¥À» Áö½ÃÇϵµ·Ï º¯°æÇÏ´Â °ÍÀ¸·Î ´Ù¸¥ ¼³Ä¡¸¦ »ç¿ëÇÒ ¼ö°¡ ÀÖ½À´Ï´Ù.
PostgreSQL ÁÖ¼¹ö·Î »ç¿ëµÇ´Â make installcheck ¸ØÃá ±¸ °°ÀÌ REGRESSº¯¼ö³»¿¡ ¿°ÅµÈ ½ºÅ©¸³Æ®°¡ µ¶ÀÚÀûÀÎ ¸ðµâÀÇ ¸®±×·¿¼ÇÅ×½ºÆ®¿ëÀ¸·Î »ç¿ëµË´Ï´Ù. À̰ÍÀÌ µ¿ÀÛÇϱâ À§Çؼ´Â, µ¶ÀÚ È®ÀåÀÇ µð·ºÅ丮³»¿¡ sql/¶ó´Â ¸íĪÀÇ µð·ºÅ丮¸¦ ÁغñÇØ, ±× Áß¿¡ ½ÇÇà½ÃŰ°í ½ÍÀº ½ÃÇè ±×·ì °¢°¢ 1°³ÀÇ ÆÄÀÏÀ» ÀúÀåÇØ¾ß ÇÕ´Ï´Ù. ÀÌ ÆÄÀÏÀÇ È®ÀåÀÚ(extension)´Â . sql°¡ ¾Æ´Ï¸é ¾ÈµË´Ï´Ù. ¶Ç, makefile ÆÄÀϳ»ÀÇ REGRESS¸®½ºÆ®¿¡´Â ÀÌ È®ÀåÀÚ(extension)¸¦ Æ÷ÇÔÇØ¼´Â ¾ÈµË´Ï´Ù. °¢°¢ÀÇ ½ÃÇè¿¡ °üÇØ¼, expected/¶ó´Â ¸íĪÀÇ µð·ºÅ丮¿¡, . out¶ó´Â È®ÀåÀÚ(extension)·Î »óÁ¤ °á°ú¸¦ ÆÄÀϷμ ÀúÀåÇÕ´Ï´Ù. ½ÃÇèÀº make installcheck¿¡ ÀÇÇØ ½ÇÇàµÇ¾î ±× °á°ú´Â »óÁ¤Ä¡ ÆÄÀÏÀ̶ó°í ºñ±³µË´Ï´Ù. Â÷ÀÌÁ¡Àº diff -cÀÇ ¼½Ä¿¡¼ regression.diffs¶ó°í ÇÏ´Â ÆÄÀÏ¿¡ ½á³»Áý´Ï´Ù. »óÁ¤Ä¡ ÆÄÀÏÀÌ Á¸ÀçÇÏÁö ¾Ê´Â ½ÃÇèÀ» ½ÇÇàÇϸé "Àå¾Ö"·Î¼ º¸°íµÇ±â ¶§¹®¿¡, »óÁ¤Ä¡ ÆÄÀÏÀÌ ¸ðµÎ Á¸ÀçÇÏ´ÂÁö È®ÀÎÇØ ÁÖ¼¼¿ä.
Tip: »óÁ¤Ä¡ ÆÄÀÏÀÇ °¡Àå °£´ÜÇÑ ÀÛ¼º ¹æ¹ýÀº ºó ÆÄÀÏÀ» ÀÛ¼ºÇØ, ½ÃÇèÀ» ½ÇÇàÇÑ ÈÄÀÇ °á°ú ÆÄÀÏ(results/µð·ºÅ丮¿¡ ÀÖ½À´Ï´Ù.)À», ±×°ÍÀÌ Á¤¸»·Î ½ÃÇè °á°úÀûÀ¸·Î ¿Ã¹Ù¸¥ °ÍÀÎÁö ÁÖÀÇ ±í°Ô °Ë»çÇÑ ÈÄ¿¡ expected/¿¡ º¹»çÇÏ´Â °ÍÀÔ´Ï´Ù.
º¹ÇÕÇü¿¡¼´Â CÀÇ ±¸Á¶¿Í °°Àº °íÁ¤ÀÇ ·¹À̾ƿôÀÌ ¾ø½À´Ï´Ù. º¹ÇÕÇüÀÇ ÀνºÅϽº´Â NULL Çʵ带 °¡Áú ¼ö°¡ ÀÖ½À´Ï´Ù. °Ô´Ù°¡ º¹ÇÕÇüÀ¸·Î °è½Â °èÃþÀÇ ÀϺÎÀÎ °ÍÀº, °°Àº °è½Â °èÃþÀÇ ´Ù¸¥ ¸â¹ö¿Í´Â ´Ù¸¥ Çʵ带 °¡Áú ¼öµµ ÀÖ½À´Ï´Ù. ±× ¶§¹®¿¡, PostgreSQL´Â C¾ð¾î·ÎºÎÅÍ º¹ÇÕÇüÀÇ Çʵ忡 Á¢±ÙÇϱâ À§ÇÑ ÇÔ¼ö ÀÎÅÍÆäÀ̽º¸¦ Á¦°øÇÕ´Ï´Ù.
ÀÌÇÏ¿Í °°ÀÌ Äõ¸®¿¡ ´ë´äÇÏ´Â ÇÔ¼ö¸¦ ¾²·Á°í ÇÑ´Ù°í °¡Á¤ÇÕ´Ï´Ù.
SELECT name, c_overpaid(emp, 1500) AS overpaid
FROM emp
WHERE name = 'Bill' OR name = 'Sam';
¹öÀü-0 È£Ãâ ±Ô¾àÀ» »ç¿ëÇϸé, c_overpaid´Â ÀÌÇÏ¿Í °°ÀÌ Á¤ÀÇÇÒ ¼ö ÀÖ½À´Ï´Ù.
#include "postgres.h"
#include "executor/executor.h" /* GetAttributeByName() ¿ë */
bool
c_overpaid(HeapTupleHeader t, /* empÀÇ ÇöÀçÀÇ Çà */
int32 limit)
{
bool isnull;
int32 salary;
salary = DatumGetInt32(GetAttributeByName(t, "salary", &isnull));
if (isnull)
return false;
return salary > limit;
}
¹öÀü-1À¸·Î ÀÛ¼ºÇϸé, À§ÀÇ ÇÔ¼ö´Â ÀÌÇÏ¿Í °°ÀÌ µË´Ï´Ù.
#include "postgres.h"
#include "executor/executor.h" /* GetAttributeByName() ¿ë */
PG_FUNCTION_INFO_V1(c_overpaid);
Datum
c_overpaid(PG_FUNCTION_ARGS)
{
HeapTupleHeader t = PG_GETARG_HEAPTUPLEHEADER(0);
int32 limit = PG_GETARG_INT32(1);
bool isnull;
Datum salary;
salary = GetAttributeByName(t, "salary", &isnull);
if (isnull)
PG_RETURN_BOOL(false);
/* ÀÌ ¿Ü, salary°¡ NULLÀÇ °æ¿ì¿¡´Â PG_RETURN_NULL()¸¦ ½Ç½ÃÇÏ´Â °ÍÀÌ ÁÁÀ» °ÍÀÔ´Ï´Ù */
PG_RETURN_BOOL(DatumGetInt32(salary) > limit);
}
GetAttributeByName´Â, ÁöÁ¤µÈ ÇàÀ¸·ÎºÎÅÍ ¼Ó¼ºÀ» µ¹·ÁÁÖ´Â, PostgreSQL½Ã½ºÅÛ ÇÔ¼öÀÔ´Ï´Ù.
À̰Ϳ¡´Â 3°³ÀÇ ÀÎÀÚ°¡ ÀÖ½À´Ï´Ù.
±×°ÍµéÀº, ÇÔ¼ö¿¡°Ô °Ç³×Áø HeapTupleHeaderÇüÀÇ ÀÎÀÚ, ¿ä±¸µÈ ¼Ó¼ºÀÇ À̸§, ¼Ó¼ºÀÌ NULLÀÎÁö ¾Æ´ÑÁö¸¦ ÅëÁöÇÏ´Â ¸Å°³º¯¼öÀÔ´Ï´Ù.
GetAttributeByName´Â ÀûÀýÇÑ DatumGet
XXX
()¸ÅÅ©·Î¸¦ »ç¿ëÇØ
ÀûÀýÇÑ µ¥ÀÌÅÍÇü¿¡ º¯È¯ °¡´ÉÇÑ DatumÇüÀÇ °ªÀ» µ¹·ÁÁÝ´Ï´Ù.
ÀÌ NULL Ç÷¡±×°¡ ¼³Á¤µÇ¾î ÀÖ´Â °æ¿ì, ¹Ýȯ°ªÀÇ Àǹ̰¡ ¾ø´Â °Í¿¡ ÁÖÀÇÇØ, ÀÌ °á°ú·Î ¹«¾ùÀΰ¡¸¦ ½Ç½ÃÇÏ·Á°í Çϱâ Àü¿¡ Ç×»ó, NULL Ç÷¡±×¸¦ °Ë»çÇØ ÁÖ¼¼¿ä.
¸ñÇ¥¿À» À̸§Àº ¾Æ´Ï°í ¿¹øÈ£·Î ¼±ÅÃÇÏ´Â GetAttributeByNumµµ ÀÖ½À´Ï´Ù.
¾Æ·¡¿Í °°Àº ¸í·ÉÀ¸·Î c_overpaidÇÔ¼ö¸¦ SQL·Î ¼±¾ðÇÕ´Ï´Ù.
CREATE FUNCTION c_overpaid(emp, integer) RETURNS boolean
AS '
DIRECTORY
/funcs', 'c_overpaid'
LANGUAGE C STRICT;
ÀÔ·Â ÀÎÀÚ°¡ NULLÀÎÁö ¾Æ´ÑÁö¸¦ °Ë»çÇÒ Çʿ䰡 ¾ø°Ô STRICT¸¦ »ç¿ëÇϰí ÀÖ´Â °Í¿¡ ÁÖÀÇÇØ ÁÖ¼¼¿ä.
C¾ð¾î ÇÔ¼ö·ÎºÎÅÍ Çà ȤÀº º¹ÇÕÇüÀÇ °ªÀ» µ¹·ÁÁÖ±â À§Çؼ, º¹ÇÕÇüÀÇ º¹ÀâÇÑ ÀÛ¼ºÀÇ ´ëºÎºÐÀ» ÀºÆó ÇÏ´Â ¸ÅÅ©·Î³ª ÇÔ¼ö¸¦ Á¦°øÇÏ´Â, Ưº°ÇÑ API¸¦ »ç¿ëÇÒ ¼ö°¡ ÀÖ½À´Ï´Ù. ÀÌ API¸¦ »ç¿ëÇϱâ À§Çؼ´Â, ¼Ò½º ÆÄÀÏ·Î ÀÌÇϸ¦ Æ÷ÇÔÇÒ Çʿ䰡 ÀÖ½À´Ï´Ù.
#include "funcapi.h"
º¹ÇÕÇüÀÇ µ¥ÀÌÅͰª(ÀÌÈÄ "Æ©ÇÃ" Àû´Â´Ù)¸¦ ÀÛ¼ºÇÏ´Â 2°³ÀÇ ¹æ¹ýÀÌ ÀÖ½À´Ï´Ù.
Datum°ªÀÇ ¹è¿·ÎºÎÅÍ ÀÛ¼ºÇÏ´Â ¹æ¹ý, ȤÀº Æ©ÇÃÀÌ ÀÖ´Â ¿ÀÇ ÇüÅÂÀÇ ÀÔ·Â º¯È¯ ÇÔ¼ö¿¡ °Ç³×ÁÙ ¼ö°¡ ÀÖ´Â Cij¸¯ÅÍ ¶óÀÎÀÇ ¹è¿·ÎºÎÅÍ ÀÛ¼ºÇÏ´Â °ÍÀÔ´Ï´Ù.
¾î´À ÂÊÀÇ ¹æ¹ý¿¡¼µµ, ¿ì¼± Æ©Çà ±¸Á¶ ü¿ëÀÇ TupleDesc±â¼ú¾î¸¦ ÀÔ¼ö, ȤÀº ÀÛ¼ºÇÏÁö ¾ÊÀ¸¸é ¾ÈµË´Ï´Ù.
Datum¸¦ »ç¿ëÇÏ´Â °æ¿ì´Â, TupleDesc¸¦ BlessTupleDesc¿¡ °Ç³×ÁÖ¾î, °¢ Çà¿¡ ´ëÇØ¼ heap_form_tuple¸¦ È£ÃâÇÕ´Ï´Ù.
C¹®ÀÚ¿À» »ç¿ëÇÏ´Â °æ¿ì´Â, TupleDesc¸¦ TupleDescGetAttInMetadata¿¡ °Ç³×ÁÖ¾î,
°¢ Çà¿¡ ´ëÇØ¼ BuildTupleFromCStrings¸¦ È£ÃâÇÕ´Ï´Ù.
Æ©ÇÃÀÇ ÁýÇÕÀ» µ¹·ÁÁÖ´Â ÇÔ¼öÀÇ °æ¿ì, ÀÌ ¼³Á¤ ´Ü°è¸¦ ÃÖÃÊÀÇ ÇÔ¼ö È£Ãâ·Î ÇÑ ¹ø¿¡ Á¤¸®ÇØ ½Ç½ÃÇÒ ¼ö°¡ ÀÖ½À´Ï´Ù.
ÇÊ¿äÇÑ TupleDescÀÇ ¼³Á¤¿ëÀÇ º¸Á¶¿ë ÇÔ¼ö°¡ ¸î °³ ÀÖ½À´Ï´Ù. ´ëºÎºÐÀÇ º¹ÇÕÇüÀ» µ¹·ÁÁÖ´Â ÇÔ¼ö¿¡¼ÀÇ Ãßõ ¹æ¹ýÀº, ÀÌÇÏÀÇ ÇÔ¼ö¸¦ È£ÃâÇØ, È£Ãâ ¿ø·¡ÀÇ ÇÔ¼ö Àڽſ¡°Ô °Ç³×Áö´Â fcinfo±¸Á¶¿Í °°Àº °ÍÀ» °Ç³×ÁÖ´Â °ÍÀÔ´Ï´Ù.
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo,
Oid *resultTypeId,
TupleDesc *resultTupleDesc)
(À̰Ϳ¡´Â ¹°·Ð, ¹öÀü 1 È£Ãâ ±Ô¾àÀ» »ç¿ëÇϰí ÀÖ´Â °ÍÀÌ ÇÊ¿äÇÕ´Ï´Ù). resultTypeId¸¦ NULL·Î ÇÏ´Â Àϵµ, ·ÎÄà º¯¼öÀÇ ÁÖ¼Ò¸¦ ÁöÁ¤ÇØ ÇÔ¼öÀÇ ¹Ýȯ°ªÇüÀ» ¹ÞÀ» ¼ö°¡ ÀÖ½À´Ï´Ù. resultTupleDesc´Â ·ÎÄÃÀÎ TupleDescº¯¼öÀÇ ÁÖ¼Ò°¡ ¾Æ´Ï¸é ¾ÈµË´Ï´Ù. °á°ú°¡TYPEFUNC_COMPOSITEȵµÀÎÁö¸¦ È®ÀÎÇØ ÁÖ¼¼¿ä. TYPEFUNC_COMPOSITE¿´À» °æ¿ì, resultTupleDesc¿¡´Â ÇÊ¿äÇÑ TupleDesc°¡ ÀúÀåµÇ°í ÀÖ½À´Ï´Ù. (TYPEFUNC_COMPOSITE´Â ¾Æ´Ï¾ú´ø °æ¿ì, "·¹ÄÚµåÇüÀ» ¹Þ¾ÆµéÀÌÁö ¾Ê´Â ¹®¸ÆÀ¸·Î ·¹Äڵ带 µ¹·ÁÁÖ´Â ÇÔ¼ö°¡ ºÒ·Á °¬´ø "À̶ó°í ÇÏ´Â ¿¡·¯¸¦ º¸°íÇÒ ¼ö°¡ ÀÖ½À´Ï´Ù. )
Tip:
get_call_result_type´Â, ´ÙÇü ÇÔ¼öÀÇ °á°úÀÇ ½ÇÁ¦ÀÇ ÇüŸ¦ ÇØ°áÇÒ ¼ö°¡ ÀÖ½À´Ï´Ù. ±×·¯¹Ç·Î, º¹ÇÕÇüÀ» µ¹·ÁÁÖ´Â ÇÔ¼ö ¸¸ÀÌ ¾Æ´Ï°í, ½ºÄ®¶óÀÇ ´Ù¾ç °á°ú¸¦ µ¹·ÁÁÖ´Â ÇÔ¼ö¿¡¼µµ Àǹ̰¡ ÀÖ½À´Ï´Ù. resultTypeIdÃâ·ÂÀº ÁÖ·Î ½ºÄ®¶óÀÇ ´Ù¾ç °á°ú¸¦ µ¹·ÁÁÖ´Â ÇÔ¼ö·Î Àǹ̰¡ ÀÖ½À´Ï´Ù.
Note:
get_call_result_type´Â,get_expr_result_type¿Í ´àÀº °Í °°Àº ÇÔ¼ö·Î, ÇÔ¼ö È£Ãâ·Î »óÁ¤µÇ´Â Ãâ·ÂÇüÀ» ½ÄÀÇ Æ®¸® ±¸Á¶·Î¼ ÇØ°áÇÕ´Ï´Ù. ÇÔ¼ö ÀڽŠÀܷ̿κÎÅÍ °á°úÇüÀ» °áÁ¤ÇÏ°í ½ÍÀº °æ¿ì¿¡, À̰ÍÀ» »ç¿ëÇÒ ¼ö°¡ ÀÖ½À´Ï´Ù. ¶Ç,get_func_result_type¶ó°í ÇÏ´Â ÇÔ¼öµµ ÀÖ½À´Ï´Ù. À̰ÍÀº ÇÔ¼öÀÇ OID¸¦ ÀÌ¿ëÇÒ ¼ö ÀÖ´Â °æ¿ì¿¡°Ô¸¸ »ç¿ëÇÒ ¼ö°¡ ÀÖ½À´Ï´Ù. ±×·¯³ª, ÀÌ·¯ÇÑ ÇÔ¼ö´Â, recordÇüÀ» µ¹·ÁÁÖ´Â °ÍÀ̶ó°í ¼±¾ðµÈ ÇÔ¼ö¿¡¼´Â »ç¿ëÇÒ ¼ö ¾ø½À´Ï´Ù. ¶Ç,get_func_result_type´Â ´ÙÇü ÇüÅÂÀ» ÇØ°áÇÒ ¼ö°¡ ¾ø½À´Ï´Ù. µû¶ó¼, ¿ì¼±ÇØget_call_result_type¸¦ »ç¿ëÇØ¾ß ÇÕ´Ï´Ù.
³°°í, ÆóÁö ¿¹Á¤ÀÇ TupleDesc¸¦ ÀÔ¼öÇϱâ À§ÇÑ ÇÔ¼ö¸¦ ÀÌÇÏ¿¡ ³ªÅ¸³À´Ï´Ù.
TupleDesc RelationNameGetTupleDesc(const char *relname)
À̰ÍÀ» Áö¸íÇÑ ¸±·¹À̼ÇÀÇ ÇàÇü¿ëÀÇ TupleDesc¸¦ ²¨³»±â À§Çؼ »ç¿ëÇØ ÁÖ¼¼¿ä. ¶Ç,
TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases)
À̰ÍÀ» ÇüÅÂÀÇ OID¿¡ ±Ù°ÅÇØ TupleDesc¸¦ ²¨³»±â À§Çؼ »ç¿ëÇØ ÁÖ¼¼¿ä. À̰ÍÀº ±âº»Çü, ȤÀº º¹ÇÕÇüÀÇ TupleDesc¸¦ ²¨³»±â À§Çؼ »ç¿ë °¡´ÉÇÕ´Ï´Ù. À̰ÍÀº record¸¦ µ¹·ÁÁÖ´Â ÇÔ¼ö¿¡¼´Â Àß ÀÛµ¿ÇÏÁö ¾Ê½À´Ï´Ù. ¶Ç, ´ÙÇü ÇüÅÂÀ» ÇØ°áÇÒ ¼öµµ ÀÖ½À´Ï´Ù.
TupleDesc¸¦ ȹµæÇÑ ÈÄ¿¡, Datum¸¦ »ç¿ëÇÏ´Â °æ¿ì´Â ÀÌÇϸ¦ È£ÃâÇØ ÁÖ¼¼¿ä.
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Cij¸¯ÅÍ ¶óÀÎÀ» »ç¿ëÇÏ´Â °æ¿ì´Â ÀÌÇϸ¦ È£ÃâÇØ ÁÖ¼¼¿ä.
AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc)
ÁýÇÕÀ» µ¹·ÁÁÖ´Â ÇÔ¼ö¸¦ ÀÛ¼ºÇÏ´Â °æ¿ì´Â, ÀÌ·¯ÇÑ ÇÔ¼öÀÇ °á°ú¸¦ FuncCallContext±¸Á¶¿¡ ÀúÀåÇØ ÁÖ¼¼¿ä. °¢°¢ tuple_desc¿Í attinmeta¸¦ »ç¿ëÇÕ´Ï´Ù.
Datum¸¦ »ç¿ëÇÏ´Â °æ¿ì´Â, »ç¿ëÀÚ µ¥ÀÌÅ͸¦ Datum Çü½Ä¿¡ ÀúÀåÇÑ HeapTuple¸¦ ±¸ÃàÇϱâ À§Çؼ ÀÌÇϸ¦ »ç¿ëÇÕ´Ï´Ù.
HeapTuple heap_form_tuple(TupleDesc tupdesc, Datum *values, bool *isnull)
C¹®ÀÚ¿À» »ç¿ëÇÏ´Â °æ¿ì´Â, »ç¿ëÀÚ µ¥ÀÌÅ͸¦ C¹®ÀÚ¿ Çü½Ä¿¡ ÀúÀåÇÑ HeapTuple¸¦ ±¸ÃàÇϱâ À§Çؼ ÀÌÇϸ¦ »ç¿ëÇÕ´Ï´Ù.
HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
valuesÇÏÇàÀÇ °¢ ¼Ó¼ºÀ» 1 ¿ä¼Ò·Î ÇÑ C¹®ÀÚ¿ÀÇ ¹è¿ÀÔ´Ï´Ù. °¢ C¹®ÀÚ¿Àº, ¼Ó¼ºÀÇ µ¥ÀÌÅÍÇü¿ëÀÇ ÀÔ·Â ÇÔ¼ö°¡ ¹Þ¾ÆµéÀÌ°í °¡´ÉÇÑ Çü½ÄÀÌ ¾Æ´Ï¸é ¾ÈµË´Ï´Ù. ¼Ó¼ºÀÇ °ªÀ» NULL°ªÀ¸·Î¼ µ¹·ÁÁÖ±â À§Çؼ´Â, values¹è¿ÀÇ ´ëÀÀÇÏ´Â Æ÷ÀÎÅÍ¿¡ NULL¸¦ ¼³Á¤ÇØ ÁÖ¼¼¿ä. ÀÌ ÇÔ¼ö´Â µ¹·ÁÁÖ´Â Çà °¢°¢ ´ëÇØ ¹Ýº¹ÇØ È£ÃâÇÒ Çʿ䰡 ÀÖ½À´Ï´Ù.
ÇÔ¼ö·ÎºÎÅÍ µ¹·ÁÁÖ´Â Æ©ÇÃÀ» ´Ù ±¸ÃàÇßÀ¸¸é, ±×°ÍÀ» Datum·Î º¯È¯ÇÏÁö ¾ÊÀ¸¸é ¾ÈµË´Ï´Ù. ÀÌÇϸ¦ »ç¿ëÇØ, HeapTuple¸¦ À¯È¿ÇÑ Datum·Î º¯È¯ÇØ ÁÖ¼¼¿ä.
HeapTupleGetDatum(HeapTuple tuple)
´ÜÀÏÇุÀ» µ¹·ÁÁشٸé, ÀÌ Datum¸¦ Á÷Á¢ µ¹·ÁÁÙ ¼ö°¡ ÀÖ½À´Ï´Ù. ¾Æ´Ï¸é, ÁýÇÕÀ» µ¹·ÁÁÖ´Â ÇÔ¼ö¿¡ ÀÖ¾î¼ÀÇ ÇöÀçÀÇ ¹Ýȯ°ªÀ¸·Î¼ »ç¿ëÇÒ ¼ö°¡ ÀÖ½À´Ï´Ù.
´ÙÀ½ ¼½¼Ç¿¡ ¿¹¸¦ ³ªÅ¸³À´Ï´Ù.
C¾ð¾î ÇÔ¼ö·ÎºÎÅÍ ÁýÇÕ(º¹¼öÇà)À» µ¹·ÁÁÖ´Â ±â´ÉÀ» À§Çؼ Ư¼öÇÑ API°¡ ÁغñµÇ¾î ÀÖ½À´Ï´Ù. ÁýÇÕÀ» µ¹·ÁÁÖ´Â ÇÔ¼ö´Â, ¹öÀü-1 È£Ã⠱Ծ࿡ µû¸¦ Çʿ䰡 ÀÖ½À´Ï´Ù. ¶Ç, ¼Ò½º ÆÄÀÏÀº »ó¼úÇÑ ´ë·Î funcapi.h¸¦ Æ÷ÇÔ ÇÒ Çʿ䰡 ÀÖ½À´Ï´Ù.
ÁýÇÕÀ» µ¹·ÁÁÖ´Â ÇÔ¼ö(SRF)´Â µ¹·ÁÁÖ¾îÁö´Â Ç׸ñ ¸¶´Ù ºÒ·Á °©´Ï´Ù. ±× ¶§¹®¿¡, SRF´Â, °ú°ÅÀÇ Á¶ÀÛÀ» ±â¾ïÇØ È£ÃâÀÇ ¹ø¿¡ ´ÙÀ½ÀÇ Ç׸ñÀ» µ¹·ÁÁÖ±â À§Çؼ ÃæºÐÇÑ »óŸ¦ À¯ÁöÇϰí ÀÖÀ» Çʿ䰡 ÀÖ½À´Ï´Ù. ÀÌ Ã³¸®¸¦ Á¦¾î¸¦ º¸Á¶Çϱâ À§ÇÑ FuncCallContext±¸Á¶°¡ °®ÃçÁö°í ÀÖ½À´Ï´Ù. ÇÔ¼ö³»¿¡¼´Â, º¹¼öÀÇ È£Ãâ¿¡ °ÉÄ¡´Â FuncCallContext¿¡ÀÇ Æ÷ÀÎÅ͸¦ º¸°ü À¯ÁöÇÏ·Á¸é, fcinfo->flinfo->fn_extra¸¦ »ç¿ëÇÕ´Ï´Ù.
typedef struct
{
/*
* ÀÌ¹Ì ÇàÇØÁø È£ÃâÀÇ È¸¼ö.
*
* SRF_FIRSTCALL_INIT()¿¡ ÀÇÇØ call_cntr°¡ 0¿¡ ÃʱâȵǾî
* SRF_RETURN_NEXT()°¡ ºÒ·Á °¥ ¶§¿¡ ÁõºÐ µË´Ï´Ù.
*/
uint32 call_cntr;
/*
* »ý·« °¡´É : È£ÃâÀÇ ÃÖ´ë¼ö
*
* max_calls´Â, ÆíÀÇ»ó ÁغñµÇ¾î ÀÖ´Â °Í¸¸À¸·Î, ¼³Á¤Àº »ý·« °¡´ÉÇÕ´Ï´Ù.
* ¼³Á¤µÇ¾î ÀÖÁö ¾ÊÀ¸¸é, ÇÔ¼ö°¡ Á¾·áÇÑ °ÍÀ» ¾Ë±â À§ÇÑ ´Ù¸¥ ¹æ¹ýÀ»
* ÁغñÇÒ Çʿ䰡 ÀÖ½À´Ï´Ù.
*/
uint32 max_calls;
/*
* »ý·« °¡´É : °á°ú ½½·Ô¿¡ÀÇ Æ÷ÀÎÅÍ
*
* À̰ÍÀº ÆóÁöµÇ¾î ÈĹæ ȣȯ¼º, Áï ºñÃßõÀÇ TupleDescGetSlot()¸¦ »ç¿ëÇϰí
* »ç¿ëÀÚ Á¤ÀÇÀÇ SRF¸¦ À§Çؼ¸¸ Á¸ÀçÇÕ´Ï´Ù.
*/
TupleTableSlot *slot;
/*
* »ý·« °¡´É : ¿©·¯°¡Áö »ç¿ëÀÚ¿¡ ÀÇÇÑ ¹®¸Æ Á¤º¸¿¡ÀÇ Æ÷ÀÎÅÍ
*
* user_fctx´Â, ÇÔ¼öÀÇ È£Ãâ°£ÀÇ ÀÓÀÇÀÇ ¹®¸Æ Á¤º¸
* ¸¦ ÃëµæÇϱâ À§ÇÑ »ç¿ëÀÚ µ¶ÀÚÀûÀÎ ±¸Á¶¿¡ÀÇ Æ÷ÀÎÅͷμ »ç¿ëµË´Ï´Ù.
*/
void *user_fctx;
/*
* »ý·« °¡´É : ¼Ó¼ºÇü ÀÔ·Â ¸ÞŸ Á¤º¸¸¦ Æ÷ÇÔÇÑ ±¸Á¶¿¡ÀÇ Æ÷ÀÎÅÍ
*
* attinmeta ´Â Æ©ÇÃ(Áï º¹ÇÕ µ¥ÀÌÅÍÇü)À» µ¹·ÁÁÙ ¶§¿¡ »ç¿ëµÇ¾î
* ±âº» µ¥ÀÌÅÍÇüÀ» µ¹·ÁÁÖ´Â °æ¿ì¿¡´Â ÇÊ¿ä ¾ø½À´Ï´Ù.
* BuildTupleFromCStrings()¸¦ »ç¿ëÇØ µ¹·ÁÁÖ¾îÁö´Â Æ©ÇÃÀ» ÀÛ¼ºÇÏ´Â °æ¿ì¿¡°Ô¸¸ ÇÊ¿äÇÕ´Ï´Ù.
*/
AttInMetadata *attinmeta;
/*
* º¹¼öÀÇ È£Ãâ·Î ÇÊ¿äÇÏ°Ô µÇ´Â ±¸Á¶¿¡ »ç¿ëµÇ´Â ¸Þ¸ð¸® ÄÁÅØ½ºÆ®
*
* multi_call_memory_ctx´Â, SRF_FIRSTCALL_INIT()¿¡ ÀÇÇØ ¼³Á¤µÇ¾î
* SRF_RETURN_DONE()°¡ Ŭ¸° ¾÷ ½Ã¿¡ »ç¿ëÇÕ´Ï´Ù.
* À̰ÍÀº SRFÀÇ º¹¼ö È£Ãâ·Î ÀçÀÌ¿ëµÇ´Â ¸ðµç ¸Þ¸ð¸®¿ëÀ¸·Î °¡Àå ÀûÀýÇÑ ¸Þ¸ð¸® ÄÁÅØ½ºÆ®ÀÔ´Ï´Ù.
*/
MemoryContext multi_call_memory_ctx;
/*
* »ý·« °¡´É: Æ©Çà ¼³¸íÀ» Æ÷ÇÔÇÑ ±¸Á¶¿¡ÀÇ Æ÷ÀÎÅÍ.
* tuple_desc´Â Æ©ÇÃ(Áï º¹ÇÕ µ¥ÀÌÅÍÇü)À» µ¹·ÁÁÖ´Â °æ¿ì¿¡ »ç¿ëµÇ¾î BuildTupleFromCStrings()
* º¸´Ù´Â heap_form_tuple()¸¦ »ç¿ëÇØ Æ©ÇÃÀ» ÀÛ¼ºÇÏ´Â °æ¿ì¿¡°Ô¸¸ ÇÊ¿äÇÕ´Ï´Ù.
* Åë»ó ¿©±â¿¡ ÀúÀåµÇ´Â TupleDesc´Â ÃÖÃÊ·Î BlessTupleDesc()¸¦ ÃÖÃÊ·Î ½ÇÇàÇÑ °ÍÀ̾î¾ß ÇÕ´Ï´Ù.
* ¼±.
*/
TupleDesc tuple_desc;
} FuncCallContext;
SRF´Â ¸î °³ÀÇ ÇÔ¼ö ¹× ¸ÅÅ©·Î¸¦ »ç¿ëÇØ FuncCallContext±¸Á¶¸¦ ÀÚµ¿ÀûÀ¸·Î Á¶ÀÛÇÕ´Ï´Ù (¶Ç fn_extra·Î °Ë»öÇÏ´Â °ÍÀ» »óÁ¤ÇÕ´Ï´Ù).
SRF_IS_FIRSTCALL()
¸¦ »ç¿ëÇØ, ±× ÇÔ¼ö È£ÃâÀÌ Ã¹ ¹øÂ° °ÍÀÎÁö, µÎ¹øÂ° ÀÌÈÄÀÎÁö¸¦ ÆÇ´ÜÇÕ´Ï´Ù. ÃÖÃÊÀÇ È£Ãâ(¿ÀÁ÷)·Î,
SRF_FIRSTCALL_INIT()
À» »ç¿ëÇØ, FuncCallContext¸¦ ÃʱâÈÇÕ´Ï´Ù. ÃÖÃÊÀÇ È£ÃâÀ» Æ÷ÇÔÇÑ ¸ðµç È£Ãâ·Î,
SRF_PERCALL_SETUP()
¸¦ »ç¿ëÇØ, FuncCallContext¸¦ »ç¿ëÇϱâ À§ÇÑ ÀûÀýÇÑ ¼³Á¤À» ½Ç½ÃÇØ, ÀÌÀüÀÇ °æ·Î·ÎºÎÅÍ ³²¾Æ ÀÖ´Â °á°ú µ¥ÀÌÅ͸¦ ¼Ò°ÅÇÕ´Ï´Ù.
ÇÔ¼ö·Î µ¹·ÁÁÖ¾î¾ß ÇÒ µ¥ÀÌÅͰ¡ ÀÖ´Â °æ¿ì´Â,
SRF_RETURN_NEXT(funcctx, result)
¸¦ »ç¿ëÇØ, ±× µ¥ÀÌÅ͸¦ È£ÃâÇØ Ãø¿¡ µ¹·ÁÁÝ´Ï´Ù (¸ÕÀú ¼³¸íÇÑ ´ë·Î result´Â DatumÇü, Áï 1°³ÀÇ °ª ¶Ç´Â Æ©ÇÃÀÏ Çʿ䰡 ÀÖ½À´Ï´Ù). ¸¶Áö¸·À¸·Î, ÇÔ¼ö°¡ µ¥ÀÌÅ͸¦ ´Ù µ¹·ÁÁÖ¾úÀ¸¸é,
SRF_RETURN_DONE(funcctx)
¸¦ »ç¿ëÇØ SRF¸¦ Ŭ¸° ¾÷ ÇØ Á¾·áÇÕ´Ï´Ù.
SRFÀÇ È£Ãâ½Ã¿¡ ÇöÇàÀÌ µÇ¾î ÀÖ´Â ¸Þ¸ð¸® ÄÁÅØ½ºÆ®´Â ÀϽÃÀûÀÎ ¹®¸ÆÀ¸·Î, °¢ È£Ã⵿¾È¿¡ ¼Ò°ÅµË´Ï´Ù.
Áï palloc¸¦ »ç¿ëÇØ ÇÒ´çÇÑ °ÍÀÇ ¸ðµÎ¸¦ pfreeÇÒ ÇÊ¿ä´Â ¾ø½À´Ï´Ù.
À̰͵éÀº ¸ÓÁö¾Ê¾Æ ¼Ò°ÅµÇ´Â °ÍÀ̱⠶§¹®ÀÔ´Ï´Ù.
±×·¯³ª, µ¥ÀÌÅÍ ±¸Á¶¸¦ º¹¼öÀÇ È£Ãâ¿¡ °Ç³Ê »ç¿ëÇϵµ·Ï ÇÒ´çÇÏ´Â °æ¿ì´Â, ¾îµò°¡ ´Ù¸¥ Àå¼Ò¿¡ ³õ¾ÆµÑ Çʿ䰡 ÀÖ½À´Ï´Ù.
multi_call_memory_ctx¿¡ ÀÇÇØ ÂüÁ¶µÇ´Â ¸Þ¸ð¸® ÄÁÅØ½ºÆ®´Â,
SRFÀÇ ½ÇÇàÀÌ ³¡³¯ ¶§±îÁö »ç¿ë °¡´ÉÇÏ°Ô ÇØ¾ß ÇÏ´Â µ¥ÀÌÅÍÀÇ º¸°ü Àå¼Ò·Î¼ ÀûÇÕÇÕ´Ï´Ù.
Áï, ´ëºÎºÐÀÇ °æ¿ì, ÃÖÃÊÀÇ È£ÃâÀÇ ¼Â¾÷Áß¿¡ multi_call_memory_ctx¿¡ ¹Ù²Ü Çʿ䰡 ÀÖ´Ù°í ÇÏ´Â °ÍÀÔ´Ï´Ù.
¿ÏÀüÇÑ À¯»ç ÄÚµåÀÇ ¿¹¸¦ ³ªÅ¸³À´Ï´Ù.
Datum
my_set_returning_function(PG_FUNCTION_ARGS)
{
FuncCallContext *funcctx;
Datum result;
MemoryContext oldcontext;
further declarations as needed
if (SRF_IS_FIRSTCALL())
{
funcctx = SRF_FIRSTCALL_INIT();
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
/* ÇÑ ¹øÀÇ ¼Â¾÷ Äڵ尡 ¿©±â¿¡ µé¾î°©´Ï´Ù: */
user code
if returning composite
build TupleDesc, and perhaps AttInMetadata
endif returning composite
user code
MemoryContextSwitchTo(oldcontext);
}
/* ¸Åȸ ½ÇÇàÇÏ´Â ¼Â¾÷ Äڵ尡 ¿©±â¿¡ µé¾î°©´Ï´Ù: */
user code
funcctx = SRF_PERCALL_SETUP();
user code
/* À̰ÍÀº, Á¾·áÇß´ÂÁö ¾Æ´ÑÁö¸¦ Å×½ºÆ®ÇÏ´Â ¹æ¹ýÀÇ ÇϳªÀÔ´Ï´Ù: */
{
/* ¿©±â¼, ´Ù¸¥ Ç׸ñÀ» µ¹·ÁÁÝ´Ï´Ù: */
user code
obtain result Datum
SRF_RETURN_NEXT(funcctx, result);
}
else
{
/* À̰ÍÀ¸·Î Ç׸ñÀ» ´Ù µ¹·ÁÁÖ¾ú½À´Ï´Ù. ÈĴ Ŭ¸° ¾÷ ÇÒ »ÓÀÔ´Ï´Ù. */
user code
SRF_RETURN_DONE(funcctx);
}
}
º¹ÇÕÇüÀ» µ¹·ÁÁÖ´Â ´Ü¼øÇÑ SRFÀÇ ¿ÏÀüÇÑ ¿¹´Â ÀÌÇÏ¿Í °°½À´Ï´Ù.
PG_FUNCTION_INFO_V1(retcomposite);
Datum
retcomposite(PG_FUNCTION_ARGS)
{
FuncCallContext *funcctx;
int call_cntr;
int max_calls;
TupleDesc tupdesc;
AttInMetadata *attinmeta;
/* ÇÔ¼öÀÇ ÃÖÃÊÀÇ È£Ãâ½Ã¿¡¸¸ ½ÇÇà */
if (SRF_IS_FIRSTCALL())
{
MemoryContext oldcontext;
/* È£Ãâ°£¿¡ ¿µ±¸ÈÇÏ´Â ÇÔ¼ö ¹®¸ÆÀ» ÀÛ¼º */
funcctx = SRF_FIRSTCALL_INIT();
/* º¹¼ö ÇÔ¼ö È£Ãâ¿¡ ÀûÀýÇÑ ¸Þ¸ð¸® ÄÁÅØ½ºÆ®¿¡ÀÇ º¯È¯ */
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
/* µ¹·ÁÁÖ¾îÁö´Â Æ©ÇÃÀÇ ÇÕ°è¼ö */
funcctx->max_calls = PG_GETARG_UINT32(0);
/* °á°úÇü¿ëÀÇ Æ©Çà ±â¼ú¾î¸¦ ÀÛ¼º */
if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("function returning record called in context "
"that cannot accept type record")));
/*
* ´ÙÀ½¿¡ ¹Ì°¡°øÀÇ C¹®ÀÚ¿À¸·ÎºÎÅÍ Æ©ÇÃÀ» ÀÛ¼ºÇϱâ À§Çؼ ÇÊ¿äÇÏ´Ù
* ¼Ó¼º ¸ÞŸµ¥ÀÌÅÍÀÇ »ý¼º
*/
attinmeta = TupleDescGetAttInMetadata(tupdesc);
funcctx->attinmeta = attinmeta;
MemoryContextSwitchTo(oldcontext);
}
/* ¸ðµç ÇÔ¼ö È£Ãâ·Î ½ÇÇà */
funcctx = SRF_PERCALL_SETUP();
call_cntr = funcctx->call_cntr;
max_calls = funcctx->max_calls;
attinmeta = funcctx->attinmeta;
if (call_cntr < max_calls) /* ±× ¹Û¿¡µµ º¸³»´Â °ÍÀÌ ÀÖ´Â °æ¿ì */
{
char **values;
HeapTuple tuple;
Datum result;
/*
* µ¹·ÁÁÖ´Â Æ©ÇÃÀ» ±¸ÃàÇϱâ À§ÇÑ °ªÀÇ ¹è¿À» ÁغñÇÕ´Ï´Ù.
* À̰ÍÀº, ´ÙÀ½¿¡ ÀûÀýÇÑ ÀÔ·Â ÇÔ¼ö·Î 󸮵ȴÙ
* C¹®ÀÚ¿ÀÇ ¹è¿ÀÌ ¾Æ´Ï¸é ¾ÈµË´Ï´Ù.
*/
values = (char **) palloc(3 * sizeof(char *));
values[0] = (char *) palloc(16 * sizeof(char));
values[1] = (char *) palloc(16 * sizeof(char));
values[2] = (char *) palloc(16 * sizeof(char));
snprintf(values[0], 16, "%d", 1 * PG_GETARG_INT32(1));
snprintf(values[1], 16, "%d", 2 * PG_GETARG_INT32(1));
snprintf(values[2], 16, "%d", 3 * PG_GETARG_INT32(1));
/* Æ©ÇÃÀÇ ÀÛ¼º */
tuple = BuildTupleFromCStrings(attinmeta, values);
/* Æ©ÇÃÀ» datum¿¡ º¯È¯ */
result = HeapTupleGetDatum(tuple);
/* Ŭ¸° ¾÷(À̰ÍÀº Çʼö°¡ ¾Æ´Õ´Ï´Ù) */
pfree(values[0]);
pfree(values[1]);
pfree(values[2]);
pfree(values);
SRF_RETURN_NEXT(funcctx, result);
}
else /* ¾Æ¹«°Íµµ ³²Áö ¾ÊÀº °æ¿ì */
{
SRF_RETURN_DONE(funcctx);
}
}
ÀÌÇÏ¿¡ ÀÌ ÇÔ¼ö¸¦ SQL·Î ¼±¾ðÇÏ´Â ÀϷʸ¦ ³ªÅ¸³À´Ï´Ù.
CREATE TYPE __retcomposite AS (f1 integer, f2 integer, f3 integer);
CREATE OR REPLACE FUNCTION retcomposite(integer, integer)
RETURNS SETOF __retcomposite
AS '
filename
', 'retcomposite'
LANGUAGE C IMMUTABLE STRICT;
±× ¹Û¿¡µµ ÀÌÇÏ¿Í °°ÀÌ OUT ¸Å°³º¯¼ö¸¦ »ç¿ëÇÏ´Â ¹æ¹ýµµ ÀÖ½À´Ï´Ù.
CREATE OR REPLACE FUNCTION retcomposite(IN integer, IN integer,
OUT f1 integer, OUT f2 integer, OUT f3 integer)
RETURNS SETOF record
AS '
filename
', 'retcomposite'
LANGUAGE C IMMUTABLE STRICT;
ÀÌ ¹æ¹ý¿¡¼´Â, ÇÔ¼öÀÇ Ãâ·ÂÇüÀº Çü½Ä»ó À͸íÀÇ recordÇüÀÌ µÇ´Â °Í¿¡ ÁÖÀÇÇØ ÁÖ¼¼¿ä.
¼Ò½º ¹èÆ÷¹°³»ÀÇ contrib/tablefuncµð·ºÅ丮¿¡´Â, ÁýÇÕÀ» µ¹·ÁÁÖ´Â ÇÔ¼öº¸´Ù ¸¹Àº ¿¹°¡ ÀÖ½À´Ï´Ù.
C¾ð¾î ÇÔ¼ö´Â, anyelement, anyarray, anynonarray ¹× anyenum´ÙÇâÇüÀ» ¹Þ¾ÆµéÀ̰ųª,
¶Ç´Â µ¹·ÁÁÖµµ·Ï ¼±¾ðÇÒ ¼ö°¡ ÀÖ½À´Ï´Ù.
´ÙÇâ ÇÔ¼öÀÇ »ó¼¼ÇÑ ¼³¸íÀº Section 33.2.5À» ÂüÁ¶ÇØ ÁÖ¼¼¿ä.
ÇÔ¼öÀÇ ÀÎÀÚ È¤Àº ¹Ýȯ°ªÀÌ ´ÙÇâÇüÀ¸·Î¼ Á¤ÀÇµÉ ¶§, ÇÔ¼öÀÇ ÀÛ¼ºÀÚ´Â ¹Ì¸® È£ÃâÇÔ¿¡ ÀÖ¾î¼ÀÇ µ¥ÀÌÅÍÇüÀ̳ª
µ¹·ÁÁÖ¾î¾ß ÇÒ µ¥ÀÌÅÍÇüÀÌ ¹«¾ùÀÎÁö ¾Ë ¼ö ¾ø½À´Ï´Ù.
¹öÀü-1 CÇÔ¼ö·Î ÀÎÀÚÀÇ ¿¸Å µ¥ÀÌÅÍÇü°ú µ¹·ÁÁÖ¾î¾ß ÇÏ´Â °Í°ú »óÁ¤µÈ ÇüŸ¦ ¹ß°ßÇÒ ¼ö ÀÖ±â À§ÇÑ 2°³ÀÇ ·çƾÀÌ fmgr.h¿¡ ÁغñµÇ¾î ÀÖ½À´Ï´Ù.
ÀÌ ·çƾÀº get_fn_expr_rettype(FmgrInfo *flinfo)¿Í get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)¶ó´Â À̸§ÀÔ´Ï´Ù.
À̰͵éÀº °á°ú ȤÀº ÀÎÀÚÇüÀÇ OID¸¦ µ¹·ÁÁÝ´Ï´Ù.
´Ù¸¸, ¸¸¾à Á¤º¸¸¦ ÀÌ¿ëÇÒ ¼ö ¾øÀ¸¸é InvalidOid¸¦ µ¹·ÁÁÝ´Ï´Ù.
flinfo±¸Á¶´Â Åë»ó fcinfo->flinfo·Î¼ Á¢¼Ó µË´Ï´Ù.
argnum¸Å°³º¯¼ö´Â 0À¸·ÎºÎÅÍ ½ÃÀ۵˴ϴÙ.
¶Ç, get_fn_expr_rettype ´ë½Å¿¡ get_call_result_type¸¦ »ç¿ëÇÒ ¼öµµ ÀÖ½À´Ï´Ù.
¿¹¸¦ µé¸é, ÀÓÀÇÀÇ ÇüÅÂÀÇ ´ÜÀÏ ¿ä¼Ò¸¦ ¹Þ¾Æµé¿© ±× ÇüÅÂÀÇ 1 Â÷¿ø ¹è¿À» µ¹·ÁÁÖ´Â ÇÔ¼ö¸¦ »ý°¢ÇØ º¸°Ú½À´Ï´Ù.
PG_FUNCTION_INFO_V1(make_array);
Datum
make_array(PG_FUNCTION_ARGS)
{
ArrayType *result;
Oid element_type = get_fn_expr_argtype(fcinfo->flinfo, 0);
Datum element;
bool isnull;
int16 typlen;
bool typbyval;
char typalign;
int ndims;
int dims[MAXDIM];
int lbs[MAXDIM];
if (!OidIsValid(element_type))
elog(ERROR, "could not determine data type of input");
/* ÁÖ¾îÁø ¿ä¼Ò°¡ NULLÀÎÁö ¾Æ´ÑÁö ÁÖÀÇÇϸé¼, ¿ä¼Ò¸¦ ²¨³À´Ï´Ù. */
isnull = PG_ARGISNULL(0);
if (isnull)
element = (Datum) 0;
else
element = PG_GETARG_DATUM(0);
/* Â÷¿ø¼ö´Â 1 */
ndims = 1;
/* ¿ä¼Ò¸¦ 1°³ */
dims[0] = 1;
/* ÇÏÇÑÀº 1 */
lbs[0] = 1;
/* ÀÌ ¿ä¼ÒÇü¿¡ °üÇÑ ÇÊ¿ä Á¤º¸¸¦ ²¨³½´Ù. */
get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign);
/* ¿©±â¼ ¹è¿À» ÀÛ¼º */
result = construct_md_array(&element, &isnull, ndims, dims, lbs,
element_type, typlen, typbyval, typalign);
PG_RETURN_ARRAYTYPE_P(result);
}
ÀÌÇÏÀÇ ¸í·ÉÀº SQL·Î make_arrayÇÔ¼ö¸¦ ¼±¾ðÇÕ´Ï´Ù.
CREATE FUNCTION make_array(anyelement) RETURNS anyarray
AS '
DIRECTORY
/funcs', 'make_array'
LANGUAGE C IMMUTABLE;
¾Öµå ÀÎ(Add In)´Â LWLocks(°æ·® ¶ô)¿Í ¼¹ö ±âµ¿½Ã¿¡ °øÀ¯ ¸Þ¸ð¸®ÀÇ ÇÒ´çÀ» º¸°ü À¯ÁöÇÒ ¼ö°¡ ÀÖ½À´Ï´Ù.
shared_preload_libraries
·Î ÁöÁ¤ÇØ,
ÀÌ·¯ÇÑ ¾Öµå ÀÎ(Add In)ÀÇ °øÀ¯ ¶óÀ̺귯¸®¸¦ »çÀü¿¡ ·ÎµåÇÏÁö ¾ÊÀ¸¸é ¾ÈµË´Ï´Ù.
°øÀ¯ ¸Þ¸ð¸®´Â, ±× _PG_initÇÔ¼ö·Î ÀÌÇϸ¦ È£ÃâÇÏ´Â °ÍÀ¸·Î º¸°ü À¯ÁöµË´Ï´Ù.
void RequestAddinShmemSpace(int size)
LWLocks´Â ±× _PG_initÇÔ¼ö·Î ÀÌÇϸ¦ È£ÃâÇÏ´Â °ÍÀ¸·Î º¸°ü À¯ÁöµË´Ï´Ù.
void RequestAddinLWLocks(int n)
°æÇÕ »óÅÂÀÇ °¡´É¼ºÀ» ¹æÁöÇϱâ À§Çؼ, ÇÒ´çÇÒ ¼ö ÀÖ¾ú´ø °øÀ¯ ¸Þ¸ð¸®¿¡ÀÇ Á¢¼ÓÀ̳ª ±× ÃʱâȽÿ¡,
ÀÌÇÏ¿Í °°ÀÌ °¢ ¿¬±¸ ÃÖÁ¾ ´Ü°è¿¡ AddinShmemInitLock°æ·® ¶ôÀ» »ç¿ëÇÏÁö ¾ÊÀ¸¸é ¾ÈµË´Ï´Ù.
static mystruct *ptr = NULL;
if (!ptr)
{
bool found;
LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);
ptr = ShmemInitStruct("my struct name", size, &found);
if (!ptr)
elog(ERROR, "out of shared memory");
if (!found)
{
initialize contents of shmem area;
acquire any requested LWLocks using:
ptr->mylockid = LWLockAssign();
}
LWLockRelease(AddinShmemInitLock);
}