1 | /*------------------------------------------------------------------------- |
2 | * |
3 | * pseudotypes.c |
4 | * Functions for the system pseudo-types. |
5 | * |
6 | * A pseudo-type isn't really a type and never has any operations, but |
7 | * we do need to supply input and output functions to satisfy the links |
8 | * in the pseudo-type's entry in pg_type. In most cases the functions |
9 | * just throw an error if invoked. (XXX the error messages here cover |
10 | * the most common case, but might be confusing in some contexts. Can |
11 | * we do better?) |
12 | * |
13 | * |
14 | * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group |
15 | * Portions Copyright (c) 1994, Regents of the University of California |
16 | * |
17 | * |
18 | * IDENTIFICATION |
19 | * src/backend/utils/adt/pseudotypes.c |
20 | * |
21 | *------------------------------------------------------------------------- |
22 | */ |
23 | #include "postgres.h" |
24 | |
25 | #include "libpq/pqformat.h" |
26 | #include "utils/array.h" |
27 | #include "utils/builtins.h" |
28 | #include "utils/rangetypes.h" |
29 | |
30 | |
31 | /* |
32 | * cstring_in - input routine for pseudo-type CSTRING. |
33 | * |
34 | * We might as well allow this to support constructs like "foo_in('blah')". |
35 | */ |
36 | Datum |
37 | cstring_in(PG_FUNCTION_ARGS) |
38 | { |
39 | char *str = PG_GETARG_CSTRING(0); |
40 | |
41 | PG_RETURN_CSTRING(pstrdup(str)); |
42 | } |
43 | |
44 | /* |
45 | * cstring_out - output routine for pseudo-type CSTRING. |
46 | * |
47 | * We allow this mainly so that "SELECT some_output_function(...)" does |
48 | * what the user will expect. |
49 | */ |
50 | Datum |
51 | cstring_out(PG_FUNCTION_ARGS) |
52 | { |
53 | char *str = PG_GETARG_CSTRING(0); |
54 | |
55 | PG_RETURN_CSTRING(pstrdup(str)); |
56 | } |
57 | |
58 | /* |
59 | * cstring_recv - binary input routine for pseudo-type CSTRING. |
60 | */ |
61 | Datum |
62 | cstring_recv(PG_FUNCTION_ARGS) |
63 | { |
64 | StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); |
65 | char *str; |
66 | int nbytes; |
67 | |
68 | str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes); |
69 | PG_RETURN_CSTRING(str); |
70 | } |
71 | |
72 | /* |
73 | * cstring_send - binary output routine for pseudo-type CSTRING. |
74 | */ |
75 | Datum |
76 | cstring_send(PG_FUNCTION_ARGS) |
77 | { |
78 | char *str = PG_GETARG_CSTRING(0); |
79 | StringInfoData buf; |
80 | |
81 | pq_begintypsend(&buf); |
82 | pq_sendtext(&buf, str, strlen(str)); |
83 | PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); |
84 | } |
85 | |
86 | /* |
87 | * anyarray_in - input routine for pseudo-type ANYARRAY. |
88 | */ |
89 | Datum |
90 | anyarray_in(PG_FUNCTION_ARGS) |
91 | { |
92 | ereport(ERROR, |
93 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
94 | errmsg("cannot accept a value of type %s" , "anyarray" ))); |
95 | |
96 | PG_RETURN_VOID(); /* keep compiler quiet */ |
97 | } |
98 | |
99 | /* |
100 | * anyarray_out - output routine for pseudo-type ANYARRAY. |
101 | * |
102 | * We may as well allow this, since array_out will in fact work. |
103 | */ |
104 | Datum |
105 | anyarray_out(PG_FUNCTION_ARGS) |
106 | { |
107 | return array_out(fcinfo); |
108 | } |
109 | |
110 | /* |
111 | * anyarray_recv - binary input routine for pseudo-type ANYARRAY. |
112 | * |
113 | * XXX this could actually be made to work, since the incoming array |
114 | * data will contain the element type OID. Need to think through |
115 | * type-safety issues before allowing it, however. |
116 | */ |
117 | Datum |
118 | anyarray_recv(PG_FUNCTION_ARGS) |
119 | { |
120 | ereport(ERROR, |
121 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
122 | errmsg("cannot accept a value of type %s" , "anyarray" ))); |
123 | |
124 | PG_RETURN_VOID(); /* keep compiler quiet */ |
125 | } |
126 | |
127 | /* |
128 | * anyarray_send - binary output routine for pseudo-type ANYARRAY. |
129 | * |
130 | * We may as well allow this, since array_send will in fact work. |
131 | */ |
132 | Datum |
133 | anyarray_send(PG_FUNCTION_ARGS) |
134 | { |
135 | return array_send(fcinfo); |
136 | } |
137 | |
138 | |
139 | /* |
140 | * anyenum_in - input routine for pseudo-type ANYENUM. |
141 | */ |
142 | Datum |
143 | anyenum_in(PG_FUNCTION_ARGS) |
144 | { |
145 | ereport(ERROR, |
146 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
147 | errmsg("cannot accept a value of type %s" , "anyenum" ))); |
148 | |
149 | PG_RETURN_VOID(); /* keep compiler quiet */ |
150 | } |
151 | |
152 | /* |
153 | * anyenum_out - output routine for pseudo-type ANYENUM. |
154 | * |
155 | * We may as well allow this, since enum_out will in fact work. |
156 | */ |
157 | Datum |
158 | anyenum_out(PG_FUNCTION_ARGS) |
159 | { |
160 | return enum_out(fcinfo); |
161 | } |
162 | |
163 | /* |
164 | * anyrange_in - input routine for pseudo-type ANYRANGE. |
165 | */ |
166 | Datum |
167 | anyrange_in(PG_FUNCTION_ARGS) |
168 | { |
169 | ereport(ERROR, |
170 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
171 | errmsg("cannot accept a value of type %s" , "anyrange" ))); |
172 | |
173 | PG_RETURN_VOID(); /* keep compiler quiet */ |
174 | } |
175 | |
176 | /* |
177 | * anyrange_out - output routine for pseudo-type ANYRANGE. |
178 | * |
179 | * We may as well allow this, since range_out will in fact work. |
180 | */ |
181 | Datum |
182 | anyrange_out(PG_FUNCTION_ARGS) |
183 | { |
184 | return range_out(fcinfo); |
185 | } |
186 | |
187 | /* |
188 | * void_in - input routine for pseudo-type VOID. |
189 | * |
190 | * We allow this so that PL functions can return VOID without any special |
191 | * hack in the PL handler. Whatever value the PL thinks it's returning |
192 | * will just be ignored. |
193 | */ |
194 | Datum |
195 | void_in(PG_FUNCTION_ARGS) |
196 | { |
197 | PG_RETURN_VOID(); /* you were expecting something different? */ |
198 | } |
199 | |
200 | /* |
201 | * void_out - output routine for pseudo-type VOID. |
202 | * |
203 | * We allow this so that "SELECT function_returning_void(...)" works. |
204 | */ |
205 | Datum |
206 | void_out(PG_FUNCTION_ARGS) |
207 | { |
208 | PG_RETURN_CSTRING(pstrdup("" )); |
209 | } |
210 | |
211 | /* |
212 | * void_recv - binary input routine for pseudo-type VOID. |
213 | * |
214 | * Note that since we consume no bytes, an attempt to send anything but |
215 | * an empty string will result in an "invalid message format" error. |
216 | */ |
217 | Datum |
218 | void_recv(PG_FUNCTION_ARGS) |
219 | { |
220 | PG_RETURN_VOID(); |
221 | } |
222 | |
223 | /* |
224 | * void_send - binary output routine for pseudo-type VOID. |
225 | * |
226 | * We allow this so that "SELECT function_returning_void(...)" works |
227 | * even when binary output is requested. |
228 | */ |
229 | Datum |
230 | void_send(PG_FUNCTION_ARGS) |
231 | { |
232 | StringInfoData buf; |
233 | |
234 | /* send an empty string */ |
235 | pq_begintypsend(&buf); |
236 | PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); |
237 | } |
238 | |
239 | /* |
240 | * shell_in - input routine for "shell" types (those not yet filled in). |
241 | */ |
242 | Datum |
243 | shell_in(PG_FUNCTION_ARGS) |
244 | { |
245 | ereport(ERROR, |
246 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
247 | errmsg("cannot accept a value of a shell type" ))); |
248 | |
249 | PG_RETURN_VOID(); /* keep compiler quiet */ |
250 | } |
251 | |
252 | /* |
253 | * shell_out - output routine for "shell" types. |
254 | */ |
255 | Datum |
256 | shell_out(PG_FUNCTION_ARGS) |
257 | { |
258 | ereport(ERROR, |
259 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
260 | errmsg("cannot display a value of a shell type" ))); |
261 | |
262 | PG_RETURN_VOID(); /* keep compiler quiet */ |
263 | } |
264 | |
265 | |
266 | /* |
267 | * pg_node_tree_in - input routine for type PG_NODE_TREE. |
268 | * |
269 | * pg_node_tree isn't really a pseudotype --- it's real enough to be a table |
270 | * column --- but it presently has no operations of its own, and disallows |
271 | * input too, so its I/O functions seem to fit here as much as anywhere. |
272 | */ |
273 | Datum |
274 | pg_node_tree_in(PG_FUNCTION_ARGS) |
275 | { |
276 | /* |
277 | * We disallow input of pg_node_tree values because the SQL functions that |
278 | * operate on the type are not secure against malformed input. |
279 | */ |
280 | ereport(ERROR, |
281 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
282 | errmsg("cannot accept a value of type %s" , "pg_node_tree" ))); |
283 | |
284 | PG_RETURN_VOID(); /* keep compiler quiet */ |
285 | } |
286 | |
287 | |
288 | /* |
289 | * pg_node_tree_out - output routine for type PG_NODE_TREE. |
290 | * |
291 | * The internal representation is the same as TEXT, so just pass it off. |
292 | */ |
293 | Datum |
294 | pg_node_tree_out(PG_FUNCTION_ARGS) |
295 | { |
296 | return textout(fcinfo); |
297 | } |
298 | |
299 | /* |
300 | * pg_node_tree_recv - binary input routine for type PG_NODE_TREE. |
301 | */ |
302 | Datum |
303 | pg_node_tree_recv(PG_FUNCTION_ARGS) |
304 | { |
305 | ereport(ERROR, |
306 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
307 | errmsg("cannot accept a value of type %s" , "pg_node_tree" ))); |
308 | |
309 | PG_RETURN_VOID(); /* keep compiler quiet */ |
310 | } |
311 | |
312 | /* |
313 | * pg_node_tree_send - binary output routine for type PG_NODE_TREE. |
314 | */ |
315 | Datum |
316 | pg_node_tree_send(PG_FUNCTION_ARGS) |
317 | { |
318 | return textsend(fcinfo); |
319 | } |
320 | |
321 | /* |
322 | * pg_ddl_command_in - input routine for type PG_DDL_COMMAND. |
323 | * |
324 | * Like pg_node_tree, pg_ddl_command isn't really a pseudotype; it's here for |
325 | * the same reasons as that one. |
326 | */ |
327 | Datum |
328 | pg_ddl_command_in(PG_FUNCTION_ARGS) |
329 | { |
330 | /* |
331 | * Disallow input of pg_ddl_command value. |
332 | */ |
333 | ereport(ERROR, |
334 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
335 | errmsg("cannot accept a value of type %s" , "pg_ddl_command" ))); |
336 | |
337 | PG_RETURN_VOID(); /* keep compiler quiet */ |
338 | } |
339 | |
340 | /* |
341 | * pg_ddl_command_out - output routine for type PG_DDL_COMMAND. |
342 | * |
343 | * We don't have any good way to output this type directly, so punt. |
344 | */ |
345 | Datum |
346 | pg_ddl_command_out(PG_FUNCTION_ARGS) |
347 | { |
348 | ereport(ERROR, |
349 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
350 | errmsg("cannot output a value of type %s" , "pg_ddl_command" ))); |
351 | |
352 | PG_RETURN_VOID(); |
353 | } |
354 | |
355 | /* |
356 | * pg_ddl_command_recv - binary input routine for type PG_DDL_COMMAND. |
357 | */ |
358 | Datum |
359 | pg_ddl_command_recv(PG_FUNCTION_ARGS) |
360 | { |
361 | ereport(ERROR, |
362 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
363 | errmsg("cannot accept a value of type %s" , "pg_ddl_command" ))); |
364 | |
365 | PG_RETURN_VOID(); |
366 | } |
367 | |
368 | /* |
369 | * pg_ddl_command_send - binary output routine for type PG_DDL_COMMAND. |
370 | */ |
371 | Datum |
372 | pg_ddl_command_send(PG_FUNCTION_ARGS) |
373 | { |
374 | ereport(ERROR, |
375 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
376 | errmsg("cannot output a value of type %s" , "pg_ddl_command" ))); |
377 | |
378 | PG_RETURN_VOID(); |
379 | } |
380 | |
381 | |
382 | /* |
383 | * Generate input and output functions for a pseudotype that will reject all |
384 | * input and output attempts. |
385 | */ |
386 | #define PSEUDOTYPE_DUMMY_IO_FUNCS(typname) \ |
387 | \ |
388 | Datum \ |
389 | typname##_in(PG_FUNCTION_ARGS) \ |
390 | { \ |
391 | ereport(ERROR, \ |
392 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), \ |
393 | errmsg("cannot accept a value of type %s", #typname))); \ |
394 | \ |
395 | PG_RETURN_VOID(); /* keep compiler quiet */ \ |
396 | } \ |
397 | \ |
398 | Datum \ |
399 | typname##_out(PG_FUNCTION_ARGS) \ |
400 | { \ |
401 | ereport(ERROR, \ |
402 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), \ |
403 | errmsg("cannot display a value of type %s", #typname))); \ |
404 | \ |
405 | PG_RETURN_VOID(); /* keep compiler quiet */ \ |
406 | } \ |
407 | \ |
408 | extern int no_such_variable |
409 | |
410 | PSEUDOTYPE_DUMMY_IO_FUNCS(any); |
411 | PSEUDOTYPE_DUMMY_IO_FUNCS(trigger); |
412 | PSEUDOTYPE_DUMMY_IO_FUNCS(event_trigger); |
413 | PSEUDOTYPE_DUMMY_IO_FUNCS(language_handler); |
414 | PSEUDOTYPE_DUMMY_IO_FUNCS(fdw_handler); |
415 | PSEUDOTYPE_DUMMY_IO_FUNCS(index_am_handler); |
416 | PSEUDOTYPE_DUMMY_IO_FUNCS(tsm_handler); |
417 | PSEUDOTYPE_DUMMY_IO_FUNCS(internal); |
418 | PSEUDOTYPE_DUMMY_IO_FUNCS(opaque); |
419 | PSEUDOTYPE_DUMMY_IO_FUNCS(anyelement); |
420 | PSEUDOTYPE_DUMMY_IO_FUNCS(anynonarray); |
421 | PSEUDOTYPE_DUMMY_IO_FUNCS(table_am_handler); |
422 | |