|
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