diff --git a/doc/src/sgml/ref/allfiles.sgml b/doc/src/sgml/ref/allfiles.sgml
index e53bfc7452..aea2171cdf 100644
--- a/doc/src/sgml/ref/allfiles.sgml
+++ b/doc/src/sgml/ref/allfiles.sgml
@@ -1,5 +1,5 @@
@@ -98,6 +98,7 @@ Complete list of usable sgml source files in this directory.
+
diff --git a/doc/src/sgml/ref/set_session_auth.sgml b/doc/src/sgml/ref/set_session_auth.sgml
new file mode 100644
index 0000000000..ba3ec6fb54
--- /dev/null
+++ b/doc/src/sgml/ref/set_session_auth.sgml
@@ -0,0 +1,103 @@
+
+
+
+ 2001-04-21
+
+
+
+ SET SESSION AUTHORIZATION
+ SQL - Language Statements
+
+
+
+ SET SESSION AUTHORIZATION
+ Set the session user identifier and the current user identifier
+ of the current SQL-session context
+
+
+
+
+SET SESSION AUTHORIZATION 'username'
+
+
+
+
+ Description
+
+
+ This command sets the session user identifier and the current user
+ identifer of the current SQL-session context to be
+ username.
+
+
+
+ The session user identifier is initially set to be the (possibly
+ authenticated) user name provided by the client. The current user
+ identifier is normally equal to the session user identifier, but
+ may change temporarily in the context of setuid
+ functions and similar mechanisms. The current user identifer is
+ relevant for permission checking.
+
+
+
+ Execution of this command is only permitted if the initial session
+ user (the authenticated user) had the
+ superuser privilege. This permission is kept for the duration of a
+ connection; for example, it is possible to temporarily become an
+ unprivileged user and later switch back to become a superuser.
+
+
+
+
+ Examples
+
+
+SELECT SESSION_USER, CURRENT_USER;
+ current_user | session_user
+--------------+--------------
+ peter | peter
+
+SET SESSION AUTHORIZATION 'paul';
+
+SELECT SESSION_USER, CURRENT_USER;
+ current_user | session_user
+--------------+--------------
+ paul | paul
+
+
+
+
+ Compatibility
+
+ SQL99
+
+
+ SQL99 allows some other expressions to appear in place of the
+ literal username which are not important in
+ practice. PostgreSQL allows identifier
+ syntax ("username"), which SQL does not. SQL
+ does not allow this command during a transaction;
+ PostgreSQL does not make
+ this restriction because there is no reason to. The
+ privileges necessary to execute this command are left
+ implementation-defined by the standard.
+
+
+
+
+
diff --git a/doc/src/sgml/reference.sgml b/doc/src/sgml/reference.sgml
index 9a977a6515..57dcc7ed28 100644
--- a/doc/src/sgml/reference.sgml
+++ b/doc/src/sgml/reference.sgml
@@ -1,5 +1,5 @@
@@ -84,6 +84,7 @@ PostgreSQL Reference Manual
&selectInto;
&set;
&setConstraints;
+ &setSessionAuth;
&setTransaction;
&show;
&truncate;
@@ -131,7 +132,6 @@ Disable this chapter until we have more functions documented.
&dropuser;
&ecpgRef;
&pgAccess;
- &pgAdmin;
&pgConfig;
&pgDump;
&pgDumpall;
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 420913a0e4..eb43be8f3f 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.47 2001/03/29 19:03:57 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.48 2001/05/08 21:06:42 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -721,6 +721,8 @@ SetPGVariable(const char *name, const char *value)
parse_server_encoding(mvalue);
else if (strcasecmp(name, "seed") == 0)
parse_random_seed(mvalue);
+ else if (strcasecmp(name, "session_authorization") == 0)
+ SetSessionAuthorization(value);
else
SetConfigOption(name, value, superuser() ? PGC_SUSET : PGC_USERSET);
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 40c379aca5..0f419edb17 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.223 2001/05/07 00:43:23 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.224 2001/05/08 21:06:42 petere Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -259,7 +259,7 @@ static void doNegateFloat(Value *v);
%type Iconst
%type Sconst, comment_text
-%type UserId, opt_boolean, var_value, zone_value
+%type UserId, opt_boolean, var_value, zone_value, Ident_or_Sconst
%type ColId, ColLabel, TokenId
%type TableConstraint
@@ -292,7 +292,7 @@ static void doNegateFloat(Value *v);
*/
/* Keywords (in SQL92 reserved words) */
-%token ABSOLUTE, ACTION, ADD, ALL, ALTER, AND, ANY, AS, ASC, AT,
+%token ABSOLUTE, ACTION, ADD, ALL, ALTER, AND, ANY, AS, ASC, AT, AUTHORIZATION,
BEGIN_TRANS, BETWEEN, BOTH, BY,
CASCADE, CASE, CAST, CHAR, CHARACTER, CHECK, CLOSE,
COALESCE, COLLATE, COLUMN, COMMIT,
@@ -761,6 +761,13 @@ VariableSetStmt: SET ColId TO var_value
n->value = $3;
$$ = (Node *) n;
}
+ | SET SESSION AUTHORIZATION Ident_or_Sconst
+ {
+ VariableSetStmt *n = makeNode(VariableSetStmt);
+ n->name = "session_authorization";
+ n->value = $4;
+ $$ = (Node *) n;
+ }
;
opt_level: READ COMMITTED { $$ = "committed"; }
@@ -837,6 +844,10 @@ opt_encoding: Sconst { $$ = $1; }
| /*EMPTY*/ { $$ = NULL; }
;
+Ident_or_Sconst: IDENT { $$ = $1; }
+ | SCONST { $$ = $1; }
+
+
VariableShowStmt: SHOW ColId
{
VariableShowStmt *n = makeNode(VariableShowStmt);
@@ -5459,6 +5470,7 @@ TokenId: ABSOLUTE { $$ = "absolute"; }
| AGGREGATE { $$ = "aggregate"; }
| ALTER { $$ = "alter"; }
| AT { $$ = "at"; }
+ | AUTHORIZATION { $$ = "authorization"; }
| BACKWARD { $$ = "backward"; }
| BEFORE { $$ = "before"; }
| BEGIN_TRANS { $$ = "begin"; }
diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c
index 8ab19f86ae..6064ca8a8f 100644
--- a/src/backend/parser/keywords.c
+++ b/src/backend/parser/keywords.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.91 2001/05/07 00:43:23 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.92 2001/05/08 21:06:43 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -44,6 +44,7 @@ static ScanKeyword ScanKeywords[] = {
{"as", AS},
{"asc", ASC},
{"at", AT},
+ {"authorization", AUTHORIZATION},
{"backward", BACKWARD},
{"before", BEFORE},
{"begin", BEGIN_TRANS},
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 33b9e11203..a07eae5129 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.65 2001/04/16 02:42:01 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.66 2001/05/08 21:06:43 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -354,6 +354,7 @@ convertstr(unsigned char *buff, int len, int dest)
static Oid CurrentUserId = InvalidOid;
static Oid SessionUserId = InvalidOid;
+static bool AuthenticatedUserIsSuperuser = false;
/*
* This function is relevant for all privilege checks.
@@ -397,7 +398,7 @@ SetSessionUserId(Oid newid)
void
-SetSessionUserIdFromUserName(const char *username)
+InitializeSessionUserId(const char *username)
{
HeapTuple userTup;
@@ -407,6 +408,9 @@ SetSessionUserIdFromUserName(const char *username)
*/
AssertState(!IsBootstrapProcessingMode());
+ /* call only once */
+ AssertState(!OidIsValid(SessionUserId));
+
userTup = SearchSysCache(SHADOWNAME,
PointerGetDatum(username),
0, 0, 0);
@@ -415,6 +419,29 @@ SetSessionUserIdFromUserName(const char *username)
SetSessionUserId(((Form_pg_shadow) GETSTRUCT(userTup))->usesysid);
+ AuthenticatedUserIsSuperuser = ((Form_pg_shadow) GETSTRUCT(userTup))->usesuper;
+
+ ReleaseSysCache(userTup);
+}
+
+
+
+void SetSessionAuthorization(const char * username)
+{
+ HeapTuple userTup;
+
+ if (!AuthenticatedUserIsSuperuser)
+ elog(ERROR, "permission denied");
+
+ userTup = SearchSysCache(SHADOWNAME,
+ PointerGetDatum(username),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(userTup))
+ elog(ERROR, "user \"%s\" does not exist", username);
+
+ SetSessionUserId(((Form_pg_shadow) GETSTRUCT(userTup))->usesysid);
+ SetUserId(((Form_pg_shadow) GETSTRUCT(userTup))->usesysid);
+
ReleaseSysCache(userTup);
}
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index f877564866..70d835aa25 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.84 2001/04/21 18:29:29 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.85 2001/05/08 21:06:43 petere Exp $
*
*
*-------------------------------------------------------------------------
@@ -341,7 +341,7 @@ InitPostgres(const char *dbname, const char *username)
if (bootstrap)
SetSessionUserId(geteuid());
else
- SetSessionUserIdFromUserName(username);
+ InitializeSessionUserId(username);
/*
* Unless we are bootstrapping, double-check that InitMyDatabaseInfo()
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index ce2a6692b7..dd323162dd 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3,7 +3,7 @@
*
* Copyright 2000 by PostgreSQL Global Development Group
*
- * $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.31 2001/05/07 19:31:33 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.32 2001/05/08 21:06:43 petere Exp $
*/
/*----------------------------------------------------------------------
@@ -201,7 +201,7 @@ psql_completion(char *text, int start, int end)
/* these SET arguments are known in gram.y */
"CONSTRAINTS",
"NAMES",
- "SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL",
+ "SESSION",
"TRANSACTION ISOLATION LEVEL",
/* these are treated in backend/commands/variable.c */
"DateStyle",
@@ -646,6 +646,22 @@ psql_completion(char *text, int start, int end)
COMPLETE_WITH_LIST(constraint_list);
}
+ /* Complete SET SESSION with AUTHORIZATION or CHARACTERISTICS... */
+ else if (strcasecmp(prev2_wd, "SET") == 0 && strcasecmp(prev_wd, "SESSION") == 0)
+ {
+ char *my_list[] = {"AUTHORIZATION",
+ "CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL",
+ NULL};
+
+ COMPLETE_WITH_LIST(my_list);
+ }
+ /* Complete SET SESSION AUTHORIZATION with username */
+ else if (strcasecmp(prev3_wd, "SET") == 0
+ && strcasecmp(prev2_wd, "SESSION") == 0
+ && strcasecmp(prev_wd, "AUTHORIZATION") == 0)
+ {
+ COMPLETE_WITH_QUERY(Query_for_list_of_users);
+ }
/* Complete SET with "TO" */
else if (strcasecmp(prev2_wd, "SET") == 0 &&
strcasecmp(prev4_wd, "UPDATE") != 0)
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index 6f90355d76..e69fba4b87 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -12,7 +12,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: miscadmin.h,v 1.83 2001/03/22 04:00:25 momjian Exp $
+ * $Id: miscadmin.h,v 1.84 2001/05/08 21:06:43 petere Exp $
*
* NOTES
* some of the information in this file should be moved to
@@ -208,7 +208,8 @@ extern Oid GetUserId(void);
extern void SetUserId(Oid userid);
extern Oid GetSessionUserId(void);
extern void SetSessionUserId(Oid userid);
-extern void SetSessionUserIdFromUserName(const char *username);
+extern void InitializeSessionUserId(const char *username);
+extern void SetSessionAuthorization(const char *username);
extern void SetDataDir(const char *dir);