]> granicus.if.org Git - postgresql/blob - src/tutorial/funcs_new.c
A visit from the message-style police ...
[postgresql] / src / tutorial / funcs_new.c
1 /******************************************************************************
2   These are user-defined functions that can be bound to a Postgres backend
3   and called by Postgres to execute SQL functions of the same name.
4
5   The calling format for these functions is defined by the CREATE FUNCTION
6   SQL statement that binds them to the backend.
7
8   NOTE: this file shows examples of "new style" function call conventions.
9   See funcs.c for examples of "old style".
10 *****************************************************************************/
11
12 #include "postgres.h"                   /* general Postgres declarations */
13
14 #include "fmgr.h"                               /* for argument/result macros */
15 #include "executor/executor.h"  /* for GetAttributeByName() */
16 #include "utils/geo_decls.h"    /* for point type */
17
18
19 /* These prototypes just prevent possible warnings from gcc. */
20
21 Datum           add_one(PG_FUNCTION_ARGS);
22 Datum           add_one_float8(PG_FUNCTION_ARGS);
23 Datum           makepoint(PG_FUNCTION_ARGS);
24 Datum           copytext(PG_FUNCTION_ARGS);
25 Datum           concat_text(PG_FUNCTION_ARGS);
26 Datum           c_overpaid(PG_FUNCTION_ARGS);
27
28
29 /* By Value */
30
31 PG_FUNCTION_INFO_V1(add_one);
32
33 Datum
34 add_one(PG_FUNCTION_ARGS)
35 {
36         int32           arg = PG_GETARG_INT32(0);
37
38         PG_RETURN_INT32(arg + 1);
39 }
40
41 /* By Reference, Fixed Length */
42
43 PG_FUNCTION_INFO_V1(add_one_float8);
44
45 Datum
46 add_one_float8(PG_FUNCTION_ARGS)
47 {
48         /* The macros for FLOAT8 hide its pass-by-reference nature */
49         float8          arg = PG_GETARG_FLOAT8(0);
50
51         PG_RETURN_FLOAT8(arg + 1.0);
52 }
53
54 PG_FUNCTION_INFO_V1(makepoint);
55
56 Datum
57 makepoint(PG_FUNCTION_ARGS)
58 {
59         Point      *pointx = PG_GETARG_POINT_P(0);
60         Point      *pointy = PG_GETARG_POINT_P(1);
61         Point      *new_point = (Point *) palloc(sizeof(Point));
62
63         new_point->x = pointx->x;
64         new_point->y = pointy->y;
65
66         PG_RETURN_POINT_P(new_point);
67 }
68
69 /* By Reference, Variable Length */
70
71 PG_FUNCTION_INFO_V1(copytext);
72
73 Datum
74 copytext(PG_FUNCTION_ARGS)
75 {
76         text       *t = PG_GETARG_TEXT_P(0);
77
78         /*
79          * VARSIZE is the total size of the struct in bytes.
80          */
81         text       *new_t = (text *) palloc(VARSIZE(t));
82
83         VARATT_SIZEP(new_t) = VARSIZE(t);
84
85         /*
86          * VARDATA is a pointer to the data region of the struct.
87          */
88         memcpy((void *) VARDATA(new_t),         /* destination */
89                    (void *) VARDATA(t), /* source */
90                    VARSIZE(t) - VARHDRSZ);              /* how many bytes */
91         PG_RETURN_TEXT_P(new_t);
92 }
93
94 PG_FUNCTION_INFO_V1(concat_text);
95
96 Datum
97 concat_text(PG_FUNCTION_ARGS)
98 {
99         text       *arg1 = PG_GETARG_TEXT_P(0);
100         text       *arg2 = PG_GETARG_TEXT_P(1);
101         int32           new_text_size = VARSIZE(arg1) + VARSIZE(arg2) - VARHDRSZ;
102         text       *new_text = (text *) palloc(new_text_size);
103
104         memset((void *) new_text, 0, new_text_size);
105         VARATT_SIZEP(new_text) = new_text_size;
106         strncpy(VARDATA(new_text), VARDATA(arg1), VARSIZE(arg1) - VARHDRSZ);
107         strncat(VARDATA(new_text), VARDATA(arg2), VARSIZE(arg2) - VARHDRSZ);
108         PG_RETURN_TEXT_P(new_text);
109 }
110
111 /* Composite types */
112
113 PG_FUNCTION_INFO_V1(c_overpaid);
114
115 Datum
116 c_overpaid(PG_FUNCTION_ARGS)
117 {
118         TupleTableSlot *t = (TupleTableSlot *) PG_GETARG_POINTER(0);
119         int32           limit = PG_GETARG_INT32(1);
120         bool            isnull;
121         int32           salary;
122
123         salary = DatumGetInt32(GetAttributeByName(t, "salary", &isnull));
124         if (isnull)
125                 PG_RETURN_BOOL(false);
126
127         /*
128          * Alternatively, we might prefer to do PG_RETURN_NULL() for null
129          * salary
130          */
131
132         PG_RETURN_BOOL(salary > limit);
133 }