Fix xslt_process() to ensure that it inserts a NULL terminator after the
[PostgreSQL.git] / src / backend / parser / parse_type.c
blobb8cca90725b425cec221b67e44678d0f239987cc
1 /*-------------------------------------------------------------------------
3 * parse_type.c
4 * handle type operations for parser
6 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * IDENTIFICATION
11 * $PostgreSQL$
13 *-------------------------------------------------------------------------
15 #include "postgres.h"
17 #include "catalog/namespace.h"
18 #include "catalog/pg_type.h"
19 #include "lib/stringinfo.h"
20 #include "nodes/makefuncs.h"
21 #include "parser/parser.h"
22 #include "parser/parse_type.h"
23 #include "utils/array.h"
24 #include "utils/builtins.h"
25 #include "utils/datum.h"
26 #include "utils/lsyscache.h"
27 #include "utils/syscache.h"
30 static int32 typenameTypeMod(ParseState *pstate, const TypeName *typename,
31 Type typ);
35 * LookupTypeName
36 * Given a TypeName object, lookup the pg_type syscache entry of the type.
37 * Returns NULL if no such type can be found. If the type is found,
38 * the typmod value represented in the TypeName struct is computed and
39 * stored into *typmod_p.
41 * NB: on success, the caller must ReleaseSysCache the type tuple when done
42 * with it.
44 * NB: direct callers of this function MUST check typisdefined before assuming
45 * that the type is fully valid. Most code should go through typenameType
46 * or typenameTypeId instead.
48 * typmod_p can be passed as NULL if the caller does not care to know the
49 * typmod value, but the typmod decoration (if any) will be validated anyway,
50 * except in the case where the type is not found. Note that if the type is
51 * found but is a shell, and there is typmod decoration, an error will be
52 * thrown --- this is intentional.
54 * pstate is only used for error location info, and may be NULL.
56 Type
57 LookupTypeName(ParseState *pstate, const TypeName *typename,
58 int32 *typmod_p)
60 Oid typoid;
61 HeapTuple tup;
62 int32 typmod;
64 if (typename->names == NIL)
66 /* We have the OID already if it's an internally generated TypeName */
67 typoid = typename->typeid;
69 else if (typename->pct_type)
71 /* Handle %TYPE reference to type of an existing field */
72 RangeVar *rel = makeRangeVar(NULL, NULL, typename->location);
73 char *field = NULL;
74 Oid relid;
75 AttrNumber attnum;
77 /* deconstruct the name list */
78 switch (list_length(typename->names))
80 case 1:
81 ereport(ERROR,
82 (errcode(ERRCODE_SYNTAX_ERROR),
83 errmsg("improper %%TYPE reference (too few dotted names): %s",
84 NameListToString(typename->names)),
85 parser_errposition(pstate, typename->location)));
86 break;
87 case 2:
88 rel->relname = strVal(linitial(typename->names));
89 field = strVal(lsecond(typename->names));
90 break;
91 case 3:
92 rel->schemaname = strVal(linitial(typename->names));
93 rel->relname = strVal(lsecond(typename->names));
94 field = strVal(lthird(typename->names));
95 break;
96 case 4:
97 rel->catalogname = strVal(linitial(typename->names));
98 rel->schemaname = strVal(lsecond(typename->names));
99 rel->relname = strVal(lthird(typename->names));
100 field = strVal(lfourth(typename->names));
101 break;
102 default:
103 ereport(ERROR,
104 (errcode(ERRCODE_SYNTAX_ERROR),
105 errmsg("improper %%TYPE reference (too many dotted names): %s",
106 NameListToString(typename->names)),
107 parser_errposition(pstate, typename->location)));
108 break;
111 /* look up the field */
112 relid = RangeVarGetRelid(rel, false);
113 attnum = get_attnum(relid, field);
114 if (attnum == InvalidAttrNumber)
115 ereport(ERROR,
116 (errcode(ERRCODE_UNDEFINED_COLUMN),
117 errmsg("column \"%s\" of relation \"%s\" does not exist",
118 field, rel->relname),
119 parser_errposition(pstate, typename->location)));
120 typoid = get_atttype(relid, attnum);
122 /* this construct should never have an array indicator */
123 Assert(typename->arrayBounds == NIL);
125 /* emit nuisance notice (intentionally not errposition'd) */
126 ereport(NOTICE,
127 (errmsg("type reference %s converted to %s",
128 TypeNameToString(typename),
129 format_type_be(typoid))));
131 else
133 /* Normal reference to a type name */
134 char *schemaname;
135 char *typname;
137 /* deconstruct the name list */
138 DeconstructQualifiedName(typename->names, &schemaname, &typname);
140 if (schemaname)
142 /* Look in specific schema only */
143 Oid namespaceId;
145 namespaceId = LookupExplicitNamespace(schemaname);
146 typoid = GetSysCacheOid(TYPENAMENSP,
147 PointerGetDatum(typname),
148 ObjectIdGetDatum(namespaceId),
149 0, 0);
151 else
153 /* Unqualified type name, so search the search path */
154 typoid = TypenameGetTypid(typname);
157 /* If an array reference, return the array type instead */
158 if (typename->arrayBounds != NIL)
159 typoid = get_array_type(typoid);
162 if (!OidIsValid(typoid))
164 if (typmod_p)
165 *typmod_p = -1;
166 return NULL;
169 tup = SearchSysCache(TYPEOID,
170 ObjectIdGetDatum(typoid),
171 0, 0, 0);
172 if (!HeapTupleIsValid(tup)) /* should not happen */
173 elog(ERROR, "cache lookup failed for type %u", typoid);
175 typmod = typenameTypeMod(pstate, typename, (Type) tup);
177 if (typmod_p)
178 *typmod_p = typmod;
180 return (Type) tup;
184 * typenameType - given a TypeName, return a Type structure and typmod
186 * This is equivalent to LookupTypeName, except that this will report
187 * a suitable error message if the type cannot be found or is not defined.
188 * Callers of this can therefore assume the result is a fully valid type.
190 Type
191 typenameType(ParseState *pstate, const TypeName *typename, int32 *typmod_p)
193 Type tup;
195 tup = LookupTypeName(pstate, typename, typmod_p);
196 if (tup == NULL)
197 ereport(ERROR,
198 (errcode(ERRCODE_UNDEFINED_OBJECT),
199 errmsg("type \"%s\" does not exist",
200 TypeNameToString(typename)),
201 parser_errposition(pstate, typename->location)));
202 if (!((Form_pg_type) GETSTRUCT(tup))->typisdefined)
203 ereport(ERROR,
204 (errcode(ERRCODE_UNDEFINED_OBJECT),
205 errmsg("type \"%s\" is only a shell",
206 TypeNameToString(typename)),
207 parser_errposition(pstate, typename->location)));
208 return tup;
212 * typenameTypeId - given a TypeName, return the type's OID and typmod
214 * This is equivalent to typenameType, but we only hand back the type OID
215 * not the syscache entry.
218 typenameTypeId(ParseState *pstate, const TypeName *typename, int32 *typmod_p)
220 Oid typoid;
221 Type tup;
223 tup = typenameType(pstate, typename, typmod_p);
224 typoid = HeapTupleGetOid(tup);
225 ReleaseSysCache(tup);
227 return typoid;
231 * typenameTypeMod - given a TypeName, return the internal typmod value
233 * This will throw an error if the TypeName includes type modifiers that are
234 * illegal for the data type.
236 * The actual type OID represented by the TypeName must already have been
237 * looked up, and is passed as "typ".
239 * pstate is only used for error location info, and may be NULL.
241 static int32
242 typenameTypeMod(ParseState *pstate, const TypeName *typename, Type typ)
244 int32 result;
245 Oid typmodin;
246 Datum *datums;
247 int n;
248 ListCell *l;
249 ArrayType *arrtypmod;
250 ParseCallbackState pcbstate;
252 /* Return prespecified typmod if no typmod expressions */
253 if (typename->typmods == NIL)
254 return typename->typemod;
257 * Else, type had better accept typmods. We give a special error message
258 * for the shell-type case, since a shell couldn't possibly have a
259 * typmodin function.
261 if (!((Form_pg_type) GETSTRUCT(typ))->typisdefined)
262 ereport(ERROR,
263 (errcode(ERRCODE_SYNTAX_ERROR),
264 errmsg("type modifier cannot be specified for shell type \"%s\"",
265 TypeNameToString(typename)),
266 parser_errposition(pstate, typename->location)));
268 typmodin = ((Form_pg_type) GETSTRUCT(typ))->typmodin;
270 if (typmodin == InvalidOid)
271 ereport(ERROR,
272 (errcode(ERRCODE_SYNTAX_ERROR),
273 errmsg("type modifier is not allowed for type \"%s\"",
274 TypeNameToString(typename)),
275 parser_errposition(pstate, typename->location)));
278 * Convert the list of raw-grammar-output expressions to a cstring array.
279 * Currently, we allow simple numeric constants, string literals, and
280 * identifiers; possibly this list could be extended.
282 datums = (Datum *) palloc(list_length(typename->typmods) * sizeof(Datum));
283 n = 0;
284 foreach(l, typename->typmods)
286 Node *tm = (Node *) lfirst(l);
287 char *cstr = NULL;
289 if (IsA(tm, A_Const))
291 A_Const *ac = (A_Const *) tm;
293 if (IsA(&ac->val, Integer))
295 cstr = (char *) palloc(32);
296 snprintf(cstr, 32, "%ld", (long) ac->val.val.ival);
298 else if (IsA(&ac->val, Float) ||
299 IsA(&ac->val, String))
301 /* we can just use the str field directly. */
302 cstr = ac->val.val.str;
305 else if (IsA(tm, ColumnRef))
307 ColumnRef *cr = (ColumnRef *) tm;
309 if (list_length(cr->fields) == 1 &&
310 IsA(linitial(cr->fields), String))
311 cstr = strVal(linitial(cr->fields));
313 if (!cstr)
314 ereport(ERROR,
315 (errcode(ERRCODE_SYNTAX_ERROR),
316 errmsg("type modifiers must be simple constants or identifiers"),
317 parser_errposition(pstate, typename->location)));
318 datums[n++] = CStringGetDatum(cstr);
321 /* hardwired knowledge about cstring's representation details here */
322 arrtypmod = construct_array(datums, n, CSTRINGOID,
323 -2, false, 'c');
325 /* arrange to report location if type's typmodin function fails */
326 setup_parser_errposition_callback(&pcbstate, pstate, typename->location);
328 result = DatumGetInt32(OidFunctionCall1(typmodin,
329 PointerGetDatum(arrtypmod)));
331 cancel_parser_errposition_callback(&pcbstate);
333 pfree(datums);
334 pfree(arrtypmod);
336 return result;
340 * appendTypeNameToBuffer
341 * Append a string representing the name of a TypeName to a StringInfo.
342 * This is the shared guts of TypeNameToString and TypeNameListToString.
344 * NB: this must work on TypeNames that do not describe any actual type;
345 * it is mostly used for reporting lookup errors.
347 static void
348 appendTypeNameToBuffer(const TypeName *typename, StringInfo string)
350 if (typename->names != NIL)
352 /* Emit possibly-qualified name as-is */
353 ListCell *l;
355 foreach(l, typename->names)
357 if (l != list_head(typename->names))
358 appendStringInfoChar(string, '.');
359 appendStringInfoString(string, strVal(lfirst(l)));
362 else
364 /* Look up internally-specified type */
365 appendStringInfoString(string, format_type_be(typename->typeid));
369 * Add decoration as needed, but only for fields considered by
370 * LookupTypeName
372 if (typename->pct_type)
373 appendStringInfoString(string, "%TYPE");
375 if (typename->arrayBounds != NIL)
376 appendStringInfoString(string, "[]");
380 * TypeNameToString
381 * Produce a string representing the name of a TypeName.
383 * NB: this must work on TypeNames that do not describe any actual type;
384 * it is mostly used for reporting lookup errors.
386 char *
387 TypeNameToString(const TypeName *typename)
389 StringInfoData string;
391 initStringInfo(&string);
392 appendTypeNameToBuffer(typename, &string);
393 return string.data;
397 * TypeNameListToString
398 * Produce a string representing the name(s) of a List of TypeNames
400 char *
401 TypeNameListToString(List *typenames)
403 StringInfoData string;
404 ListCell *l;
406 initStringInfo(&string);
407 foreach(l, typenames)
409 TypeName *typename = (TypeName *) lfirst(l);
411 Assert(IsA(typename, TypeName));
412 if (l != list_head(typenames))
413 appendStringInfoChar(&string, ',');
414 appendTypeNameToBuffer(typename, &string);
416 return string.data;
419 /* return a Type structure, given a type id */
420 /* NB: caller must ReleaseSysCache the type tuple when done with it */
421 Type
422 typeidType(Oid id)
424 HeapTuple tup;
426 tup = SearchSysCache(TYPEOID,
427 ObjectIdGetDatum(id),
428 0, 0, 0);
429 if (!HeapTupleIsValid(tup))
430 elog(ERROR, "cache lookup failed for type %u", id);
431 return (Type) tup;
434 /* given type (as type struct), return the type OID */
436 typeTypeId(Type tp)
438 if (tp == NULL) /* probably useless */
439 elog(ERROR, "typeTypeId() called with NULL type struct");
440 return HeapTupleGetOid(tp);
443 /* given type (as type struct), return the length of type */
444 int16
445 typeLen(Type t)
447 Form_pg_type typ;
449 typ = (Form_pg_type) GETSTRUCT(t);
450 return typ->typlen;
453 /* given type (as type struct), return the value of its 'byval' attribute.*/
454 bool
455 typeByVal(Type t)
457 Form_pg_type typ;
459 typ = (Form_pg_type) GETSTRUCT(t);
460 return typ->typbyval;
463 /* given type (as type struct), return the name of type */
464 char *
465 typeTypeName(Type t)
467 Form_pg_type typ;
469 typ = (Form_pg_type) GETSTRUCT(t);
470 /* pstrdup here because result may need to outlive the syscache entry */
471 return pstrdup(NameStr(typ->typname));
475 typeTypeRelid(Type typ)
477 Form_pg_type typtup;
479 typtup = (Form_pg_type) GETSTRUCT(typ);
481 return typtup->typrelid;
485 * Given a type structure and a string, returns the internal representation
486 * of that string. The "string" can be NULL to perform conversion of a NULL
487 * (which might result in failure, if the input function rejects NULLs).
489 Datum
490 stringTypeDatum(Type tp, char *string, int32 atttypmod)
492 Form_pg_type typform = (Form_pg_type) GETSTRUCT(tp);
493 Oid typinput = typform->typinput;
494 Oid typioparam = getTypeIOParam(tp);
495 Datum result;
497 result = OidInputFunctionCall(typinput, string,
498 typioparam, atttypmod);
500 #ifdef RANDOMIZE_ALLOCATED_MEMORY
503 * For pass-by-reference data types, repeat the conversion to see if the
504 * input function leaves any uninitialized bytes in the result. We can
505 * only detect that reliably if RANDOMIZE_ALLOCATED_MEMORY is enabled, so
506 * we don't bother testing otherwise. The reason we don't want any
507 * instability in the input function is that comparison of Const nodes
508 * relies on bytewise comparison of the datums, so if the input function
509 * leaves garbage then subexpressions that should be identical may not get
510 * recognized as such. See pgsql-hackers discussion of 2008-04-04.
512 if (string && !typform->typbyval)
514 Datum result2;
516 result2 = OidInputFunctionCall(typinput, string,
517 typioparam, atttypmod);
518 if (!datumIsEqual(result, result2, typform->typbyval, typform->typlen))
519 elog(WARNING, "type %s has unstable input conversion for \"%s\"",
520 NameStr(typform->typname), string);
522 #endif
524 return result;
527 /* given a typeid, return the type's typrelid (associated relation, if any) */
529 typeidTypeRelid(Oid type_id)
531 HeapTuple typeTuple;
532 Form_pg_type type;
533 Oid result;
535 typeTuple = SearchSysCache(TYPEOID,
536 ObjectIdGetDatum(type_id),
537 0, 0, 0);
538 if (!HeapTupleIsValid(typeTuple))
539 elog(ERROR, "cache lookup failed for type %u", type_id);
541 type = (Form_pg_type) GETSTRUCT(typeTuple);
542 result = type->typrelid;
543 ReleaseSysCache(typeTuple);
544 return result;
548 * error context callback for parse failure during parseTypeString()
550 static void
551 pts_error_callback(void *arg)
553 const char *str = (const char *) arg;
555 errcontext("invalid type name \"%s\"", str);
558 * Currently we just suppress any syntax error position report, rather
559 * than transforming to an "internal query" error. It's unlikely that a
560 * type name is complex enough to need positioning.
562 errposition(0);
566 * Given a string that is supposed to be a SQL-compatible type declaration,
567 * such as "int4" or "integer" or "character varying(32)", parse
568 * the string and convert it to a type OID and type modifier.
570 void
571 parseTypeString(const char *str, Oid *type_id, int32 *typmod_p)
573 StringInfoData buf;
574 List *raw_parsetree_list;
575 SelectStmt *stmt;
576 ResTarget *restarget;
577 TypeCast *typecast;
578 TypeName *typename;
579 ErrorContextCallback ptserrcontext;
581 /* make sure we give useful error for empty input */
582 if (strspn(str, " \t\n\r\f") == strlen(str))
583 goto fail;
585 initStringInfo(&buf);
586 appendStringInfo(&buf, "SELECT NULL::%s", str);
589 * Setup error traceback support in case of ereport() during parse
591 ptserrcontext.callback = pts_error_callback;
592 ptserrcontext.arg = (void *) str;
593 ptserrcontext.previous = error_context_stack;
594 error_context_stack = &ptserrcontext;
596 raw_parsetree_list = raw_parser(buf.data);
598 error_context_stack = ptserrcontext.previous;
601 * Make sure we got back exactly what we expected and no more; paranoia is
602 * justified since the string might contain anything.
604 if (list_length(raw_parsetree_list) != 1)
605 goto fail;
606 stmt = (SelectStmt *) linitial(raw_parsetree_list);
607 if (stmt == NULL ||
608 !IsA(stmt, SelectStmt) ||
609 stmt->distinctClause != NIL ||
610 stmt->intoClause != NULL ||
611 stmt->fromClause != NIL ||
612 stmt->whereClause != NULL ||
613 stmt->groupClause != NIL ||
614 stmt->havingClause != NULL ||
615 stmt->windowClause != NIL ||
616 stmt->withClause != NULL ||
617 stmt->valuesLists != NIL ||
618 stmt->sortClause != NIL ||
619 stmt->limitOffset != NULL ||
620 stmt->limitCount != NULL ||
621 stmt->lockingClause != NIL ||
622 stmt->op != SETOP_NONE)
623 goto fail;
624 if (list_length(stmt->targetList) != 1)
625 goto fail;
626 restarget = (ResTarget *) linitial(stmt->targetList);
627 if (restarget == NULL ||
628 !IsA(restarget, ResTarget) ||
629 restarget->name != NULL ||
630 restarget->indirection != NIL)
631 goto fail;
632 typecast = (TypeCast *) restarget->val;
633 if (typecast == NULL ||
634 !IsA(typecast, TypeCast) ||
635 typecast->arg == NULL ||
636 !IsA(typecast->arg, A_Const))
637 goto fail;
638 typename = typecast->typename;
639 if (typename == NULL ||
640 !IsA(typename, TypeName))
641 goto fail;
642 if (typename->setof)
643 goto fail;
645 *type_id = typenameTypeId(NULL, typename, typmod_p);
647 pfree(buf.data);
649 return;
651 fail:
652 ereport(ERROR,
653 (errcode(ERRCODE_SYNTAX_ERROR),
654 errmsg("invalid type name \"%s\"", str)));