2015-04-28 19:44 GMT+02:00 Jim Nasby <jim.na...@bluetreble.com>:

> On 4/28/15 1:16 AM, Pavel Stehule wrote:
>
>>
>>         I think it can't be any clearer than the proposed
>>         "plpgsql.display_context_min_messages"
>>
>>
>>     client_min_context. It's doing the same thing as min_messages does,
>>     just for context instead of the message.
>>
>>     Or does this affect client and log the same way?
>>
>>
>> it affect client and log together
>>
>> maybe "min_context"
>>
>
> +1


third variant with GUC plpgsql.min_context

Regards

Pavel


>
> --
> Jim Nasby, Data Architect, Blue Treble Consulting
> Data in Trouble? Get it in Treble! http://BlueTreble.com
>
commit c2f49938f636864234d03994d2f64f8095392d11
Author: Pavel Stehule <pavel.steh...@gooddata.com>
Date:   Sat Apr 25 22:09:28 2015 +0200

    initial implementation of (WITH|WITHOUT) CONTEXT clause to plpgsql RAISE statement.
    
    initial implementation of plpgsql GUC plpgsql.min_context

diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml
index d36acf6..ffc3eb8 100644
--- a/doc/src/sgml/plpgsql.sgml
+++ b/doc/src/sgml/plpgsql.sgml
@@ -3406,10 +3406,10 @@ END LOOP <optional> <replaceable>label</replaceable> </optional>;
     raise errors.
 
 <synopsis>
-RAISE <optional> <replaceable class="parameter">level</replaceable> </optional> '<replaceable class="parameter">format</replaceable>' <optional>, <replaceable class="parameter">expression</replaceable> <optional>, ... </optional></optional> <optional> USING <replaceable class="parameter">option</replaceable> = <replaceable class="parameter">expression</replaceable> <optional>, ... </optional> </optional>;
-RAISE <optional> <replaceable class="parameter">level</replaceable> </optional> <replaceable class="parameter">condition_name</> <optional> USING <replaceable class="parameter">option</replaceable> = <replaceable class="parameter">expression</replaceable> <optional>, ... </optional> </optional>;
-RAISE <optional> <replaceable class="parameter">level</replaceable> </optional> SQLSTATE '<replaceable class="parameter">sqlstate</>' <optional> USING <replaceable class="parameter">option</replaceable> = <replaceable class="parameter">expression</replaceable> <optional>, ... </optional> </optional>;
-RAISE <optional> <replaceable class="parameter">level</replaceable> </optional> USING <replaceable class="parameter">option</replaceable> = <replaceable class="parameter">expression</replaceable> <optional>, ... </optional>;
+RAISE <optional> <replaceable class="parameter">level</replaceable> </optional> <optional> ( WITH | WITHOUT ) CONTEXT </optional> '<replaceable class="parameter">format</replaceable>' <optional>, <replaceable class="parameter">expression</replaceable> <optional>, ... </optional></optional> <optional> USING <replaceable class="parameter">option</replaceable> = <replaceable class="parameter">expression</replaceable> <optional>, ... </optional> </optional>;
+RAISE <optional> <replaceable class="parameter">level</replaceable> </optional> <optional> ( WITH | WITHOUT ) CONTEXT </optional> <replaceable class="parameter">condition_name</> <optional> USING <replaceable class="parameter">option</replaceable> = <replaceable class="parameter">expression</replaceable> <optional>, ... </optional> </optional>;
+RAISE <optional> <replaceable class="parameter">level</replaceable> </optional> <optional> ( WITH | WITHOUT ) CONTEXT </optional> SQLSTATE '<replaceable class="parameter">sqlstate</>' <optional> USING <replaceable class="parameter">option</replaceable> = <replaceable class="parameter">expression</replaceable> <optional>, ... </optional> </optional>;
+RAISE <optional> <replaceable class="parameter">level</replaceable> </optional> <optional> ( WITH | WITHOUT ) CONTEXT </optional> USING <replaceable class="parameter">option</replaceable> = <replaceable class="parameter">expression</replaceable> <optional>, ... </optional>;
 RAISE ;
 </synopsis>
 
@@ -3431,6 +3431,18 @@ RAISE ;
    </para>
 
    <para>
