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

Commitcd37bb7

Browse files
committed
Improve PL/Tcl errorCode facility by providing decoded name for SQLSTATE.
We don't really want to encourage people to write numeric SQLSTATEs inprograms; that's unreadable and error-prone. Copy plpgsql's infrastructurefor converting between SQLSTATEs and exception names shown in Appendix A,and modify examples in tests and documentation to do it that way.
1 parentfb8d2a7 commitcd37bb7

File tree

9 files changed

+118
-13
lines changed

9 files changed

+118
-13
lines changed

‎doc/src/sgml/pltcl.sgml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -813,14 +813,16 @@ CREATE EVENT TRIGGER tcl_a_snitch ON ddl_command_start EXECUTE PROCEDURE tclsnit
813813
word is <literal>POSTGRES</literal>, the second word is the Postgres
814814
version number, and additional words are field name/value pairs
815815
providing detailed information about the error.
816-
Fields <varname>message</> and <varname>SQLSTATE</> (the error code
817-
shown in <xref linkend="errcodes-appendix">) are always supplied.
816+
Fields <varname>SQLSTATE</>, <varname>condition</>,
817+
and <varname>message</> are always supplied
818+
(the first two represent the error code and condition name as shown
819+
in <xref linkend="errcodes-appendix">).
818820
Fields that may be present include
819821
<varname>detail</>, <varname>hint</>, <varname>context</>,
820822
<varname>schema</>, <varname>table</>, <varname>column</>,
821823
<varname>datatype</>, <varname>constraint</>,
822824
<varname>statement</>, <varname>cursor_position</>,
823-
<varname>filename</>, <varname>lineno</> and
825+
<varname>filename</>, <varname>lineno</>, and
824826
<varname>funcname</>.
825827
</para>
826828

