I revised my patch as I attached.

The hook function is modified and consolidated as follows:

  typedef enum FunctionCallEventType
  {
     FCET_BE_HOOKED,
     FCET_PREPARE,
     FCET_START,
     FCET_END,
     FCET_ABORT,
  } FunctionCallEventType;

  typedef Datum (*function_call_event_type)(Oid functionId,
                                            FunctionCallEventType event,
                                            Datum event_arg);
  extern PGDLLIMPORT function_call_event_type function_call_event_hook;

Unlike the subject of this e-mail, now it does not focus on only switching
security labels during execution of a certain functions.
For example, we may use this hook to track certain functions for security
auditing, performance tuning, and others.

In the case of SE-PgSQL, it shall return BoolGetDatum(true), if the target
function is configured as a trusted procedure, then, this invocation will
be hooked by fmgr_security_definer. In the first call, it shall compute
the security context to be assigned during execution on FCET_PREPARE event.
Then, it switches to the computed label on the FCET_START event, and
restore it on the FCET_END or ECET_ABORT event.

I also fixed up regression test, dummy_seclabel module and its
documentation as Robert pointed out in another topic.

Thanks,

(2010/11/14 13:16), KaiGai Kohei wrote:
> (2010/11/14 11:19), Robert Haas wrote:
>> 2010/11/12 KaiGai Kohei<kai...@kaigai.gr.jp>:
>>> The attached patch allows the security label provider to switch
>>> security label of the client during execution of certain functions.
>>> I named it as "label switcher function"; also called as "trusted-
>>> procedure" in SELinux community.
>>>
>>> This feature is quite similar idea toward security definer function,
>>> or set-uid program on operating system. It allows label providers
>>> to switch its internal state that holds security label of the
>>> client, then restore it.
>>> If and when a label provider said the function being invoked is
>>> a label-switcher, fmgr_security_definer() traps this invocation
>>> and set some states just before actual invocations.
>>>
>>> We added three new hooks for security label provider.
>>> The get_client_label and set_client_label allows the PG core to
>>> save and restore security label of the client; which is mostly
>>> just an internal state of plugin module.
>>> And, the get_switched_label shall return NULL or a valid label
>>> if the supplied function is a label switcher. It also informs
>>> the PG core whether the function is switcher or not.
>>
>> I don't see why the plugin needs to expose the label stack to core PG.
>> If the plugin needs a label stack, it can do that all on its own. I
>> see that we need the hooks to allow the plugin to selectively disable
>> inlining and to gain control when function execution starts and ends
>> (or aborts) but I don't think the exact manipulations that the plugin
>> chooses to do at that point need to be visible to core PG.
>>
> Hmm. I designed this patch according to the implementation of existing
> security definer function, but it is not a only design.
> 
> Does the "label stack" means that this patch touches xact.c, doesn't it?
> Yes, if we have above three hooks around function calls, the core PG
> does not need to manage a label stack.
> 
> However, I want fmgr_security_definer_cache to have a field to save
> private opaque data, because it is not a very-light step to ask SE-Linux
> whether the function is trusted-procedure and to allocate a string to
> be applied during execution, although switching is a very-light step.
> So, I want to compute it at first time of the function calls, like as
> security definer function checks syscache at once.
> 
> Of course, it is a private opaque data, it will be open for other usage.
> 
>> For SE-Linux, how do you intend to determine whether or not the
>> function is a trusted procedure? Will that be a function of the
>> security label applied to it?
>>
> When the function being invoked has a special security label with
> a "type_transition" rule on the current client's label in the
> security policy, SE-Linux decides the function is trusted procedure.
> 
> In other words, we can know whether or not the function is a trusted
> procedure by asking to the security policy. It is a task of the plugin.
> 
> Thanks,


-- 
KaiGai Kohei <kai...@ak.jp.nec.com>
diff --git a/contrib/dummy_seclabel/dummy_seclabel.c b/contrib/dummy_seclabel/dummy_seclabel.c
index 8bd50a3..557cc0c 100644
--- a/contrib/dummy_seclabel/dummy_seclabel.c
+++ b/contrib/dummy_seclabel/dummy_seclabel.c
@@ -12,14 +12,156 @@
  */
 #include "postgres.h"
 
+#include "catalog/pg_proc.h"
 #include "commands/seclabel.h"
 #include "miscadmin.h"
 
 PG_MODULE_MAGIC;
 
+PG_FUNCTION_INFO_V1(dummy_client_label);
+
+Datum dummay_client_label(PG_FUNCTION_ARGS);
+
 /* Entrypoint of the module */
 void _PG_init(void);
 
+static const char *client_label = "unclassified";
+
+static function_call_event_type function_call_event_next = NULL;
+
+typedef struct {
+	Datum	self;
+	Datum	next;
+} private_stack;
+
+static Datum
+dummy_function_call(Oid functionId,
+					FunctionCallEventType event,
+					Datum event_arg)
+{
+	Datum			result = 0;
+	char		   *label;
+	ObjectAddress	object = { .classId = ProcedureRelationId,
+							   .objectId = functionId,
+							   .objectSubId = 0 };
+	switch (event)
+	{
+		case FCET_BE_HOOKED:
+			/*
+			 * If the target function is labeled as "trusted",
+			 * the dummy tries to hook invocation of the function.
+			 */
+			result = BoolGetDatum(false);
+
+			if (function_call_event_next)
+			{
+				result = (*function_call_event_next)(functionId,
+													 event,
+													 event_arg);
+				if (DatumGetBool(result))
+					break;		/* no need to check anymore */
+			}
+			label = GetSecurityLabel(&object, "dummy");
+			if (label && strcmp(label, "trusted") == 0)
+				result = BoolGetDatum(true);
+			break;
+
+		case FCET_PREPARE:
+			/*
+			 * It computes an alternative label during execution
+			 * of the trusted procedure. This computation is not
+			 * necessary to repeat twice or more, so we save it
+			 * on the private opaque data.
+			 */
+			if (function_call_event_next)
+			{
+				FmgrInfo	   *flinfo = (FmgrInfo *)(event_arg);
+				private_stack  *out
+					= MemoryContextAlloc(flinfo->fn_mcxt, sizeof(*out));
+
+				out->next = (*function_call_event_next)(functionId,
+														  event,
+														  event_arg);
+				/*
+				 * XXX - we already checked the function being labeled
+				 *       as "trusted"
+				 */
+				if (!superuser())
+					out->self = PointerGetDatum("secret");
+				else
+					out->self = PointerGetDatum("top secret");
+
+				result = PointerGetDatum(out);
+			}
+			else
+			{
+				if (!superuser())
+					result = PointerGetDatum("secret");
+				else
+					result = PointerGetDatum("top secret");
+			}
+			break;
+
+		case FCET_START:
+			/*
+			 * Switch security label of the client
+			 */
+			if (function_call_event_next)
+			{
+				private_stack  *in = (private_stack *)(event_arg);
+				private_stack  *out = palloc(sizeof(*out));
+
+				out->next = (*function_call_event_next)(functionId,
+														event,
+														in->next);
+				out->self = PointerGetDatum(client_label);
+				client_label = DatumGetPointer(in->self);
+
+				result = PointerGetDatum(out);
+			}
+			else
+			{
+				result = PointerGetDatum(client_label);
+				client_label = DatumGetPointer(event_arg);
+			}
+			break;
+
+		case FCET_END:
+		case FCET_ABORT:
+			/*
+			 * Restore security label of the client
+			 */
+			if (function_call_event_next)
+			{
+				private_stack  *in = (private_stack *)(event_arg);
+
+				(void)(*function_call_event_next)(functionId,
+												  event,
+												  in->next);
+				client_label = DatumGetPointer(in->self);
+			}
+			else
+			{
+				client_label = DatumGetPointer(event_arg);
+			}
+			break;
+
+		default:
+			elog(ERROR, "unexpected event type: %d", (int)event);
+			break;
+	}
+	return result;
+}
+
+Datum
+dummy_client_label(PG_FUNCTION_ARGS)
+{
+	if (!client_label)
+		PG_RETURN_NULL();
+
+	PG_RETURN_TEXT_P(cstring_to_text(client_label));
+}
+
 static void
 dummy_object_relabel(const ObjectAddress *object, const char *seclabel)
 {
@@ -28,7 +170,8 @@ dummy_object_relabel(const ObjectAddress *object, const char *seclabel)
 		strcmp(seclabel, "classified") == 0)
 		return;
 