+    The options <literal>WITH CONTEXT</literal> or <literal>WITHOUT CONTEXT</literal>
+    can enforce or suppress context information related to error or notice. This possibility
+    can be forced by settings of configuration parameter <literal>plpgsql.min_context</>.
+    This allows same values like <replaceable class="parameter">level</replaceable> option plus
+    value <literal>none</literal> that is a default. When it is changed, then all errors and notices
+    with higher than specified severity are raised with context info.
+<programlisting>
+RAISE NOTICE WITH CONTEXT 'This message will have a context';
+</programlisting>
+   </para>
+
+   <para>
     After <replaceable class="parameter">level</replaceable> if any,
     you can write a <replaceable class="parameter">format</replaceable>
     (which must be a simple string literal, not an expression).  The
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index deefb1f..eaee5a7 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -2921,6 +2921,7 @@ exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
 	char	   *err_table = NULL;
 	char	   *err_schema = NULL;
 	ListCell   *lc;
+	bool			hide_ctx = true;		/* suppress context by default */
 
 	/* RAISE with no parameters: re-throw current exception */
 	if (stmt->condname == NULL && stmt->message == NULL &&
@@ -3080,10 +3081,16 @@ exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
 			err_message = pstrdup(unpack_sql_state(err_code));
 	}
 
-	/*
-	 * Throw the error (may or may not come back)
-	 */
-	estate->err_text = raise_skip_msg;	/* suppress traceback of raise */
+	if (stmt->context_info == PLPGSQL_CONTEXT_DISPLAY)
+		hide_ctx = false;
+	else if (stmt->context_info == PLPGSQL_CONTEXT_DEFAULT)
+	{
+		if (plpgsql_min_context != PLPGSQL_MIN_CONTEXT_SUPPRESS)
+			hide_ctx = stmt->elog_level < plpgsql_min_context;
+	}
+
+	if (hide_ctx)
+		estate->err_text = raise_skip_msg;
 
 	ereport(stmt->elog_level,
 			(err_code ? errcode(err_code) : 0,
@@ -3099,7 +3106,8 @@ exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
 			 (err_table != NULL) ?
 			 err_generic_string(PG_DIAG_TABLE_NAME, err_table) : 0,
 			 (err_schema != NULL) ?
-			 err_generic_string(PG_DIAG_SCHEMA_NAME, err_schema) : 0));
+			 err_generic_string(PG_DIAG_SCHEMA_NAME, err_schema) : 0,
+			 errhidecontext(hide_ctx)));
 
 	estate->err_text = NULL;	/* un-suppress... */
 
diff --git a/src/pl/plpgsql/src/pl_gram.y b/src/pl/plpgsql/src/pl_gram.y
index 4026e41..48914a7 100644
--- a/src/pl/plpgsql/src/pl_gram.y
+++ b/src/pl/plpgsql/src/pl_gram.y
@@ -259,6 +259,7 @@ static	void			check_raise_parameters(PLpgSQL_stmt_raise *stmt);
 %token <keyword>	K_CONSTANT
 %token <keyword>	K_CONSTRAINT
 %token <keyword>	K_CONSTRAINT_NAME
+%token <keyword>	K_CONTEXT
 %token <keyword>	K_CONTINUE
 %token <keyword>	K_CURRENT
 %token <keyword>	K_CURSOR
@@ -341,6 +342,8 @@ static	void			check_raise_parameters(PLpgSQL_stmt_raise *stmt);
 %token <keyword>	K_WARNING
 %token <keyword>	K_WHEN
 %token <keyword>	K_WHILE
+%token <keyword>	K_WITH
+%token <keyword>	K_WITHOUT
 
 %%
 
@@ -1716,6 +1719,7 @@ stmt_raise		: K_RAISE
 						new->cmd_type	= PLPGSQL_STMT_RAISE;
 						new->lineno		= plpgsql_location_to_lineno(@1);
 						new->elog_level = ERROR;	/* default */
+						new->context_info = PLPGSQL_CONTEXT_DEFAULT;
 						new->condname	= NULL;
 						new->message	= NULL;
 						new->params		= NIL;
@@ -1773,6 +1777,21 @@ stmt_raise		: K_RAISE
 							if (tok == 0)
 								yyerror("unexpected end of function definition");
 
+							/* Optional choose about including context */
+							if (tok == K_WITH || tok == K_WITHOUT)
+							{
+								if (tok == K_WITH)
+									new->context_info = PLPGSQL_CONTEXT_DISPLAY;
+								else
+									new->context_info = PLPGSQL_CONTEXT_SUPPRESS;
+							
+								/* keyword CONTEXT is required */
+								if (yylex() != K_CONTEXT)
+									yyerror("expected CONTEXT");
+
+								tok = yylex();
+							}
+
 							/*
 							 * Next we can have a condition name, or
 							 * equivalently SQLSTATE 'xxxxx', or a string
@@ -2350,6 +2369,7 @@ unreserved_keyword	:
 				| K_CONSTANT
 				| K_CONSTRAINT
 				| K_CONSTRAINT_NAME
+				| K_CONTEXT
 				| K_CONTINUE
 				| K_CURRENT
 				| K_CURSOR
@@ -2412,6 +2432,8 @@ unreserved_keyword	:
 				| K_USE_VARIABLE
 				| K_VARIABLE_CONFLICT
 				| K_WARNING
+				| K_WITH
+				| K_WITHOUT
 				;
 
 %%
diff --git a/src/pl/plpgsql/src/pl_handler.c b/src/pl/plpgsql/src/pl_handler.c
index 266c314..2d05cf6 100644
--- a/src/pl/plpgsql/src/pl_handler.c
+++ b/src/pl/plpgsql/src/pl_handler.c
@@ -40,6 +40,17 @@ static const struct config_enum_entry variable_conflict_options[] = {
 	{NULL, 0, false}
 };
 
+static const struct config_enum_entry min_context_options[] = {
+	{"none", PLPGSQL_MIN_CONTEXT_SUPPRESS},
+	{"exception", ERROR},
+	{"warning", WARNING},
+	{"notice", NOTICE},
+	{"info", INFO},
+	{"log", LOG},
+	{"debug", DEBUG1},
+	{NULL, 0, false}
+};
+
 int			plpgsql_variable_conflict = PLPGSQL_RESOLVE_ERROR;
 
 bool		plpgsql_print_strict_params = false;
@@ -51,6 +62,8 @@ char	   *plpgsql_extra_errors_string = NULL;
 int			plpgsql_extra_warnings;
 int			plpgsql_extra_errors;
 
+int			plpgsql_min_context = PLPGSQL_MIN_CONTEXT_SUPPRESS;
+
 /* Hook for plugins */
 PLpgSQL_plugin **plugin_ptr = NULL;
 
@@ -154,6 +167,15 @@ _PG_init(void)
 							 PGC_SUSET, 0,
 							 NULL, NULL, NULL);
 
+	DefineCustomEnumVariable("plpgsql.min_context",
+							 gettext_noop("Sets minimal level of messages with context information."),
+							 NULL,
+							 &plpgsql_min_context,
+							 PLPGSQL_MIN_CONTEXT_SUPPRESS,
+							 min_context_options,
+							 PGC_SUSET, 0,
+							 NULL, NULL, NULL);
+
 	DefineCustomBoolVariable("plpgsql.print_strict_params",
 							 gettext_noop("Print information about parameters in the DETAIL part of the error messages generated on INTO ... STRICT failures."),
 							 NULL,
diff --git a/src/pl/plpgsql/src/pl_scanner.c b/src/pl/plpgsql/src/pl_scanner.c
index 683fdab..973cab8 100644
--- a/src/pl/plpgsql/src/pl_scanner.c
+++ b/src/pl/plpgsql/src/pl_scanner.c
@@ -107,6 +107,7 @@ static const ScanKeyword unreserved_keywords[] = {
 	PG_KEYWORD("constant", K_CONSTANT, UNRESERVED_KEYWORD)
 	PG_KEYWORD("constraint", K_CONSTRAINT, UNRESERVED_KEYWORD)
 	PG_KEYWORD("constraint_name", K_CONSTRAINT_NAME, UNRESERVED_KEYWORD)
+	PG_KEYWORD("context", K_CONTEXT, UNRESERVED_KEYWORD)
 	PG_KEYWORD("continue", K_CONTINUE, UNRESERVED_KEYWORD)
 	PG_KEYWORD("current", K_CURRENT, UNRESERVED_KEYWORD)
 	PG_KEYWORD("cursor", K_CURSOR, UNRESERVED_KEYWORD)
@@ -170,6 +171,8 @@ static const ScanKeyword unreserved_keywords[] = {
 	PG_KEYWORD("use_variable", K_USE_VARIABLE, UNRESERVED_KEYWORD)
 	PG_KEYWORD("variable_conflict", K_VARIABLE_CONFLICT, UNRESERVED_KEYWORD)
 	PG_KEYWORD("warning", K_WARNING, UNRESERVED_KEYWORD)
+	PG_KEYWORD("with", K_WITH, UNRESERVED_KEYWORD)
+	PG_KEYWORD("without", K_WITHOUT, UNRESERVED_KEYWORD)
 };
 
 static const int num_unreserved_keywords = lengthof(unreserved_keywords);
diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h
index bec773a..269fec3 100644
--- a/src/pl/plpgsql/src/plpgsql.h
+++ b/src/pl/plpgsql/src/plpgsql.h
@@ -168,6 +168,18 @@ typedef enum
 } PLpgSQL_resolve_option;
 
 
+/* --------
+ * Manipulation with context of exception
+ * --------
+ */
+enum
+{
+	PLPGSQL_CONTEXT_DISPLAY,
+	PLPGSQL_CONTEXT_SUPPRESS,
+	PLPGSQL_CONTEXT_DEFAULT
+};
+
+
 /**********************************************************************
  * Node and structure definitions
  **********************************************************************/
@@ -619,6 +631,7 @@ typedef struct
 	int			cmd_type;
 	int			lineno;
 	int			elog_level;
+	int			context_info;
 	char	   *condname;		/* condition name, SQLSTATE, or NULL */
 	char	   *message;		/* old-style message format literal, or NULL */
 	List	   *params;			/* list of expressions for old-style message */
@@ -922,6 +935,10 @@ extern MemoryContext compile_tmp_cxt;
 
 extern PLpgSQL_plugin **plugin_ptr;
 
+#define PLPGSQL_MIN_CONTEXT_SUPPRESS		0
+
+extern int plpgsql_min_context;
+
 /**********************************************************************
  * Function declarations
  **********************************************************************/
diff --git a/src/test/regress/expected/plpgsql.out b/src/test/regress/expected/plpgsql.out
index 78e5a85..4f74f9f 100644
--- a/src/test/regress/expected/plpgsql.out
+++ b/src/test/regress/expected/plpgsql.out
@@ -5426,3 +5426,51 @@ end;
 $$;
 ERROR:  unhandled assertion
 CONTEXT:  PL/pgSQL function inline_code_block line 3 at ASSERT
+-- context is not displayed by default
+do $$
+begin
+  raise notice 'hello';
+end;
+$$;
+NOTICE:  hello
+do $$
+begin
+  raise exception 'hello';
+end;
+$$;
+ERROR:  hello
+--possibility to enforce context message displaying
+do $$
+begin
+  raise notice with context 'hello';
+end;
+$$;
+NOTICE:  hello
+CONTEXT:  PL/pgSQL function inline_code_block line 3 at RAISE
+do $$
+begin
+  raise exception with context 'hello';
+end;
+$$;
+ERROR:  hello
+CONTEXT:  PL/pgSQL function inline_code_block line 3 at RAISE
+set plpgsql.min_context = 'notice';
+do $$
+begin
+  raise notice 'some notice';
+  raise exception 'some exception';
+end;
+$$;
+NOTICE:  some notice
+CONTEXT:  PL/pgSQL function inline_code_block line 3 at RAISE
+ERROR:  some exception
+CONTEXT:  PL/pgSQL function inline_code_block line 4 at RAISE
+-- possibility to suppress default
+do $$
+begin
+  raise notice without context 'some notice';
+  raise exception without context 'some exception';
+end;
+$$;
+NOTICE:  some notice
+ERROR:  some exception
diff --git a/src/test/regress/sql/plpgsql.sql b/src/test/regress/sql/plpgsql.sql
index e19e415..e23a74a 100644
--- a/src/test/regress/sql/plpgsql.sql
+++ b/src/test/regress/sql/plpgsql.sql
@@ -4265,3 +4265,47 @@ exception when others then
   null; -- do nothing
 end;
 $$;
+
+-- context is not displayed by default
+do $$
+begin
+  raise notice 'hello';
+end;
+$$;
+
+do $$
+begin
+  raise exception 'hello';
+end;
+$$;
+
+--possibility to enforce context message displaying
+do $$
+begin
+  raise notice with context 'hello';
+end;
+$$;
+
+do $$
+begin
+  raise exception with context 'hello';
+end;
+$$;
+
+set plpgsql.min_context = 'notice';
+do $$
+begin
+  raise notice 'some notice';
+  raise exception 'some exception';
+end;
+$$;
+
+-- possibility to suppress default
+do $$
+begin
+  raise notice without context 'some notice';
+  raise exception without context 'some exception';
+end;
+$$;
+
+
-- 
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