@@ -832,7 +834,7 @@ CREATE EVENT TRIGGER tcl_a_snitch ON ddl_command_start EXECUTE PROCEDURE tclsnit
832834
if {[catch { spi_exec $sql_command }]} {
833835
if {[lindex $::errorCode 0] == "POSTGRES"} {
834836
array set errorArray $::errorCode
835-
if {$errorArray(SQLSTATE) == "42P01"} { # UNDEFINED_TABLE
837+
if {$errorArray(condition) == "undefined_table"} {
836838
# deal with missing table
837839
} else {
838840
# deal with some other type of SQL error

‎src/backend/utils/errcodes.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
# src/pl/plpgsql/src/plerrcodes.h
1616
# a list of PL/pgSQL condition names and their SQLSTATE codes
1717
#
18+
# src/pl/tcl/pltclerrcodes.h
19+
# the same, for PL/Tcl
20+
#
1821
# doc/src/sgml/errcodes-list.sgml
1922
# a SGML table of error codes for inclusion in the documentation
2023
#

‎src/pl/tcl/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
/pltclerrcodes.h
2+
13
# Generated subdirectories
24
/log/
35
/results/

‎src/pl/tcl/Makefile

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ include $(top_builddir)/src/Makefile.global
1313

1414
overrideCPPFLAGS :=$(TCL_INCLUDE_SPEC)$(CPPFLAGS)
1515

16-
1716
# On Windows, we don't link directly with the Tcl library; see below
1817
ifneq ($(PORTNAME), win32)
1918
SHLIB_LINK =$(TCL_LIB_SPEC)$(TCL_LIBS) -lc
@@ -56,6 +55,14 @@ include $(top_srcdir)/src/Makefile.shlib
5655
all: all-lib
5756
$(MAKE) -C modules$@
5857

58+
# Force this dependency to be known even without dependency info built:
59+
pltcl.o: pltclerrcodes.h
60+
61+
# generate pltclerrcodes.h from src/backend/utils/errcodes.txt
62+
pltclerrcodes.h:$(top_srcdir)/src/backend/utils/errcodes.txt generate-pltclerrcodes.pl
63+
$(PERL)$(srcdir)/generate-pltclerrcodes.pl$<>$@
64+
65+
distprep: pltclerrcodes.h
5966

6067
install: all install-lib install-data
6168
$(MAKE) -C modules$@
@@ -86,10 +93,14 @@ installcheck: submake
8693
submake:
8794
$(MAKE) -C$(top_builddir)/src/test/regress pg_regress$(X)
8895

89-
cleandistcleanmaintainer-clean: clean-lib
96+
# pltclerrcodes.h is in the distribution tarball, so don't clean it here.
97+
cleandistclean: clean-lib
9098
rm -f$(OBJS)
9199
rm -rf$(pg_regress_clean_files)
92100
ifeq ($(PORTNAME), win32)
93101
rm -f $(tclwithver).def
94102
endif
95103
$(MAKE) -C modules $@
104+
105+
maintainer-clean: distclean
106+
rm -f pltclerrcodes.h

‎src/pl/tcl/expected/pltcl_setup.out

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -560,10 +560,10 @@ create function tcl_error_handling_test() returns text as $$
560560
global errorCode
561561
if {[catch { spi_exec "select no_such_column from foo;" }]} {
562562
array set errArray $errorCode
563-
if {$errArray(SQLSTATE) == "42P01"} {
563+
if {$errArray(condition) == "undefined_table"} {
564564
return "expected error: $errArray(message)"
565565
} else {
566-
return "unexpected error: $errArray(SQLSTATE) $errArray(message)"
566+
return "unexpected error: $errArray(condition) $errArray(message)"
567567
}
568568
} else {
569569
return "no error"
@@ -577,9 +577,9 @@ select tcl_error_handling_test();
577577

578578
create temp table foo(f1 int);
579579
select tcl_error_handling_test();
580-
tcl_error_handling_test
581-
----------------------------------------------------------------
582-
unexpected error:42703 column "no_such_column" does not exist
580+
tcl_error_handling_test
581+
---------------------------------------------------------------------------
582+
unexpected error:undefined_column column "no_such_column" does not exist
583583
(1 row)
584584

585585
drop table foo;

‎src/pl/tcl/generate-pltclerrcodes.pl

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#!/usr/bin/perl
2+
#
3+
# Generate the pltclerrcodes.h header from errcodes.txt
4+
# Copyright (c) 2000-2016, PostgreSQL Global Development Group
5+
6+
use warnings;
7+
use strict;
8+
9+
print
10+
"/* autogenerated from src/backend/utils/errcodes.txt, do not edit */\n";
11+
print"/* there is deliberately not an #ifndef PLTCLERRCODES_H here */\n";
12+
13+
openmy$errcodes,$ARGV[0]ordie;
14+
15+
while (<$errcodes>)
16+
{
17+
chomp;
18+
19+
# Skip comments
20+
nextif/^#/;
21+
nextif/^\s*$/;
22+
23+
# Skip section headers
24+
nextif/^Section:/;
25+
26+
dieunless/^([^\s]{5})\s+([EWS])\s+([^\s]+)(?:\s+)?([^\s]+)?/;
27+
28+
(my$sqlstate,my$type,my$errcode_macro,my$condition_name) =
29+
($1,$2,$3,$4);
30+
31+
# Skip non-errors
32+
nextunless$typeeq'E';
33+
34+
# Skip lines without PL/pgSQL condition names
35+
nextunlessdefined($condition_name);
36+
37+
print"{\n\t\"$condition_name\",$errcode_macro\n},\n\n";
38+
}
39+
40+
close$errcodes;

‎src/pl/tcl/pltcl.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,20 @@ static HTAB *pltcl_proc_htab = NULL;
188188
staticFunctionCallInfopltcl_current_fcinfo=NULL;
189189
staticpltcl_proc_desc*pltcl_current_prodesc=NULL;
190190

191+
/**********************************************************************
192+
* Lookup table for SQLSTATE condition names
193+
**********************************************************************/
194+
typedefstruct
195+
{
196+
constchar*label;
197+
intsqlerrstate;
198+
}TclExceptionNameMap;
199+
200+
staticconstTclExceptionNameMapexception_name_map[]= {
201+
#include"pltclerrcodes.h"/* pgrminclude ignore */
202+
{NULL,0}
203+
};
204+
191205
/**********************************************************************
192206
* Forward declarations
193207
**********************************************************************/
@@ -213,6 +227,7 @@ static pltcl_proc_desc *compile_pltcl_function(Oid fn_oid, Oid tgreloid,
213227
staticintpltcl_elog(ClientDatacdata,Tcl_Interp*interp,
214228
intobjc,Tcl_Obj*constobjv[]);
215229
staticvoidpltcl_construct_errorCode(Tcl_Interp*interp,ErrorData*edata);
230+
staticconstchar*pltcl_get_condition_name(intsqlstate);
216231
staticintpltcl_quote(ClientDatacdata,Tcl_Interp*interp,
217232
intobjc,Tcl_Obj*constobjv[]);
218233
staticintpltcl_argisnull(ClientDatacdata,Tcl_Interp*interp,
@@ -1681,6 +1696,10 @@ pltcl_construct_errorCode(Tcl_Interp *interp, ErrorData *edata)
16811696
Tcl_NewStringObj("SQLSTATE",-1));
16821697
Tcl_ListObjAppendElement(interp,obj,
16831698
Tcl_NewStringObj(unpack_sql_state(edata->sqlerrcode),-1));
1699+
Tcl_ListObjAppendElement(interp,obj,
1700+
Tcl_NewStringObj("condition",-1));
1701+
Tcl_ListObjAppendElement(interp,obj,
1702+
Tcl_NewStringObj(pltcl_get_condition_name(edata->sqlerrcode),-1));
16841703
Tcl_ListObjAppendElement(interp,obj,
16851704
Tcl_NewStringObj("message",-1));
16861705
UTF_BEGIN;
@@ -1806,6 +1825,23 @@ pltcl_construct_errorCode(Tcl_Interp *interp, ErrorData *edata)
18061825
}
18071826

18081827

1828+
/**********************************************************************
1829+
* pltcl_get_condition_name()- find name for SQLSTATE
1830+
**********************************************************************/
1831+
staticconstchar*
1832+
pltcl_get_condition_name(intsqlstate)
1833+
{
1834+
inti;
1835+
1836+
for (i=0;exception_name_map[i].label!=NULL;i++)
1837+
{
1838+
if (exception_name_map[i].sqlerrstate==sqlstate)
1839+
returnexception_name_map[i].label;
1840+
}
1841+
return"unrecognized_sqlstate";
1842+
}
1843+
1844+
18091845
/**********************************************************************
18101846
* pltcl_quote()- quote literal strings that are to
18111847
* be used in SPI_execute query strings

‎src/pl/tcl/sql/pltcl_setup.sql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -602,10 +602,10 @@ create function tcl_error_handling_test() returns text as $$
602602
global errorCode
603603
if {[catch { spi_exec"select no_such_column from foo;" }]} {
604604
arrayset errArray $errorCode
605-
if {$errArray(SQLSTATE)=="42P01"} {
605+
if {$errArray(condition)=="undefined_table"} {
606606
return"expected error: $errArray(message)"
607607
} else {
608-
return"unexpected error: $errArray(SQLSTATE) $errArray(message)"
608+
return"unexpected error: $errArray(condition) $errArray(message)"
609609
}
610610
} else {
611611
return"no error"

‎src/tools/msvc/Solution.pm

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,17 @@ s{PG_VERSION_STR "[^"]+"}{__STRINGIFY(x) #x\n#define __STRINGIFY2(z) __STRINGIFY
350350
);
351351
}
352352

353+
if ($self->{options}->{tcl}
354+
&& IsNewer(
355+
'src/pl/tcl/pltclerrcodes.h',
356+
'src/backend/utils/errcodes.txt'))
357+
{
358+
print"Generating pltclerrcodes.h...\n";
359+
system(
360+
'perl src/pl/tcl/generate-pltclerrcodes.pl src/backend/utils/errcodes.txt > src/pl/tcl/pltclerrcodes.h'
361+
);
362+
}
363+
353364
if (IsNewer(
354365
'src/backend/utils/sort/qsort_tuple.c',
355366
'src/backend/utils/sort/gen_qsort_tuple.pl'))

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp