PostgreSQL Source Code  git master
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 /*
645  * Given a typeid, return the type's typrelid (associated relation), if any.
646  * Returns InvalidOid if type is not a composite type.
647  */
648 Oid
650 {
651  HeapTuple typeTuple;
653  Oid result;
654 
655  typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_id));
656  if (!HeapTupleIsValid(typeTuple))
657  elog(ERROR, "cache lookup failed for type %u", type_id);
658  type = (Form_pg_type) GETSTRUCT(typeTuple);
659  result = type->typrelid;
660  ReleaseSysCache(typeTuple);
661  return result;
662 }
663 
664 /*
665  * Given a typeid, return the type's typrelid (associated relation), if any.
666  * Returns InvalidOid if type is not a composite type or a domain over one.
667  * This is the same as typeidTypeRelid(getBaseType(type_id)), but faster.
668  */
669 Oid
671 {
672  HeapTuple typeTuple;
674  Oid result;
675 
676  for (;;)
677  {
678  typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_id));
679  if (!HeapTupleIsValid(typeTuple))
680  elog(ERROR, "cache lookup failed for type %u", type_id);
681  type = (Form_pg_type) GETSTRUCT(typeTuple);
682  if (type->typtype != TYPTYPE_DOMAIN)
683  {
684  /* Not a domain, so done looking through domains */
685  break;
686  }
687  /* It is a domain, so examine the base type instead */
688  type_id = type->typbasetype;
689  ReleaseSysCache(typeTuple);
690  }
691  result = type->typrelid;
692  ReleaseSysCache(typeTuple);
693  return result;
694 }
695 
696 /*
697  * error context callback for parse failure during parseTypeString()
698  */
699 static void
701 {
702  const char *str = (const char *) arg;
703 
704  errcontext("invalid type name \"%s\"", str);
705 
706  /*
707  * Currently we just suppress any syntax error position report, rather
708  * than transforming to an "internal query" error. It's unlikely that a
709  * type name is complex enough to need positioning.
710  */
711  errposition(0);
712 }
713 
714 /*
715  * Given a string that is supposed to be a SQL-compatible type declaration,
716  * such as "int4" or "integer" or "character varying(32)", parse
717  * the string and return the result as a TypeName.
718  * If the string cannot be parsed as a type, an error is raised.
719  */
720 TypeName *
722 {
724  List *raw_parsetree_list;
725  SelectStmt *stmt;
726  ResTarget *restarget;
727  TypeCast *typecast;
728  TypeName *typeName;
729  ErrorContextCallback ptserrcontext;
730 
731  /* make sure we give useful error for empty input */
732  if (strspn(str, " \t\n\r\f") == strlen(str))
733  goto fail;
734 
735  initStringInfo(&buf);
736  appendStringInfo(&buf, "SELECT NULL::%s", str);
737 
738  /*
739  * Setup error traceback support in case of ereport() during parse
740  */
741  ptserrcontext.callback = pts_error_callback;
742  ptserrcontext.arg = (void *) str;
743  ptserrcontext.previous = error_context_stack;
744  error_context_stack = &ptserrcontext;
745 
746  raw_parsetree_list = raw_parser(buf.data);
747 
748  error_context_stack = ptserrcontext.previous;
749 
750  /*
751  * Make sure we got back exactly what we expected and no more; paranoia is
752  * justified since the string might contain anything.
753  */
754  if (list_length(raw_parsetree_list) != 1)
755  goto fail;
756  stmt = (SelectStmt *) linitial_node(RawStmt, raw_parsetree_list)->stmt;
757  if (stmt == NULL ||
758  !IsA(stmt, SelectStmt) ||
759  stmt->distinctClause != NIL ||
760  stmt->intoClause != NULL ||
761  stmt->fromClause != NIL ||
762  stmt->whereClause != NULL ||
763  stmt->groupClause != NIL ||
764  stmt->havingClause != NULL ||
765  stmt->windowClause != NIL ||
766  stmt->valuesLists != NIL ||
767  stmt->sortClause != NIL ||
768  stmt->limitOffset != NULL ||
769  stmt->limitCount != NULL ||
770  stmt->lockingClause != NIL ||
771  stmt->withClause != NULL ||
772  stmt->op != SETOP_NONE)
773  goto fail;
774  if (list_length(stmt->targetList) != 1)
775  goto fail;
776  restarget = (ResTarget *) linitial(stmt->targetList);
777  if (restarget == NULL ||
778  !IsA(restarget, ResTarget) ||
779  restarget->name != NULL ||
780  restarget->indirection != NIL)
781  goto fail;
782  typecast = (TypeCast *) restarget->val;
783  if (typecast == NULL ||
784  !IsA(typecast, TypeCast) ||
785  typecast->arg == NULL ||
786  !IsA(typecast->arg, A_Const))
787  goto fail;
788 
789  typeName = typecast->typeName;
790  if (typeName == NULL ||
791  !IsA(typeName, TypeName))
792  goto fail;
793  if (typeName->setof)
794  goto fail;
795 
796  pfree(buf.data);
797 
798  return typeName;
799 
800 fail:
801  ereport(ERROR,
802  (errcode(ERRCODE_SYNTAX_ERROR),
803  errmsg("invalid type name \"%s\"", str)));
804  return NULL; /* keep compiler quiet */
805 }
806 
807 /*
808  * Given a string that is supposed to be a SQL-compatible type declaration,
809  * such as "int4" or "integer" or "character varying(32)", parse
810  * the string and convert it to a type OID and type modifier.
811  * If missing_ok is true, InvalidOid is returned rather than raising an error
812  * when the type name is not found.
813  */
814 void
815 parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p, bool missing_ok)
816 {
817  TypeName *typeName;
818  Type tup;
819 
820  typeName = typeStringToTypeName(str);
821 
822  tup = LookupTypeName(NULL, typeName, typmod_p, missing_ok);
823  if (tup == NULL)
824  {
825  if (!missing_ok)
826  ereport(ERROR,
827  (errcode(ERRCODE_UNDEFINED_OBJECT),
828  errmsg("type \"%s\" does not exist",
829  TypeNameToString(typeName)),
830  parser_errposition(NULL, typeName->location)));
831  *typeid_p = InvalidOid;
832  }
833  else
834  {
835  if (!((Form_pg_type) GETSTRUCT(tup))->typisdefined)
836  ereport(ERROR,
837  (errcode(ERRCODE_UNDEFINED_OBJECT),
838  errmsg("type \"%s\" is only a shell",
839  TypeNameToString(typeName)),
840  parser_errposition(NULL, typeName->location)));
841  *typeid_p = HeapTupleGetOid(tup);
842  ReleaseSysCache(tup);
843  }
844 }
Type LookupTypeName(ParseState *pstate, const TypeName *typeName, int32 *typmod_p, bool missing_ok)
Definition: parse_type.c:57
signed short int16
Definition: c.h:283
List * indirection
Definition: parsenodes.h:440
#define NIL
Definition: pg_list.h:69
#define TYPTYPE_DOMAIN
Definition: pg_type.h:722
Oid typeTypeCollation(Type typ)
Definition: parse_type.c:621
Oid typeOid
Definition: parsenodes.h:209
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
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:661
List * raw_parser(const char *str)
Definition: parser.c:36
Oid typeOrDomainTypeRelid(Oid type_id)
Definition: parse_type.c:670
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:1519
List * fromClause
Definition: parsenodes.h:1521
#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:1542
char * TypeNameToString(const TypeName *typeName)
Definition: parse_type.c:459
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2526
char * pstrdup(const char *in)
Definition: mcxt.c:1076
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:3279
Definition: nodes.h:510
#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:649
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
void(* callback)(void *arg)
Definition: elog.h:239
struct ErrorContextCallback * previous
Definition: elog.h:238
#define OidIsValid(objectId)
Definition: c.h:576
#define lsecond(l)
Definition: pg_list.h:116
signed int int32
Definition: c.h:284
#define GetSysCacheOid2(cacheId, key1, key2)
Definition: syscache.h:193
static struct pg_tm tm
Definition: localtime.c:107
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:1517
void pfree(void *pointer)
Definition: mcxt.c:949
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:623
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:67
List * sortClause
Definition: parsenodes.h:1541
static void pts_error_callback(void *arg)
Definition: parse_type.c:700
AttrNumber get_attnum(Oid relid, const char *attname)
Definition: lsyscache.c:821
List * targetList
Definition: parsenodes.h:1520
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:1535
Oid get_atttype(Oid relid, AttrNumber attnum)
Definition: lsyscache.c:878
#define ereport(elevel, rest)
Definition: elog.h:122
List * lockingClause
Definition: parsenodes.h:1544
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
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
char * NameListToString(List *names)
Definition: namespace.c:3063
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
List * typmods
Definition: parsenodes.h:212
TypeName * typeName
Definition: parsenodes.h:298
TypeName * typeStringToTypeName(const char *str)
Definition: parse_type.c:721
List * windowClause
Definition: parsenodes.h:1525
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:815
SetOperation op
Definition: parsenodes.h:1550
#define InvalidOid
Definition: postgres_ext.h:36
Oid get_typcollation(Oid typid)
Definition: lsyscache.c:2795
#define NOTICE
Definition: elog.h:37
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define CSTRINGOID
Definition: pg_type.h:684
#define Assert(condition)
Definition: c.h:670
#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:1523
List * collname
Definition: parsenodes.h:309
List * arrayBounds
Definition: parsenodes.h:214
void * palloc(Size size)
Definition: mcxt.c:848
int errmsg(const char *fmt,...)
Definition: elog.c:797
Node * havingClause
Definition: parsenodes.h:1524
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:547
void * arg
#define lthird(l)
Definition: pg_list.h:121
WithClause * withClause
Definition: parsenodes.h:1545
#define elog
Definition: elog.h:219
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700
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:1733
int16 AttrNumber
Definition: attnum.h:21
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:421
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:1543
List * fields
Definition: parsenodes.h:234
Node * whereClause
Definition: parsenodes.h:1522
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