PL/PgSQL: EXIT USING ROLLBACK
Hello,
Today I'd like to present a way to get rid of code like this:
$$
BEGIN
BEGIN
INSERT INTO foo VALUES (1);
-- run some tests/checks/whatever
RAISE EXCEPTION 'OK';
EXCEPTION WHEN raise_exception THEN
IF SQLERRM <> 'OK' THEN
RAISE;
END IF;
END;
RETURN 'success';
END
$$
And replace it with code like this:
$$
BEGIN
<<testsomething>>
BEGIN
INSERT INTO foo VALUES (1);
-- run some tests/checks/whatever
EXIT USING ROLLBACK testsomething;
EXCEPTION WHEN others THEN
RAISE;
END;
RETURN 'success';
END
$$
I'm not set on the USING ROLLBACK syntax; it was the only thing I could
come up with that seemed even remotely sane and didn't break backwards
compatibility.
Thoughts? Patch attached, if someone cares.
.marko
Attachments:
plpgsql_using_rollback.v1.patchtext/plain; charset=UTF-8; name=plpgsql_using_rollback.v1.patch; x-mac-creator=0; x-mac-type=0Download
*** a/doc/src/sgml/plpgsql.sgml
--- b/doc/src/sgml/plpgsql.sgml
***************
*** 2107,2113 **** END LOOP <optional> <replaceable>label</replaceable> </optional>;
</indexterm>
<synopsis>
! EXIT <optional> <replaceable>label</replaceable> </optional> <optional> WHEN <replaceable>boolean-expression</replaceable> </optional>;
</synopsis>
<para>
--- 2107,2113 ----
</indexterm>
<synopsis>
! EXIT <optional> <replaceable>label</replaceable> </optional> <optional> USING ROLLBACK </optional> <optional> WHEN <replaceable>boolean-expression</replaceable> </optional>;
</synopsis>
<para>
***************
*** 2121,2126 **** EXIT <optional> <replaceable>label</replaceable> </optional> <optional> WHEN <re
--- 2121,2134 ----
</para>
<para>
+ If <literal>USING ROLLBACK</> is specified, instead of persisting the
+ changes made inside the escaped <literal>BEGIN</> blocks, they are
+ rolled back. The <replaceable>label</> must be the label of the
+ current or an outer level <literal>BEGIN</> block with an
+ <literal>EXCEPTION</> block.
+ </para>
+
+ <para>
If <literal>WHEN</> is specified, the loop exit occurs only if
<replaceable>boolean-expression</> is true. Otherwise, control passes
to the statement after <literal>EXIT</>.
*** a/src/pl/plpgsql/src/pl_exec.c
--- b/src/pl/plpgsql/src/pl_exec.c
***************
*** 1181,1188 **** exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
resTypByVal, resTypLen);
}
! /* Commit the inner transaction, return to outer xact context */
! ReleaseCurrentSubTransaction();
MemoryContextSwitchTo(oldcontext);
CurrentResourceOwner = oldowner;
--- 1181,1192 ----
resTypByVal, resTypLen);
}
! if (rc == PLPGSQL_RC_EXIT && estate->exitrollback)
! RollbackAndReleaseCurrentSubTransaction();
! else
! /* Commit the inner transaction, return to outer xact context */
! ReleaseCurrentSubTransaction();
!
MemoryContextSwitchTo(oldcontext);
CurrentResourceOwner = oldowner;
***************
*** 1330,1335 **** exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
--- 1334,1347 ----
return PLPGSQL_RC_EXIT;
if (strcmp(block->label, estate->exitlabel) != 0)
return PLPGSQL_RC_EXIT;
+ if (estate->exitrollback)
+ {
+ if (!block->exceptions)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("the BEGIN block targeted by EXIT USING ROLLBACK must have an EXCEPTION clause")));
+ estate->exitrollback = false;
+ }
estate->exitlabel = NULL;
return PLPGSQL_RC_OK;
***************
*** 1789,1794 **** exec_stmt_loop(PLpgSQL_execstate *estate, PLpgSQL_stmt_loop *stmt)
--- 1801,1810 ----
return PLPGSQL_RC_EXIT;
if (strcmp(stmt->label, estate->exitlabel) != 0)
return PLPGSQL_RC_EXIT;
+ if (estate->exitrollback)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("the target of EXIT USING ROLLBACK must be a BEGIN block")));
estate->exitlabel = NULL;
return PLPGSQL_RC_OK;
***************
*** 1850,1855 **** exec_stmt_while(PLpgSQL_execstate *estate, PLpgSQL_stmt_while *stmt)
--- 1866,1875 ----
return PLPGSQL_RC_EXIT;
if (strcmp(stmt->label, estate->exitlabel) != 0)
return PLPGSQL_RC_EXIT;
+ if (estate->exitrollback)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("the target of EXIT USING ROLLBACK must be a BEGIN block")));
estate->exitlabel = NULL;
return PLPGSQL_RC_OK;
***************
*** 1996,2001 **** exec_stmt_fori(PLpgSQL_execstate *estate, PLpgSQL_stmt_fori *stmt)
--- 2016,2025 ----
strcmp(stmt->label, estate->exitlabel) == 0)
{
/* labelled exit, matches the current stmt's label */
+ if (estate->exitrollback)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("the target of EXIT USING ROLLBACK must be a BEGIN block")));
estate->exitlabel = NULL;
rc = PLPGSQL_RC_OK;
}
***************
*** 2348,2353 **** exec_stmt_foreach_a(PLpgSQL_execstate *estate, PLpgSQL_stmt_foreach_a *stmt)
--- 2372,2381 ----
strcmp(stmt->label, estate->exitlabel) == 0)
{
/* labelled exit, matches the current stmt's label */
+ if (estate->exitrollback)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("the target of EXIT USING ROLLBACK must be a BEGIN block")));
estate->exitlabel = NULL;
rc = PLPGSQL_RC_OK;
}
***************
*** 2423,2428 **** exec_stmt_exit(PLpgSQL_execstate *estate, PLpgSQL_stmt_exit *stmt)
--- 2451,2457 ----
}
estate->exitlabel = stmt->label;
+ estate->exitrollback = stmt->rollback;
if (stmt->is_exit)
return PLPGSQL_RC_EXIT;
else
***************
*** 3125,3130 **** plpgsql_estate_setup(PLpgSQL_execstate *estate,
--- 3154,3160 ----
estate->rettupdesc = NULL;
estate->exitlabel = NULL;
+ estate->exitrollback = false;
estate->cur_error = NULL;
estate->tuple_store = NULL;
***************
*** 4995,5000 **** exec_for_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_forq *stmt,
--- 5025,5034 ----
strcmp(stmt->label, estate->exitlabel) == 0)
{
/* label matches this loop, so exit loop */
+ if (estate->exitrollback)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("the target of EXIT USING ROLLBACK must be a BEGIN block")));
estate->exitlabel = NULL;
rc = PLPGSQL_RC_OK;
}
*** a/src/pl/plpgsql/src/pl_funcs.c
--- b/src/pl/plpgsql/src/pl_funcs.c
***************
*** 1209,1214 **** dump_exit(PLpgSQL_stmt_exit *stmt)
--- 1209,1216 ----
{
dump_ind();
printf("%s", stmt->is_exit ? "EXIT" : "CONTINUE");
+ if (stmt->rollback)
+ printf(" USING ROLLBACK");
if (stmt->label != NULL)
printf(" label='%s'", stmt->label);
if (stmt->cond != NULL)
*** a/src/pl/plpgsql/src/pl_gram.y
--- b/src/pl/plpgsql/src/pl_gram.y
***************
*** 178,183 **** static List *read_raise_options(void);
--- 178,184 ----
%type <expr> expr_until_semi expr_until_rightbracket
%type <expr> expr_until_then expr_until_loop opt_expr_until_when
%type <expr> opt_exitcond
+ %type <boolean> opt_using_rollback
%type <ival> assign_var foreach_slice
%type <var> cursor_variable
***************
*** 1660,1675 **** foreach_slice :
}
;
! stmt_exit : exit_type opt_label opt_exitcond
{
PLpgSQL_stmt_exit *new;
new = palloc0(sizeof(PLpgSQL_stmt_exit));
new->cmd_type = PLPGSQL_STMT_EXIT;
new->is_exit = $1;
new->lineno = plpgsql_location_to_lineno(@1);
! new->label = $2;
! new->cond = $3;
$$ = (PLpgSQL_stmt *)new;
}
--- 1661,1688 ----
}
;
! stmt_exit : exit_type opt_using_rollback opt_label opt_exitcond
{
PLpgSQL_stmt_exit *new;
new = palloc0(sizeof(PLpgSQL_stmt_exit));
new->cmd_type = PLPGSQL_STMT_EXIT;
new->is_exit = $1;
+ new->rollback = $2;
new->lineno = plpgsql_location_to_lineno(@1);
! new->label = $3;
! new->cond = $4;
!
! if (new->rollback && !new->is_exit)
! ereport(ERROR,
! (errcode(ERRCODE_SYNTAX_ERROR),
! errmsg("USING ROLLBACK is only supported with EXIT"),
! parser_errposition(@3)));
! else if (new->rollback && new->label == NULL)
! ereport(ERROR,
! (errcode(ERRCODE_SYNTAX_ERROR),
! errmsg("EXIT USING ROLLBACK requires a label"),
! parser_errposition(@3)));
$$ = (PLpgSQL_stmt *)new;
}
***************
*** 1685,1690 **** exit_type : K_EXIT
--- 1698,1716 ----
}
;
+ opt_using_rollback :
+ {
+ $$ = false;
+ }
+ |
+ K_USING T_WORD
+ {
+ if (strcmp($2.ident, "rollback") != 0)
+ yyerror("syntax error");
+ $$ = true;
+ }
+ ;
+
stmt_return : K_RETURN
{
int tok;
*** a/src/pl/plpgsql/src/plpgsql.h
--- b/src/pl/plpgsql/src/plpgsql.h
***************
*** 582,587 **** typedef struct
--- 582,588 ----
int cmd_type;
int lineno;
bool is_exit; /* Is this an exit or a continue? */
+ bool rollback; /* If this is an exit, true if we should roll back the current subtxn */
char *label; /* NULL if it's an unlabelled EXIT/CONTINUE */
PLpgSQL_expr *cond;
} PLpgSQL_stmt_exit;
***************
*** 770,775 **** typedef struct PLpgSQL_execstate
--- 771,778 ----
TupleDesc rettupdesc;
char *exitlabel; /* the "target" label of the current EXIT or
* CONTINUE stmt, if any */
+ bool exitrollback; /* true if we should also roll back when exiting
+ the BEGIN/END block matching "exitlabel" */
ErrorData *cur_error; /* current exception handler's error */
Tuplestorestate *tuple_store; /* SRFs accumulate results here */
*** a/src/test/regress/expected/plpgsql.out
--- b/src/test/regress/expected/plpgsql.out
***************
*** 2896,2901 **** $$ language plpgsql;
--- 2896,3026 ----
ERROR: end label "outer_label" specified for unlabelled block
LINE 6: end loop outer_label;
^
+ -- exit using rollback
+ create temporary table foo(a text not null);
+ create function exit_using_rollback() returns void as $$
+ begin
+ <<subtxn>>
+ begin
+ insert into foo values ('not ok');
+ exit using rollback subtxn;
+ exception when others then
+ raise;
+ end;
+ insert into foo values ('ok');
+ end;
+ $$ language plpgsql;
+ select exit_using_rollback();
+ exit_using_rollback
+ ---------------------
+
+ (1 row)
+
+ select * from foo;
+ a
+ ----
+ ok
+ (1 row)
+
+ -- roll back two blocks at once
+ create or replace function exit_using_rollback() returns void as $$
+ begin
+ <<subtxn>>
+ begin
+ insert into foo values ('not ok');
+ begin
+ insert into foo values ('not ok');
+ exit using rollback subtxn;
+ end;
+ exception when others then
+ raise;
+ end;
+ end;
+ $$ language plpgsql;
+ select exit_using_rollback();
+ exit_using_rollback
+ ---------------------
+
+ (1 row)
+
+ select * from foo;
+ a
+ ----
+ ok
+ (1 row)
+
+ -- roll back two blocks at once, both with EXCEPTION blocks
+ create or replace function exit_using_rollback() returns void as $$
+ begin
+ <<subtxn>>
+ begin
+ insert into foo values ('not ok');
+ begin
+ insert into foo values ('not ok');
+ exit using rollback subtxn;
+ exception when others then
+ raise;
+ end;
+ exception when others then
+ raise;
+ end;
+ end;
+ $$ language plpgsql;
+ select exit_using_rollback();
+ exit_using_rollback
+ ---------------------
+
+ (1 row)
+
+ select * from foo;
+ a
+ ----
+ ok
+ (1 row)
+
+ drop table foo;
+ -- should fail: not allowed to target LOOP label (runtime failure)
+ create or replace function exit_using_rollback() returns void as $$
+ begin
+ <<invalid>>
+ loop
+ exit using rollback invalid;
+ end loop;
+ end;
+ $$ language plpgsql;
+ select exit_using_rollback();
+ ERROR: the target of EXIT USING ROLLBACK must be a BEGIN block
+ CONTEXT: PL/pgSQL function exit_using_rollback() line 4 at LOOP
+ -- should fail: invalid syntax
+ create or replace function exit_using_rollback() returns void as $$
+ begin
+ continue using rollback;
+ end;
+ $$ language plpgsql;
+ ERROR: USING ROLLBACK is only supported with EXIT
+ LINE 3: continue using rollback;
+ ^
+ -- should fail: requires label
+ create or replace function exit_using_rollback() returns void as $$
+ begin
+ exit using rollback;
+ end;
+ $$ language plpgsql;
+ ERROR: EXIT USING ROLLBACK requires a label
+ LINE 3: exit using rollback;
+ ^
+ -- should fail: requires exception handler (runtime failure)
+ create or replace function exit_using_rollback() returns void as $$
+ begin
+ <<nosubtxn>>
+ begin
+ exit using rollback nosubtxn;
+ end;
+ end;
+ $$ language plpgsql;
+ select exit_using_rollback();
+ ERROR: the BEGIN block targeted by EXIT USING ROLLBACK must have an EXCEPTION clause
+ CONTEXT: PL/pgSQL function exit_using_rollback() line 4 at statement block
-- using list of scalars in fori and fore stmts
create function for_vect() returns void as $proc$
<<lbl>>declare a integer; b varchar; c varchar; r record;
*** a/src/test/regress/sql/plpgsql.sql
--- b/src/test/regress/sql/plpgsql.sql
***************
*** 2429,2434 **** begin
--- 2429,2532 ----
end;
$$ language plpgsql;
+ -- exit using rollback
+ create temporary table foo(a text not null);
+ create function exit_using_rollback() returns void as $$
+ begin
+ <<subtxn>>
+ begin
+ insert into foo values ('not ok');
+ exit using rollback subtxn;
+ exception when others then
+ raise;
+ end;
+ insert into foo values ('ok');
+ end;
+ $$ language plpgsql;
+
+ select exit_using_rollback();
+ select * from foo;
+
+ -- roll back two blocks at once
+ create or replace function exit_using_rollback() returns void as $$
+ begin
+ <<subtxn>>
+ begin
+ insert into foo values ('not ok');
+ begin
+ insert into foo values ('not ok');
+ exit using rollback subtxn;
+ end;
+ exception when others then
+ raise;
+ end;
+ end;
+ $$ language plpgsql;
+
+ select exit_using_rollback();
+ select * from foo;
+
+ -- roll back two blocks at once, both with EXCEPTION blocks
+ create or replace function exit_using_rollback() returns void as $$
+ begin
+ <<subtxn>>
+ begin
+ insert into foo values ('not ok');
+ begin
+ insert into foo values ('not ok');
+ exit using rollback subtxn;
+ exception when others then
+ raise;
+ end;
+ exception when others then
+ raise;
+ end;
+ end;
+ $$ language plpgsql;
+
+ select exit_using_rollback();
+ select * from foo;
+
+ drop table foo;
+
+ -- should fail: not allowed to target LOOP label (runtime failure)
+ create or replace function exit_using_rollback() returns void as $$
+ begin
+ <<invalid>>
+ loop
+ exit using rollback invalid;
+ end loop;
+ end;
+ $$ language plpgsql;
+
+ select exit_using_rollback();
+
+ -- should fail: invalid syntax
+ create or replace function exit_using_rollback() returns void as $$
+ begin
+ continue using rollback;
+ end;
+ $$ language plpgsql;
+
+ -- should fail: requires label
+ create or replace function exit_using_rollback() returns void as $$
+ begin
+ exit using rollback;
+ end;
+ $$ language plpgsql;
+
+ -- should fail: requires exception handler (runtime failure)
+ create or replace function exit_using_rollback() returns void as $$
+ begin
+ <<nosubtxn>>
+ begin
+ exit using rollback nosubtxn;
+ end;
+ end;
+ $$ language plpgsql;
+
+ select exit_using_rollback();
+
-- using list of scalars in fori and fore stmts
create function for_vect() returns void as $proc$
<<lbl>>declare a integer; b varchar; c varchar; r record;
Marko Tiikkaja <marko@joh.to> writes:
Hello,
Today I'd like to present a way to get rid of code like this:
$$
BEGIN
BEGIN
INSERT INTO foo VALUES (1);
-- run some tests/checks/whatever
RAISE EXCEPTION 'OK';
EXCEPTION WHEN raise_exception THEN
IF SQLERRM <> 'OK' THEN
RAISE;
END IF;
END;
RETURN 'success';
END
$$
And replace it with code like this:
$$
BEGIN
<<testsomething>>
BEGIN
INSERT INTO foo VALUES (1);
-- run some tests/checks/whatever
EXIT USING ROLLBACK testsomething;
EXCEPTION WHEN others THEN
RAISE;
END;
RETURN 'success';
END
$$
Somehow I'm failing to see that as much of an improvement;
in fact, it's probably less clear than before. I don't much
care for the idea that EXIT should take on some transaction-control
properties instead of being a simple transfer of control.
In particular, what happens if someone attaches USING ROLLBACK
to an EXIT that does not lead from inside to outside a BEGIN/EXCEPTION
block?
regards, tom lane
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On 7/26/14, 8:22 PM, Tom Lane wrote:
In particular, what happens if someone attaches USING ROLLBACK
to an EXIT that does not lead from inside to outside a BEGIN/EXCEPTION
block?
I'm not sure which case you're envisioning. A label is required, and
the label must be that of a BEGIN block with an EXCEPTION block if USING
ROLLBACK is specified. If that doesn't answer your question, could try
and explain (perhaps in the form of an example) which problem you're seeing?
.marko
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
Marko Tiikkaja <marko@joh.to> writes:
On 7/26/14, 8:22 PM, Tom Lane wrote:
In particular, what happens if someone attaches USING ROLLBACK
to an EXIT that does not lead from inside to outside a BEGIN/EXCEPTION
block?
I'm not sure which case you're envisioning. A label is required, and
the label must be that of a BEGIN block with an EXCEPTION block if USING
ROLLBACK is specified. If that doesn't answer your question, could try
and explain (perhaps in the form of an example) which problem you're seeing?
Well, restrictions of that sort might dodge the implementation problem,
but they make the construct even less orthogonal. (And the restriction as
stated isn't good enough anyway, since I could still place such an EXIT in
the EXCEPTION part of the block.)
Basically my point is that this just seems like inventing another way to
do what one can already do with RAISE, and it doesn't have much redeeming
social value to justify the cognitive load of inventing another construct.
regards, tom lane
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On 7/26/14, 8:39 PM, Tom Lane wrote:
Marko Tiikkaja <marko@joh.to> writes:
I'm not sure which case you're envisioning. A label is required, and
the label must be that of a BEGIN block with an EXCEPTION block if USING
ROLLBACK is specified. If that doesn't answer your question, could try
and explain (perhaps in the form of an example) which problem you're seeing?Well, restrictions of that sort might dodge the implementation problem,
but they make the construct even less orthogonal. (And the restriction as
stated isn't good enough anyway, since I could still place such an EXIT in
the EXCEPTION part of the block.)
That's a good point; the patch would have to be changed to disallow this
case.
Basically my point is that this just seems like inventing another way to
do what one can already do with RAISE, and it doesn't have much redeeming
social value to justify the cognitive load of inventing another construct.
Yes, you can already do this with RAISE but that seems more like an
accident than anything else. I feel a dedicated syntax is less error
prone and makes the intent clearer to people reading the code. But I
realize I might be in the minority with this.
.marko
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
Hello
2014-07-26 19:14 GMT+02:00 Marko Tiikkaja <marko@joh.to>:
Hello,
Today I'd like to present a way to get rid of code like this:
$$
BEGINBEGIN
INSERT INTO foo VALUES (1);
-- run some tests/checks/whatever
RAISE EXCEPTION 'OK';
EXCEPTION WHEN raise_exception THEN
IF SQLERRM <> 'OK' THEN
RAISE;
END IF;
END;RETURN 'success';
END
$$And replace it with code like this:
$$
BEGIN<<testsomething>>
BEGIN
INSERT INTO foo VALUES (1);
-- run some tests/checks/whatever
EXIT USING ROLLBACK testsomething;
EXCEPTION WHEN others THEN
RAISE;
END;RETURN 'success';
END
$$I'm not set on the USING ROLLBACK syntax; it was the only thing I could
come up with that seemed even remotely sane and didn't break backwards
compatibility.Thoughts? Patch attached, if someone cares.
-1
I don't think, so we need to cobolize PL/pgSQL more.
There is not any strong reason why we should to introduce it. You don't
save a code, you don't increase a performance
Regards
Pavel
Show quoted text
.marko
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On 26 July 2014 18:14, Marko Tiikkaja <marko@joh.to> wrote:
Today I'd like to present a way to get rid of code like this:
You haven't explained this very well... there is nothing that explains
WHY you want this.
In the absence of a good explanation and a viable benefit, I would
vote -1 for this feature suggestion.
--
Simon Riggs http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On 7/28/14 11:27 AM, Simon Riggs wrote:
On 26 July 2014 18:14, Marko Tiikkaja <marko@joh.to> wrote:
Today I'd like to present a way to get rid of code like this:
You haven't explained this very well... there is nothing that explains
WHY you want this.In the absence of a good explanation and a viable benefit, I would
vote -1 for this feature suggestion.
Yes, I did a poor job in the original email, but I did explain my
reasoning later:
Yes, you can already do this with RAISE but that seems more like an
accident than anything else. I feel a dedicated syntax is less error
prone and makes the intent clearer to people reading the code. But I
realize I might be in the minority with this.
I guess -3, +0 is enough that I'll be dropping the patch. Thanks to
everyone who had a look.
.marko
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On 28 July 2014 10:34, Marko Tiikkaja <marko@joh.to> wrote:
On 7/28/14 11:27 AM, Simon Riggs wrote:
On 26 July 2014 18:14, Marko Tiikkaja <marko@joh.to> wrote:
Today I'd like to present a way to get rid of code like this:
You haven't explained this very well... there is nothing that explains
WHY you want this.In the absence of a good explanation and a viable benefit, I would
vote -1 for this feature suggestion.Yes, I did a poor job in the original email, but I did explain my reasoning
later:
With respect, I think you did a poor job the second time too. I can't
find a clearly explained reasoning behind the proposal, nor do I
understand what the problem was.
One of the things I do is work hard on my initial explanations and
reasoning. This helps me because I frequently end up not proposing
something because my reasoning was poor, but it also helps me focus on
whether I am solving a real problem by sharepening my understanding of
the actual problem. And it also helps Tom (or others) demolish things
more quickly with a well placed "indeed" ;-)
--
Simon Riggs http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Sat, Jul 26, 2014 at 8:39 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
Basically my point is that this just seems like inventing another way to
do what one can already do with RAISE, and it doesn't have much redeeming
social value to justify the cognitive load of inventing another construct.
The main difference is with RAISE EXCEPTION 'OK'; you cannot know if
it was *your* line of code which throw the 'OK'-exception or if it
came from some other function which was called in the block of code.
This means with the current way you have to inspect all lines of code
in all functions in the entire call graph for the block of code for
which you want to capture the 'OK'-exception (or whatever name one
wishes to use),
alternatively to use a name which is guaranteed to be unique, such as
a UUID or something which no other line of code could possibly emmit
as an exception.
Both approaches are ugly and hackish. I think the language should
provide a documented and safe way of exiting from a begin block
without having to worry about other code raising exceptions of the
same name.
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Mon, Sep 1, 2014 at 5:08 AM, Joel Jacobson <joel@trustly.com> wrote:
On Sat, Jul 26, 2014 at 8:39 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
Basically my point is that this just seems like inventing another way to
do what one can already do with RAISE, and it doesn't have much redeeming
social value to justify the cognitive load of inventing another construct.The main difference is with RAISE EXCEPTION 'OK'; you cannot know if
it was *your* line of code which throw the 'OK'-exception or if it
came from some other function which was called in the block of code.
The real problem here is that if you're using PL/pgsql exceptions for
control-flow reasons, you are taking a huge performance hit for that
notational convenience. I do agree that the syntax of PL/pgsql is
clunky and maybe we should fix that anyway, but I honestly can't
imagine too many people actually wanting to do this once they realize
what it does to the run time of their procedure (and in some cases,
the XID-consumption rate of their database).
--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On 3 sep 2014, at 16:20, Robert Haas <robertmhaas@gmail.com> wrote:
On Mon, Sep 1, 2014 at 5:08 AM, Joel Jacobson <joel@trustly.com> wrote:
On Sat, Jul 26, 2014 at 8:39 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
Basically my point is that this just seems like inventing another way to
do what one can already do with RAISE, and it doesn't have much redeeming
social value to justify the cognitive load of inventing another construct.The main difference is with RAISE EXCEPTION 'OK'; you cannot know if
it was *your* line of code which throw the 'OK'-exception or if it
came from some other function which was called in the block of code.The real problem here is that if you're using PL/pgsql exceptions for
control-flow reasons, you are taking a huge performance hit for that
notational convenience. I do agree that the syntax of PL/pgsql is
clunky and maybe we should fix that anyway, but I honestly can't
imagine too many people actually wanting to do this once they realize
what it does to the run time of their procedure (and in some cases,
the XID-consumption rate of their database).
Exceptions in plpgsql is indeed an exception itself :-)
There are a few use cases when they are crucial though, I would say I
use this code pattern in 0.1% of all functions, but still, when I need
this, it gets ugly.
Glad to hear you might consider the idea of fixing this.
--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers