00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "postgres.h"
00017
00018 #include "access/htup_details.h"
00019 #include "catalog/pg_operator.h"
00020 #include "catalog/pg_type.h"
00021 #include "lib/stringinfo.h"
00022 #include "nodes/nodeFuncs.h"
00023 #include "parser/parse_coerce.h"
00024 #include "parser/parse_func.h"
00025 #include "parser/parse_oper.h"
00026 #include "parser/parse_type.h"
00027 #include "utils/builtins.h"
00028 #include "utils/inval.h"
00029 #include "utils/lsyscache.h"
00030 #include "utils/syscache.h"
00031 #include "utils/typcache.h"
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 #define MAX_CACHED_PATH_LEN 16
00050
00051 typedef struct OprCacheKey
00052 {
00053 char oprname[NAMEDATALEN];
00054 Oid left_arg;
00055 Oid right_arg;
00056 Oid search_path[MAX_CACHED_PATH_LEN];
00057 } OprCacheKey;
00058
00059 typedef struct OprCacheEntry
00060 {
00061
00062 OprCacheKey key;
00063
00064 Oid opr_oid;
00065 } OprCacheEntry;
00066
00067
00068 static Oid binary_oper_exact(List *opname, Oid arg1, Oid arg2);
00069 static FuncDetailCode oper_select_candidate(int nargs,
00070 Oid *input_typeids,
00071 FuncCandidateList candidates,
00072 Oid *operOid);
00073 static const char *op_signature_string(List *op, char oprkind,
00074 Oid arg1, Oid arg2);
00075 static void op_error(ParseState *pstate, List *op, char oprkind,
00076 Oid arg1, Oid arg2,
00077 FuncDetailCode fdresult, int location);
00078 static bool make_oper_cache_key(OprCacheKey *key, List *opname,
00079 Oid ltypeId, Oid rtypeId);
00080 static Oid find_oper_cache_entry(OprCacheKey *key);
00081 static void make_oper_cache_entry(OprCacheKey *key, Oid opr_oid);
00082 static void InvalidateOprCacheCallBack(Datum arg, int cacheid, uint32 hashvalue);
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 Oid
00101 LookupOperName(ParseState *pstate, List *opername, Oid oprleft, Oid oprright,
00102 bool noError, int location)
00103 {
00104 Oid result;
00105
00106 result = OpernameGetOprid(opername, oprleft, oprright);
00107 if (OidIsValid(result))
00108 return result;
00109
00110
00111 if (!noError)
00112 {
00113 char oprkind;
00114
00115 if (!OidIsValid(oprleft))
00116 oprkind = 'l';
00117 else if (!OidIsValid(oprright))
00118 oprkind = 'r';
00119 else
00120 oprkind = 'b';
00121
00122 ereport(ERROR,
00123 (errcode(ERRCODE_UNDEFINED_FUNCTION),
00124 errmsg("operator does not exist: %s",
00125 op_signature_string(opername, oprkind,
00126 oprleft, oprright)),
00127 parser_errposition(pstate, location)));
00128 }
00129
00130 return InvalidOid;
00131 }
00132
00133
00134
00135
00136
00137
00138
00139
00140 Oid
00141 LookupOperNameTypeNames(ParseState *pstate, List *opername,
00142 TypeName *oprleft, TypeName *oprright,
00143 bool noError, int location)
00144 {
00145 Oid leftoid,
00146 rightoid;
00147
00148 if (oprleft == NULL)
00149 leftoid = InvalidOid;
00150 else
00151 leftoid = typenameTypeId(pstate, oprleft);
00152
00153 if (oprright == NULL)
00154 rightoid = InvalidOid;
00155 else
00156 rightoid = typenameTypeId(pstate, oprright);
00157
00158 return LookupOperName(pstate, opername, leftoid, rightoid,
00159 noError, location);
00160 }
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183 void
00184 get_sort_group_operators(Oid argtype,
00185 bool needLT, bool needEQ, bool needGT,
00186 Oid *ltOpr, Oid *eqOpr, Oid *gtOpr,
00187 bool *isHashable)
00188 {
00189 TypeCacheEntry *typentry;
00190 int cache_flags;
00191 Oid lt_opr;
00192 Oid eq_opr;
00193 Oid gt_opr;
00194 bool hashable;
00195
00196
00197
00198
00199
00200
00201
00202 if (isHashable != NULL)
00203 cache_flags = TYPECACHE_LT_OPR | TYPECACHE_EQ_OPR | TYPECACHE_GT_OPR |
00204 TYPECACHE_HASH_PROC;
00205 else
00206 cache_flags = TYPECACHE_LT_OPR | TYPECACHE_EQ_OPR | TYPECACHE_GT_OPR;
00207
00208 typentry = lookup_type_cache(argtype, cache_flags);
00209 lt_opr = typentry->lt_opr;
00210 eq_opr = typentry->eq_opr;
00211 gt_opr = typentry->gt_opr;
00212 hashable = OidIsValid(typentry->hash_proc);
00213
00214
00215 if ((needLT && !OidIsValid(lt_opr)) ||
00216 (needGT && !OidIsValid(gt_opr)))
00217 ereport(ERROR,
00218 (errcode(ERRCODE_UNDEFINED_FUNCTION),
00219 errmsg("could not identify an ordering operator for type %s",
00220 format_type_be(argtype)),
00221 errhint("Use an explicit ordering operator or modify the query.")));
00222 if (needEQ && !OidIsValid(eq_opr))
00223 ereport(ERROR,
00224 (errcode(ERRCODE_UNDEFINED_FUNCTION),
00225 errmsg("could not identify an equality operator for type %s",
00226 format_type_be(argtype))));
00227
00228
00229 if (ltOpr)
00230 *ltOpr = lt_opr;
00231 if (eqOpr)
00232 *eqOpr = eq_opr;
00233 if (gtOpr)
00234 *gtOpr = gt_opr;
00235 if (isHashable)
00236 *isHashable = hashable;
00237 }
00238
00239
00240
00241 Oid
00242 oprid(Operator op)
00243 {
00244 return HeapTupleGetOid(op);
00245 }
00246
00247
00248 Oid
00249 oprfuncid(Operator op)
00250 {
00251 Form_pg_operator pgopform = (Form_pg_operator) GETSTRUCT(op);
00252
00253 return pgopform->oprcode;
00254 }
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265 static Oid
00266 binary_oper_exact(List *opname, Oid arg1, Oid arg2)
00267 {
00268 Oid result;
00269 bool was_unknown = false;
00270
00271
00272 if ((arg1 == UNKNOWNOID) && (arg2 != InvalidOid))
00273 {
00274 arg1 = arg2;
00275 was_unknown = true;
00276 }
00277 else if ((arg2 == UNKNOWNOID) && (arg1 != InvalidOid))
00278 {
00279 arg2 = arg1;
00280 was_unknown = true;
00281 }
00282
00283 result = OpernameGetOprid(opname, arg1, arg2);
00284 if (OidIsValid(result))
00285 return result;
00286
00287 if (was_unknown)
00288 {
00289
00290 Oid basetype = getBaseType(arg1);
00291
00292 if (basetype != arg1)
00293 {
00294 result = OpernameGetOprid(opname, basetype, basetype);
00295 if (OidIsValid(result))
00296 return result;
00297 }
00298 }
00299
00300 return InvalidOid;
00301 }
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315 static FuncDetailCode
00316 oper_select_candidate(int nargs,
00317 Oid *input_typeids,
00318 FuncCandidateList candidates,
00319 Oid *operOid)
00320 {
00321 int ncandidates;
00322
00323
00324
00325
00326
00327 ncandidates = func_match_argtypes(nargs, input_typeids,
00328 candidates, &candidates);
00329
00330
00331 if (ncandidates == 0)
00332 {
00333 *operOid = InvalidOid;
00334 return FUNCDETAIL_NOTFOUND;
00335 }
00336 if (ncandidates == 1)
00337 {
00338 *operOid = candidates->oid;
00339 return FUNCDETAIL_NORMAL;
00340 }
00341
00342
00343
00344
00345
00346 candidates = func_select_candidate(nargs, input_typeids, candidates);
00347
00348 if (candidates)
00349 {
00350 *operOid = candidates->oid;
00351 return FUNCDETAIL_NORMAL;
00352 }
00353
00354 *operOid = InvalidOid;
00355 return FUNCDETAIL_MULTIPLE;
00356 }
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373 Operator
00374 oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId,
00375 bool noError, int location)
00376 {
00377 Oid operOid;
00378 OprCacheKey key;
00379 bool key_ok;
00380 FuncDetailCode fdresult = FUNCDETAIL_NOTFOUND;
00381 HeapTuple tup = NULL;
00382
00383
00384
00385
00386 key_ok = make_oper_cache_key(&key, opname, ltypeId, rtypeId);
00387 if (key_ok)
00388 {
00389 operOid = find_oper_cache_entry(&key);
00390 if (OidIsValid(operOid))
00391 {
00392 tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
00393 if (HeapTupleIsValid(tup))
00394 return (Operator) tup;
00395 }
00396 }
00397
00398
00399
00400
00401 operOid = binary_oper_exact(opname, ltypeId, rtypeId);
00402 if (!OidIsValid(operOid))
00403 {
00404
00405
00406
00407 FuncCandidateList clist;
00408
00409
00410 clist = OpernameGetCandidates(opname, 'b');
00411
00412
00413 if (clist != NULL)
00414 {
00415
00416
00417
00418
00419 Oid inputOids[2];
00420
00421 if (rtypeId == InvalidOid)
00422 rtypeId = ltypeId;
00423 else if (ltypeId == InvalidOid)
00424 ltypeId = rtypeId;
00425 inputOids[0] = ltypeId;
00426 inputOids[1] = rtypeId;
00427 fdresult = oper_select_candidate(2, inputOids, clist, &operOid);
00428 }
00429 }
00430
00431 if (OidIsValid(operOid))
00432 tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
00433
00434 if (HeapTupleIsValid(tup))
00435 {
00436 if (key_ok)
00437 make_oper_cache_entry(&key, operOid);
00438 }
00439 else if (!noError)
00440 op_error(pstate, opname, 'b', ltypeId, rtypeId, fdresult, location);
00441
00442 return (Operator) tup;
00443 }
00444
00445
00446
00447
00448
00449
00450
00451
00452 Operator
00453 compatible_oper(ParseState *pstate, List *op, Oid arg1, Oid arg2,
00454 bool noError, int location)
00455 {
00456 Operator optup;
00457 Form_pg_operator opform;
00458
00459
00460 optup = oper(pstate, op, arg1, arg2, noError, location);
00461 if (optup == (Operator) NULL)
00462 return (Operator) NULL;
00463
00464
00465 opform = (Form_pg_operator) GETSTRUCT(optup);
00466 if (IsBinaryCoercible(arg1, opform->oprleft) &&
00467 IsBinaryCoercible(arg2, opform->oprright))
00468 return optup;
00469
00470
00471 ReleaseSysCache(optup);
00472
00473 if (!noError)
00474 ereport(ERROR,
00475 (errcode(ERRCODE_UNDEFINED_FUNCTION),
00476 errmsg("operator requires run-time type coercion: %s",
00477 op_signature_string(op, 'b', arg1, arg2)),
00478 parser_errposition(pstate, location)));
00479
00480 return (Operator) NULL;
00481 }
00482
00483
00484
00485
00486
00487
00488
00489 Oid
00490 compatible_oper_opid(List *op, Oid arg1, Oid arg2, bool noError)
00491 {
00492 Operator optup;
00493 Oid result;
00494
00495 optup = compatible_oper(NULL, op, arg1, arg2, noError, -1);
00496 if (optup != NULL)
00497 {
00498 result = oprid(optup);
00499 ReleaseSysCache(optup);
00500 return result;
00501 }
00502 return InvalidOid;
00503 }
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520 Operator
00521 right_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
00522 {
00523 Oid operOid;
00524 OprCacheKey key;
00525 bool key_ok;
00526 FuncDetailCode fdresult = FUNCDETAIL_NOTFOUND;
00527 HeapTuple tup = NULL;
00528
00529
00530
00531
00532 key_ok = make_oper_cache_key(&key, op, arg, InvalidOid);
00533 if (key_ok)
00534 {
00535 operOid = find_oper_cache_entry(&key);
00536 if (OidIsValid(operOid))
00537 {
00538 tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
00539 if (HeapTupleIsValid(tup))
00540 return (Operator) tup;
00541 }
00542 }
00543
00544
00545
00546
00547 operOid = OpernameGetOprid(op, arg, InvalidOid);
00548 if (!OidIsValid(operOid))
00549 {
00550
00551
00552
00553 FuncCandidateList clist;
00554
00555
00556 clist = OpernameGetCandidates(op, 'r');
00557
00558
00559 if (clist != NULL)
00560 {
00561
00562
00563
00564
00565 fdresult = oper_select_candidate(1, &arg, clist, &operOid);
00566 }
00567 }
00568
00569 if (OidIsValid(operOid))
00570 tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
00571
00572 if (HeapTupleIsValid(tup))
00573 {
00574 if (key_ok)
00575 make_oper_cache_entry(&key, operOid);
00576 }
00577 else if (!noError)
00578 op_error(pstate, op, 'r', arg, InvalidOid, fdresult, location);
00579
00580 return (Operator) tup;
00581 }
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598 Operator
00599 left_oper(ParseState *pstate, List *op, Oid arg, bool noError, int location)
00600 {
00601 Oid operOid;
00602 OprCacheKey key;
00603 bool key_ok;
00604 FuncDetailCode fdresult = FUNCDETAIL_NOTFOUND;
00605 HeapTuple tup = NULL;
00606
00607
00608
00609
00610 key_ok = make_oper_cache_key(&key, op, InvalidOid, arg);
00611 if (key_ok)
00612 {
00613 operOid = find_oper_cache_entry(&key);
00614 if (OidIsValid(operOid))
00615 {
00616 tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
00617 if (HeapTupleIsValid(tup))
00618 return (Operator) tup;
00619 }
00620 }
00621
00622
00623
00624
00625 operOid = OpernameGetOprid(op, InvalidOid, arg);
00626 if (!OidIsValid(operOid))
00627 {
00628
00629
00630
00631 FuncCandidateList clist;
00632
00633
00634 clist = OpernameGetCandidates(op, 'l');
00635
00636
00637 if (clist != NULL)
00638 {
00639
00640
00641
00642
00643
00644 FuncCandidateList clisti;
00645
00646 for (clisti = clist; clisti != NULL; clisti = clisti->next)
00647 {
00648 clisti->args[0] = clisti->args[1];
00649 }
00650
00651
00652
00653
00654
00655 fdresult = oper_select_candidate(1, &arg, clist, &operOid);
00656 }
00657 }
00658
00659 if (OidIsValid(operOid))
00660 tup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operOid));
00661
00662 if (HeapTupleIsValid(tup))
00663 {
00664 if (key_ok)
00665 make_oper_cache_entry(&key, operOid);
00666 }
00667 else if (!noError)
00668 op_error(pstate, op, 'l', InvalidOid, arg, fdresult, location);
00669
00670 return (Operator) tup;
00671 }
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681 static const char *
00682 op_signature_string(List *op, char oprkind, Oid arg1, Oid arg2)
00683 {
00684 StringInfoData argbuf;
00685
00686 initStringInfo(&argbuf);
00687
00688 if (oprkind != 'l')
00689 appendStringInfo(&argbuf, "%s ", format_type_be(arg1));
00690
00691 appendStringInfoString(&argbuf, NameListToString(op));
00692
00693 if (oprkind != 'r')
00694 appendStringInfo(&argbuf, " %s", format_type_be(arg2));
00695
00696 return argbuf.data;
00697 }
00698
00699
00700
00701
00702 static void
00703 op_error(ParseState *pstate, List *op, char oprkind,
00704 Oid arg1, Oid arg2,
00705 FuncDetailCode fdresult, int location)
00706 {
00707 if (fdresult == FUNCDETAIL_MULTIPLE)
00708 ereport(ERROR,
00709 (errcode(ERRCODE_AMBIGUOUS_FUNCTION),
00710 errmsg("operator is not unique: %s",
00711 op_signature_string(op, oprkind, arg1, arg2)),
00712 errhint("Could not choose a best candidate operator. "
00713 "You might need to add explicit type casts."),
00714 parser_errposition(pstate, location)));
00715 else
00716 ereport(ERROR,
00717 (errcode(ERRCODE_UNDEFINED_FUNCTION),
00718 errmsg("operator does not exist: %s",
00719 op_signature_string(op, oprkind, arg1, arg2)),
00720 errhint("No operator matches the given name and argument type(s). "
00721 "You might need to add explicit type casts."),
00722 parser_errposition(pstate, location)));
00723 }
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735 Expr *
00736 make_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree,
00737 int location)
00738 {
00739 Oid ltypeId,
00740 rtypeId;
00741 Operator tup;
00742 Form_pg_operator opform;
00743 Oid actual_arg_types[2];
00744 Oid declared_arg_types[2];
00745 int nargs;
00746 List *args;
00747 Oid rettype;
00748 OpExpr *result;
00749
00750
00751 if (rtree == NULL)
00752 {
00753
00754 ltypeId = exprType(ltree);
00755 rtypeId = InvalidOid;
00756 tup = right_oper(pstate, opname, ltypeId, false, location);
00757 }
00758 else if (ltree == NULL)
00759 {
00760
00761 rtypeId = exprType(rtree);
00762 ltypeId = InvalidOid;
00763 tup = left_oper(pstate, opname, rtypeId, false, location);
00764 }
00765 else
00766 {
00767
00768 ltypeId = exprType(ltree);
00769 rtypeId = exprType(rtree);
00770 tup = oper(pstate, opname, ltypeId, rtypeId, false, location);
00771 }
00772
00773 opform = (Form_pg_operator) GETSTRUCT(tup);
00774
00775
00776 if (!RegProcedureIsValid(opform->oprcode))
00777 ereport(ERROR,
00778 (errcode(ERRCODE_UNDEFINED_FUNCTION),
00779 errmsg("operator is only a shell: %s",
00780 op_signature_string(opname,
00781 opform->oprkind,
00782 opform->oprleft,
00783 opform->oprright)),
00784 parser_errposition(pstate, location)));
00785
00786
00787 if (rtree == NULL)
00788 {
00789
00790 args = list_make1(ltree);
00791 actual_arg_types[0] = ltypeId;
00792 declared_arg_types[0] = opform->oprleft;
00793 nargs = 1;
00794 }
00795 else if (ltree == NULL)
00796 {
00797
00798 args = list_make1(rtree);
00799 actual_arg_types[0] = rtypeId;
00800 declared_arg_types[0] = opform->oprright;
00801 nargs = 1;
00802 }
00803 else
00804 {
00805
00806 args = list_make2(ltree, rtree);
00807 actual_arg_types[0] = ltypeId;
00808 actual_arg_types[1] = rtypeId;
00809 declared_arg_types[0] = opform->oprleft;
00810 declared_arg_types[1] = opform->oprright;
00811 nargs = 2;
00812 }
00813
00814
00815
00816
00817
00818
00819 rettype = enforce_generic_type_consistency(actual_arg_types,
00820 declared_arg_types,
00821 nargs,
00822 opform->oprresult,
00823 false);
00824
00825
00826 make_fn_arguments(pstate, args, actual_arg_types, declared_arg_types);
00827
00828
00829 result = makeNode(OpExpr);
00830 result->opno = oprid(tup);
00831 result->opfuncid = opform->oprcode;
00832 result->opresulttype = rettype;
00833 result->opretset = get_func_retset(opform->oprcode);
00834
00835 result->args = args;
00836 result->location = location;
00837
00838 ReleaseSysCache(tup);
00839
00840 return (Expr *) result;
00841 }
00842
00843
00844
00845
00846
00847 Expr *
00848 make_scalar_array_op(ParseState *pstate, List *opname,
00849 bool useOr,
00850 Node *ltree, Node *rtree,
00851 int location)
00852 {
00853 Oid ltypeId,
00854 rtypeId,
00855 atypeId,
00856 res_atypeId;
00857 Operator tup;
00858 Form_pg_operator opform;
00859 Oid actual_arg_types[2];
00860 Oid declared_arg_types[2];
00861 List *args;
00862 Oid rettype;
00863 ScalarArrayOpExpr *result;
00864
00865 ltypeId = exprType(ltree);
00866 atypeId = exprType(rtree);
00867
00868
00869
00870
00871
00872
00873 if (atypeId == UNKNOWNOID)
00874 rtypeId = UNKNOWNOID;
00875 else
00876 {
00877 rtypeId = get_base_element_type(atypeId);
00878 if (!OidIsValid(rtypeId))
00879 ereport(ERROR,
00880 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
00881 errmsg("op ANY/ALL (array) requires array on right side"),
00882 parser_errposition(pstate, location)));
00883 }
00884
00885
00886 tup = oper(pstate, opname, ltypeId, rtypeId, false, location);
00887 opform = (Form_pg_operator) GETSTRUCT(tup);
00888
00889
00890 if (!RegProcedureIsValid(opform->oprcode))
00891 ereport(ERROR,
00892 (errcode(ERRCODE_UNDEFINED_FUNCTION),
00893 errmsg("operator is only a shell: %s",
00894 op_signature_string(opname,
00895 opform->oprkind,
00896 opform->oprleft,
00897 opform->oprright)),
00898 parser_errposition(pstate, location)));
00899
00900 args = list_make2(ltree, rtree);
00901 actual_arg_types[0] = ltypeId;
00902 actual_arg_types[1] = rtypeId;
00903 declared_arg_types[0] = opform->oprleft;
00904 declared_arg_types[1] = opform->oprright;
00905
00906
00907
00908
00909
00910
00911 rettype = enforce_generic_type_consistency(actual_arg_types,
00912 declared_arg_types,
00913 2,
00914 opform->oprresult,
00915 false);
00916
00917
00918
00919
00920 if (rettype != BOOLOID)
00921 ereport(ERROR,
00922 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
00923 errmsg("op ANY/ALL (array) requires operator to yield boolean"),
00924 parser_errposition(pstate, location)));
00925 if (get_func_retset(opform->oprcode))
00926 ereport(ERROR,
00927 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
00928 errmsg("op ANY/ALL (array) requires operator not to return a set"),
00929 parser_errposition(pstate, location)));
00930
00931
00932
00933
00934
00935
00936
00937 if (IsPolymorphicType(declared_arg_types[1]))
00938 {
00939
00940 res_atypeId = atypeId;
00941 }
00942 else
00943 {
00944 res_atypeId = get_array_type(declared_arg_types[1]);
00945 if (!OidIsValid(res_atypeId))
00946 ereport(ERROR,
00947 (errcode(ERRCODE_UNDEFINED_OBJECT),
00948 errmsg("could not find array type for data type %s",
00949 format_type_be(declared_arg_types[1])),
00950 parser_errposition(pstate, location)));
00951 }
00952 actual_arg_types[1] = atypeId;
00953 declared_arg_types[1] = res_atypeId;
00954
00955
00956 make_fn_arguments(pstate, args, actual_arg_types, declared_arg_types);
00957
00958
00959 result = makeNode(ScalarArrayOpExpr);
00960 result->opno = oprid(tup);
00961 result->opfuncid = opform->oprcode;
00962 result->useOr = useOr;
00963
00964 result->args = args;
00965 result->location = location;
00966
00967 ReleaseSysCache(tup);
00968
00969 return (Expr *) result;
00970 }
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000 static HTAB *OprCacheHash = NULL;
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010 static bool
01011 make_oper_cache_key(OprCacheKey *key, List *opname, Oid ltypeId, Oid rtypeId)
01012 {
01013 char *schemaname;
01014 char *opername;
01015
01016
01017 DeconstructQualifiedName(opname, &schemaname, &opername);
01018
01019
01020 MemSet(key, 0, sizeof(OprCacheKey));
01021
01022
01023 strlcpy(key->oprname, opername, NAMEDATALEN);
01024 key->left_arg = ltypeId;
01025 key->right_arg = rtypeId;
01026
01027 if (schemaname)
01028 {
01029
01030 key->search_path[0] = LookupExplicitNamespace(schemaname, false);
01031 }
01032 else
01033 {
01034
01035 if (fetch_search_path_array(key->search_path,
01036 MAX_CACHED_PATH_LEN) > MAX_CACHED_PATH_LEN)
01037 return false;
01038 }
01039
01040 return true;
01041 }
01042
01043
01044
01045
01046
01047
01048
01049 static Oid
01050 find_oper_cache_entry(OprCacheKey *key)
01051 {
01052 OprCacheEntry *oprentry;
01053
01054 if (OprCacheHash == NULL)
01055 {
01056
01057 HASHCTL ctl;
01058
01059 MemSet(&ctl, 0, sizeof(ctl));
01060 ctl.keysize = sizeof(OprCacheKey);
01061 ctl.entrysize = sizeof(OprCacheEntry);
01062 ctl.hash = tag_hash;
01063 OprCacheHash = hash_create("Operator lookup cache", 256,
01064 &ctl, HASH_ELEM | HASH_FUNCTION);
01065
01066
01067 CacheRegisterSyscacheCallback(OPERNAMENSP,
01068 InvalidateOprCacheCallBack,
01069 (Datum) 0);
01070 CacheRegisterSyscacheCallback(CASTSOURCETARGET,
01071 InvalidateOprCacheCallBack,
01072 (Datum) 0);
01073 }
01074
01075
01076 oprentry = (OprCacheEntry *) hash_search(OprCacheHash,
01077 (void *) key,
01078 HASH_FIND, NULL);
01079 if (oprentry == NULL)
01080 return InvalidOid;
01081
01082 return oprentry->opr_oid;
01083 }
01084
01085
01086
01087
01088
01089
01090 static void
01091 make_oper_cache_entry(OprCacheKey *key, Oid opr_oid)
01092 {
01093 OprCacheEntry *oprentry;
01094
01095 Assert(OprCacheHash != NULL);
01096
01097 oprentry = (OprCacheEntry *) hash_search(OprCacheHash,
01098 (void *) key,
01099 HASH_ENTER, NULL);
01100 oprentry->opr_oid = opr_oid;
01101 }
01102
01103
01104
01105
01106 static void
01107 InvalidateOprCacheCallBack(Datum arg, int cacheid, uint32 hashvalue)
01108 {
01109 HASH_SEQ_STATUS status;
01110 OprCacheEntry *hentry;
01111
01112 Assert(OprCacheHash != NULL);
01113
01114
01115 hash_seq_init(&status, OprCacheHash);
01116
01117 while ((hentry = (OprCacheEntry *) hash_seq_search(&status)) != NULL)
01118 {
01119 if (hash_search(OprCacheHash,
01120 (void *) &hentry->key,
01121 HASH_REMOVE, NULL) == NULL)
01122 elog(ERROR, "hash table corrupted");
01123 }
01124 }