]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/char.c
Add explicit tests for division by zero to all user-accessible integer
[postgresql] / src / backend / utils / adt / char.c
1 /*-------------------------------------------------------------------------
2  *
3  * char.c
4  *        Functions for the built-in type "char".
5  *        Functions for the built-in type "cid" (what's that doing here?)
6  *
7  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
8  * Portions Copyright (c) 1994, Regents of the University of California
9  *
10  *
11  * IDENTIFICATION
12  *        $Header: /cvsroot/pgsql/src/backend/utils/adt/char.c,v 1.34 2003/03/11 21:01:33 tgl Exp $
13  *
14  *-------------------------------------------------------------------------
15  */
16 #include "postgres.h"
17
18 #include "utils/builtins.h"
19
20 /*****************************************************************************
21  *       USER I/O ROUTINES                                                                                                               *
22  *****************************************************************************/
23
24 /*
25  *              charin                  - converts "x" to 'x'
26  *
27  * Note that an empty input string will implicitly be converted to \0.
28  */
29 Datum
30 charin(PG_FUNCTION_ARGS)
31 {
32         char       *ch = PG_GETARG_CSTRING(0);
33
34         PG_RETURN_CHAR(ch[0]);
35 }
36
37 /*
38  *              charout                 - converts 'x' to "x"
39  *
40  * Note that if the char value is \0, the resulting string will appear
41  * to be empty (null-terminated after zero characters).  So this is the
42  * inverse of the charin() function for such data.
43  */
44 Datum
45 charout(PG_FUNCTION_ARGS)
46 {
47         char            ch = PG_GETARG_CHAR(0);
48         char       *result = (char *) palloc(2);
49
50         result[0] = ch;
51         result[1] = '\0';
52         PG_RETURN_CSTRING(result);
53 }
54
55 /*****************************************************************************
56  *       PUBLIC ROUTINES                                                                                                                 *
57  *****************************************************************************/
58
59 /*
60  * NOTE: comparisons are done as though char is unsigned (uint8).
61  * Arithmetic is done as though char is signed (int8).
62  *
63  * You wanted consistency?
64  */
65
66 Datum
67 chareq(PG_FUNCTION_ARGS)
68 {
69         char            arg1 = PG_GETARG_CHAR(0);
70         char            arg2 = PG_GETARG_CHAR(1);
71
72         PG_RETURN_BOOL(arg1 == arg2);
73 }
74
75 Datum
76 charne(PG_FUNCTION_ARGS)
77 {
78         char            arg1 = PG_GETARG_CHAR(0);
79         char            arg2 = PG_GETARG_CHAR(1);
80
81         PG_RETURN_BOOL(arg1 != arg2);
82 }
83
84 Datum
85 charlt(PG_FUNCTION_ARGS)
86 {
87         char            arg1 = PG_GETARG_CHAR(0);
88         char            arg2 = PG_GETARG_CHAR(1);
89
90         PG_RETURN_BOOL((uint8) arg1 < (uint8) arg2);
91 }
92
93 Datum
94 charle(PG_FUNCTION_ARGS)
95 {
96         char            arg1 = PG_GETARG_CHAR(0);
97         char            arg2 = PG_GETARG_CHAR(1);
98
99         PG_RETURN_BOOL((uint8) arg1 <= (uint8) arg2);
100 }
101
102 Datum
103 chargt(PG_FUNCTION_ARGS)
104 {
105         char            arg1 = PG_GETARG_CHAR(0);
106         char            arg2 = PG_GETARG_CHAR(1);
107
108         PG_RETURN_BOOL((uint8) arg1 > (uint8) arg2);
109 }
110
111 Datum
112 charge(PG_FUNCTION_ARGS)
113 {
114         char            arg1 = PG_GETARG_CHAR(0);
115         char            arg2 = PG_GETARG_CHAR(1);
116
117         PG_RETURN_BOOL((uint8) arg1 >= (uint8) arg2);
118 }
119
120 Datum
121 charpl(PG_FUNCTION_ARGS)
122 {
123         char            arg1 = PG_GETARG_CHAR(0);
124         char            arg2 = PG_GETARG_CHAR(1);
125
126         PG_RETURN_CHAR((int8) arg1 + (int8) arg2);
127 }
128
129 Datum
130 charmi(PG_FUNCTION_ARGS)
131 {
132         char            arg1 = PG_GETARG_CHAR(0);
133         char            arg2 = PG_GETARG_CHAR(1);
134
135         PG_RETURN_CHAR((int8) arg1 - (int8) arg2);
136 }
137
138 Datum
139 charmul(PG_FUNCTION_ARGS)
140 {
141         char            arg1 = PG_GETARG_CHAR(0);
142         char            arg2 = PG_GETARG_CHAR(1);
143
144         PG_RETURN_CHAR((int8) arg1 * (int8) arg2);
145 }
146
147 Datum
148 chardiv(PG_FUNCTION_ARGS)
149 {
150         char            arg1 = PG_GETARG_CHAR(0);
151         char            arg2 = PG_GETARG_CHAR(1);
152
153         if (arg2 == 0)
154                 elog(ERROR, "division by zero");
155
156         PG_RETURN_CHAR((int8) arg1 / (int8) arg2);
157 }
158
159
160 Datum
161 text_char(PG_FUNCTION_ARGS)
162 {
163         text       *arg1 = PG_GETARG_TEXT_P(0);
164         char            result;
165
166         /*
167          * An empty input string is converted to \0 (for consistency with
168          * charin). If the input is longer than one character, the excess data
169          * is silently discarded.
170          */
171         if (VARSIZE(arg1) > VARHDRSZ)
172                 result = *(VARDATA(arg1));
173         else
174                 result = '\0';
175
176         PG_RETURN_CHAR(result);
177 }
178
179 Datum
180 char_text(PG_FUNCTION_ARGS)
181 {
182         char            arg1 = PG_GETARG_CHAR(0);
183         text       *result = palloc(VARHDRSZ + 1);
184
185         /*
186          * Convert \0 to an empty string, for consistency with charout (and
187          * because the text stuff doesn't like embedded nulls all that well).
188          */
189         if (arg1 != '\0')
190         {
191                 VARATT_SIZEP(result) = VARHDRSZ + 1;
192                 *(VARDATA(result)) = arg1;
193         }
194         else
195                 VARATT_SIZEP(result) = VARHDRSZ;
196
197         PG_RETURN_TEXT_P(result);
198 }
199
200
201 /*****************************************************************************
202  *       USER I/O ROUTINES                                                                                                               *
203  *****************************************************************************/
204
205 /*
206  *              cidin   - converts CommandId to internal representation.
207  */
208 Datum
209 cidin(PG_FUNCTION_ARGS)
210 {
211         char       *s = PG_GETARG_CSTRING(0);
212         CommandId       c;
213
214         c = atoi(s);
215
216         /* XXX assume that CommandId is 32 bits... */
217         PG_RETURN_INT32((int32) c);
218 }
219
220 /*
221  *              cidout  - converts a cid to external representation.
222  */
223 Datum
224 cidout(PG_FUNCTION_ARGS)
225 {
226         /* XXX assume that CommandId is 32 bits... */
227         CommandId       c = PG_GETARG_INT32(0);
228         char       *result = (char *) palloc(16);
229
230         sprintf(result, "%u", (unsigned int) c);
231         PG_RETURN_CSTRING(result);
232 }
233
234 /*****************************************************************************
235  *       PUBLIC ROUTINES                                                                                                                 *
236  *****************************************************************************/
237
238 Datum
239 cideq(PG_FUNCTION_ARGS)
240 {
241         /* XXX assume that CommandId is 32 bits... */
242         CommandId       arg1 = PG_GETARG_INT32(0);
243         CommandId       arg2 = PG_GETARG_INT32(1);
244
245         PG_RETURN_BOOL(arg1 == arg2);
246 }