00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "postgres.h"
00016
00017 #include "access/htup_details.h"
00018 #include "catalog/pg_cast.h"
00019 #include "catalog/pg_class.h"
00020 #include "catalog/pg_inherits_fn.h"
00021 #include "catalog/pg_proc.h"
00022 #include "catalog/pg_type.h"
00023 #include "nodes/makefuncs.h"
00024 #include "nodes/nodeFuncs.h"
00025 #include "parser/parse_coerce.h"
00026 #include "parser/parse_relation.h"
00027 #include "parser/parse_type.h"
00028 #include "utils/builtins.h"
00029 #include "utils/lsyscache.h"
00030 #include "utils/syscache.h"
00031 #include "utils/typcache.h"
00032
00033
00034 static Node *coerce_type_typmod(Node *node,
00035 Oid targetTypeId, int32 targetTypMod,
00036 CoercionForm cformat, int location,
00037 bool isExplicit, bool hideInputCoercion);
00038 static void hide_coercion_node(Node *node);
00039 static Node *build_coercion_expression(Node *node,
00040 CoercionPathType pathtype,
00041 Oid funcId,
00042 Oid targetTypeId, int32 targetTypMod,
00043 CoercionForm cformat, int location,
00044 bool isExplicit);
00045 static Node *coerce_record_to_complex(ParseState *pstate, Node *node,
00046 Oid targetTypeId,
00047 CoercionContext ccontext,
00048 CoercionForm cformat,
00049 int location);
00050 static bool is_complex_array(Oid typid);
00051 static bool typeIsOfTypedTable(Oid reltypeId, Oid reloftypeId);
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 Node *
00076 coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype,
00077 Oid targettype, int32 targettypmod,
00078 CoercionContext ccontext,
00079 CoercionForm cformat,
00080 int location)
00081 {
00082 Node *result;
00083 Node *origexpr;
00084
00085 if (!can_coerce_type(1, &exprtype, &targettype, ccontext))
00086 return NULL;
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 origexpr = expr;
00098 while (expr && IsA(expr, CollateExpr))
00099 expr = (Node *) ((CollateExpr *) expr)->arg;
00100
00101 result = coerce_type(pstate, expr, exprtype,
00102 targettype, targettypmod,
00103 ccontext, cformat, location);
00104
00105
00106
00107
00108
00109
00110 result = coerce_type_typmod(result,
00111 targettype, targettypmod,
00112 cformat, location,
00113 (cformat != COERCE_IMPLICIT_CAST),
00114 (result != expr && !IsA(result, Const)));
00115
00116 if (expr != origexpr)
00117 {
00118
00119 CollateExpr *coll = (CollateExpr *) origexpr;
00120 CollateExpr *newcoll = makeNode(CollateExpr);
00121
00122 newcoll->arg = (Expr *) result;
00123 newcoll->collOid = coll->collOid;
00124 newcoll->location = coll->location;
00125 result = (Node *) newcoll;
00126 }
00127
00128 return result;
00129 }
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 Node *
00155 coerce_type(ParseState *pstate, Node *node,
00156 Oid inputTypeId, Oid targetTypeId, int32 targetTypeMod,
00157 CoercionContext ccontext, CoercionForm cformat, int location)
00158 {
00159 Node *result;
00160 CoercionPathType pathtype;
00161 Oid funcId;
00162
00163 if (targetTypeId == inputTypeId ||
00164 node == NULL)
00165 {
00166
00167 return node;
00168 }
00169 if (targetTypeId == ANYOID ||
00170 targetTypeId == ANYELEMENTOID ||
00171 targetTypeId == ANYNONARRAYOID)
00172 {
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 return node;
00186 }
00187 if (targetTypeId == ANYARRAYOID ||
00188 targetTypeId == ANYENUMOID ||
00189 targetTypeId == ANYRANGEOID)
00190 {
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 if (inputTypeId != UNKNOWNOID)
00207 {
00208 Oid baseTypeId = getBaseType(inputTypeId);
00209
00210 if (baseTypeId != inputTypeId)
00211 {
00212 RelabelType *r = makeRelabelType((Expr *) node,
00213 baseTypeId, -1,
00214 InvalidOid,
00215 cformat);
00216
00217 r->location = location;
00218 return (Node *) r;
00219 }
00220
00221 return node;
00222 }
00223 }
00224 if (inputTypeId == UNKNOWNOID && IsA(node, Const))
00225 {
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243 Const *con = (Const *) node;
00244 Const *newcon = makeNode(Const);
00245 Oid baseTypeId;
00246 int32 baseTypeMod;
00247 int32 inputTypeMod;
00248 Type targetType;
00249 ParseCallbackState pcbstate;
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 baseTypeMod = targetTypeMod;
00260 baseTypeId = getBaseTypeAndTypmod(targetTypeId, &baseTypeMod);
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271 if (baseTypeId == INTERVALOID)
00272 inputTypeMod = baseTypeMod;
00273 else
00274 inputTypeMod = -1;
00275
00276 targetType = typeidType(baseTypeId);
00277
00278 newcon->consttype = baseTypeId;
00279 newcon->consttypmod = inputTypeMod;
00280 newcon->constcollid = typeTypeCollation(targetType);
00281 newcon->constlen = typeLen(targetType);
00282 newcon->constbyval = typeByVal(targetType);
00283 newcon->constisnull = con->constisnull;
00284
00285
00286
00287
00288
00289
00290 newcon->location = con->location;
00291
00292
00293
00294
00295
00296 setup_parser_errposition_callback(&pcbstate, pstate, con->location);
00297
00298
00299
00300
00301
00302 if (!con->constisnull)
00303 newcon->constvalue = stringTypeDatum(targetType,
00304 DatumGetCString(con->constvalue),
00305 inputTypeMod);
00306 else
00307 newcon->constvalue = stringTypeDatum(targetType,
00308 NULL,
00309 inputTypeMod);
00310
00311 cancel_parser_errposition_callback(&pcbstate);
00312
00313 result = (Node *) newcon;
00314
00315
00316 if (baseTypeId != targetTypeId)
00317 result = coerce_to_domain(result,
00318 baseTypeId, baseTypeMod,
00319 targetTypeId,
00320 cformat, location, false, false);
00321
00322 ReleaseSysCache(targetType);
00323
00324 return result;
00325 }
00326 if (IsA(node, Param) &&
00327 pstate != NULL && pstate->p_coerce_param_hook != NULL)
00328 {
00329
00330
00331
00332
00333
00334 result = (*pstate->p_coerce_param_hook) (pstate,
00335 (Param *) node,
00336 targetTypeId,
00337 targetTypeMod,
00338 location);
00339 if (result)
00340 return result;
00341 }
00342 if (IsA(node, CollateExpr))
00343 {
00344
00345
00346
00347
00348
00349
00350 CollateExpr *coll = (CollateExpr *) node;
00351 CollateExpr *newcoll = makeNode(CollateExpr);
00352
00353 newcoll->arg = (Expr *)
00354 coerce_type(pstate, (Node *) coll->arg,
00355 inputTypeId, targetTypeId, targetTypeMod,
00356 ccontext, cformat, location);
00357 newcoll->collOid = coll->collOid;
00358 newcoll->location = coll->location;
00359 return (Node *) newcoll;
00360 }
00361 pathtype = find_coercion_pathway(targetTypeId, inputTypeId, ccontext,
00362 &funcId);
00363 if (pathtype != COERCION_PATH_NONE)
00364 {
00365 if (pathtype != COERCION_PATH_RELABELTYPE)
00366 {
00367
00368
00369
00370
00371
00372
00373
00374 Oid baseTypeId;
00375 int32 baseTypeMod;
00376
00377 baseTypeMod = targetTypeMod;
00378 baseTypeId = getBaseTypeAndTypmod(targetTypeId, &baseTypeMod);
00379
00380 result = build_coercion_expression(node, pathtype, funcId,
00381 baseTypeId, baseTypeMod,
00382 cformat, location,
00383 (cformat != COERCE_IMPLICIT_CAST));
00384
00385
00386
00387
00388
00389
00390 if (targetTypeId != baseTypeId)
00391 result = coerce_to_domain(result, baseTypeId, baseTypeMod,
00392 targetTypeId,
00393 cformat, location, true,
00394 exprIsLengthCoercion(result,
00395 NULL));
00396 }
00397 else
00398 {
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408 result = coerce_to_domain(node, InvalidOid, -1, targetTypeId,
00409 cformat, location, false, false);
00410 if (result == node)
00411 {
00412
00413
00414
00415
00416
00417
00418 RelabelType *r = makeRelabelType((Expr *) result,
00419 targetTypeId, -1,
00420 InvalidOid,
00421 cformat);
00422
00423 r->location = location;
00424 result = (Node *) r;
00425 }
00426 }
00427 return result;
00428 }
00429 if (inputTypeId == RECORDOID &&
00430 ISCOMPLEX(targetTypeId))
00431 {
00432
00433 return coerce_record_to_complex(pstate, node, targetTypeId,
00434 ccontext, cformat, location);
00435 }
00436 if (targetTypeId == RECORDOID &&
00437 ISCOMPLEX(inputTypeId))
00438 {
00439
00440
00441 return node;
00442 }
00443 #ifdef NOT_USED
00444 if (inputTypeId == RECORDARRAYOID &&
00445 is_complex_array(targetTypeId))
00446 {
00447
00448
00449 }
00450 #endif
00451 if (targetTypeId == RECORDARRAYOID &&
00452 is_complex_array(inputTypeId))
00453 {
00454
00455
00456 return node;
00457 }
00458 if (typeInheritsFrom(inputTypeId, targetTypeId)
00459 || typeIsOfTypedTable(inputTypeId, targetTypeId))
00460 {
00461
00462
00463
00464
00465
00466 ConvertRowtypeExpr *r = makeNode(ConvertRowtypeExpr);
00467
00468 r->arg = (Expr *) node;
00469 r->resulttype = targetTypeId;
00470 r->convertformat = cformat;
00471 r->location = location;
00472 return (Node *) r;
00473 }
00474
00475 elog(ERROR, "failed to find conversion function from %s to %s",
00476 format_type_be(inputTypeId), format_type_be(targetTypeId));
00477 return NULL;
00478 }
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488 bool
00489 can_coerce_type(int nargs, Oid *input_typeids, Oid *target_typeids,
00490 CoercionContext ccontext)
00491 {
00492 bool have_generics = false;
00493 int i;
00494
00495
00496 for (i = 0; i < nargs; i++)
00497 {
00498 Oid inputTypeId = input_typeids[i];
00499 Oid targetTypeId = target_typeids[i];
00500 CoercionPathType pathtype;
00501 Oid funcId;
00502
00503
00504 if (inputTypeId == targetTypeId)
00505 continue;
00506
00507
00508 if (targetTypeId == ANYOID)
00509 continue;
00510
00511
00512 if (IsPolymorphicType(targetTypeId))
00513 {
00514 have_generics = true;
00515 continue;
00516 }
00517
00518
00519
00520
00521
00522 if (inputTypeId == UNKNOWNOID)
00523 continue;
00524
00525
00526
00527
00528
00529 pathtype = find_coercion_pathway(targetTypeId, inputTypeId, ccontext,
00530 &funcId);
00531 if (pathtype != COERCION_PATH_NONE)
00532 continue;
00533
00534
00535
00536
00537
00538 if (inputTypeId == RECORDOID &&
00539 ISCOMPLEX(targetTypeId))
00540 continue;
00541
00542
00543
00544
00545 if (targetTypeId == RECORDOID &&
00546 ISCOMPLEX(inputTypeId))
00547 continue;
00548
00549 #ifdef NOT_USED
00550
00551
00552
00553
00554
00555 if (inputTypeId == RECORDARRAYOID &&
00556 is_complex_array(targetTypeId))
00557 continue;
00558 #endif
00559
00560
00561
00562
00563 if (targetTypeId == RECORDARRAYOID &&
00564 is_complex_array(inputTypeId))
00565 continue;
00566
00567
00568
00569
00570 if (typeInheritsFrom(inputTypeId, targetTypeId)
00571 || typeIsOfTypedTable(inputTypeId, targetTypeId))
00572 continue;
00573
00574
00575
00576
00577 return false;
00578 }
00579
00580
00581 if (have_generics)
00582 {
00583 if (!check_generic_type_consistency(input_typeids, target_typeids,
00584 nargs))
00585 return false;
00586 }
00587
00588 return true;
00589 }
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609 Node *
00610 coerce_to_domain(Node *arg, Oid baseTypeId, int32 baseTypeMod, Oid typeId,
00611 CoercionForm cformat, int location,
00612 bool hideInputCoercion,
00613 bool lengthCoercionDone)
00614 {
00615 CoerceToDomain *result;
00616
00617
00618 if (baseTypeId == InvalidOid)
00619 baseTypeId = getBaseTypeAndTypmod(typeId, &baseTypeMod);
00620
00621
00622 if (baseTypeId == typeId)
00623 return arg;
00624
00625
00626 if (hideInputCoercion)
00627 hide_coercion_node(arg);
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642 if (!lengthCoercionDone)
00643 {
00644 if (baseTypeMod >= 0)
00645 arg = coerce_type_typmod(arg, baseTypeId, baseTypeMod,
00646 COERCE_IMPLICIT_CAST, location,
00647 (cformat != COERCE_IMPLICIT_CAST),
00648 false);
00649 }
00650
00651
00652
00653
00654
00655
00656 result = makeNode(CoerceToDomain);
00657 result->arg = (Expr *) arg;
00658 result->resulttype = typeId;
00659 result->resulttypmod = -1;
00660
00661 result->coercionformat = cformat;
00662 result->location = location;
00663
00664 return (Node *) result;
00665 }
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689 static Node *
00690 coerce_type_typmod(Node *node, Oid targetTypeId, int32 targetTypMod,
00691 CoercionForm cformat, int location,
00692 bool isExplicit, bool hideInputCoercion)
00693 {
00694 CoercionPathType pathtype;
00695 Oid funcId;
00696
00697
00698
00699
00700
00701 if (targetTypMod < 0 || targetTypMod == exprTypmod(node))
00702 return node;
00703
00704 pathtype = find_typmod_coercion_function(targetTypeId, &funcId);
00705
00706 if (pathtype != COERCION_PATH_NONE)
00707 {
00708
00709 if (hideInputCoercion)
00710 hide_coercion_node(node);
00711
00712 node = build_coercion_expression(node, pathtype, funcId,
00713 targetTypeId, targetTypMod,
00714 cformat, location,
00715 isExplicit);
00716 }
00717
00718 return node;
00719 }
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731 static void
00732 hide_coercion_node(Node *node)
00733 {
00734 if (IsA(node, FuncExpr))
00735 ((FuncExpr *) node)->funcformat = COERCE_IMPLICIT_CAST;
00736 else if (IsA(node, RelabelType))
00737 ((RelabelType *) node)->relabelformat = COERCE_IMPLICIT_CAST;
00738 else if (IsA(node, CoerceViaIO))
00739 ((CoerceViaIO *) node)->coerceformat = COERCE_IMPLICIT_CAST;
00740 else if (IsA(node, ArrayCoerceExpr))
00741 ((ArrayCoerceExpr *) node)->coerceformat = COERCE_IMPLICIT_CAST;
00742 else if (IsA(node, ConvertRowtypeExpr))
00743 ((ConvertRowtypeExpr *) node)->convertformat = COERCE_IMPLICIT_CAST;
00744 else if (IsA(node, RowExpr))
00745 ((RowExpr *) node)->row_format = COERCE_IMPLICIT_CAST;
00746 else if (IsA(node, CoerceToDomain))
00747 ((CoerceToDomain *) node)->coercionformat = COERCE_IMPLICIT_CAST;
00748 else
00749 elog(ERROR, "unsupported node type: %d", (int) nodeTag(node));
00750 }
00751
00752
00753
00754
00755
00756
00757
00758
00759 static Node *
00760 build_coercion_expression(Node *node,
00761 CoercionPathType pathtype,
00762 Oid funcId,
00763 Oid targetTypeId, int32 targetTypMod,
00764 CoercionForm cformat, int location,
00765 bool isExplicit)
00766 {
00767 int nargs = 0;
00768
00769 if (OidIsValid(funcId))
00770 {
00771 HeapTuple tp;
00772 Form_pg_proc procstruct;
00773
00774 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcId));
00775 if (!HeapTupleIsValid(tp))
00776 elog(ERROR, "cache lookup failed for function %u", funcId);
00777 procstruct = (Form_pg_proc) GETSTRUCT(tp);
00778
00779
00780
00781
00782
00783
00784
00785
00786 Assert(!procstruct->proretset);
00787 Assert(!procstruct->proisagg);
00788 Assert(!procstruct->proiswindow);
00789 nargs = procstruct->pronargs;
00790 Assert(nargs >= 1 && nargs <= 3);
00791
00792 Assert(nargs < 2 || procstruct->proargtypes.values[1] == INT4OID);
00793 Assert(nargs < 3 || procstruct->proargtypes.values[2] == BOOLOID);
00794
00795 ReleaseSysCache(tp);
00796 }
00797
00798 if (pathtype == COERCION_PATH_FUNC)
00799 {
00800
00801 FuncExpr *fexpr;
00802 List *args;
00803 Const *cons;
00804
00805 Assert(OidIsValid(funcId));
00806
00807 args = list_make1(node);
00808
00809 if (nargs >= 2)
00810 {
00811
00812 cons = makeConst(INT4OID,
00813 -1,
00814 InvalidOid,
00815 sizeof(int32),
00816 Int32GetDatum(targetTypMod),
00817 false,
00818 true);
00819
00820 args = lappend(args, cons);
00821 }
00822
00823 if (nargs == 3)
00824 {
00825
00826 cons = makeConst(BOOLOID,
00827 -1,
00828 InvalidOid,
00829 sizeof(bool),
00830 BoolGetDatum(isExplicit),
00831 false,
00832 true);
00833
00834 args = lappend(args, cons);
00835 }
00836
00837 fexpr = makeFuncExpr(funcId, targetTypeId, args,
00838 InvalidOid, InvalidOid, cformat);
00839 fexpr->location = location;
00840 return (Node *) fexpr;
00841 }
00842 else if (pathtype == COERCION_PATH_ARRAYCOERCE)
00843 {
00844
00845 ArrayCoerceExpr *acoerce = makeNode(ArrayCoerceExpr);
00846
00847 acoerce->arg = (Expr *) node;
00848 acoerce->elemfuncid = funcId;
00849 acoerce->resulttype = targetTypeId;
00850
00851
00852
00853
00854
00855
00856 acoerce->resulttypmod = (nargs >= 2) ? targetTypMod : -1;
00857
00858 acoerce->isExplicit = isExplicit;
00859 acoerce->coerceformat = cformat;
00860 acoerce->location = location;
00861
00862 return (Node *) acoerce;
00863 }
00864 else if (pathtype == COERCION_PATH_COERCEVIAIO)
00865 {
00866
00867 CoerceViaIO *iocoerce = makeNode(CoerceViaIO);
00868
00869 Assert(!OidIsValid(funcId));
00870
00871 iocoerce->arg = (Expr *) node;
00872 iocoerce->resulttype = targetTypeId;
00873
00874 iocoerce->coerceformat = cformat;
00875 iocoerce->location = location;
00876
00877 return (Node *) iocoerce;
00878 }
00879 else
00880 {
00881 elog(ERROR, "unsupported pathtype %d in build_coercion_expression",
00882 (int) pathtype);
00883 return NULL;
00884 }
00885 }
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895 static Node *
00896 coerce_record_to_complex(ParseState *pstate, Node *node,
00897 Oid targetTypeId,
00898 CoercionContext ccontext,
00899 CoercionForm cformat,
00900 int location)
00901 {
00902 RowExpr *rowexpr;
00903 TupleDesc tupdesc;
00904 List *args = NIL;
00905 List *newargs;
00906 int i;
00907 int ucolno;
00908 ListCell *arg;
00909
00910 if (node && IsA(node, RowExpr))
00911 {
00912
00913
00914
00915
00916 args = ((RowExpr *) node)->args;
00917 }
00918 else if (node && IsA(node, Var) &&
00919 ((Var *) node)->varattno == InvalidAttrNumber)
00920 {
00921 int rtindex = ((Var *) node)->varno;
00922 int sublevels_up = ((Var *) node)->varlevelsup;
00923 int vlocation = ((Var *) node)->location;
00924 RangeTblEntry *rte;
00925
00926 rte = GetRTEByRangeTablePosn(pstate, rtindex, sublevels_up);
00927 expandRTE(rte, rtindex, sublevels_up, vlocation, false,
00928 NULL, &args);
00929 }
00930 else
00931 ereport(ERROR,
00932 (errcode(ERRCODE_CANNOT_COERCE),
00933 errmsg("cannot cast type %s to %s",
00934 format_type_be(RECORDOID),
00935 format_type_be(targetTypeId)),
00936 parser_coercion_errposition(pstate, location, node)));
00937
00938 tupdesc = lookup_rowtype_tupdesc(targetTypeId, -1);
00939 newargs = NIL;
00940 ucolno = 1;
00941 arg = list_head(args);
00942 for (i = 0; i < tupdesc->natts; i++)
00943 {
00944 Node *expr;
00945 Node *cexpr;
00946 Oid exprtype;
00947
00948
00949 if (tupdesc->attrs[i]->attisdropped)
00950 {
00951
00952
00953
00954
00955 newargs = lappend(newargs,
00956 makeNullConst(INT4OID, -1, InvalidOid));
00957 continue;
00958 }
00959
00960 if (arg == NULL)
00961 ereport(ERROR,
00962 (errcode(ERRCODE_CANNOT_COERCE),
00963 errmsg("cannot cast type %s to %s",
00964 format_type_be(RECORDOID),
00965 format_type_be(targetTypeId)),
00966 errdetail("Input has too few columns."),
00967 parser_coercion_errposition(pstate, location, node)));
00968 expr = (Node *) lfirst(arg);
00969 exprtype = exprType(expr);
00970
00971 cexpr = coerce_to_target_type(pstate,
00972 expr, exprtype,
00973 tupdesc->attrs[i]->atttypid,
00974 tupdesc->attrs[i]->atttypmod,
00975 ccontext,
00976 COERCE_IMPLICIT_CAST,
00977 -1);
00978 if (cexpr == NULL)
00979 ereport(ERROR,
00980 (errcode(ERRCODE_CANNOT_COERCE),
00981 errmsg("cannot cast type %s to %s",
00982 format_type_be(RECORDOID),
00983 format_type_be(targetTypeId)),
00984 errdetail("Cannot cast type %s to %s in column %d.",
00985 format_type_be(exprtype),
00986 format_type_be(tupdesc->attrs[i]->atttypid),
00987 ucolno),
00988 parser_coercion_errposition(pstate, location, expr)));
00989 newargs = lappend(newargs, cexpr);
00990 ucolno++;
00991 arg = lnext(arg);
00992 }
00993 if (arg != NULL)
00994 ereport(ERROR,
00995 (errcode(ERRCODE_CANNOT_COERCE),
00996 errmsg("cannot cast type %s to %s",
00997 format_type_be(RECORDOID),
00998 format_type_be(targetTypeId)),
00999 errdetail("Input has too many columns."),
01000 parser_coercion_errposition(pstate, location, node)));
01001
01002 ReleaseTupleDesc(tupdesc);
01003
01004 rowexpr = makeNode(RowExpr);
01005 rowexpr->args = newargs;
01006 rowexpr->row_typeid = targetTypeId;
01007 rowexpr->row_format = cformat;
01008 rowexpr->colnames = NIL;
01009 rowexpr->location = location;
01010 return (Node *) rowexpr;
01011 }
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023 Node *
01024 coerce_to_boolean(ParseState *pstate, Node *node,
01025 const char *constructName)
01026 {
01027 Oid inputTypeId = exprType(node);
01028
01029 if (inputTypeId != BOOLOID)
01030 {
01031 Node *newnode;
01032
01033 newnode = coerce_to_target_type(pstate, node, inputTypeId,
01034 BOOLOID, -1,
01035 COERCION_ASSIGNMENT,
01036 COERCE_IMPLICIT_CAST,
01037 -1);
01038 if (newnode == NULL)
01039 ereport(ERROR,
01040 (errcode(ERRCODE_DATATYPE_MISMATCH),
01041
01042 errmsg("argument of %s must be type boolean, not type %s",
01043 constructName, format_type_be(inputTypeId)),
01044 parser_errposition(pstate, exprLocation(node))));
01045 node = newnode;
01046 }
01047
01048 if (expression_returns_set(node))
01049 ereport(ERROR,
01050 (errcode(ERRCODE_DATATYPE_MISMATCH),
01051
01052 errmsg("argument of %s must not return a set",
01053 constructName),
01054 parser_errposition(pstate, exprLocation(node))));
01055
01056 return node;
01057 }
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069 Node *
01070 coerce_to_specific_type(ParseState *pstate, Node *node,
01071 Oid targetTypeId,
01072 const char *constructName)
01073 {
01074 Oid inputTypeId = exprType(node);
01075
01076 if (inputTypeId != targetTypeId)
01077 {
01078 Node *newnode;
01079
01080 newnode = coerce_to_target_type(pstate, node, inputTypeId,
01081 targetTypeId, -1,
01082 COERCION_ASSIGNMENT,
01083 COERCE_IMPLICIT_CAST,
01084 -1);
01085 if (newnode == NULL)
01086 ereport(ERROR,
01087 (errcode(ERRCODE_DATATYPE_MISMATCH),
01088
01089 errmsg("argument of %s must be type %s, not type %s",
01090 constructName,
01091 format_type_be(targetTypeId),
01092 format_type_be(inputTypeId)),
01093 parser_errposition(pstate, exprLocation(node))));
01094 node = newnode;
01095 }
01096
01097 if (expression_returns_set(node))
01098 ereport(ERROR,
01099 (errcode(ERRCODE_DATATYPE_MISMATCH),
01100
01101 errmsg("argument of %s must not return a set",
01102 constructName),
01103 parser_errposition(pstate, exprLocation(node))));
01104
01105 return node;
01106 }
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119 int
01120 parser_coercion_errposition(ParseState *pstate,
01121 int coerce_location,
01122 Node *input_expr)
01123 {
01124 if (coerce_location >= 0)
01125 return parser_errposition(pstate, coerce_location);
01126 else
01127 return parser_errposition(pstate, exprLocation(input_expr));
01128 }
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145 Oid
01146 select_common_type(ParseState *pstate, List *exprs, const char *context,
01147 Node **which_expr)
01148 {
01149 Node *pexpr;
01150 Oid ptype;
01151 TYPCATEGORY pcategory;
01152 bool pispreferred;
01153 ListCell *lc;
01154
01155 Assert(exprs != NIL);
01156 pexpr = (Node *) linitial(exprs);
01157 lc = lnext(list_head(exprs));
01158 ptype = exprType(pexpr);
01159
01160
01161
01162
01163
01164
01165 if (ptype != UNKNOWNOID)
01166 {
01167 for_each_cell(lc, lc)
01168 {
01169 Node *nexpr = (Node *) lfirst(lc);
01170 Oid ntype = exprType(nexpr);
01171
01172 if (ntype != ptype)
01173 break;
01174 }
01175 if (lc == NULL)
01176 {
01177 if (which_expr)
01178 *which_expr = pexpr;
01179 return ptype;
01180 }
01181 }
01182
01183
01184
01185
01186
01187
01188 ptype = getBaseType(ptype);
01189 get_type_category_preferred(ptype, &pcategory, &pispreferred);
01190
01191 for_each_cell(lc, lc)
01192 {
01193 Node *nexpr = (Node *) lfirst(lc);
01194 Oid ntype = getBaseType(exprType(nexpr));
01195
01196
01197 if (ntype != UNKNOWNOID && ntype != ptype)
01198 {
01199 TYPCATEGORY ncategory;
01200 bool nispreferred;
01201
01202 get_type_category_preferred(ntype, &ncategory, &nispreferred);
01203 if (ptype == UNKNOWNOID)
01204 {
01205
01206 pexpr = nexpr;
01207 ptype = ntype;
01208 pcategory = ncategory;
01209 pispreferred = nispreferred;
01210 }
01211 else if (ncategory != pcategory)
01212 {
01213
01214
01215
01216 if (context == NULL)
01217 return InvalidOid;
01218 ereport(ERROR,
01219 (errcode(ERRCODE_DATATYPE_MISMATCH),
01220
01221
01222 errmsg("%s types %s and %s cannot be matched",
01223 context,
01224 format_type_be(ptype),
01225 format_type_be(ntype)),
01226 parser_errposition(pstate, exprLocation(nexpr))));
01227 }
01228 else if (!pispreferred &&
01229 can_coerce_type(1, &ptype, &ntype, COERCION_IMPLICIT) &&
01230 !can_coerce_type(1, &ntype, &ptype, COERCION_IMPLICIT))
01231 {
01232
01233
01234
01235
01236 pexpr = nexpr;
01237 ptype = ntype;
01238 pcategory = ncategory;
01239 pispreferred = nispreferred;
01240 }
01241 }
01242 }
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255 if (ptype == UNKNOWNOID)
01256 ptype = TEXTOID;
01257
01258 if (which_expr)
01259 *which_expr = pexpr;
01260 return ptype;
01261 }
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274 Node *
01275 coerce_to_common_type(ParseState *pstate, Node *node,
01276 Oid targetTypeId, const char *context)
01277 {
01278 Oid inputTypeId = exprType(node);
01279
01280 if (inputTypeId == targetTypeId)
01281 return node;
01282 if (can_coerce_type(1, &inputTypeId, &targetTypeId, COERCION_IMPLICIT))
01283 node = coerce_type(pstate, node, inputTypeId, targetTypeId, -1,
01284 COERCION_IMPLICIT, COERCE_IMPLICIT_CAST, -1);
01285 else
01286 ereport(ERROR,
01287 (errcode(ERRCODE_CANNOT_COERCE),
01288
01289 errmsg("%s could not convert type %s to %s",
01290 context,
01291 format_type_be(inputTypeId),
01292 format_type_be(targetTypeId)),
01293 parser_errposition(pstate, exprLocation(node))));
01294 return node;
01295 }
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345 bool
01346 check_generic_type_consistency(Oid *actual_arg_types,
01347 Oid *declared_arg_types,
01348 int nargs)
01349 {
01350 int j;
01351 Oid elem_typeid = InvalidOid;
01352 Oid array_typeid = InvalidOid;
01353 Oid array_typelem;
01354 Oid range_typeid = InvalidOid;
01355 Oid range_typelem;
01356 bool have_anyelement = false;
01357 bool have_anynonarray = false;
01358 bool have_anyenum = false;
01359
01360
01361
01362
01363
01364 for (j = 0; j < nargs; j++)
01365 {
01366 Oid decl_type = declared_arg_types[j];
01367 Oid actual_type = actual_arg_types[j];
01368
01369 if (decl_type == ANYELEMENTOID ||
01370 decl_type == ANYNONARRAYOID ||
01371 decl_type == ANYENUMOID)
01372 {
01373 have_anyelement = true;
01374 if (decl_type == ANYNONARRAYOID)
01375 have_anynonarray = true;
01376 else if (decl_type == ANYENUMOID)
01377 have_anyenum = true;
01378 if (actual_type == UNKNOWNOID)
01379 continue;
01380 if (OidIsValid(elem_typeid) && actual_type != elem_typeid)
01381 return false;
01382 elem_typeid = actual_type;
01383 }
01384 else if (decl_type == ANYARRAYOID)
01385 {
01386 if (actual_type == UNKNOWNOID)
01387 continue;
01388 actual_type = getBaseType(actual_type);
01389 if (OidIsValid(array_typeid) && actual_type != array_typeid)
01390 return false;
01391 array_typeid = actual_type;
01392 }
01393 else if (decl_type == ANYRANGEOID)
01394 {
01395 if (actual_type == UNKNOWNOID)
01396 continue;
01397 actual_type = getBaseType(actual_type);
01398 if (OidIsValid(range_typeid) && actual_type != range_typeid)
01399 return false;
01400 range_typeid = actual_type;
01401 }
01402 }
01403
01404
01405 if (OidIsValid(array_typeid))
01406 {
01407 if (array_typeid == ANYARRAYOID)
01408 {
01409
01410 if (have_anyelement)
01411 return false;
01412 return true;
01413 }
01414
01415 array_typelem = get_element_type(array_typeid);
01416 if (!OidIsValid(array_typelem))
01417 return false;
01418
01419 if (!OidIsValid(elem_typeid))
01420 {
01421
01422
01423
01424 elem_typeid = array_typelem;
01425 }
01426 else if (array_typelem != elem_typeid)
01427 {
01428
01429 return false;
01430 }
01431 }
01432
01433
01434 if (OidIsValid(range_typeid))
01435 {
01436 range_typelem = get_range_subtype(range_typeid);
01437 if (!OidIsValid(range_typelem))
01438 return false;
01439
01440 if (!OidIsValid(elem_typeid))
01441 {
01442
01443
01444
01445 elem_typeid = range_typelem;
01446 }
01447 else if (range_typelem != elem_typeid)
01448 {
01449
01450 return false;
01451 }
01452 }
01453
01454 if (have_anynonarray)
01455 {
01456
01457 if (type_is_array_domain(elem_typeid))
01458 return false;
01459 }
01460
01461 if (have_anyenum)
01462 {
01463
01464 if (!type_is_enum(elem_typeid))
01465 return false;
01466 }
01467
01468
01469 return true;
01470 }
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542 Oid
01543 enforce_generic_type_consistency(Oid *actual_arg_types,
01544 Oid *declared_arg_types,
01545 int nargs,
01546 Oid rettype,
01547 bool allow_poly)
01548 {
01549 int j;
01550 bool have_generics = false;
01551 bool have_unknowns = false;
01552 Oid elem_typeid = InvalidOid;
01553 Oid array_typeid = InvalidOid;
01554 Oid range_typeid = InvalidOid;
01555 Oid array_typelem;
01556 Oid range_typelem;
01557 bool have_anyelement = (rettype == ANYELEMENTOID ||
01558 rettype == ANYNONARRAYOID ||
01559 rettype == ANYENUMOID);
01560 bool have_anynonarray = (rettype == ANYNONARRAYOID);
01561 bool have_anyenum = (rettype == ANYENUMOID);
01562
01563
01564
01565
01566
01567 for (j = 0; j < nargs; j++)
01568 {
01569 Oid decl_type = declared_arg_types[j];
01570 Oid actual_type = actual_arg_types[j];
01571
01572 if (decl_type == ANYELEMENTOID ||
01573 decl_type == ANYNONARRAYOID ||
01574 decl_type == ANYENUMOID)
01575 {
01576 have_generics = have_anyelement = true;
01577 if (decl_type == ANYNONARRAYOID)
01578 have_anynonarray = true;
01579 else if (decl_type == ANYENUMOID)
01580 have_anyenum = true;
01581 if (actual_type == UNKNOWNOID)
01582 {
01583 have_unknowns = true;
01584 continue;
01585 }
01586 if (allow_poly && decl_type == actual_type)
01587 continue;
01588 if (OidIsValid(elem_typeid) && actual_type != elem_typeid)
01589 ereport(ERROR,
01590 (errcode(ERRCODE_DATATYPE_MISMATCH),
01591 errmsg("arguments declared \"anyelement\" are not all alike"),
01592 errdetail("%s versus %s",
01593 format_type_be(elem_typeid),
01594 format_type_be(actual_type))));
01595 elem_typeid = actual_type;
01596 }
01597 else if (decl_type == ANYARRAYOID)
01598 {
01599 have_generics = true;
01600 if (actual_type == UNKNOWNOID)
01601 {
01602 have_unknowns = true;
01603 continue;
01604 }
01605 if (allow_poly && decl_type == actual_type)
01606 continue;
01607 actual_type = getBaseType(actual_type);
01608 if (OidIsValid(array_typeid) && actual_type != array_typeid)
01609 ereport(ERROR,
01610 (errcode(ERRCODE_DATATYPE_MISMATCH),
01611 errmsg("arguments declared \"anyarray\" are not all alike"),
01612 errdetail("%s versus %s",
01613 format_type_be(array_typeid),
01614 format_type_be(actual_type))));
01615 array_typeid = actual_type;
01616 }
01617 else if (decl_type == ANYRANGEOID)
01618 {
01619 have_generics = true;
01620 if (actual_type == UNKNOWNOID)
01621 {
01622 have_unknowns = true;
01623 continue;
01624 }
01625 if (allow_poly && decl_type == actual_type)
01626 continue;
01627 actual_type = getBaseType(actual_type);
01628 if (OidIsValid(range_typeid) && actual_type != range_typeid)
01629 ereport(ERROR,
01630 (errcode(ERRCODE_DATATYPE_MISMATCH),
01631 errmsg("arguments declared \"anyrange\" are not all alike"),
01632 errdetail("%s versus %s",
01633 format_type_be(range_typeid),
01634 format_type_be(actual_type))));
01635 range_typeid = actual_type;
01636 }
01637 }
01638
01639
01640
01641
01642
01643 if (!have_generics)
01644 return rettype;
01645
01646
01647 if (OidIsValid(array_typeid))
01648 {
01649 if (array_typeid == ANYARRAYOID && !have_anyelement)
01650 {
01651
01652 array_typelem = ANYELEMENTOID;
01653 }
01654 else
01655 {
01656 array_typelem = get_element_type(array_typeid);
01657 if (!OidIsValid(array_typelem))
01658 ereport(ERROR,
01659 (errcode(ERRCODE_DATATYPE_MISMATCH),
01660 errmsg("argument declared \"anyarray\" is not an array but type %s",
01661 format_type_be(array_typeid))));
01662 }
01663
01664 if (!OidIsValid(elem_typeid))
01665 {
01666
01667
01668
01669 elem_typeid = array_typelem;
01670 }
01671 else if (array_typelem != elem_typeid)
01672 {
01673
01674 ereport(ERROR,
01675 (errcode(ERRCODE_DATATYPE_MISMATCH),
01676 errmsg("argument declared \"anyarray\" is not consistent with argument declared \"anyelement\""),
01677 errdetail("%s versus %s",
01678 format_type_be(array_typeid),
01679 format_type_be(elem_typeid))));
01680 }
01681 }
01682
01683
01684 if (OidIsValid(range_typeid))
01685 {
01686 if (range_typeid == ANYRANGEOID && !have_anyelement)
01687 {
01688
01689 range_typelem = ANYELEMENTOID;
01690 }
01691 else
01692 {
01693 range_typelem = get_range_subtype(range_typeid);
01694 if (!OidIsValid(range_typelem))
01695 ereport(ERROR,
01696 (errcode(ERRCODE_DATATYPE_MISMATCH),
01697 errmsg("argument declared \"anyrange\" is not a range type but type %s",
01698 format_type_be(range_typeid))));
01699 }
01700
01701 if (!OidIsValid(elem_typeid))
01702 {
01703
01704
01705
01706 elem_typeid = range_typelem;
01707 }
01708 else if (range_typelem != elem_typeid)
01709 {
01710
01711 ereport(ERROR,
01712 (errcode(ERRCODE_DATATYPE_MISMATCH),
01713 errmsg("argument declared \"anyrange\" is not consistent with argument declared \"anyelement\""),
01714 errdetail("%s versus %s",
01715 format_type_be(range_typeid),
01716 format_type_be(elem_typeid))));
01717 }
01718 }
01719
01720 if (!OidIsValid(elem_typeid))
01721 {
01722 if (allow_poly)
01723 {
01724 elem_typeid = ANYELEMENTOID;
01725 array_typeid = ANYARRAYOID;
01726 range_typeid = ANYRANGEOID;
01727 }
01728 else
01729 {
01730
01731 ereport(ERROR,
01732 (errcode(ERRCODE_DATATYPE_MISMATCH),
01733 errmsg("could not determine polymorphic type because input has type \"unknown\"")));
01734 }
01735 }
01736
01737 if (have_anynonarray && elem_typeid != ANYELEMENTOID)
01738 {
01739
01740 if (type_is_array_domain(elem_typeid))
01741 ereport(ERROR,
01742 (errcode(ERRCODE_DATATYPE_MISMATCH),
01743 errmsg("type matched to anynonarray is an array type: %s",
01744 format_type_be(elem_typeid))));
01745 }
01746
01747 if (have_anyenum && elem_typeid != ANYELEMENTOID)
01748 {
01749
01750 if (!type_is_enum(elem_typeid))
01751 ereport(ERROR,
01752 (errcode(ERRCODE_DATATYPE_MISMATCH),
01753 errmsg("type matched to anyenum is not an enum type: %s",
01754 format_type_be(elem_typeid))));
01755 }
01756
01757
01758
01759
01760 if (have_unknowns)
01761 {
01762 for (j = 0; j < nargs; j++)
01763 {
01764 Oid decl_type = declared_arg_types[j];
01765 Oid actual_type = actual_arg_types[j];
01766
01767 if (actual_type != UNKNOWNOID)
01768 continue;
01769
01770 if (decl_type == ANYELEMENTOID ||
01771 decl_type == ANYNONARRAYOID ||
01772 decl_type == ANYENUMOID)
01773 declared_arg_types[j] = elem_typeid;
01774 else if (decl_type == ANYARRAYOID)
01775 {
01776 if (!OidIsValid(array_typeid))
01777 {
01778 array_typeid = get_array_type(elem_typeid);
01779 if (!OidIsValid(array_typeid))
01780 ereport(ERROR,
01781 (errcode(ERRCODE_UNDEFINED_OBJECT),
01782 errmsg("could not find array type for data type %s",
01783 format_type_be(elem_typeid))));
01784 }
01785 declared_arg_types[j] = array_typeid;
01786 }
01787 else if (decl_type == ANYRANGEOID)
01788 {
01789 if (!OidIsValid(range_typeid))
01790 {
01791 ereport(ERROR,
01792 (errcode(ERRCODE_UNDEFINED_OBJECT),
01793 errmsg("could not find range type for data type %s",
01794 format_type_be(elem_typeid))));
01795 }
01796 declared_arg_types[j] = range_typeid;
01797 }
01798 }
01799 }
01800
01801
01802 if (rettype == ANYARRAYOID)
01803 {
01804 if (!OidIsValid(array_typeid))
01805 {
01806 array_typeid = get_array_type(elem_typeid);
01807 if (!OidIsValid(array_typeid))
01808 ereport(ERROR,
01809 (errcode(ERRCODE_UNDEFINED_OBJECT),
01810 errmsg("could not find array type for data type %s",
01811 format_type_be(elem_typeid))));
01812 }
01813 return array_typeid;
01814 }
01815
01816
01817 if (rettype == ANYRANGEOID)
01818 {
01819 if (!OidIsValid(range_typeid))
01820 {
01821 ereport(ERROR,
01822 (errcode(ERRCODE_UNDEFINED_OBJECT),
01823 errmsg("could not find range type for data type %s",
01824 format_type_be(elem_typeid))));
01825 }
01826 return range_typeid;
01827 }
01828
01829
01830 if (rettype == ANYELEMENTOID ||
01831 rettype == ANYNONARRAYOID ||
01832 rettype == ANYENUMOID)
01833 return elem_typeid;
01834
01835
01836 return rettype;
01837 }
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852 Oid
01853 resolve_generic_type(Oid declared_type,
01854 Oid context_actual_type,
01855 Oid context_declared_type)
01856 {
01857 if (declared_type == ANYARRAYOID)
01858 {
01859 if (context_declared_type == ANYARRAYOID)
01860 {
01861
01862
01863
01864
01865 Oid context_base_type = getBaseType(context_actual_type);
01866 Oid array_typelem = get_element_type(context_base_type);
01867
01868 if (!OidIsValid(array_typelem))
01869 ereport(ERROR,
01870 (errcode(ERRCODE_DATATYPE_MISMATCH),
01871 errmsg("argument declared \"anyarray\" is not an array but type %s",
01872 format_type_be(context_base_type))));
01873 return context_base_type;
01874 }
01875 else if (context_declared_type == ANYELEMENTOID ||
01876 context_declared_type == ANYNONARRAYOID ||
01877 context_declared_type == ANYENUMOID ||
01878 context_declared_type == ANYRANGEOID)
01879 {
01880
01881 Oid array_typeid = get_array_type(context_actual_type);
01882
01883 if (!OidIsValid(array_typeid))
01884 ereport(ERROR,
01885 (errcode(ERRCODE_UNDEFINED_OBJECT),
01886 errmsg("could not find array type for data type %s",
01887 format_type_be(context_actual_type))));
01888 return array_typeid;
01889 }
01890 }
01891 else if (declared_type == ANYELEMENTOID ||
01892 declared_type == ANYNONARRAYOID ||
01893 declared_type == ANYENUMOID ||
01894 declared_type == ANYRANGEOID)
01895 {
01896 if (context_declared_type == ANYARRAYOID)
01897 {
01898
01899 Oid context_base_type = getBaseType(context_actual_type);
01900 Oid array_typelem = get_element_type(context_base_type);
01901
01902 if (!OidIsValid(array_typelem))
01903 ereport(ERROR,
01904 (errcode(ERRCODE_DATATYPE_MISMATCH),
01905 errmsg("argument declared \"anyarray\" is not an array but type %s",
01906 format_type_be(context_base_type))));
01907 return array_typelem;
01908 }
01909 else if (context_declared_type == ANYRANGEOID)
01910 {
01911
01912 Oid context_base_type = getBaseType(context_actual_type);
01913 Oid range_typelem = get_range_subtype(context_base_type);
01914
01915 if (!OidIsValid(range_typelem))
01916 ereport(ERROR,
01917 (errcode(ERRCODE_DATATYPE_MISMATCH),
01918 errmsg("argument declared \"anyrange\" is not a range type but type %s",
01919 format_type_be(context_base_type))));
01920 return range_typelem;
01921 }
01922 else if (context_declared_type == ANYELEMENTOID ||
01923 context_declared_type == ANYNONARRAYOID ||
01924 context_declared_type == ANYENUMOID)
01925 {
01926
01927 return context_actual_type;
01928 }
01929 }
01930 else
01931 {
01932
01933 return declared_type;
01934 }
01935
01936
01937 elog(ERROR, "could not determine polymorphic type because context isn't polymorphic");
01938 return InvalidOid;
01939 }
01940
01941
01942
01943
01944
01945
01946
01947 TYPCATEGORY
01948 TypeCategory(Oid type)
01949 {
01950 char typcategory;
01951 bool typispreferred;
01952
01953 get_type_category_preferred(type, &typcategory, &typispreferred);
01954 Assert(typcategory != TYPCATEGORY_INVALID);
01955 return (TYPCATEGORY) typcategory;
01956 }
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966 bool
01967 IsPreferredType(TYPCATEGORY category, Oid type)
01968 {
01969 char typcategory;
01970 bool typispreferred;
01971
01972 get_type_category_preferred(type, &typcategory, &typispreferred);
01973 if (category == typcategory || category == TYPCATEGORY_INVALID)
01974 return typispreferred;
01975 else
01976 return false;
01977 }
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001 bool
02002 IsBinaryCoercible(Oid srctype, Oid targettype)
02003 {
02004 HeapTuple tuple;
02005 Form_pg_cast castForm;
02006 bool result;
02007
02008
02009 if (srctype == targettype)
02010 return true;
02011
02012
02013 if (OidIsValid(srctype))
02014 srctype = getBaseType(srctype);
02015
02016
02017 if (srctype == targettype)
02018 return true;
02019
02020
02021 if (targettype == ANYARRAYOID)
02022 if (type_is_array(srctype))
02023 return true;
02024
02025
02026 if (targettype == ANYNONARRAYOID)
02027 if (!type_is_array(srctype))
02028 return true;
02029
02030
02031 if (targettype == ANYENUMOID)
02032 if (type_is_enum(srctype))
02033 return true;
02034
02035
02036 if (targettype == ANYRANGEOID)
02037 if (type_is_range(srctype))
02038 return true;
02039
02040
02041 if (targettype == RECORDOID)
02042 if (ISCOMPLEX(srctype))
02043 return true;
02044
02045
02046 if (targettype == RECORDARRAYOID)
02047 if (is_complex_array(srctype))
02048 return true;
02049
02050
02051 tuple = SearchSysCache2(CASTSOURCETARGET,
02052 ObjectIdGetDatum(srctype),
02053 ObjectIdGetDatum(targettype));
02054 if (!HeapTupleIsValid(tuple))
02055 return false;
02056 castForm = (Form_pg_cast) GETSTRUCT(tuple);
02057
02058 result = (castForm->castmethod == COERCION_METHOD_BINARY &&
02059 castForm->castcontext == COERCION_CODE_IMPLICIT);
02060
02061 ReleaseSysCache(tuple);
02062
02063 return result;
02064 }
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089
02090
02091
02092
02093
02094 CoercionPathType
02095 find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
02096 CoercionContext ccontext,
02097 Oid *funcid)
02098 {
02099 CoercionPathType result = COERCION_PATH_NONE;
02100 HeapTuple tuple;
02101
02102 *funcid = InvalidOid;
02103
02104
02105 if (OidIsValid(sourceTypeId))
02106 sourceTypeId = getBaseType(sourceTypeId);
02107 if (OidIsValid(targetTypeId))
02108 targetTypeId = getBaseType(targetTypeId);
02109
02110
02111 if (sourceTypeId == targetTypeId)
02112 return COERCION_PATH_RELABELTYPE;
02113
02114
02115 tuple = SearchSysCache2(CASTSOURCETARGET,
02116 ObjectIdGetDatum(sourceTypeId),
02117 ObjectIdGetDatum(targetTypeId));
02118
02119 if (HeapTupleIsValid(tuple))
02120 {
02121 Form_pg_cast castForm = (Form_pg_cast) GETSTRUCT(tuple);
02122 CoercionContext castcontext;
02123
02124
02125 switch (castForm->castcontext)
02126 {
02127 case COERCION_CODE_IMPLICIT:
02128 castcontext = COERCION_IMPLICIT;
02129 break;
02130 case COERCION_CODE_ASSIGNMENT:
02131 castcontext = COERCION_ASSIGNMENT;
02132 break;
02133 case COERCION_CODE_EXPLICIT:
02134 castcontext = COERCION_EXPLICIT;
02135 break;
02136 default:
02137 elog(ERROR, "unrecognized castcontext: %d",
02138 (int) castForm->castcontext);
02139 castcontext = 0;
02140 break;
02141 }
02142
02143
02144 if (ccontext >= castcontext)
02145 {
02146 switch (castForm->castmethod)
02147 {
02148 case COERCION_METHOD_FUNCTION:
02149 result = COERCION_PATH_FUNC;
02150 *funcid = castForm->castfunc;
02151 break;
02152 case COERCION_METHOD_INOUT:
02153 result = COERCION_PATH_COERCEVIAIO;
02154 break;
02155 case COERCION_METHOD_BINARY:
02156 result = COERCION_PATH_RELABELTYPE;
02157 break;
02158 default:
02159 elog(ERROR, "unrecognized castmethod: %d",
02160 (int) castForm->castmethod);
02161 break;
02162 }
02163 }
02164
02165 ReleaseSysCache(tuple);
02166 }
02167 else
02168 {
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184 if (targetTypeId != OIDVECTOROID && targetTypeId != INT2VECTOROID)
02185 {
02186 Oid targetElem;
02187 Oid sourceElem;
02188
02189 if ((targetElem = get_element_type(targetTypeId)) != InvalidOid &&
02190 (sourceElem = get_base_element_type(sourceTypeId)) != InvalidOid)
02191 {
02192 CoercionPathType elempathtype;
02193 Oid elemfuncid;
02194
02195 elempathtype = find_coercion_pathway(targetElem,
02196 sourceElem,
02197 ccontext,
02198 &elemfuncid);
02199 if (elempathtype != COERCION_PATH_NONE &&
02200 elempathtype != COERCION_PATH_ARRAYCOERCE)
02201 {
02202 *funcid = elemfuncid;
02203 if (elempathtype == COERCION_PATH_COERCEVIAIO)
02204 result = COERCION_PATH_COERCEVIAIO;
02205 else
02206 result = COERCION_PATH_ARRAYCOERCE;
02207 }
02208 }
02209 }
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221 if (result == COERCION_PATH_NONE)
02222 {
02223 if (ccontext >= COERCION_ASSIGNMENT &&
02224 TypeCategory(targetTypeId) == TYPCATEGORY_STRING)
02225 result = COERCION_PATH_COERCEVIAIO;
02226 else if (ccontext >= COERCION_EXPLICIT &&
02227 TypeCategory(sourceTypeId) == TYPCATEGORY_STRING)
02228 result = COERCION_PATH_COERCEVIAIO;
02229 }
02230 }
02231
02232 return result;
02233 }
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245
02246
02247
02248
02249
02250
02251
02252
02253
02254
02255 CoercionPathType
02256 find_typmod_coercion_function(Oid typeId,
02257 Oid *funcid)
02258 {
02259 CoercionPathType result;
02260 Type targetType;
02261 Form_pg_type typeForm;
02262 HeapTuple tuple;
02263
02264 *funcid = InvalidOid;
02265 result = COERCION_PATH_FUNC;
02266
02267 targetType = typeidType(typeId);
02268 typeForm = (Form_pg_type) GETSTRUCT(targetType);
02269
02270
02271 if (typeForm->typelem != InvalidOid && typeForm->typlen == -1)
02272 {
02273
02274 typeId = typeForm->typelem;
02275 result = COERCION_PATH_ARRAYCOERCE;
02276 }
02277 ReleaseSysCache(targetType);
02278
02279
02280 tuple = SearchSysCache2(CASTSOURCETARGET,
02281 ObjectIdGetDatum(typeId),
02282 ObjectIdGetDatum(typeId));
02283
02284 if (HeapTupleIsValid(tuple))
02285 {
02286 Form_pg_cast castForm = (Form_pg_cast) GETSTRUCT(tuple);
02287
02288 *funcid = castForm->castfunc;
02289 ReleaseSysCache(tuple);
02290 }
02291
02292 if (!OidIsValid(*funcid))
02293 result = COERCION_PATH_NONE;
02294
02295 return result;
02296 }
02297
02298
02299
02300
02301
02302
02303
02304
02305 static bool
02306 is_complex_array(Oid typid)
02307 {
02308 Oid elemtype = get_element_type(typid);
02309
02310 return (OidIsValid(elemtype) && ISCOMPLEX(elemtype));
02311 }
02312
02313
02314
02315
02316
02317
02318
02319 static bool
02320 typeIsOfTypedTable(Oid reltypeId, Oid reloftypeId)
02321 {
02322 Oid relid = typeidTypeRelid(reltypeId);
02323 bool result = false;
02324
02325 if (relid)
02326 {
02327 HeapTuple tp;
02328 Form_pg_class reltup;
02329
02330 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
02331 if (!HeapTupleIsValid(tp))
02332 elog(ERROR, "cache lookup failed for relation %u", relid);
02333
02334 reltup = (Form_pg_class) GETSTRUCT(tp);
02335 if (reltup->reloftype == reloftypeId)
02336 result = true;
02337
02338 ReleaseSysCache(tp);
02339 }
02340
02341 return result;
02342 }