OSDN Git Service

Update copyright for 2009.
[pg-rex/syncrep.git] / src / backend / parser / parse_type.c
1 /*-------------------------------------------------------------------------
2  *
3  * parse_type.c
4  *              handle type operations for parser
5  *
6  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $PostgreSQL: pgsql/src/backend/parser/parse_type.c,v 1.102 2009/01/01 17:23:46 momjian Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16
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"
28
29
30 static int32 typenameTypeMod(ParseState *pstate, const TypeName *typename,
31                                 Type typ);
32
33
34 /*
35  * LookupTypeName
36  *              Given a TypeName object, lookup the pg_type syscache entry of the type.
37  *              Returns NULL if no such type can be found.      If the type is found,
38  *              the typmod value represented in the TypeName struct is computed and
39  *              stored into *typmod_p.
40  *
41  * NB: on success, the caller must ReleaseSysCache the type tuple when done
42  * with it.
43  *
44  * NB: direct callers of this function MUST check typisdefined before assuming
45  * that the type is fully valid.  Most code should go through typenameType
46  * or typenameTypeId instead.
47  *
48  * typmod_p can be passed as NULL if the caller does not care to know the
49  * typmod value, but the typmod decoration (if any) will be validated anyway,
50  * except in the case where the type is not found.      Note that if the type is
51  * found but is a shell, and there is typmod decoration, an error will be
52  * thrown --- this is intentional.
53  *
54  * pstate is only used for error location info, and may be NULL.
55  */
56 Type
57 LookupTypeName(ParseState *pstate, const TypeName *typename,
58                            int32 *typmod_p)
59 {
60         Oid                     typoid;
61         HeapTuple       tup;
62         int32           typmod;
63
64         if (typename->names == NIL)
65         {
66                 /* We have the OID already if it's an internally generated TypeName */
67                 typoid = typename->typeid;
68         }
69         else if (typename->pct_type)
70         {
71                 /* Handle %TYPE reference to type of an existing field */
72                 RangeVar   *rel = makeRangeVar(NULL, NULL, typename->location);
73                 char       *field = NULL;
74                 Oid                     relid;
75                 AttrNumber      attnum;
76
77                 /* deconstruct the name list */
78                 switch (list_length(typename->names))
79                 {
80                         case 1:
81                                 ereport(ERROR,
82                                                 (errcode(ERRCODE_SYNTAX_ERROR),
83                                 errmsg("improper %%TYPE reference (too few dotted names): %s",
84                                            NameListToString(typename->names)),
85                                                  parser_errposition(pstate, typename->location)));
86                                 break;
87                         case 2:
88                                 rel->relname = strVal(linitial(typename->names));
89                                 field = strVal(lsecond(typename->names));
90                                 break;
91                         case 3:
92                                 rel->schemaname = strVal(linitial(typename->names));
93                                 rel->relname = strVal(lsecond(typename->names));
94                                 field = strVal(lthird(typename->names));
95                                 break;
96                         case 4:
97                                 rel->catalogname = strVal(linitial(typename->names));
98                                 rel->schemaname = strVal(lsecond(typename->names));
99                                 rel->relname = strVal(lthird(typename->names));
100                                 field = strVal(lfourth(typename->names));
101                                 break;
102                         default:
103                                 ereport(ERROR,
104                                                 (errcode(ERRCODE_SYNTAX_ERROR),
105                                                  errmsg("improper %%TYPE reference (too many dotted names): %s",
106                                                                 NameListToString(typename->names)),
107                                                  parser_errposition(pstate, typename->location)));
108                                 break;
109                 }
110
111                 /* 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);
121
122                 /* this construct should never have an array indicator */
123                 Assert(typename->arrayBounds == NIL);
124
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))));
130         }
131         else
132         {
133                 /* Normal reference to a type name */
134                 char       *schemaname;
135                 char       *typname;
136
137                 /* deconstruct the name list */
138                 DeconstructQualifiedName(typename->names, &schemaname, &typname);
139
140                 if (schemaname)
141                 {
142                         /* Look in specific schema only */
143                         Oid                     namespaceId;
144
145                         namespaceId = LookupExplicitNamespace(schemaname);
146                         typoid = GetSysCacheOid(TYPENAMENSP,
147                                                                         PointerGetDatum(typname),
148                                                                         ObjectIdGetDatum(namespaceId),
149                                                                         0, 0);
150                 }
151                 else
152                 {
153                         /* Unqualified type name, so search the search path */
154                         typoid = TypenameGetTypid(typname);
155                 }
156
157                 /* If an array reference, return the array type instead */
158                 if (typename->arrayBounds != NIL)
159                         typoid = get_array_type(typoid);
160         }
161
162         if (!OidIsValid(typoid))
163         {
164                 if (typmod_p)
165                         *typmod_p = -1;
166                 return NULL;
167         }
168
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);
174
175         typmod = typenameTypeMod(pstate, typename, (Type) tup);
176
177         if (typmod_p)
178                 *typmod_p = typmod;
179
180         return (Type) tup;
181 }
182
183 /*
184  * typenameType - given a TypeName, return a Type structure and typmod
185  *
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.
189  */
190 Type
191 typenameType(ParseState *pstate, const TypeName *typename, int32 *typmod_p)
192 {
193         Type            tup;
194
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;
209 }
210
211 /*
212  * typenameTypeId - given a TypeName, return the type's OID and typmod
213  *
214  * This is equivalent to typenameType, but we only hand back the type OID
215  * not the syscache entry.
216  */
217 Oid
218 typenameTypeId(ParseState *pstate, const TypeName *typename, int32 *typmod_p)
219 {
220         Oid                     typoid;
221         Type            tup;
222
223         tup = typenameType(pstate, typename, typmod_p);
224         typoid = HeapTupleGetOid(tup);
225         ReleaseSysCache(tup);
226
227         return typoid;
228 }
229
230 /*
231  * typenameTypeMod - given a TypeName, return the internal typmod value
232  *
233  * This will throw an error if the TypeName includes type modifiers that are
234  * illegal for the data type.
235  *
236  * The actual type OID represented by the TypeName must already have been
237  * looked up, and is passed as "typ".
238  *
239  * pstate is only used for error location info, and may be NULL.
240  */
241 static int32
242 typenameTypeMod(ParseState *pstate, const TypeName *typename, Type typ)
243 {
244         int32           result;
245         Oid                     typmodin;
246         Datum      *datums;
247         int                     n;
248         ListCell   *l;
249         ArrayType  *arrtypmod;
250         ParseCallbackState pcbstate;
251
252         /* Return prespecified typmod if no typmod expressions */
253         if (typename->typmods == NIL)
254                 return typename->typemod;
255
256         /*
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.
260          */
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)));
267
268         typmodin = ((Form_pg_type) GETSTRUCT(typ))->typmodin;
269
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)));
276
277         /*
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.
281          */
282         datums = (Datum *) palloc(list_length(typename->typmods) * sizeof(Datum));
283         n = 0;
284         foreach(l, typename->typmods)
285         {
286                 Node       *tm = (Node *) lfirst(l);
287                 char       *cstr = NULL;
288
289                 if (IsA(tm, A_Const))
290                 {
291                         A_Const    *ac = (A_Const *) tm;
292
293                         if (IsA(&ac->val, Integer))
294                         {
295                                 cstr = (char *) palloc(32);
296                                 snprintf(cstr, 32, "%ld", (long) ac->val.val.ival);
297                         }
298                         else if (IsA(&ac->val, Float) ||
299                                          IsA(&ac->val, String))
300                         {
301                                 /* we can just use the str field directly. */
302                                 cstr = ac->val.val.str;
303                         }
304                 }
305                 else if (IsA(tm, ColumnRef))
306                 {
307                         ColumnRef  *cr = (ColumnRef *) tm;
308
309                         if (list_length(cr->fields) == 1 &&
310                                 IsA(linitial(cr->fields), String))
311                                 cstr = strVal(linitial(cr->fields));
312                 }
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);
319         }
320
321         /* hardwired knowledge about cstring's representation details here */
322         arrtypmod = construct_array(datums, n, CSTRINGOID,
323                                                                 -2, false, 'c');
324
325         /* arrange to report location if type's typmodin function fails */
326         setup_parser_errposition_callback(&pcbstate, pstate, typename->location);
327
328         result = DatumGetInt32(OidFunctionCall1(typmodin,
329                                                                                         PointerGetDatum(arrtypmod)));
330
331         cancel_parser_errposition_callback(&pcbstate);
332
333         pfree(datums);
334         pfree(arrtypmod);
335
336         return result;
337 }
338
339 /*
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.
343  *
344  * NB: this must work on TypeNames that do not describe any actual type;
345  * it is mostly used for reporting lookup errors.
346  */
347 static void
348 appendTypeNameToBuffer(const TypeName *typename, StringInfo string)
349 {
350         if (typename->names != NIL)
351         {
352                 /* Emit possibly-qualified name as-is */
353                 ListCell   *l;
354
355                 foreach(l, typename->names)
356                 {
357                         if (l != list_head(typename->names))
358                                 appendStringInfoChar(string, '.');
359                         appendStringInfoString(string, strVal(lfirst(l)));
360                 }
361         }
362         else
363         {
364                 /* Look up internally-specified type */
365                 appendStringInfoString(string, format_type_be(typename->typeid));
366         }
367
368         /*
369          * Add decoration as needed, but only for fields considered by
370          * LookupTypeName
371          */
372         if (typename->pct_type)
373                 appendStringInfoString(string, "%TYPE");
374
375         if (typename->arrayBounds != NIL)
376                 appendStringInfoString(string, "[]");
377 }
378
379 /*
380  * TypeNameToString
381  *              Produce a string representing the name of a TypeName.
382  *
383  * NB: this must work on TypeNames that do not describe any actual type;
384  * it is mostly used for reporting lookup errors.
385  */
386 char *
387 TypeNameToString(const TypeName *typename)
388 {
389         StringInfoData string;
390
391         initStringInfo(&string);
392         appendTypeNameToBuffer(typename, &string);
393         return string.data;
394 }
395
396 /*
397  * TypeNameListToString
398  *              Produce a string representing the name(s) of a List of TypeNames
399  */
400 char *
401 TypeNameListToString(List *typenames)
402 {
403         StringInfoData string;
404         ListCell   *l;
405
406         initStringInfo(&string);
407         foreach(l, typenames)
408         {
409                 TypeName   *typename = (TypeName *) lfirst(l);
410
411                 Assert(IsA(typename, TypeName));
412                 if (l != list_head(typenames))
413                         appendStringInfoChar(&string, ',');
414                 appendTypeNameToBuffer(typename, &string);
415         }
416         return string.data;
417 }
418
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)
423 {
424         HeapTuple       tup;
425
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;
432 }
433
434 /* given type (as type struct), return the type OID */
435 Oid
436 typeTypeId(Type tp)
437 {
438         if (tp == NULL)                         /* probably useless */
439                 elog(ERROR, "typeTypeId() called with NULL type struct");
440         return HeapTupleGetOid(tp);
441 }
442
443 /* given type (as type struct), return the length of type */
444 int16
445 typeLen(Type t)
446 {
447         Form_pg_type typ;
448
449         typ = (Form_pg_type) GETSTRUCT(t);
450         return typ->typlen;
451 }
452
453 /* given type (as type struct), return the value of its 'byval' attribute.*/
454 bool
455 typeByVal(Type t)
456 {
457         Form_pg_type typ;
458
459         typ = (Form_pg_type) GETSTRUCT(t);
460         return typ->typbyval;
461 }
462
463 /* given type (as type struct), return the name of type */
464 char *
465 typeTypeName(Type t)
466 {
467         Form_pg_type typ;
468
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));
472 }
473
474 Oid
475 typeTypeRelid(Type typ)
476 {
477         Form_pg_type typtup;
478
479         typtup = (Form_pg_type) GETSTRUCT(typ);
480
481         return typtup->typrelid;
482 }
483
484 /*
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).
488  */
489 Datum
490 stringTypeDatum(Type tp, char *string, int32 atttypmod)
491 {
492         Form_pg_type typform = (Form_pg_type) GETSTRUCT(tp);
493         Oid                     typinput = typform->typinput;
494         Oid                     typioparam = getTypeIOParam(tp);
495         Datum           result;
496
497         result = OidInputFunctionCall(typinput, string,
498                                                                   typioparam, atttypmod);
499
500 #ifdef RANDOMIZE_ALLOCATED_MEMORY
501         /*
502          * For pass-by-reference data types, repeat the conversion to see if the
503          * input function leaves any uninitialized bytes in the result.  We can
504          * only detect that reliably if RANDOMIZE_ALLOCATED_MEMORY is enabled,
505          * so we don't bother testing otherwise.  The reason we don't want any
506          * instability in the input function is that comparison of Const nodes
507          * relies on bytewise comparison of the datums, so if the input function
508          * leaves garbage then subexpressions that should be identical may not get
509          * recognized as such.  See pgsql-hackers discussion of 2008-04-04.
510          */
511         if (string && !typform->typbyval)
512         {
513                 Datum           result2;
514
515                 result2 = OidInputFunctionCall(typinput, string,
516                                                                            typioparam, atttypmod);
517                 if (!datumIsEqual(result, result2, typform->typbyval, typform->typlen))
518                         elog(WARNING, "type %s has unstable input conversion for \"%s\"",
519                                  NameStr(typform->typname), string);
520         }
521 #endif
522
523         return result;
524 }
525
526 /* given a typeid, return the type's typrelid (associated relation, if any) */
527 Oid
528 typeidTypeRelid(Oid type_id)
529 {
530         HeapTuple       typeTuple;
531         Form_pg_type type;
532         Oid                     result;
533
534         typeTuple = SearchSysCache(TYPEOID,
535                                                            ObjectIdGetDatum(type_id),
536                                                            0, 0, 0);
537         if (!HeapTupleIsValid(typeTuple))
538                 elog(ERROR, "cache lookup failed for type %u", type_id);
539
540         type = (Form_pg_type) GETSTRUCT(typeTuple);
541         result = type->typrelid;
542         ReleaseSysCache(typeTuple);
543         return result;
544 }
545
546 /*
547  * error context callback for parse failure during parseTypeString()
548  */
549 static void
550 pts_error_callback(void *arg)
551 {
552         const char *str = (const char *) arg;
553
554         errcontext("invalid type name \"%s\"", str);
555
556         /*
557          * Currently we just suppress any syntax error position report, rather
558          * than transforming to an "internal query" error.      It's unlikely that a
559          * type name is complex enough to need positioning.
560          */
561         errposition(0);
562 }
563
564 /*
565  * Given a string that is supposed to be a SQL-compatible type declaration,
566  * such as "int4" or "integer" or "character varying(32)", parse
567  * the string and convert it to a type OID and type modifier.
568  */
569 void
570 parseTypeString(const char *str, Oid *type_id, int32 *typmod_p)
571 {
572         StringInfoData buf;
573         List       *raw_parsetree_list;
574         SelectStmt *stmt;
575         ResTarget  *restarget;
576         TypeCast   *typecast;
577         TypeName   *typename;
578         ErrorContextCallback ptserrcontext;
579
580         /* make sure we give useful error for empty input */
581         if (strspn(str, " \t\n\r\f") == strlen(str))
582                 goto fail;
583
584         initStringInfo(&buf);
585         appendStringInfo(&buf, "SELECT NULL::%s", str);
586
587         /*
588          * Setup error traceback support in case of ereport() during parse
589          */
590         ptserrcontext.callback = pts_error_callback;
591         ptserrcontext.arg = (void *) str;
592         ptserrcontext.previous = error_context_stack;
593         error_context_stack = &ptserrcontext;
594
595         raw_parsetree_list = raw_parser(buf.data);
596
597         error_context_stack = ptserrcontext.previous;
598
599         /*
600          * Make sure we got back exactly what we expected and no more; paranoia is
601          * justified since the string might contain anything.
602          */
603         if (list_length(raw_parsetree_list) != 1)
604                 goto fail;
605         stmt = (SelectStmt *) linitial(raw_parsetree_list);
606         if (stmt == NULL ||
607                 !IsA(stmt, SelectStmt) ||
608                 stmt->distinctClause != NIL ||
609                 stmt->intoClause != NULL ||
610                 stmt->fromClause != NIL ||
611                 stmt->whereClause != NULL ||
612                 stmt->groupClause != NIL ||
613                 stmt->havingClause != NULL ||
614                 stmt->windowClause != NIL ||
615                 stmt->withClause != NULL ||
616                 stmt->valuesLists != NIL ||
617                 stmt->sortClause != NIL ||
618                 stmt->limitOffset != NULL ||
619                 stmt->limitCount != NULL ||
620                 stmt->lockingClause != NIL ||
621                 stmt->op != SETOP_NONE)
622                 goto fail;
623         if (list_length(stmt->targetList) != 1)
624                 goto fail;
625         restarget = (ResTarget *) linitial(stmt->targetList);
626         if (restarget == NULL ||
627                 !IsA(restarget, ResTarget) ||
628                 restarget->name != NULL ||
629                 restarget->indirection != NIL)
630                 goto fail;
631         typecast = (TypeCast *) restarget->val;
632         if (typecast == NULL ||
633                 !IsA(typecast, TypeCast) ||
634                 typecast->arg == NULL ||
635                 !IsA(typecast->arg, A_Const))
636                 goto fail;
637         typename = typecast->typename;
638         if (typename == NULL ||
639                 !IsA(typename, TypeName))
640                 goto fail;
641         if (typename->setof)
642                 goto fail;
643
644         *type_id = typenameTypeId(NULL, typename, typmod_p);
645
646         pfree(buf.data);
647
648         return;
649
650 fail:
651         ereport(ERROR,
652                         (errcode(ERRCODE_SYNTAX_ERROR),
653                          errmsg("invalid type name \"%s\"", str)));
654 }