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-2016, 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 = (TypeName *) lfirst(l);
482 
483  Assert(IsA(typeName, TypeName));
484  if (l != list_head(typenames))
485  appendStringInfoChar(&string, ',');
486  appendTypeNameToBuffer(typeName, &string);
487  }
488  return string.data;
489 }
490 
491 /*
492  * LookupCollation
493  *
494  * Look up collation by name, return OID, with support for error location.
495  */
496 Oid
497 LookupCollation(ParseState *pstate, List *collnames, int location)
498 {
499  Oid colloid;
500  ParseCallbackState pcbstate;
501 
502  if (pstate)
503  setup_parser_errposition_callback(&pcbstate, pstate, location);
504 
505  colloid = get_collation_oid(collnames, false);
506 
507  if (pstate)
509 
510  return colloid;
511 }
512 
513 /*
514  * GetColumnDefCollation
515  *
516  * Get the collation to be used for a column being defined, given the
517  * ColumnDef node and the previously-determined column type OID.
518  *
519  * pstate is only used for error location purposes, and can be NULL.
520  */
521 Oid
522 GetColumnDefCollation(ParseState *pstate, ColumnDef *coldef, Oid typeOid)
523 {
524  Oid result;
525  Oid typcollation = get_typcollation(typeOid);
526  int location = coldef->location;
527 
528  if (coldef->collClause)
529  {
530  /* We have a raw COLLATE clause, so look up the collation */
531  location = coldef->collClause->location;
532  result = LookupCollation(pstate, coldef->collClause->collname,
533  location);
534  }
535  else if (OidIsValid(coldef->collOid))
536  {
537  /* Precooked collation spec, use that */
538  result = coldef->collOid;
539  }
540  else
541  {
542  /* Use the type's default collation if any */
543  result = typcollation;
544  }
545 
546  /* Complain if COLLATE is applied to an uncollatable type */
547  if (OidIsValid(result) && !OidIsValid(typcollation))
548  ereport(ERROR,
549  (errcode(ERRCODE_DATATYPE_MISMATCH),
550  errmsg("collations are not supported by type %s",
551  format_type_be(typeOid)),
552  parser_errposition(pstate, location)));
553 
554  return result;
555 }
556 
557 /* return a Type structure, given a type id */
558 /* NB: caller must ReleaseSysCache the type tuple when done with it */
559 Type
561 {
562  HeapTuple tup;
563 
565  if (!HeapTupleIsValid(tup))
566  elog(ERROR, "cache lookup failed for type %u", id);
567  return (Type) tup;
568 }
569 
570 /* given type (as type struct), return the type OID */
571 Oid
573 {
574  if (tp == NULL) /* probably useless */
575  elog(ERROR, "typeTypeId() called with NULL type struct");
576  return HeapTupleGetOid(tp);
577 }
578 
579 /* given type (as type struct), return the length of type */
580 int16
582 {
583  Form_pg_type typ;
584 
585  typ = (Form_pg_type) GETSTRUCT(t);
586  return typ->typlen;
587 }
588 
589 /* given type (as type struct), return its 'byval' attribute */
590 bool
592 {
593  Form_pg_type typ;
594 
595  typ = (Form_pg_type) GETSTRUCT(t);
596  return typ->typbyval;
597 }
598 
599 /* given type (as type struct), return the type's name */
600 char *
602 {
603  Form_pg_type typ;
604 
605  typ = (Form_pg_type) GETSTRUCT(t);
606  /* pstrdup here because result may need to outlive the syscache entry */
607  return pstrdup(NameStr(typ->typname));
608 }
609 
610 /* given type (as type struct), return its 'typrelid' attribute */
611 Oid
613 {
614  Form_pg_type typtup;
615 
616  typtup = (Form_pg_type) GETSTRUCT(typ);
617  return typtup->typrelid;
618 }
619 
620 /* given type (as type struct), return its 'typcollation' attribute */
621 Oid
623 {
624  Form_pg_type typtup;
625 
626  typtup = (Form_pg_type) GETSTRUCT(typ);
627  return typtup->typcollation;
628 }
629 
630 /*
631  * Given a type structure and a string, returns the internal representation
632  * of that string. The "string" can be NULL to perform conversion of a NULL
633  * (which might result in failure, if the input function rejects NULLs).
634  */
635 Datum
636 stringTypeDatum(Type tp, char *string, int32 atttypmod)
637 {
638  Form_pg_type typform = (Form_pg_type) GETSTRUCT(tp);
639  Oid typinput = typform->typinput;
640  Oid typioparam = getTypeIOParam(tp);
641 
642  return OidInputFunctionCall(typinput, string, typioparam, atttypmod);
643 }
644 
645 /* given a typeid, return the type's typrelid (associated relation, if any) */
646 Oid
648 {
649  HeapTuple typeTuple;
650  Form_pg_type type;
651  Oid result;
652 
653  typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_id));
654  if (!HeapTupleIsValid(typeTuple))
655  elog(ERROR, "cache lookup failed for type %u", type_id);
656 
657  type = (Form_pg_type) GETSTRUCT(typeTuple);
658  result = type->typrelid;
659  ReleaseSysCache(typeTuple);
660  return result;
661 }
662 
663 /*
664  * error context callback for parse failure during parseTypeString()
665  */
666 static void
668 {
669  const char *str = (const char *) arg;
670 
671  errcontext("invalid type name \"%s\"", str);
672 
673  /*
674  * Currently we just suppress any syntax error position report, rather
675  * than transforming to an "internal query" error. It's unlikely that a
676  * type name is complex enough to need positioning.
677  */
678  errposition(0);
679 }
680 
681 /*
682  * Given a string that is supposed to be a SQL-compatible type declaration,
683  * such as "int4" or "integer" or "character varying(32)", parse
684  * the string and return the result as a TypeName.
685  * If the string cannot be parsed as a type, an error is raised.
686  */
687 TypeName *
688 typeStringToTypeName(const char *str)
689 {
691  List *raw_parsetree_list;
692  SelectStmt *stmt;
693  ResTarget *restarget;
694  TypeCast *typecast;
695  TypeName *typeName;
696  ErrorContextCallback ptserrcontext;
697 
698  /* make sure we give useful error for empty input */
699  if (strspn(str, " \t\n\r\f") == strlen(str))
700  goto fail;
701 
702  initStringInfo(&buf);
703  appendStringInfo(&buf, "SELECT NULL::%s", str);
704 
705  /*
706  * Setup error traceback support in case of ereport() during parse
707  */
708  ptserrcontext.callback = pts_error_callback;
709  ptserrcontext.arg = (void *) str;
710  ptserrcontext.previous = error_context_stack;
711  error_context_stack = &ptserrcontext;
712 
713  raw_parsetree_list = raw_parser(buf.data);
714 
715  error_context_stack = ptserrcontext.previous;
716 
717  /*
718  * Make sure we got back exactly what we expected and no more; paranoia is
719  * justified since the string might contain anything.
720  */
721  if (list_length(raw_parsetree_list) != 1)
722  goto fail;
723  stmt = (SelectStmt *) linitial(raw_parsetree_list);
724  if (stmt == NULL ||
725  !IsA(stmt, SelectStmt) ||
726  stmt->distinctClause != NIL ||
727  stmt->intoClause != NULL ||
728  stmt->fromClause != NIL ||
729  stmt->whereClause != NULL ||
730  stmt->groupClause != NIL ||
731  stmt->havingClause != NULL ||
732  stmt->windowClause != NIL ||
733  stmt->valuesLists != NIL ||
734  stmt->sortClause != NIL ||
735  stmt->limitOffset != NULL ||
736  stmt->limitCount != NULL ||
737  stmt->lockingClause != NIL ||
738  stmt->withClause != NULL ||
739  stmt->op != SETOP_NONE)
740  goto fail;
741  if (list_length(stmt->targetList) != 1)
742  goto fail;
743  restarget = (ResTarget *) linitial(stmt->targetList);
744  if (restarget == NULL ||
745  !IsA(restarget, ResTarget) ||
746  restarget->name != NULL ||
747  restarget->indirection != NIL)
748  goto fail;
749  typecast = (TypeCast *) restarget->val;
750  if (typecast == NULL ||
751  !IsA(typecast, TypeCast) ||
752  typecast->arg == NULL ||
753  !IsA(typecast->arg, A_Const))
754  goto fail;
755 
756  typeName = typecast->typeName;
757  if (typeName == NULL ||
758  !IsA(typeName, TypeName))
759  goto fail;
760  if (typeName->setof)
761  goto fail;
762 
763  pfree(buf.data);
764 
765  return typeName;
766 
767 fail:
768  ereport(ERROR,
769  (errcode(ERRCODE_SYNTAX_ERROR),
770  errmsg("invalid type name \"%s\"", str)));
771  return NULL; /* keep compiler quiet */
772 }
773 
774 /*
775  * Given a string that is supposed to be a SQL-compatible type declaration,
776  * such as "int4" or "integer" or "character varying(32)", parse
777  * the string and convert it to a type OID and type modifier.
778  * If missing_ok is true, InvalidOid is returned rather than raising an error
779  * when the type name is not found.
780  */
781 void
782 parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p, bool missing_ok)
783 {
784  TypeName *typeName;
785  Type tup;
786 
787  typeName = typeStringToTypeName(str);
788 
789  tup = LookupTypeName(NULL, typeName, typmod_p, missing_ok);
790  if (tup == NULL)
791  {
792  if (!missing_ok)
793  ereport(ERROR,
794  (errcode(ERRCODE_UNDEFINED_OBJECT),
795  errmsg("type \"%s\" does not exist",
796  TypeNameToString(typeName)),
797  parser_errposition(NULL, typeName->location)));
798  *typeid_p = InvalidOid;
799  }
800  else
801  {
802  if (!((Form_pg_type) GETSTRUCT(tup))->typisdefined)
803  ereport(ERROR,
804  (errcode(ERRCODE_UNDEFINED_OBJECT),
805  errmsg("type \"%s\" is only a shell",
806  TypeNameToString(typeName)),
807  parser_errposition(NULL, typeName->location)));
808  *typeid_p = HeapTupleGetOid(tup);
809  ReleaseSysCache(tup);
810  }
811 }
Type LookupTypeName(ParseState *pstate, const TypeName *typeName, int32 *typmod_p, bool missing_ok)
Definition: parse_type.c:57
signed short int16
Definition: c.h:252
List * indirection
Definition: parsenodes.h:422
#define NIL
Definition: pg_list.h:69
Oid typeTypeCollation(Type typ)
Definition: parse_type.c:622
Oid typeOid
Definition: parsenodes.h:192
#define IsA(nodeptr, _type_)
Definition: nodes.h:542
Node * val
Definition: parsenodes.h:423
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
Definition: namespace.c:2702
#define GETSTRUCT(TUP)
Definition: htup_details.h:631
List * raw_parser(const char *str)
Definition: parser.c:35
Type typenameType(ParseState *pstate, const TypeName *typeName, int32 *typmod_p)
Definition: parse_type.c:247
List * names
Definition: parsenodes.h:191
IntoClause * intoClause
Definition: parsenodes.h:1287
List * fromClause
Definition: parsenodes.h:1289
#define DatumGetInt32(X)
Definition: postgres.h:480
char * name
Definition: parsenodes.h:421
Oid TypenameGetTypid(const char *typname)
Definition: namespace.c:762
long ival
Definition: value.h:47
int16 typeLen(Type t)
Definition: parse_type.c:581
#define PointerGetDatum(X)
Definition: postgres.h:564
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:53
Node * limitOffset
Definition: parsenodes.h:1310
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:459
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2480
char * pstrdup(const char *in)
Definition: mcxt.c:1168
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:491
#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
char * TypeNameListToString(List *typenames)
Definition: parse_type.c:473
Oid typeidTypeRelid(Oid type_id)
Definition: parse_type.c:647
void DeconstructQualifiedName(List *names, char **nspname_p, char **objname_p)
Definition: namespace.c:2618
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
unsigned int Oid
Definition: postgres_ext.h:31
struct ErrorContextCallback * previous
Definition: elog.h:237
#define OidIsValid(objectId)
Definition: c.h:530
#define lsecond(l)
Definition: pg_list.h:114
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:141
signed int int32
Definition: c.h:253
#define GetSysCacheOid2(cacheId, key1, key2)
Definition: syscache.h:170
static struct pg_tm tm
Definition: localtime.c:103
char * schemaname
Definition: primnodes.h:73
ErrorContextCallback * error_context_stack
Definition: elog.c:89
char * relname
Definition: primnodes.h:74
List * distinctClause
Definition: parsenodes.h:1285
void pfree(void *pointer)
Definition: mcxt.c:995
void cancel_parser_errposition_callback(ParseCallbackState *pcbstate)
Definition: parse_node.c:158
bool typeByVal(Type t)
Definition: parse_type.c:591
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define linitial(l)
Definition: pg_list.h:110
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
char * typeTypeName(Type t)
Definition: parse_type.c:601
bool setof
Definition: parsenodes.h:193
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:586
Datum stringTypeDatum(Type tp, char *string, int32 atttypmod)
Definition: parse_type.c:636
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:65
List * sortClause
Definition: parsenodes.h:1309
static void pts_error_callback(void *arg)
Definition: parse_type.c:667
AttrNumber get_attnum(Oid relid, const char *attname)
Definition: lsyscache.c:821
List * targetList
Definition: parsenodes.h:1288
Oid collOid
Definition: parsenodes.h:598
union Value::ValUnion val
#define CStringGetDatum(X)
Definition: postgres.h:586
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:601
List * valuesLists
Definition: parsenodes.h:1303
Oid get_atttype(Oid relid, AttrNumber attnum)
Definition: lsyscache.c:846
#define ereport(elevel, rest)
Definition: elog.h:122
List * lockingClause
Definition: parsenodes.h:1312
void setup_parser_errposition_callback(ParseCallbackState *pcbstate, ParseState *pstate, int location)
Definition: parse_node.c:142
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:522
char * NameListToString(List *names)
Definition: namespace.c:2912
uintptr_t Datum
Definition: postgres.h:374
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:990
List * typmods
Definition: parsenodes.h:195
TypeName * typeName
Definition: parsenodes.h:280
TypeName * typeStringToTypeName(const char *str)
Definition: parse_type.c:688
List * windowClause
Definition: parsenodes.h:1293
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:497
void parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p, bool missing_ok)
Definition: parse_type.c:782
SetOperation op
Definition: parsenodes.h:1318
#define InvalidOid
Definition: postgres_ext.h:36
Oid get_typcollation(Oid typid)
Definition: lsyscache.c:2749
#define NOTICE
Definition: elog.h:37
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define CSTRINGOID
Definition: pg_type.h:672
#define Assert(condition)
Definition: c.h:667
#define lfirst(lc)
Definition: pg_list.h:106
#define lfourth(l)
Definition: pg_list.h:122
int location
Definition: parsenodes.h:198
static int list_length(const List *l)
Definition: pg_list.h:89
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:108
int32 typemod
Definition: parsenodes.h:196
CollateClause * collClause
Definition: parsenodes.h:597
#define InvalidAttrNumber
Definition: attnum.h:23
List * groupClause
Definition: parsenodes.h:1291
List * collname
Definition: parsenodes.h:291
List * arrayBounds
Definition: parsenodes.h:197
void(* callback)(void *arg)
Definition: elog.h:238
void * palloc(Size size)
Definition: mcxt.c:894
int errmsg(const char *fmt,...)
Definition: elog.c:797
Node * havingClause
Definition: parsenodes.h:1292
Oid typeTypeRelid(Type typ)
Definition: parse_type.c:612
char * str
Definition: value.h:48
Oid getTypeIOParam(HeapTuple typeTuple)
Definition: lsyscache.c:2021
#define errcontext
Definition: elog.h:164
#define NameStr(name)
Definition: c.h:494
void * arg
#define lthird(l)
Definition: pg_list.h:118
WithClause * withClause
Definition: parsenodes.h:1313
#define elog
Definition: elog.h:218
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:670
Type typeidType(Oid id)
Definition: parse_type.c:560
Oid typeTypeId(Type tp)
Definition: parse_type.c:572
Value val
Definition: parsenodes.h:269
Oid get_collation_oid(List *name, bool missing_ok)
Definition: namespace.c:3294
Definition: pg_list.h:45
Datum OidInputFunctionCall(Oid functionId, char *str, Oid typioparam, int32 typmod)
Definition: fmgr.c:2039
int16 AttrNumber
Definition: attnum.h:21
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:419
char * catalogname
Definition: primnodes.h:72
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:1311
List * fields
Definition: parsenodes.h:217
Node * whereClause
Definition: parsenodes.h:1290
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:194
Node * arg
Definition: parsenodes.h:279