TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * parse_type.c
4 : * handle type operations for parser
5 : *
6 : * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : *
10 : * IDENTIFICATION
11 : * src/backend/parser/parse_type.c
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 : #include "postgres.h"
16 :
17 : #include "access/htup_details.h"
18 : #include "catalog/namespace.h"
19 : #include "catalog/pg_type.h"
20 : #include "lib/stringinfo.h"
21 : #include "nodes/makefuncs.h"
22 : #include "parser/parse_type.h"
23 : #include "parser/parser.h"
24 : #include "utils/array.h"
25 : #include "utils/builtins.h"
26 : #include "utils/lsyscache.h"
27 : #include "utils/syscache.h"
28 :
29 : static int32 typenameTypeMod(ParseState *pstate, const TypeName *typeName,
30 : Type typ);
31 :
32 :
33 : /*
34 : * LookupTypeName
35 : * Wrapper for typical case.
36 : */
37 : Type
38 CBC 1002657 : LookupTypeName(ParseState *pstate, const TypeName *typeName,
39 : int32 *typmod_p, bool missing_ok)
40 : {
41 1002657 : return LookupTypeNameExtended(pstate,
42 : typeName, typmod_p, true, missing_ok);
43 : }
44 :
45 : /*
46 : * LookupTypeNameExtended
47 : * Given a TypeName object, lookup the pg_type syscache entry of the type.
48 : * Returns NULL if no such type can be found. If the type is found,
49 : * the typmod value represented in the TypeName struct is computed and
50 : * stored into *typmod_p.
51 : *
52 : * NB: on success, the caller must ReleaseSysCache the type tuple when done
53 : * with it.
54 : *
55 : * NB: direct callers of this function MUST check typisdefined before assuming
56 : * that the type is fully valid. Most code should go through typenameType
57 : * or typenameTypeId instead.
58 : *
59 : * typmod_p can be passed as NULL if the caller does not care to know the
60 : * typmod value, but the typmod decoration (if any) will be validated anyway,
61 : * except in the case where the type is not found. Note that if the type is
62 : * found but is a shell, and there is typmod decoration, an error will be
63 : * thrown --- this is intentional.
64 : *
65 : * If temp_ok is false, ignore types in the temporary namespace. Pass false
66 : * when the caller will decide, using goodness of fit criteria, whether the
67 : * typeName is actually a type or something else. If typeName always denotes
68 : * a type (or denotes nothing), pass true.
69 : *
70 : * pstate is only used for error location info, and may be NULL.
71 : */
72 : Type
73 1042170 : LookupTypeNameExtended(ParseState *pstate,
74 : const TypeName *typeName, int32 *typmod_p,
75 : bool temp_ok, bool missing_ok)
76 : {
77 : Oid typoid;
78 : HeapTuple tup;
79 : int32 typmod;
80 :
81 1042170 : if (typeName->names == NIL)
82 : {
83 : /* We have the OID already if it's an internally generated TypeName */
84 454328 : typoid = typeName->typeOid;
85 : }
86 587842 : else if (typeName->pct_type)
87 : {
88 : /* Handle %TYPE reference to type of an existing field */
89 12 : RangeVar *rel = makeRangeVar(NULL, NULL, typeName->location);
90 12 : char *field = NULL;
91 : Oid relid;
92 : AttrNumber attnum;
93 :
94 : /* deconstruct the name list */
95 12 : switch (list_length(typeName->names))
96 : {
97 UBC 0 : case 1:
98 0 : ereport(ERROR,
99 : (errcode(ERRCODE_SYNTAX_ERROR),
100 : errmsg("improper %%TYPE reference (too few dotted names): %s",
101 : NameListToString(typeName->names)),
102 : parser_errposition(pstate, typeName->location)));
103 : break;
104 CBC 12 : case 2:
105 12 : rel->relname = strVal(linitial(typeName->names));
106 12 : field = strVal(lsecond(typeName->names));
107 12 : break;
108 UBC 0 : case 3:
109 0 : rel->schemaname = strVal(linitial(typeName->names));
110 0 : rel->relname = strVal(lsecond(typeName->names));
111 0 : field = strVal(lthird(typeName->names));
112 0 : break;
113 0 : case 4:
114 0 : rel->catalogname = strVal(linitial(typeName->names));
115 0 : rel->schemaname = strVal(lsecond(typeName->names));
116 0 : rel->relname = strVal(lthird(typeName->names));
117 0 : field = strVal(lfourth(typeName->names));
118 0 : break;
119 0 : default:
120 0 : ereport(ERROR,
121 : (errcode(ERRCODE_SYNTAX_ERROR),
122 : errmsg("improper %%TYPE reference (too many dotted names): %s",
123 : NameListToString(typeName->names)),
124 : parser_errposition(pstate, typeName->location)));
125 : break;
126 : }
127 :
128 : /*
129 : * Look up the field.
130 : *
131 : * XXX: As no lock is taken here, this might fail in the presence of
132 : * concurrent DDL. But taking a lock would carry a performance
133 : * penalty and would also require a permissions check.
134 : */
135 CBC 12 : relid = RangeVarGetRelid(rel, NoLock, missing_ok);
136 12 : attnum = get_attnum(relid, field);
137 12 : if (attnum == InvalidAttrNumber)
138 : {
139 UBC 0 : if (missing_ok)
140 0 : typoid = InvalidOid;
141 : else
142 0 : ereport(ERROR,
143 : (errcode(ERRCODE_UNDEFINED_COLUMN),
144 : errmsg("column \"%s\" of relation \"%s\" does not exist",
145 : field, rel->relname),
146 : parser_errposition(pstate, typeName->location)));
147 : }
148 : else
149 : {
150 CBC 12 : typoid = get_atttype(relid, attnum);
151 :
152 : /* this construct should never have an array indicator */
153 12 : Assert(typeName->arrayBounds == NIL);
154 :
155 : /* emit nuisance notice (intentionally not errposition'd) */
156 12 : ereport(NOTICE,
157 : (errmsg("type reference %s converted to %s",
158 : TypeNameToString(typeName),
159 : format_type_be(typoid))));
160 : }
161 : }
162 : else
163 : {
164 : /* Normal reference to a type name */
165 : char *schemaname;
166 : char *typname;
167 :
168 : /* deconstruct the name list */
169 587830 : DeconstructQualifiedName(typeName->names, &schemaname, &typname);
170 :
171 587824 : if (schemaname)
172 : {
173 : /* Look in specific schema only */
174 : Oid namespaceId;
175 : ParseCallbackState pcbstate;
176 :
177 137075 : setup_parser_errposition_callback(&pcbstate, pstate, typeName->location);
178 :
179 137075 : namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
180 137072 : if (OidIsValid(namespaceId))
181 137024 : typoid = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid,
182 : PointerGetDatum(typname),
183 : ObjectIdGetDatum(namespaceId));
184 : else
185 48 : typoid = InvalidOid;
186 :
187 137072 : cancel_parser_errposition_callback(&pcbstate);
188 : }
189 : else
190 : {
191 : /* Unqualified type name, so search the search path */
192 450749 : typoid = TypenameGetTypidExtended(typname, temp_ok);
193 : }
194 :
195 : /* If an array reference, return the array type instead */
196 587821 : if (typeName->arrayBounds != NIL)
197 10055 : typoid = get_array_type(typoid);
198 : }
199 :
200 1042161 : if (!OidIsValid(typoid))
201 : {
202 39388 : if (typmod_p)
203 19 : *typmod_p = -1;
204 39388 : return NULL;
205 : }
206 :
207 1002773 : tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typoid));
208 1002773 : if (!HeapTupleIsValid(tup)) /* should not happen */
209 UBC 0 : elog(ERROR, "cache lookup failed for type %u", typoid);
210 :
211 CBC 1002773 : typmod = typenameTypeMod(pstate, typeName, (Type) tup);
212 :
213 1002767 : if (typmod_p)
214 809052 : *typmod_p = typmod;
215 :
216 1002767 : return (Type) tup;
217 : }
218 :
219 : /*
220 : * LookupTypeNameOid
221 : * Given a TypeName object, lookup the pg_type syscache entry of the type.
222 : * Returns InvalidOid if no such type can be found. If the type is found,
223 : * return its Oid.
224 : *
225 : * NB: direct callers of this function need to be aware that the type OID
226 : * returned may correspond to a shell type. Most code should go through
227 : * typenameTypeId instead.
228 : *
229 : * pstate is only used for error location info, and may be NULL.
230 : */
231 : Oid
232 26815 : LookupTypeNameOid(ParseState *pstate, const TypeName *typeName, bool missing_ok)
233 : {
234 : Oid typoid;
235 : Type tup;
236 :
237 26815 : tup = LookupTypeName(pstate, typeName, NULL, missing_ok);
238 26815 : if (tup == NULL)
239 : {
240 90 : if (!missing_ok)
241 16 : ereport(ERROR,
242 : (errcode(ERRCODE_UNDEFINED_OBJECT),
243 : errmsg("type \"%s\" does not exist",
244 : TypeNameToString(typeName)),
245 : parser_errposition(pstate, typeName->location)));
246 :
247 74 : return InvalidOid;
248 : }
249 :
250 26725 : typoid = ((Form_pg_type) GETSTRUCT(tup))->oid;
251 26725 : ReleaseSysCache(tup);
252 :
253 26725 : return typoid;
254 : }
255 :
256 : /*
257 : * typenameType - given a TypeName, return a Type structure and typmod
258 : *
259 : * This is equivalent to LookupTypeName, except that this will report
260 : * a suitable error message if the type cannot be found or is not defined.
261 : * Callers of this can therefore assume the result is a fully valid type.
262 : */
263 : Type
264 847159 : typenameType(ParseState *pstate, const TypeName *typeName, int32 *typmod_p)
265 : {
266 : Type tup;
267 :
268 847159 : tup = LookupTypeName(pstate, typeName, typmod_p, false);
269 847156 : if (tup == NULL)
270 16 : ereport(ERROR,
271 : (errcode(ERRCODE_UNDEFINED_OBJECT),
272 : errmsg("type \"%s\" does not exist",
273 : TypeNameToString(typeName)),
274 : parser_errposition(pstate, typeName->location)));
275 847140 : if (!((Form_pg_type) GETSTRUCT(tup))->typisdefined)
276 3 : ereport(ERROR,
277 : (errcode(ERRCODE_UNDEFINED_OBJECT),
278 : errmsg("type \"%s\" is only a shell",
279 : TypeNameToString(typeName)),
280 : parser_errposition(pstate, typeName->location)));
281 847137 : return tup;
282 : }
283 :
284 : /*
285 : * typenameTypeId - given a TypeName, return the type's OID
286 : *
287 : * This is similar to typenameType, but we only hand back the type OID
288 : * not the syscache entry.
289 : */
290 : Oid
291 4801 : typenameTypeId(ParseState *pstate, const TypeName *typeName)
292 : {
293 : Oid typoid;
294 : Type tup;
295 :
296 4801 : tup = typenameType(pstate, typeName, NULL);
297 4794 : typoid = ((Form_pg_type) GETSTRUCT(tup))->oid;
298 4794 : ReleaseSysCache(tup);
299 :
300 4794 : return typoid;
301 : }
302 :
303 : /*
304 : * typenameTypeIdAndMod - given a TypeName, return the type's OID and typmod
305 : *
306 : * This is equivalent to typenameType, but we only hand back the type OID
307 : * and typmod, not the syscache entry.
308 : */
309 : void
310 804028 : typenameTypeIdAndMod(ParseState *pstate, const TypeName *typeName,
311 : Oid *typeid_p, int32 *typmod_p)
312 : {
313 : Type tup;
314 :
315 804028 : tup = typenameType(pstate, typeName, typmod_p);
316 804026 : *typeid_p = ((Form_pg_type) GETSTRUCT(tup))->oid;
317 804026 : ReleaseSysCache(tup);
318 804026 : }
319 :
320 : /*
321 : * typenameTypeMod - given a TypeName, return the internal typmod value
322 : *
323 : * This will throw an error if the TypeName includes type modifiers that are
324 : * illegal for the data type.
325 : *
326 : * The actual type OID represented by the TypeName must already have been
327 : * looked up, and is passed as "typ".
328 : *
329 : * pstate is only used for error location info, and may be NULL.
330 : */
331 : static int32
332 1002773 : typenameTypeMod(ParseState *pstate, const TypeName *typeName, Type typ)
333 : {
334 : int32 result;
335 : Oid typmodin;
336 : Datum *datums;
337 : int n;
338 : ListCell *l;
339 : ArrayType *arrtypmod;
340 : ParseCallbackState pcbstate;
341 :
342 : /* Return prespecified typmod if no typmod expressions */
343 1002773 : if (typeName->typmods == NIL)
344 998395 : return typeName->typemod;
345 :
346 : /*
347 : * Else, type had better accept typmods. We give a special error message
348 : * for the shell-type case, since a shell couldn't possibly have a
349 : * typmodin function.
350 : */
351 4378 : if (!((Form_pg_type) GETSTRUCT(typ))->typisdefined)
352 UBC 0 : ereport(ERROR,
353 : (errcode(ERRCODE_SYNTAX_ERROR),
354 : errmsg("type modifier cannot be specified for shell type \"%s\"",
355 : TypeNameToString(typeName)),
356 : parser_errposition(pstate, typeName->location)));
357 :
358 CBC 4378 : typmodin = ((Form_pg_type) GETSTRUCT(typ))->typmodin;
359 :
360 4378 : if (typmodin == InvalidOid)
361 UBC 0 : ereport(ERROR,
362 : (errcode(ERRCODE_SYNTAX_ERROR),
363 : errmsg("type modifier is not allowed for type \"%s\"",
364 : TypeNameToString(typeName)),
365 : parser_errposition(pstate, typeName->location)));
366 :
367 : /*
368 : * Convert the list of raw-grammar-output expressions to a cstring array.
369 : * Currently, we allow simple numeric constants, string literals, and
370 : * identifiers; possibly this list could be extended.
371 : */
372 CBC 4378 : datums = (Datum *) palloc(list_length(typeName->typmods) * sizeof(Datum));
373 4378 : n = 0;
374 9713 : foreach(l, typeName->typmods)
375 : {
376 5335 : Node *tm = (Node *) lfirst(l);
377 5335 : char *cstr = NULL;
378 :
379 5335 : if (IsA(tm, A_Const))
380 : {
381 5335 : A_Const *ac = (A_Const *) tm;
382 :
383 5335 : if (IsA(&ac->val, Integer))
384 : {
385 5335 : cstr = psprintf("%ld", (long) intVal(&ac->val));
386 : }
387 UBC 0 : else if (IsA(&ac->val, Float))
388 : {
389 : /* we can just use the string representation directly. */
390 0 : cstr = ac->val.fval.fval;
391 : }
392 0 : else if (IsA(&ac->val, String))
393 : {
394 : /* we can just use the string representation directly. */
395 0 : cstr = strVal(&ac->val);
396 : }
397 : }
398 0 : else if (IsA(tm, ColumnRef))
399 : {
400 0 : ColumnRef *cr = (ColumnRef *) tm;
401 :
402 0 : if (list_length(cr->fields) == 1 &&
403 0 : IsA(linitial(cr->fields), String))
404 0 : cstr = strVal(linitial(cr->fields));
405 : }
406 CBC 5335 : if (!cstr)
407 UBC 0 : ereport(ERROR,
408 : (errcode(ERRCODE_SYNTAX_ERROR),
409 : errmsg("type modifiers must be simple constants or identifiers"),
410 : parser_errposition(pstate, typeName->location)));
411 CBC 5335 : datums[n++] = CStringGetDatum(cstr);
412 : }
413 :
414 GNC 4378 : arrtypmod = construct_array_builtin(datums, n, CSTRINGOID);
415 ECB :
416 : /* arrange to report location if type's typmodin function fails */
417 CBC 4378 : setup_parser_errposition_callback(&pcbstate, pstate, typeName->location);
418 :
419 GIC 4378 : result = DatumGetInt32(OidFunctionCall1(typmodin,
420 ECB : PointerGetDatum(arrtypmod)));
421 :
422 CBC 4372 : cancel_parser_errposition_callback(&pcbstate);
423 ECB :
424 GIC 4372 : pfree(datums);
425 CBC 4372 : pfree(arrtypmod);
426 :
427 GIC 4372 : return result;
428 : }
429 :
430 : /*
431 : * appendTypeNameToBuffer
432 : * Append a string representing the name of a TypeName to a StringInfo.
433 : * This is the shared guts of TypeNameToString and TypeNameListToString.
434 : *
435 : * NB: this must work on TypeNames that do not describe any actual type;
436 : * it is mostly used for reporting lookup errors.
437 ECB : */
438 : static void
439 CBC 14113 : appendTypeNameToBuffer(const TypeName *typeName, StringInfo string)
440 : {
441 GIC 14113 : if (typeName->names != NIL)
442 : {
443 : /* Emit possibly-qualified name as-is */
444 ECB : ListCell *l;
445 :
446 CBC 28328 : foreach(l, typeName->names)
447 ECB : {
448 CBC 14215 : if (l != list_head(typeName->names))
449 GIC 102 : appendStringInfoChar(string, '.');
450 14215 : appendStringInfoString(string, strVal(lfirst(l)));
451 : }
452 : }
453 : else
454 EUB : {
455 : /* Look up internally-specified type */
456 UIC 0 : appendStringInfoString(string, format_type_be(typeName->typeOid));
457 : }
458 :
459 : /*
460 : * Add decoration as needed, but only for fields considered by
461 ECB : * LookupTypeName
462 : */
463 GIC 14113 : if (typeName->pct_type)
464 CBC 12 : appendStringInfoString(string, "%TYPE");
465 ECB :
466 CBC 14113 : if (typeName->arrayBounds != NIL)
467 GIC 3 : appendStringInfoString(string, "[]");
468 14113 : }
469 :
470 : /*
471 : * TypeNameToString
472 : * Produce a string representing the name of a TypeName.
473 : *
474 : * NB: this must work on TypeNames that do not describe any actual type;
475 : * it is mostly used for reporting lookup errors.
476 ECB : */
477 : char *
478 GIC 14101 : TypeNameToString(const TypeName *typeName)
479 : {
480 ECB : StringInfoData string;
481 :
482 CBC 14101 : initStringInfo(&string);
483 GIC 14101 : appendTypeNameToBuffer(typeName, &string);
484 14101 : return string.data;
485 : }
486 :
487 : /*
488 : * TypeNameListToString
489 : * Produce a string representing the name(s) of a List of TypeNames
490 ECB : */
491 : char *
492 GIC 20 : TypeNameListToString(List *typenames)
493 : {
494 : StringInfoData string;
495 ECB : ListCell *l;
496 :
497 GIC 20 : initStringInfo(&string);
498 CBC 32 : foreach(l, typenames)
499 : {
500 12 : TypeName *typeName = lfirst_node(TypeName, l);
501 ECB :
502 CBC 12 : if (l != list_head(typenames))
503 GIC 6 : appendStringInfoChar(&string, ',');
504 CBC 12 : appendTypeNameToBuffer(typeName, &string);
505 : }
506 GIC 20 : return string.data;
507 : }
508 :
509 : /*
510 : * LookupCollation
511 : *
512 : * Look up collation by name, return OID, with support for error location.
513 ECB : */
514 : Oid
515 GIC 4115 : LookupCollation(ParseState *pstate, List *collnames, int location)
516 : {
517 : Oid colloid;
518 ECB : ParseCallbackState pcbstate;
519 :
520 GIC 4115 : if (pstate)
521 CBC 3889 : setup_parser_errposition_callback(&pcbstate, pstate, location);
522 :
523 4115 : colloid = get_collation_oid(collnames, false);
524 ECB :
525 GIC 4103 : if (pstate)
526 CBC 3877 : cancel_parser_errposition_callback(&pcbstate);
527 :
528 GIC 4103 : return colloid;
529 : }
530 :
531 : /*
532 : * GetColumnDefCollation
533 : *
534 : * Get the collation to be used for a column being defined, given the
535 : * ColumnDef node and the previously-determined column type OID.
536 : *
537 : * pstate is only used for error location purposes, and can be NULL.
538 ECB : */
539 : Oid
540 GIC 490390 : GetColumnDefCollation(ParseState *pstate, ColumnDef *coldef, Oid typeOid)
541 ECB : {
542 : Oid result;
543 GIC 490390 : Oid typcollation = get_typcollation(typeOid);
544 CBC 490390 : int location = coldef->location;
545 :
546 GIC 490390 : if (coldef->collClause)
547 ECB : {
548 : /* We have a raw COLLATE clause, so look up the collation */
549 GIC 226 : location = coldef->collClause->location;
550 226 : result = LookupCollation(pstate, coldef->collClause->collname,
551 ECB : location);
552 : }
553 GIC 490164 : else if (OidIsValid(coldef->collOid))
554 ECB : {
555 : /* Precooked collation spec, use that */
556 GIC 255139 : result = coldef->collOid;
557 : }
558 : else
559 ECB : {
560 : /* Use the type's default collation if any */
561 GIC 235025 : result = typcollation;
562 : }
563 ECB :
564 EUB : /* Complain if COLLATE is applied to an uncollatable type */
565 GIC 490390 : if (OidIsValid(result) && !OidIsValid(typcollation))
566 UIC 0 : ereport(ERROR,
567 : (errcode(ERRCODE_DATATYPE_MISMATCH),
568 : errmsg("collations are not supported by type %s",
569 : format_type_be(typeOid)),
570 ECB : parser_errposition(pstate, location)));
571 :
572 GIC 490390 : return result;
573 : }
574 :
575 : /* return a Type structure, given a type id */
576 ECB : /* NB: caller must ReleaseSysCache the type tuple when done with it */
577 : Type
578 GIC 622937 : typeidType(Oid id)
579 : {
580 ECB : HeapTuple tup;
581 :
582 GBC 622937 : tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(id));
583 CBC 622937 : if (!HeapTupleIsValid(tup))
584 UIC 0 : elog(ERROR, "cache lookup failed for type %u", id);
585 GIC 622937 : return (Type) tup;
586 : }
587 :
588 ECB : /* given type (as type struct), return the type OID */
589 : Oid
590 CBC 127364 : typeTypeId(Type tp)
591 EUB : {
592 CBC 127364 : if (tp == NULL) /* probably useless */
593 UIC 0 : elog(ERROR, "typeTypeId() called with NULL type struct");
594 GIC 127364 : return ((Form_pg_type) GETSTRUCT(tp))->oid;
595 : }
596 :
597 ECB : /* given type (as type struct), return the length of type */
598 : int16
599 GIC 596911 : typeLen(Type t)
600 : {
601 ECB : Form_pg_type typ;
602 :
603 GIC 596911 : typ = (Form_pg_type) GETSTRUCT(t);
604 596911 : return typ->typlen;
605 : }
606 :
607 ECB : /* given type (as type struct), return its 'byval' attribute */
608 : bool
609 GIC 596911 : typeByVal(Type t)
610 : {
611 ECB : Form_pg_type typ;
612 :
613 GIC 596911 : typ = (Form_pg_type) GETSTRUCT(t);
614 596911 : return typ->typbyval;
615 : }
616 :
617 EUB : /* given type (as type struct), return the type's name */
618 : char *
619 UIC 0 : typeTypeName(Type t)
620 : {
621 EUB : Form_pg_type typ;
622 :
623 UBC 0 : typ = (Form_pg_type) GETSTRUCT(t);
624 : /* pstrdup here because result may need to outlive the syscache entry */
625 UIC 0 : return pstrdup(NameStr(typ->typname));
626 : }
627 :
628 ECB : /* given type (as type struct), return its 'typrelid' attribute */
629 : Oid
630 GIC 336 : typeTypeRelid(Type typ)
631 : {
632 ECB : Form_pg_type typtup;
633 :
634 GIC 336 : typtup = (Form_pg_type) GETSTRUCT(typ);
635 336 : return typtup->typrelid;
636 : }
637 :
638 ECB : /* given type (as type struct), return its 'typcollation' attribute */
639 : Oid
640 GIC 596911 : typeTypeCollation(Type typ)
641 : {
642 ECB : Form_pg_type typtup;
643 :
644 GIC 596911 : typtup = (Form_pg_type) GETSTRUCT(typ);
645 596911 : return typtup->typcollation;
646 : }
647 :
648 : /*
649 : * Given a type structure and a string, returns the internal representation
650 : * of that string. The "string" can be NULL to perform conversion of a NULL
651 : * (which might result in failure, if the input function rejects NULLs).
652 ECB : */
653 : Datum
654 CBC 596911 : stringTypeDatum(Type tp, char *string, int32 atttypmod)
655 ECB : {
656 CBC 596911 : Form_pg_type typform = (Form_pg_type) GETSTRUCT(tp);
657 GIC 596911 : Oid typinput = typform->typinput;
658 CBC 596911 : Oid typioparam = getTypeIOParam(tp);
659 :
660 GIC 596911 : return OidInputFunctionCall(typinput, string, typioparam, atttypmod);
661 : }
662 :
663 : /*
664 : * Given a typeid, return the type's typrelid (associated relation), if any.
665 : * Returns InvalidOid if type is not a composite type.
666 ECB : */
667 : Oid
668 GIC 6369 : typeidTypeRelid(Oid type_id)
669 : {
670 : HeapTuple typeTuple;
671 : Form_pg_type type;
672 ECB : Oid result;
673 :
674 GBC 6369 : typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_id));
675 CBC 6369 : if (!HeapTupleIsValid(typeTuple))
676 LBC 0 : elog(ERROR, "cache lookup failed for type %u", type_id);
677 CBC 6369 : type = (Form_pg_type) GETSTRUCT(typeTuple);
678 6369 : result = type->typrelid;
679 GIC 6369 : ReleaseSysCache(typeTuple);
680 6369 : return result;
681 : }
682 :
683 : /*
684 : * Given a typeid, return the type's typrelid (associated relation), if any.
685 : * Returns InvalidOid if type is not a composite type or a domain over one.
686 : * This is the same as typeidTypeRelid(getBaseType(type_id)), but faster.
687 ECB : */
688 : Oid
689 GIC 1387112 : typeOrDomainTypeRelid(Oid type_id)
690 : {
691 : HeapTuple typeTuple;
692 : Form_pg_type type;
693 : Oid result;
694 :
695 ECB : for (;;)
696 : {
697 GBC 1554136 : typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_id));
698 CBC 1554136 : if (!HeapTupleIsValid(typeTuple))
699 LBC 0 : elog(ERROR, "cache lookup failed for type %u", type_id);
700 GIC 1554136 : type = (Form_pg_type) GETSTRUCT(typeTuple);
701 1554136 : if (type->typtype != TYPTYPE_DOMAIN)
702 ECB : {
703 : /* Not a domain, so done looking through domains */
704 GIC 1387112 : break;
705 ECB : }
706 : /* It is a domain, so examine the base type instead */
707 GIC 167024 : type_id = type->typbasetype;
708 CBC 167024 : ReleaseSysCache(typeTuple);
709 ECB : }
710 CBC 1387112 : result = type->typrelid;
711 GIC 1387112 : ReleaseSysCache(typeTuple);
712 1387112 : return result;
713 : }
714 :
715 : /*
716 : * error context callback for parse failure during parseTypeString()
717 ECB : */
718 : static void
719 CBC 3 : pts_error_callback(void *arg)
720 : {
721 3 : const char *str = (const char *) arg;
722 ECB :
723 GIC 3 : errcontext("invalid type name \"%s\"", str);
724 3 : }
725 :
726 : /*
727 : * Given a string that is supposed to be a SQL-compatible type declaration,
728 : * such as "int4" or "integer" or "character varying(32)", parse
729 : * the string and return the result as a TypeName.
730 : *
731 : * If the string cannot be parsed as a type, an error is raised,
732 : * unless escontext is an ErrorSaveContext node, in which case we may
733 : * fill that and return NULL. But note that the ErrorSaveContext option
734 : * is mostly aspirational at present: errors detected by the main
735 : * grammar, rather than here, will still be thrown.
736 : */
737 : TypeName *
738 GNC 4552 : typeStringToTypeName(const char *str, Node *escontext)
739 : {
740 : List *raw_parsetree_list;
741 ECB : TypeName *typeName;
742 : ErrorContextCallback ptserrcontext;
743 :
744 : /* make sure we give useful error for empty input */
745 GIC 4552 : if (strspn(str, " \t\n\r\f") == strlen(str))
746 UIC 0 : goto fail;
747 :
748 ECB : /*
749 EUB : * Setup error traceback support in case of ereport() during parse
750 : */
751 GIC 4552 : ptserrcontext.callback = pts_error_callback;
752 4552 : ptserrcontext.arg = unconstify(char *, str);
753 4552 : ptserrcontext.previous = error_context_stack;
754 CBC 4552 : error_context_stack = &ptserrcontext;
755 ECB :
756 CBC 4552 : raw_parsetree_list = raw_parser(str, RAW_PARSE_TYPE_NAME);
757 ECB :
758 GIC 4549 : error_context_stack = ptserrcontext.previous;
759 ECB :
760 : /* We should get back exactly one TypeName node. */
761 CBC 4549 : Assert(list_length(raw_parsetree_list) == 1);
762 GIC 4549 : typeName = linitial_node(TypeName, raw_parsetree_list);
763 :
764 ECB : /* The grammar allows SETOF in TypeName, but we don't want that here. */
765 CBC 4549 : if (typeName->setof)
766 UIC 0 : goto fail;
767 :
768 CBC 4549 : return typeName;
769 EUB :
770 UIC 0 : fail:
771 UNC 0 : ereturn(escontext, NULL,
772 : (errcode(ERRCODE_SYNTAX_ERROR),
773 EUB : errmsg("invalid type name \"%s\"", str)));
774 : }
775 :
776 : /*
777 : * Given a string that is supposed to be a SQL-compatible type declaration,
778 : * such as "int4" or "integer" or "character varying(32)", parse
779 : * the string and convert it to a type OID and type modifier.
780 : *
781 : * If escontext is an ErrorSaveContext node, then errors are reported by
782 : * filling escontext and returning false, instead of throwing them.
783 : */
784 : bool
785 GNC 1591 : parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p,
786 : Node *escontext)
787 : {
788 : TypeName *typeName;
789 ECB : Type tup;
790 :
791 GNC 1591 : typeName = typeStringToTypeName(str, escontext);
792 1588 : if (typeName == NULL)
793 UNC 0 : return false;
794 :
795 GNC 1588 : tup = LookupTypeName(NULL, typeName, typmod_p,
796 1588 : (escontext && IsA(escontext, ErrorSaveContext)));
797 GIC 1576 : if (tup == NULL)
798 ECB : {
799 GNC 17 : ereturn(escontext, false,
800 : (errcode(ERRCODE_UNDEFINED_OBJECT),
801 : errmsg("type \"%s\" does not exist",
802 : TypeNameToString(typeName))));
803 ECB : }
804 : else
805 : {
806 GIC 1559 : Form_pg_type typ = (Form_pg_type) GETSTRUCT(tup);
807 :
808 1559 : if (!typ->typisdefined)
809 : {
810 UNC 0 : ReleaseSysCache(tup);
811 0 : ereturn(escontext, false,
812 ECB : (errcode(ERRCODE_UNDEFINED_OBJECT),
813 : errmsg("type \"%s\" is only a shell",
814 : TypeNameToString(typeName))));
815 : }
816 GBC 1559 : *typeid_p = typ->oid;
817 1559 : ReleaseSysCache(tup);
818 : }
819 :
820 GNC 1559 : return true;
821 : }
|