00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "postgres.h"
00017
00018 #include "access/hash.h"
00019 #include "access/htup_details.h"
00020 #include "access/nbtree.h"
00021 #include "bootstrap/bootstrap.h"
00022 #include "catalog/pg_amop.h"
00023 #include "catalog/pg_amproc.h"
00024 #include "catalog/pg_collation.h"
00025 #include "catalog/pg_constraint.h"
00026 #include "catalog/pg_namespace.h"
00027 #include "catalog/pg_opclass.h"
00028 #include "catalog/pg_operator.h"
00029 #include "catalog/pg_proc.h"
00030 #include "catalog/pg_range.h"
00031 #include "catalog/pg_statistic.h"
00032 #include "catalog/pg_type.h"
00033 #include "miscadmin.h"
00034 #include "nodes/makefuncs.h"
00035 #include "utils/array.h"
00036 #include "utils/builtins.h"
00037 #include "utils/catcache.h"
00038 #include "utils/datum.h"
00039 #include "utils/fmgroids.h"
00040 #include "utils/lsyscache.h"
00041 #include "utils/rel.h"
00042 #include "utils/syscache.h"
00043 #include "utils/typcache.h"
00044
00045
00046 get_attavgwidth_hook_type get_attavgwidth_hook = NULL;
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 bool
00059 op_in_opfamily(Oid opno, Oid opfamily)
00060 {
00061 return SearchSysCacheExists3(AMOPOPID,
00062 ObjectIdGetDatum(opno),
00063 CharGetDatum(AMOP_SEARCH),
00064 ObjectIdGetDatum(opfamily));
00065 }
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 int
00076 get_op_opfamily_strategy(Oid opno, Oid opfamily)
00077 {
00078 HeapTuple tp;
00079 Form_pg_amop amop_tup;
00080 int result;
00081
00082 tp = SearchSysCache3(AMOPOPID,
00083 ObjectIdGetDatum(opno),
00084 CharGetDatum(AMOP_SEARCH),
00085 ObjectIdGetDatum(opfamily));
00086 if (!HeapTupleIsValid(tp))
00087 return 0;
00088 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
00089 result = amop_tup->amopstrategy;
00090 ReleaseSysCache(tp);
00091 return result;
00092 }
00093
00094
00095
00096
00097
00098
00099
00100 Oid
00101 get_op_opfamily_sortfamily(Oid opno, Oid opfamily)
00102 {
00103 HeapTuple tp;
00104 Form_pg_amop amop_tup;
00105 Oid result;
00106
00107 tp = SearchSysCache3(AMOPOPID,
00108 ObjectIdGetDatum(opno),
00109 CharGetDatum(AMOP_ORDER),
00110 ObjectIdGetDatum(opfamily));
00111 if (!HeapTupleIsValid(tp))
00112 return InvalidOid;
00113 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
00114 result = amop_tup->amopsortfamily;
00115 ReleaseSysCache(tp);
00116 return result;
00117 }
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 void
00129 get_op_opfamily_properties(Oid opno, Oid opfamily, bool ordering_op,
00130 int *strategy,
00131 Oid *lefttype,
00132 Oid *righttype)
00133 {
00134 HeapTuple tp;
00135 Form_pg_amop amop_tup;
00136
00137 tp = SearchSysCache3(AMOPOPID,
00138 ObjectIdGetDatum(opno),
00139 CharGetDatum(ordering_op ? AMOP_ORDER : AMOP_SEARCH),
00140 ObjectIdGetDatum(opfamily));
00141 if (!HeapTupleIsValid(tp))
00142 elog(ERROR, "operator %u is not a member of opfamily %u",
00143 opno, opfamily);
00144 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
00145 *strategy = amop_tup->amopstrategy;
00146 *lefttype = amop_tup->amoplefttype;
00147 *righttype = amop_tup->amoprighttype;
00148 ReleaseSysCache(tp);
00149 }
00150
00151
00152
00153
00154
00155
00156
00157
00158 Oid
00159 get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype,
00160 int16 strategy)
00161 {
00162 HeapTuple tp;
00163 Form_pg_amop amop_tup;
00164 Oid result;
00165
00166 tp = SearchSysCache4(AMOPSTRATEGY,
00167 ObjectIdGetDatum(opfamily),
00168 ObjectIdGetDatum(lefttype),
00169 ObjectIdGetDatum(righttype),
00170 Int16GetDatum(strategy));
00171 if (!HeapTupleIsValid(tp))
00172 return InvalidOid;
00173 amop_tup = (Form_pg_amop) GETSTRUCT(tp);
00174 result = amop_tup->amopopr;
00175 ReleaseSysCache(tp);
00176 return result;
00177 }
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199 bool
00200 get_ordering_op_properties(Oid opno,
00201 Oid *opfamily, Oid *opcintype, int16 *strategy)
00202 {
00203 bool result = false;
00204 CatCList *catlist;
00205 int i;
00206
00207
00208 *opfamily = InvalidOid;
00209 *opcintype = InvalidOid;
00210 *strategy = 0;
00211
00212
00213
00214
00215
00216 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
00217
00218 for (i = 0; i < catlist->n_members; i++)
00219 {
00220 HeapTuple tuple = &catlist->members[i]->tuple;
00221 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
00222
00223
00224 if (aform->amopmethod != BTREE_AM_OID)
00225 continue;
00226
00227 if (aform->amopstrategy == BTLessStrategyNumber ||
00228 aform->amopstrategy == BTGreaterStrategyNumber)
00229 {
00230
00231 if (aform->amoplefttype == aform->amoprighttype)
00232 {
00233
00234 *opfamily = aform->amopfamily;
00235 *opcintype = aform->amoplefttype;
00236 *strategy = aform->amopstrategy;
00237 result = true;
00238 break;
00239 }
00240 }
00241 }
00242
00243 ReleaseSysCacheList(catlist);
00244
00245 return result;
00246 }
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262 bool
00263 get_sort_function_for_ordering_op(Oid opno, Oid *sortfunc,
00264 bool *issupport, bool *reverse)
00265 {
00266 Oid opfamily;
00267 Oid opcintype;
00268 int16 strategy;
00269
00270
00271 if (get_ordering_op_properties(opno,
00272 &opfamily, &opcintype, &strategy))
00273 {
00274
00275 *sortfunc = get_opfamily_proc(opfamily,
00276 opcintype,
00277 opcintype,
00278 BTSORTSUPPORT_PROC);
00279 if (OidIsValid(*sortfunc))
00280 *issupport = true;
00281 else
00282 {
00283
00284 *sortfunc = get_opfamily_proc(opfamily,
00285 opcintype,
00286 opcintype,
00287 BTORDER_PROC);
00288 if (!OidIsValid(*sortfunc))
00289 elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
00290 BTORDER_PROC, opcintype, opcintype, opfamily);
00291 *issupport = false;
00292 }
00293 *reverse = (strategy == BTGreaterStrategyNumber);
00294 return true;
00295 }
00296
00297
00298 *sortfunc = InvalidOid;
00299 *issupport = false;
00300 *reverse = false;
00301 return false;
00302 }
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315 Oid
00316 get_equality_op_for_ordering_op(Oid opno, bool *reverse)
00317 {
00318 Oid result = InvalidOid;
00319 Oid opfamily;
00320 Oid opcintype;
00321 int16 strategy;
00322
00323
00324 if (get_ordering_op_properties(opno,
00325 &opfamily, &opcintype, &strategy))
00326 {
00327
00328 result = get_opfamily_member(opfamily,
00329 opcintype,
00330 opcintype,
00331 BTEqualStrategyNumber);
00332 if (reverse)
00333 *reverse = (strategy == BTGreaterStrategyNumber);
00334 }
00335
00336 return result;
00337 }
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353 Oid
00354 get_ordering_op_for_equality_op(Oid opno, bool use_lhs_type)
00355 {
00356 Oid result = InvalidOid;
00357 CatCList *catlist;
00358 int i;
00359
00360
00361
00362
00363
00364 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
00365
00366 for (i = 0; i < catlist->n_members; i++)
00367 {
00368 HeapTuple tuple = &catlist->members[i]->tuple;
00369 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
00370
00371
00372 if (aform->amopmethod != BTREE_AM_OID)
00373 continue;
00374
00375 if (aform->amopstrategy == BTEqualStrategyNumber)
00376 {
00377
00378 Oid typid;
00379
00380 typid = use_lhs_type ? aform->amoplefttype : aform->amoprighttype;
00381 result = get_opfamily_member(aform->amopfamily,
00382 typid, typid,
00383 BTLessStrategyNumber);
00384 if (OidIsValid(result))
00385 break;
00386
00387 }
00388 }
00389
00390 ReleaseSysCacheList(catlist);
00391
00392 return result;
00393 }
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414 List *
00415 get_mergejoin_opfamilies(Oid opno)
00416 {
00417 List *result = NIL;
00418 CatCList *catlist;
00419 int i;
00420
00421
00422
00423
00424
00425 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
00426
00427 for (i = 0; i < catlist->n_members; i++)
00428 {
00429 HeapTuple tuple = &catlist->members[i]->tuple;
00430 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
00431
00432
00433 if (aform->amopmethod == BTREE_AM_OID &&
00434 aform->amopstrategy == BTEqualStrategyNumber)
00435 result = lappend_oid(result, aform->amopfamily);
00436 }
00437
00438 ReleaseSysCacheList(catlist);
00439
00440 return result;
00441 }
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458 bool
00459 get_compatible_hash_operators(Oid opno,
00460 Oid *lhs_opno, Oid *rhs_opno)
00461 {
00462 bool result = false;
00463 CatCList *catlist;
00464 int i;
00465
00466
00467 if (lhs_opno)
00468 *lhs_opno = InvalidOid;
00469 if (rhs_opno)
00470 *rhs_opno = InvalidOid;
00471
00472
00473
00474
00475
00476
00477 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
00478
00479 for (i = 0; i < catlist->n_members; i++)
00480 {
00481 HeapTuple tuple = &catlist->members[i]->tuple;
00482 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
00483
00484 if (aform->amopmethod == HASH_AM_OID &&
00485 aform->amopstrategy == HTEqualStrategyNumber)
00486 {
00487
00488 if (aform->amoplefttype == aform->amoprighttype)
00489 {
00490 if (lhs_opno)
00491 *lhs_opno = opno;
00492 if (rhs_opno)
00493 *rhs_opno = opno;
00494 result = true;
00495 break;
00496 }
00497
00498
00499
00500
00501
00502
00503 if (lhs_opno)
00504 {
00505 *lhs_opno = get_opfamily_member(aform->amopfamily,
00506 aform->amoplefttype,
00507 aform->amoplefttype,
00508 HTEqualStrategyNumber);
00509 if (!OidIsValid(*lhs_opno))
00510 continue;
00511
00512 if (!rhs_opno)
00513 {
00514 result = true;
00515 break;
00516 }
00517 }
00518 if (rhs_opno)
00519 {
00520 *rhs_opno = get_opfamily_member(aform->amopfamily,
00521 aform->amoprighttype,
00522 aform->amoprighttype,
00523 HTEqualStrategyNumber);
00524 if (!OidIsValid(*rhs_opno))
00525 {
00526
00527 if (lhs_opno)
00528 *lhs_opno = InvalidOid;
00529 continue;
00530 }
00531
00532 result = true;
00533 break;
00534 }
00535 }
00536 }
00537
00538 ReleaseSysCacheList(catlist);
00539
00540 return result;
00541 }
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558 bool
00559 get_op_hash_functions(Oid opno,
00560 RegProcedure *lhs_procno, RegProcedure *rhs_procno)
00561 {
00562 bool result = false;
00563 CatCList *catlist;
00564 int i;
00565
00566
00567 if (lhs_procno)
00568 *lhs_procno = InvalidOid;
00569 if (rhs_procno)
00570 *rhs_procno = InvalidOid;
00571
00572
00573
00574
00575
00576
00577 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
00578
00579 for (i = 0; i < catlist->n_members; i++)
00580 {
00581 HeapTuple tuple = &catlist->members[i]->tuple;
00582 Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
00583
00584 if (aform->amopmethod == HASH_AM_OID &&
00585 aform->amopstrategy == HTEqualStrategyNumber)
00586 {
00587
00588
00589
00590
00591
00592 if (lhs_procno)
00593 {
00594 *lhs_procno = get_opfamily_proc(aform->amopfamily,
00595 aform->amoplefttype,
00596 aform->amoplefttype,
00597 HASHPROC);
00598 if (!OidIsValid(*lhs_procno))
00599 continue;
00600
00601 if (!rhs_procno)
00602 {
00603 result = true;
00604 break;
00605 }
00606
00607 if (aform->amoplefttype == aform->amoprighttype)
00608 {
00609 *rhs_procno = *lhs_procno;
00610 result = true;
00611 break;
00612 }
00613 }
00614 if (rhs_procno)
00615 {
00616 *rhs_procno = get_opfamily_proc(aform->amopfamily,
00617 aform->amoprighttype,
00618 aform->amoprighttype,
00619 HASHPROC);
00620 if (!OidIsValid(*rhs_procno))
00621 {
00622
00623 if (lhs_procno)
00624 *lhs_procno = InvalidOid;
00625 continue;
00626 }
00627
00628 result = true;
00629 break;
00630 }
00631 }
00632 }
00633
00634 ReleaseSysCacheList(catlist);
00635
00636 return result;
00637 }
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649 List *
00650 get_op_btree_interpretation(Oid opno)
00651 {
00652 List *result = NIL;
00653 OpBtreeInterpretation *thisresult;
00654 CatCList *catlist;
00655 int i;
00656
00657
00658
00659
00660 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
00661
00662 for (i = 0; i < catlist->n_members; i++)
00663 {
00664 HeapTuple op_tuple = &catlist->members[i]->tuple;
00665 Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
00666 StrategyNumber op_strategy;
00667
00668
00669 if (op_form->amopmethod != BTREE_AM_OID)
00670 continue;
00671
00672
00673 op_strategy = (StrategyNumber) op_form->amopstrategy;
00674 Assert(op_strategy >= 1 && op_strategy <= 5);
00675
00676 thisresult = (OpBtreeInterpretation *)
00677 palloc(sizeof(OpBtreeInterpretation));
00678 thisresult->opfamily_id = op_form->amopfamily;
00679 thisresult->strategy = op_strategy;
00680 thisresult->oplefttype = op_form->amoplefttype;
00681 thisresult->oprighttype = op_form->amoprighttype;
00682 result = lappend(result, thisresult);
00683 }
00684
00685 ReleaseSysCacheList(catlist);
00686
00687
00688
00689
00690
00691 if (result == NIL)
00692 {
00693 Oid op_negator = get_negator(opno);
00694
00695 if (OidIsValid(op_negator))
00696 {
00697 catlist = SearchSysCacheList1(AMOPOPID,
00698 ObjectIdGetDatum(op_negator));
00699
00700 for (i = 0; i < catlist->n_members; i++)
00701 {
00702 HeapTuple op_tuple = &catlist->members[i]->tuple;
00703 Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
00704 StrategyNumber op_strategy;
00705
00706
00707 if (op_form->amopmethod != BTREE_AM_OID)
00708 continue;
00709
00710
00711 op_strategy = (StrategyNumber) op_form->amopstrategy;
00712 Assert(op_strategy >= 1 && op_strategy <= 5);
00713
00714
00715 if (op_strategy != BTEqualStrategyNumber)
00716 continue;
00717
00718
00719 thisresult = (OpBtreeInterpretation *)
00720 palloc(sizeof(OpBtreeInterpretation));
00721 thisresult->opfamily_id = op_form->amopfamily;
00722 thisresult->strategy = ROWCOMPARE_NE;
00723 thisresult->oplefttype = op_form->amoplefttype;
00724 thisresult->oprighttype = op_form->amoprighttype;
00725 result = lappend(result, thisresult);
00726 }
00727
00728 ReleaseSysCacheList(catlist);
00729 }
00730 }
00731
00732 return result;
00733 }
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746 bool
00747 equality_ops_are_compatible(Oid opno1, Oid opno2)
00748 {
00749 bool result;
00750 CatCList *catlist;
00751 int i;
00752
00753
00754 if (opno1 == opno2)
00755 return true;
00756
00757
00758
00759
00760 catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno1));
00761
00762 result = false;
00763 for (i = 0; i < catlist->n_members; i++)
00764 {
00765 HeapTuple op_tuple = &catlist->members[i]->tuple;
00766 Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
00767
00768
00769 if (op_form->amopmethod == BTREE_AM_OID ||
00770 op_form->amopmethod == HASH_AM_OID)
00771 {
00772 if (op_in_opfamily(opno2, op_form->amopfamily))
00773 {
00774 result = true;
00775 break;
00776 }
00777 }
00778 }
00779
00780 ReleaseSysCacheList(catlist);
00781
00782 return result;
00783 }
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795 Oid
00796 get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
00797 {
00798 HeapTuple tp;
00799 Form_pg_amproc amproc_tup;
00800 RegProcedure result;
00801
00802 tp = SearchSysCache4(AMPROCNUM,
00803 ObjectIdGetDatum(opfamily),
00804 ObjectIdGetDatum(lefttype),
00805 ObjectIdGetDatum(righttype),
00806 Int16GetDatum(procnum));
00807 if (!HeapTupleIsValid(tp))
00808 return InvalidOid;
00809 amproc_tup = (Form_pg_amproc) GETSTRUCT(tp);
00810 result = amproc_tup->amproc;
00811 ReleaseSysCache(tp);
00812 return result;
00813 }
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825 char *
00826 get_attname(Oid relid, AttrNumber attnum)
00827 {
00828 HeapTuple tp;
00829
00830 tp = SearchSysCache2(ATTNUM,
00831 ObjectIdGetDatum(relid),
00832 Int16GetDatum(attnum));
00833 if (HeapTupleIsValid(tp))
00834 {
00835 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
00836 char *result;
00837
00838 result = pstrdup(NameStr(att_tup->attname));
00839 ReleaseSysCache(tp);
00840 return result;
00841 }
00842 else
00843 return NULL;
00844 }
00845
00846
00847
00848
00849
00850
00851
00852 char *
00853 get_relid_attribute_name(Oid relid, AttrNumber attnum)
00854 {
00855 char *attname;
00856
00857 attname = get_attname(relid, attnum);
00858 if (attname == NULL)
00859 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
00860 attnum, relid);
00861 return attname;
00862 }
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872 AttrNumber
00873 get_attnum(Oid relid, const char *attname)
00874 {
00875 HeapTuple tp;
00876
00877 tp = SearchSysCacheAttName(relid, attname);
00878 if (HeapTupleIsValid(tp))
00879 {
00880 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
00881 AttrNumber result;
00882
00883 result = att_tup->attnum;
00884 ReleaseSysCache(tp);
00885 return result;
00886 }
00887 else
00888 return InvalidAttrNumber;
00889 }
00890
00891
00892
00893
00894
00895
00896
00897 Oid
00898 get_atttype(Oid relid, AttrNumber attnum)
00899 {
00900 HeapTuple tp;
00901
00902 tp = SearchSysCache2(ATTNUM,
00903 ObjectIdGetDatum(relid),
00904 Int16GetDatum(attnum));
00905 if (HeapTupleIsValid(tp))
00906 {
00907 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
00908 Oid result;
00909
00910 result = att_tup->atttypid;
00911 ReleaseSysCache(tp);
00912 return result;
00913 }
00914 else
00915 return InvalidOid;
00916 }
00917
00918
00919
00920
00921
00922
00923
00924 int32
00925 get_atttypmod(Oid relid, AttrNumber attnum)
00926 {
00927 HeapTuple tp;
00928
00929 tp = SearchSysCache2(ATTNUM,
00930 ObjectIdGetDatum(relid),
00931 Int16GetDatum(attnum));
00932 if (HeapTupleIsValid(tp))
00933 {
00934 Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
00935 int32 result;
00936
00937 result = att_tup->atttypmod;
00938 ReleaseSysCache(tp);
00939 return result;
00940 }
00941 else
00942 return -1;
00943 }
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954 void
00955 get_atttypetypmodcoll(Oid relid, AttrNumber attnum,
00956 Oid *typid, int32 *typmod, Oid *collid)
00957 {
00958 HeapTuple tp;
00959 Form_pg_attribute att_tup;
00960
00961 tp = SearchSysCache2(ATTNUM,
00962 ObjectIdGetDatum(relid),
00963 Int16GetDatum(attnum));
00964 if (!HeapTupleIsValid(tp))
00965 elog(ERROR, "cache lookup failed for attribute %d of relation %u",
00966 attnum, relid);
00967 att_tup = (Form_pg_attribute) GETSTRUCT(tp);
00968
00969 *typid = att_tup->atttypid;
00970 *typmod = att_tup->atttypmod;
00971 *collid = att_tup->attcollation;
00972 ReleaseSysCache(tp);
00973 }
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986 char *
00987 get_collation_name(Oid colloid)
00988 {
00989 HeapTuple tp;
00990
00991 tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(colloid));
00992 if (HeapTupleIsValid(tp))
00993 {
00994 Form_pg_collation colltup = (Form_pg_collation) GETSTRUCT(tp);
00995 char *result;
00996
00997 result = pstrdup(NameStr(colltup->collname));
00998 ReleaseSysCache(tp);
00999 return result;
01000 }
01001 else
01002 return NULL;
01003 }
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016 char *
01017 get_constraint_name(Oid conoid)
01018 {
01019 HeapTuple tp;
01020
01021 tp = SearchSysCache1(CONSTROID, ObjectIdGetDatum(conoid));
01022 if (HeapTupleIsValid(tp))
01023 {
01024 Form_pg_constraint contup = (Form_pg_constraint) GETSTRUCT(tp);
01025 char *result;
01026
01027 result = pstrdup(NameStr(contup->conname));
01028 ReleaseSysCache(tp);
01029 return result;
01030 }
01031 else
01032 return NULL;
01033 }
01034
01035
01036
01037
01038
01039
01040
01041
01042 Oid
01043 get_opclass_family(Oid opclass)
01044 {
01045 HeapTuple tp;
01046 Form_pg_opclass cla_tup;
01047 Oid result;
01048
01049 tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
01050 if (!HeapTupleIsValid(tp))
01051 elog(ERROR, "cache lookup failed for opclass %u", opclass);
01052 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
01053
01054 result = cla_tup->opcfamily;
01055 ReleaseSysCache(tp);
01056 return result;
01057 }
01058
01059
01060
01061
01062
01063
01064 Oid
01065 get_opclass_input_type(Oid opclass)
01066 {
01067 HeapTuple tp;
01068 Form_pg_opclass cla_tup;
01069 Oid result;
01070
01071 tp = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
01072 if (!HeapTupleIsValid(tp))
01073 elog(ERROR, "cache lookup failed for opclass %u", opclass);
01074 cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
01075
01076 result = cla_tup->opcintype;
01077 ReleaseSysCache(tp);
01078 return result;
01079 }
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089 RegProcedure
01090 get_opcode(Oid opno)
01091 {
01092 HeapTuple tp;
01093
01094 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
01095 if (HeapTupleIsValid(tp))
01096 {
01097 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
01098 RegProcedure result;
01099
01100 result = optup->oprcode;
01101 ReleaseSysCache(tp);
01102 return result;
01103 }
01104 else
01105 return (RegProcedure) InvalidOid;
01106 }
01107
01108
01109
01110
01111
01112
01113
01114 char *
01115 get_opname(Oid opno)
01116 {
01117 HeapTuple tp;
01118
01119 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
01120 if (HeapTupleIsValid(tp))
01121 {
01122 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
01123 char *result;
01124
01125 result = pstrdup(NameStr(optup->oprname));
01126 ReleaseSysCache(tp);
01127 return result;
01128 }
01129 else
01130 return NULL;
01131 }
01132
01133
01134
01135
01136
01137
01138
01139 void
01140 op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
01141 {
01142 HeapTuple tp;
01143 Form_pg_operator optup;
01144
01145 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
01146 if (!HeapTupleIsValid(tp))
01147 elog(ERROR, "cache lookup failed for operator %u", opno);
01148 optup = (Form_pg_operator) GETSTRUCT(tp);
01149 *lefttype = optup->oprleft;
01150 *righttype = optup->oprright;
01151 ReleaseSysCache(tp);
01152 }
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167 bool
01168 op_mergejoinable(Oid opno, Oid inputtype)
01169 {
01170 bool result = false;
01171 HeapTuple tp;
01172 TypeCacheEntry *typentry;
01173
01174
01175
01176
01177
01178
01179
01180 if (opno == ARRAY_EQ_OP)
01181 {
01182 typentry = lookup_type_cache(inputtype, TYPECACHE_CMP_PROC);
01183 if (typentry->cmp_proc == F_BTARRAYCMP)
01184 result = true;
01185 }
01186 else if (opno == RECORD_EQ_OP)
01187 {
01188 typentry = lookup_type_cache(inputtype, TYPECACHE_CMP_PROC);
01189 if (typentry->cmp_proc == F_BTRECORDCMP)
01190 result = true;
01191 }
01192 else
01193 {
01194
01195 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
01196 if (HeapTupleIsValid(tp))
01197 {
01198 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
01199
01200 result = optup->oprcanmerge;
01201 ReleaseSysCache(tp);
01202 }
01203 }
01204 return result;
01205 }
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218 bool
01219 op_hashjoinable(Oid opno, Oid inputtype)
01220 {
01221 bool result = false;
01222 HeapTuple tp;
01223 TypeCacheEntry *typentry;
01224
01225
01226
01227 if (opno == ARRAY_EQ_OP)
01228 {
01229 typentry = lookup_type_cache(inputtype, TYPECACHE_HASH_PROC);
01230 if (typentry->hash_proc == F_HASH_ARRAY)
01231 result = true;
01232 }
01233 else
01234 {
01235
01236 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
01237 if (HeapTupleIsValid(tp))
01238 {
01239 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
01240
01241 result = optup->oprcanhash;
01242 ReleaseSysCache(tp);
01243 }
01244 }
01245 return result;
01246 }
01247
01248
01249
01250
01251
01252
01253 bool
01254 op_strict(Oid opno)
01255 {
01256 RegProcedure funcid = get_opcode(opno);
01257
01258 if (funcid == (RegProcedure) InvalidOid)
01259 elog(ERROR, "operator %u does not exist", opno);
01260
01261 return func_strict((Oid) funcid);
01262 }
01263
01264
01265
01266
01267
01268
01269 char
01270 op_volatile(Oid opno)
01271 {
01272 RegProcedure funcid = get_opcode(opno);
01273
01274 if (funcid == (RegProcedure) InvalidOid)
01275 elog(ERROR, "operator %u does not exist", opno);
01276
01277 return func_volatile((Oid) funcid);
01278 }
01279
01280
01281
01282
01283
01284
01285 Oid
01286 get_commutator(Oid opno)
01287 {
01288 HeapTuple tp;
01289
01290 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
01291 if (HeapTupleIsValid(tp))
01292 {
01293 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
01294 Oid result;
01295
01296 result = optup->oprcom;
01297 ReleaseSysCache(tp);
01298 return result;
01299 }
01300 else
01301 return InvalidOid;
01302 }
01303
01304
01305
01306
01307
01308
01309 Oid
01310 get_negator(Oid opno)
01311 {
01312 HeapTuple tp;
01313
01314 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
01315 if (HeapTupleIsValid(tp))
01316 {
01317 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
01318 Oid result;
01319
01320 result = optup->oprnegate;
01321 ReleaseSysCache(tp);
01322 return result;
01323 }
01324 else
01325 return InvalidOid;
01326 }
01327
01328
01329
01330
01331
01332
01333 RegProcedure
01334 get_oprrest(Oid opno)
01335 {
01336 HeapTuple tp;
01337
01338 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
01339 if (HeapTupleIsValid(tp))
01340 {
01341 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
01342 RegProcedure result;
01343
01344 result = optup->oprrest;
01345 ReleaseSysCache(tp);
01346 return result;
01347 }
01348 else
01349 return (RegProcedure) InvalidOid;
01350 }
01351
01352
01353
01354
01355
01356
01357 RegProcedure
01358 get_oprjoin(Oid opno)
01359 {
01360 HeapTuple tp;
01361
01362 tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
01363 if (HeapTupleIsValid(tp))
01364 {
01365 Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
01366 RegProcedure result;
01367
01368 result = optup->oprjoin;
01369 ReleaseSysCache(tp);
01370 return result;
01371 }
01372 else
01373 return (RegProcedure) InvalidOid;
01374 }
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384 char *
01385 get_func_name(Oid funcid)
01386 {
01387 HeapTuple tp;
01388
01389 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
01390 if (HeapTupleIsValid(tp))
01391 {
01392 Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
01393 char *result;
01394
01395 result = pstrdup(NameStr(functup->proname));
01396 ReleaseSysCache(tp);
01397 return result;
01398 }
01399 else
01400 return NULL;
01401 }
01402
01403
01404
01405
01406
01407
01408 Oid
01409 get_func_namespace(Oid funcid)
01410 {
01411 HeapTuple tp;
01412
01413 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
01414 if (HeapTupleIsValid(tp))
01415 {
01416 Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
01417 Oid result;
01418
01419 result = functup->pronamespace;
01420 ReleaseSysCache(tp);
01421 return result;
01422 }
01423 else
01424 return InvalidOid;
01425 }
01426
01427
01428
01429
01430
01431 Oid
01432 get_func_rettype(Oid funcid)
01433 {
01434 HeapTuple tp;
01435 Oid result;
01436
01437 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
01438 if (!HeapTupleIsValid(tp))
01439 elog(ERROR, "cache lookup failed for function %u", funcid);
01440
01441 result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
01442 ReleaseSysCache(tp);
01443 return result;
01444 }
01445
01446
01447
01448
01449
01450 int
01451 get_func_nargs(Oid funcid)
01452 {
01453 HeapTuple tp;
01454 int result;
01455
01456 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
01457 if (!HeapTupleIsValid(tp))
01458 elog(ERROR, "cache lookup failed for function %u", funcid);
01459
01460 result = ((Form_pg_proc) GETSTRUCT(tp))->pronargs;
01461 ReleaseSysCache(tp);
01462 return result;
01463 }
01464
01465
01466
01467
01468
01469
01470
01471
01472 Oid
01473 get_func_signature(Oid funcid, Oid **argtypes, int *nargs)
01474 {
01475 HeapTuple tp;
01476 Form_pg_proc procstruct;
01477 Oid result;
01478
01479 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
01480 if (!HeapTupleIsValid(tp))
01481 elog(ERROR, "cache lookup failed for function %u", funcid);
01482
01483 procstruct = (Form_pg_proc) GETSTRUCT(tp);
01484
01485 result = procstruct->prorettype;
01486 *nargs = (int) procstruct->pronargs;
01487 Assert(*nargs == procstruct->proargtypes.dim1);
01488 *argtypes = (Oid *) palloc(*nargs * sizeof(Oid));
01489 memcpy(*argtypes, procstruct->proargtypes.values, *nargs * sizeof(Oid));
01490
01491 ReleaseSysCache(tp);
01492 return result;
01493 }
01494
01495
01496
01497
01498
01499 bool
01500 get_func_retset(Oid funcid)
01501 {
01502 HeapTuple tp;
01503 bool result;
01504
01505 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
01506 if (!HeapTupleIsValid(tp))
01507 elog(ERROR, "cache lookup failed for function %u", funcid);
01508
01509 result = ((Form_pg_proc) GETSTRUCT(tp))->proretset;
01510 ReleaseSysCache(tp);
01511 return result;
01512 }
01513
01514
01515
01516
01517
01518 bool
01519 func_strict(Oid funcid)
01520 {
01521 HeapTuple tp;
01522 bool result;
01523
01524 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
01525 if (!HeapTupleIsValid(tp))
01526 elog(ERROR, "cache lookup failed for function %u", funcid);
01527
01528 result = ((Form_pg_proc) GETSTRUCT(tp))->proisstrict;
01529 ReleaseSysCache(tp);
01530 return result;
01531 }
01532
01533
01534
01535
01536
01537 char
01538 func_volatile(Oid funcid)
01539 {
01540 HeapTuple tp;
01541 char result;
01542
01543 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
01544 if (!HeapTupleIsValid(tp))
01545 elog(ERROR, "cache lookup failed for function %u", funcid);
01546
01547 result = ((Form_pg_proc) GETSTRUCT(tp))->provolatile;
01548 ReleaseSysCache(tp);
01549 return result;
01550 }
01551
01552
01553
01554
01555
01556 bool
01557 get_func_leakproof(Oid funcid)
01558 {
01559 HeapTuple tp;
01560 bool result;
01561
01562 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
01563 if (!HeapTupleIsValid(tp))
01564 elog(ERROR, "cache lookup failed for function %u", funcid);
01565
01566 result = ((Form_pg_proc) GETSTRUCT(tp))->proleakproof;
01567 ReleaseSysCache(tp);
01568 return result;
01569 }
01570
01571
01572
01573
01574
01575 float4
01576 get_func_cost(Oid funcid)
01577 {
01578 HeapTuple tp;
01579 float4 result;
01580
01581 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
01582 if (!HeapTupleIsValid(tp))
01583 elog(ERROR, "cache lookup failed for function %u", funcid);
01584
01585 result = ((Form_pg_proc) GETSTRUCT(tp))->procost;
01586 ReleaseSysCache(tp);
01587 return result;
01588 }
01589
01590
01591
01592
01593
01594 float4
01595 get_func_rows(Oid funcid)
01596 {
01597 HeapTuple tp;
01598 float4 result;
01599
01600 tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
01601 if (!HeapTupleIsValid(tp))
01602 elog(ERROR, "cache lookup failed for function %u", funcid);
01603
01604 result = ((Form_pg_proc) GETSTRUCT(tp))->prorows;
01605 ReleaseSysCache(tp);
01606 return result;
01607 }
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617 Oid
01618 get_relname_relid(const char *relname, Oid relnamespace)
01619 {
01620 return GetSysCacheOid2(RELNAMENSP,
01621 PointerGetDatum(relname),
01622 ObjectIdGetDatum(relnamespace));
01623 }
01624
01625 #ifdef NOT_USED
01626
01627
01628
01629
01630
01631 int
01632 get_relnatts(Oid relid)
01633 {
01634 HeapTuple tp;
01635
01636 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
01637 if (HeapTupleIsValid(tp))
01638 {
01639 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
01640 int result;
01641
01642 result = reltup->relnatts;
01643 ReleaseSysCache(tp);
01644 return result;
01645 }
01646 else
01647 return InvalidAttrNumber;
01648 }
01649 #endif
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660 char *
01661 get_rel_name(Oid relid)
01662 {
01663 HeapTuple tp;
01664
01665 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
01666 if (HeapTupleIsValid(tp))
01667 {
01668 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
01669 char *result;
01670
01671 result = pstrdup(NameStr(reltup->relname));
01672 ReleaseSysCache(tp);
01673 return result;
01674 }
01675 else
01676 return NULL;
01677 }
01678
01679
01680
01681
01682
01683
01684 Oid
01685 get_rel_namespace(Oid relid)
01686 {
01687 HeapTuple tp;
01688
01689 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
01690 if (HeapTupleIsValid(tp))
01691 {
01692 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
01693 Oid result;
01694
01695 result = reltup->relnamespace;
01696 ReleaseSysCache(tp);
01697 return result;
01698 }
01699 else
01700 return InvalidOid;
01701 }
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711 Oid
01712 get_rel_type_id(Oid relid)
01713 {
01714 HeapTuple tp;
01715
01716 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
01717 if (HeapTupleIsValid(tp))
01718 {
01719 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
01720 Oid result;
01721
01722 result = reltup->reltype;
01723 ReleaseSysCache(tp);
01724 return result;
01725 }
01726 else
01727 return InvalidOid;
01728 }
01729
01730
01731
01732
01733
01734
01735 char
01736 get_rel_relkind(Oid relid)
01737 {
01738 HeapTuple tp;
01739
01740 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
01741 if (HeapTupleIsValid(tp))
01742 {
01743 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
01744 char result;
01745
01746 result = reltup->relkind;
01747 ReleaseSysCache(tp);
01748 return result;
01749 }
01750 else
01751 return '\0';
01752 }
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762 Oid
01763 get_rel_tablespace(Oid relid)
01764 {
01765 HeapTuple tp;
01766
01767 tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
01768 if (HeapTupleIsValid(tp))
01769 {
01770 Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
01771 Oid result;
01772
01773 result = reltup->reltablespace;
01774 ReleaseSysCache(tp);
01775 return result;
01776 }
01777 else
01778 return InvalidOid;
01779 }
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790 bool
01791 get_typisdefined(Oid typid)
01792 {
01793 HeapTuple tp;
01794
01795 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
01796 if (HeapTupleIsValid(tp))
01797 {
01798 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
01799 bool result;
01800
01801 result = typtup->typisdefined;
01802 ReleaseSysCache(tp);
01803 return result;
01804 }
01805 else
01806 return false;
01807 }
01808
01809
01810
01811
01812
01813
01814 int16
01815 get_typlen(Oid typid)
01816 {
01817 HeapTuple tp;
01818
01819 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
01820 if (HeapTupleIsValid(tp))
01821 {
01822 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
01823 int16 result;
01824
01825 result = typtup->typlen;
01826 ReleaseSysCache(tp);
01827 return result;
01828 }
01829 else
01830 return 0;
01831 }
01832
01833
01834
01835
01836
01837
01838
01839 bool
01840 get_typbyval(Oid typid)
01841 {
01842 HeapTuple tp;
01843
01844 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
01845 if (HeapTupleIsValid(tp))
01846 {
01847 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
01848 bool result;
01849
01850 result = typtup->typbyval;
01851 ReleaseSysCache(tp);
01852 return result;
01853 }
01854 else
01855 return false;
01856 }
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868 void
01869 get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
01870 {
01871 HeapTuple tp;
01872 Form_pg_type typtup;
01873
01874 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
01875 if (!HeapTupleIsValid(tp))
01876 elog(ERROR, "cache lookup failed for type %u", typid);
01877 typtup = (Form_pg_type) GETSTRUCT(tp);
01878 *typlen = typtup->typlen;
01879 *typbyval = typtup->typbyval;
01880 ReleaseSysCache(tp);
01881 }
01882
01883
01884
01885
01886
01887
01888 void
01889 get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
01890 char *typalign)
01891 {
01892 HeapTuple tp;
01893 Form_pg_type typtup;
01894
01895 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
01896 if (!HeapTupleIsValid(tp))
01897 elog(ERROR, "cache lookup failed for type %u", typid);
01898 typtup = (Form_pg_type) GETSTRUCT(tp);
01899 *typlen = typtup->typlen;
01900 *typbyval = typtup->typbyval;
01901 *typalign = typtup->typalign;
01902 ReleaseSysCache(tp);
01903 }
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920 Oid
01921 getTypeIOParam(HeapTuple typeTuple)
01922 {
01923 Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
01924
01925
01926
01927
01928
01929 if (OidIsValid(typeStruct->typelem))
01930 return typeStruct->typelem;
01931 else
01932 return HeapTupleGetOid(typeTuple);
01933 }
01934
01935
01936
01937
01938
01939
01940
01941
01942 void
01943 get_type_io_data(Oid typid,
01944 IOFuncSelector which_func,
01945 int16 *typlen,
01946 bool *typbyval,
01947 char *typalign,
01948 char *typdelim,
01949 Oid *typioparam,
01950 Oid *func)
01951 {
01952 HeapTuple typeTuple;
01953 Form_pg_type typeStruct;
01954
01955
01956
01957
01958
01959 if (IsBootstrapProcessingMode())
01960 {
01961 Oid typinput;
01962 Oid typoutput;
01963
01964 boot_get_type_io_data(typid,
01965 typlen,
01966 typbyval,
01967 typalign,
01968 typdelim,
01969 typioparam,
01970 &typinput,
01971 &typoutput);
01972 switch (which_func)
01973 {
01974 case IOFunc_input:
01975 *func = typinput;
01976 break;
01977 case IOFunc_output:
01978 *func = typoutput;
01979 break;
01980 default:
01981 elog(ERROR, "binary I/O not supported during bootstrap");
01982 break;
01983 }
01984 return;
01985 }
01986
01987 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
01988 if (!HeapTupleIsValid(typeTuple))
01989 elog(ERROR, "cache lookup failed for type %u", typid);
01990 typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
01991
01992 *typlen = typeStruct->typlen;
01993 *typbyval = typeStruct->typbyval;
01994 *typalign = typeStruct->typalign;
01995 *typdelim = typeStruct->typdelim;
01996 *typioparam = getTypeIOParam(typeTuple);
01997 switch (which_func)
01998 {
01999 case IOFunc_input:
02000 *func = typeStruct->typinput;
02001 break;
02002 case IOFunc_output:
02003 *func = typeStruct->typoutput;
02004 break;
02005 case IOFunc_receive:
02006 *func = typeStruct->typreceive;
02007 break;
02008 case IOFunc_send:
02009 *func = typeStruct->typsend;
02010 break;
02011 }
02012 ReleaseSysCache(typeTuple);
02013 }
02014
02015 #ifdef NOT_USED
02016 char
02017 get_typalign(Oid typid)
02018 {
02019 HeapTuple tp;
02020
02021 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
02022 if (HeapTupleIsValid(tp))
02023 {
02024 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
02025 char result;
02026
02027 result = typtup->typalign;
02028 ReleaseSysCache(tp);
02029 return result;
02030 }
02031 else
02032 return 'i';
02033 }
02034 #endif
02035
02036 char
02037 get_typstorage(Oid typid)
02038 {
02039 HeapTuple tp;
02040
02041 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
02042 if (HeapTupleIsValid(tp))
02043 {
02044 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
02045 char result;
02046
02047 result = typtup->typstorage;
02048 ReleaseSysCache(tp);
02049 return result;
02050 }
02051 else
02052 return 'p';
02053 }
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065 Node *
02066 get_typdefault(Oid typid)
02067 {
02068 HeapTuple typeTuple;
02069 Form_pg_type type;
02070 Datum datum;
02071 bool isNull;
02072 Node *expr;
02073
02074 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
02075 if (!HeapTupleIsValid(typeTuple))
02076 elog(ERROR, "cache lookup failed for type %u", typid);
02077 type = (Form_pg_type) GETSTRUCT(typeTuple);
02078
02079
02080
02081
02082
02083
02084 datum = SysCacheGetAttr(TYPEOID,
02085 typeTuple,
02086 Anum_pg_type_typdefaultbin,
02087 &isNull);
02088
02089 if (!isNull)
02090 {
02091
02092 expr = stringToNode(TextDatumGetCString(datum));
02093 }
02094 else
02095 {
02096
02097 datum = SysCacheGetAttr(TYPEOID,
02098 typeTuple,
02099 Anum_pg_type_typdefault,
02100 &isNull);
02101
02102 if (!isNull)
02103 {
02104 char *strDefaultVal;
02105
02106
02107 strDefaultVal = TextDatumGetCString(datum);
02108
02109 datum = OidInputFunctionCall(type->typinput, strDefaultVal,
02110 getTypeIOParam(typeTuple), -1);
02111
02112 expr = (Node *) makeConst(typid,
02113 -1,
02114 type->typcollation,
02115 type->typlen,
02116 datum,
02117 false,
02118 type->typbyval);
02119 pfree(strDefaultVal);
02120 }
02121 else
02122 {
02123
02124 expr = NULL;
02125 }
02126 }
02127
02128 ReleaseSysCache(typeTuple);
02129
02130 return expr;
02131 }
02132
02133
02134
02135
02136
02137
02138 Oid
02139 getBaseType(Oid typid)
02140 {
02141 int32 typmod = -1;
02142
02143 return getBaseTypeAndTypmod(typid, &typmod);
02144 }
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155 Oid
02156 getBaseTypeAndTypmod(Oid typid, int32 *typmod)
02157 {
02158
02159
02160
02161 for (;;)
02162 {
02163 HeapTuple tup;
02164 Form_pg_type typTup;
02165
02166 tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
02167 if (!HeapTupleIsValid(tup))
02168 elog(ERROR, "cache lookup failed for type %u", typid);
02169 typTup = (Form_pg_type) GETSTRUCT(tup);
02170 if (typTup->typtype != TYPTYPE_DOMAIN)
02171 {
02172
02173 ReleaseSysCache(tup);
02174 break;
02175 }
02176
02177 Assert(*typmod == -1);
02178 typid = typTup->typbasetype;
02179 *typmod = typTup->typtypmod;
02180
02181 ReleaseSysCache(tup);
02182 }
02183
02184 return typid;
02185 }
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195 int32
02196 get_typavgwidth(Oid typid, int32 typmod)
02197 {
02198 int typlen = get_typlen(typid);
02199 int32 maxwidth;
02200
02201
02202
02203
02204 if (typlen > 0)
02205 return typlen;
02206
02207
02208
02209
02210
02211 maxwidth = type_maximum_size(typid, typmod);
02212 if (maxwidth > 0)
02213 {
02214
02215
02216
02217
02218
02219 if (typid == BPCHAROID)
02220 return maxwidth;
02221 if (maxwidth <= 32)
02222 return maxwidth;
02223 if (maxwidth < 1000)
02224 return 32 + (maxwidth - 32) / 2;
02225
02226
02227
02228
02229
02230
02231 return 32 + (1000 - 32) / 2;
02232 }
02233
02234
02235
02236
02237 return 32;
02238 }
02239
02240
02241
02242
02243
02244
02245
02246 char
02247 get_typtype(Oid typid)
02248 {
02249 HeapTuple tp;
02250
02251 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
02252 if (HeapTupleIsValid(tp))
02253 {
02254 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
02255 char result;
02256
02257 result = typtup->typtype;
02258 ReleaseSysCache(tp);
02259 return result;
02260 }
02261 else
02262 return '\0';
02263 }
02264
02265
02266
02267
02268
02269
02270
02271 bool
02272 type_is_rowtype(Oid typid)
02273 {
02274 return (typid == RECORDOID || get_typtype(typid) == TYPTYPE_COMPOSITE);
02275 }
02276
02277
02278
02279
02280
02281 bool
02282 type_is_enum(Oid typid)
02283 {
02284 return (get_typtype(typid) == TYPTYPE_ENUM);
02285 }
02286
02287
02288
02289
02290
02291 bool
02292 type_is_range(Oid typid)
02293 {
02294 return (get_typtype(typid) == TYPTYPE_RANGE);
02295 }
02296
02297
02298
02299
02300
02301
02302
02303 void
02304 get_type_category_preferred(Oid typid, char *typcategory, bool *typispreferred)
02305 {
02306 HeapTuple tp;
02307 Form_pg_type typtup;
02308
02309 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
02310 if (!HeapTupleIsValid(tp))
02311 elog(ERROR, "cache lookup failed for type %u", typid);
02312 typtup = (Form_pg_type) GETSTRUCT(tp);
02313 *typcategory = typtup->typcategory;
02314 *typispreferred = typtup->typispreferred;
02315 ReleaseSysCache(tp);
02316 }
02317
02318
02319
02320
02321
02322
02323
02324 Oid
02325 get_typ_typrelid(Oid typid)
02326 {
02327 HeapTuple tp;
02328
02329 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
02330 if (HeapTupleIsValid(tp))
02331 {
02332 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
02333 Oid result;
02334
02335 result = typtup->typrelid;
02336 ReleaseSysCache(tp);
02337 return result;
02338 }
02339 else
02340 return InvalidOid;
02341 }
02342
02343
02344
02345
02346
02347
02348
02349
02350
02351 Oid
02352 get_element_type(Oid typid)
02353 {
02354 HeapTuple tp;
02355
02356 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
02357 if (HeapTupleIsValid(tp))
02358 {
02359 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
02360 Oid result;
02361
02362 if (typtup->typlen == -1)
02363 result = typtup->typelem;
02364 else
02365 result = InvalidOid;
02366 ReleaseSysCache(tp);
02367 return result;
02368 }
02369 else
02370 return InvalidOid;
02371 }
02372
02373
02374
02375
02376
02377
02378
02379 Oid
02380 get_array_type(Oid typid)
02381 {
02382 HeapTuple tp;
02383 Oid result = InvalidOid;
02384
02385 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
02386 if (HeapTupleIsValid(tp))
02387 {
02388 result = ((Form_pg_type) GETSTRUCT(tp))->typarray;
02389 ReleaseSysCache(tp);
02390 }
02391 return result;
02392 }
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403 Oid
02404 get_base_element_type(Oid typid)
02405 {
02406
02407
02408
02409 for (;;)
02410 {
02411 HeapTuple tup;
02412 Form_pg_type typTup;
02413
02414 tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
02415 if (!HeapTupleIsValid(tup))
02416 break;
02417 typTup = (Form_pg_type) GETSTRUCT(tup);
02418 if (typTup->typtype != TYPTYPE_DOMAIN)
02419 {
02420
02421 Oid result;
02422
02423
02424 if (typTup->typlen == -1)
02425 result = typTup->typelem;
02426 else
02427 result = InvalidOid;
02428 ReleaseSysCache(tup);
02429 return result;
02430 }
02431
02432 typid = typTup->typbasetype;
02433 ReleaseSysCache(tup);
02434 }
02435
02436
02437 return InvalidOid;
02438 }
02439
02440
02441
02442
02443
02444
02445 void
02446 getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
02447 {
02448 HeapTuple typeTuple;
02449 Form_pg_type pt;
02450
02451 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
02452 if (!HeapTupleIsValid(typeTuple))
02453 elog(ERROR, "cache lookup failed for type %u", type);
02454 pt = (Form_pg_type) GETSTRUCT(typeTuple);
02455
02456 if (!pt->typisdefined)
02457 ereport(ERROR,
02458 (errcode(ERRCODE_UNDEFINED_OBJECT),
02459 errmsg("type %s is only a shell",
02460 format_type_be(type))));
02461 if (!OidIsValid(pt->typinput))
02462 ereport(ERROR,
02463 (errcode(ERRCODE_UNDEFINED_FUNCTION),
02464 errmsg("no input function available for type %s",
02465 format_type_be(type))));
02466
02467 *typInput = pt->typinput;
02468 *typIOParam = getTypeIOParam(typeTuple);
02469
02470 ReleaseSysCache(typeTuple);
02471 }
02472
02473
02474
02475
02476
02477
02478 void
02479 getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
02480 {
02481 HeapTuple typeTuple;
02482 Form_pg_type pt;
02483
02484 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
02485 if (!HeapTupleIsValid(typeTuple))
02486 elog(ERROR, "cache lookup failed for type %u", type);
02487 pt = (Form_pg_type) GETSTRUCT(typeTuple);
02488
02489 if (!pt->typisdefined)
02490 ereport(ERROR,
02491 (errcode(ERRCODE_UNDEFINED_OBJECT),
02492 errmsg("type %s is only a shell",
02493 format_type_be(type))));
02494 if (!OidIsValid(pt->typoutput))
02495 ereport(ERROR,
02496 (errcode(ERRCODE_UNDEFINED_FUNCTION),
02497 errmsg("no output function available for type %s",
02498 format_type_be(type))));
02499
02500 *typOutput = pt->typoutput;
02501 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
02502
02503 ReleaseSysCache(typeTuple);
02504 }
02505
02506
02507
02508
02509
02510
02511 void
02512 getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
02513 {
02514 HeapTuple typeTuple;
02515 Form_pg_type pt;
02516
02517 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
02518 if (!HeapTupleIsValid(typeTuple))
02519 elog(ERROR, "cache lookup failed for type %u", type);
02520 pt = (Form_pg_type) GETSTRUCT(typeTuple);
02521
02522 if (!pt->typisdefined)
02523 ereport(ERROR,
02524 (errcode(ERRCODE_UNDEFINED_OBJECT),
02525 errmsg("type %s is only a shell",
02526 format_type_be(type))));
02527 if (!OidIsValid(pt->typreceive))
02528 ereport(ERROR,
02529 (errcode(ERRCODE_UNDEFINED_FUNCTION),
02530 errmsg("no binary input function available for type %s",
02531 format_type_be(type))));
02532
02533 *typReceive = pt->typreceive;
02534 *typIOParam = getTypeIOParam(typeTuple);
02535
02536 ReleaseSysCache(typeTuple);
02537 }
02538
02539
02540
02541
02542
02543
02544 void
02545 getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
02546 {
02547 HeapTuple typeTuple;
02548 Form_pg_type pt;
02549
02550 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
02551 if (!HeapTupleIsValid(typeTuple))
02552 elog(ERROR, "cache lookup failed for type %u", type);
02553 pt = (Form_pg_type) GETSTRUCT(typeTuple);
02554
02555 if (!pt->typisdefined)
02556 ereport(ERROR,
02557 (errcode(ERRCODE_UNDEFINED_OBJECT),
02558 errmsg("type %s is only a shell",
02559 format_type_be(type))));
02560 if (!OidIsValid(pt->typsend))
02561 ereport(ERROR,
02562 (errcode(ERRCODE_UNDEFINED_FUNCTION),
02563 errmsg("no binary output function available for type %s",
02564 format_type_be(type))));
02565
02566 *typSend = pt->typsend;
02567 *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
02568
02569 ReleaseSysCache(typeTuple);
02570 }
02571
02572
02573
02574
02575
02576
02577 Oid
02578 get_typmodin(Oid typid)
02579 {
02580 HeapTuple tp;
02581
02582 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
02583 if (HeapTupleIsValid(tp))
02584 {
02585 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
02586 Oid result;
02587
02588 result = typtup->typmodin;
02589 ReleaseSysCache(tp);
02590 return result;
02591 }
02592 else
02593 return InvalidOid;
02594 }
02595
02596 #ifdef NOT_USED
02597
02598
02599
02600
02601
02602 Oid
02603 get_typmodout(Oid typid)
02604 {
02605 HeapTuple tp;
02606
02607 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
02608 if (HeapTupleIsValid(tp))
02609 {
02610 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
02611 Oid result;
02612
02613 result = typtup->typmodout;
02614 ReleaseSysCache(tp);
02615 return result;
02616 }
02617 else
02618 return InvalidOid;
02619 }
02620 #endif
02621
02622
02623
02624
02625
02626
02627 Oid
02628 get_typcollation(Oid typid)
02629 {
02630 HeapTuple tp;
02631
02632 tp = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
02633 if (HeapTupleIsValid(tp))
02634 {
02635 Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
02636 Oid result;
02637
02638 result = typtup->typcollation;
02639 ReleaseSysCache(tp);
02640 return result;
02641 }
02642 else
02643 return InvalidOid;
02644 }
02645
02646
02647
02648
02649
02650
02651
02652 bool
02653 type_is_collatable(Oid typid)
02654 {
02655 return OidIsValid(get_typcollation(typid));
02656 }
02657
02658
02659
02660
02661
02662
02663
02664
02665
02666
02667
02668
02669
02670
02671
02672
02673
02674 int32
02675 get_attavgwidth(Oid relid, AttrNumber attnum)
02676 {
02677 HeapTuple tp;
02678 int32 stawidth;
02679
02680 if (get_attavgwidth_hook)
02681 {
02682 stawidth = (*get_attavgwidth_hook) (relid, attnum);
02683 if (stawidth > 0)
02684 return stawidth;
02685 }
02686 tp = SearchSysCache3(STATRELATTINH,
02687 ObjectIdGetDatum(relid),
02688 Int16GetDatum(attnum),
02689 BoolGetDatum(false));
02690 if (HeapTupleIsValid(tp))
02691 {
02692 stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
02693 ReleaseSysCache(tp);
02694 if (stawidth > 0)
02695 return stawidth;
02696 }
02697 return 0;
02698 }
02699
02700
02701
02702
02703
02704
02705
02706
02707
02708
02709
02710
02711
02712
02713
02714
02715
02716
02717
02718
02719
02720
02721
02722
02723
02724
02725
02726
02727
02728
02729
02730
02731
02732 bool
02733 get_attstatsslot(HeapTuple statstuple,
02734 Oid atttype, int32 atttypmod,
02735 int reqkind, Oid reqop,
02736 Oid *actualop,
02737 Datum **values, int *nvalues,
02738 float4 **numbers, int *nnumbers)
02739 {
02740 Form_pg_statistic stats = (Form_pg_statistic) GETSTRUCT(statstuple);
02741 int i,
02742 j;
02743 Datum val;
02744 bool isnull;
02745 ArrayType *statarray;
02746 Oid arrayelemtype;
02747 int narrayelem;
02748 HeapTuple typeTuple;
02749 Form_pg_type typeForm;
02750
02751 for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
02752 {
02753 if ((&stats->stakind1)[i] == reqkind &&
02754 (reqop == InvalidOid || (&stats->staop1)[i] == reqop))
02755 break;
02756 }
02757 if (i >= STATISTIC_NUM_SLOTS)
02758 return false;
02759
02760 if (actualop)
02761 *actualop = (&stats->staop1)[i];
02762
02763 if (values)
02764 {
02765 val = SysCacheGetAttr(STATRELATTINH, statstuple,
02766 Anum_pg_statistic_stavalues1 + i,
02767 &isnull);
02768 if (isnull)
02769 elog(ERROR, "stavalues is null");
02770 statarray = DatumGetArrayTypeP(val);
02771
02772
02773
02774
02775
02776
02777
02778
02779 arrayelemtype = ARR_ELEMTYPE(statarray);
02780 typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(arrayelemtype));
02781 if (!HeapTupleIsValid(typeTuple))
02782 elog(ERROR, "cache lookup failed for type %u", arrayelemtype);
02783 typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
02784
02785
02786 deconstruct_array(statarray,
02787 arrayelemtype,
02788 typeForm->typlen,
02789 typeForm->typbyval,
02790 typeForm->typalign,
02791 values, NULL, nvalues);
02792
02793
02794
02795
02796
02797
02798 if (!typeForm->typbyval)
02799 {
02800 for (j = 0; j < *nvalues; j++)
02801 {
02802 (*values)[j] = datumCopy((*values)[j],
02803 typeForm->typbyval,
02804 typeForm->typlen);
02805 }
02806 }
02807
02808 ReleaseSysCache(typeTuple);
02809
02810
02811
02812
02813 if ((Pointer) statarray != DatumGetPointer(val))
02814 pfree(statarray);
02815 }
02816
02817 if (numbers)
02818 {
02819 val = SysCacheGetAttr(STATRELATTINH, statstuple,
02820 Anum_pg_statistic_stanumbers1 + i,
02821 &isnull);
02822 if (isnull)
02823 elog(ERROR, "stanumbers is null");
02824 statarray = DatumGetArrayTypeP(val);
02825
02826
02827
02828
02829
02830
02831 narrayelem = ARR_DIMS(statarray)[0];
02832 if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
02833 ARR_HASNULL(statarray) ||
02834 ARR_ELEMTYPE(statarray) != FLOAT4OID)
02835 elog(ERROR, "stanumbers is not a 1-D float4 array");
02836 *numbers = (float4 *) palloc(narrayelem * sizeof(float4));
02837 memcpy(*numbers, ARR_DATA_PTR(statarray), narrayelem * sizeof(float4));
02838 *nnumbers = narrayelem;
02839
02840
02841
02842
02843 if ((Pointer) statarray != DatumGetPointer(val))
02844 pfree(statarray);
02845 }
02846
02847 return true;
02848 }
02849
02850
02851
02852
02853
02854
02855
02856 void
02857 free_attstatsslot(Oid atttype,
02858 Datum *values, int nvalues,
02859 float4 *numbers, int nnumbers)
02860 {
02861 if (values)
02862 {
02863 if (!get_typbyval(atttype))
02864 {
02865 int i;
02866
02867 for (i = 0; i < nvalues; i++)
02868 pfree(DatumGetPointer(values[i]));
02869 }
02870 pfree(values);
02871 }
02872 if (numbers)
02873 pfree(numbers);
02874 }
02875
02876
02877
02878
02879
02880
02881
02882
02883
02884 char *
02885 get_namespace_name(Oid nspid)
02886 {
02887 HeapTuple tp;
02888
02889 tp = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(nspid));
02890 if (HeapTupleIsValid(tp))
02891 {
02892 Form_pg_namespace nsptup = (Form_pg_namespace) GETSTRUCT(tp);
02893 char *result;
02894
02895 result = pstrdup(NameStr(nsptup->nspname));
02896 ReleaseSysCache(tp);
02897 return result;
02898 }
02899 else
02900 return NULL;
02901 }
02902
02903
02904
02905
02906
02907
02908
02909
02910
02911 Oid
02912 get_range_subtype(Oid rangeOid)
02913 {
02914 HeapTuple tp;
02915
02916 tp = SearchSysCache1(RANGETYPE, ObjectIdGetDatum(rangeOid));
02917 if (HeapTupleIsValid(tp))
02918 {
02919 Form_pg_range rngtup = (Form_pg_range) GETSTRUCT(tp);
02920 Oid result;
02921
02922 result = rngtup->rngsubtype;
02923 ReleaseSysCache(tp);
02924 return result;
02925 }
02926 else
02927 return InvalidOid;
02928 }