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