Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * char.c
4 : * Functions for the built-in type "char" (not to be confused with
5 : * bpchar, which is the SQL CHAR(n) type).
6 : *
7 : * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
8 : * Portions Copyright (c) 1994, Regents of the University of California
9 : *
10 : *
11 : * IDENTIFICATION
12 : * src/backend/utils/adt/char.c
13 : *
14 : *-------------------------------------------------------------------------
15 : */
16 : #include "postgres.h"
17 :
18 : #include <limits.h>
19 :
20 : #include "libpq/pqformat.h"
21 : #include "utils/builtins.h"
22 :
23 : /*****************************************************************************
24 : * USER I/O ROUTINES *
25 : *****************************************************************************/
26 :
27 : /*
28 : * charin - converts "x" to 'x'
29 : *
30 : * Note that an empty input string will implicitly be converted to \0.
31 : */
32 : Datum
33 11396 : charin(PG_FUNCTION_ARGS)
34 : {
35 11396 : char *ch = PG_GETARG_CSTRING(0);
36 :
37 11396 : PG_RETURN_CHAR(ch[0]);
38 : }
39 :
40 : /*
41 : * charout - converts 'x' to "x"
42 : *
43 : * Note that if the char value is \0, the resulting string will appear
44 : * to be empty (null-terminated after zero characters). So this is the
45 : * inverse of the charin() function for such data.
46 : */
47 : Datum
48 2029 : charout(PG_FUNCTION_ARGS)
49 : {
50 2029 : char ch = PG_GETARG_CHAR(0);
51 2029 : char *result = (char *) palloc(2);
52 :
53 2029 : result[0] = ch;
54 2029 : result[1] = '\0';
55 2029 : PG_RETURN_CSTRING(result);
56 : }
57 :
58 : /*
59 : * charrecv - converts external binary format to char
60 : *
61 : * The external representation is one byte, with no character set
62 : * conversion. This is somewhat dubious, perhaps, but in many
63 : * cases people use char for a 1-byte binary type.
64 : */
65 : Datum
66 0 : charrecv(PG_FUNCTION_ARGS)
67 : {
68 0 : StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
69 :
70 0 : PG_RETURN_CHAR(pq_getmsgbyte(buf));
71 : }
72 :
73 : /*
74 : * charsend - converts char to binary format
75 : */
76 : Datum
77 0 : charsend(PG_FUNCTION_ARGS)
78 : {
79 0 : char arg1 = PG_GETARG_CHAR(0);
80 : StringInfoData buf;
81 :
82 0 : pq_begintypsend(&buf);
83 0 : pq_sendbyte(&buf, arg1);
84 0 : PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
85 : }
86 :
87 : /*****************************************************************************
88 : * PUBLIC ROUTINES *
89 : *****************************************************************************/
90 :
91 : /*
92 : * NOTE: comparisons are done as though char is unsigned (uint8).
93 : * Conversions to and from integer are done as though char is signed (int8).
94 : *
95 : * You wanted consistency?
96 : */
97 :
98 : Datum
99 187547 : chareq(PG_FUNCTION_ARGS)
100 : {
101 187547 : char arg1 = PG_GETARG_CHAR(0);
102 187547 : char arg2 = PG_GETARG_CHAR(1);
103 :
104 187547 : PG_RETURN_BOOL(arg1 == arg2);
105 : }
106 :
107 : Datum
108 120918 : charne(PG_FUNCTION_ARGS)
109 : {
110 120918 : char arg1 = PG_GETARG_CHAR(0);
111 120918 : char arg2 = PG_GETARG_CHAR(1);
112 :
113 120918 : PG_RETURN_BOOL(arg1 != arg2);
114 : }
115 :
116 : Datum
117 516 : charlt(PG_FUNCTION_ARGS)
118 : {
119 516 : char arg1 = PG_GETARG_CHAR(0);
120 516 : char arg2 = PG_GETARG_CHAR(1);
121 :
122 516 : PG_RETURN_BOOL((uint8) arg1 < (uint8) arg2);
123 : }
124 :
125 : Datum
126 404 : charle(PG_FUNCTION_ARGS)
127 : {
128 404 : char arg1 = PG_GETARG_CHAR(0);
129 404 : char arg2 = PG_GETARG_CHAR(1);
130 :
131 404 : PG_RETURN_BOOL((uint8) arg1 <= (uint8) arg2);
132 : }
133 :
134 : Datum
135 507 : chargt(PG_FUNCTION_ARGS)
136 : {
137 507 : char arg1 = PG_GETARG_CHAR(0);
138 507 : char arg2 = PG_GETARG_CHAR(1);
139 :
140 507 : PG_RETURN_BOOL((uint8) arg1 > (uint8) arg2);
141 : }
142 :
143 : Datum
144 355 : charge(PG_FUNCTION_ARGS)
145 : {
146 355 : char arg1 = PG_GETARG_CHAR(0);
147 355 : char arg2 = PG_GETARG_CHAR(1);
148 :
149 355 : PG_RETURN_BOOL((uint8) arg1 >= (uint8) arg2);
150 : }
151 :
152 :
153 : Datum
154 0 : chartoi4(PG_FUNCTION_ARGS)
155 : {
156 0 : char arg1 = PG_GETARG_CHAR(0);
157 :
158 0 : PG_RETURN_INT32((int32) ((int8) arg1));
159 : }
160 :
161 : Datum
162 0 : i4tochar(PG_FUNCTION_ARGS)
163 : {
164 0 : int32 arg1 = PG_GETARG_INT32(0);
165 :
166 0 : if (arg1 < SCHAR_MIN || arg1 > SCHAR_MAX)
167 0 : ereport(ERROR,
168 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
169 : errmsg("\"char\" out of range")));
170 :
171 0 : PG_RETURN_CHAR((int8) arg1);
172 : }
173 :
174 :
175 : Datum
176 221 : text_char(PG_FUNCTION_ARGS)
177 : {
178 221 : text *arg1 = PG_GETARG_TEXT_PP(0);
179 : char result;
180 :
181 : /*
182 : * An empty input string is converted to \0 (for consistency with charin).
183 : * If the input is longer than one character, the excess data is silently
184 : * discarded.
185 : */
186 221 : if (VARSIZE_ANY_EXHDR(arg1) > 0)
187 221 : result = *(VARDATA_ANY(arg1));
188 : else
189 0 : result = '\0';
190 :
191 221 : PG_RETURN_CHAR(result);
192 : }
193 :
194 : Datum
195 0 : char_text(PG_FUNCTION_ARGS)
196 : {
197 0 : char arg1 = PG_GETARG_CHAR(0);
198 0 : text *result = palloc(VARHDRSZ + 1);
199 :
200 : /*
201 : * Convert \0 to an empty string, for consistency with charout (and
202 : * because the text stuff doesn't like embedded nulls all that well).
203 : */
204 0 : if (arg1 != '\0')
205 : {
206 0 : SET_VARSIZE(result, VARHDRSZ + 1);
207 0 : *(VARDATA(result)) = arg1;
208 : }
209 : else
210 0 : SET_VARSIZE(result, VARHDRSZ);
211 :
212 0 : PG_RETURN_TEXT_P(result);
213 : }
|