-	if (strcmp(seclabel, "secret") == 0 ||
+	if (strcmp(seclabel, "trusted") == 0 ||
+		strcmp(seclabel, "secret") == 0 ||
 		strcmp(seclabel, "top secret") == 0)
 	{
 		if (!superuser())
@@ -46,4 +189,8 @@ void
 _PG_init(void)
 {
 	register_label_provider("dummy", dummy_object_relabel);
+
+	/* trusted procedure test */
+	function_call_event_next = function_call_event_hook;
+	function_call_event_hook = dummy_function_call;
 }
diff --git a/doc/src/sgml/contrib.sgml b/doc/src/sgml/contrib.sgml
index c310416..1d424a9 100644
--- a/doc/src/sgml/contrib.sgml
+++ b/doc/src/sgml/contrib.sgml
@@ -90,6 +90,7 @@ psql -d dbname -f <replaceable>SHAREDIR</>/contrib/<replaceable>module</>.sql
  &dblink;
  &dict-int;
  &dict-xsyn;
+ &dummy_seclabel;
  &earthdistance;
  &fuzzystrmatch;
  &hstore;
diff --git a/doc/src/sgml/dummy_seclabel.sgml b/doc/src/sgml/dummy_seclabel.sgml
new file mode 100644
index 0000000..1d65ff1
--- /dev/null
+++ b/doc/src/sgml/dummy_seclabel.sgml
@@ -0,0 +1,94 @@
+<!-- doc/src/sgml/dummy_seclabel.sgml -->
+
+<sect1 id="dummy_seclabel">
+ <title>dummy_seclabel</title>
+
+ <indexterm zone="dummy_seclabel">
+  <primary>dummy_seclabel</primary>
+ </indexterm>
+
+ <para>
+  The <filename>dummy_seclabel</> module provides a pseudo security label
+  support for regression testing.
+ </para>
+
+ <sect2>
+  <title>Rationale</title>
+
+  <para>
+   <productname>PostgreSQL</> got support <command>SECURITY LABEL</>
+   statement at the version 9.1 or later. It allows us to assign security
+   labels on database objects using plugin modules that are also called
+   external label provider.
+  </para>
+
+  <para>
+   This feature expects plugin modules validate given security labels,
+   because format of the labels completely depends on the security model
+   that plugin tries to provide, so we must install a plugin module to
+   provide security label feature at least.
+  </para>
+
+  <para>
+   However, we need to run regression test for the core features to
+   detect obvious regressions in the future. So, we also needed to ship
+   a dummy security label module independent from the platform.
+  </para>
+ </sect2>
+
+ <sect2>
+  <title>How to Use It</title>
+
+  <para>
+   Here's a simple example of usage:
+  </para>
+
+<programlisting>
+# postgresql.conf
+shared_preload_libraries = 'dummy_label'
+</programlisting>
+
+<programlisting>
+postgres=# CREATE TABLE t (a int, b text);
+CREATE TABLE
+postgres=# SECURITY LABEL ON TABLE t IS 'classified';
+SECURITY LABEL
+</programlisting>
+
+  <para>
+   The <filename>dummy_seclabel</> provide only a few kind of security
+   labels: <literal>unclassified</>, <literal>classified</>,
+   <literal>secret</>, <literal>top secret</> and <literal>trusted</>.
+
+   It does not allow any other strings as security labels.
+  </para>
+  <para>
+   These labels are not used to any valid access controls.
+   So, all we can do is to check whether <command>SECURITY LABEL</>
+   statement works as expected, or not.
+  </para>
+ </sect2>
+
+ <sect2>
+  <title>Limitations</title>
+
+  <itemizedlist>
+   <listitem>
+    <para>
+     This module is not intended to provide something useful features,
+     except for regression tests, so we don't recommend to install your
+     systems.
+    </para>
+   </listitem>
+  </itemizedlist>
+ </sect2>
+
+ <sect2>
+  <title>Author</title>
+
+  <para>
+   KaiGai Kohei <email>kai...@ak.jp.nec.com</email>
+  </para>
+ </sect2>
+
+</sect1>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 9b1de85..ca24638 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -102,6 +102,7 @@
 <!entity dblink          SYSTEM "dblink.sgml">
 <!entity dict-int        SYSTEM "dict-int.sgml">
 <!entity dict-xsyn       SYSTEM "dict-xsyn.sgml">
+<!entity dummy_seclabel  SYSTEM "dummy_seclabel.sgml">
 <!entity earthdistance   SYSTEM "earthdistance.sgml">
 <!entity fuzzystrmatch   SYSTEM "fuzzystrmatch.sgml">
 <!entity hstore          SYSTEM "hstore.sgml">
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index de2e66b..3b64d37 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -3721,6 +3721,10 @@ inline_function(Oid funcid, Oid result_type, List *args,
 	if (pg_proc_aclcheck(funcid, GetUserId(), ACL_EXECUTE) != ACLCHECK_OK)
 		return NULL;
 
+	/* Check whether plugin want to hook this function, or not */
+	if (IsFunctionCallEventHooked(funcid))
+		return NULL;
+
 	/*
 	 * Make a temporary memory context, so that we don't leak all the stuff
 	 * that parsing might create.
@@ -4153,6 +4157,10 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
 	if (pg_proc_aclcheck(func_oid, GetUserId(), ACL_EXECUTE) != ACLCHECK_OK)
 		return NULL;
 
+	/* Check whether plugin want to hook this function, or not */
+	if (IsFunctionCallEventHooked(func_oid))
+		return NULL;
+
 	/*
 	 * OK, let's take a look at the function's pg_proc entry.
 	 */
diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c
index 1c9d2c2..e7651cb 100644
--- a/src/backend/utils/fmgr/fmgr.c
+++ b/src/backend/utils/fmgr/fmgr.c
@@ -30,6 +30,10 @@
 #include "utils/lsyscache.h"
 #include "utils/syscache.h"
 
+/*
+ * Hooks for function calls
+ */
+PGDLLIMPORT function_call_event_type	function_call_event_hook = NULL;
 
 /*
  * Declaration for old-style function pointer type.  This is now used only
@@ -230,7 +234,8 @@ fmgr_info_cxt_security(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt,
 	 */
 	if (!ignore_security &&
 		(procedureStruct->prosecdef ||
-		 !heap_attisnull(procedureTuple, Anum_pg_proc_proconfig)))
+		 !heap_attisnull(procedureTuple, Anum_pg_proc_proconfig) ||
+		 IsFunctionCallEventHooked(functionId)))
 	{
 		finfo->fn_addr = fmgr_security_definer;
 		finfo->fn_stats = TRACK_FUNC_ALL;		/* ie, never track */
@@ -857,6 +862,7 @@ struct fmgr_security_definer_cache
 	FmgrInfo	flinfo;			/* lookup info for target function */
 	Oid			userid;			/* userid to set, or InvalidOid */
 	ArrayType  *proconfig;		/* GUC values to set, or NULL */
+	Datum		private;		/* private usage for hook plugins */
 };
 
 /*
@@ -878,6 +884,7 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
 	Oid			save_userid;
 	int			save_sec_context;
 	volatile int save_nestlevel;
+	Datum		save_datum;
 	PgStat_FunctionCallUsage fcusage;
 
 	if (!fcinfo->flinfo->fn_extra)
@@ -916,6 +923,12 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
 
 		ReleaseSysCache(tuple);
 
+		/* Function call event hook */
+		if (function_call_event_hook)
+			fcache->private =
+				(*function_call_event_hook)(fcinfo->flinfo->fn_oid,
+											FCET_PREPARE,
+											PointerGetDatum(&fcache->flinfo));
 		fcinfo->flinfo->fn_extra = fcache;
 	}
 	else
@@ -930,7 +943,7 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
 
 	if (OidIsValid(fcache->userid))
 		SetUserIdAndSecContext(fcache->userid,
-							save_sec_context | SECURITY_LOCAL_USERID_CHANGE);
+							   save_sec_context | SECURITY_LOCAL_USERID_CHANGE);
 
 	if (fcache->proconfig)
 	{
@@ -940,6 +953,13 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
 						GUC_ACTION_SAVE);
 	}
 
+	if (function_call_event_hook)
+		save_datum = (*function_call_event_hook)(fcinfo->flinfo->fn_oid,
+												 FCET_START,
+												 fcache->private);
+	else
+		save_datum = PointerGetDatum(NULL);		/* keep compiler quiet */
+
 	/*
 	 * We don't need to restore GUC or userid settings on error, because the
 	 * ensuing xact or subxact abort will do that.	The PG_TRY block is only
@@ -968,6 +988,9 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
 	PG_CATCH();
 	{
 		fcinfo->flinfo = save_flinfo;
+		if (function_call_event_hook)
+			(void)(*function_call_event_hook)(fcinfo->flinfo->fn_oid,
+											  FCET_ABORT, save_datum);
 		PG_RE_THROW();
 	}
 	PG_END_TRY();
@@ -978,7 +1001,9 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
 		AtEOXact_GUC(true, save_nestlevel);
 	if (OidIsValid(fcache->userid))
 		SetUserIdAndSecContext(save_userid, save_sec_context);
-
+	if (function_call_event_hook)
+		(void)(*function_call_event_hook)(fcinfo->flinfo->fn_oid,
+										  FCET_END, save_datum);
 	return result;
 }
 
diff --git a/src/include/fmgr.h b/src/include/fmgr.h
index ca5a5ea..a9a8d31 100644
--- a/src/include/fmgr.h
+++ b/src/include/fmgr.h
@@ -544,6 +544,55 @@ extern void **find_rendezvous_variable(const char *varName);
 extern int AggCheckCallContext(FunctionCallInfo fcinfo,
 					MemoryContext *aggcontext);
 
+/*
+ * function_call_event_hook
+ * ------------------------
+ * This hook allows plugin modules to hook events of function calls.
+ * It enables to switch some of its internal state (such as privilege
+ * of the client) during execution of the hooked function.
+ *
+ * This hook takes three arguments: OID of the function, event typee
+ * and its argument depending on the type.
+ *
+ * FCET_BE_HOOKED is used to ask plugins whether it wants to hook this
+ * function call. This event type has no argument. It shall return
+ * BoolGetDatum(true), if a plugin wants to hook this function
+ *
+ * FCET_PREPARE allows plugins to acquire control on the first invocation
+ * time of the function. This event type delivers a pointer to the FmgrInfo.
+ * It shall return an opaque private data that will be delivered to
+ * FCET_START event.
+ *
+ * FCET_START allows plugins to acquire control just before invocation
+ * of the hooked function for each time. This event type delivers the
+ * opaque private data come from FCET_PREPARE. Then, it can also return
+ * an opaque private to inform something for FCET_END and FCET_ABORT.
+ *
+ * FCET_END and FCET_ABORT allow plugins to acquire control just after
+ * invocation of the hooked function for each time. This event type delivers
+ * an opaque private come from FCET_START.
+ */
+typedef enum FunctionCallEventType
+{
+	FCET_BE_HOOKED,
+	FCET_PREPARE,
+	FCET_START,
+	FCET_END,
+	FCET_ABORT,
+} FunctionCallEventType;
+
+typedef Datum (*function_call_event_type)(Oid functionId,
+										  FunctionCallEventType event,
+										  Datum event_arg);
+extern PGDLLIMPORT function_call_event_type function_call_event_hook;
+
+#define IsFunctionCallEventHooked(funcOid)								\
+	(!function_call_event_hook ?										\
+	 false																\
+	 :																	\
+	 DatumGetBool((*function_call_event_hook)(ObjectIdGetDatum(funcOid), \
+											  FCET_BE_HOOKED, 0))		\
+	)
 
 /*
  * !!! OLD INTERFACE !!!
diff --git a/src/test/regress/input/security_label.source b/src/test/regress/input/security_label.source
index 810a721..8a9646c 100644
--- a/src/test/regress/input/security_label.source
+++ b/src/test/regress/input/security_label.source
@@ -37,6 +37,15 @@ SECURITY LABEL ON TABLE seclabel_tbl3 IS 'unclassified';			-- fail
 -- Load dummy external security provider
 LOAD '@libdir@/dummy_secla...@dlsuffix@';
 
+CREATE FUNCTION dummy_client_label() RETURNS text LANGUAGE 'c'
+	AS '@libdir@/dummy_secla...@dlsuffix@', 'dummy_client_label';
+
+CREATE FUNCTION seclabel_regular() RETURNS text LANGUAGE 'sql'
+	AS 'SELECT dummy_client_label()';
+
+CREATE FUNCTION seclabel_trusted() RETURNS text LANGUAGE 'sql'
+    AS 'SELECT dummy_client_label()';
+
 --
 -- Test of SECURITY LABEL statement with a plugin
 --
@@ -70,7 +79,28 @@ SELECT objtype, objname, provider, label FROM pg_seclabels
 SECURITY LABEL ON LANGUAGE plpgsql IS NULL;						-- OK
 SECURITY LABEL ON SCHEMA public IS NULL;						-- OK
 
+-- test for trusted procedures
+SECURITY LABEL ON FUNCTION seclabel_regular() IS 'unclassified';	-- OK
+SECURITY LABEL ON FUNCTION seclabel_trusted() IS 'trusted';			-- OK
+
+-- should be 'unclassified' and 'top secret'
+SELECT seclabel_regular(), seclabel_trusted();
+
+SET SESSION AUTHORIZATION seclabel_user1;
+
+-- should be 'unclassified' and 'secret'
+SELECT seclabel_regular(), seclabel_trusted();
+
+-- be inlined
+EXPLAIN SELECT * FROM seclabel_regular();
+
+-- be not inlined
+EXPLAIN SELECT * FROM seclabel_trusted();
+
 -- clean up objects
+RESET SESSION AUTHORIZATION;
+DROP FUNCTION seclabel_regular();
+DROP FUNCTION seclabel_trusted();
 DROP FUNCTION seclabel_four();
 DROP DOMAIN seclabel_domain;
 DROP VIEW seclabel_view1;
diff --git a/src/test/regress/output/security_label.source b/src/test/regress/output/security_label.source
index 4bc803d..ec2baff 100644
--- a/src/test/regress/output/security_label.source
+++ b/src/test/regress/output/security_label.source
@@ -30,7 +30,13 @@ ERROR:  no security label providers have been loaded
 SECURITY LABEL ON TABLE seclabel_tbl3 IS 'unclassified';			-- fail
 ERROR:  no security label providers have been loaded
 -- Load dummy external security provider
-LOAD '@abs_builddir@/dummy_secla...@dlsuffix@';
+LOAD '@libdir@/dummy_secla...@dlsuffix@';
+CREATE FUNCTION dummy_client_label() RETURNS text LANGUAGE 'c'
+	AS '@libdir@/dummy_secla...@dlsuffix@', 'dummy_client_label';
+CREATE FUNCTION seclabel_regular() RETURNS text LANGUAGE 'sql'
+	AS 'SELECT dummy_client_label()';
+CREATE FUNCTION seclabel_trusted() RETURNS text LANGUAGE 'sql'
+    AS 'SELECT dummy_client_label()';
 --
 -- Test of SECURITY LABEL statement with a plugin
 --
@@ -75,7 +81,42 @@ SELECT objtype, objname, provider, label FROM pg_seclabels
 
 SECURITY LABEL ON LANGUAGE plpgsql IS NULL;						-- OK
 SECURITY LABEL ON SCHEMA public IS NULL;						-- OK
+-- test for trusted procedures
+SECURITY LABEL ON FUNCTION seclabel_regular() IS 'unclassified';	-- OK
+SECURITY LABEL ON FUNCTION seclabel_trusted() IS 'trusted';			-- OK
+-- should be 'unclassified' and 'top secret'
+SELECT seclabel_regular(), seclabel_trusted();
+ seclabel_regular | seclabel_trusted 
+------------------+------------------
+ unclassified     | top secret
+(1 row)
+
+SET SESSION AUTHORIZATION seclabel_user1;
+-- should be 'unclassified' and 'secret'
+SELECT seclabel_regular(), seclabel_trusted();
+ seclabel_regular | seclabel_trusted 
+------------------+------------------
+ unclassified     | secret
+(1 row)
+
+-- be inlined
+EXPLAIN SELECT * FROM seclabel_regular();
+                                       QUERY PLAN                                        
+-----------------------------------------------------------------------------------------
+ Function Scan on dummy_client_label seclabel_regular  (cost=0.00..0.01 rows=1 width=32)
+(1 row)
+
+-- be not inlined
+EXPLAIN SELECT * FROM seclabel_trusted();
+                              QUERY PLAN                              
+----------------------------------------------------------------------
+ Function Scan on seclabel_trusted  (cost=0.25..0.26 rows=1 width=32)
+(1 row)
+
 -- clean up objects
+RESET SESSION AUTHORIZATION;
+DROP FUNCTION seclabel_regular();
+DROP FUNCTION seclabel_trusted();
 DROP FUNCTION seclabel_four();
 DROP DOMAIN seclabel_domain;
 DROP VIEW seclabel_view1;
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to