00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "postgres.h"
00021
00022 #include "access/htup_details.h"
00023 #include "access/xact.h"
00024 #include "catalog/dependency.h"
00025 #include "catalog/objectaccess.h"
00026 #include "catalog/pg_authid.h"
00027 #include "catalog/pg_collation.h"
00028 #include "catalog/pg_conversion.h"
00029 #include "catalog/pg_conversion_fn.h"
00030 #include "catalog/pg_namespace.h"
00031 #include "catalog/pg_opclass.h"
00032 #include "catalog/pg_operator.h"
00033 #include "catalog/pg_opfamily.h"
00034 #include "catalog/pg_proc.h"
00035 #include "catalog/pg_ts_config.h"
00036 #include "catalog/pg_ts_dict.h"
00037 #include "catalog/pg_ts_parser.h"
00038 #include "catalog/pg_ts_template.h"
00039 #include "catalog/pg_type.h"
00040 #include "commands/dbcommands.h"
00041 #include "funcapi.h"
00042 #include "mb/pg_wchar.h"
00043 #include "miscadmin.h"
00044 #include "nodes/makefuncs.h"
00045 #include "parser/parse_func.h"
00046 #include "storage/ipc.h"
00047 #include "storage/lmgr.h"
00048 #include "storage/sinval.h"
00049 #include "utils/acl.h"
00050 #include "utils/builtins.h"
00051 #include "utils/catcache.h"
00052 #include "utils/guc.h"
00053 #include "utils/inval.h"
00054 #include "utils/lsyscache.h"
00055 #include "utils/memutils.h"
00056 #include "utils/syscache.h"
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130 static List *activeSearchPath = NIL;
00131
00132
00133 static Oid activeCreationNamespace = InvalidOid;
00134
00135
00136 static bool activeTempCreationPending = false;
00137
00138
00139
00140 static List *baseSearchPath = NIL;
00141
00142 static Oid baseCreationNamespace = InvalidOid;
00143
00144 static bool baseTempCreationPending = false;
00145
00146 static Oid namespaceUser = InvalidOid;
00147
00148
00149 static bool baseSearchPathValid = true;
00150
00151
00152
00153 typedef struct
00154 {
00155 List *searchPath;
00156 Oid creationNamespace;
00157 int nestLevel;
00158 } OverrideStackEntry;
00159
00160 static List *overrideStack = NIL;
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 static Oid myTempNamespace = InvalidOid;
00178
00179 static Oid myTempToastNamespace = InvalidOid;
00180
00181 static SubTransactionId myTempNamespaceSubID = InvalidSubTransactionId;
00182
00183
00184
00185
00186
00187 char *namespace_search_path = NULL;
00188
00189
00190
00191 static void recomputeNamespacePath(void);
00192 static void InitTempTableNamespace(void);
00193 static void RemoveTempRelations(Oid tempNamespaceId);
00194 static void RemoveTempRelationsCallback(int code, Datum arg);
00195 static void NamespaceCallback(Datum arg, int cacheid, uint32 hashvalue);
00196 static bool MatchNamedCall(HeapTuple proctup, int nargs, List *argnames,
00197 int **argnumbers);
00198
00199
00200 Datum pg_table_is_visible(PG_FUNCTION_ARGS);
00201 Datum pg_type_is_visible(PG_FUNCTION_ARGS);
00202 Datum pg_function_is_visible(PG_FUNCTION_ARGS);
00203 Datum pg_operator_is_visible(PG_FUNCTION_ARGS);
00204 Datum pg_opclass_is_visible(PG_FUNCTION_ARGS);
00205 Datum pg_opfamily_is_visible(PG_FUNCTION_ARGS);
00206 Datum pg_collation_is_visible(PG_FUNCTION_ARGS);
00207 Datum pg_conversion_is_visible(PG_FUNCTION_ARGS);
00208 Datum pg_ts_parser_is_visible(PG_FUNCTION_ARGS);
00209 Datum pg_ts_dict_is_visible(PG_FUNCTION_ARGS);
00210 Datum pg_ts_template_is_visible(PG_FUNCTION_ARGS);
00211 Datum pg_ts_config_is_visible(PG_FUNCTION_ARGS);
00212 Datum pg_my_temp_schema(PG_FUNCTION_ARGS);
00213 Datum pg_is_other_temp_schema(PG_FUNCTION_ARGS);
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229 Oid
00230 RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode,
00231 bool missing_ok, bool nowait,
00232 RangeVarGetRelidCallback callback, void *callback_arg)
00233 {
00234 uint64 inval_count;
00235 Oid relId;
00236 Oid oldRelId = InvalidOid;
00237 bool retry = false;
00238
00239
00240
00241
00242 if (relation->catalogname)
00243 {
00244 if (strcmp(relation->catalogname, get_database_name(MyDatabaseId)) != 0)
00245 ereport(ERROR,
00246 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00247 errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
00248 relation->catalogname, relation->schemaname,
00249 relation->relname)));
00250 }
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268 for (;;)
00269 {
00270
00271
00272
00273
00274
00275 inval_count = SharedInvalidMessageCounter;
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285 if (relation->relpersistence == RELPERSISTENCE_TEMP)
00286 {
00287 if (!OidIsValid(myTempNamespace))
00288 relId = InvalidOid;
00289 else
00290 {
00291 if (relation->schemaname)
00292 {
00293 Oid namespaceId;
00294
00295 namespaceId = LookupExplicitNamespace(relation->schemaname, missing_ok);
00296
00297
00298
00299
00300 if (namespaceId != myTempNamespace)
00301 ereport(ERROR,
00302 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
00303 errmsg("temporary tables cannot specify a schema name")));
00304 }
00305
00306 relId = get_relname_relid(relation->relname, myTempNamespace);
00307 }
00308 }
00309 else if (relation->schemaname)
00310 {
00311 Oid namespaceId;
00312
00313
00314 namespaceId = LookupExplicitNamespace(relation->schemaname, missing_ok);
00315 if (missing_ok && !OidIsValid(namespaceId))
00316 relId = InvalidOid;
00317 else
00318 relId = get_relname_relid(relation->relname, namespaceId);
00319 }
00320 else
00321 {
00322
00323 relId = RelnameGetRelid(relation->relname);
00324 }
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336 if (callback)
00337 callback(relation, relId, oldRelId, callback_arg);
00338
00339
00340
00341
00342
00343
00344
00345
00346 if (lockmode == NoLock)
00347 break;
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358 if (retry)
00359 {
00360 if (relId == oldRelId)
00361 break;
00362 if (OidIsValid(oldRelId))
00363 UnlockRelationOid(oldRelId, lockmode);
00364 }
00365
00366
00367
00368
00369
00370
00371
00372
00373 if (!OidIsValid(relId))
00374 AcceptInvalidationMessages();
00375 else if (!nowait)
00376 LockRelationOid(relId, lockmode);
00377 else if (!ConditionalLockRelationOid(relId, lockmode))
00378 {
00379 if (relation->schemaname)
00380 ereport(ERROR,
00381 (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
00382 errmsg("could not obtain lock on relation \"%s.%s\"",
00383 relation->schemaname, relation->relname)));
00384 else
00385 ereport(ERROR,
00386 (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
00387 errmsg("could not obtain lock on relation \"%s\"",
00388 relation->relname)));
00389 }
00390
00391
00392
00393
00394 if (inval_count == SharedInvalidMessageCounter)
00395 break;
00396
00397
00398
00399
00400
00401
00402 retry = true;
00403 oldRelId = relId;
00404 }
00405
00406 if (!OidIsValid(relId) && !missing_ok)
00407 {
00408 if (relation->schemaname)
00409 ereport(ERROR,
00410 (errcode(ERRCODE_UNDEFINED_TABLE),
00411 errmsg("relation \"%s.%s\" does not exist",
00412 relation->schemaname, relation->relname)));
00413 else
00414 ereport(ERROR,
00415 (errcode(ERRCODE_UNDEFINED_TABLE),
00416 errmsg("relation \"%s\" does not exist",
00417 relation->relname)));
00418 }
00419 return relId;
00420 }
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431 Oid
00432 RangeVarGetCreationNamespace(const RangeVar *newRelation)
00433 {
00434 Oid namespaceId;
00435
00436
00437
00438
00439 if (newRelation->catalogname)
00440 {
00441 if (strcmp(newRelation->catalogname, get_database_name(MyDatabaseId)) != 0)
00442 ereport(ERROR,
00443 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00444 errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
00445 newRelation->catalogname, newRelation->schemaname,
00446 newRelation->relname)));
00447 }
00448
00449 if (newRelation->schemaname)
00450 {
00451
00452 if (strcmp(newRelation->schemaname, "pg_temp") == 0)
00453 {
00454
00455 if (!OidIsValid(myTempNamespace))
00456 InitTempTableNamespace();
00457 return myTempNamespace;
00458 }
00459
00460 namespaceId = get_namespace_oid(newRelation->schemaname, false);
00461
00462 }
00463 else if (newRelation->relpersistence == RELPERSISTENCE_TEMP)
00464 {
00465
00466 if (!OidIsValid(myTempNamespace))
00467 InitTempTableNamespace();
00468 return myTempNamespace;
00469 }
00470 else
00471 {
00472
00473 recomputeNamespacePath();
00474 if (activeTempCreationPending)
00475 {
00476
00477 InitTempTableNamespace();
00478 return myTempNamespace;
00479 }
00480 namespaceId = activeCreationNamespace;
00481 if (!OidIsValid(namespaceId))
00482 ereport(ERROR,
00483 (errcode(ERRCODE_UNDEFINED_SCHEMA),
00484 errmsg("no schema has been selected to create in")));
00485 }
00486
00487
00488
00489 return namespaceId;
00490 }
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518 Oid
00519 RangeVarGetAndCheckCreationNamespace(RangeVar *relation,
00520 LOCKMODE lockmode,
00521 Oid *existing_relation_id)
00522 {
00523 uint64 inval_count;
00524 Oid relid;
00525 Oid oldrelid = InvalidOid;
00526 Oid nspid;
00527 Oid oldnspid = InvalidOid;
00528 bool retry = false;
00529
00530
00531
00532
00533 if (relation->catalogname)
00534 {
00535 if (strcmp(relation->catalogname, get_database_name(MyDatabaseId)) != 0)
00536 ereport(ERROR,
00537 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00538 errmsg("cross-database references are not implemented: \"%s.%s.%s\"",
00539 relation->catalogname, relation->schemaname,
00540 relation->relname)));
00541 }
00542
00543
00544
00545
00546
00547
00548
00549 for (;;)
00550 {
00551 AclResult aclresult;
00552
00553 inval_count = SharedInvalidMessageCounter;
00554
00555
00556 nspid = RangeVarGetCreationNamespace(relation);
00557 Assert(OidIsValid(nspid));
00558 if (existing_relation_id != NULL)
00559 relid = get_relname_relid(relation->relname, nspid);
00560 else
00561 relid = InvalidOid;
00562
00563
00564
00565
00566
00567
00568 if (IsBootstrapProcessingMode())
00569 break;
00570
00571
00572 aclresult = pg_namespace_aclcheck(nspid, GetUserId(), ACL_CREATE);
00573 if (aclresult != ACLCHECK_OK)
00574 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
00575 get_namespace_name(nspid));
00576
00577 if (retry)
00578 {
00579
00580 if (relid == oldrelid && nspid == oldnspid)
00581 break;
00582
00583 if (nspid != oldnspid)
00584 UnlockDatabaseObject(NamespaceRelationId, oldnspid, 0,
00585 AccessShareLock);
00586
00587 if (relid != oldrelid && OidIsValid(oldrelid) && lockmode != NoLock)
00588 UnlockRelationOid(oldrelid, lockmode);
00589 }
00590
00591
00592 if (nspid != oldnspid)
00593 LockDatabaseObject(NamespaceRelationId, nspid, 0, AccessShareLock);
00594
00595
00596 if (lockmode != NoLock && OidIsValid(relid))
00597 {
00598 if (!pg_class_ownercheck(relid, GetUserId()))
00599 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
00600 relation->relname);
00601 if (relid != oldrelid)
00602 LockRelationOid(relid, lockmode);
00603 }
00604
00605
00606 if (inval_count == SharedInvalidMessageCounter)
00607 break;
00608
00609
00610 retry = true;
00611 oldrelid = relid;
00612 oldnspid = nspid;
00613 }
00614
00615 RangeVarAdjustRelationPersistence(relation, nspid);
00616 if (existing_relation_id != NULL)
00617 *existing_relation_id = relid;
00618 return nspid;
00619 }
00620
00621
00622
00623
00624
00625 void
00626 RangeVarAdjustRelationPersistence(RangeVar *newRelation, Oid nspid)
00627 {
00628 switch (newRelation->relpersistence)
00629 {
00630 case RELPERSISTENCE_TEMP:
00631 if (!isTempOrToastNamespace(nspid))
00632 {
00633 if (isAnyTempNamespace(nspid))
00634 ereport(ERROR,
00635 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
00636 errmsg("cannot create relations in temporary schemas of other sessions")));
00637 else
00638 ereport(ERROR,
00639 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
00640 errmsg("cannot create temporary relation in non-temporary schema")));
00641 }
00642 break;
00643 case RELPERSISTENCE_PERMANENT:
00644 if (isTempOrToastNamespace(nspid))
00645 newRelation->relpersistence = RELPERSISTENCE_TEMP;
00646 else if (isAnyTempNamespace(nspid))
00647 ereport(ERROR,
00648 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
00649 errmsg("cannot create relations in temporary schemas of other sessions")));
00650 break;
00651 default:
00652 if (isAnyTempNamespace(nspid))
00653 ereport(ERROR,
00654 (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
00655 errmsg("only temporary relations may be created in temporary schemas")));
00656 }
00657 }
00658
00659
00660
00661
00662
00663
00664 Oid
00665 RelnameGetRelid(const char *relname)
00666 {
00667 Oid relid;
00668 ListCell *l;
00669
00670 recomputeNamespacePath();
00671
00672 foreach(l, activeSearchPath)
00673 {
00674 Oid namespaceId = lfirst_oid(l);
00675
00676 relid = get_relname_relid(relname, namespaceId);
00677 if (OidIsValid(relid))
00678 return relid;
00679 }
00680
00681
00682 return InvalidOid;
00683 }
00684
00685
00686
00687
00688
00689
00690
00691
00692 bool
00693 RelationIsVisible(Oid relid)
00694 {
00695 HeapTuple reltup;
00696 Form_pg_class relform;
00697 Oid relnamespace;
00698 bool visible;
00699
00700 reltup = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
00701 if (!HeapTupleIsValid(reltup))
00702 elog(ERROR, "cache lookup failed for relation %u", relid);
00703 relform = (Form_pg_class) GETSTRUCT(reltup);
00704
00705 recomputeNamespacePath();
00706
00707
00708
00709
00710
00711
00712 relnamespace = relform->relnamespace;
00713 if (relnamespace != PG_CATALOG_NAMESPACE &&
00714 !list_member_oid(activeSearchPath, relnamespace))
00715 visible = false;
00716 else
00717 {
00718
00719
00720
00721
00722
00723 char *relname = NameStr(relform->relname);
00724 ListCell *l;
00725
00726 visible = false;
00727 foreach(l, activeSearchPath)
00728 {
00729 Oid namespaceId = lfirst_oid(l);
00730
00731 if (namespaceId == relnamespace)
00732 {
00733
00734 visible = true;
00735 break;
00736 }
00737 if (OidIsValid(get_relname_relid(relname, namespaceId)))
00738 {
00739
00740 break;
00741 }
00742 }
00743 }
00744
00745 ReleaseSysCache(reltup);
00746
00747 return visible;
00748 }
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758 Oid
00759 TypenameGetTypid(const char *typname)
00760 {
00761 Oid typid;
00762 ListCell *l;
00763
00764 recomputeNamespacePath();
00765
00766 foreach(l, activeSearchPath)
00767 {
00768 Oid namespaceId = lfirst_oid(l);
00769
00770 typid = GetSysCacheOid2(TYPENAMENSP,
00771 PointerGetDatum(typname),
00772 ObjectIdGetDatum(namespaceId));
00773 if (OidIsValid(typid))
00774 return typid;
00775 }
00776
00777
00778 return InvalidOid;
00779 }
00780
00781
00782
00783
00784
00785
00786
00787 bool
00788 TypeIsVisible(Oid typid)
00789 {
00790 HeapTuple typtup;
00791 Form_pg_type typform;
00792 Oid typnamespace;
00793 bool visible;
00794
00795 typtup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typid));
00796 if (!HeapTupleIsValid(typtup))
00797 elog(ERROR, "cache lookup failed for type %u", typid);
00798 typform = (Form_pg_type) GETSTRUCT(typtup);
00799
00800 recomputeNamespacePath();
00801
00802
00803
00804
00805
00806
00807 typnamespace = typform->typnamespace;
00808 if (typnamespace != PG_CATALOG_NAMESPACE &&
00809 !list_member_oid(activeSearchPath, typnamespace))
00810 visible = false;
00811 else
00812 {
00813
00814
00815
00816
00817
00818 char *typname = NameStr(typform->typname);
00819 ListCell *l;
00820
00821 visible = false;
00822 foreach(l, activeSearchPath)
00823 {
00824 Oid namespaceId = lfirst_oid(l);
00825
00826 if (namespaceId == typnamespace)
00827 {
00828
00829 visible = true;
00830 break;
00831 }
00832 if (SearchSysCacheExists2(TYPENAMENSP,
00833 PointerGetDatum(typname),
00834 ObjectIdGetDatum(namespaceId)))
00835 {
00836
00837 break;
00838 }
00839 }
00840 }
00841
00842 ReleaseSysCache(typtup);
00843
00844 return visible;
00845 }
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909 FuncCandidateList
00910 FuncnameGetCandidates(List *names, int nargs, List *argnames,
00911 bool expand_variadic, bool expand_defaults)
00912 {
00913 FuncCandidateList resultList = NULL;
00914 bool any_special = false;
00915 char *schemaname;
00916 char *funcname;
00917 Oid namespaceId;
00918 CatCList *catlist;
00919 int i;
00920
00921
00922 Assert(nargs >= 0 || !(expand_variadic | expand_defaults));
00923
00924
00925 DeconstructQualifiedName(names, &schemaname, &funcname);
00926
00927 if (schemaname)
00928 {
00929
00930 namespaceId = LookupExplicitNamespace(schemaname, false);
00931 }
00932 else
00933 {
00934
00935 namespaceId = InvalidOid;
00936 recomputeNamespacePath();
00937 }
00938
00939
00940 catlist = SearchSysCacheList1(PROCNAMEARGSNSP, CStringGetDatum(funcname));
00941
00942 for (i = 0; i < catlist->n_members; i++)
00943 {
00944 HeapTuple proctup = &catlist->members[i]->tuple;
00945 Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
00946 int pronargs = procform->pronargs;
00947 int effective_nargs;
00948 int pathpos = 0;
00949 bool variadic;
00950 bool use_defaults;
00951 Oid va_elem_type;
00952 int *argnumbers = NULL;
00953 FuncCandidateList newResult;
00954
00955 if (OidIsValid(namespaceId))
00956 {
00957
00958 if (procform->pronamespace != namespaceId)
00959 continue;
00960 }
00961 else
00962 {
00963
00964
00965
00966
00967 ListCell *nsp;
00968
00969 foreach(nsp, activeSearchPath)
00970 {
00971 if (procform->pronamespace == lfirst_oid(nsp) &&
00972 procform->pronamespace != myTempNamespace)
00973 break;
00974 pathpos++;
00975 }
00976 if (nsp == NULL)
00977 continue;
00978 }
00979
00980 if (argnames != NIL)
00981 {
00982
00983
00984
00985
00986
00987
00988
00989 if (OidIsValid(procform->provariadic) && expand_variadic)
00990 continue;
00991 va_elem_type = InvalidOid;
00992 variadic = false;
00993
00994
00995
00996
00997 Assert(nargs >= 0);
00998
00999 if (pronargs > nargs && expand_defaults)
01000 {
01001
01002 if (nargs + procform->pronargdefaults < pronargs)
01003 continue;
01004 use_defaults = true;
01005 }
01006 else
01007 use_defaults = false;
01008
01009
01010 if (pronargs != nargs && !use_defaults)
01011 continue;
01012
01013
01014 if (!MatchNamedCall(proctup, nargs, argnames,
01015 &argnumbers))
01016 continue;
01017
01018
01019 any_special = true;
01020 }
01021 else
01022 {
01023
01024
01025
01026
01027
01028
01029
01030 if (pronargs <= nargs && expand_variadic)
01031 {
01032 va_elem_type = procform->provariadic;
01033 variadic = OidIsValid(va_elem_type);
01034 any_special |= variadic;
01035 }
01036 else
01037 {
01038 va_elem_type = InvalidOid;
01039 variadic = false;
01040 }
01041
01042
01043
01044
01045 if (pronargs > nargs && expand_defaults)
01046 {
01047
01048 if (nargs + procform->pronargdefaults < pronargs)
01049 continue;
01050 use_defaults = true;
01051 any_special = true;
01052 }
01053 else
01054 use_defaults = false;
01055
01056
01057 if (nargs >= 0 && pronargs != nargs && !variadic && !use_defaults)
01058 continue;
01059 }
01060
01061
01062
01063
01064
01065
01066
01067 effective_nargs = Max(pronargs, nargs);
01068 newResult = (FuncCandidateList)
01069 palloc(sizeof(struct _FuncCandidateList) - sizeof(Oid)
01070 + effective_nargs * sizeof(Oid));
01071 newResult->pathpos = pathpos;
01072 newResult->oid = HeapTupleGetOid(proctup);
01073 newResult->nargs = effective_nargs;
01074 newResult->argnumbers = argnumbers;
01075 if (argnumbers)
01076 {
01077
01078 Oid *proargtypes = procform->proargtypes.values;
01079 int i;
01080
01081 for (i = 0; i < pronargs; i++)
01082 newResult->args[i] = proargtypes[argnumbers[i]];
01083 }
01084 else
01085 {
01086
01087 memcpy(newResult->args, procform->proargtypes.values,
01088 pronargs * sizeof(Oid));
01089 }
01090 if (variadic)
01091 {
01092 int i;
01093
01094 newResult->nvargs = effective_nargs - pronargs + 1;
01095
01096 for (i = pronargs - 1; i < effective_nargs; i++)
01097 newResult->args[i] = va_elem_type;
01098 }
01099 else
01100 newResult->nvargs = 0;
01101 newResult->ndargs = use_defaults ? pronargs - nargs : 0;
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111 if (resultList != NULL &&
01112 (any_special || !OidIsValid(namespaceId)))
01113 {
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125 FuncCandidateList prevResult;
01126
01127 if (catlist->ordered && !any_special)
01128 {
01129
01130 if (effective_nargs == resultList->nargs &&
01131 memcmp(newResult->args,
01132 resultList->args,
01133 effective_nargs * sizeof(Oid)) == 0)
01134 prevResult = resultList;
01135 else
01136 prevResult = NULL;
01137 }
01138 else
01139 {
01140 int cmp_nargs = newResult->nargs - newResult->ndargs;
01141
01142 for (prevResult = resultList;
01143 prevResult;
01144 prevResult = prevResult->next)
01145 {
01146 if (cmp_nargs == prevResult->nargs - prevResult->ndargs &&
01147 memcmp(newResult->args,
01148 prevResult->args,
01149 cmp_nargs * sizeof(Oid)) == 0)
01150 break;
01151 }
01152 }
01153
01154 if (prevResult)
01155 {
01156
01157
01158
01159
01160
01161
01162
01163 int preference;
01164
01165 if (pathpos != prevResult->pathpos)
01166 {
01167
01168
01169
01170 preference = pathpos - prevResult->pathpos;
01171 }
01172 else if (variadic && prevResult->nvargs == 0)
01173 {
01174
01175
01176
01177
01178
01179
01180 preference = 1;
01181 }
01182 else if (!variadic && prevResult->nvargs > 0)
01183 {
01184 preference = -1;
01185 }
01186 else
01187 {
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197 preference = 0;
01198 }
01199
01200 if (preference > 0)
01201 {
01202
01203 pfree(newResult);
01204 continue;
01205 }
01206 else if (preference < 0)
01207 {
01208
01209 if (prevResult == resultList)
01210 resultList = prevResult->next;
01211 else
01212 {
01213 FuncCandidateList prevPrevResult;
01214
01215 for (prevPrevResult = resultList;
01216 prevPrevResult;
01217 prevPrevResult = prevPrevResult->next)
01218 {
01219 if (prevResult == prevPrevResult->next)
01220 {
01221 prevPrevResult->next = prevResult->next;
01222 break;
01223 }
01224 }
01225 Assert(prevPrevResult);
01226 }
01227 pfree(prevResult);
01228
01229 }
01230 else
01231 {
01232
01233 prevResult->oid = InvalidOid;
01234 pfree(newResult);
01235 continue;
01236 }
01237 }
01238 }
01239
01240
01241
01242
01243 newResult->next = resultList;
01244 resultList = newResult;
01245 }
01246
01247 ReleaseSysCacheList(catlist);
01248
01249 return resultList;
01250 }
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269 static bool
01270 MatchNamedCall(HeapTuple proctup, int nargs, List *argnames,
01271 int **argnumbers)
01272 {
01273 Form_pg_proc procform = (Form_pg_proc) GETSTRUCT(proctup);
01274 int pronargs = procform->pronargs;
01275 int numposargs = nargs - list_length(argnames);
01276 int pronallargs;
01277 Oid *p_argtypes;
01278 char **p_argnames;
01279 char *p_argmodes;
01280 bool arggiven[FUNC_MAX_ARGS];
01281 bool isnull;
01282 int ap;
01283 int pp;
01284 ListCell *lc;
01285
01286 Assert(argnames != NIL);
01287 Assert(numposargs >= 0);
01288 Assert(nargs <= pronargs);
01289
01290
01291 (void) SysCacheGetAttr(PROCOID, proctup, Anum_pg_proc_proargnames,
01292 &isnull);
01293 if (isnull)
01294 return false;
01295
01296
01297 pronallargs = get_func_arg_info(proctup,
01298 &p_argtypes, &p_argnames, &p_argmodes);
01299 Assert(p_argnames != NULL);
01300
01301
01302 *argnumbers = (int *) palloc(pronargs * sizeof(int));
01303 memset(arggiven, false, pronargs * sizeof(bool));
01304
01305
01306 for (ap = 0; ap < numposargs; ap++)
01307 {
01308 (*argnumbers)[ap] = ap;
01309 arggiven[ap] = true;
01310 }
01311
01312
01313 foreach(lc, argnames)
01314 {
01315 char *argname = (char *) lfirst(lc);
01316 bool found;
01317 int i;
01318
01319 pp = 0;
01320 found = false;
01321 for (i = 0; i < pronallargs; i++)
01322 {
01323
01324 if (p_argmodes &&
01325 (p_argmodes[i] != FUNC_PARAM_IN &&
01326 p_argmodes[i] != FUNC_PARAM_INOUT &&
01327 p_argmodes[i] != FUNC_PARAM_VARIADIC))
01328 continue;
01329 if (p_argnames[i] && strcmp(p_argnames[i], argname) == 0)
01330 {
01331
01332 if (arggiven[pp])
01333 return false;
01334 arggiven[pp] = true;
01335 (*argnumbers)[ap] = pp;
01336 found = true;
01337 break;
01338 }
01339
01340 pp++;
01341 }
01342
01343 if (!found)
01344 return false;
01345 ap++;
01346 }
01347
01348 Assert(ap == nargs);
01349
01350
01351 if (nargs < pronargs)
01352 {
01353 int first_arg_with_default = pronargs - procform->pronargdefaults;
01354
01355 for (pp = numposargs; pp < pronargs; pp++)
01356 {
01357 if (arggiven[pp])
01358 continue;
01359
01360 if (pp < first_arg_with_default)
01361 return false;
01362 (*argnumbers)[ap++] = pp;
01363 }
01364 }
01365
01366 Assert(ap == pronargs);
01367
01368 return true;
01369 }
01370
01371
01372
01373
01374
01375
01376
01377 bool
01378 FunctionIsVisible(Oid funcid)
01379 {
01380 HeapTuple proctup;
01381 Form_pg_proc procform;
01382 Oid pronamespace;
01383 bool visible;
01384
01385 proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
01386 if (!HeapTupleIsValid(proctup))
01387 elog(ERROR, "cache lookup failed for function %u", funcid);
01388 procform = (Form_pg_proc) GETSTRUCT(proctup);
01389
01390 recomputeNamespacePath();
01391
01392
01393
01394
01395
01396
01397 pronamespace = procform->pronamespace;
01398 if (pronamespace != PG_CATALOG_NAMESPACE &&
01399 !list_member_oid(activeSearchPath, pronamespace))
01400 visible = false;
01401 else
01402 {
01403
01404
01405
01406
01407
01408
01409 char *proname = NameStr(procform->proname);
01410 int nargs = procform->pronargs;
01411 FuncCandidateList clist;
01412
01413 visible = false;
01414
01415 clist = FuncnameGetCandidates(list_make1(makeString(proname)),
01416 nargs, NIL, false, false);
01417
01418 for (; clist; clist = clist->next)
01419 {
01420 if (memcmp(clist->args, procform->proargtypes.values,
01421 nargs * sizeof(Oid)) == 0)
01422 {
01423
01424 visible = (clist->oid == funcid);
01425 break;
01426 }
01427 }
01428 }
01429
01430 ReleaseSysCache(proctup);
01431
01432 return visible;
01433 }
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447 Oid
01448 OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
01449 {
01450 char *schemaname;
01451 char *opername;
01452 CatCList *catlist;
01453 ListCell *l;
01454
01455
01456 DeconstructQualifiedName(names, &schemaname, &opername);
01457
01458 if (schemaname)
01459 {
01460
01461 Oid namespaceId;
01462 HeapTuple opertup;
01463
01464 namespaceId = LookupExplicitNamespace(schemaname, false);
01465 opertup = SearchSysCache4(OPERNAMENSP,
01466 CStringGetDatum(opername),
01467 ObjectIdGetDatum(oprleft),
01468 ObjectIdGetDatum(oprright),
01469 ObjectIdGetDatum(namespaceId));
01470 if (HeapTupleIsValid(opertup))
01471 {
01472 Oid result = HeapTupleGetOid(opertup);
01473
01474 ReleaseSysCache(opertup);
01475 return result;
01476 }
01477 return InvalidOid;
01478 }
01479
01480
01481 catlist = SearchSysCacheList3(OPERNAMENSP,
01482 CStringGetDatum(opername),
01483 ObjectIdGetDatum(oprleft),
01484 ObjectIdGetDatum(oprright));
01485
01486 if (catlist->n_members == 0)
01487 {
01488
01489 ReleaseSysCacheList(catlist);
01490 return InvalidOid;
01491 }
01492
01493
01494
01495
01496
01497
01498 recomputeNamespacePath();
01499
01500 foreach(l, activeSearchPath)
01501 {
01502 Oid namespaceId = lfirst_oid(l);
01503 int i;
01504
01505 if (namespaceId == myTempNamespace)
01506 continue;
01507
01508 for (i = 0; i < catlist->n_members; i++)
01509 {
01510 HeapTuple opertup = &catlist->members[i]->tuple;
01511 Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
01512
01513 if (operform->oprnamespace == namespaceId)
01514 {
01515 Oid result = HeapTupleGetOid(opertup);
01516
01517 ReleaseSysCacheList(catlist);
01518 return result;
01519 }
01520 }
01521 }
01522
01523 ReleaseSysCacheList(catlist);
01524 return InvalidOid;
01525 }
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544 FuncCandidateList
01545 OpernameGetCandidates(List *names, char oprkind)
01546 {
01547 FuncCandidateList resultList = NULL;
01548 char *resultSpace = NULL;
01549 int nextResult = 0;
01550 char *schemaname;
01551 char *opername;
01552 Oid namespaceId;
01553 CatCList *catlist;
01554 int i;
01555
01556
01557 DeconstructQualifiedName(names, &schemaname, &opername);
01558
01559 if (schemaname)
01560 {
01561
01562 namespaceId = LookupExplicitNamespace(schemaname, false);
01563 }
01564 else
01565 {
01566
01567 namespaceId = InvalidOid;
01568 recomputeNamespacePath();
01569 }
01570
01571
01572 catlist = SearchSysCacheList1(OPERNAMENSP, CStringGetDatum(opername));
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583 #define SPACE_PER_OP MAXALIGN(sizeof(struct _FuncCandidateList) + sizeof(Oid))
01584
01585 if (catlist->n_members > 0)
01586 resultSpace = palloc(catlist->n_members * SPACE_PER_OP);
01587
01588 for (i = 0; i < catlist->n_members; i++)
01589 {
01590 HeapTuple opertup = &catlist->members[i]->tuple;
01591 Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
01592 int pathpos = 0;
01593 FuncCandidateList newResult;
01594
01595
01596 if (oprkind && operform->oprkind != oprkind)
01597 continue;
01598
01599 if (OidIsValid(namespaceId))
01600 {
01601
01602 if (operform->oprnamespace != namespaceId)
01603 continue;
01604
01605 }
01606 else
01607 {
01608
01609
01610
01611
01612 ListCell *nsp;
01613
01614 foreach(nsp, activeSearchPath)
01615 {
01616 if (operform->oprnamespace == lfirst_oid(nsp) &&
01617 operform->oprnamespace != myTempNamespace)
01618 break;
01619 pathpos++;
01620 }
01621 if (nsp == NULL)
01622 continue;
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635 if (resultList)
01636 {
01637 FuncCandidateList prevResult;
01638
01639 if (catlist->ordered)
01640 {
01641 if (operform->oprleft == resultList->args[0] &&
01642 operform->oprright == resultList->args[1])
01643 prevResult = resultList;
01644 else
01645 prevResult = NULL;
01646 }
01647 else
01648 {
01649 for (prevResult = resultList;
01650 prevResult;
01651 prevResult = prevResult->next)
01652 {
01653 if (operform->oprleft == prevResult->args[0] &&
01654 operform->oprright == prevResult->args[1])
01655 break;
01656 }
01657 }
01658 if (prevResult)
01659 {
01660
01661 Assert(pathpos != prevResult->pathpos);
01662 if (pathpos > prevResult->pathpos)
01663 continue;
01664
01665 prevResult->pathpos = pathpos;
01666 prevResult->oid = HeapTupleGetOid(opertup);
01667 continue;
01668 }
01669 }
01670 }
01671
01672
01673
01674
01675 newResult = (FuncCandidateList) (resultSpace + nextResult);
01676 nextResult += SPACE_PER_OP;
01677
01678 newResult->pathpos = pathpos;
01679 newResult->oid = HeapTupleGetOid(opertup);
01680 newResult->nargs = 2;
01681 newResult->nvargs = 0;
01682 newResult->ndargs = 0;
01683 newResult->argnumbers = NULL;
01684 newResult->args[0] = operform->oprleft;
01685 newResult->args[1] = operform->oprright;
01686 newResult->next = resultList;
01687 resultList = newResult;
01688 }
01689
01690 ReleaseSysCacheList(catlist);
01691
01692 return resultList;
01693 }
01694
01695
01696
01697
01698
01699
01700
01701 bool
01702 OperatorIsVisible(Oid oprid)
01703 {
01704 HeapTuple oprtup;
01705 Form_pg_operator oprform;
01706 Oid oprnamespace;
01707 bool visible;
01708
01709 oprtup = SearchSysCache1(OPEROID, ObjectIdGetDatum(oprid));
01710 if (!HeapTupleIsValid(oprtup))
01711 elog(ERROR, "cache lookup failed for operator %u", oprid);
01712 oprform = (Form_pg_operator) GETSTRUCT(oprtup);
01713
01714 recomputeNamespacePath();
01715
01716
01717
01718
01719
01720
01721 oprnamespace = oprform->oprnamespace;
01722 if (oprnamespace != PG_CATALOG_NAMESPACE &&
01723 !list_member_oid(activeSearchPath, oprnamespace))
01724 visible = false;
01725 else
01726 {
01727
01728
01729
01730
01731
01732
01733 char *oprname = NameStr(oprform->oprname);
01734
01735 visible = (OpernameGetOprid(list_make1(makeString(oprname)),
01736 oprform->oprleft, oprform->oprright)
01737 == oprid);
01738 }
01739
01740 ReleaseSysCache(oprtup);
01741
01742 return visible;
01743 }
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754 Oid
01755 OpclassnameGetOpcid(Oid amid, const char *opcname)
01756 {
01757 Oid opcid;
01758 ListCell *l;
01759
01760 recomputeNamespacePath();
01761
01762 foreach(l, activeSearchPath)
01763 {
01764 Oid namespaceId = lfirst_oid(l);
01765
01766 if (namespaceId == myTempNamespace)
01767 continue;
01768
01769 opcid = GetSysCacheOid3(CLAAMNAMENSP,
01770 ObjectIdGetDatum(amid),
01771 PointerGetDatum(opcname),
01772 ObjectIdGetDatum(namespaceId));
01773 if (OidIsValid(opcid))
01774 return opcid;
01775 }
01776
01777
01778 return InvalidOid;
01779 }
01780
01781
01782
01783
01784
01785
01786
01787 bool
01788 OpclassIsVisible(Oid opcid)
01789 {
01790 HeapTuple opctup;
01791 Form_pg_opclass opcform;
01792 Oid opcnamespace;
01793 bool visible;
01794
01795 opctup = SearchSysCache1(CLAOID, ObjectIdGetDatum(opcid));
01796 if (!HeapTupleIsValid(opctup))
01797 elog(ERROR, "cache lookup failed for opclass %u", opcid);
01798 opcform = (Form_pg_opclass) GETSTRUCT(opctup);
01799
01800 recomputeNamespacePath();
01801
01802
01803
01804
01805
01806
01807 opcnamespace = opcform->opcnamespace;
01808 if (opcnamespace != PG_CATALOG_NAMESPACE &&
01809 !list_member_oid(activeSearchPath, opcnamespace))
01810 visible = false;
01811 else
01812 {
01813
01814
01815
01816
01817
01818
01819 char *opcname = NameStr(opcform->opcname);
01820
01821 visible = (OpclassnameGetOpcid(opcform->opcmethod, opcname) == opcid);
01822 }
01823
01824 ReleaseSysCache(opctup);
01825
01826 return visible;
01827 }
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837 Oid
01838 OpfamilynameGetOpfid(Oid amid, const char *opfname)
01839 {
01840 Oid opfid;
01841 ListCell *l;
01842
01843 recomputeNamespacePath();
01844
01845 foreach(l, activeSearchPath)
01846 {
01847 Oid namespaceId = lfirst_oid(l);
01848
01849 if (namespaceId == myTempNamespace)
01850 continue;
01851
01852 opfid = GetSysCacheOid3(OPFAMILYAMNAMENSP,
01853 ObjectIdGetDatum(amid),
01854 PointerGetDatum(opfname),
01855 ObjectIdGetDatum(namespaceId));
01856 if (OidIsValid(opfid))
01857 return opfid;
01858 }
01859
01860
01861 return InvalidOid;
01862 }
01863
01864
01865
01866
01867
01868
01869
01870 bool
01871 OpfamilyIsVisible(Oid opfid)
01872 {
01873 HeapTuple opftup;
01874 Form_pg_opfamily opfform;
01875 Oid opfnamespace;
01876 bool visible;
01877
01878 opftup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfid));
01879 if (!HeapTupleIsValid(opftup))
01880 elog(ERROR, "cache lookup failed for opfamily %u", opfid);
01881 opfform = (Form_pg_opfamily) GETSTRUCT(opftup);
01882
01883 recomputeNamespacePath();
01884
01885
01886
01887
01888
01889
01890 opfnamespace = opfform->opfnamespace;
01891 if (opfnamespace != PG_CATALOG_NAMESPACE &&
01892 !list_member_oid(activeSearchPath, opfnamespace))
01893 visible = false;
01894 else
01895 {
01896
01897
01898
01899
01900
01901
01902 char *opfname = NameStr(opfform->opfname);
01903
01904 visible = (OpfamilynameGetOpfid(opfform->opfmethod, opfname) == opfid);
01905 }
01906
01907 ReleaseSysCache(opftup);
01908
01909 return visible;
01910 }
01911
01912
01913
01914
01915
01916
01917 Oid
01918 CollationGetCollid(const char *collname)
01919 {
01920 int32 dbencoding = GetDatabaseEncoding();
01921 ListCell *l;
01922
01923 recomputeNamespacePath();
01924
01925 foreach(l, activeSearchPath)
01926 {
01927 Oid namespaceId = lfirst_oid(l);
01928 Oid collid;
01929
01930 if (namespaceId == myTempNamespace)
01931 continue;
01932
01933
01934 collid = GetSysCacheOid3(COLLNAMEENCNSP,
01935 PointerGetDatum(collname),
01936 Int32GetDatum(dbencoding),
01937 ObjectIdGetDatum(namespaceId));
01938 if (OidIsValid(collid))
01939 return collid;
01940
01941
01942 collid = GetSysCacheOid3(COLLNAMEENCNSP,
01943 PointerGetDatum(collname),
01944 Int32GetDatum(-1),
01945 ObjectIdGetDatum(namespaceId));
01946 if (OidIsValid(collid))
01947 return collid;
01948 }
01949
01950
01951 return InvalidOid;
01952 }
01953
01954
01955
01956
01957
01958
01959
01960 bool
01961 CollationIsVisible(Oid collid)
01962 {
01963 HeapTuple colltup;
01964 Form_pg_collation collform;
01965 Oid collnamespace;
01966 bool visible;
01967
01968 colltup = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid));
01969 if (!HeapTupleIsValid(colltup))
01970 elog(ERROR, "cache lookup failed for collation %u", collid);
01971 collform = (Form_pg_collation) GETSTRUCT(colltup);
01972
01973 recomputeNamespacePath();
01974
01975
01976
01977
01978
01979
01980 collnamespace = collform->collnamespace;
01981 if (collnamespace != PG_CATALOG_NAMESPACE &&
01982 !list_member_oid(activeSearchPath, collnamespace))
01983 visible = false;
01984 else
01985 {
01986
01987
01988
01989
01990
01991
01992 char *collname = NameStr(collform->collname);
01993
01994 visible = (CollationGetCollid(collname) == collid);
01995 }
01996
01997 ReleaseSysCache(colltup);
01998
01999 return visible;
02000 }
02001
02002
02003
02004
02005
02006
02007
02008
02009
02010 Oid
02011 ConversionGetConid(const char *conname)
02012 {
02013 Oid conid;
02014 ListCell *l;
02015
02016 recomputeNamespacePath();
02017
02018 foreach(l, activeSearchPath)
02019 {
02020 Oid namespaceId = lfirst_oid(l);
02021
02022 if (namespaceId == myTempNamespace)
02023 continue;
02024
02025 conid = GetSysCacheOid2(CONNAMENSP,
02026 PointerGetDatum(conname),
02027 ObjectIdGetDatum(namespaceId));
02028 if (OidIsValid(conid))
02029 return conid;
02030 }
02031
02032
02033 return InvalidOid;
02034 }
02035
02036
02037
02038
02039
02040
02041
02042 bool
02043 ConversionIsVisible(Oid conid)
02044 {
02045 HeapTuple contup;
02046 Form_pg_conversion conform;
02047 Oid connamespace;
02048 bool visible;
02049
02050 contup = SearchSysCache1(CONVOID, ObjectIdGetDatum(conid));
02051 if (!HeapTupleIsValid(contup))
02052 elog(ERROR, "cache lookup failed for conversion %u", conid);
02053 conform = (Form_pg_conversion) GETSTRUCT(contup);
02054
02055 recomputeNamespacePath();
02056
02057
02058
02059
02060
02061
02062 connamespace = conform->connamespace;
02063 if (connamespace != PG_CATALOG_NAMESPACE &&
02064 !list_member_oid(activeSearchPath, connamespace))
02065 visible = false;
02066 else
02067 {
02068
02069
02070
02071
02072
02073
02074 char *conname = NameStr(conform->conname);
02075
02076 visible = (ConversionGetConid(conname) == conid);
02077 }
02078
02079 ReleaseSysCache(contup);
02080
02081 return visible;
02082 }
02083
02084
02085
02086
02087
02088
02089 Oid
02090 get_ts_parser_oid(List *names, bool missing_ok)
02091 {
02092 char *schemaname;
02093 char *parser_name;
02094 Oid namespaceId;
02095 Oid prsoid = InvalidOid;
02096 ListCell *l;
02097
02098
02099 DeconstructQualifiedName(names, &schemaname, &parser_name);
02100
02101 if (schemaname)
02102 {
02103
02104 namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
02105 if (missing_ok && !OidIsValid(namespaceId))
02106 prsoid = InvalidOid;
02107 else
02108 prsoid = GetSysCacheOid2(TSPARSERNAMENSP,
02109 PointerGetDatum(parser_name),
02110 ObjectIdGetDatum(namespaceId));
02111 }
02112 else
02113 {
02114
02115 recomputeNamespacePath();
02116
02117 foreach(l, activeSearchPath)
02118 {
02119 namespaceId = lfirst_oid(l);
02120
02121 if (namespaceId == myTempNamespace)
02122 continue;
02123
02124 prsoid = GetSysCacheOid2(TSPARSERNAMENSP,
02125 PointerGetDatum(parser_name),
02126 ObjectIdGetDatum(namespaceId));
02127 if (OidIsValid(prsoid))
02128 break;
02129 }
02130 }
02131
02132 if (!OidIsValid(prsoid) && !missing_ok)
02133 ereport(ERROR,
02134 (errcode(ERRCODE_UNDEFINED_OBJECT),
02135 errmsg("text search parser \"%s\" does not exist",
02136 NameListToString(names))));
02137
02138 return prsoid;
02139 }
02140
02141
02142
02143
02144
02145
02146
02147 bool
02148 TSParserIsVisible(Oid prsId)
02149 {
02150 HeapTuple tup;
02151 Form_pg_ts_parser form;
02152 Oid namespace;
02153 bool visible;
02154
02155 tup = SearchSysCache1(TSPARSEROID, ObjectIdGetDatum(prsId));
02156 if (!HeapTupleIsValid(tup))
02157 elog(ERROR, "cache lookup failed for text search parser %u", prsId);
02158 form = (Form_pg_ts_parser) GETSTRUCT(tup);
02159
02160 recomputeNamespacePath();
02161
02162
02163
02164
02165
02166
02167 namespace = form->prsnamespace;
02168 if (namespace != PG_CATALOG_NAMESPACE &&
02169 !list_member_oid(activeSearchPath, namespace))
02170 visible = false;
02171 else
02172 {
02173
02174
02175
02176
02177
02178 char *name = NameStr(form->prsname);
02179 ListCell *l;
02180
02181 visible = false;
02182 foreach(l, activeSearchPath)
02183 {
02184 Oid namespaceId = lfirst_oid(l);
02185
02186 if (namespaceId == myTempNamespace)
02187 continue;
02188
02189 if (namespaceId == namespace)
02190 {
02191
02192 visible = true;
02193 break;
02194 }
02195 if (SearchSysCacheExists2(TSPARSERNAMENSP,
02196 PointerGetDatum(name),
02197 ObjectIdGetDatum(namespaceId)))
02198 {
02199
02200 break;
02201 }
02202 }
02203 }
02204
02205 ReleaseSysCache(tup);
02206
02207 return visible;
02208 }
02209
02210
02211
02212
02213
02214
02215 Oid
02216 get_ts_dict_oid(List *names, bool missing_ok)
02217 {
02218 char *schemaname;
02219 char *dict_name;
02220 Oid namespaceId;
02221 Oid dictoid = InvalidOid;
02222 ListCell *l;
02223
02224
02225 DeconstructQualifiedName(names, &schemaname, &dict_name);
02226
02227 if (schemaname)
02228 {
02229
02230 namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
02231 if (missing_ok && !OidIsValid(namespaceId))
02232 dictoid = InvalidOid;
02233 else
02234 dictoid = GetSysCacheOid2(TSDICTNAMENSP,
02235 PointerGetDatum(dict_name),
02236 ObjectIdGetDatum(namespaceId));
02237 }
02238 else
02239 {
02240
02241 recomputeNamespacePath();
02242
02243 foreach(l, activeSearchPath)
02244 {
02245 namespaceId = lfirst_oid(l);
02246
02247 if (namespaceId == myTempNamespace)
02248 continue;
02249
02250 dictoid = GetSysCacheOid2(TSDICTNAMENSP,
02251 PointerGetDatum(dict_name),
02252 ObjectIdGetDatum(namespaceId));
02253 if (OidIsValid(dictoid))
02254 break;
02255 }
02256 }
02257
02258 if (!OidIsValid(dictoid) && !missing_ok)
02259 ereport(ERROR,
02260 (errcode(ERRCODE_UNDEFINED_OBJECT),
02261 errmsg("text search dictionary \"%s\" does not exist",
02262 NameListToString(names))));
02263
02264 return dictoid;
02265 }
02266
02267
02268
02269
02270
02271
02272
02273 bool
02274 TSDictionaryIsVisible(Oid dictId)
02275 {
02276 HeapTuple tup;
02277 Form_pg_ts_dict form;
02278 Oid namespace;
02279 bool visible;
02280
02281 tup = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(dictId));
02282 if (!HeapTupleIsValid(tup))
02283 elog(ERROR, "cache lookup failed for text search dictionary %u",
02284 dictId);
02285 form = (Form_pg_ts_dict) GETSTRUCT(tup);
02286
02287 recomputeNamespacePath();
02288
02289
02290
02291
02292
02293
02294 namespace = form->dictnamespace;
02295 if (namespace != PG_CATALOG_NAMESPACE &&
02296 !list_member_oid(activeSearchPath, namespace))
02297 visible = false;
02298 else
02299 {
02300
02301
02302
02303
02304
02305 char *name = NameStr(form->dictname);
02306 ListCell *l;
02307
02308 visible = false;
02309 foreach(l, activeSearchPath)
02310 {
02311 Oid namespaceId = lfirst_oid(l);
02312
02313 if (namespaceId == myTempNamespace)
02314 continue;
02315
02316 if (namespaceId == namespace)
02317 {
02318
02319 visible = true;
02320 break;
02321 }
02322 if (SearchSysCacheExists2(TSDICTNAMENSP,
02323 PointerGetDatum(name),
02324 ObjectIdGetDatum(namespaceId)))
02325 {
02326
02327 break;
02328 }
02329 }
02330 }
02331
02332 ReleaseSysCache(tup);
02333
02334 return visible;
02335 }
02336
02337
02338
02339
02340
02341
02342 Oid
02343 get_ts_template_oid(List *names, bool missing_ok)
02344 {
02345 char *schemaname;
02346 char *template_name;
02347 Oid namespaceId;
02348 Oid tmploid = InvalidOid;
02349 ListCell *l;
02350
02351
02352 DeconstructQualifiedName(names, &schemaname, &template_name);
02353
02354 if (schemaname)
02355 {
02356
02357 namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
02358 if (missing_ok && !OidIsValid(namespaceId))
02359 tmploid = InvalidOid;
02360 else
02361 tmploid = GetSysCacheOid2(TSTEMPLATENAMENSP,
02362 PointerGetDatum(template_name),
02363 ObjectIdGetDatum(namespaceId));
02364 }
02365 else
02366 {
02367
02368 recomputeNamespacePath();
02369
02370 foreach(l, activeSearchPath)
02371 {
02372 namespaceId = lfirst_oid(l);
02373
02374 if (namespaceId == myTempNamespace)
02375 continue;
02376
02377 tmploid = GetSysCacheOid2(TSTEMPLATENAMENSP,
02378 PointerGetDatum(template_name),
02379 ObjectIdGetDatum(namespaceId));
02380 if (OidIsValid(tmploid))
02381 break;
02382 }
02383 }
02384
02385 if (!OidIsValid(tmploid) && !missing_ok)
02386 ereport(ERROR,
02387 (errcode(ERRCODE_UNDEFINED_OBJECT),
02388 errmsg("text search template \"%s\" does not exist",
02389 NameListToString(names))));
02390
02391 return tmploid;
02392 }
02393
02394
02395
02396
02397
02398
02399
02400 bool
02401 TSTemplateIsVisible(Oid tmplId)
02402 {
02403 HeapTuple tup;
02404 Form_pg_ts_template form;
02405 Oid namespace;
02406 bool visible;
02407
02408 tup = SearchSysCache1(TSTEMPLATEOID, ObjectIdGetDatum(tmplId));
02409 if (!HeapTupleIsValid(tup))
02410 elog(ERROR, "cache lookup failed for text search template %u", tmplId);
02411 form = (Form_pg_ts_template) GETSTRUCT(tup);
02412
02413 recomputeNamespacePath();
02414
02415
02416
02417
02418
02419
02420 namespace = form->tmplnamespace;
02421 if (namespace != PG_CATALOG_NAMESPACE &&
02422 !list_member_oid(activeSearchPath, namespace))
02423 visible = false;
02424 else
02425 {
02426
02427
02428
02429
02430
02431 char *name = NameStr(form->tmplname);
02432 ListCell *l;
02433
02434 visible = false;
02435 foreach(l, activeSearchPath)
02436 {
02437 Oid namespaceId = lfirst_oid(l);
02438
02439 if (namespaceId == myTempNamespace)
02440 continue;
02441
02442 if (namespaceId == namespace)
02443 {
02444
02445 visible = true;
02446 break;
02447 }
02448 if (SearchSysCacheExists2(TSTEMPLATENAMENSP,
02449 PointerGetDatum(name),
02450 ObjectIdGetDatum(namespaceId)))
02451 {
02452
02453 break;
02454 }
02455 }
02456 }
02457
02458 ReleaseSysCache(tup);
02459
02460 return visible;
02461 }
02462
02463
02464
02465
02466
02467
02468 Oid
02469 get_ts_config_oid(List *names, bool missing_ok)
02470 {
02471 char *schemaname;
02472 char *config_name;
02473 Oid namespaceId;
02474 Oid cfgoid = InvalidOid;
02475 ListCell *l;
02476
02477
02478 DeconstructQualifiedName(names, &schemaname, &config_name);
02479
02480 if (schemaname)
02481 {
02482
02483 namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
02484 if (missing_ok && !OidIsValid(namespaceId))
02485 cfgoid = InvalidOid;
02486 else
02487 cfgoid = GetSysCacheOid2(TSCONFIGNAMENSP,
02488 PointerGetDatum(config_name),
02489 ObjectIdGetDatum(namespaceId));
02490 }
02491 else
02492 {
02493
02494 recomputeNamespacePath();
02495
02496 foreach(l, activeSearchPath)
02497 {
02498 namespaceId = lfirst_oid(l);
02499
02500 if (namespaceId == myTempNamespace)
02501 continue;
02502
02503 cfgoid = GetSysCacheOid2(TSCONFIGNAMENSP,
02504 PointerGetDatum(config_name),
02505 ObjectIdGetDatum(namespaceId));
02506 if (OidIsValid(cfgoid))
02507 break;
02508 }
02509 }
02510
02511 if (!OidIsValid(cfgoid) && !missing_ok)
02512 ereport(ERROR,
02513 (errcode(ERRCODE_UNDEFINED_OBJECT),
02514 errmsg("text search configuration \"%s\" does not exist",
02515 NameListToString(names))));
02516
02517 return cfgoid;
02518 }
02519
02520
02521
02522
02523
02524
02525
02526 bool
02527 TSConfigIsVisible(Oid cfgid)
02528 {
02529 HeapTuple tup;
02530 Form_pg_ts_config form;
02531 Oid namespace;
02532 bool visible;
02533
02534 tup = SearchSysCache1(TSCONFIGOID, ObjectIdGetDatum(cfgid));
02535 if (!HeapTupleIsValid(tup))
02536 elog(ERROR, "cache lookup failed for text search configuration %u",
02537 cfgid);
02538 form = (Form_pg_ts_config) GETSTRUCT(tup);
02539
02540 recomputeNamespacePath();
02541
02542
02543
02544
02545
02546
02547 namespace = form->cfgnamespace;
02548 if (namespace != PG_CATALOG_NAMESPACE &&
02549 !list_member_oid(activeSearchPath, namespace))
02550 visible = false;
02551 else
02552 {
02553
02554
02555
02556
02557
02558 char *name = NameStr(form->cfgname);
02559 ListCell *l;
02560
02561 visible = false;
02562 foreach(l, activeSearchPath)
02563 {
02564 Oid namespaceId = lfirst_oid(l);
02565
02566 if (namespaceId == myTempNamespace)
02567 continue;
02568
02569 if (namespaceId == namespace)
02570 {
02571
02572 visible = true;
02573 break;
02574 }
02575 if (SearchSysCacheExists2(TSCONFIGNAMENSP,
02576 PointerGetDatum(name),
02577 ObjectIdGetDatum(namespaceId)))
02578 {
02579
02580 break;
02581 }
02582 }
02583 }
02584
02585 ReleaseSysCache(tup);
02586
02587 return visible;
02588 }
02589
02590
02591
02592
02593
02594
02595
02596
02597
02598 void
02599 DeconstructQualifiedName(List *names,
02600 char **nspname_p,
02601 char **objname_p)
02602 {
02603 char *catalogname;
02604 char *schemaname = NULL;
02605 char *objname = NULL;
02606
02607 switch (list_length(names))
02608 {
02609 case 1:
02610 objname = strVal(linitial(names));
02611 break;
02612 case 2:
02613 schemaname = strVal(linitial(names));
02614 objname = strVal(lsecond(names));
02615 break;
02616 case 3:
02617 catalogname = strVal(linitial(names));
02618 schemaname = strVal(lsecond(names));
02619 objname = strVal(lthird(names));
02620
02621
02622
02623
02624 if (strcmp(catalogname, get_database_name(MyDatabaseId)) != 0)
02625 ereport(ERROR,
02626 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
02627 errmsg("cross-database references are not implemented: %s",
02628 NameListToString(names))));
02629 break;
02630 default:
02631 ereport(ERROR,
02632 (errcode(ERRCODE_SYNTAX_ERROR),
02633 errmsg("improper qualified name (too many dotted names): %s",
02634 NameListToString(names))));
02635 break;
02636 }
02637
02638 *nspname_p = schemaname;
02639 *objname_p = objname;
02640 }
02641
02642
02643
02644
02645
02646
02647
02648
02649
02650
02651
02652 Oid
02653 LookupNamespaceNoError(const char *nspname)
02654 {
02655
02656 if (strcmp(nspname, "pg_temp") == 0)
02657 {
02658 if (OidIsValid(myTempNamespace))
02659 {
02660 InvokeNamespaceSearchHook(myTempNamespace, true);
02661 return myTempNamespace;
02662 }
02663
02664
02665
02666
02667
02668
02669 return InvalidOid;
02670 }
02671
02672 return get_namespace_oid(nspname, true);
02673 }
02674
02675
02676
02677
02678
02679
02680
02681
02682 Oid
02683 LookupExplicitNamespace(const char *nspname, bool missing_ok)
02684 {
02685 Oid namespaceId;
02686 AclResult aclresult;
02687
02688
02689 if (strcmp(nspname, "pg_temp") == 0)
02690 {
02691 if (OidIsValid(myTempNamespace))
02692 return myTempNamespace;
02693
02694
02695
02696
02697
02698
02699 }
02700
02701 namespaceId = get_namespace_oid(nspname, missing_ok);
02702 if (missing_ok && !OidIsValid(namespaceId))
02703 return InvalidOid;
02704
02705 aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
02706 if (aclresult != ACLCHECK_OK)
02707 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
02708 nspname);
02709
02710 InvokeNamespaceSearchHook(namespaceId, true);
02711
02712 return namespaceId;
02713 }
02714
02715
02716
02717
02718
02719
02720
02721
02722
02723
02724
02725 Oid
02726 LookupCreationNamespace(const char *nspname)
02727 {
02728 Oid namespaceId;
02729 AclResult aclresult;
02730
02731
02732 if (strcmp(nspname, "pg_temp") == 0)
02733 {
02734
02735 if (!OidIsValid(myTempNamespace))
02736 InitTempTableNamespace();
02737 return myTempNamespace;
02738 }
02739
02740 namespaceId = get_namespace_oid(nspname, false);
02741
02742 aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
02743 if (aclresult != ACLCHECK_OK)
02744 aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
02745 nspname);
02746
02747 return namespaceId;
02748 }
02749
02750
02751
02752
02753
02754
02755
02756
02757 void
02758 CheckSetNamespace(Oid oldNspOid, Oid nspOid, Oid classid, Oid objid)
02759 {
02760 if (oldNspOid == nspOid)
02761 ereport(ERROR,
02762 (classid == RelationRelationId ?
02763 errcode(ERRCODE_DUPLICATE_TABLE) :
02764 classid == ProcedureRelationId ?
02765 errcode(ERRCODE_DUPLICATE_FUNCTION) :
02766 errcode(ERRCODE_DUPLICATE_OBJECT),
02767 errmsg("%s is already in schema \"%s\"",
02768 getObjectDescriptionOids(classid, objid),
02769 get_namespace_name(nspOid))));
02770
02771
02772 if (isAnyTempNamespace(nspOid) || isAnyTempNamespace(oldNspOid))
02773 ereport(ERROR,
02774 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
02775 errmsg("cannot move objects into or out of temporary schemas")));
02776
02777
02778 if (nspOid == PG_TOAST_NAMESPACE || oldNspOid == PG_TOAST_NAMESPACE)
02779 ereport(ERROR,
02780 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
02781 errmsg("cannot move objects into or out of TOAST schema")));
02782 }
02783
02784
02785
02786
02787
02788
02789
02790
02791
02792
02793
02794
02795
02796 Oid
02797 QualifiedNameGetCreationNamespace(List *names, char **objname_p)
02798 {
02799 char *schemaname;
02800 Oid namespaceId;
02801
02802
02803 DeconstructQualifiedName(names, &schemaname, objname_p);
02804
02805 if (schemaname)
02806 {
02807
02808 if (strcmp(schemaname, "pg_temp") == 0)
02809 {
02810
02811 if (!OidIsValid(myTempNamespace))
02812 InitTempTableNamespace();
02813 return myTempNamespace;
02814 }
02815
02816 namespaceId = get_namespace_oid(schemaname, false);
02817
02818 }
02819 else
02820 {
02821
02822 recomputeNamespacePath();
02823 if (activeTempCreationPending)
02824 {
02825
02826 InitTempTableNamespace();
02827 return myTempNamespace;
02828 }
02829 namespaceId = activeCreationNamespace;
02830 if (!OidIsValid(namespaceId))
02831 ereport(ERROR,
02832 (errcode(ERRCODE_UNDEFINED_SCHEMA),
02833 errmsg("no schema has been selected to create in")));
02834 }
02835
02836 return namespaceId;
02837 }
02838
02839
02840
02841
02842
02843
02844
02845 Oid
02846 get_namespace_oid(const char *nspname, bool missing_ok)
02847 {
02848 Oid oid;
02849
02850 oid = GetSysCacheOid1(NAMESPACENAME, CStringGetDatum(nspname));
02851 if (!OidIsValid(oid) && !missing_ok)
02852 ereport(ERROR,
02853 (errcode(ERRCODE_UNDEFINED_SCHEMA),
02854 errmsg("schema \"%s\" does not exist", nspname)));
02855
02856 return oid;
02857 }
02858
02859
02860
02861
02862
02863 RangeVar *
02864 makeRangeVarFromNameList(List *names)
02865 {
02866 RangeVar *rel = makeRangeVar(NULL, NULL, -1);
02867
02868 switch (list_length(names))
02869 {
02870 case 1:
02871 rel->relname = strVal(linitial(names));
02872 break;
02873 case 2:
02874 rel->schemaname = strVal(linitial(names));
02875 rel->relname = strVal(lsecond(names));
02876 break;
02877 case 3:
02878 rel->catalogname = strVal(linitial(names));
02879 rel->schemaname = strVal(lsecond(names));
02880 rel->relname = strVal(lthird(names));
02881 break;
02882 default:
02883 ereport(ERROR,
02884 (errcode(ERRCODE_SYNTAX_ERROR),
02885 errmsg("improper relation name (too many dotted names): %s",
02886 NameListToString(names))));
02887 break;
02888 }
02889
02890 return rel;
02891 }
02892
02893
02894
02895
02896
02897
02898
02899
02900
02901
02902
02903 char *
02904 NameListToString(List *names)
02905 {
02906 StringInfoData string;
02907 ListCell *l;
02908
02909 initStringInfo(&string);
02910
02911 foreach(l, names)
02912 {
02913 Node *name = (Node *) lfirst(l);
02914
02915 if (l != list_head(names))
02916 appendStringInfoChar(&string, '.');
02917
02918 if (IsA(name, String))
02919 appendStringInfoString(&string, strVal(name));
02920 else if (IsA(name, A_Star))
02921 appendStringInfoString(&string, "*");
02922 else
02923 elog(ERROR, "unexpected node type in name list: %d",
02924 (int) nodeTag(name));
02925 }
02926
02927 return string.data;
02928 }
02929
02930
02931
02932
02933
02934
02935
02936
02937 char *
02938 NameListToQuotedString(List *names)
02939 {
02940 StringInfoData string;
02941 ListCell *l;
02942
02943 initStringInfo(&string);
02944
02945 foreach(l, names)
02946 {
02947 if (l != list_head(names))
02948 appendStringInfoChar(&string, '.');
02949 appendStringInfoString(&string, quote_identifier(strVal(lfirst(l))));
02950 }
02951
02952 return string.data;
02953 }
02954
02955
02956
02957
02958 bool
02959 isTempNamespace(Oid namespaceId)
02960 {
02961 if (OidIsValid(myTempNamespace) && myTempNamespace == namespaceId)
02962 return true;
02963 return false;
02964 }
02965
02966
02967
02968
02969
02970 bool
02971 isTempToastNamespace(Oid namespaceId)
02972 {
02973 if (OidIsValid(myTempToastNamespace) && myTempToastNamespace == namespaceId)
02974 return true;
02975 return false;
02976 }
02977
02978
02979
02980
02981
02982 bool
02983 isTempOrToastNamespace(Oid namespaceId)
02984 {
02985 if (OidIsValid(myTempNamespace) &&
02986 (myTempNamespace == namespaceId || myTempToastNamespace == namespaceId))
02987 return true;
02988 return false;
02989 }
02990
02991
02992
02993
02994
02995
02996 bool
02997 isAnyTempNamespace(Oid namespaceId)
02998 {
02999 bool result;
03000 char *nspname;
03001
03002
03003 nspname = get_namespace_name(namespaceId);
03004 if (!nspname)
03005 return false;
03006 result = (strncmp(nspname, "pg_temp_", 8) == 0) ||
03007 (strncmp(nspname, "pg_toast_temp_", 14) == 0);
03008 pfree(nspname);
03009 return result;
03010 }
03011
03012
03013
03014
03015
03016
03017
03018
03019 bool
03020 isOtherTempNamespace(Oid namespaceId)
03021 {
03022
03023 if (isTempOrToastNamespace(namespaceId))
03024 return false;
03025
03026 return isAnyTempNamespace(namespaceId);
03027 }
03028
03029
03030
03031
03032
03033
03034
03035 int
03036 GetTempNamespaceBackendId(Oid namespaceId)
03037 {
03038 int result;
03039 char *nspname;
03040
03041
03042 nspname = get_namespace_name(namespaceId);
03043 if (!nspname)
03044 return InvalidBackendId;
03045 if (strncmp(nspname, "pg_temp_", 8) == 0)
03046 result = atoi(nspname + 8);
03047 else if (strncmp(nspname, "pg_toast_temp_", 14) == 0)
03048 result = atoi(nspname + 14);
03049 else
03050 result = InvalidBackendId;
03051 pfree(nspname);
03052 return result;
03053 }
03054
03055
03056
03057
03058
03059
03060 Oid
03061 GetTempToastNamespace(void)
03062 {
03063 Assert(OidIsValid(myTempToastNamespace));
03064 return myTempToastNamespace;
03065 }
03066
03067
03068
03069
03070
03071
03072
03073
03074
03075
03076 OverrideSearchPath *
03077 GetOverrideSearchPath(MemoryContext context)
03078 {
03079 OverrideSearchPath *result;
03080 List *schemas;
03081 MemoryContext oldcxt;
03082
03083 recomputeNamespacePath();
03084
03085 oldcxt = MemoryContextSwitchTo(context);
03086
03087 result = (OverrideSearchPath *) palloc0(sizeof(OverrideSearchPath));
03088 schemas = list_copy(activeSearchPath);
03089 while (schemas && linitial_oid(schemas) != activeCreationNamespace)
03090 {
03091 if (linitial_oid(schemas) == myTempNamespace)
03092 result->addTemp = true;
03093 else
03094 {
03095 Assert(linitial_oid(schemas) == PG_CATALOG_NAMESPACE);
03096 result->addCatalog = true;
03097 }
03098 schemas = list_delete_first(schemas);
03099 }
03100 result->schemas = schemas;
03101
03102 MemoryContextSwitchTo(oldcxt);
03103
03104 return result;
03105 }
03106
03107
03108
03109
03110
03111
03112 OverrideSearchPath *
03113 CopyOverrideSearchPath(OverrideSearchPath *path)
03114 {
03115 OverrideSearchPath *result;
03116
03117 result = (OverrideSearchPath *) palloc(sizeof(OverrideSearchPath));
03118 result->schemas = list_copy(path->schemas);
03119 result->addCatalog = path->addCatalog;
03120 result->addTemp = path->addTemp;
03121
03122 return result;
03123 }
03124
03125
03126
03127
03128 bool
03129 OverrideSearchPathMatchesCurrent(OverrideSearchPath *path)
03130 {
03131
03132 bool result;
03133 OverrideSearchPath *cur;
03134
03135 cur = GetOverrideSearchPath(CurrentMemoryContext);
03136 if (path->addCatalog == cur->addCatalog &&
03137 path->addTemp == cur->addTemp &&
03138 equal(path->schemas, cur->schemas))
03139 result = true;
03140 else
03141 result = false;
03142 list_free(cur->schemas);
03143 pfree(cur);
03144 return result;
03145 }
03146
03147
03148
03149
03150
03151
03152
03153
03154
03155
03156
03157
03158
03159
03160
03161
03162
03163
03164 void
03165 PushOverrideSearchPath(OverrideSearchPath *newpath)
03166 {
03167 OverrideStackEntry *entry;
03168 List *oidlist;
03169 Oid firstNS;
03170 MemoryContext oldcxt;
03171
03172
03173
03174
03175
03176 oldcxt = MemoryContextSwitchTo(TopMemoryContext);
03177
03178 oidlist = list_copy(newpath->schemas);
03179
03180
03181
03182
03183 if (oidlist == NIL)
03184 firstNS = InvalidOid;
03185 else
03186 firstNS = linitial_oid(oidlist);
03187
03188
03189
03190
03191
03192
03193 if (newpath->addCatalog)
03194 oidlist = lcons_oid(PG_CATALOG_NAMESPACE, oidlist);
03195
03196 if (newpath->addTemp && OidIsValid(myTempNamespace))
03197 oidlist = lcons_oid(myTempNamespace, oidlist);
03198
03199
03200
03201
03202 entry = (OverrideStackEntry *) palloc(sizeof(OverrideStackEntry));
03203 entry->searchPath = oidlist;
03204 entry->creationNamespace = firstNS;
03205 entry->nestLevel = GetCurrentTransactionNestLevel();
03206
03207 overrideStack = lcons(entry, overrideStack);
03208
03209
03210 activeSearchPath = entry->searchPath;
03211 activeCreationNamespace = entry->creationNamespace;
03212 activeTempCreationPending = false;
03213
03214 MemoryContextSwitchTo(oldcxt);
03215 }
03216
03217
03218
03219
03220
03221
03222
03223 void
03224 PopOverrideSearchPath(void)
03225 {
03226 OverrideStackEntry *entry;
03227
03228
03229 if (overrideStack == NIL)
03230 elog(ERROR, "bogus PopOverrideSearchPath call");
03231 entry = (OverrideStackEntry *) linitial(overrideStack);
03232 if (entry->nestLevel != GetCurrentTransactionNestLevel())
03233 elog(ERROR, "bogus PopOverrideSearchPath call");
03234
03235
03236 overrideStack = list_delete_first(overrideStack);
03237 list_free(entry->searchPath);
03238 pfree(entry);
03239
03240
03241 if (overrideStack)
03242 {
03243 entry = (OverrideStackEntry *) linitial(overrideStack);
03244 activeSearchPath = entry->searchPath;
03245 activeCreationNamespace = entry->creationNamespace;
03246 activeTempCreationPending = false;
03247 }
03248 else
03249 {
03250
03251 activeSearchPath = baseSearchPath;
03252 activeCreationNamespace = baseCreationNamespace;
03253 activeTempCreationPending = baseTempCreationPending;
03254 }
03255 }
03256
03257
03258
03259
03260
03261 Oid
03262 get_collation_oid(List *name, bool missing_ok)
03263 {
03264 char *schemaname;
03265 char *collation_name;
03266 int32 dbencoding = GetDatabaseEncoding();
03267 Oid namespaceId;
03268 Oid colloid;
03269 ListCell *l;
03270
03271
03272 DeconstructQualifiedName(name, &schemaname, &collation_name);
03273
03274 if (schemaname)
03275 {
03276
03277 namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
03278 if (missing_ok && !OidIsValid(namespaceId))
03279 return InvalidOid;
03280
03281
03282 colloid = GetSysCacheOid3(COLLNAMEENCNSP,
03283 PointerGetDatum(collation_name),
03284 Int32GetDatum(dbencoding),
03285 ObjectIdGetDatum(namespaceId));
03286 if (OidIsValid(colloid))
03287 return colloid;
03288 colloid = GetSysCacheOid3(COLLNAMEENCNSP,
03289 PointerGetDatum(collation_name),
03290 Int32GetDatum(-1),
03291 ObjectIdGetDatum(namespaceId));
03292 if (OidIsValid(colloid))
03293 return colloid;
03294 }
03295 else
03296 {
03297
03298 recomputeNamespacePath();
03299
03300 foreach(l, activeSearchPath)
03301 {
03302 namespaceId = lfirst_oid(l);
03303
03304 if (namespaceId == myTempNamespace)
03305 continue;
03306
03307 colloid = GetSysCacheOid3(COLLNAMEENCNSP,
03308 PointerGetDatum(collation_name),
03309 Int32GetDatum(dbencoding),
03310 ObjectIdGetDatum(namespaceId));
03311 if (OidIsValid(colloid))
03312 return colloid;
03313 colloid = GetSysCacheOid3(COLLNAMEENCNSP,
03314 PointerGetDatum(collation_name),
03315 Int32GetDatum(-1),
03316 ObjectIdGetDatum(namespaceId));
03317 if (OidIsValid(colloid))
03318 return colloid;
03319 }
03320 }
03321
03322
03323 if (!missing_ok)
03324 ereport(ERROR,
03325 (errcode(ERRCODE_UNDEFINED_OBJECT),
03326 errmsg("collation \"%s\" for encoding \"%s\" does not exist",
03327 NameListToString(name), GetDatabaseEncodingName())));
03328 return InvalidOid;
03329 }
03330
03331
03332
03333
03334 Oid
03335 get_conversion_oid(List *name, bool missing_ok)
03336 {
03337 char *schemaname;
03338 char *conversion_name;
03339 Oid namespaceId;
03340 Oid conoid = InvalidOid;
03341 ListCell *l;
03342
03343
03344 DeconstructQualifiedName(name, &schemaname, &conversion_name);
03345
03346 if (schemaname)
03347 {
03348
03349 namespaceId = LookupExplicitNamespace(schemaname, missing_ok);
03350 if (missing_ok && !OidIsValid(namespaceId))
03351 conoid = InvalidOid;
03352 else
03353 conoid = GetSysCacheOid2(CONNAMENSP,
03354 PointerGetDatum(conversion_name),
03355 ObjectIdGetDatum(namespaceId));
03356 }
03357 else
03358 {
03359
03360 recomputeNamespacePath();
03361
03362 foreach(l, activeSearchPath)
03363 {
03364 namespaceId = lfirst_oid(l);
03365
03366 if (namespaceId == myTempNamespace)
03367 continue;
03368
03369 conoid = GetSysCacheOid2(CONNAMENSP,
03370 PointerGetDatum(conversion_name),
03371 ObjectIdGetDatum(namespaceId));
03372 if (OidIsValid(conoid))
03373 return conoid;
03374 }
03375 }
03376
03377
03378 if (!OidIsValid(conoid) && !missing_ok)
03379 ereport(ERROR,
03380 (errcode(ERRCODE_UNDEFINED_OBJECT),
03381 errmsg("conversion \"%s\" does not exist",
03382 NameListToString(name))));
03383 return conoid;
03384 }
03385
03386
03387
03388
03389 Oid
03390 FindDefaultConversionProc(int32 for_encoding, int32 to_encoding)
03391 {
03392 Oid proc;
03393 ListCell *l;
03394
03395 recomputeNamespacePath();
03396
03397 foreach(l, activeSearchPath)
03398 {
03399 Oid namespaceId = lfirst_oid(l);
03400
03401 if (namespaceId == myTempNamespace)
03402 continue;
03403
03404 proc = FindDefaultConversion(namespaceId, for_encoding, to_encoding);
03405 if (OidIsValid(proc))
03406 return proc;
03407 }
03408
03409
03410 return InvalidOid;
03411 }
03412
03413
03414
03415
03416 static void
03417 recomputeNamespacePath(void)
03418 {
03419 Oid roleid = GetUserId();
03420 char *rawname;
03421 List *namelist;
03422 List *oidlist;
03423 List *newpath;
03424 ListCell *l;
03425 bool temp_missing;
03426 Oid firstNS;
03427 MemoryContext oldcxt;
03428
03429
03430 if (overrideStack)
03431 return;
03432
03433
03434 if (baseSearchPathValid && namespaceUser == roleid)
03435 return;
03436
03437
03438 rawname = pstrdup(namespace_search_path);
03439
03440
03441 if (!SplitIdentifierString(rawname, ',', &namelist))
03442 {
03443
03444
03445 elog(ERROR, "invalid list syntax");
03446 }
03447
03448
03449
03450
03451
03452
03453
03454 oidlist = NIL;
03455 temp_missing = false;
03456 foreach(l, namelist)
03457 {
03458 char *curname = (char *) lfirst(l);
03459 Oid namespaceId;
03460
03461 if (strcmp(curname, "$user") == 0)
03462 {
03463
03464 HeapTuple tuple;
03465
03466 tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
03467 if (HeapTupleIsValid(tuple))
03468 {
03469 char *rname;
03470
03471 rname = NameStr(((Form_pg_authid) GETSTRUCT(tuple))->rolname);
03472 namespaceId = get_namespace_oid(rname, true);
03473 ReleaseSysCache(tuple);
03474 if (OidIsValid(namespaceId) &&
03475 !list_member_oid(oidlist, namespaceId) &&
03476 pg_namespace_aclcheck(namespaceId, roleid,
03477 ACL_USAGE) == ACLCHECK_OK &&
03478 InvokeNamespaceSearchHook(namespaceId, false))
03479 oidlist = lappend_oid(oidlist, namespaceId);
03480 }
03481 }
03482 else if (strcmp(curname, "pg_temp") == 0)
03483 {
03484
03485 if (OidIsValid(myTempNamespace))
03486 {
03487 if (!list_member_oid(oidlist, myTempNamespace) &&
03488 InvokeNamespaceSearchHook(myTempNamespace, false))
03489 oidlist = lappend_oid(oidlist, myTempNamespace);
03490 }
03491 else
03492 {
03493
03494 if (oidlist == NIL)
03495 temp_missing = true;
03496 }
03497 }
03498 else
03499 {
03500
03501 namespaceId = get_namespace_oid(curname, true);
03502 if (OidIsValid(namespaceId) &&
03503 !list_member_oid(oidlist, namespaceId) &&
03504 pg_namespace_aclcheck(namespaceId, roleid,
03505 ACL_USAGE) == ACLCHECK_OK &&
03506 InvokeNamespaceSearchHook(namespaceId, false))
03507 oidlist = lappend_oid(oidlist, namespaceId);
03508 }
03509 }
03510
03511
03512
03513
03514
03515
03516 if (oidlist == NIL)
03517 firstNS = InvalidOid;
03518 else
03519 firstNS = linitial_oid(oidlist);
03520
03521
03522
03523
03524
03525
03526 if (!list_member_oid(oidlist, PG_CATALOG_NAMESPACE))
03527 oidlist = lcons_oid(PG_CATALOG_NAMESPACE, oidlist);
03528
03529 if (OidIsValid(myTempNamespace) &&
03530 !list_member_oid(oidlist, myTempNamespace))
03531 oidlist = lcons_oid(myTempNamespace, oidlist);
03532
03533
03534
03535
03536
03537 oldcxt = MemoryContextSwitchTo(TopMemoryContext);
03538 newpath = list_copy(oidlist);
03539 MemoryContextSwitchTo(oldcxt);
03540
03541
03542 list_free(baseSearchPath);
03543 baseSearchPath = newpath;
03544 baseCreationNamespace = firstNS;
03545 baseTempCreationPending = temp_missing;
03546
03547
03548 baseSearchPathValid = true;
03549 namespaceUser = roleid;
03550
03551
03552 activeSearchPath = baseSearchPath;
03553 activeCreationNamespace = baseCreationNamespace;
03554 activeTempCreationPending = baseTempCreationPending;
03555
03556
03557 pfree(rawname);
03558 list_free(namelist);
03559 list_free(oidlist);
03560 }
03561
03562
03563
03564
03565
03566 static void
03567 InitTempTableNamespace(void)
03568 {
03569 char namespaceName[NAMEDATALEN];
03570 Oid namespaceId;
03571 Oid toastspaceId;
03572
03573 Assert(!OidIsValid(myTempNamespace));
03574
03575
03576
03577
03578
03579
03580
03581
03582
03583
03584
03585 if (pg_database_aclcheck(MyDatabaseId, GetUserId(),
03586 ACL_CREATE_TEMP) != ACLCHECK_OK)
03587 ereport(ERROR,
03588 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
03589 errmsg("permission denied to create temporary tables in database \"%s\"",
03590 get_database_name(MyDatabaseId))));
03591
03592
03593
03594
03595
03596
03597
03598
03599
03600
03601
03602 if (RecoveryInProgress())
03603 ereport(ERROR,
03604 (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
03605 errmsg("cannot create temporary tables during recovery")));
03606
03607 snprintf(namespaceName, sizeof(namespaceName), "pg_temp_%d", MyBackendId);
03608
03609 namespaceId = get_namespace_oid(namespaceName, true);
03610 if (!OidIsValid(namespaceId))
03611 {
03612
03613
03614
03615
03616
03617
03618
03619
03620 namespaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID,
03621 true);
03622
03623 CommandCounterIncrement();
03624 }
03625 else
03626 {
03627
03628
03629
03630
03631 RemoveTempRelations(namespaceId);
03632 }
03633
03634
03635
03636
03637
03638
03639 snprintf(namespaceName, sizeof(namespaceName), "pg_toast_temp_%d",
03640 MyBackendId);
03641
03642 toastspaceId = get_namespace_oid(namespaceName, true);
03643 if (!OidIsValid(toastspaceId))
03644 {
03645 toastspaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID,
03646 true);
03647
03648 CommandCounterIncrement();
03649 }
03650
03651
03652
03653
03654
03655
03656 myTempNamespace = namespaceId;
03657 myTempToastNamespace = toastspaceId;
03658
03659
03660 AssertState(myTempNamespaceSubID == InvalidSubTransactionId);
03661 myTempNamespaceSubID = GetCurrentSubTransactionId();
03662
03663 baseSearchPathValid = false;
03664 }
03665
03666
03667
03668
03669 void
03670 AtEOXact_Namespace(bool isCommit)
03671 {
03672
03673
03674
03675
03676
03677
03678
03679
03680 if (myTempNamespaceSubID != InvalidSubTransactionId)
03681 {
03682 if (isCommit)
03683 on_shmem_exit(RemoveTempRelationsCallback, 0);
03684 else
03685 {
03686 myTempNamespace = InvalidOid;
03687 myTempToastNamespace = InvalidOid;
03688 baseSearchPathValid = false;
03689 }
03690 myTempNamespaceSubID = InvalidSubTransactionId;
03691 }
03692
03693
03694
03695
03696 if (overrideStack)
03697 {
03698 if (isCommit)
03699 elog(WARNING, "leaked override search path");
03700 while (overrideStack)
03701 {
03702 OverrideStackEntry *entry;
03703
03704 entry = (OverrideStackEntry *) linitial(overrideStack);
03705 overrideStack = list_delete_first(overrideStack);
03706 list_free(entry->searchPath);
03707 pfree(entry);
03708 }
03709
03710 activeSearchPath = baseSearchPath;
03711 activeCreationNamespace = baseCreationNamespace;
03712 activeTempCreationPending = baseTempCreationPending;
03713 }
03714 }
03715
03716
03717
03718
03719
03720
03721
03722
03723
03724 void
03725 AtEOSubXact_Namespace(bool isCommit, SubTransactionId mySubid,
03726 SubTransactionId parentSubid)
03727 {
03728 OverrideStackEntry *entry;
03729
03730 if (myTempNamespaceSubID == mySubid)
03731 {
03732 if (isCommit)
03733 myTempNamespaceSubID = parentSubid;
03734 else
03735 {
03736 myTempNamespaceSubID = InvalidSubTransactionId;
03737
03738 myTempNamespace = InvalidOid;
03739 myTempToastNamespace = InvalidOid;
03740 baseSearchPathValid = false;
03741 }
03742 }
03743
03744
03745
03746
03747 while (overrideStack)
03748 {
03749 entry = (OverrideStackEntry *) linitial(overrideStack);
03750 if (entry->nestLevel < GetCurrentTransactionNestLevel())
03751 break;
03752 if (isCommit)
03753 elog(WARNING, "leaked override search path");
03754 overrideStack = list_delete_first(overrideStack);
03755 list_free(entry->searchPath);
03756 pfree(entry);
03757 }
03758
03759
03760 if (overrideStack)
03761 {
03762 entry = (OverrideStackEntry *) linitial(overrideStack);
03763 activeSearchPath = entry->searchPath;
03764 activeCreationNamespace = entry->creationNamespace;
03765 activeTempCreationPending = false;
03766 }
03767 else
03768 {
03769
03770 activeSearchPath = baseSearchPath;
03771 activeCreationNamespace = baseCreationNamespace;
03772 activeTempCreationPending = baseTempCreationPending;
03773 }
03774 }
03775
03776
03777
03778
03779
03780
03781
03782
03783
03784 static void
03785 RemoveTempRelations(Oid tempNamespaceId)
03786 {
03787 ObjectAddress object;
03788
03789
03790
03791
03792
03793
03794
03795 object.classId = NamespaceRelationId;
03796 object.objectId = tempNamespaceId;
03797 object.objectSubId = 0;
03798
03799 deleteWhatDependsOn(&object, false);
03800 }
03801
03802
03803
03804
03805 static void
03806 RemoveTempRelationsCallback(int code, Datum arg)
03807 {
03808 if (OidIsValid(myTempNamespace))
03809 {
03810
03811 AbortOutOfAnyTransaction();
03812 StartTransactionCommand();
03813
03814 RemoveTempRelations(myTempNamespace);
03815
03816 CommitTransactionCommand();
03817 }
03818 }
03819
03820
03821
03822
03823 void
03824 ResetTempTableNamespace(void)
03825 {
03826 if (OidIsValid(myTempNamespace))
03827 RemoveTempRelations(myTempNamespace);
03828 }
03829
03830
03831
03832
03833
03834
03835
03836 bool
03837 check_search_path(char **newval, void **extra, GucSource source)
03838 {
03839 char *rawname;
03840 List *namelist;
03841
03842
03843 rawname = pstrdup(*newval);
03844
03845
03846 if (!SplitIdentifierString(rawname, ',', &namelist))
03847 {
03848
03849 GUC_check_errdetail("List syntax is invalid.");
03850 pfree(rawname);
03851 list_free(namelist);
03852 return false;
03853 }
03854
03855
03856
03857
03858
03859
03860
03861
03862
03863 pfree(rawname);
03864 list_free(namelist);
03865
03866 return true;
03867 }
03868
03869
03870 void
03871 assign_search_path(const char *newval, void *extra)
03872 {
03873
03874
03875
03876
03877
03878 baseSearchPathValid = false;
03879 }
03880
03881
03882
03883
03884
03885
03886 void
03887 InitializeSearchPath(void)
03888 {
03889 if (IsBootstrapProcessingMode())
03890 {
03891
03892
03893
03894
03895 MemoryContext oldcxt;
03896
03897 oldcxt = MemoryContextSwitchTo(TopMemoryContext);
03898 baseSearchPath = list_make1_oid(PG_CATALOG_NAMESPACE);
03899 MemoryContextSwitchTo(oldcxt);
03900 baseCreationNamespace = PG_CATALOG_NAMESPACE;
03901 baseTempCreationPending = false;
03902 baseSearchPathValid = true;
03903 namespaceUser = GetUserId();
03904 activeSearchPath = baseSearchPath;
03905 activeCreationNamespace = baseCreationNamespace;
03906 activeTempCreationPending = baseTempCreationPending;
03907 }
03908 else
03909 {
03910
03911
03912
03913
03914 CacheRegisterSyscacheCallback(NAMESPACEOID,
03915 NamespaceCallback,
03916 (Datum) 0);
03917
03918 baseSearchPathValid = false;
03919 }
03920 }
03921
03922
03923
03924
03925
03926 static void
03927 NamespaceCallback(Datum arg, int cacheid, uint32 hashvalue)
03928 {
03929
03930 baseSearchPathValid = false;
03931 }
03932
03933
03934
03935
03936
03937
03938
03939
03940
03941
03942
03943
03944 List *
03945 fetch_search_path(bool includeImplicit)
03946 {
03947 List *result;
03948
03949 recomputeNamespacePath();
03950
03951
03952
03953
03954
03955
03956
03957
03958 if (activeTempCreationPending)
03959 {
03960 InitTempTableNamespace();
03961 recomputeNamespacePath();
03962 }
03963
03964 result = list_copy(activeSearchPath);
03965 if (!includeImplicit)
03966 {
03967 while (result && linitial_oid(result) != activeCreationNamespace)
03968 result = list_delete_first(result);
03969 }
03970
03971 return result;
03972 }
03973
03974
03975
03976
03977
03978
03979
03980
03981
03982
03983
03984 int
03985 fetch_search_path_array(Oid *sarray, int sarray_len)
03986 {
03987 int count = 0;
03988 ListCell *l;
03989
03990 recomputeNamespacePath();
03991
03992 foreach(l, activeSearchPath)
03993 {
03994 Oid namespaceId = lfirst_oid(l);
03995
03996 if (namespaceId == myTempNamespace)
03997 continue;
03998
03999 if (count < sarray_len)
04000 sarray[count] = namespaceId;
04001 count++;
04002 }
04003
04004 return count;
04005 }
04006
04007
04008
04009
04010
04011
04012
04013
04014
04015
04016
04017
04018
04019
04020
04021 Datum
04022 pg_table_is_visible(PG_FUNCTION_ARGS)
04023 {
04024 Oid oid = PG_GETARG_OID(0);
04025
04026 if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(oid)))
04027 PG_RETURN_NULL();
04028
04029 PG_RETURN_BOOL(RelationIsVisible(oid));
04030 }
04031
04032 Datum
04033 pg_type_is_visible(PG_FUNCTION_ARGS)
04034 {
04035 Oid oid = PG_GETARG_OID(0);
04036
04037 if (!SearchSysCacheExists1(TYPEOID, ObjectIdGetDatum(oid)))
04038 PG_RETURN_NULL();
04039
04040 PG_RETURN_BOOL(TypeIsVisible(oid));
04041 }
04042
04043 Datum
04044 pg_function_is_visible(PG_FUNCTION_ARGS)
04045 {
04046 Oid oid = PG_GETARG_OID(0);
04047
04048 if (!SearchSysCacheExists1(PROCOID, ObjectIdGetDatum(oid)))
04049 PG_RETURN_NULL();
04050
04051 PG_RETURN_BOOL(FunctionIsVisible(oid));
04052 }
04053
04054 Datum
04055 pg_operator_is_visible(PG_FUNCTION_ARGS)
04056 {
04057 Oid oid = PG_GETARG_OID(0);
04058
04059 if (!SearchSysCacheExists1(OPEROID, ObjectIdGetDatum(oid)))
04060 PG_RETURN_NULL();
04061
04062 PG_RETURN_BOOL(OperatorIsVisible(oid));
04063 }
04064
04065 Datum
04066 pg_opclass_is_visible(PG_FUNCTION_ARGS)
04067 {
04068 Oid oid = PG_GETARG_OID(0);
04069
04070 if (!SearchSysCacheExists1(CLAOID, ObjectIdGetDatum(oid)))
04071 PG_RETURN_NULL();
04072
04073 PG_RETURN_BOOL(OpclassIsVisible(oid));
04074 }
04075
04076 Datum
04077 pg_opfamily_is_visible(PG_FUNCTION_ARGS)
04078 {
04079 Oid oid = PG_GETARG_OID(0);
04080
04081 if (!SearchSysCacheExists1(OPFAMILYOID, ObjectIdGetDatum(oid)))
04082 PG_RETURN_NULL();
04083
04084 PG_RETURN_BOOL(OpfamilyIsVisible(oid));
04085 }
04086
04087 Datum
04088 pg_collation_is_visible(PG_FUNCTION_ARGS)
04089 {
04090 Oid oid = PG_GETARG_OID(0);
04091
04092 if (!SearchSysCacheExists1(COLLOID, ObjectIdGetDatum(oid)))
04093 PG_RETURN_NULL();
04094
04095 PG_RETURN_BOOL(CollationIsVisible(oid));
04096 }
04097
04098 Datum
04099 pg_conversion_is_visible(PG_FUNCTION_ARGS)
04100 {
04101 Oid oid = PG_GETARG_OID(0);
04102
04103 if (!SearchSysCacheExists1(CONVOID, ObjectIdGetDatum(oid)))
04104 PG_RETURN_NULL();
04105
04106 PG_RETURN_BOOL(ConversionIsVisible(oid));
04107 }
04108
04109 Datum
04110 pg_ts_parser_is_visible(PG_FUNCTION_ARGS)
04111 {
04112 Oid oid = PG_GETARG_OID(0);
04113
04114 if (!SearchSysCacheExists1(TSPARSEROID, ObjectIdGetDatum(oid)))
04115 PG_RETURN_NULL();
04116
04117 PG_RETURN_BOOL(TSParserIsVisible(oid));
04118 }
04119
04120 Datum
04121 pg_ts_dict_is_visible(PG_FUNCTION_ARGS)
04122 {
04123 Oid oid = PG_GETARG_OID(0);
04124
04125 if (!SearchSysCacheExists1(TSDICTOID, ObjectIdGetDatum(oid)))
04126 PG_RETURN_NULL();
04127
04128 PG_RETURN_BOOL(TSDictionaryIsVisible(oid));
04129 }
04130
04131 Datum
04132 pg_ts_template_is_visible(PG_FUNCTION_ARGS)
04133 {
04134 Oid oid = PG_GETARG_OID(0);
04135
04136 if (!SearchSysCacheExists1(TSTEMPLATEOID, ObjectIdGetDatum(oid)))
04137 PG_RETURN_NULL();
04138
04139 PG_RETURN_BOOL(TSTemplateIsVisible(oid));
04140 }
04141
04142 Datum
04143 pg_ts_config_is_visible(PG_FUNCTION_ARGS)
04144 {
04145 Oid oid = PG_GETARG_OID(0);
04146
04147 if (!SearchSysCacheExists1(TSCONFIGOID, ObjectIdGetDatum(oid)))
04148 PG_RETURN_NULL();
04149
04150 PG_RETURN_BOOL(TSConfigIsVisible(oid));
04151 }
04152
04153 Datum
04154 pg_my_temp_schema(PG_FUNCTION_ARGS)
04155 {
04156 PG_RETURN_OID(myTempNamespace);
04157 }
04158
04159 Datum
04160 pg_is_other_temp_schema(PG_FUNCTION_ARGS)
04161 {
04162 Oid oid = PG_GETARG_OID(0);
04163
04164 PG_RETURN_BOOL(isOtherTempNamespace(oid));
04165 }