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  *		Wrapper for typical case.
37  */
38 Type
LookupTypeName(ParseState * pstate,const TypeName * typeName,int32 * typmod_p,bool missing_ok)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
LookupTypeNameExtended(ParseState * pstate,const TypeName * typeName,int32 * typmod_p,bool temp_ok,bool missing_ok)74 LookupTypeNameExtended(ParseState *pstate,
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;
93 		AttrNumber	attnum;
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,
183 										 PointerGetDatum(typname),
184 										 ObjectIdGetDatum(namespaceId));
185 			else
186 				typoid = InvalidOid;
187 
188 			cancel_parser_errposition_callback(&pcbstate);
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
LookupTypeNameOid(ParseState * pstate,const TypeName * typeName,bool missing_ok)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 = HeapTupleGetOid(tup);
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
typenameType(ParseState * pstate,const TypeName * typeName,int32 * typmod_p)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
typenameTypeId(ParseState * pstate,const TypeName * typeName)292 typenameTypeId(ParseState *pstate, const TypeName *typeName)
293 {
294 	Oid			typoid;
295 	Type		tup;
296 
297 	tup = typenameType(pstate, typeName, NULL);
298 	typoid = HeapTupleGetOid(tup);
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
typenameTypeIdAndMod(ParseState * pstate,const TypeName * typeName,Oid * typeid_p,int32 * typmod_p)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 = HeapTupleGetOid(tup);
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
typenameTypeMod(ParseState * pstate,const TypeName * typeName,Type typ)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 
421 	cancel_parser_errposition_callback(&pcbstate);
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
appendTypeNameToBuffer(const TypeName * typeName,StringInfo string)438 appendTypeNameToBuffer(const TypeName *typeName, StringInfo string)
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 *
TypeNameToString(const TypeName * typeName)477 TypeNameToString(const TypeName *typeName)
478 {
479 	StringInfoData string;
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 *
TypeNameListToString(List * typenames)491 TypeNameListToString(List *typenames)
492 {
493 	StringInfoData string;
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
LookupCollation(ParseState * pstate,List * collnames,int location)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)
525 		cancel_parser_errposition_callback(&pcbstate);
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
GetColumnDefCollation(ParseState * pstate,ColumnDef * coldef,Oid typeOid)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
typeidType(Oid id)577 typeidType(Oid id)
578 {
579 	HeapTuple	tup;
580 
581 	tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(id));
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
typeTypeId(Type tp)589 typeTypeId(Type tp)
590 {
591 	if (tp == NULL)				/* probably useless */
592 		elog(ERROR, "typeTypeId() called with NULL type struct");
593 	return HeapTupleGetOid(tp);
594 }
595 
596 /* given type (as type struct), return the length of type */
597 int16
typeLen(Type t)598 typeLen(Type t)
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
typeByVal(Type t)608 typeByVal(Type t)
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 *
typeTypeName(Type t)618 typeTypeName(Type t)
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
typeTypeRelid(Type typ)629 typeTypeRelid(Type typ)
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
typeTypeCollation(Type typ)639 typeTypeCollation(Type typ)
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
stringTypeDatum(Type tp,char * string,int32 atttypmod)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 /* given a typeid, return the type's typrelid (associated relation, if any) */
663 Oid
typeidTypeRelid(Oid type_id)664 typeidTypeRelid(Oid type_id)
665 {
666 	HeapTuple	typeTuple;
667 	Form_pg_type type;
668 	Oid			result;
669 
670 	typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type_id));
671 	if (!HeapTupleIsValid(typeTuple))
672 		elog(ERROR, "cache lookup failed for type %u", type_id);
673 
674 	type = (Form_pg_type) GETSTRUCT(typeTuple);
675 	result = type->typrelid;
676 	ReleaseSysCache(typeTuple);
677 	return result;
678 }
679 
680 /*
681  * error context callback for parse failure during parseTypeString()
682  */
683 static void
pts_error_callback(void * arg)684 pts_error_callback(void *arg)
685 {
686 	const char *str = (const char *) arg;
687 
688 	errcontext("invalid type name \"%s\"", str);
689 
690 	/*
691 	 * Currently we just suppress any syntax error position report, rather
692 	 * than transforming to an "internal query" error.  It's unlikely that a
693 	 * type name is complex enough to need positioning.
694 	 */
695 	errposition(0);
696 }
697 
698 /*
699  * Given a string that is supposed to be a SQL-compatible type declaration,
700  * such as "int4" or "integer" or "character varying(32)", parse
701  * the string and return the result as a TypeName.
702  * If the string cannot be parsed as a type, an error is raised.
703  */
704 TypeName *
typeStringToTypeName(const char * str)705 typeStringToTypeName(const char *str)
706 {
707 	StringInfoData buf;
708 	List	   *raw_parsetree_list;
709 	SelectStmt *stmt;
710 	ResTarget  *restarget;
711 	TypeCast   *typecast;
712 	TypeName   *typeName;
713 	ErrorContextCallback ptserrcontext;
714 
715 	/* make sure we give useful error for empty input */
716 	if (strspn(str, " \t\n\r\f") == strlen(str))
717 		goto fail;
718 
719 	initStringInfo(&buf);
720 	appendStringInfo(&buf, "SELECT NULL::%s", str);
721 
722 	/*
723 	 * Setup error traceback support in case of ereport() during parse
724 	 */
725 	ptserrcontext.callback = pts_error_callback;
726 	ptserrcontext.arg = (void *) str;
727 	ptserrcontext.previous = error_context_stack;
728 	error_context_stack = &ptserrcontext;
729 
730 	raw_parsetree_list = raw_parser(buf.data);
731 
732 	error_context_stack = ptserrcontext.previous;
733 
734 	/*
735 	 * Make sure we got back exactly what we expected and no more; paranoia is
736 	 * justified since the string might contain anything.
737 	 */
738 	if (list_length(raw_parsetree_list) != 1)
739 		goto fail;
740 	stmt = (SelectStmt *) linitial_node(RawStmt, raw_parsetree_list)->stmt;
741 	if (stmt == NULL ||
742 		!IsA(stmt, SelectStmt) ||
743 		stmt->distinctClause != NIL ||
744 		stmt->intoClause != NULL ||
745 		stmt->fromClause != NIL ||
746 		stmt->whereClause != NULL ||
747 		stmt->groupClause != NIL ||
748 		stmt->havingClause != NULL ||
749 		stmt->windowClause != NIL ||
750 		stmt->valuesLists != NIL ||
751 		stmt->sortClause != NIL ||
752 		stmt->limitOffset != NULL ||
753 		stmt->limitCount != NULL ||
754 		stmt->lockingClause != NIL ||
755 		stmt->withClause != NULL ||
756 		stmt->op != SETOP_NONE)
757 		goto fail;
758 	if (list_length(stmt->targetList) != 1)
759 		goto fail;
760 	restarget = (ResTarget *) linitial(stmt->targetList);
761 	if (restarget == NULL ||
762 		!IsA(restarget, ResTarget) ||
763 		restarget->name != NULL ||
764 		restarget->indirection != NIL)
765 		goto fail;
766 	typecast = (TypeCast *) restarget->val;
767 	if (typecast == NULL ||
768 		!IsA(typecast, TypeCast) ||
769 		typecast->arg == NULL ||
770 		!IsA(typecast->arg, A_Const))
771 		goto fail;
772 
773 	typeName = typecast->typeName;
774 	if (typeName == NULL ||
775 		!IsA(typeName, TypeName))
776 		goto fail;
777 	if (typeName->setof)
778 		goto fail;
779 
780 	pfree(buf.data);
781 
782 	return typeName;
783 
784 fail:
785 	ereport(ERROR,
786 			(errcode(ERRCODE_SYNTAX_ERROR),
787 			 errmsg("invalid type name \"%s\"", str)));
788 	return NULL;				/* keep compiler quiet */
789 }
790 
791 /*
792  * Given a string that is supposed to be a SQL-compatible type declaration,
793  * such as "int4" or "integer" or "character varying(32)", parse
794  * the string and convert it to a type OID and type modifier.
795  * If missing_ok is true, InvalidOid is returned rather than raising an error
796  * when the type name is not found.
797  */
798 void
parseTypeString(const char * str,Oid * typeid_p,int32 * typmod_p,bool missing_ok)799 parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p, bool missing_ok)
800 {
801 	TypeName   *typeName;
802 	Type		tup;
803 
804 	typeName = typeStringToTypeName(str);
805 
806 	tup = LookupTypeName(NULL, typeName, typmod_p, missing_ok);
807 	if (tup == NULL)
808 	{
809 		if (!missing_ok)
810 			ereport(ERROR,
811 					(errcode(ERRCODE_UNDEFINED_OBJECT),
812 					 errmsg("type \"%s\" does not exist",
813 							TypeNameToString(typeName)),
814 					 parser_errposition(NULL, typeName->location)));
815 		*typeid_p = InvalidOid;
816 	}
817 	else
818 	{
819 		if (!((Form_pg_type) GETSTRUCT(tup))->typisdefined)
820 			ereport(ERROR,
821 					(errcode(ERRCODE_UNDEFINED_OBJECT),
822 					 errmsg("type \"%s\" is only a shell",
823 							TypeNameToString(typeName)),
824 					 parser_errposition(NULL, typeName->location)));
825 		*typeid_p = HeapTupleGetOid(tup);
826 		ReleaseSysCache(tup);
827 	}
828 }
829