使用C编写的动态链接库为PostgreSQL数据库添加自定义函数


不得不说,在这点上,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.     int32       arg = PG_GETARG_INT32(0); 
  40.  
  41.     PG_RETURN_INT32(arg + 1); 
  42.  
  43. /* By Reference, Fixed Length */ 
  44.  
  45. PG_FUNCTION_INFO_V1(add_one_float8); 
  46.  
  47. __declspec (dllexport) Datum 
  48. add_one_float8(PG_FUNCTION_ARGS) 
  49.     /* The macros for FLOAT8 hide its pass-by-reference nature */ 
  50.     float8      arg = PG_GETARG_FLOAT8(0); 
  51.  
  52.     PG_RETURN_FLOAT8(arg + 1.0); 
  53.  
  54. PG_FUNCTION_INFO_V1(makepoint); 
  55.  
  56. __declspec (dllexport) Datum 
  57. makepoint(PG_FUNCTION_ARGS) 
  58.     Point      *pointx = PG_GETARG_POINT_P(0); 
  59.     Point      *pointy = PG_GETARG_POINT_P(1); 
  60.     Point      *new_point = (Point *) palloc(sizeof(Point)); 
  61.  
  62.     new_point->x = pointx->x; 
  63.     new_point->y = pointy->y; 
  64.  
  65.     PG_RETURN_POINT_P(new_point); 
  66.  
  67. /* By Reference, Variable Length */ 
  68.  
  69. PG_FUNCTION_INFO_V1(copytext); 
  70.  
  71. __declspec (dllexport) Datum 
  72. copytext(PG_FUNCTION_ARGS) 
  73.     text       *t = PG_GETARG_TEXT_P(0); 
  74.  
  75.     /* 
  76.      * VARSIZE is the total size of the struct in bytes. 
  77.      */ 
  78.     text       *new_t = (text *) palloc(VARSIZE(t)); 
  79.  
  80.     SET_VARSIZE(new_t, VARSIZE(t)); 
  81.  
  82.     /* 
  83.      * VARDATA is a pointer to the data region of the struct. 
  84.      */ 
  85.     memcpy((void *) VARDATA(new_t),     /* destination */ 
  86.            (void *) VARDATA(t), /* source */ 
  87.            VARSIZE(t) - VARHDRSZ);      /* how many bytes */ 
  88.     PG_RETURN_TEXT_P(new_t); 
  89.  
  90. PG_FUNCTION_INFO_V1(concat_text); 
  91.  
  92. __declspec (dllexport) Datum 
  93. concat_text(PG_FUNCTION_ARGS) 
  94.     text       *arg1 = PG_GETARG_TEXT_P(0); 
  95.     text       *arg2 = PG_GETARG_TEXT_P(1); 
  96.     int32       arg1_size = VARSIZE(arg1) - VARHDRSZ; 
  97.     int32       arg2_size = VARSIZE(arg2) - VARHDRSZ; 
  98.     int32       new_text_size = arg1_size + arg2_size + VARHDRSZ; 
  99.     text       *new_text = (text *) palloc(new_text_size); 
  100.  
  101.     SET_VARSIZE(new_text, new_text_size); 
  102.     memcpy(VARDATA(new_text), VARDATA(arg1), arg1_size); 
  103.     memcpy(VARDATA(new_text) + arg1_size, VARDATA(arg2), arg2_size); 
  104.     PG_RETURN_TEXT_P(new_text); 
  105.  
  106. /* Composite types */ 
  107.  
  108. PG_FUNCTION_INFO_V1(c_overpaid); 
  109.  
  110. __declspec (dllexport) Datum 
  111. c_overpaid(PG_FUNCTION_ARGS) 
  112.     HeapTupleHeader t = PG_GETARG_HEAPTUPLEHEADER(0); 
  113.     int32       limit = PG_GETARG_INT32(1); 
  114.     bool        isnull; 
  115.     int32       salary; 
  116.  
  117.     salary = DatumGetInt32(GetAttributeByName(t, "salary", &isnull)); 
  118.     if (isnull) 
  119.         PG_RETURN_BOOL(false); 
  120.  
  121.     /* 
  122.      * Alternatively, we might prefer to do PG_RETURN_NULL() for null salary 
  123.      */ 
  124.  
  125.     PG_RETURN_BOOL(salary > limit); 
  126.  
  127. PG_FUNCTION_INFO_V1(test); 
  128. __declspec (dllexport)  Datum test(PG_FUNCTION_ARGS) 
  129.        char *command; 
  130.        int ret; 
  131.        int proc; 
  132.  
  133.        command = "SELECT 1"
  134.  
  135.        elog(INFO,"1"); 
  136.  
  137.        SPI_connect(); 
  138.  
  139.        elog(INFO,"2"); 
  140.  
  141.        ret = SPI_exec(command, 1); 
  142.  
  143.        elog(INFO,"3"); 
  144.  
  145.        proc = SPI_processed; 
  146.  
  147.        elog(INFO,"4"); 
  148.        if (ret > 0 && SPI_tuptable != NULL) 
  149.        { 
  150.            TupleDesc tupdesc = SPI_tuptable->tupdesc; 
  151.            SPITupleTable *tuptable = SPI_tuptable; 
  152.            char buf[8192]; 
  153.            int i, j; 
  154.  
  155.            elog(INFO,"5"); 
  156.            for (j = 0; j < proc; j++) 
  157.            { 
  158.                HeapTuple tuple = tuptable->vals[j]; 
  159.  
  160.                elog(INFO,"6"); 
  161.                for (i = 1, buf[0] = 0; i <= tupdesc->natts; i++) 
  162.                { 
  163.                        snprintf(buf + strlen (buf), sizeof(buf) - strlen(buf), " %s%s"
  164.                                 SPI_getvalue(tuple, tupdesc, i), 
  165.                                 (i == tupdesc->natts) ? " " : " |"); 
  166.  
  167.                        elog(INFO,"7"); 
  168.                } 
  169.                elog(INFO, "EXECQ: %s", buf); 
  170.            } 
  171.        } 
  172.  
  173.        SPI_finish(); 
  174.        // pfree(command);  
  175.  
  • 1
  • 2
  • 下一页

相关内容