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