Index: src/pl/plpgsql/src/gram.y
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v
retrieving revision 1.21
diff -c -r1.21 gram.y
*** src/pl/plpgsql/src/gram.y	2001/06/06 18:54:41	1.21
--- src/pl/plpgsql/src/gram.y	2001/07/11 18:37:07
***************
*** 122,132 ****
  %type <stmts>	proc_sect, proc_stmts, stmt_else, loop_body
  %type <stmt>	proc_stmt, pl_block
  %type <stmt>	stmt_assign, stmt_if, stmt_loop, stmt_while, stmt_exit
! %type <stmt>	stmt_return, stmt_raise, stmt_execsql, stmt_fori
  %type <stmt>	stmt_fors, stmt_select, stmt_perform
  %type <stmt>	stmt_dynexecute, stmt_dynfors, stmt_getdiag
  %type <stmt>	stmt_open, stmt_fetch, stmt_close
  
  %type <intlist>	raise_params
  %type <ival>	raise_level, raise_param
  %type <str>		raise_msg
--- 122,134 ----
  %type <stmts>	proc_sect, proc_stmts, stmt_else, loop_body
  %type <stmt>	proc_stmt, pl_block
  %type <stmt>	stmt_assign, stmt_if, stmt_loop, stmt_while, stmt_exit
! %type <stmt>	stmt_return, stmt_raise, stmt_execsql, stmt_fori, stmt_setauth
  %type <stmt>	stmt_fors, stmt_select, stmt_perform
  %type <stmt>	stmt_dynexecute, stmt_dynfors, stmt_getdiag
  %type <stmt>	stmt_open, stmt_fetch, stmt_close
  
+ %type <ival>	auth_level
+ 
  %type <intlist>	raise_params
  %type <ival>	raise_level, raise_param
  %type <str>		raise_msg
***************
*** 172,177 ****
--- 174,183 ----
  %token	K_PERFORM
  %token	K_ROW_COUNT
  %token	K_RAISE
+ %token	K_SET
+ %token	K_AUTHORIZATION
+ %token	K_INVOKER
+ %token	K_DEFINER
  %token	K_RECORD
  %token	K_RENAME
  %token	K_RESULT_OID
***************
*** 726,731 ****
--- 732,739 ----
  						{ $$ = $1; }
  				| stmt_raise
  						{ $$ = $1; }
+ 				| stmt_setauth
+ 						{ $$ = $1; }
  				| stmt_execsql
  						{ $$ = $1; }
  				| stmt_dynexecute
***************
*** 1242,1247 ****
--- 1250,1278 ----
  						$$ = (PLpgSQL_stmt *)new;
  					}
  				;
+ 
+ stmt_setauth		: K_SET K_AUTHORIZATION auth_level lno ';'
+ 				{
+ 					PLpgSQL_stmt_setauth *new;
+ 
+ 					new=malloc(sizeof(PLpgSQL_stmt_setauth));
+ 
+ 					new->cmd_type = PLPGSQL_STMT_SETAUTH;
+ 					new->auth_level = $3;
+                                         new->lineno = $4;
+                                         
+ 					$$ = (PLpgSQL_stmt *)new;
+ 				}
+ 
+ auth_level : K_DEFINER
+ 		{
+ 			$$=PLPGSQL_AUTH_DEFINER;
+                 }
+ 	   | K_INVOKER
+            	{
+                 	$$=PLPGSQL_AUTH_INVOKER;
+                 }
+ ;
  
  stmt_raise		: K_RAISE lno raise_level raise_msg raise_params ';'
  					{
Index: src/pl/plpgsql/src/pl_comp.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v
retrieving revision 1.31
diff -c -r1.31 pl_comp.c
*** src/pl/plpgsql/src/pl_comp.c	2001/05/21 14:22:18	1.31
--- src/pl/plpgsql/src/pl_comp.c	2001/07/11 18:37:07
***************
*** 169,174 ****
--- 169,175 ----
  
  	function->fn_functype = functype;
  	function->fn_oid = fn_oid;
+         function->definer_uid = procStruct->proowner;
  	function->fn_name = strdup(DatumGetCString(DirectFunctionCall1(nameout,
  								 NameGetDatum(&(procStruct->proname)))));
  
Index: src/pl/plpgsql/src/pl_exec.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v
retrieving revision 1.44
diff -c -r1.44 pl_exec.c
*** src/pl/plpgsql/src/pl_exec.c	2001/05/28 19:33:24	1.44
--- src/pl/plpgsql/src/pl_exec.c	2001/07/11 18:37:07
***************
*** 47,52 ****
--- 47,53 ----
  #include "plpgsql.h"
  #include "pl.tab.h"
  
+ #include "miscadmin.h"
  #include "access/heapam.h"
  #include "catalog/pg_proc.h"
  #include "catalog/pg_type.h"
***************
*** 105,110 ****
--- 106,113 ----
  			   PLpgSQL_stmt_exit * stmt);
  static int exec_stmt_return(PLpgSQL_execstate * estate,
  				 PLpgSQL_stmt_return * stmt);
