|
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 | | -int add_one(int arg); |
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 | | -bool c_overpaid(HeapTupleHeader t, /* the current instance of EMP */ |
29 | | - int32 limit); |
30 | | - |
31 | 18 |
|
32 | 19 | /* By Value */ |
33 | 20 |
|
34 | | -int |
35 | | -add_one(int arg) |
| 21 | +PG_FUNCTION_INFO_V1(add_one); |
| 22 | + |
| 23 | +Datum |
| 24 | +add_one(PG_FUNCTION_ARGS) |
36 | 25 | { |
37 | | - return arg + 1; |
| 26 | + int32 arg = 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 | + float8 arg = PG_GETARG_FLOAT8(0); |
48 | 40 |
|
49 | | - return result; |
| 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 | | - return new_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 | | - return new_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 | | - int32 arg1_size = VARSIZE(arg1) - VARHDRSZ; |
88 | | - int32 arg2_size = VARSIZE(arg2) - VARHDRSZ; |
| 92 | + text *arg1 = PG_GETARG_TEXT_PP(0); |
| 93 | + text *arg2 = PG_GETARG_TEXT_PP(1); |
| 94 | + int32 arg1_size = VARSIZE_ANY_EXHDR(arg1); |
| 95 | + int32 arg2_size = VARSIZE_ANY_EXHDR(arg2); |
89 | 96 | int32 new_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 | | - return new_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(HeapTupleHeader t, /* the current instance of EMP */ |
102 | | - int32 limit) |
| 107 | +PG_FUNCTION_INFO_V1(c_overpaid); |
| 108 | + |
| 109 | +Datum |
| 110 | +c_overpaid(PG_FUNCTION_ARGS) |
103 | 111 | { |
| 112 | + HeapTupleHeader t = PG_GETARG_HEAPTUPLEHEADER(0); |
| 113 | + int32 limit = PG_GETARG_INT32(1); |
104 | 114 | bool isnull; |
105 | 115 | int32 salary; |
106 | 116 |
|
107 | 117 | salary = DatumGetInt32(GetAttributeByName(t, "salary", &isnull)); |
108 | 118 | if (isnull) |
109 | | - return false; |
110 | | - return salary > 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 | } |
0 commit comments