greenplumn pg_db_role_setting 源码
greenplumn pg_db_role_setting 代码
文件路径:/src/backend/catalog/pg_db_role_setting.c
/*
* pg_db_role_setting.c
* Routines to support manipulation of the pg_db_role_setting relation
*
* Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* src/backend/catalog/pg_db_role_setting.c
*/
#include "postgres.h"
#include "access/genam.h"
#include "access/heapam.h"
#include "access/htup_details.h"
#include "access/tableam.h"
#include "catalog/indexing.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_db_role_setting.h"
#include "utils/fmgroids.h"
#include "utils/rel.h"
#include "catalog/heap.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_database.h"
#include "cdb/cdbdisp_query.h"
#include "cdb/cdbvars.h"
#include "utils/builtins.h"
#include "utils/syscache.h"
void
AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt)
{
char *valuestr;
HeapTuple tuple;
Relation rel;
ScanKeyData scankey[2];
SysScanDesc scan;
valuestr = ExtractSetVariableArgs(setstmt);
/* Get the old tuple, if any. */
rel = table_open(DbRoleSettingRelationId, RowExclusiveLock);
ScanKeyInit(&scankey[0],
Anum_pg_db_role_setting_setdatabase,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(databaseid));
ScanKeyInit(&scankey[1],
Anum_pg_db_role_setting_setrole,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(roleid));
scan = systable_beginscan(rel, DbRoleSettingDatidRolidIndexId, true,
NULL, 2, scankey);
tuple = systable_getnext(scan);
/*
* There are three cases:
*
* - in RESET ALL, request GUC to reset the settings array and update the
* catalog if there's anything left, delete it otherwise
*
* - in other commands, if there's a tuple in pg_db_role_setting, update
* it; if it ends up empty, delete it
*
* - otherwise, insert a new pg_db_role_setting tuple, but only if the
* command is not RESET
*/
if (setstmt->kind == VAR_RESET_ALL)
{
if (HeapTupleIsValid(tuple))
{
ArrayType *new = NULL;
Datum datum;
bool isnull;
datum = heap_getattr(tuple, Anum_pg_db_role_setting_setconfig,
RelationGetDescr(rel), &isnull);
if (!isnull)
new = GUCArrayReset(DatumGetArrayTypeP(datum));
if (new)
{
Datum repl_val[Natts_pg_db_role_setting];
bool repl_null[Natts_pg_db_role_setting];
bool repl_repl[Natts_pg_db_role_setting];
HeapTuple newtuple;
memset(repl_repl, false, sizeof(repl_repl));
repl_val[Anum_pg_db_role_setting_setconfig - 1] =
PointerGetDatum(new);
repl_repl[Anum_pg_db_role_setting_setconfig - 1] = true;
repl_null[Anum_pg_db_role_setting_setconfig - 1] = false;
newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel),
repl_val, repl_null, repl_repl);
CatalogTupleUpdate(rel, &tuple->t_self, newtuple);
}
else
CatalogTupleDelete(rel, &tuple->t_self);
}
}
else if (HeapTupleIsValid(tuple))
{
Datum repl_val[Natts_pg_db_role_setting];
bool repl_null[Natts_pg_db_role_setting];
bool repl_repl[Natts_pg_db_role_setting];
HeapTuple newtuple;
Datum datum;
bool isnull;
ArrayType *a;
memset(repl_repl, false, sizeof(repl_repl));
repl_repl[Anum_pg_db_role_setting_setconfig - 1] = true;
repl_null[Anum_pg_db_role_setting_setconfig - 1] = false;
/* Extract old value of setconfig */
datum = heap_getattr(tuple, Anum_pg_db_role_setting_setconfig,
RelationGetDescr(rel), &isnull);
a = isnull ? NULL : DatumGetArrayTypeP(datum);
/* Update (valuestr is NULL in RESET cases) */
if (valuestr)
a = GUCArrayAdd(a, setstmt->name, valuestr);
else
a = GUCArrayDelete(a, setstmt->name);
if (a)
{
repl_val[Anum_pg_db_role_setting_setconfig - 1] =
PointerGetDatum(a);
newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel),
repl_val, repl_null, repl_repl);
CatalogTupleUpdate(rel, &tuple->t_self, newtuple);
}
else
CatalogTupleDelete(rel, &tuple->t_self);
}
else if (valuestr)
{
/* non-null valuestr means it's not RESET, so insert a new tuple */
HeapTuple newtuple;
Datum values[Natts_pg_db_role_setting];
bool nulls[Natts_pg_db_role_setting];
ArrayType *a;
memset(nulls, false, sizeof(nulls));
a = GUCArrayAdd(NULL, setstmt->name, valuestr);
values[Anum_pg_db_role_setting_setdatabase - 1] =
ObjectIdGetDatum(databaseid);
values[Anum_pg_db_role_setting_setrole - 1] = ObjectIdGetDatum(roleid);
values[Anum_pg_db_role_setting_setconfig - 1] = PointerGetDatum(a);
newtuple = heap_form_tuple(RelationGetDescr(rel), values, nulls);
CatalogTupleInsert(rel, newtuple);
}
InvokeObjectPostAlterHookArg(DbRoleSettingRelationId,
databaseid, 0, roleid, false);
systable_endscan(scan);
/* update pg_stat_last_shoperation for metadata tracking */
if (Gp_role == GP_ROLE_DISPATCH)
{
char *alter_subtype;
if (setstmt->kind == VAR_RESET_ALL)
alter_subtype = "RESET ALL";
else if (setstmt->kind == VAR_RESET)
alter_subtype = "RESET";
else
alter_subtype = "SET";
/* roleoid is only valid for ALTER ROLE */
MetaTrackUpdObject(DatabaseRelationId,
OidIsValid(roleid) ? roleid : databaseid,
GetUserId(),
"ALTER", alter_subtype);
}
if (Gp_role == GP_ROLE_DISPATCH)
{
StringInfoData buffer;
char *rolename;
char *dbname;
HeapTuple htup;
if (roleid)
{
htup = SearchSysCache1(AUTHOID, roleid);
if (!HeapTupleIsValid(htup))
elog(ERROR, "cache lookup failed for role %u", roleid);
rolename = pstrdup(NameStr(((Form_pg_authid) GETSTRUCT(htup))->rolname));
ReleaseSysCache(htup);
}
else
rolename = NULL;
if (databaseid)
{
htup = SearchSysCache1(DATABASEOID, databaseid);
if (!htup)
elog(ERROR, "cache lookup failed for database %u", databaseid);
dbname = pstrdup(NameStr(((Form_pg_database) GETSTRUCT(htup))->datname));
ReleaseSysCache(htup);
}
else
dbname = NULL;
initStringInfo(&buffer);
if (databaseid && roleid)
appendStringInfo(&buffer, "ALTER ROLE %s IN DATABASE %s ",
quote_identifier(rolename), quote_identifier(dbname));
else if (roleid)
appendStringInfo(&buffer, "ALTER ROLE %s ",
quote_identifier(rolename));
else if (databaseid)
appendStringInfo(&buffer, "ALTER DATABASE %s ",
quote_identifier(dbname));
else
appendStringInfo(&buffer, "ALTER ROLE ALL ");
if (setstmt->kind == VAR_RESET_ALL)
appendStringInfo(&buffer, "RESET ALL");
else if (valuestr == NULL)
appendStringInfo(&buffer, "RESET %s", quote_identifier(setstmt->name));
else if (setstmt->kind == VAR_SET_CURRENT)
appendStringInfo(&buffer, "SET %s TO %s", quote_identifier(setstmt->name), quote_literal_cstr(valuestr));
else
{
ListCell *l;
bool first;
appendStringInfo(&buffer, "SET %s TO ", quote_identifier(setstmt->name));
/* Parse string into list of identifiers */
first = true;
foreach(l, setstmt->args)
{
A_Const *arg = (A_Const *) lfirst(l);
if (!first)
appendStringInfo(&buffer, ",");
first = false;
switch (nodeTag(&arg->val))
{
case T_Integer:
appendStringInfo(&buffer, "%d", intVal(&arg->val));
break;
case T_Float:
/* represented as a string, so just copy it */
appendStringInfoString(&buffer, strVal(&arg->val));
break;
case T_String:
appendStringInfoString(&buffer, quote_literal_cstr(strVal(&arg->val)));
break;
default:
elog(ERROR, "unexpected constant type: %d", nodeTag(&arg->val));
}
}
}
CdbDispatchCommand(buffer.data,
DF_CANCEL_ON_ERROR|
DF_NEED_TWO_PHASE|
DF_WITH_SNAPSHOT,
NULL);
pfree(buffer.data);
}
/* Close pg_db_role_setting, but keep lock till commit */
table_close(rel, NoLock);
}
/*
* Drop some settings from the catalog. These can be for a particular
* database, or for a particular role. (It is of course possible to do both
* too, but it doesn't make sense for current uses.)
*/
void
DropSetting(Oid databaseid, Oid roleid)
{
Relation relsetting;
TableScanDesc scan;
ScanKeyData keys[2];
HeapTuple tup;
int numkeys = 0;
relsetting = table_open(DbRoleSettingRelationId, RowExclusiveLock);
if (OidIsValid(databaseid))
{
ScanKeyInit(&keys[numkeys],
Anum_pg_db_role_setting_setdatabase,
BTEqualStrategyNumber,
F_OIDEQ,
ObjectIdGetDatum(databaseid));
numkeys++;
}
if (OidIsValid(roleid))
{
ScanKeyInit(&keys[numkeys],
Anum_pg_db_role_setting_setrole,
BTEqualStrategyNumber,
F_OIDEQ,
ObjectIdGetDatum(roleid));
numkeys++;
}
scan = table_beginscan_catalog(relsetting, numkeys, keys);
while (HeapTupleIsValid(tup = heap_getnext(scan, ForwardScanDirection)))
{
CatalogTupleDelete(relsetting, &tup->t_self);
}
table_endscan(scan);
table_close(relsetting, RowExclusiveLock);
}
/*
* Scan pg_db_role_setting looking for applicable settings, and load them on
* the current process.
*
* relsetting is pg_db_role_setting, already opened and locked.
*
* Note: we only consider setting for the exact databaseid/roleid combination.
* This probably needs to be called more than once, with InvalidOid passed as
* databaseid/roleid.
*/
void
ApplySetting(Snapshot snapshot, Oid databaseid, Oid roleid,
Relation relsetting, GucSource source)
{
SysScanDesc scan;
ScanKeyData keys[2];
HeapTuple tup;
ScanKeyInit(&keys[0],
Anum_pg_db_role_setting_setdatabase,
BTEqualStrategyNumber,
F_OIDEQ,
ObjectIdGetDatum(databaseid));
ScanKeyInit(&keys[1],
Anum_pg_db_role_setting_setrole,
BTEqualStrategyNumber,
F_OIDEQ,
ObjectIdGetDatum(roleid));
scan = systable_beginscan(relsetting, DbRoleSettingDatidRolidIndexId, true,
snapshot, 2, keys);
while (HeapTupleIsValid(tup = systable_getnext(scan)))
{
bool isnull;
Datum datum;
datum = heap_getattr(tup, Anum_pg_db_role_setting_setconfig,
RelationGetDescr(relsetting), &isnull);
if (!isnull)
{
ArrayType *a = DatumGetArrayTypeP(datum);
/*
* We process all the options at SUSET level. We assume that the
* right to insert an option into pg_db_role_setting was checked
* when it was inserted.
*/
ProcessGUCArray(a, PGC_SUSET, source, GUC_ACTION_SET);
}
}
systable_endscan(scan);
}
相关信息
相关文章
0
赞
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