+ static int exec_stmt_setauth(PLpgSQL_execstate * estate,
+ 				PLpgSQL_stmt_setauth * stmt);
  static int exec_stmt_raise(PLpgSQL_execstate * estate,
  				PLpgSQL_stmt_raise * stmt);
  static int exec_stmt_execsql(PLpgSQL_execstate * estate,
***************
*** 226,231 ****
--- 229,237 ----
  					case PLPGSQL_STMT_RETURN:
  						stmttype = "return";
  						break;
+ 					case PLPGSQL_STMT_SETAUTH:
+ 						stmttype = "setauth";
+ 						break;
  					case PLPGSQL_STMT_RAISE:
  						stmttype = "raise";
  						break;
***************
*** 277,283 ****
  	estate.retistuple = func->fn_retistuple;
  	estate.retisset = func->fn_retset;
  	estate.exitlabel = NULL;
! 
  	estate.found_varno = func->found_varno;
  	estate.ndatums = func->ndatums;
  	estate.datums = palloc(sizeof(PLpgSQL_datum *) * estate.ndatums);
--- 283,292 ----
  	estate.retistuple = func->fn_retistuple;
  	estate.retisset = func->fn_retset;
  	estate.exitlabel = NULL;
! 	estate.invoker_uid = GetUserId();
! 	estate.definer_uid = func->definer_uid;
! 	estate.auth_level = PLPGSQL_AUTH_INVOKER;
!         
  	estate.found_varno = func->found_varno;
  	estate.ndatums = func->ndatums;
  	estate.datums = palloc(sizeof(PLpgSQL_datum *) * estate.ndatums);
***************
*** 397,402 ****
--- 406,414 ----
  		elog(ERROR, "control reaches end of function without RETURN");
  	}
  
+ 	if (estate.auth_level!=PLPGSQL_AUTH_INVOKER)
+ 		SetUserId(estate.invoker_uid);
+ 
  	/*
  	 * We got a return value - process it
  	 */
***************
*** 577,582 ****
--- 589,597 ----
  	estate.retistuple = func->fn_retistuple;
  	estate.retisset = func->fn_retset;
  	estate.exitlabel = NULL;
+ 	estate.invoker_uid = GetUserId();
+ 	estate.definer_uid = func->definer_uid;
+ 	estate.auth_level = PLPGSQL_AUTH_INVOKER;
  
  	estate.found_varno = func->found_varno;
  	estate.ndatums = func->ndatums;
***************
*** 760,765 ****
--- 775,783 ----
  		elog(ERROR, "control reaches end of trigger procedure without RETURN");
  	}
  
+ 	if (estate.auth_level!=PLPGSQL_AUTH_INVOKER)
+ 		SetUserId(estate.invoker_uid);
+ 
  	/*
  	 * Check that the returned tuple structure has the same attributes,
  	 * the relation that fired the trigger has.
***************
*** 1022,1027 ****
--- 1040,1049 ----
  			rc = exec_stmt_return(estate, (PLpgSQL_stmt_return *) stmt);
  			break;
  
+ 		case PLPGSQL_STMT_SETAUTH:
+ 			rc = exec_stmt_setauth(estate, (PLpgSQL_stmt_setauth *) stmt);
+ 			break;
+ 
  		case PLPGSQL_STMT_RAISE:
  			rc = exec_stmt_raise(estate, (PLpgSQL_stmt_raise *) stmt);
  			break;
***************
*** 1643,1648 ****
--- 1665,1693 ----
  									&(estate->rettype));
  
  	return PLPGSQL_RC_RETURN;
+ }
+ 
+ /* ----------
+  * exec_stmt_setauth            Changes user ID to/from
+  *                              that of the function owner's
+  * ----------
+  */
+ 
+ static int
+ exec_stmt_setauth(PLpgSQL_execstate * estate, PLpgSQL_stmt_setauth * stmt)
+ {
+ 	switch(stmt->auth_level)
+         {
+         	case PLPGSQL_AUTH_DEFINER:
+                 	SetUserId(estate->definer_uid);
+                         break;
+                 case PLPGSQL_AUTH_INVOKER:
+                 	SetUserId(estate->invoker_uid);
+                         break;
+ 	}
+ 
+ 	estate->auth_level=stmt->auth_level;
+ 	return PLPGSQL_RC_OK;
  }
  
  
