📄 namespace.c
字号:
if (procform->pronamespace != namespaceId) continue; /* No need to check args, they must all be different */ } else { /* Consider only procs that are in the search path */ List *nsp; foreach(nsp, namespaceSearchPath) { if (procform->pronamespace == lfirsto(nsp)) break; pathpos++; } if (nsp == NIL) continue; /* proc is not in search path */ /* * Okay, it's in the search path, but does it have the same * arguments as something we already accepted? If so, keep * only the one that appears earlier in the search path. * * If we have an ordered list from SearchSysCacheList (the normal * case), then any conflicting proc must immediately adjoin * this one in the list, so we only need to look at the newest * result item. If we have an unordered list, we have to scan * the whole result list. */ if (resultList) { FuncCandidateList prevResult; if (catlist->ordered) { if (nargs == resultList->nargs && memcmp(procform->proargtypes, resultList->args, nargs * sizeof(Oid)) == 0) prevResult = resultList; else prevResult = NULL; } else { for (prevResult = resultList; prevResult; prevResult = prevResult->next) { if (nargs == prevResult->nargs && memcmp(procform->proargtypes, prevResult->args, nargs * sizeof(Oid)) == 0) break; } } if (prevResult) { /* We have a match with a previous result */ Assert(pathpos != prevResult->pathpos); if (pathpos > prevResult->pathpos) continue; /* keep previous result */ /* replace previous result */ prevResult->pathpos = pathpos; prevResult->oid = HeapTupleGetOid(proctup); continue; /* args are same, of course */ } } } /* * Okay to add it to result list */ newResult = (FuncCandidateList) palloc(sizeof(struct _FuncCandidateList) - sizeof(Oid) + nargs * sizeof(Oid)); newResult->pathpos = pathpos; newResult->oid = HeapTupleGetOid(proctup); newResult->nargs = nargs; memcpy(newResult->args, procform->proargtypes, nargs * sizeof(Oid)); newResult->next = resultList; resultList = newResult; } ReleaseSysCacheList(catlist); return resultList;}/* * FunctionIsVisible * Determine whether a function (identified by OID) is visible in the * current search path. Visible means "would be found by searching * for the unqualified function name with exact argument matches". */boolFunctionIsVisible(Oid funcid){ HeapTuple proctup; Form_pg_proc procform; Oid pronamespace; bool visible; proctup = SearchSysCache(PROCOID, ObjectIdGetDatum(funcid), 0, 0, 0); if (!HeapTupleIsValid(proctup)) elog(ERROR, "cache lookup failed for function %u", funcid); procform = (Form_pg_proc) GETSTRUCT(proctup); recomputeNamespacePath(); /* * Quick check: if it ain't in the path at all, it ain't visible. * Items in the system namespace are surely in the path and so we * needn't even do oidMember() for them. */ pronamespace = procform->pronamespace; if (pronamespace != PG_CATALOG_NAMESPACE && !oidMember(pronamespace, namespaceSearchPath)) visible = false; else { /* * If it is in the path, it might still not be visible; it could * be hidden by another proc of the same name and arguments * earlier in the path. So we must do a slow check to see if this * is the same proc that would be found by FuncnameGetCandidates. */ char *proname = NameStr(procform->proname); int nargs = procform->pronargs; FuncCandidateList clist; visible = false; clist = FuncnameGetCandidates(makeList1(makeString(proname)), nargs); for (; clist; clist = clist->next) { if (memcmp(clist->args, procform->proargtypes, nargs * sizeof(Oid)) == 0) { /* Found the expected entry; is it the right proc? */ visible = (clist->oid == funcid); break; } } } ReleaseSysCache(proctup); return visible;}/* * OpernameGetCandidates * Given a possibly-qualified operator name and operator kind, * retrieve a list of the possible matches. * * If oprkind is '\0', we return all operators matching the given name, * regardless of arguments. * * We search a single namespace if the operator name is qualified, else * all namespaces in the search path. The return list will never contain * multiple entries with identical argument lists --- in the multiple- * namespace case, we arrange for entries in earlier namespaces to mask * identical entries in later namespaces. * * The returned items always have two args[] entries --- one or the other * will be InvalidOid for a prefix or postfix oprkind. nargs is 2, too. */FuncCandidateListOpernameGetCandidates(List *names, char oprkind){ FuncCandidateList resultList = NULL; char *schemaname; char *opername; Oid namespaceId; CatCList *catlist; int i; /* deconstruct the name list */ DeconstructQualifiedName(names, &schemaname, &opername); if (schemaname) { /* use exact schema given */ namespaceId = LookupExplicitNamespace(schemaname); } else { /* flag to indicate we need namespace search */ namespaceId = InvalidOid; recomputeNamespacePath(); } /* Search syscache by name only */ catlist = SearchSysCacheList(OPERNAMENSP, 1, CStringGetDatum(opername), 0, 0, 0); for (i = 0; i < catlist->n_members; i++) { HeapTuple opertup = &catlist->members[i]->tuple; Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup); int pathpos = 0; FuncCandidateList newResult; /* Ignore operators of wrong kind, if specific kind requested */ if (oprkind && operform->oprkind != oprkind) continue; if (OidIsValid(namespaceId)) { /* Consider only opers in specified namespace */ if (operform->oprnamespace != namespaceId) continue; /* No need to check args, they must all be different */ } else { /* Consider only opers that are in the search path */ List *nsp; foreach(nsp, namespaceSearchPath) { if (operform->oprnamespace == lfirsto(nsp)) break; pathpos++; } if (nsp == NIL) continue; /* oper is not in search path */ /* * Okay, it's in the search path, but does it have the same * arguments as something we already accepted? If so, keep * only the one that appears earlier in the search path. * * If we have an ordered list from SearchSysCacheList (the normal * case), then any conflicting oper must immediately adjoin * this one in the list, so we only need to look at the newest * result item. If we have an unordered list, we have to scan * the whole result list. */ if (resultList) { FuncCandidateList prevResult; if (catlist->ordered) { if (operform->oprleft == resultList->args[0] && operform->oprright == resultList->args[1]) prevResult = resultList; else prevResult = NULL; } else { for (prevResult = resultList; prevResult; prevResult = prevResult->next) { if (operform->oprleft == prevResult->args[0] && operform->oprright == prevResult->args[1]) break; } } if (prevResult) { /* We have a match with a previous result */ Assert(pathpos != prevResult->pathpos); if (pathpos > prevResult->pathpos) continue; /* keep previous result */ /* replace previous result */ prevResult->pathpos = pathpos; prevResult->oid = HeapTupleGetOid(opertup); continue; /* args are same, of course */ } } } /* * Okay to add it to result list */ newResult = (FuncCandidateList) palloc(sizeof(struct _FuncCandidateList) + sizeof(Oid)); newResult->pathpos = pathpos; newResult->oid = HeapTupleGetOid(opertup); newResult->nargs = 2; newResult->args[0] = operform->oprleft; newResult->args[1] = operform->oprright; newResult->next = resultList; resultList = newResult; } ReleaseSysCacheList(catlist); return resultList;}/* * OperatorIsVisible * Determine whether an operator (identified by OID) is visible in the * current search path. Visible means "would be found by searching * for the unqualified operator name with exact argument matches". */boolOperatorIsVisible(Oid oprid){ HeapTuple oprtup; Form_pg_operator oprform; Oid oprnamespace; bool visible; oprtup = SearchSysCache(OPEROID, ObjectIdGetDatum(oprid), 0, 0, 0); if (!HeapTupleIsValid(oprtup)) elog(ERROR, "cache lookup failed for operator %u", oprid); oprform = (Form_pg_operator) GETSTRUCT(oprtup); recomputeNamespacePath(); /* * Quick check: if it ain't in the path at all, it ain't visible. * Items in the system namespace are surely in the path and so we * needn't even do oidMember() for them. */ oprnamespace = oprform->oprnamespace; if (oprnamespace != PG_CATALOG_NAMESPACE && !oidMember(oprnamespace, namespaceSearchPath)) visible = false; else { /* * If it is in the path, it might still not be visible; it could * be hidden by another operator of the same name and arguments * earlier in the path. So we must do a slow check to see if this * is the same operator that would be found by * OpernameGetCandidates. */ char *oprname = NameStr(oprform->oprname); FuncCandidateList clist; visible = false; clist = OpernameGetCandidates(makeList1(makeString(oprname)), oprform->oprkind); for (; clist; clist = clist->next) { if (clist->args[0] == oprform->oprleft && clist->args[1] == oprform->oprright) { /* Found the expected entry; is it the right op? */ visible = (clist->oid == oprid); break; } } } ReleaseSysCache(oprtup); return visible;}/* * OpclassGetCandidates * Given an index access method OID, retrieve a list of all the * opclasses for that AM that are visible in the search path. * * NOTE: the opcname_tmp field in the returned structs should not be used * by callers, because it points at syscache entries that we release at * the end of this routine. If any callers needed the name information, * we could pstrdup() the names ... but at present it'd be wasteful. */OpclassCandidateListOpclassGetCandidates(Oid amid){ OpclassCandidateList resultList = NULL; CatCList *catlist; int i; /* Search syscache by AM OID only */ catlist = SearchSysCacheList(CLAAMNAMENSP, 1, ObjectIdGetDatum(amid), 0, 0, 0); recomputeNamespacePath(); for (i = 0; i < catlist->n_members; i++) { HeapTuple opctup = &catlist->members[i]->tuple; Form_pg_opclass opcform = (Form_pg_opclass) GETSTRUCT(opctup); int pathpos = 0; OpclassCandidateList newResult; List *nsp; /* Consider only opclasses that are in the search path */ foreach(nsp, namespaceSearchPath) { if (opcform->opcnamespace == lfirsto(nsp)) break; pathpos++; } if (nsp == NIL) continue; /* opclass is not in search path */ /* * Okay, it's in the search path, but does it have the same name * as something we already accepted? If so, keep only the one * that appears earlier in the search path. * * If we have an ordered list from SearchSysCacheList (the normal * case), then any conflicting opclass must immediately adjoin * this one in the list, so we only need to look at the newest * result item. If we have an unordered list, we have to scan the * whole result list. */ if (resultList) { OpclassCandidateList prevResult; if (catlist->ordered) { if (strcmp(NameStr(opcform->opcname), resultList->opcname_tmp) == 0) prevResult = resultList; else prevResult = NULL; } else { for (prevResult = resultList; prevResult; prevResult = prevResult->next) { if (strcmp(NameStr(opcform->opcname), prevResult->opcname_tmp) == 0) break; } } if (prevResult) { /* We have a match with a previous result */ Assert(pathpos != prevResult->pathpos); if (pathpos > prevResult->pathpos) continue; /* keep previous result */ /* replace previous result */ prevResult->opcname_tmp = NameStr(opcform->opcname); prevResult->pathpos = pathpos; prevResult->oid = HeapTupleGetOid(opctup); prevResult->opcintype = opcform->opcintype; prevResult->opcdefault = opcform->opcdefault; prevResult->opckeytype = opcform->opckeytype; continue; } } /* * Okay to add it to result list */ newResult = (OpclassCandidateList) palloc(sizeof(struct _OpclassCandidateList)); newResult->opcname_tmp = NameStr(opcform->opcname); newResult->pathpos = pathpos; newResult->oid = HeapTupleGetOid(opctup); newResult->opcintype = opcform->opcintype; newResult->opcdefault = opcform->opcdefault; newResult->opckeytype = opcform->opckeytype; newResult->next = resultList; resultList = newResult; } ReleaseSysCacheList(catlist); return resultList;}/* * OpclassnameGetOpcid * Try to resolve an unqualified index opclass name. * Returns OID if opclass found in search path, else InvalidOid. * * This is essentially the same as TypenameGetTypid, but we have to have
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -