Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitd46bc44

Browse files
author
Neil Conway
committed
Implement two new special variables in PL/PgSQL: SQLSTATE and SQLERRM.
These contain the SQLSTATE and error message of the current exception,respectively. They are scope-local variables that are only definedin exception handlers (so attempting to reference them outside anexception handler is an error). Update the regression tests and thedocumentation.Also, do some minor related cleanup: export an unpack_sql_state()function from the backend and use it to unpack a SQLSTATE into astring, and add a free_var() function to pl_exec.cOriginal patch from Pavel Stehule, review by Neil Conway.
1 parent1a61896 commitd46bc44

File tree

10 files changed

+226
-51
lines changed

10 files changed

+226
-51
lines changed

‎doc/src/sgml/plpgsql.sgml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.70 2005/06/07 02:47:15 neilc Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.71 2005/06/10 16:23:09 neilc Exp $
33
-->
44

55
<chapter id="plpgsql">
@@ -2110,6 +2110,17 @@ END;
21102110
don't use <literal>EXCEPTION</> without need.
21112111
</para>
21122112
</tip>
2113+
2114+
<para>
2115+
Within an exception handler, the <varname>SQLSTATE</varname>
2116+
variable contains the error code that corresponds to the
2117+
exception that was raised (refer to <xref
2118+
linkend="errcodes-table"> for a list of possible error
2119+
codes). The <varname>SQLERRM</varname> variable contains the
2120+
error message associated with the exception. These variables are
2121+
undefined outside exception handlers.
2122+
</para>
2123+
21132124
<example id="plpgsql-upsert-example">
21142125
<title>Exceptions with UPDATE/INSERT</title>
21152126
<para>

‎src/backend/utils/error/elog.c

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
*
4343
*
4444
* IDENTIFICATION
45-
* $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.159 2005/06/09 22:29:52 momjian Exp $
45+
* $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.160 2005/06/10 16:23:10 neilc Exp $
4646
*
4747
*-------------------------------------------------------------------------
4848
*/
@@ -1482,6 +1482,26 @@ log_line_prefix(StringInfo buf)
14821482
}
14831483
}
14841484

1485+
/*
1486+
* Unpack MAKE_SQLSTATE code. Note that this returns a pointer to a
1487+
* static buffer.
1488+
*/
1489+
char*
1490+
unpack_sql_state(intsql_state)
1491+
{
1492+
staticcharbuf[12];
1493+
inti;
1494+
1495+
for (i=0;i<5;i++)
1496+
{
1497+
buf[i]=PGUNSIXBIT(sql_state);
1498+
sql_state >>=6;
1499+
}
1500+
1501+
buf[i]='\0';
1502+
returnbuf;
1503+
}
1504+
14851505

14861506
/*
14871507
* Write error report to server's log
@@ -1497,21 +1517,7 @@ send_message_to_server_log(ErrorData *edata)
14971517
appendStringInfo(&buf,"%s: ",error_severity(edata->elevel));
14981518

14991519
if (Log_error_verbosity >=PGERROR_VERBOSE)
1500-
{
1501-
/* unpack MAKE_SQLSTATE code */
1502-
chartbuf[12];
1503-
intssval;
1504-
inti;
1505-
1506-
ssval=edata->sqlerrcode;
1507-
for (i=0;i<5;i++)
1508-
{
1509-
tbuf[i]=PGUNSIXBIT(ssval);
1510-
ssval >>=6;
1511-
}
1512-
tbuf[i]='\0';
1513-
appendStringInfo(&buf,"%s: ",tbuf);
1514-
}
1520+
appendStringInfo(&buf,"%s: ",unpack_sql_state(edata->sqlerrcode));
15151521

15161522
if (edata->message)
15171523
append_with_tabs(&buf,edata->message);

‎src/include/utils/elog.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/utils/elog.h,v 1.78 2004/12/31 22:03:46 pgsql Exp $
10+
* $PostgreSQL: pgsql/src/include/utils/elog.h,v 1.79 2005/06/10 16:23:10 neilc Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -282,6 +282,7 @@ extern intLog_destination;
282282

283283
/* Other exported functions */
284284
externvoidDebugFileOpen(void);
285+
externchar*unpack_sql_state(intsql_state);
285286

286287
/*
287288
* Write errors to stderr (or by equal means when stderr is

‎src/pl/plpgsql/src/gram.y

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* procedural language
55
*
66
* IDENTIFICATION
7-
* $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.74 2005/06/08 00:49:36 neilc Exp $
7+
* $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.75 2005/06/10 16:23:11 neilc Exp $
88
*
99
* This software is copyrighted by Jan Wieck - Hamburg.
1010
*
@@ -92,6 +92,7 @@ staticvoid plpgsql_sql_error_callback(void *arg);
9292
PLpgSQL_stmt_block*program;
9393
PLpgSQL_condition*condition;
9494
PLpgSQL_exception*exception;
95+
PLpgSQL_exception_block*exception_block;
9596
PLpgSQL_nsitem*nsitem;
9697
PLpgSQL_diag_item*diagitem;
9798
}
@@ -129,7 +130,8 @@ staticvoid plpgsql_sql_error_callback(void *arg);
129130
%type<stmt>stmt_dynexecutestmt_getdiag
130131
%type<stmt>stmt_openstmt_fetchstmt_closestmt_null
131132

132-
%type<list>exception_sectproc_exceptions
133+
%type<list>proc_exceptions
134+
%type<exception_block>exception_sect
133135
%type<exception>proc_exception
134136
%type<condition>proc_conditions
135137

@@ -1495,9 +1497,38 @@ execsql_start: T_WORD
14951497
;
14961498

14971499
exception_sect:
1498-
{$$ = NIL; }
1499-
|K_EXCEPTIONproc_exceptions
1500-
{$$ =$2; }
1500+
{$$ =NULL; }
1501+
|K_EXCEPTIONlno
1502+
{
1503+
/*
1504+
* We use a mid-rule action to add these
1505+
* special variables to the namespace before
1506+
* parsing the WHEN clauses themselves.
1507+
*/
1508+
PLpgSQL_exception_block *new = palloc(sizeof(PLpgSQL_exception_block));
1509+
PLpgSQL_variable *var;
1510+
1511+
var = plpgsql_build_variable("sqlstate",$2,
1512+
plpgsql_build_datatype(TEXTOID, -1),
1513+
true);
1514+
((PLpgSQL_var *) var)->isconst =true;
1515+
new->sqlstate_varno = var->dno;
1516+
1517+
var = plpgsql_build_variable("sqlerrm",$2,
1518+
plpgsql_build_datatype(TEXTOID, -1),
1519+
true);
1520+
((PLpgSQL_var *) var)->isconst =true;
1521+
new->sqlerrm_varno = var->dno;
1522+
1523+
$<exception_block>$ =new;
1524+
}
1525+
proc_exceptions
1526+
{
1527+
PLpgSQL_exception_block *new = $<exception_block>3;
1528+
new->exc_list =$4;
1529+
1530+
$$ =new;
1531+
}
15011532
;
15021533

15031534
proc_exceptions:proc_exceptionsproc_exception

