PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
parse_type.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * parse_type.c
4  * handle type operations for parser
5  *
6  * Portions Copyright (c) 1996-2017, 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/parser.h"
23 #include "parser/parse_type.h"
24 #include "utils/array.h"
25 #include "utils/builtins.h"
26 #include "utils/lsyscache.h"
27 #include "utils/syscache.h"
28 
29 
30 static int32 typenameTypeMod(ParseState *pstate, const TypeName *typeName,
31  Type typ);
32 
33 
34 /*
35  * LookupTypeName
36  * Given a TypeName object, lookup the pg_type syscache entry of the type.
37  * Returns NULL if no such type can be found. If the type is found,
38  * the typmod value represented in the TypeName struct is computed and
39  * stored into *typmod_p.
40  *
41  * NB: on success, the caller must ReleaseSysCache the type tuple when done
42  * with it.
43  *
44  * NB: direct callers of this function MUST check typisdefined before assuming
45  * that the type is fully valid. Most code should go through typenameType
46  * or typenameTypeId instead.
47  *
48  * typmod_p can be passed as NULL if the caller does not care to know the
49  * typmod value, but the typmod decoration (if any) will be validated anyway,
50  * except in the case where the type is not found. Note that if the type is
51  * found but is a shell, and there is typmod decoration, an error will be
52  * thrown --- this is intentional.
53  *
54  * pstate is only used for error location info, and may be NULL.
55  */
56 Type
57 LookupTypeName(ParseState *pstate, const TypeName *typeName,
58  int32 *typmod_p, bool missing_ok)
59 {
60  Oid typoid;
61  HeapTuple tup;
62  int32 typmod;
63 
64  if (typeName->names == NIL)
65  {
66  /* We have the OID already if it's an internally generated TypeName */
67  typoid = typeName->typeOid;
68  }
69  else if (typeName->pct_type)
70  {
71  /* Handle %TYPE reference to type of an existing field */
72  RangeVar *rel = makeRangeVar(NULL, NULL, typeName->location);
73  char *field = NULL;
74  Oid relid;
75  AttrNumber attnum;
76 
77  /* deconstruct the name list */
78  switch (list_length(typeName->names))
79  {
80  case 1:
81  ereport(ERROR,
82  (errcode(ERRCODE_SYNTAX_ERROR),
83  errmsg("improper %%TYPE reference (too few dotted names): %s",
84  NameListToString(typeName->names)),
85  parser_errposition(pstate, typeName->location)));
86  break;
87  case 2:
88  rel->relname = strVal(linitial(typeName->names));
89  field = strVal(lsecond(typeName->names));
90  break;
91  case 3:
92  rel->schemaname = strVal(linitial(typeName->names));
93  rel->relname = strVal(lsecond(typeName->names));
94  field = strVal(lthird(typeName->names));
95  break;
96  case 4:
97  rel->catalogname = strVal(linitial(typeName->names));
98  rel->schemaname = strVal(lsecond(typeName->names));
99  rel->relname = strVal(lthird(typeName->names));
100  field = strVal(lfourth(typeName->names));
101  break;
102  default:
103  ereport(ERROR,
104  (errcode(ERRCODE_SYNTAX_ERROR),
105  errmsg("improper %%TYPE reference (too many dotted names): %s",
106  NameListToString(typeName->names)),
107  parser_errposition(pstate, typeName->location)));
108  break;
109  }
110 
111  /*
112  * Look up the field.
113  *
114  * XXX: As no lock is taken here, this might fail in the presence of
115  * concurrent DDL. But taking a lock would carry a performance
116  * penalty and would also require a permissions check.
117  */
118  relid = RangeVarGetRelid(rel, NoLock, missing_ok);
119  attnum = get_attnum(relid, field);
120  if (attnum == InvalidAttrNumber)
121  {
122  if (missing_ok)
123  typoid = InvalidOid;
124  else
125  ereport(ERROR,
126  (errcode(ERRCODE_UNDEFINED_COLUMN),
127  errmsg("column \"%s\" of relation \"%s\" does not exist",
128  field, rel->relname),
129  parser_errposition(pstate, typeName->location)));
130  }
131  else
132  {
133  typoid = get_atttype(relid, attnum);
134 
135  /* this construct should never have an array indicator */
136  Assert(typeName->arrayBounds == NIL);
137 
138  /* emit nuisance notice (intentionally not errposition'd) */
139  ereport(NOTICE,
140  (errmsg("type reference %s converted to %s",
141  TypeNameToString(typeName),
142  format_type_be(typoid))));
143  }
144  }
145  else
146  {
147  /* Normal reference to a type name */
148  char *schemaname;
149  char *typname;
150 
151  /* deconstruct the name list */
152  DeconstructQualifiedName(typeName->names, &schemaname, &typname);
153 
154  if (schemaname)
155  {
156  /* Look in specific schema only */
157  Oid namespaceId;
158  ParseCallbackState pcbstate;
159 
160  setup_parser_errposition_callback(&pcbstate, pstate, typeName->location);
161 
162  namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
163  if (OidIsValid(namespaceId))
164  typoid = GetSysCacheOid2(TYPENAMENSP,
165  PointerGetDatum(typname),
166  ObjectIdGetDatum(namespaceId));
167  else
168  typoid = InvalidOid;
169 
171  }
172  else
173  {
174  /* Unqualified type name, so search the search path */
175  typoid = TypenameGetTypid(typname);
176  }
177 
178  /* If an array reference, return the array type instead */
179  if (typeName->arrayBounds != NIL)
180  typoid = get_array_type(typoid);
181  }
182 
183  if (!OidIsValid(typoid))
184  {
185  if (typmod_p)
186  *typmod_p = -1;
187  return NULL;
188  }
189 
190  tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typoid));
191  if (!HeapTupleIsValid(tup)) /* should not happen */
192  elog(ERROR, "cache lookup failed for type %u", typoid);
193 
194  typmod = typenameTypeMod(pstate, typeName, (Type) tup);
195 
196  if (typmod_p)
197  *typmod_p = typmod;
198 
199  return (Type) tup;
200 }
201 
202 /*
203  * LookupTypeNameOid
204  * Given a TypeName object, lookup the pg_type syscache entry of the type.
205  * Returns InvalidOid if no such type can be found. If the type is found,
206  * return its Oid.
207  *
208  * NB: direct callers of this function need to be aware that the type OID
209  * returned may correspond to a shell type. Most code should go through
210  * typenameTypeId instead.
211  *
212  * pstate is only used for error location info, and may be NULL.
213  */
214 Oid
215 LookupTypeNameOid(ParseState *pstate, const TypeName *typeName, bool missing_ok)
216 {
217  Oid typoid;
218  Type tup;
219 
220  tup = LookupTypeName(pstate, typeName, NULL, missing_ok);
221  if (tup == NULL)
222  {
223  if (!missing_ok)
224  ereport(ERROR,
225  (errcode(ERRCODE_UNDEFINED_OBJECT),
226  errmsg("type \"%s\" does not exist",
227  TypeNameToString(typeName)),
228  parser_errposition(pstate, typeName->location)));
229 
230  return InvalidOid;
231  }
232 
233  typoid = HeapTupleGetOid(tup);
234  ReleaseSysCache(tup);
235 
236  return typoid;
237 }
238 
239 /*
240  * typenameType - given a TypeName, return a Type structure and typmod
241  *
242  * This is equivalent to LookupTypeName, except that this will report
243  * a suitable error message if the type cannot be found or is not defined.
244  * Callers of this can therefore assume the result is a fully valid type.
245  */
246 Type
247 typenameType(ParseState *pstate, const TypeName *typeName, int32 *typmod_p)
248 {
249  Type tup;
250 
251  tup = LookupTypeName(pstate, typeName, typmod_p, false);
252  if (tup == NULL)
253  ereport(ERROR,
254  (errcode(ERRCODE_UNDEFINED_OBJECT),
255  errmsg("type \"%s\" does not exist",
256  TypeNameToString(typeName)),
257  parser_errposition(pstate, typeName->location)));
258  if (!((Form_pg_type) GETSTRUCT(tup))->typisdefined)
259  ereport(ERROR,
260  (errcode(ERRCODE_UNDEFINED_OBJECT),
261  errmsg("type \"%s\" is only a shell",
262  TypeNameToString(typeName)),
263  parser_errposition(pstate, typeName->location)));
264  return tup;
265 }
266 
267 /*
268  * typenameTypeId - given a TypeName, return the type's OID
269  *
270  * This is similar to typenameType, but we only hand back the type OID
271  * not the syscache entry.
272  */
273 Oid
274 typenameTypeId(ParseState *pstate, const TypeName *typeName)
275 {
276  Oid typoid;
277  Type tup;
278 
279  tup = typenameType(pstate, typeName, NULL);
280  typoid = HeapTupleGetOid(tup);
281  ReleaseSysCache(tup);
282 
283  return typoid;
284 }
285 
286 /*
287  * typenameTypeIdAndMod - given a TypeName, return the type's OID and typmod
288  *
289  * This is equivalent to typenameType, but we only hand back the type OID
290  * and typmod, not the syscache entry.
291  */
292 void
293 typenameTypeIdAndMod(ParseState *pstate, const TypeName *typeName,
294  Oid *typeid_p, int32 *typmod_p)
295 {
296  Type tup;
297 
298  tup = typenameType(pstate, typeName, typmod_p);
299  *typeid_p = HeapTupleGetOid(tup);
300  ReleaseSysCache(tup);
301 }
302 
303 /*
304  * typenameTypeMod - given a TypeName, return the internal typmod value
305  *
306  * This will throw an error if the TypeName includes type modifiers that are
307  * illegal for the data type.
308  *
309  * The actual type OID represented by the TypeName must already have been
310  * looked up, and is passed as "typ".
311  *
312  * pstate is only used for error location info, and may be NULL.
313  */
314 static int32
315 typenameTypeMod(ParseState *pstate, const TypeName *typeName, Type typ)
316 {
317  int32 result;
318  Oid typmodin;
319  Datum *datums;
320  int n;
321  ListCell *l;
322  ArrayType *arrtypmod;
323  ParseCallbackState pcbstate;
324 
325  /* Return prespecified typmod if no typmod expressions */
326  if (typeName->typmods == NIL)
327  return typeName->typemod;
328 
329  /*
330  * Else, type had better accept typmods. We give a special error message
331  * for the shell-type case, since a shell couldn't possibly have a
332  * typmodin function.
333  */
334  if (!((Form_pg_type) GETSTRUCT(typ))->typisdefined)
335  ereport(ERROR,
336  (errcode(ERRCODE_SYNTAX_ERROR),
337  errmsg("type modifier cannot be specified for shell type \"%s\"",
338  TypeNameToString(typeName)),
339  parser_errposition(pstate, typeName->location)));
340 
341  typmodin = ((Form_pg_type) GETSTRUCT(typ))->typmodin;
342 
343  if (typmodin == InvalidOid)
344  ereport(ERROR,
345  (errcode(ERRCODE_SYNTAX_ERROR),
346  errmsg("type modifier is not allowed for type \"%s\"",
347  TypeNameToString(typeName)),
348  parser_errposition(pstate, typeName->location)));
349 
350  /*
351  * Convert the list of raw-grammar-output expressions to a cstring array.
352  * Currently, we allow simple numeric constants, string literals, and
353  * identifiers; possibly this list could be extended.
354  */
355  datums = (Datum *) palloc(list_length(typeName->typmods) * sizeof(Datum));
356  n = 0;
357  foreach(l, typeName->typmods)
358  {
359  Node *tm = (Node *) lfirst(l);
360  char *cstr = NULL;
361 
362  if (IsA(tm, A_Const))
363  {
364  A_Const *ac = (A_Const *) tm;
365 
366  if (IsA(&ac->val, Integer))
367  {
368  cstr = psprintf("%ld", (long) ac->val.val.ival);
369  }
370  else if (IsA(&ac->val, Float) ||
371  IsA(&ac->val, String))
372  {
373  /* we can just use the str field directly. */
374  cstr = ac->val.val.str;
375  }
376  }
377  else if (IsA(tm, ColumnRef))
378  {
379  ColumnRef *cr = (ColumnRef *) tm;
380 
381  if (list_length(cr->fields) == 1 &&
382  IsA(linitial(cr->fields), String))
383  cstr = strVal(linitial(cr->fields));
384  }
385  if (!cstr)
386  ereport(ERROR,
387  (errcode(ERRCODE_SYNTAX_ERROR),
388  errmsg("type modifiers must be simple constants or identifiers"),
389  parser_errposition(pstate, typeName->location)));
390  datums[n++] = CStringGetDatum(cstr);
391  }
392 
393  /* hardwired knowledge about cstring's representation details here */
394  arrtypmod = construct_array(datums, n, CSTRINGOID,
395  -2, false, 'c');
396 
397  /* arrange to report location if type's typmodin function fails */
398  setup_parser_errposition_callback(&pcbstate, pstate, typeName->location);
399 
400  result = DatumGetInt32(OidFunctionCall1(typmodin,
401  PointerGetDatum(arrtypmod)));
402 
404 
405  pfree(datums);
406  pfree(arrtypmod);
407 
408  return result;
409 }
410 
411 /*
412  * appendTypeNameToBuffer
413  * Append a string representing the name of a TypeName to a StringInfo.
414  * This is the shared guts of TypeNameToString and TypeNameListToString.
415  *
416  * NB: this must work on TypeNames that do not describe any actual type;
417  * it is mostly used for reporting lookup errors.
418  */
419 static void
421 {
422  if (typeName->names != NIL)
423  {
424  /* Emit possibly-qualified name as-is */
425  ListCell *l;
426 
427  foreach(l, typeName->names)
428  {
429  if (l != list_head(typeName->names))
430  appendStringInfoChar(string, '.');
431  appendStringInfoString(string, strVal(lfirst(l)));
432  }
433  }
434  else
435  {
436  /* Look up internally-specified type */
437  appendStringInfoString(string, format_type_be(typeName->typeOid));
438  }
439 
440  /*
441  * Add decoration as needed, but only for fields considered by
442  * LookupTypeName
443  */
444  if (typeName->pct_type)
445  appendStringInfoString(string, "%TYPE");
446 
447  if (typeName->arrayBounds != NIL)
448  appendStringInfoString(string, "[]");
449 }
450 
451 /*
452  * TypeNameToString
453  * Produce a string representing the name of a TypeName.
454  *
455  * NB: this must work on TypeNames that do not describe any actual type;
456  * it is mostly used for reporting lookup errors.
457  */
458 char *
459 TypeNameToString(const TypeName *typeName)
460 {
462 
463  initStringInfo(&string);
464  appendTypeNameToBuffer(typeName, &string);
465  return string.data;
466 }
467 
468 /*
469  * TypeNameListToString
470  * Produce a string representing the name(s) of a List of TypeNames
471  */
472 char *
474 {
476  ListCell *l;
477 
478  initStringInfo(&string);
479  foreach(l, typenames)
480  {
481  TypeName *typeName = lfirst_node(TypeName, l);
482 
483  if (l != list_head(typenames))
484  appendStringInfoChar(&string, ',');
485  appendTypeNameToBuffer(typeName, &string);
486  }
487  return string.data;
488 }
489 
490 /*
491  * LookupCollation
492  *
493  * Look up collation by name, return OID, with support for error location.
494  */
495 Oid
496 LookupCollation(ParseState *pstate, List *collnames, int location)
497 {
498  Oid colloid;
499  ParseCallbackState pcbstate;
500 
501  if (pstate)
502  setup_parser_errposition_callback(&pcbstate, pstate, location);
503 
504  colloid = get_collation_oid(collnames, false);
505 
506  if (pstate)
508 
509  return colloid;
510 }
511 
512 /*
513  * GetColumnDefCollation
514  *
515  * Get the collation to be used for a column being defined, given the
516  * ColumnDef node and the previously-determined column type OID.
517  *
518  * pstate is only used for error location purposes, and can be NULL.
519  */
520 Oid
521 GetColumnDefCollation(ParseState *pstate, ColumnDef *coldef, Oid typeOid)
522 {
523  Oid result;
524  Oid typcollation = get_typcollation(typeOid);
525  int location = coldef->location;
526 
527  if (coldef->collClause)
528  {
529  /* We have a raw COLLATE clause, so look up the collation */
530  location = coldef->collClause->location;
531  result = LookupCollation(pstate, coldef->collClause->collname,
532  location);
533  }
534  else if (OidIsValid(coldef->collOid))
535  {
536  /* Precooked collation spec, use that */
537  result = coldef->collOid;
538  }
539  else
540  {
541  /* Use the type's default collation if any */
542  result = typcollation;
543  }
544 
545  /* Complain if COLLATE is applied to an uncollatable type */
546  if (OidIsValid(result) && !OidIsValid(typcollation))
547  ereport(ERROR,
548  (errcode(ERRCODE_DATATYPE_MISMATCH),
549  errmsg("collations are not supported by type %s",
550  format_type_be(typeOid)),
551  parser_errposition(pstate, location)));
552 
553  return result;
554 }
555 
556 /* return a Type structure, given a type id */
557 /* NB: caller must ReleaseSysCache the type tuple when done with it */
558 Type
560 {
561  HeapTuple tup;
562 
564  if (!HeapTupleIsValid(tup))
565  elog(ERROR, "cache lookup failed for type %u", id);
566  return (Type) tup;
567 }
568 
569 /* given type (as type struct), return the type OID */
570 Oid
572 {
573  if (tp == NULL) /* probably useless */
574  elog(ERROR, "typeTypeId() called with NULL type struct");
575  return HeapTupleGetOid(tp);
576 }
577 
578 /* given type (as type struct), return the length of type */
579 int16
581 {
582  Form_pg_type typ;
583 
584  typ = (Form_pg_type) GETSTRUCT(t);
585  return typ->typlen;
586 }
587 
588 /* given type (as type struct), return its 'byval' attribute */
589 bool
591 {
592  Form_pg_type typ;
593 
594  typ = (Form_pg_type) GETSTRUCT(t);
595  return typ->typbyval;
596 }
597 
598 /* given type (as type struct), return the type's name */
599 char *
601 {
602  Form_pg_type typ;
603 
604  typ = (Form_pg_type) GETSTRUCT(t);
605  /* pstrdup here because result may need to outlive the syscache entry */
606  return pstrdup(NameStr(typ->typname));
607 }
608 
609 /* given type (as type struct), return its 'typrelid' attribute */
610 Oid
612 {
613  Form_pg_type typtup;
614 
615  typtup = (Form_pg_type) GETSTRUCT(typ);
616  return typtup->typrelid;
617 }
618 
619 /* given type (as type struct), return its 'typcollation' attribute */
620 Oid
622 {
623  Form_pg_type typtup;
624 
625  typtup = (Form_pg_type) GETSTRUCT(typ);
626  return typtup->typcollation;
627 }
628 
629 /*
630  * Given a type structure and a string, returns the internal representation
631  * of that string. The "string" can be NULL to perform conversion of a NULL
632  * (which might result in failure, if the input function rejects NULLs).
633  */
634 Datum
635 stringTypeDatum(Type tp, char *string, int32 atttypmod)
636 {
637  Form_pg_type typform = (Form_pg_type) GETSTRUCT(tp);
638  Oid typinput = typform->typinput;
639  Oid typioparam = getTypeIOParam(tp);
640 
641  return OidInputFunctionCall(typinput, string, typioparam, atttypmod);
642 }
643 
644 /* given a typeid, return the type's typrelid (associated relation, if any) */
645 Oid
647 {
648  HeapTuple typeTuple;
649  Form_pg_type type;
650  Oid result;
651 
652  typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_id));
653  if (!HeapTupleIsValid(typeTuple))
654  elog(ERROR, "cache lookup failed for type %u", type_id);
655 
656  type = (Form_pg_type) GETSTRUCT(typeTuple);
657  result = type->typrelid;
658  ReleaseSysCache(typeTuple);
659  return result;
660 }
661 
662 /*
663  * error context callback for parse failure during parseTypeString()
664  */
665 static void
667 {
668  const char *str = (const char *) arg;
669 
670  errcontext("invalid type name \"%s\"", str);
671 
672  /*
673  * Currently we just suppress any syntax error position report, rather
674  * than transforming to an "internal query" error. It's unlikely that a
675  * type name is complex enough to need positioning.
676  */
677  errposition(0);
678 }
679 
680 /*
681  * Given a string that is supposed to be a SQL-compatible type declaration,
682  * such as "int4" or "integer" or "character varying(32)", parse
683  * the string and return the result as a TypeName.
684  * If the string cannot be parsed as a type, an error is raised.
685  */
686 TypeName *
687 typeStringToTypeName(const char *str)
688 {
690  List *raw_parsetree_list;
691  SelectStmt *stmt;
692  ResTarget *restarget;
693  TypeCast *typecast;
694  TypeName *typeName;
695  ErrorContextCallback ptserrcontext;
696 
697  /* make sure we give useful error for empty input */
698  if (strspn(str, " \t\n\r\f") == strlen(str))
699  goto fail;
700 
701  initStringInfo(&buf);
702  appendStringInfo(&buf, "SELECT NULL::%s", str);
703 
704  /*
705  * Setup error traceback support in case of ereport() during parse
706  */
707  ptserrcontext.callback = pts_error_callback;
708  ptserrcontext.arg = (void *) str;
709  ptserrcontext.previous = error_context_stack;
710  error_context_stack = &ptserrcontext;
711 
712  raw_parsetree_list = raw_parser(buf.data);
713 
714  error_context_stack = ptserrcontext.previous;
715 
716  /*
717  * Make sure we got back exactly what we expected and no more; paranoia is
718  * justified since the string might contain anything.
719  */
720  if (list_length(raw_parsetree_list) != 1)
721  goto fail;
722  stmt = (SelectStmt *) linitial_node(RawStmt, raw_parsetree_list)->stmt;
723  if (stmt == NULL ||
724  !IsA(stmt, SelectStmt) ||
725  stmt->distinctClause != NIL ||
726  stmt->intoClause != NULL ||
727  stmt->fromClause != NIL ||
728  stmt->whereClause != NULL ||
729  stmt->groupClause != NIL ||
730  stmt->havingClause != NULL ||
731  stmt->windowClause != NIL ||
732  stmt->valuesLists != NIL ||
733  stmt->sortClause != NIL ||
734  stmt->limitOffset != NULL ||
735  stmt->limitCount != NULL ||
736  stmt->lockingClause != NIL ||
737  stmt->withClause != NULL ||
738  stmt->op != SETOP_NONE)
739  goto fail;
740  if (list_length(stmt->targetList) != 1)
741  goto fail;
742  restarget = (ResTarget *) linitial(stmt->targetList);
743  if (restarget == NULL ||
744  !IsA(restarget, ResTarget) ||
745  restarget->name != NULL ||
746  restarget->indirection != NIL)
747  goto fail;
748  typecast = (TypeCast *) restarget->val;
749  if (typecast == NULL ||
750  !IsA(typecast, TypeCast) ||
751  typecast->arg == NULL ||
752  !IsA(typecast->arg, A_Const))
753  goto fail;
754 
755  typeName = typecast->typeName;
756  if (typeName == NULL ||
757  !IsA(typeName, TypeName))
758  goto fail;
759  if (typeName->setof)
760  goto fail;
761 
762  pfree(buf.data);
763 
764  return typeName;
765 
766 fail:
767  ereport(ERROR,
768  (errcode(ERRCODE_SYNTAX_ERROR),
769  errmsg("invalid type name \"%s\"", str)));
770  return NULL; /* keep compiler quiet */
771 }
772 
773 /*
774  * Given a string that is supposed to be a SQL-compatible type declaration,
775  * such as "int4" or "integer" or "character varying(32)", parse
776  * the string and convert it to a type OID and type modifier.
777  * If missing_ok is true, InvalidOid is returned rather than raising an error
778  * when the type name is not found.
779  */
780 void
781 parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p, bool missing_ok)
782 {
783  TypeName *typeName;
784  Type tup;
785 
786  typeName = typeStringToTypeName(str);
787 
788  tup = LookupTypeName(NULL, typeName, typmod_p, missing_ok);
789  if (tup == NULL)
790  {
791  if (!missing_ok)
792  ereport(ERROR,
793  (errcode(ERRCODE_UNDEFINED_OBJECT),
794  errmsg("type \"%s\" does not exist",
795  TypeNameToString(typeName)),
796  parser_errposition(NULL, typeName->location)));
797  *typeid_p = InvalidOid;
798  }
799  else
800  {
801  if (!((Form_pg_type) GETSTRUCT(tup))->typisdefined)
802  ereport(ERROR,
803  (errcode(ERRCODE_UNDEFINED_OBJECT),
804  errmsg("type \"%s\" is only a shell",
805  TypeNameToString(typeName)),
806  parser_errposition(NULL, typeName->location)));
807  *typeid_p = HeapTupleGetOid(tup);
808  ReleaseSysCache(tup);
809  }
810 }
Type LookupTypeName(ParseState *pstate, const TypeName *typeName, int32 *typmod_p, bool missing_ok)
Definition: parse_type.c:57
signed short int16
Definition: c.h:255
List * indirection
Definition: parsenodes.h:440
#define NIL
Definition: pg_list.h:69
Oid typeTypeCollation(Type typ)
Definition: parse_type.c:621
Oid typeOid
Definition: parsenodes.h:209
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
Node * val
Definition: parsenodes.h:441
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
Definition: namespace.c:2853
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
List * raw_parser(const char *str)
Definition: parser.c:36
Type typenameType(ParseState *pstate, const TypeName *typeName, int32 *typmod_p)
Definition: parse_type.c:247
List * names
Definition: parsenodes.h:208
IntoClause * intoClause
Definition: parsenodes.h:1507
List * fromClause
Definition: parsenodes.h:1509
#define DatumGetInt32(X)
Definition: postgres.h:478
char * name
Definition: parsenodes.h:439
Oid TypenameGetTypid(const char *typname)
Definition: namespace.c:748
long ival
Definition: value.h:47
int16 typeLen(Type t)
Definition: parse_type.c:580
#define PointerGetDatum(X)
Definition: postgres.h:562
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:53
Node * limitOffset
Definition: parsenodes.h:1530
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:459
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2512
char * pstrdup(const char *in)
Definition: mcxt.c:1077
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3306
Definition: nodes.h:509
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
return result
Definition: formatting.c:1633
char * TypeNameListToString(List *typenames)
Definition: parse_type.c:473
Oid typeidTypeRelid(Oid type_id)
Definition: parse_type.c:646
void DeconstructQualifiedName(List *names, char **nspname_p, char **objname_p)
Definition: namespace.c:2769
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
unsigned int Oid
Definition: postgres_ext.h:31
#define linitial_node(type, l)
Definition: pg_list.h:114
struct ErrorContextCallback * previous
Definition: elog.h:238
#define OidIsValid(objectId)
Definition: c.h:538
#define lsecond(l)
Definition: pg_list.h:116
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
signed int int32
Definition: c.h:256
#define GetSysCacheOid2(cacheId, key1, key2)
Definition: syscache.h:185
static struct pg_tm tm
Definition: localtime.c:111
char * schemaname
Definition: primnodes.h:67
ErrorContextCallback * error_context_stack
Definition: elog.c:88
char * relname
Definition: primnodes.h:68
List * distinctClause
Definition: parsenodes.h:1505
void pfree(void *pointer)
Definition: mcxt.c:950
void cancel_parser_errposition_callback(ParseCallbackState *pcbstate)
Definition: parse_node.c:161
bool typeByVal(Type t)
Definition: parse_type.c:590
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define linitial(l)
Definition: pg_list.h:111
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
char * typeTypeName(Type t)
Definition: parse_type.c:600
bool setof
Definition: parsenodes.h:210
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:622
Datum stringTypeDatum(Type tp, char *string, int32 atttypmod)
Definition: parse_type.c:635
#define lfirst_node(type, lc)
Definition: pg_list.h:109
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
#define NoLock
Definition: lockdefs.h:34
static char * buf
Definition: pg_test_fsync.c:66
List * sortClause
Definition: parsenodes.h:1529
static void pts_error_callback(void *arg)
Definition: parse_type.c:666
AttrNumber get_attnum(Oid relid, const char *attname)
Definition: lsyscache.c:821
List * targetList
Definition: parsenodes.h:1508
Oid collOid
Definition: parsenodes.h:651
union Value::ValUnion val
#define CStringGetDatum(X)
Definition: postgres.h:584
char string[11]
Definition: preproc-type.c:46
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
static void appendTypeNameToBuffer(const TypeName *typeName, StringInfo string)
Definition: parse_type.c:420
int location
Definition: parsenodes.h:654
List * valuesLists
Definition: parsenodes.h:1523
Oid get_atttype(Oid relid, AttrNumber attnum)
Definition: lsyscache.c:878
#define ereport(elevel, rest)
Definition: elog.h:122
List * lockingClause
Definition: parsenodes.h:1532
void setup_parser_errposition_callback(ParseCallbackState *pcbstate, ParseState *pstate, int location)
Definition: parse_node.c:145
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
Oid GetColumnDefCollation(ParseState *pstate, ColumnDef *coldef, Oid typeOid)
Definition: parse_type.c:521
char * NameListToString(List *names)
Definition: namespace.c:3063
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
List * typmods
Definition: parsenodes.h:212
TypeName * typeName
Definition: parsenodes.h:298
TypeName * typeStringToTypeName(const char *str)
Definition: parse_type.c:687
List * windowClause
Definition: parsenodes.h:1513
void typenameTypeIdAndMod(ParseState *pstate, const TypeName *typeName, Oid *typeid_p, int32 *typmod_p)
Definition: parse_type.c:293
Oid LookupCollation(ParseState *pstate, List *collnames, int location)
Definition: parse_type.c:496
void parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p, bool missing_ok)
Definition: parse_type.c:781
SetOperation op
Definition: parsenodes.h:1538
#define InvalidOid
Definition: postgres_ext.h:36
Oid get_typcollation(Oid typid)
Definition: lsyscache.c:2781
#define NOTICE
Definition: elog.h:37
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#define CSTRINGOID
Definition: pg_type.h:684
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
#define lfourth(l)
Definition: pg_list.h:126
int location
Definition: parsenodes.h:215
static int list_length(const List *l)
Definition: pg_list.h:89
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
int32 typemod
Definition: parsenodes.h:213
CollateClause * collClause
Definition: parsenodes.h:650
#define InvalidAttrNumber
Definition: attnum.h:23
List * groupClause
Definition: parsenodes.h:1511
List * collname
Definition: parsenodes.h:309
List * arrayBounds
Definition: parsenodes.h:214
void(* callback)(void *arg)
Definition: elog.h:239
void * palloc(Size size)
Definition: mcxt.c:849
int errmsg(const char *fmt,...)
Definition: elog.c:797
Node * havingClause
Definition: parsenodes.h:1512
Oid typeTypeRelid(Type typ)
Definition: parse_type.c:611
char * str
Definition: value.h:48
Oid getTypeIOParam(HeapTuple typeTuple)
Definition: lsyscache.c:2053
#define errcontext
Definition: elog.h:164
#define NameStr(name)
Definition: c.h:499
void * arg
#define lthird(l)
Definition: pg_list.h:121
WithClause * withClause
Definition: parsenodes.h:1533
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
Type typeidType(Oid id)
Definition: parse_type.c:559
Oid typeTypeId(Type tp)
Definition: parse_type.c:571
Value val
Definition: parsenodes.h:287
Oid get_collation_oid(List *name, bool missing_ok)
Definition: namespace.c:3493
Definition: pg_list.h:45
Datum OidInputFunctionCall(Oid functionId, char *str, Oid typioparam, int32 typmod)
Definition: fmgr.c:1738
int16 AttrNumber
Definition: attnum.h:21
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:419
char * catalogname
Definition: primnodes.h:66
static int32 typenameTypeMod(ParseState *pstate, const TypeName *typeName, Type typ)
Definition: parse_type.c:315
int errposition(int cursorpos)
Definition: elog.c:1125
Node * limitCount
Definition: parsenodes.h:1531
List * fields
Definition: parsenodes.h:234
Node * whereClause
Definition: parsenodes.h:1510
Oid LookupTypeNameOid(ParseState *pstate, const TypeName *typeName, bool missing_ok)
Definition: parse_type.c:215
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:274
bool pct_type
Definition: parsenodes.h:211
Node * arg
Definition: parsenodes.h:297