Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Greenplum
Gpdb
提交
ccfaf906
G
Gpdb
项目概览
Greenplum
/
Gpdb
通知
7
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
Gpdb
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
ccfaf906
编写于
4月 29, 2002
作者:
T
Tom Lane
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Implement checking of USAGE rights on namespaces.
上级
88ef7067
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
197 addition
and
107 deletion
+197
-107
src/backend/catalog/namespace.c
src/backend/catalog/namespace.c
+197
-107
未找到文件。
src/backend/catalog/namespace.c
浏览文件 @
ccfaf906
...
...
@@ -13,7 +13,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.1
4 2002/04/27 03:45:00
tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.1
5 2002/04/29 22:15:07
tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -37,9 +37,10 @@
#include "storage/backendid.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/catcache.h"
#include "utils/fmgroids.h"
#include "utils/guc.h"
#include "utils/
catcache
.h"
#include "utils/
inval
.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
...
...
@@ -66,10 +67,25 @@
* path is determined by GUC. The factory default path contains the PUBLIC
* namespace (if it exists), preceded by the user's personal namespace
* (if one exists).
*
* If namespaceSearchPathValid is false, then namespaceSearchPath (and the
* derived variables) need to be recomputed from namespace_search_path.
* We mark it invalid upon an assignment to namespace_search_path or receipt
* of a syscache invalidation event for pg_namespace. The recomputation
* is done during the next lookup attempt.
*
* Any namespaces mentioned in namespace_search_path that are not readable
* by the current user ID are simply left out of namespaceSearchPath; so
* we have to be willing to recompute the path when current userid changes.
* namespaceUser is the userid the path has been computed for.
*/
static
List
*
namespaceSearchPath
=
NIL
;
static
bool
namespaceSearchPathValid
=
true
;
static
Oid
namespaceUser
=
InvalidOid
;
/* this flag must be updated correctly when namespaceSearchPath is changed */
static
bool
pathContainsSystemNamespace
=
false
;
...
...
@@ -103,12 +119,14 @@ typedef struct DelConstraint
/* Local functions */
static
void
recomputeNamespacePath
(
void
);
static
Oid
GetTempTableNamespace
(
void
);
static
void
RemoveTempRelations
(
Oid
tempNamespaceId
);
static
List
*
FindTempRelations
(
Oid
tempNamespaceId
);
static
List
*
FindDeletionConstraints
(
List
*
relOids
);
static
List
*
TopoSortRels
(
List
*
relOids
,
List
*
constraintList
);
static
void
RemoveTempRelationsCallback
(
void
);
static
void
NamespaceCallback
(
Datum
arg
,
Oid
relid
);
/*
...
...
@@ -137,12 +155,18 @@ RangeVarGetRelid(const RangeVar *relation, bool failOK)
if
(
relation
->
schemaname
)
{
/* use exact schema given */
AclResult
aclresult
;
namespaceId
=
GetSysCacheOid
(
NAMESPACENAME
,
CStringGetDatum
(
relation
->
schemaname
),
0
,
0
,
0
);
if
(
!
OidIsValid
(
namespaceId
))
elog
(
ERROR
,
"Namespace
\"
%s
\"
does not exist"
,
relation
->
schemaname
);
aclresult
=
pg_namespace_aclcheck
(
namespaceId
,
GetUserId
(),
ACL_USAGE
);
if
(
aclresult
!=
ACLCHECK_OK
)
aclcheck_error
(
aclresult
,
relation
->
schemaname
);
relId
=
get_relname_relid
(
relation
->
relname
,
namespaceId
);
}
else
...
...
@@ -210,11 +234,14 @@ RangeVarGetCreationNamespace(const RangeVar *newRelation)
else
{
/* use the default creation namespace */
recomputeNamespacePath
();
namespaceId
=
defaultCreationNamespace
;
if
(
!
OidIsValid
(
namespaceId
))
elog
(
ERROR
,
"No namespace has been selected to create in"
);
}
/* Note: callers will check for CREATE rights when appropriate */
return
namespaceId
;
}
...
...
@@ -229,9 +256,11 @@ RelnameGetRelid(const char *relname)
Oid
relid
;
List
*
lptr
;
recomputeNamespacePath
();
/*
* If a TEMP-table namespace has been set up, it is implicitly first
* in the search path.
* in the search path.
We do not need to check USAGE permission.
*/
if
(
OidIsValid
(
myTempNamespace
))
{
...
...
@@ -241,7 +270,8 @@ RelnameGetRelid(const char *relname)
}
/*
* If system namespace is not in path, implicitly search it before path
* If system namespace is not in path, implicitly search it before path.
* We do not check USAGE permission.
*/
if
(
!
pathContainsSystemNamespace
)
{
...
...
@@ -281,6 +311,8 @@ TypenameGetTypid(const char *typname)
Oid
typid
;
List
*
lptr
;
recomputeNamespacePath
();
/*
* If system namespace is not in path, implicitly search it before path
*/
...
...
@@ -327,6 +359,8 @@ OpclassnameGetOpcid(Oid amid, const char *opcname)
Oid
opcid
;
List
*
lptr
;
recomputeNamespacePath
();
/*
* If system namespace is not in path, implicitly search it before path
*/
...
...
@@ -414,17 +448,23 @@ FuncnameGetCandidates(List *names, int nargs)
if
(
schemaname
)
{
/* use exact schema given */
AclResult
aclresult
;
namespaceId
=
GetSysCacheOid
(
NAMESPACENAME
,
CStringGetDatum
(
schemaname
),
0
,
0
,
0
);
if
(
!
OidIsValid
(
namespaceId
))
elog
(
ERROR
,
"Namespace
\"
%s
\"
does not exist"
,
schemaname
);
aclresult
=
pg_namespace_aclcheck
(
namespaceId
,
GetUserId
(),
ACL_USAGE
);
if
(
aclresult
!=
ACLCHECK_OK
)
aclcheck_error
(
aclresult
,
schemaname
);
}
else
{
/* flag to indicate we need namespace search */
namespaceId
=
InvalidOid
;
recomputeNamespacePath
();
}
/* Search syscache by name and (optionally) nargs only */
...
...
@@ -598,17 +638,23 @@ OpernameGetCandidates(List *names, char oprkind)
if
(
schemaname
)
{
/* use exact schema given */
AclResult
aclresult
;
namespaceId
=
GetSysCacheOid
(
NAMESPACENAME
,
CStringGetDatum
(
schemaname
),
0
,
0
,
0
);
if
(
!
OidIsValid
(
namespaceId
))
elog
(
ERROR
,
"Namespace
\"
%s
\"
does not exist"
,
schemaname
);
aclresult
=
pg_namespace_aclcheck
(
namespaceId
,
GetUserId
(),
ACL_USAGE
);
if
(
aclresult
!=
ACLCHECK_OK
)
aclcheck_error
(
aclresult
,
schemaname
);
}
else
{
/* flag to indicate we need namespace search */
namespaceId
=
InvalidOid
;
recomputeNamespacePath
();
}
/* Search syscache by name only */
...
...
@@ -736,6 +782,8 @@ OpclassGetCandidates(Oid amid)
CatCList
*
catlist
;
int
i
;
recomputeNamespacePath
();
/* Search syscache by AM OID only */
catlist
=
SearchSysCacheList
(
CLAAMNAMENSP
,
1
,
ObjectIdGetDatum
(
amid
),
...
...
@@ -891,11 +939,14 @@ QualifiedNameGetCreationNamespace(List *names, char **objname_p)
else
{
/* use the default creation namespace */
recomputeNamespacePath
();
namespaceId
=
defaultCreationNamespace
;
if
(
!
OidIsValid
(
namespaceId
))
elog
(
ERROR
,
"No namespace has been selected to create in"
);
}
/* Note: callers will check for CREATE rights when appropriate */
*
objname_p
=
objname
;
return
namespaceId
;
}
...
...
@@ -965,6 +1016,118 @@ isTempNamespace(Oid namespaceId)
return
false
;
}
/*
* recomputeNamespacePath - recompute path derived variables if needed.
*/
static
void
recomputeNamespacePath
(
void
)
{
Oid
userId
=
GetUserId
();
char
*
rawname
;
List
*
namelist
;
List
*
oidlist
;
List
*
newpath
;
List
*
l
;
MemoryContext
oldcxt
;
/*
* Do nothing if path is already valid.
*/
if
(
namespaceSearchPathValid
&&
namespaceUser
==
userId
)
return
;
/* Need a modifiable copy of namespace_search_path string */
rawname
=
pstrdup
(
namespace_search_path
);
/* Parse string into list of identifiers */
if
(
!
SplitIdentifierString
(
rawname
,
','
,
&
namelist
))
{
/* syntax error in name list */
/* this should not happen if GUC checked check_search_path */
elog
(
ERROR
,
"recomputeNamespacePath: invalid list syntax"
);
}
/*
* Convert the list of names to a list of OIDs. If any names are not
* recognizable or we don't have read access, just leave them out of
* the list. (We can't raise an error, since the search_path setting
* has already been accepted.)
*/
oidlist
=
NIL
;
foreach
(
l
,
namelist
)
{
char
*
curname
=
(
char
*
)
lfirst
(
l
);
Oid
namespaceId
;
if
(
strcmp
(
curname
,
"$user"
)
==
0
)
{
/* $user --- substitute namespace matching user name, if any */
HeapTuple
tuple
;
tuple
=
SearchSysCache
(
SHADOWSYSID
,
ObjectIdGetDatum
(
userId
),
0
,
0
,
0
);
if
(
HeapTupleIsValid
(
tuple
))
{
char
*
uname
;
uname
=
NameStr
(((
Form_pg_shadow
)
GETSTRUCT
(
tuple
))
->
usename
);
namespaceId
=
GetSysCacheOid
(
NAMESPACENAME
,
CStringGetDatum
(
uname
),
0
,
0
,
0
);
ReleaseSysCache
(
tuple
);
if
(
OidIsValid
(
namespaceId
)
&&
pg_namespace_aclcheck
(
namespaceId
,
userId
,
ACL_USAGE
)
==
ACLCHECK_OK
)
oidlist
=
lappendi
(
oidlist
,
namespaceId
);
}
}
else
{
/* normal namespace reference */
namespaceId
=
GetSysCacheOid
(
NAMESPACENAME
,
CStringGetDatum
(
curname
),
0
,
0
,
0
);
if
(
OidIsValid
(
namespaceId
)
&&
pg_namespace_aclcheck
(
namespaceId
,
userId
,
ACL_USAGE
)
==
ACLCHECK_OK
)
oidlist
=
lappendi
(
oidlist
,
namespaceId
);
}
}
/*
* Now that we've successfully built the new list of namespace OIDs,
* save it in permanent storage.
*/
oldcxt
=
MemoryContextSwitchTo
(
TopMemoryContext
);
newpath
=
listCopy
(
oidlist
);
MemoryContextSwitchTo
(
oldcxt
);
/* Now safe to assign to state variable. */
freeList
(
namespaceSearchPath
);
namespaceSearchPath
=
newpath
;
/*
* Update info derived from search path.
*/
pathContainsSystemNamespace
=
intMember
(
PG_CATALOG_NAMESPACE
,
namespaceSearchPath
);
if
(
namespaceSearchPath
==
NIL
)
defaultCreationNamespace
=
InvalidOid
;
else
defaultCreationNamespace
=
(
Oid
)
lfirsti
(
namespaceSearchPath
);
/* Mark the path valid. */
namespaceSearchPathValid
=
true
;
namespaceUser
=
userId
;
/* Clean up. */
pfree
(
rawname
);
freeList
(
namelist
);
freeList
(
oidlist
);
}
/*
* GetTempTableNamespace
* Initialize temp table namespace on first use in a particular backend
...
...
@@ -979,8 +1142,12 @@ GetTempTableNamespace(void)
* First, do permission check to see if we are authorized to make
* temp tables. We use a nonstandard error message here since
* "databasename: permission denied" might be a tad cryptic.
*
* Note we apply the check to the session user, not the currently
* active userid, since we are not going to change our minds about
* temp table availability during the session.
*/
if
(
pg_database_aclcheck
(
MyDatabaseId
,
GetUserId
(),
if
(
pg_database_aclcheck
(
MyDatabaseId
,
Get
Session
UserId
(),
ACL_CREATE_TEMP
)
!=
ACLCHECK_OK
)
elog
(
ERROR
,
"%s: not authorized to create temp tables"
,
DatabaseName
);
...
...
@@ -1320,7 +1487,8 @@ check_search_path(const char *proposed)
/*
* Verify that all the names are either valid namespace names or "$user".
* (We do not require $user to correspond to a valid namespace; should we?)
* We do not require $user to correspond to a valid namespace.
* We do not check for USAGE rights, either; should we?
*/
foreach
(
l
,
namelist
)
{
...
...
@@ -1348,104 +1516,12 @@ check_search_path(const char *proposed)
void
assign_search_path
(
const
char
*
newval
)
{
char
*
rawname
;
List
*
namelist
;
List
*
oidlist
;
List
*
newpath
;
List
*
l
;
MemoryContext
oldcxt
;
/*
* If we aren't inside a transaction, we cannot do database access so
* cannot look up the names. In this case, do nothing; the internal
* search path will be fixed later by InitializeSearchPath. (We assume
* this situation can only happen in the postmaster or early in backend
* startup.)
*/
if
(
!
IsTransactionState
())
return
;
/* Need a modifiable copy of string */
rawname
=
pstrdup
(
newval
);
/* Parse string into list of identifiers */
if
(
!
SplitIdentifierString
(
rawname
,
','
,
&
namelist
))
{
/* syntax error in name list */
/* this should not happen if GUC checked check_search_path */
elog
(
ERROR
,
"assign_search_path: invalid list syntax"
);
}
/*
*
Convert the list of names to a list of OIDs. If any names are not
*
recognizable, just leave them out of the list. (This is our only
*
reasonable recourse when the already-accepted default is bogus.)
*
We mark the path as needing recomputation, but don't do anything until
*
it's needed. This avoids trying to do database access during GUC
*
initialization.
*/
oidlist
=
NIL
;
foreach
(
l
,
namelist
)
{
char
*
curname
=
(
char
*
)
lfirst
(
l
);
Oid
namespaceId
;
if
(
strcmp
(
curname
,
"$user"
)
==
0
)
{
/* $user --- substitute namespace matching user name, if any */
HeapTuple
tuple
;
tuple
=
SearchSysCache
(
SHADOWSYSID
,
ObjectIdGetDatum
(
GetSessionUserId
()),
0
,
0
,
0
);
if
(
HeapTupleIsValid
(
tuple
))
{
char
*
uname
;
uname
=
NameStr
(((
Form_pg_shadow
)
GETSTRUCT
(
tuple
))
->
usename
);
namespaceId
=
GetSysCacheOid
(
NAMESPACENAME
,
CStringGetDatum
(
uname
),
0
,
0
,
0
);
if
(
OidIsValid
(
namespaceId
))
oidlist
=
lappendi
(
oidlist
,
namespaceId
);
ReleaseSysCache
(
tuple
);
}
}
else
{
/* normal namespace reference */
namespaceId
=
GetSysCacheOid
(
NAMESPACENAME
,
CStringGetDatum
(
curname
),
0
,
0
,
0
);
if
(
OidIsValid
(
namespaceId
))
oidlist
=
lappendi
(
oidlist
,
namespaceId
);
}
}
/*
* Now that we've successfully built the new list of namespace OIDs,
* save it in permanent storage.
*/
oldcxt
=
MemoryContextSwitchTo
(
TopMemoryContext
);
newpath
=
listCopy
(
oidlist
);
MemoryContextSwitchTo
(
oldcxt
);
/* Now safe to assign to state variable. */
freeList
(
namespaceSearchPath
);
namespaceSearchPath
=
newpath
;
/*
* Update info derived from search path.
*/
pathContainsSystemNamespace
=
intMember
(
PG_CATALOG_NAMESPACE
,
namespaceSearchPath
);
if
(
namespaceSearchPath
==
NIL
)
defaultCreationNamespace
=
InvalidOid
;
else
defaultCreationNamespace
=
(
Oid
)
lfirsti
(
namespaceSearchPath
);
/* Clean up. */
pfree
(
rawname
);
freeList
(
namelist
);
freeList
(
oidlist
);
namespaceSearchPathValid
=
false
;
}
/*
...
...
@@ -1469,19 +1545,32 @@ InitializeSearchPath(void)
MemoryContextSwitchTo
(
oldcxt
);
pathContainsSystemNamespace
=
true
;
defaultCreationNamespace
=
PG_CATALOG_NAMESPACE
;
namespaceSearchPathValid
=
true
;
namespaceUser
=
GetUserId
();
}
else
{
/*
* I
f a search path setting was provided before we were able to
*
execute lookups, establish the internal search path now
.
* I
n normal mode, arrange for a callback on any syscache invalidation
*
of pg_namespace rows
.
*/
if
(
namespace_search_path
&&
*
namespace_search_path
&&
namespaceSearchPath
==
NIL
)
assign_search_path
(
namespace_search_path
);
CacheRegisterSyscacheCallback
(
NAMESPACEOID
,
NamespaceCallback
,
(
Datum
)
0
);
}
}
/*
* NamespaceCallback
* Syscache inval callback function
*/
static
void
NamespaceCallback
(
Datum
arg
,
Oid
relid
)
{
/* Force search path to be recomputed on next use */
namespaceSearchPathValid
=
false
;
}
/*
* Fetch the active search path, expressed as a List of OIDs.
*
...
...
@@ -1490,5 +1579,6 @@ InitializeSearchPath(void)
List
*
fetch_search_path
(
void
)
{
recomputeNamespacePath
();
return
namespaceSearchPath
;
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录