‎src/pl/plpgsql/src/pl_comp.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* procedural language
44
*
55
* IDENTIFICATION
6-
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.90 2005/05/29 04:23:06 tgl Exp $
6+
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.91 2005/06/10 16:23:11 neilc Exp $
77
*
88
* This software is copyrighted by Jan Wieck - Hamburg.
99
*
@@ -656,7 +656,7 @@ do_compile(FunctionCallInfo fcinfo,
656656
if (num_out_args>0||function->fn_rettype==VOIDOID||
657657
function->fn_retset)
658658
{
659-
if (function->action->exceptions!=NIL)
659+
if (function->action->exceptions!=NULL)
660660
{
661661
PLpgSQL_stmt_block*new;
662662

@@ -882,7 +882,7 @@ plpgsql_parse_word(char *word)
882882
}
883883

884884
/*
885-
* Do a lookup on thecompilers namestack
885+
* Do a lookup on thecompiler's namestack
886886
*/
887887
nse=plpgsql_ns_lookup(cp[0],NULL);
888888
if (nse!=NULL)
@@ -1935,7 +1935,7 @@ plpgsql_parse_err_condition(char *condname)
19351935

19361936
/* ----------
19371937
* plpgsql_adddatumAdd a variable, record or row
1938-
*to thecompilers datum list.
1938+
*to thecompiler's datum list.
19391939
* ----------
19401940
*/
19411941
void

‎src/pl/plpgsql/src/pl_exec.c

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* procedural language
44
*
55
* IDENTIFICATION
6-
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.142 2005/06/07 02:47:17 neilc Exp $
6+
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.143 2005/06/10 16:23:11 neilc Exp $
77
*
88
* This software is copyrighted by Jan Wieck - Hamburg.
99
*
@@ -180,7 +180,7 @@ static Datum exec_simple_cast_value(Datum value, Oid valtype,
180180
staticvoidexec_init_tuple_store(PLpgSQL_execstate*estate);
181181
staticboolcompatible_tupdesc(TupleDesctd1,TupleDesctd2);
182182
staticvoidexec_set_found(PLpgSQL_execstate*estate,boolstate);
183-
183+
staticvoidfree_var(PLpgSQL_var*var);
184184

185185
/* ----------
186186
* plpgsql_exec_functionCalled by the call handler for
@@ -760,12 +760,7 @@ exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
760760
{
761761
PLpgSQL_var*var= (PLpgSQL_var*) (estate->datums[n]);
762762

763-
if (var->freeval)
764-
{
765-
pfree((void*) (var->value));
766-
var->freeval= false;
767-
}
768-
763+
free_var(var);
769764
if (!var->isconst||var->isnull)
770765
{
771766
if (var->default_val==NULL)
@@ -864,13 +859,37 @@ exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
864859
SPI_restore_connection();
865860

866861
/* Look for a matching exception handler */
867-
foreach (e,block->exceptions)
862+
foreach (e,block->exceptions->exc_list)
868863
{
869864
PLpgSQL_exception*exception= (PLpgSQL_exception*)lfirst(e);
870865

871866
if (exception_matches_conditions(edata,exception->conditions))
872867
{
868+
/*
869+
* Initialize the magic SQLSTATE and SQLERRM
870+
* variables for the exception block. We needn't
871+
* do this until we have found a matching
872+
* exception.
873+
*/
874+
PLpgSQL_var*state_var;
875+
PLpgSQL_var*errm_var;
876+
877+
state_var= (PLpgSQL_var*) (estate->datums[block->exceptions->sqlstate_varno]);
878+
state_var->value=DirectFunctionCall1(textin,
879+
CStringGetDatum(unpack_sql_state(edata->sqlerrcode)));
880+
state_var->freeval= true;
881+
state_var->isnull= false;
882+
883+
errm_var= (PLpgSQL_var*) (estate->datums[block->exceptions->sqlerrm_varno]);
884+
errm_var->value=DirectFunctionCall1(textin,
885+
CStringGetDatum(edata->message));
886+
errm_var->freeval= true;
887+
errm_var->isnull= false;
888+
873889
rc=exec_stmts(estate,exception->action);
890+
891+
free_var(state_var);
892+
free_var(errm_var);
874893
break;
875894
}
876895
}
@@ -2586,9 +2605,7 @@ exec_stmt_open(PLpgSQL_execstate *estate, PLpgSQL_stmt_open *stmt)
25862605
* Store the eventually assigned cursor name in the cursor variable
25872606
* ----------
25882607
*/
2589-
if (curvar->freeval)
2590-
pfree((void*) (curvar->value));
2591-
2608+
free_var(curvar);
25922609
curvar->value=DirectFunctionCall1(textin,CStringGetDatum(portal->name));
25932610
curvar->isnull= false;
25942611
curvar->freeval= true;
@@ -2684,9 +2701,7 @@ exec_stmt_open(PLpgSQL_execstate *estate, PLpgSQL_stmt_open *stmt)
26842701
* Store the eventually assigned portal name in the cursor variable
26852702
* ----------
26862703
*/
2687-
if (curvar->freeval)
2688-
pfree((void*) (curvar->value));
2689-
2704+
free_var(curvar);
26902705
curvar->value=DirectFunctionCall1(textin,CStringGetDatum(portal->name));
26912706
curvar->isnull= false;
26922707
curvar->freeval= true;
@@ -2857,11 +2872,7 @@ exec_assign_value(PLpgSQL_execstate *estate,
28572872
errmsg("NULL cannot be assigned to variable \"%s\" declared NOT NULL",
28582873
var->refname)));
28592874

2860-
if (var->freeval)
2861-
{
2862-
pfree(DatumGetPointer(var->value));
2863-
var->freeval= false;
2864-
}
2875+
free_var(var);
28652876

28662877
/*
28672878
* If type is by-reference, make sure we have a freshly
@@ -4343,3 +4354,13 @@ plpgsql_xact_cb(XactEvent event, void *arg)
43434354
FreeExecutorState(simple_eval_estate);
43444355
simple_eval_estate=NULL;
43454356
}
4357+
4358+
staticvoid
4359+
free_var(PLpgSQL_var*var)
4360+
{
4361+
if (var->freeval)
4362+
{
4363+
pfree(DatumGetPointer(var->value));
4364+
var->freeval= false;
4365+
}
4366+
}

‎src/pl/plpgsql/src/pl_funcs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* procedural language
44
*
55
* IDENTIFICATION
6-
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.40 2005/04/05 06:22:16 tgl Exp $
6+
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.41 2005/06/10 16:23:11 neilc Exp $
77
*
88
* This software is copyrighted by Jan Wieck - Hamburg.
99
*
@@ -634,7 +634,7 @@ dump_block(PLpgSQL_stmt_block *block)
634634
{
635635
ListCell*e;
636636

637-
foreach (e,block->exceptions)
637+
foreach (e,block->exceptions->exc_list)
638638
{
639639
PLpgSQL_exception*exc= (PLpgSQL_exception*)lfirst(e);
640640
PLpgSQL_condition*cond;

‎src/pl/plpgsql/src/plpgsql.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* procedural language
44
*
55
* IDENTIFICATION
6-
* $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.61 2005/06/07 02:47:18 neilc Exp $
6+
* $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.62 2005/06/10 16:23:11 neilc Exp $
77
*
88
* This software is copyrighted by Jan Wieck - Hamburg.
99
*
@@ -322,6 +322,13 @@ typedef struct PLpgSQL_condition
322322
structPLpgSQL_condition*next;
323323
}PLpgSQL_condition;
324324

325+
typedefstruct
326+
{
327+
intsqlstate_varno;
328+
intsqlerrm_varno;
329+
List*exc_list;/* List of WHEN clauses */
330+
}PLpgSQL_exception_block;
331+
325332
typedefstruct
326333
{/* One EXCEPTION ... WHEN clause */
327334
intlineno;
@@ -336,9 +343,9 @@ typedef struct
336343
intlineno;
337344
char*label;
338345
List*body;/* List of statements */
339-
List*exceptions;/* List of WHEN clauses */
340346
intn_initvars;
341347
int*initvarnos;
348+
PLpgSQL_exception_block*exceptions;
342349
}PLpgSQL_stmt_block;
343350

344351

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp