2015-01-26 22:34 GMT+01:00 Jim Nasby <jim.na...@bluetreble.com>:

> On 1/22/15 2:01 PM, Pavel Stehule wrote:
>
>>
>>         * I would to simplify a behave of evaluating of message
>> expression - probably I disallow NULL there.
>>
>>
>>     Well, the only thing I could see you doing there is throwing a
>> different error if the hint is null. I don't see that as an improvement.
>> I'd just leave it as-is.
>>
>>
>> I enabled a NULL - but enforced a WARNING before.
>>
>
> I don't see the separate warning as being helpful. I'd just do something
> like
>
> +                                (err_hint != NULL) ? errhint("%s",
> err_hint) : errhint("Message attached to failed assertion is null") ));
>

done


>
> There should also be a test case for a NULL message.
>

is there, if I understand well

Regards

Pavel


>
>          * GUC enable_asserts will be supported
>>
>>
>>     That would be good. Would that allow for enabling/disabling on a
>> per-function basis too?
>>
>>
>> sure - there is only question if we develop a #option
>> enable|disable_asserts. I have no string idea.
>>
>
> The option would be nice, but I don't think it's strictly necessary. The
> big thing is being able to control this on a per-function basis (which I
> think you can do with ALTER FUNCTION SET?)
>
> --
> Jim Nasby, Data Architect, Blue Treble Consulting
> Data in Trouble? Get it in Treble! http://BlueTreble.com
>
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
new file mode 100644
index 6bcb106..5663983
*** a/doc/src/sgml/config.sgml
--- b/doc/src/sgml/config.sgml
*************** dynamic_library_path = 'C:\tools\postgre
*** 6912,6917 ****
--- 6912,6931 ----
  
      <variablelist>
  
+      <varlistentry id="guc-enable-user-asserts" xreflabel="enable_user_asserts">
+       <term><varname>enable_user_asserts</varname> (<type>boolean</type>)
+       <indexterm>
+        <primary><varname>enable_user_asserts</> configuration parameter</primary>
+       </indexterm>
+       </term>
+       <listitem>
+        <para>
+         If true, any user assertions are evaluated.  By default, this 
+         is set to true.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
       <varlistentry id="guc-exit-on-error" xreflabel="exit_on_error">
        <term><varname>exit_on_error</varname> (<type>boolean</type>)
        <indexterm>
diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml
new file mode 100644
index 69a0885..26f7eba
*** a/doc/src/sgml/plpgsql.sgml
--- b/doc/src/sgml/plpgsql.sgml
*************** END LOOP <optional> <replaceable>label</
*** 3372,3377 ****
--- 3372,3380 ----
    <sect1 id="plpgsql-errors-and-messages">
     <title>Errors and Messages</title>
  
+   <sect2 id="plpgsql-statements-raise">
+     <title>RAISE statement</title>
+ 
     <indexterm>
      <primary>RAISE</primary>
     </indexterm>
*************** RAISE unique_violation USING MESSAGE = '
*** 3564,3570 ****
--- 3567,3599 ----
       the whole category.
      </para>
     </note>
+   </sect2>
  
+   <sect2 id="plpgsql-statements-assert">
+     <title>ASSERT statement</title>
+ 
+    <indexterm>
+     <primary>ASSERT</primary>
+    </indexterm>
+ 
+    <indexterm>
+     <primary>assertions</primary>
+     <secondary>in PL/pgSQL</secondary>
+    </indexterm>
+ 
+    <para>
+     Use the <command>ASSERT</command> statement to ensure so expected
+     predicate is allways true. If the predicate is false or is null,
+     then a assertion exception is raised.
+ 
+ <synopsis>
+ ASSERT <replaceable class="parameter">expression</replaceable> <optional>, <replaceable class="parameter">message expression</replaceable> </optional>;
+ </synopsis>
+ 
+     The user assertions can be enabled or disabled by the 
+     <xref linkend="guc-enable-user-asserts">.
+    </para>
+   </sect2>
   </sect1>
  
   <sect1 id="plpgsql-trigger">
