提交 36f887c4 编写于 作者: P Peter Eisentraut

Speed up information schema privilege views

Instead of expensive cross joins to resolve the ACL, add table-returning
function aclexplode() that expands the ACL into a useful form, and join
against that.

Also, implement the role_*_grants views as a thin layer over the respective
*_privileges views instead of essentially repeating the same code twice.

fixes bug #4596

by Joachim Wieland, with cleanup by me
上级 636bac6e
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.150 2009/10/05 19:24:41 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.151 2009/12/05 21:43:35 petere Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -24,6 +24,7 @@
#include "commands/dbcommands.h"
#include "commands/tablespace.h"
#include "foreign/foreign.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "utils/acl.h"
#include "utils/builtins.h"
......@@ -1622,6 +1623,143 @@ convert_any_priv_string(text *priv_type_text,
}
static const char *
convert_aclright_to_string(int aclright)
{
switch (aclright)
{
case ACL_INSERT:
return "INSERT";
case ACL_SELECT:
return "SELECT";
case ACL_UPDATE:
return "UPDATE";
case ACL_DELETE:
return "DELETE";
case ACL_TRUNCATE:
return "TRUNCATE";
case ACL_REFERENCES:
return "REFERENCES";
case ACL_TRIGGER:
return "TRIGGER";
case ACL_EXECUTE:
return "EXECUTE";
case ACL_USAGE:
return "USAGE";
case ACL_CREATE:
return "CREATE";
case ACL_CREATE_TEMP:
return "TEMPORARY";
case ACL_CONNECT:
return "CONNECT";
default:
elog(ERROR, "unrecognized aclright: %d", aclright);
return NULL;
}
}
/*----------
* Convert an aclitem[] to a table.
*
* Example:
*
* aclexplode('{=r/joe,foo=a*w/joe}'::aclitem[])
*
* returns the table
*
* {{ OID(joe), 0::OID, 'SELECT', false },
* { OID(joe), OID(foo), 'INSERT', true },
* { OID(joe), OID(foo), 'UPDATE', false }}
*----------
*/
Datum
aclexplode(PG_FUNCTION_ARGS)
{
FuncCallContext *funcctx;
int *idx;
Acl *acl = PG_GETARG_ACL_P(0);
AclItem *aidat;
if (SRF_IS_FIRSTCALL())
{
TupleDesc tupdesc;
MemoryContext oldcontext;
check_acl(acl);
funcctx = SRF_FIRSTCALL_INIT();
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
/*
* build tupdesc for result tuples (matches out parameters in
* pg_proc entry)
*/
tupdesc = CreateTemplateTupleDesc(4, false);
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "grantor",
OIDOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 2, "grantee",
OIDOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 3, "privilege_type",
TEXTOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 4, "is_grantable",
BOOLOID, -1, 0);
funcctx->tuple_desc = BlessTupleDesc(tupdesc);
/* allocate memory for user context */
idx = (int *) palloc(sizeof(int[2]));
idx[0] = 0; /* ACL array item index */
idx[1] = -1; /* privilege type counter */
funcctx->user_fctx = (void *) idx;
MemoryContextSwitchTo(oldcontext);
}
funcctx = SRF_PERCALL_SETUP();
idx = (int *) funcctx->user_fctx;
aidat = ACL_DAT(acl);
while (1)
{
idx[1]++;
if (idx[1] == N_ACL_RIGHTS)
{
idx[1] = 0;
idx[0]++;
if (idx[0] == ACL_NUM(acl))
/* done */
break;
}
Assert(idx[0] < ACL_NUM(acl));
Assert(idx[1] < N_ACL_RIGHTS);
if (ACLITEM_GET_PRIVS(aidat[idx[0]]) & (1 << idx[1]))
{
Datum result;
Datum values[4];
bool nulls[4];
HeapTuple tuple;
values[0] = ObjectIdGetDatum(aidat[idx[0]].ai_grantor);
values[1] = ObjectIdGetDatum(aidat[idx[0]].ai_grantee);
values[2] = CStringGetTextDatum(convert_aclright_to_string(1 << idx[1]));
values[3] = BoolGetDatum(ACLITEM_GET_GOPTIONS(aidat[idx[0]]) & (1 << idx[1]));
MemSet(nulls, 0, sizeof(nulls));
tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
result = HeapTupleGetDatum(tuple);
SRF_RETURN_NEXT(funcctx, result);
}
}
SRF_RETURN_DONE(funcctx);
}
/*
* has_table_privilege variants
* These are all named "has_table_privilege" at the SQL level.
......
......@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.554 2009/11/29 18:14:30 tgl Exp $
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.555 2009/12/05 21:43:35 petere Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 200911291
#define CATALOG_VERSION_NO 200912051
#endif
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.554 2009/11/29 18:14:30 tgl Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.555 2009/12/05 21:43:35 petere Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
......@@ -1314,6 +1314,8 @@ DATA(insert OID = 1062 ( aclitemeq PGNSP PGUID 12 1 0 0 f f f t f i 2 0 16
DESCR("equality operator for ACL items");
DATA(insert OID = 1365 ( makeaclitem PGNSP PGUID 12 1 0 0 f f f t f i 4 0 1033 "26 26 25 16" _null_ _null_ _null_ _null_ makeaclitem _null_ _null_ _null_ ));
DESCR("make ACL item");
DATA(insert OID = 1248 ( aclexplode PGNSP PGUID 12 1 10 0 f f f t t s 1 0 2249 "1034" "{1034,26,26,25,16}" "{i,o,o,o,o}" "{acl,grantor,grantee,privilege_type,is_grantable}" _null_ aclexplode _null_ _null_ _null_ ));
DESCR("convert ACL item array to table, for use by information schema");
DATA(insert OID = 1044 ( bpcharin PGNSP PGUID 12 1 0 0 f f f t f i 3 0 1042 "2275 26 23" _null_ _null_ _null_ _null_ bpcharin _null_ _null_ _null_ ));
DESCR("I/O");
DATA(insert OID = 1045 ( bpcharout PGNSP PGUID 12 1 0 0 f f f t f i 1 0 2275 "1042" _null_ _null_ _null_ _null_ bpcharout _null_ _null_ _null_ ));
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.109 2009/10/05 19:24:49 tgl Exp $
* $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.110 2009/12/05 21:43:36 petere Exp $
*
* NOTES
* An ACL array is simply an array of AclItems, representing the union
......@@ -238,6 +238,7 @@ extern Datum aclcontains(PG_FUNCTION_ARGS);
extern Datum makeaclitem(PG_FUNCTION_ARGS);
extern Datum aclitem_eq(PG_FUNCTION_ARGS);
extern Datum hash_aclitem(PG_FUNCTION_ARGS);
extern Datum aclexplode(PG_FUNCTION_ARGS);
/*
* prototypes for functions in aclchk.c
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册