|
6 | 6 |
|
7 | 7 | The calling format for these functions is defined by the CREATE FUNCTION
|
8 | 8 | SQL statement that binds them to the backend.
|
9 |
| -
|
10 |
| - NOTE: this file shows examples of "old style" function call conventions. |
11 |
| - See funcs_new.c for examples of "new style". |
12 | 9 | *****************************************************************************/
|
13 | 10 |
|
14 | 11 | #include"postgres.h"/* general Postgres declarations */
|
|
18 | 15 |
|
19 | 16 | PG_MODULE_MAGIC;
|
20 | 17 |
|
21 |
| -/* These prototypes just prevent possible warnings from gcc. */ |
22 |
| - |
23 |
| -intadd_one(intarg); |
24 |
| -float8*add_one_float8(float8*arg); |
25 |
| -Point*makepoint(Point*pointx,Point*pointy); |
26 |
| -text*copytext(text*t); |
27 |
| -text*concat_text(text*arg1,text*arg2); |
28 |
| -boolc_overpaid(HeapTupleHeadert,/* the current instance of EMP */ |
29 |
| -int32limit); |
30 |
| - |
31 | 18 |
|
32 | 19 | /* By Value */
|
33 | 20 |
|
34 |
| -int |
35 |
| -add_one(intarg) |
| 21 | +PG_FUNCTION_INFO_V1(add_one); |
| 22 | + |
| 23 | +Datum |
| 24 | +add_one(PG_FUNCTION_ARGS) |
36 | 25 | {
|
37 |
| -returnarg+1; |
| 26 | +int32arg=PG_GETARG_INT32(0); |
| 27 | + |
| 28 | +PG_RETURN_INT32(arg+1); |
38 | 29 | }
|
39 | 30 |
|
40 | 31 | /* By Reference, Fixed Length */
|
41 | 32 |
|
42 |
| -float8* |
43 |
| -add_one_float8(float8*arg) |
44 |
| -{ |
45 |
| -float8*result= (float8*)palloc(sizeof(float8)); |
| 33 | +PG_FUNCTION_INFO_V1(add_one_float8); |
46 | 34 |
|
47 |
| -*result=*arg+1.0; |
| 35 | +Datum |
| 36 | +add_one_float8(PG_FUNCTION_ARGS) |
| 37 | +{ |
| 38 | +/* The macros for FLOAT8 hide its pass-by-reference nature */ |
| 39 | +float8arg=PG_GETARG_FLOAT8(0); |
48 | 40 |
|
49 |
| -returnresult; |
| 41 | +PG_RETURN_FLOAT8(arg+1.0); |
50 | 42 | }
|
51 | 43 |
|
52 |
| -Point* |
53 |
| -makepoint(Point*pointx,Point*pointy) |
| 44 | +PG_FUNCTION_INFO_V1(makepoint); |
| 45 | + |
| 46 | +Datum |
| 47 | +makepoint(PG_FUNCTION_ARGS) |
54 | 48 | {
|
| 49 | +Point*pointx=PG_GETARG_POINT_P(0); |
| 50 | +Point*pointy=PG_GETARG_POINT_P(1); |
55 | 51 | Point*new_point= (Point*)palloc(sizeof(Point));
|
56 | 52 |
|
57 | 53 | new_point->x=pointx->x;
|
58 | 54 | new_point->y=pointy->y;
|
59 | 55 |
|
60 |
| -returnnew_point; |
| 56 | +PG_RETURN_POINT_P(new_point); |
61 | 57 | }
|
62 | 58 |
|
63 | 59 | /* By Reference, Variable Length */
|
64 | 60 |
|
65 |
| -text* |
66 |
| -copytext(text*t) |
| 61 | +PG_FUNCTION_INFO_V1(copytext); |
| 62 | + |
| 63 | +Datum |
| 64 | +copytext(PG_FUNCTION_ARGS) |
67 | 65 | {
|
| 66 | +text*t=PG_GETARG_TEXT_PP(0); |
| 67 | + |
68 | 68 | /*
|
69 |
| - * VARSIZE is the total size of the struct in bytes. |
| 69 | + * VARSIZE_ANY_EXHDR is the size of the struct in bytes, minus the |
| 70 | + * VARHDRSZ or VARHDRSZ_SHORT of its header. Construct the copy with a |
| 71 | + * full-length header. |
70 | 72 | */
|
71 |
| -text*new_t= (text*)palloc(VARSIZE(t)); |
| 73 | +text*new_t= (text*)palloc(VARSIZE_ANY_EXHDR(t)+VARHDRSZ); |
72 | 74 |
|
73 |
| -SET_VARSIZE(new_t,VARSIZE(t)); |
| 75 | +SET_VARSIZE(new_t,VARSIZE_ANY_EXHDR(t)+VARHDRSZ); |
74 | 76 |
|
75 | 77 | /*
|
76 |
| - * VARDATA is a pointer to the data region of the struct. |
| 78 | + * VARDATA is a pointer to the data region of the new struct. The source |
| 79 | + * could be a short datum, so retrieve its data through VARDATA_ANY. |
77 | 80 | */
|
78 | 81 | memcpy((void*)VARDATA(new_t),/* destination */
|
79 |
| - (void*)VARDATA(t),/* source */ |
80 |
| -VARSIZE(t)-VARHDRSZ);/* how many bytes */ |
81 |
| -returnnew_t; |
| 82 | + (void*)VARDATA_ANY(t),/* source */ |
| 83 | +VARSIZE_ANY_EXHDR(t));/* how many bytes */ |
| 84 | +PG_RETURN_TEXT_P(new_t); |
82 | 85 | }
|
83 | 86 |
|
84 |
| -text* |
85 |
| -concat_text(text*arg1,text*arg2) |
| 87 | +PG_FUNCTION_INFO_V1(concat_text); |
| 88 | + |
| 89 | +Datum |
| 90 | +concat_text(PG_FUNCTION_ARGS) |
86 | 91 | {
|
87 |
| -int32arg1_size=VARSIZE(arg1)-VARHDRSZ; |
88 |
| -int32arg2_size=VARSIZE(arg2)-VARHDRSZ; |
| 92 | +text*arg1=PG_GETARG_TEXT_PP(0); |
| 93 | +text*arg2=PG_GETARG_TEXT_PP(1); |
| 94 | +int32arg1_size=VARSIZE_ANY_EXHDR(arg1); |
| 95 | +int32arg2_size=VARSIZE_ANY_EXHDR(arg2); |
89 | 96 | int32new_text_size=arg1_size+arg2_size+VARHDRSZ;
|
90 | 97 | text*new_text= (text*)palloc(new_text_size);
|
91 | 98 |
|
92 | 99 | SET_VARSIZE(new_text,new_text_size);
|
93 |
| -memcpy(VARDATA(new_text),VARDATA(arg1),arg1_size); |
94 |
| -memcpy(VARDATA(new_text)+arg1_size,VARDATA(arg2),arg2_size); |
95 |
| -returnnew_text; |
| 100 | +memcpy(VARDATA(new_text),VARDATA_ANY(arg1),arg1_size); |
| 101 | +memcpy(VARDATA(new_text)+arg1_size,VARDATA_ANY(arg2),arg2_size); |
| 102 | +PG_RETURN_TEXT_P(new_text); |
96 | 103 | }
|
97 | 104 |
|
98 | 105 | /* Composite types */
|
99 | 106 |
|
100 |
| -bool |
101 |
| -c_overpaid(HeapTupleHeadert,/* the current instance of EMP */ |
102 |
| -int32limit) |
| 107 | +PG_FUNCTION_INFO_V1(c_overpaid); |
| 108 | + |
| 109 | +Datum |
| 110 | +c_overpaid(PG_FUNCTION_ARGS) |
103 | 111 | {
|
| 112 | +HeapTupleHeadert=PG_GETARG_HEAPTUPLEHEADER(0); |
| 113 | +int32limit=PG_GETARG_INT32(1); |
104 | 114 | boolisnull;
|
105 | 115 | int32salary;
|
106 | 116 |
|
107 | 117 | salary=DatumGetInt32(GetAttributeByName(t,"salary",&isnull));
|
108 | 118 | if (isnull)
|
109 |
| -return false; |
110 |
| -returnsalary>limit; |
| 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); |
111 | 126 | }
|