diff --git a/src/backend/utils/errcodes.txt b/src/backend/utils/errcodes.txt
new file mode 100644
index 28c8c40..da12428
*** a/src/backend/utils/errcodes.txt
--- b/src/backend/utils/errcodes.txt
*************** P0000    E    ERRCODE_PLPGSQL_ERROR
*** 454,459 ****
--- 454,460 ----
  P0001    E    ERRCODE_RAISE_EXCEPTION                                        raise_exception
  P0002    E    ERRCODE_NO_DATA_FOUND                                          no_data_found
  P0003    E    ERRCODE_TOO_MANY_ROWS                                          too_many_rows
+ P0004    E    ERRCODE_ASSERT_EXCEPTION                                       assert_exception
  
  Section: Class XX - Internal Error
  
diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c
new file mode 100644
index c35867b..cd55e94
*** a/src/backend/utils/init/globals.c
--- b/src/backend/utils/init/globals.c
*************** bool		IsBinaryUpgrade = false;
*** 99,104 ****
--- 99,105 ----
  bool		IsBackgroundWorker = false;
  
  bool		ExitOnAnyError = false;
+ bool		enable_user_asserts = true;
  
  int			DateStyle = USE_ISO_DATES;
  int			DateOrder = DATEORDER_MDY;
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
new file mode 100644
index f6df077..b3a2660
*** a/src/backend/utils/misc/guc.c
--- b/src/backend/utils/misc/guc.c
*************** static struct config_bool ConfigureNames
*** 980,985 ****
--- 980,994 ----
  	},
  
  	{
+ 		{"enable_user_asserts", PGC_USERSET, ERROR_HANDLING_OPTIONS,
+ 			gettext_noop("Enable user asserts checks."),
+ 			NULL
+ 		},
+ 		&enable_user_asserts,
+ 		true,
+ 		NULL, NULL, NULL
+ 	},
+ 	{
  		{"exit_on_error", PGC_USERSET, ERROR_HANDLING_OPTIONS,
  			gettext_noop("Terminate session on any error."),
  			NULL
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
new file mode 100644
index 6e33a17..fab3e8a
*** a/src/include/miscadmin.h
--- b/src/include/miscadmin.h
*************** extern bool IsBackgroundWorker;
*** 137,142 ****
--- 137,143 ----
  extern PGDLLIMPORT bool IsBinaryUpgrade;
  
  extern bool ExitOnAnyError;
+ extern bool enable_user_asserts;
  
  extern PGDLLIMPORT char *DataDir;
  
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
new file mode 100644
index ae5421f..54e60ab
*** a/src/pl/plpgsql/src/pl_exec.c
--- b/src/pl/plpgsql/src/pl_exec.c
*************** static int exec_stmt_return_query(PLpgSQ
*** 136,141 ****
--- 136,143 ----
  					   PLpgSQL_stmt_return_query *stmt);
  static int exec_stmt_raise(PLpgSQL_execstate *estate,
  				PLpgSQL_stmt_raise *stmt);
+ static int exec_stmt_assert(PLpgSQL_execstate *estate,
+ 				PLpgSQL_stmt_assert *stmt);
  static int exec_stmt_execsql(PLpgSQL_execstate *estate,
  				  PLpgSQL_stmt_execsql *stmt);
  static int exec_stmt_dynexecute(PLpgSQL_execstate *estate,
*************** exception_matches_conditions(ErrorData *
*** 1013,1024 ****
  		int			sqlerrstate = cond->sqlerrstate;
  
  		/*
! 		 * OTHERS matches everything *except* query-canceled; if you're
! 		 * foolish enough, you can match that explicitly.
  		 */
  		if (sqlerrstate == 0)
  		{
! 			if (edata->sqlerrcode != ERRCODE_QUERY_CANCELED)
  				return true;
  		}
  		/* Exact match? */
--- 1015,1028 ----
  		int			sqlerrstate = cond->sqlerrstate;
  
  		/*
! 		 * OTHERS matches everything *except* query-canceled and
! 		 * assert-exception. if you're foolish enough, you can 
! 		 * match that explicitly.
  		 */
  		if (sqlerrstate == 0)
  		{
! 			if (edata->sqlerrcode != ERRCODE_QUERY_CANCELED &&
! 				 edata->sqlerrcode != ERRCODE_ASSERT_EXCEPTION)
  				return true;
  		}
  		/* Exact match? */
*************** exec_stmt(PLpgSQL_execstate *estate, PLp
*** 1465,1470 ****
--- 1469,1478 ----
  			rc = exec_stmt_raise(estate, (PLpgSQL_stmt_raise *) stmt);
  			break;
  
+ 		case PLPGSQL_STMT_ASSERT:
+ 			rc = exec_stmt_assert(estate, (PLpgSQL_stmt_assert *) stmt);
+ 			break;
+ 
  		case PLPGSQL_STMT_EXECSQL:
  			rc = exec_stmt_execsql(estate, (PLpgSQL_stmt_execsql *) stmt);
  			break;
*************** exec_stmt_raise(PLpgSQL_execstate *estat
*** 3091,3096 ****
--- 3099,3160 ----
  	return PLPGSQL_RC_OK;
  }
  
+ /* ----------
+  * exec_stmt_assert			Assert statement
+  * ----------
+  */
+ static int
+ exec_stmt_assert(PLpgSQL_execstate *estate, PLpgSQL_stmt_assert *stmt)
+ {
+ 	bool		value;
+ 	bool		isnull;
+ 
+ 	/* do nothing when asserts are not enabled */
+ 	if (!enable_user_asserts)
+ 		return PLPGSQL_RC_OK;
+ 
+ 	value = exec_eval_boolean(estate, stmt->cond, &isnull);
+ 	exec_eval_cleanup(estate);
+ 
+ 	if (isnull || !value)
+ 	{
+ 		StringInfoData		ds;
+ 		char *err_hint = NULL;
+ 
+ 		initStringInfo(&ds);
+ 
+ 		if (isnull)
+ 			appendStringInfo(&ds, "\"%s\" is null", stmt->cond->query + 7);
+ 		else
+ 			appendStringInfo(&ds, "\"%s\" is false", stmt->cond->query + 7);
+ 
+ 		if (stmt->hint != NULL)
+ 		{
+ 			Oid			expr_typeid;
+ 			bool			expr_isnull;
+ 			Datum			expr_val;
+ 
+ 			expr_val = exec_eval_expr(estate, stmt->hint,
+ 									 &expr_isnull,
+ 									 &expr_typeid);
+ 
+ 			if (!expr_isnull)
+ 				err_hint = pstrdup(convert_value_to_string(estate, expr_val, expr_typeid));
+ 			else
+ 				err_hint = pstrdup("Message attached to failed assertion is null");
+ 
+ 			exec_eval_cleanup(estate);
+ 		}
+ 
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_ASSERT_EXCEPTION),
+ 				 errmsg("Assertion failure"),
+ 				 errdetail("%s", ds.data),
+ 				 (err_hint != NULL) ? errhint("%s", err_hint) : 0));
+ 	}
+ 
+ 	return PLPGSQL_RC_OK;
+ }
  
  /* ----------
   * Initialize a mostly empty execution state
diff --git a/src/pl/plpgsql/src/pl_funcs.c b/src/pl/plpgsql/src/pl_funcs.c
new file mode 100644
index 1dcea73..2b8d3b7
*** a/src/pl/plpgsql/src/pl_funcs.c
--- b/src/pl/plpgsql/src/pl_funcs.c
*************** plpgsql_stmt_typename(PLpgSQL_stmt *stmt
*** 244,249 ****
--- 244,251 ----
  			return "RETURN QUERY";
  		case PLPGSQL_STMT_RAISE:
  			return "RAISE";
+ 		case PLPGSQL_STMT_ASSERT:
+ 			return "ASSERT";
  		case PLPGSQL_STMT_EXECSQL:
  			return _("SQL statement");
  		case PLPGSQL_STMT_DYNEXECUTE:
*************** static void free_return(PLpgSQL_stmt_ret
*** 330,335 ****
--- 332,338 ----
  static void free_return_next(PLpgSQL_stmt_return_next *stmt);
  static void free_return_query(PLpgSQL_stmt_return_query *stmt);
  static void free_raise(PLpgSQL_stmt_raise *stmt);
+ static void free_assert(PLpgSQL_stmt_assert *stmt);
  static void free_execsql(PLpgSQL_stmt_execsql *stmt);
  static void free_dynexecute(PLpgSQL_stmt_dynexecute *stmt);
  static void free_dynfors(PLpgSQL_stmt_dynfors *stmt);
*************** free_stmt(PLpgSQL_stmt *stmt)
*** 391,396 ****
--- 394,402 ----
  		case PLPGSQL_STMT_RAISE:
  			free_raise((PLpgSQL_stmt_raise *) stmt);
  			break;
+ 		case PLPGSQL_STMT_ASSERT:
+ 			free_assert((PLpgSQL_stmt_assert *) stmt);
+ 			break;
  		case PLPGSQL_STMT_EXECSQL:
  			free_execsql((PLpgSQL_stmt_execsql *) stmt);
  			break;
*************** free_raise(PLpgSQL_stmt_raise *stmt)
*** 611,616 ****
--- 617,629 ----
  }
  
  static void
+ free_assert(PLpgSQL_stmt_assert *stmt)
+ {
+ 	free_expr(stmt->cond);
+ 	free_expr(stmt->hint);
+ }
+ 
+ static void
  free_execsql(PLpgSQL_stmt_execsql *stmt)
  {
  	free_expr(stmt->sqlstmt);
*************** static void dump_return(PLpgSQL_stmt_ret
*** 732,737 ****
--- 745,751 ----
  static void dump_return_next(PLpgSQL_stmt_return_next *stmt);
  static void dump_return_query(PLpgSQL_stmt_return_query *stmt);
  static void dump_raise(PLpgSQL_stmt_raise *stmt);
+ static void dump_assert(PLpgSQL_stmt_assert *stmt);
  static void dump_execsql(PLpgSQL_stmt_execsql *stmt);
  static void dump_dynexecute(PLpgSQL_stmt_dynexecute *stmt);
  static void dump_dynfors(PLpgSQL_stmt_dynfors *stmt);
*************** dump_stmt(PLpgSQL_stmt *stmt)
*** 804,809 ****
--- 818,826 ----
  		case PLPGSQL_STMT_RAISE:
  			dump_raise((PLpgSQL_stmt_raise *) stmt);
  			break;
+ 		case PLPGSQL_STMT_ASSERT:
+ 			dump_assert((PLpgSQL_stmt_assert *) stmt);
+ 			break;
  		case PLPGSQL_STMT_EXECSQL:
  			dump_execsql((PLpgSQL_stmt_execsql *) stmt);
  			break;
*************** dump_raise(PLpgSQL_stmt_raise *stmt)
*** 1352,1357 ****
--- 1369,1392 ----
  	}
  	dump_indent -= 2;
  }
+ 
+ static void
+ dump_assert(PLpgSQL_stmt_assert *stmt)
+ {
+ 	dump_ind();
+ 	printf("ASSERT ");
+ 	dump_expr(stmt->cond);
+ 	printf("\n");
+ 
+ 	dump_indent += 2;
+ 	if (stmt->hint != NULL)
+ 	{
+ 		dump_ind();
+ 		printf("    HINT = ");
+ 		dump_expr(stmt->hint);
+ 	}
+ 	dump_indent -= 2;
+ }
  
  static void
  dump_execsql(PLpgSQL_stmt_execsql *stmt)
diff --git a/src/pl/plpgsql/src/pl_gram.y b/src/pl/plpgsql/src/pl_gram.y
new file mode 100644
index 590aac5..8d87255
*** a/src/pl/plpgsql/src/pl_gram.y
--- b/src/pl/plpgsql/src/pl_gram.y
*************** static	void			check_raise_parameters(PLp
*** 192,198 ****
  %type <loop_body>	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
  %type <stmt>	stmt_dynexecute stmt_for stmt_perform stmt_getdiag
  %type <stmt>	stmt_open stmt_fetch stmt_move stmt_close stmt_null
  %type <stmt>	stmt_case stmt_foreach_a
--- 192,198 ----
  %type <loop_body>	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_assert stmt_execsql
  %type <stmt>	stmt_dynexecute stmt_for stmt_perform stmt_getdiag
  %type <stmt>	stmt_open stmt_fetch stmt_move stmt_close stmt_null
  %type <stmt>	stmt_case stmt_foreach_a
*************** static	void			check_raise_parameters(PLp
*** 246,251 ****
--- 246,252 ----
  %token <keyword>	K_ALIAS
  %token <keyword>	K_ALL
  %token <keyword>	K_ARRAY
+ %token <keyword>	K_ASSERT
  %token <keyword>	K_BACKWARD
  %token <keyword>	K_BEGIN
  %token <keyword>	K_BY
*************** proc_stmt		: pl_block ';'
*** 870,875 ****
--- 871,878 ----
  						{ $$ = $1; }
  				| stmt_raise
  						{ $$ = $1; }
+ 				| stmt_assert
+ 						{ $$ = $1; }
  				| stmt_execsql
  						{ $$ = $1; }
  				| stmt_dynexecute
*************** stmt_raise		: K_RAISE
*** 1846,1851 ****
--- 1849,1885 ----
  					}
  				;
  
+ stmt_assert:		 K_ASSERT
+ 					{
+ 						PLpgSQL_stmt_assert *new;
+ 						int	endtoken;
+ 
+ 						new = palloc(sizeof(PLpgSQL_stmt_assert));
+ 
+ 						new->cmd_type = PLPGSQL_STMT_ASSERT;
+ 						new->lineno = plpgsql_location_to_lineno(@1);
+ 
+ 						new->cond = read_sql_construct(',', ';', 0,
+ 											  ", or ;",
+ 											  "SELECT ",
+ 											  true, true, true,
+ 											  NULL, &endtoken);
+ 
+ 						if (endtoken == ',')
+ 						{
+ 							new->hint = read_sql_construct(';', 0, 0,
+ 												  ";",
+ 												  "SELECT ",
+ 												  true, true, true,
+ 												  NULL, NULL);
+ 						}
+ 						else
+ 							new->hint = NULL;
+ 
+ 						$$ = (PLpgSQL_stmt *) new;
+ 					}
+ 				;
+ 
  loop_body		: proc_sect K_END K_LOOP opt_label ';'
  					{
  						$$.stmts = $1;
diff --git a/src/pl/plpgsql/src/pl_scanner.c b/src/pl/plpgsql/src/pl_scanner.c
new file mode 100644
index ec08b02..8af7d41
*** a/src/pl/plpgsql/src/pl_scanner.c
--- b/src/pl/plpgsql/src/pl_scanner.c
*************** static const ScanKeyword unreserved_keyw
*** 98,103 ****
--- 98,104 ----
  	PG_KEYWORD("absolute", K_ABSOLUTE, UNRESERVED_KEYWORD)
  	PG_KEYWORD("alias", K_ALIAS, UNRESERVED_KEYWORD)
  	PG_KEYWORD("array", K_ARRAY, UNRESERVED_KEYWORD)
+ 	PG_KEYWORD("assert", K_ASSERT, UNRESERVED_KEYWORD)
  	PG_KEYWORD("backward", K_BACKWARD, UNRESERVED_KEYWORD)
  	PG_KEYWORD("close", K_CLOSE, UNRESERVED_KEYWORD)
  	PG_KEYWORD("collate", K_COLLATE, UNRESERVED_KEYWORD)
diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h
new file mode 100644
index 00f2f77..b909865
*** a/src/pl/plpgsql/src/plpgsql.h
--- b/src/pl/plpgsql/src/plpgsql.h
*************** enum
*** 79,84 ****
--- 79,85 ----
  enum PLpgSQL_stmt_types
  {
  	PLPGSQL_STMT_BLOCK,
+ 	PLPGSQL_STMT_ASSERT,
  	PLPGSQL_STMT_ASSIGN,
  	PLPGSQL_STMT_IF,
  	PLPGSQL_STMT_CASE,
*************** typedef struct
*** 631,636 ****
--- 632,645 ----
  
  
  typedef struct
+ {								/* ASSERT statement			*/
+ 	int			cmd_type;
+ 	int			lineno;
+ 	PLpgSQL_expr *cond;
+ 	PLpgSQL_expr *hint;
+ } PLpgSQL_stmt_assert;
+ 
+ typedef struct
  {								/* Generic SQL statement to execute */
  	int			cmd_type;
  	int			lineno;
diff --git a/src/test/regress/expected/plpgsql.out b/src/test/regress/expected/plpgsql.out
new file mode 100644
index daf3447..04e2b74
*** a/src/test/regress/expected/plpgsql.out
--- b/src/test/regress/expected/plpgsql.out
*************** NOTICE:  outer_func() done
*** 5365,5367 ****
--- 5365,5427 ----
  drop function outer_outer_func(int);
  drop function outer_func(int);
  drop function inner_func(int);
+ -- ensure enabled user assertions
+ set enable_user_asserts = on;
+ -- should be ok
+ do $$
+ begin 
+   assert 1=1;
+ end;
+ $$;
+ -- should fails
+ do $$
+ begin
+   assert 1=0;
+ end;
+ $$;
+ ERROR:  Assertion failure
+ DETAIL:  "1=0" is false
+ CONTEXT:  PL/pgSQL function inline_code_block line 3 at ASSERT
+ -- should fails
+ do $$
+ begin
+   assert NULL;
+ end;
+ $$;
+ ERROR:  Assertion failure
+ DETAIL:  "NULL" is null
+ CONTEXT:  PL/pgSQL function inline_code_block line 3 at ASSERT
+ -- should fails
+ -- test of warning, when message related to a assert is null
+ do $$
+ begin
+   assert 1=0, NULL;
+ end;
+ $$;
+ ERROR:  Assertion failure
+ DETAIL:  "1=0" is false
+ HINT:  Message attached to failed assertion is null
+ CONTEXT:  PL/pgSQL function inline_code_block line 3 at ASSERT
+ -- should fails
+ do $$
+ declare var text := 'some value';
+ begin
+   assert 1=0, format('content of var: "%s"', var);
+ end;
+ $$;
+ ERROR:  Assertion failure
+ DETAIL:  "1=0" is false
+ HINT:  content of var: "some value"
+ CONTEXT:  PL/pgSQL function inline_code_block line 4 at ASSERT
+ -- assertions is unhandled
+ do $$
+ begin
+   assert 1=0, 'unhandled assert';
+ exception when others then
+   null; -- do nothing
+ end;
+ $$ language plpgsql;
+ ERROR:  Assertion failure
+ DETAIL:  "1=0" is false
+ HINT:  unhandled assert
+ CONTEXT:  PL/pgSQL function inline_code_block line 3 at ASSERT
diff --git a/src/test/regress/expected/rangefuncs.out b/src/test/regress/expected/rangefuncs.out
new file mode 100644
index 7991e99..80e0b4b
*** a/src/test/regress/expected/rangefuncs.out
--- b/src/test/regress/expected/rangefuncs.out
*************** SELECT name, setting FROM pg_settings WH
*** 12,18 ****
   enable_seqscan       | on
   enable_sort          | on
   enable_tidscan       | on
! (11 rows)
  
  CREATE TABLE foo2(fooid int, f2 int);
  INSERT INTO foo2 VALUES(1, 11);
--- 12,19 ----
   enable_seqscan       | on
   enable_sort          | on
   enable_tidscan       | on
!  enable_user_asserts  | on
! (12 rows)
  
  CREATE TABLE foo2(fooid int, f2 int);
  INSERT INTO foo2 VALUES(1, 11);
diff --git a/src/test/regress/sql/plpgsql.sql b/src/test/regress/sql/plpgsql.sql
new file mode 100644
index a0840c9..aece91b
*** a/src/test/regress/sql/plpgsql.sql
--- b/src/test/regress/sql/plpgsql.sql
*************** select outer_outer_func(20);
*** 4209,4211 ****
--- 4209,4260 ----
  drop function outer_outer_func(int);
  drop function outer_func(int);
  drop function inner_func(int);
+ 
+ -- ensure enabled user assertions
+ set enable_user_asserts = on;
+ 
+ -- should be ok
+ do $$
+ begin 
+   assert 1=1;
+ end;
+ $$;
+ 
+ -- should fails
+ do $$
+ begin
+   assert 1=0;
+ end;
+ $$;
+ 
+ -- should fails
+ do $$
+ begin
+   assert NULL;
+ end;
+ $$;
+ 
+ -- should fails
+ -- test of warning, when message related to a assert is null
+ do $$
+ begin
+   assert 1=0, NULL;
+ end;
+ $$;
+ 
+ -- should fails
+ do $$
+ declare var text := 'some value';
+ begin
+   assert 1=0, format('content of var: "%s"', var);
+ end;
+ $$;
+ 
+ -- assertions is unhandled
+ do $$
+ begin
+   assert 1=0, 'unhandled assert';
+ exception when others then
+   null; -- do nothing
+ end;
+ $$ language plpgsql;
-- 
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