Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1276838
  • 博文数量: 185
  • 博客积分: 50
  • 博客等级: 民兵
  • 技术积分: 3934
  • 用 户 组: 普通用户
  • 注册时间: 2007-09-11 13:11
个人简介

iihero@ChinaUnix, ehero.[iihero] 数据库技术的痴迷爱好者. 您可以通过iihero AT qq.com联系到我 以下是我的三本图书: Sybase ASE in Action, Oracle Spatial及OCI高级编程, Java2网络协议内幕

文章分类

全部博文(185)

文章存档

2014年(4)

2013年(181)

分类: Mysql/postgreSQL

2013-07-26 10:47:13

不得不说,在这点上,PostgreSQL功能非常强大,不亚于任何家大型商业数据库。要添加一些自定义函数,不是那么复杂。

下边的示例会添加如下函数:test(), concat_text(string, string)  还有另外两个,不作举例,您可以自行尝试

1. 代码如下:

  1. /* $PostgreSQL: pgsql/src/tutorial/funcs_new.c,v 1.13 2007/02/27 23:48:10 tgl Exp $ */  
  2.   
  3. /****************************************************************************** 
  4.   These are user-defined functions that can be bound to a Postgres backend 
  5.   and called by Postgres to execute SQL functions of the same name. 
  6.  
  7.   The calling format for these functions is defined by the CREATE FUNCTION 
  8.   SQL statement that binds them to the backend. 
  9.  
  10.   NOTE: this file shows examples of "new style" function call conventions. 
  11.   See funcs.c for examples of "old style". 
  12. *****************************************************************************/  
  13.   
  14. #include "postgres.h"           /* general Postgres declarations */  
  15.   
  16. #include "executor/executor.h"  /* for GetAttributeByName() */  
  17. #include "utils/geo_decls.h"    /* for point type */  
  18.   
  19. #include "executor/spi.h"  
  20.   
  21. PG_MODULE_MAGIC;  
  22.   
  23. /* These prototypes just prevent possible warnings from gcc. */  
  24. //  
  25. //Datum     add_one(PG_FUNCTION_ARGS);  
  26. //Datum     add_one_float8(PG_FUNCTION_ARGS);  
  27. //Datum     makepoint(PG_FUNCTION_ARGS);  
  28. //Datum     copytext(PG_FUNCTION_ARGS);  
  29. //Datum     concat_text(PG_FUNCTION_ARGS);  
  30. //Datum     c_overpaid(PG_FUNCTION_ARGS);  
  31.   
  32.   
  33. /* By Value */  
  34.   
  35. PG_FUNCTION_INFO_V1(add_one);  
  36.   
  37. __declspec (dllexport) Datum  
  38. add_one(PG_FUNCTION_ARGS)  
  39. {  
  40.     int32       arg = PG_GETARG_INT32(0);  
  41.   
  42.     PG_RETURN_INT32(arg + 1);  
  43. }  
  44.   
  45. /* By Reference, Fixed Length */  
  46.   
  47. PG_FUNCTION_INFO_V1(add_one_float8);  
  48.   
  49. __declspec (dllexport) Datum  
  50. add_one_float8(PG_FUNCTION_ARGS)  
  51. {  
  52.     /* The macros for FLOAT8 hide its pass-by-reference nature */  
  53.     float8      arg = PG_GETARG_FLOAT8(0);  
  54.   
  55.     PG_RETURN_FLOAT8(arg + 1.0);  
  56. }  
  57.   
  58. PG_FUNCTION_INFO_V1(makepoint);  
  59.   
  60. __declspec (dllexport) Datum  
  61. makepoint(PG_FUNCTION_ARGS)  
  62. {  
  63.     Point      *pointx = PG_GETARG_POINT_P(0);  
  64.     Point      *pointy = PG_GETARG_POINT_P(1);  
  65.     Point      *new_point = (Point *) palloc(sizeof(Point));  
  66.   
  67.     new_point->x = pointx->x;  
  68.     new_point->y = pointy->y;  
  69.   
  70.     PG_RETURN_POINT_P(new_point);  
  71. }  
  72.   
  73. /* By Reference, Variable Length */  
  74.   
  75. PG_FUNCTION_INFO_V1(copytext);  
  76.   
  77. __declspec (dllexport) Datum  
  78. copytext(PG_FUNCTION_ARGS)  
  79. {  
  80.     text       *t = PG_GETARG_TEXT_P(0);  
  81.   
  82.     /* 
  83.      * VARSIZE is the total size of the struct in bytes. 
  84.      */  
  85.     text       *new_t = (text *) palloc(VARSIZE(t));  
  86.   
  87.     SET_VARSIZE(new_t, VARSIZE(t));  
  88.   
  89.     /* 
  90.      * VARDATA is a pointer to the data region of the struct. 
  91.      */  
  92.     memcpy((void *) VARDATA(new_t),     /* destination */  
  93.            (void *) VARDATA(t), /* source */  
  94.            VARSIZE(t) - VARHDRSZ);      /* how many bytes */  
  95.     PG_RETURN_TEXT_P(new_t);  
  96. }  
  97.   
  98. PG_FUNCTION_INFO_V1(concat_text);  
  99.   
  100. __declspec (dllexport) Datum  
  101. concat_text(PG_FUNCTION_ARGS)  
  102. {  
  103.     text       *arg1 = PG_GETARG_TEXT_P(0);  
  104.     text       *arg2 = PG_GETARG_TEXT_P(1);  
  105.     int32       arg1_size = VARSIZE(arg1) - VARHDRSZ;  
  106.     int32       arg2_size = VARSIZE(arg2) - VARHDRSZ;  
  107.     int32       new_text_size = arg1_size + arg2_size + VARHDRSZ;  
  108.     text       *new_text = (text *) palloc(new_text_size);  
  109.   
  110.     SET_VARSIZE(new_text, new_text_size);  
  111.     memcpy(VARDATA(new_text), VARDATA(arg1), arg1_size);  
  112.     memcpy(VARDATA(new_text) + arg1_size, VARDATA(arg2), arg2_size);  
  113.     PG_RETURN_TEXT_P(new_text);  
  114. }  
  115.   
  116. /* Composite types */  
  117.   
  118. PG_FUNCTION_INFO_V1(c_overpaid);  
  119.   
  120. __declspec (dllexport) Datum  
  121. c_overpaid(PG_FUNCTION_ARGS)  
  122. {  
  123.     HeapTupleHeader t = PG_GETARG_HEAPTUPLEHEADER(0);  
  124.     int32       limit = PG_GETARG_INT32(1);  
  125.     bool        isnull;  
  126.     int32       salary;  
  127.   
  128.     salary = DatumGetInt32(GetAttributeByName(t, "salary", &isnull));  
  129.     if (isnull)  
  130.         PG_RETURN_BOOL(false);  
  131.   
  132.     /* 
  133.      * Alternatively, we might prefer to do PG_RETURN_NULL() for null salary 
  134.      */  
  135.   
  136.     PG_RETURN_BOOL(salary > limit);  
  137. }  
  138.   
  139. PG_FUNCTION_INFO_V1(test);  
  140. __declspec (dllexport)  Datum test(PG_FUNCTION_ARGS)  
  141. {  
  142.        char *command;  
  143.        int ret;  
  144.        int proc;  
  145.   
  146.        command = "SELECT 1";  
  147.   
  148.        elog(INFO,"1");  
  149.   
  150.        SPI_connect();  
  151.   
  152.        elog(INFO,"2");  
  153.   
  154.        ret = SPI_exec(command, 1);  
  155.   
  156.        elog(INFO,"3");  
  157.   
  158.        proc = SPI_processed;  
  159.   
  160.        elog(INFO,"4");  
  161.        if (ret > 0 && SPI_tuptable != NULL)  
  162.        {  
  163.            TupleDesc tupdesc = SPI_tuptable->tupdesc;  
  164.            SPITupleTable *tuptable = SPI_tuptable;  
  165.            char buf[8192];  
  166.            int i, j;  
  167.   
  168.            elog(INFO,"5");  
  169.            for (j = 0; j < proc; j++)  
  170.            {  
  171.                HeapTuple tuple = tuptable->vals[j];  
  172.   
  173.                elog(INFO,"6");  
  174.                for (i = 1, buf[0] = 0; i <= tupdesc->natts; i++)  
  175.                {  
  176.                        snprintf(buf + strlen (buf), sizeof(buf) - strlen(buf), " %s%s",  
  177.                                 SPI_getvalue(tuple, tupdesc, i),  
  178.                                 (i == tupdesc->natts) ? " " : " |");  
  179.   
  180.                        elog(INFO,"7");  
  181.                }  
  182.                elog(INFO, "EXECQ: %s", buf);  
  183.            }  
  184.        }  
  185.   
  186.        SPI_finish();  
  187.        // pfree(command);  
  188.   
  189. }  