Index: src/pl/plpgsql/src/pl_funcs.c
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/pl/plpgsql/src/pl_funcs.c,v
retrieving revision 1.13
diff -c -r1.13 pl_funcs.c
*** src/pl/plpgsql/src/pl_funcs.c	2001/05/21 14:22:19	1.13
--- src/pl/plpgsql/src/pl_funcs.c	2001/07/11 18:37:08
***************
*** 382,387 ****
--- 382,388 ----
  static void dump_select(PLpgSQL_stmt_select * stmt);
  static void dump_exit(PLpgSQL_stmt_exit * stmt);
  static void dump_return(PLpgSQL_stmt_return * stmt);
+ static void dump_setauth(PLpgSQL_stmt_setauth * stmt);
  static void dump_raise(PLpgSQL_stmt_raise * stmt);
  static void dump_execsql(PLpgSQL_stmt_execsql * stmt);
  static void dump_dynexecute(PLpgSQL_stmt_dynexecute * stmt);
***************
*** 438,443 ****
--- 439,447 ----
  		case PLPGSQL_STMT_RETURN:
  			dump_return((PLpgSQL_stmt_return *) stmt);
  			break;
+ 		case PLPGSQL_STMT_SETAUTH:
+ 			dump_setauth((PLpgSQL_stmt_setauth *) stmt);
+ 			break;
  		case PLPGSQL_STMT_RAISE:
  			dump_raise((PLpgSQL_stmt_raise *) stmt);
  			break;
***************
*** 719,724 ****
--- 723,743 ----
  			dump_expr(stmt->expr);
  	}
  	printf("\n");
+ }
+ 
+ static void
+ dump_setauth(PLpgSQL_stmt_setauth * stmt)
+ {
+ 	dump_ind();
+         switch (stmt->auth_level)
+         {
+         	case PLPGSQL_AUTH_DEFINER:
+                 	printf("SET AUTHORIZATION DEFINER\n");
+                         break;
+                 case PLPGSQL_AUTH_INVOKER:
+                 	printf("SET AUTHORIZATION INVOKER\n");
+                         break;
+         }
  }
  
  static void
Index: src/pl/plpgsql/src/plpgsql.h
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v
retrieving revision 1.14
diff -c -r1.14 plpgsql.h
*** src/pl/plpgsql/src/plpgsql.h	2001/05/21 14:22:19	1.14
--- src/pl/plpgsql/src/plpgsql.h	2001/07/11 18:37:08
***************
*** 95,100 ****
--- 95,101 ----
  	PLPGSQL_STMT_DYNEXECUTE,
  	PLPGSQL_STMT_DYNFORS,
  	PLPGSQL_STMT_GETDIAG,
+ 	PLPGSQL_STMT_SETAUTH,
  	PLPGSQL_STMT_OPEN,
  	PLPGSQL_STMT_FETCH,
  	PLPGSQL_STMT_CLOSE
***************
*** 112,117 ****
--- 113,128 ----
  	PLPGSQL_RC_RETURN
  };
  
+ /* ---------
+  * Authorization levels
+  * ---------
+  */
+ enum
+ {
+ 	PLPGSQL_AUTH_INVOKER,
+         PLPGSQL_AUTH_DEFINER,
+ };
+ 
  /* ----------
   * GET DIAGNOSTICS system attrs
   * ----------
***************
*** 425,430 ****
--- 436,447 ----
  	int			retrecno;
  }			PLpgSQL_stmt_return;
  
+ typedef struct
+ {                               /* SET AUTHORIZATION statement */
+     int         cmd_type;
+     int         lineno;
+     int		auth_level;
+ }           PLpgSQL_stmt_setauth;
  
  typedef struct
  {								/* RAISE statement			*/
***************
*** 480,485 ****
--- 497,503 ----
  	int			tg_nargs_varno;
  
  	int			ndatums;
+         Oid			definer_uid;
  	PLpgSQL_datum **datums;
  	PLpgSQL_stmt_block *action;
  	struct PLpgSQL_function *next;
***************
*** 502,507 ****
--- 520,528 ----
  	int			found_varno;
  	int			ndatums;
  	PLpgSQL_datum **datums;
+ 	Oid		invoker_uid;
+ 	Oid		definer_uid;
+         int		auth_level;
  }			PLpgSQL_execstate;
  
  
Index: src/pl/plpgsql/src/scan.l
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/pl/plpgsql/src/scan.l,v
retrieving revision 1.12
diff -c -r1.12 scan.l
*** src/pl/plpgsql/src/scan.l	2001/05/21 14:22:19	1.12
--- src/pl/plpgsql/src/scan.l	2001/07/11 18:37:08
***************
*** 121,126 ****
--- 121,130 ----
  open			{ return K_OPEN;			}
  perform			{ return K_PERFORM;			}
  raise			{ return K_RAISE;			}
+ set			{ return K_SET;				}
+ authorization		{ return K_AUTHORIZATION;		}
+ invoker			{ return K_INVOKER;			}
+ definer			{ return K_DEFINER;			}
  record			{ return K_RECORD;			}
  rename			{ return K_RENAME;			}
  result_oid		{ return K_RESULT_OID;		}
