]> granicus.if.org Git - postgresql/blob - src/backend/parser/parse_coerce.c
> Marko Kreen <marko@l-t.ee> writes:
[postgresql] / src / backend / parser / parse_coerce.c
1 /*-------------------------------------------------------------------------
2  *
3  * parse_coerce.c
4  *              handle type coercions/conversions for parser
5  *
6  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.59 2001/06/23 22:23:49 momjian Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16
17 #include "catalog/pg_proc.h"
18 #include "optimizer/clauses.h"
19 #include "parser/parse_coerce.h"
20 #include "parser/parse_expr.h"
21 #include "parser/parse_func.h"
22 #include "parser/parse_type.h"
23 #include "utils/builtins.h"
24 #include "utils/syscache.h"
25
26 Oid                     DemoteType(Oid inType);
27 Oid                     PromoteTypeToNext(Oid inType);
28
29 static Oid      PreferredType(CATEGORY category, Oid type);
30
31
32 /* coerce_type()
33  * Convert a function argument to a different type.
34  */
35 Node *
36 coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
37                         Oid targetTypeId, int32 atttypmod)
38 {
39         Node       *result;
40
41         if (targetTypeId == inputTypeId ||
42                 targetTypeId == InvalidOid ||
43                 node == NULL)
44         {
45                 /* no conversion needed */
46                 result = node;
47         }
48         else if (inputTypeId == UNKNOWNOID && IsA(node, Const))
49         {
50
51                 /*
52                  * Input is a string constant with previously undetermined type.
53                  * Apply the target type's typinput function to it to produce a
54                  * constant of the target type.
55                  *
56                  * NOTE: this case cannot be folded together with the other
57                  * constant-input case, since the typinput function does not
58                  * necessarily behave the same as a type conversion function. For
59                  * example, int4's typinput function will reject "1.2", whereas
60                  * float-to-int type conversion will round to integer.
61                  *
62                  * XXX if the typinput function is not cachable, we really ought to
63                  * postpone evaluation of the function call until runtime. But
64                  * there is no way to represent a typinput function call as an
65                  * expression tree, because C-string values are not Datums.
66                  */
67                 Const      *con = (Const *) node;
68                 Const      *newcon = makeNode(Const);
69                 Type            targetType = typeidType(targetTypeId);
70
71                 newcon->consttype = targetTypeId;
72                 newcon->constlen = typeLen(targetType);
73                 newcon->constbyval = typeByVal(targetType);
74                 newcon->constisnull = con->constisnull;
75                 newcon->constisset = false;
76
77                 if (!con->constisnull)
78                 {
79                         /* We know the source constant is really of type 'text' */
80                         char       *val = DatumGetCString(DirectFunctionCall1(textout,
81                                                                                                            con->constvalue));
82
83                         newcon->constvalue = stringTypeDatum(targetType, val, atttypmod);
84                         pfree(val);
85                 }
86
87                 ReleaseSysCache(targetType);
88
89                 result = (Node *) newcon;
90         }
91         else if (IS_BINARY_COMPATIBLE(inputTypeId, targetTypeId))
92         {
93
94                 /*
95                  * We don't really need to do a conversion, but we do need to
96                  * attach a RelabelType node so that the expression will be seen
97                  * to have the intended type when inspected by higher-level code.
98                  */
99                 RelabelType *relabel = makeNode(RelabelType);
100
101                 relabel->arg = node;
102                 relabel->resulttype = targetTypeId;
103
104                 /*
105                  * XXX could we label result with exprTypmod(node) instead of
106                  * default -1 typmod, to save a possible length-coercion later?
107                  * Would work if both types have same interpretation of typmod,
108                  * which is likely but not certain.
109                  */
110                 relabel->resulttypmod = -1;
111
112                 result = (Node *) relabel;
113         }
114         else if (typeInheritsFrom(inputTypeId, targetTypeId))
115         {
116                 /* Input class type is a subclass of target, so nothing to do */
117                 result = node;
118         }
119         else
120         {
121
122                 /*
123                  * Otherwise, find the appropriate type conversion function
124                  * (caller should have determined that there is one), and generate
125                  * an expression tree representing run-time application of the
126                  * conversion function.
127                  */
128                 FuncCall   *n = makeNode(FuncCall);
129
130                 n->funcname = typeidTypeName(targetTypeId);
131                 n->args = makeList1(node);
132                 n->agg_star = false;
133                 n->agg_distinct = false;
134
135                 result = transformExpr(pstate, (Node *) n, EXPR_COLUMN_FIRST);
136
137                 /* safety check that we got the right thing */
138                 if (exprType(result) != targetTypeId)
139                         elog(ERROR, "coerce_type: conversion function %s produced %s",
140                                  typeidTypeName(targetTypeId),
141                                  typeidTypeName(exprType(result)));
142
143                 /*
144                  * If the input is a constant, apply the type conversion function
145                  * now instead of delaying to runtime.  (We could, of course, just
146                  * leave this to be done during planning/optimization; but it's a
147                  * very frequent special case, and we save cycles in the rewriter
148                  * if we fold the expression now.)
149                  *
150                  * Note that no folding will occur if the conversion function is not
151                  * marked 'iscachable'.
152                  *
153                  * HACK: if constant is NULL, don't fold it here.  This is needed by
154                  * make_subplan(), which calls this routine on placeholder Const
155                  * nodes that mustn't be collapsed.  (It'd be a lot cleaner to
156                  * make a separate node type for that purpose...)
157                  */
158                 if (IsA(node, Const) &&!((Const *) node)->constisnull)
159                         result = eval_const_expressions(result);
160         }
161
162         return result;
163 }
164
165
166 /* can_coerce_type()
167  * Can input_typeids be coerced to func_typeids?
168  *
169  * There are a few types which are known apriori to be convertible.
170  * We will check for those cases first, and then look for possible
171  *      conversion functions.
172  *
173  * Notes:
174  * This uses the same mechanism as the CAST() SQL construct in gram.y.
175  * We should also check the function return type on candidate conversion
176  *      routines just to be safe but we do not do that yet...
177  * - thomas 1998-03-31
178  */
179 bool
180 can_coerce_type(int nargs, Oid *input_typeids, Oid *func_typeids)
181 {
182         int                     i;
183         HeapTuple       ftup;
184         Form_pg_proc pform;
185         Oid                     oid_array[FUNC_MAX_ARGS];
186
187         /* run through argument list... */
188         for (i = 0; i < nargs; i++)
189         {
190                 Oid                     inputTypeId = input_typeids[i];
191                 Oid                     targetTypeId = func_typeids[i];
192
193                 /* no problem if same type */
194                 if (inputTypeId == targetTypeId)
195                         continue;
196
197                 /*
198                  * one of the known-good transparent conversions? then drop
199                  * through...
200                  */
201                 if (IS_BINARY_COMPATIBLE(inputTypeId, targetTypeId))
202                         continue;
203
204                 /* don't know what to do for the output type? then quit... */
205                 if (targetTypeId == InvalidOid)
206                         return false;
207                 /* don't know what to do for the input type? then quit... */
208                 if (inputTypeId == InvalidOid)
209                         return false;
210
211                 /*
212                  * If input is an untyped string constant, assume we can convert
213                  * it to anything except a class type.
214                  */
215                 if (inputTypeId == UNKNOWNOID)
216                 {
217                         if (ISCOMPLEX(targetTypeId))
218                                 return false;
219                         continue;
220                 }
221
222                 /*
223                  * If input is a class type that inherits from target, no problem
224                  */
225                 if (typeInheritsFrom(inputTypeId, targetTypeId))
226                         continue;
227
228                 /* don't choke on references to no-longer-existing types */
229                 if (!typeidIsValid(inputTypeId))
230                         return false;
231                 if (!typeidIsValid(targetTypeId))
232                         return false;
233
234                 /*
235                  * Else, try for explicit conversion using functions: look for a
236                  * single-argument function named with the target type name and
237                  * accepting the source type.
238                  */
239                 MemSet(oid_array, 0, FUNC_MAX_ARGS * sizeof(Oid));
240                 oid_array[0] = inputTypeId;
241
242                 ftup = SearchSysCache(PROCNAME,
243                                                    PointerGetDatum(typeidTypeName(targetTypeId)),
244                                                           Int32GetDatum(1),
245                                                           PointerGetDatum(oid_array),
246                                                           0);
247                 if (!HeapTupleIsValid(ftup))
248                         return false;
249                 /* Make sure the function's result type is as expected, too */
250                 pform = (Form_pg_proc) GETSTRUCT(ftup);
251                 if (pform->prorettype != targetTypeId)
252                 {
253                         ReleaseSysCache(ftup);
254                         return false;
255                 }
256                 ReleaseSysCache(ftup);
257         }
258
259         return true;
260 }
261
262 /* coerce_type_typmod()
263  * Force a value to a particular typmod, if meaningful and possible.
264  *
265  * This is applied to values that are going to be stored in a relation
266  * (where we have an atttypmod for the column) as well as values being
267  * explicitly CASTed (where the typmod comes from the target type spec).
268  *
269  * The caller must have already ensured that the value is of the correct
270  * type, typically by applying coerce_type.
271  *
272  * If the target column type possesses a function named for the type
273  * and having parameter signature (columntype, int4), we assume that
274  * the type requires coercion to its own length and that the said
275  * function should be invoked to do that.
276  *
277  * "bpchar" (ie, char(N)) and "numeric" are examples of such types.
278  */
279 Node *
280 coerce_type_typmod(ParseState *pstate, Node *node,
281                                    Oid targetTypeId, int32 atttypmod)
282 {
283         char       *funcname;
284         Oid                     oid_array[FUNC_MAX_ARGS];
285
286         /*
287          * We assume that only typmod values greater than 0 indicate a forced
288          * conversion is necessary.
289          */
290         if (atttypmod <= 0 ||
291                 atttypmod == exprTypmod(node))
292                 return node;
293
294         funcname = typeidTypeName(targetTypeId);
295         MemSet(oid_array, 0, FUNC_MAX_ARGS * sizeof(Oid));
296         oid_array[0] = targetTypeId;
297         oid_array[1] = INT4OID;
298
299         /* attempt to find with arguments exactly as specified... */
300         if (SearchSysCacheExists(PROCNAME,
301                                                          PointerGetDatum(funcname),
302                                                          Int32GetDatum(2),
303                                                          PointerGetDatum(oid_array),
304                                                          0))
305         {
306                 A_Const    *cons = makeNode(A_Const);
307                 FuncCall   *func = makeNode(FuncCall);
308
309                 cons->val.type = T_Integer;
310                 cons->val.val.ival = atttypmod;
311
312                 func->funcname = funcname;
313                 func->args = makeList2(node, cons);
314                 func->agg_star = false;
315                 func->agg_distinct = false;
316
317                 node = transformExpr(pstate, (Node *) func, EXPR_COLUMN_FIRST);
318         }
319
320         return node;
321 }
322
323
324 /* coerce_to_boolean()
325  *              Coerce an argument of a construct that requires boolean input
326  *              (AND, OR, NOT, etc).
327  *
328  * If successful, update *pnode to be the transformed argument (if any
329  * transformation is needed), and return TRUE.  If fail, return FALSE.
330  * (The caller must check for FALSE and emit a suitable error message.)
331  */
332 bool
333 coerce_to_boolean(ParseState *pstate, Node **pnode)
334 {
335         Oid                     inputTypeId = exprType(*pnode);
336         Oid                     targetTypeId;
337
338         if (inputTypeId == BOOLOID)
339                 return true;                    /* no work */
340         targetTypeId = BOOLOID;
341         if (! can_coerce_type(1, &inputTypeId, &targetTypeId))
342                 return false;                   /* fail, but let caller choose error msg */
343         *pnode = coerce_type(pstate, *pnode, inputTypeId, targetTypeId, -1);
344         return true;
345 }
346
347
348 /* select_common_type()
349  *              Determine the common supertype of a list of input expression types.
350  *              This is used for determining the output type of CASE and UNION
351  *              constructs.
352  *
353  * typeids is a nonempty integer list of type OIDs.  Note that earlier items
354  * in the list will be preferred if there is doubt.
355  * 'context' is a phrase to use in the error message if we fail to select
356  * a usable type.
357  *
358  * XXX this code is WRONG, since (for example) given the input (int4,int8)
359  * it will select int4, whereas according to SQL92 clause 9.3 the correct
360  * answer is clearly int8.      To fix this we need a notion of a promotion
361  * hierarchy within type categories --- something more complete than
362  * just a single preferred type.
363  */
364 Oid
365 select_common_type(List *typeids, const char *context)
366 {
367         Oid                     ptype;
368         CATEGORY        pcategory;
369         List       *l;
370
371         Assert(typeids != NIL);
372         ptype = (Oid) lfirsti(typeids);
373         pcategory = TypeCategory(ptype);
374         foreach(l, lnext(typeids))
375         {
376                 Oid                     ntype = (Oid) lfirsti(l);
377
378                 /* move on to next one if no new information... */
379                 if (ntype && (ntype != UNKNOWNOID) && (ntype != ptype))
380                 {
381                         if (!ptype || ptype == UNKNOWNOID)
382                         {
383                                 /* so far, only nulls so take anything... */
384                                 ptype = ntype;
385                                 pcategory = TypeCategory(ptype);
386                         }
387                         else if (TypeCategory(ntype) != pcategory)
388                         {
389
390                                 /*
391                                  * both types in different categories? then not much
392                                  * hope...
393                                  */
394                                 elog(ERROR, "%s types \"%s\" and \"%s\" not matched",
395                                   context, typeidTypeName(ptype), typeidTypeName(ntype));
396                         }
397                         else if (IsPreferredType(pcategory, ntype)
398                                          && !IsPreferredType(pcategory, ptype)
399                                          && can_coerce_type(1, &ptype, &ntype))
400                         {
401
402                                 /*
403                                  * new one is preferred and can convert? then take it...
404                                  */
405                                 ptype = ntype;
406                                 pcategory = TypeCategory(ptype);
407                         }
408                 }
409         }
410
411         /*
412          * If all the inputs were UNKNOWN type --- ie, unknown-type literals
413          * --- then resolve as type TEXT.  This situation comes up with
414          * constructs like SELECT (CASE WHEN foo THEN 'bar' ELSE 'baz' END);
415          * SELECT 'foo' UNION SELECT 'bar'; It might seem desirable to leave
416          * the construct's output type as UNKNOWN, but that really doesn't
417          * work, because we'd probably end up needing a runtime coercion from
418          * UNKNOWN to something else, and we usually won't have it.  We need
419          * to coerce the unknown literals while they are still literals, so a
420          * decision has to be made now.
421          */
422         if (ptype == UNKNOWNOID)
423                 ptype = TEXTOID;
424
425         return ptype;
426 }
427
428 /* coerce_to_common_type()
429  *              Coerce an expression to the given type.
430  *
431  * This is used following select_common_type() to coerce the individual
432  * expressions to the desired type.  'context' is a phrase to use in the
433  * error message if we fail to coerce.
434  *
435  * NOTE: pstate may be NULL.
436  */
437 Node *
438 coerce_to_common_type(ParseState *pstate, Node *node,
439                                           Oid targetTypeId,
440                                           const char *context)
441 {
442         Oid                     inputTypeId = exprType(node);
443
444         if (inputTypeId == targetTypeId)
445                 return node;                    /* no work */
446         if (can_coerce_type(1, &inputTypeId, &targetTypeId))
447                 node = coerce_type(pstate, node, inputTypeId, targetTypeId, -1);
448         else
449         {
450                 elog(ERROR, "%s unable to convert to type \"%s\"",
451                          context, typeidTypeName(targetTypeId));
452         }
453         return node;
454 }
455
456
457 /* TypeCategory()
458  * Assign a category to the specified OID.
459  */
460 CATEGORY
461 TypeCategory(Oid inType)
462 {
463         CATEGORY        result;
464
465         switch (inType)
466         {
467                 case (BOOLOID):
468                         result = BOOLEAN_TYPE;
469                         break;
470
471                 case (CHAROID):
472                 case (NAMEOID):
473                 case (BYTEAOID):
474                 case (BPCHAROID):
475                 case (VARCHAROID):
476                 case (TEXTOID):
477                         result = STRING_TYPE;
478                         break;
479
480                 case (BITOID):
481                 case (VARBITOID):
482                         result = BITSTRING_TYPE;
483                         break;
484
485                 case (OIDOID):
486                 case (REGPROCOID):
487                 case (INT2OID):
488                 case (INT4OID):
489                 case (INT8OID):
490                 case (FLOAT4OID):
491                 case (FLOAT8OID):
492                 case (NUMERICOID):
493                 case (CASHOID):
494                         result = NUMERIC_TYPE;
495                         break;
496
497                 case (DATEOID):
498                 case (TIMEOID):
499                 case (TIMETZOID):
500                 case (ABSTIMEOID):
501                 case (TIMESTAMPOID):
502                         result = DATETIME_TYPE;
503                         break;
504
505                 case (RELTIMEOID):
506                 case (TINTERVALOID):
507                 case (INTERVALOID):
508                         result = TIMESPAN_TYPE;
509                         break;
510
511                 case (POINTOID):
512                 case (LSEGOID):
513                 case (PATHOID):
514                 case (BOXOID):
515                 case (POLYGONOID):
516                 case (LINEOID):
517                 case (CIRCLEOID):
518                         result = GEOMETRIC_TYPE;
519                         break;
520
521                 case (INETOID):
522                 case (CIDROID):
523                         result = NETWORK_TYPE;
524                         break;
525
526                 case (UNKNOWNOID):
527                 case (InvalidOid):
528                         result = UNKNOWN_TYPE;
529                         break;
530
531                 default:
532                         result = USER_TYPE;
533                         break;
534         }
535         return result;
536 }       /* TypeCategory() */
537
538
539 /* IsPreferredType()
540  * Check if this type is a preferred type.
541  */
542 bool
543 IsPreferredType(CATEGORY category, Oid type)
544 {
545         return type == PreferredType(category, type);
546 }       /* IsPreferredType() */
547
548
549 /* PreferredType()
550  * Return the preferred type OID for the specified category.
551  */
552 static Oid
553 PreferredType(CATEGORY category, Oid type)
554 {
555         Oid                     result;
556
557         switch (category)
558         {
559                 case (BOOLEAN_TYPE):
560                         result = BOOLOID;
561                         break;
562
563                 case (STRING_TYPE):
564                         result = TEXTOID;
565                         break;
566
567                 case (BITSTRING_TYPE):
568                         result = VARBITOID;
569                         break;
570
571                 case (NUMERIC_TYPE):
572                         if (type == OIDOID)
573                                 result = OIDOID;
574                         else if (type == NUMERICOID)
575                                 result = NUMERICOID;
576                         else
577                                 result = FLOAT8OID;
578                         break;
579
580                 case (DATETIME_TYPE):
581                         result = TIMESTAMPOID;
582                         break;
583
584                 case (TIMESPAN_TYPE):
585                         result = INTERVALOID;
586                         break;
587
588                 case (NETWORK_TYPE):
589                         result = INETOID;
590                         break;
591
592                 case (GEOMETRIC_TYPE):
593                 case (USER_TYPE):
594                         result = type;
595                         break;
596
597                 default:
598                         result = UNKNOWNOID;
599                         break;
600         }
601         return result;
602 }       /* PreferredType() */
603
604
605 #ifdef NOT_USED
606 Oid
607 PromoteTypeToNext(Oid inType)
608 {
609         Oid                     result;
610
611         switch (inType)
612         {
613                 case (CHAROID):
614                 case (BPCHAROID):
615                         result = VARCHAROID;
616                         break;
617
618                 case (BYTEAOID):
619                 case (VARCHAROID):
620                         result = TEXTOID;
621                         break;
622
623                 case (INT2OID):
624                 case (CASHOID):
625                         result = INT4OID;
626                         break;
627
628                 case (INT4OID):
629                 case (INT8OID):
630                 case (FLOAT4OID):
631                         result = FLOAT8OID;
632                         break;
633
634                 case (NUMERICOID):
635                         result = NUMERICOID;
636                         break;
637
638                 case (DATEOID):
639                 case (ABSTIMEOID):
640                         result = TIMESTAMPOID;
641                         break;
642
643                 case (TIMEOID):
644                 case (RELTIMEOID):
645                         result = INTERVALOID;
646                         break;
647
648                 case (BOOLOID):
649                 case (TEXTOID):
650                 case (FLOAT8OID):
651                 case (TIMESTAMPOID):
652                 case (INTERVALOID):
653                 default:
654                         result = inType;
655                         break;
656         }
657         return result;
658 }       /* PromoteTypeToNext() */
659
660
661 Oid
662 DemoteType(Oid inType)
663 {
664         Oid                     result;
665
666         switch (inType)
667         {
668                 case (FLOAT4OID):
669                 case (FLOAT8OID):
670                         result = INT4OID;
671                         break;
672
673                 default:
674                         result = inType;
675                         break;
676         }
677         return result;
678 }       /* DemoteType() */
679
680
681 Oid
682 PromoteLesserType(Oid inType1, Oid inType2, Oid *newType1, Oid *newType2)
683 {
684         Oid                     result;
685
686         if (inType1 == inType2)
687         {
688                 result = PromoteTypeToNext(inType1);
689                 inType1 = result;
690                 *arg2 = result;
691                 return result;
692         }
693
694         kind1 = ClassifyType(inType1);
695         kind2 = ClassifyType(*arg2);
696         if (kind1 != kind2)
697         {
698                 *newType1 = inType1;
699                 *newType2 = inType2;
700                 result = InvalidOid;
701         }
702
703         isBuiltIn1 = IS_BUILTIN_TYPE(inType1);
704         isBuiltIn2 = IS_BUILTIN_TYPE(*arg2);
705
706         if (isBuiltIn1 && isBuiltIn2)
707         {
708                 switch (*arg1)
709                 {
710                         case (CHAROID):
711                                 switch (*arg2)
712                                 {
713                                         case (BYTEAOID):
714                                         case (BPCHAROID):
715                                         case (VARCHAROID):
716                                         case (TEXTOID):
717
718                                         case (INT2OID):
719                                         case (INT4OID):
720                                         case (FLOAT4OID):
721                                         case (FLOAT8OID):
722                                         case (CASHOID):
723
724                                         case (POINTOID):
725                                         case (LSEGOID):
726                                         case (LINEOID):
727                                         case (BOXOID):
728                                         case (PATHOID):
729                                         case (CIRCLEOID):
730                                         case (POLYGONOID):
731
732                                         case (InvalidOid):
733                                         case (UNKNOWNOID):
734                                         case (BOOLOID):
735                                         default:
736                                                 *arg1 = InvalidOid;
737                                                 *arg2 = InvalidOid;
738                                                 result = InvalidOid;
739                                 }
740                 }
741         }
742         else if (isBuiltIn1 && !isBuiltIn2)
743         {
744                 if ((promotedType = PromoteBuiltInType(*arg1)) != *arg1)
745                 {
746                         *arg1 = promotedType;
747                         return promotedType;
748                 }
749                 else if (CanCoerceType(*arg1, *arg2))
750                 {
751                         *arg1 = *arg2;
752                         return *arg2;
753                 }
754         }
755         else if (!isBuiltIn1 && isBuiltIn2)
756         {
757                 if ((promotedType = PromoteBuiltInType(*arg2)) != *arg2)
758                 {
759                         *arg2 = promotedType;
760                         return promotedType;
761                 }
762                 else if (CanCoerceType(*arg2, *arg1))
763                 {
764                         *arg2 = *arg1;
765                         return *arg1;
766                 }
767         }
768
769
770         if (*arg2 == InvalidOid)
771                 return InvalidOid;
772
773         switch (*arg1)
774         {
775                 case (CHAROID):
776                         switch (*arg2)
777                         {
778                                 case (BYTEAOID):
779                                 case (BPCHAROID):
780                                 case (VARCHAROID):
781                                 case (TEXTOID):
782
783                                 case (INT2OID):
784                                 case (INT4OID):
785                                 case (FLOAT4OID):
786                                 case (FLOAT8OID):
787                                 case (CASHOID):
788
789                                 case (POINTOID):
790                                 case (LSEGOID):
791                                 case (LINEOID):
792                                 case (BOXOID):
793                                 case (PATHOID):
794                                 case (CIRCLEOID):
795                                 case (POLYGONOID):
796
797                                 case (InvalidOid):
798                                 case (UNKNOWNOID):
799                                 case (BOOLOID):
800                                 default:
801                                         *arg1 = InvalidOid;
802                                         *arg2 = InvalidOid;
803                                         result = InvalidOid;
804                         }
805         }
806 }
807
808 #endif