2. 编译过程

要注意的是编译过程,需要添加头文件路径,lib路径,bin路径,以完成编译,最后得到func1.dll,以本例为例,过程并不复杂。在linux平台,相信更简单。

以windows为例,您可以先从 下载整个示例工程,应该是vs2005的vc++工程,添加如下include路径,最前头带PG(9.0或以上)的安装路径:

include\server
include\server\port\win32
include\server\port\win32_msvc
include\

最后得到func1.dll,将其复制到${PG_HOME}\bin下边。

3. 验证创建的函数


  1. "code" class="java">create function mytest() RETURNs VARCHAR(256)  
  2. AS 'd:/pg921/bin/func1''test'  
  3. LANGUAGE C STRICT;  
  4.   
  5. 说明: 添加SQL函数mytest, 不带参数,它的实现是func1.dll中的test,含义非常明确。    
  6.   
  7. iihero=# create function mytest() RETURNs VARCHAR(256)  
  8. iihero-# AS 'd:/pg921/bin/func1''test'  
  9. iihero-# LANGUAGE C STRICT;  
  10. CREATE FUNCTION  
  11. iihero=# select mytest();  
  12. INFO:  1  
  13. INFO:  2  
  14. INFO:  3  
  15. INFO:  4  
  16. INFO:  5  
  17. INFO:  6  
  18. INFO:  7  
  19. INFO:  EXECQ:  1  
  20. server closed the connection unexpectedly  
  21.         This probably means the server terminated abnormally  
  22.         before or while processing the request.  
  23. The connection to the server was lost. Attempting reset: Succeeded.  
  24.   
  25.   
  26. create function myconcat(varchar(256), varchar(256)) RETURNs VARCHAR(512)  
  27. AS 'd:/pg921/bin/func1''concat_text'  
  28. LANGUAGE C STRICT;  
  29.   
  30. 说明: 添加函数myconcat, 带两个字符串参数,它的实现是func1.dll中的concat_text,含义非常明确。  
  31.   
  32. iihero=# create function myconcat(varchar(256), varchar(256)) RETURNs VARCHAR(512)  
  33. iihero-# AS 'd:/pg921/bin/func1''concat_text'  
  34. iihero-# LANGUAGE C STRICT;  
  35. CREATE FUNCTION  
  36. iihero=# select myconcat('abc###, ''bcd1234');  
  37.     myconcat  
  38. -----------------  
  39.  abc###, bcd1234  
  40. (1 row)  
  41.   
  42.   
  43. iihero=#

      

其实,在其它商业数据库里,至少Sybase ASE/ASA, Oracle是支持这种C函数扩展的,就是编写起来,可能更麻烦一些。
阅读(2069) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~