Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit ad4d2e9

Browse files
committed
Be more consistent about reporting SPI errors in the various PLs.
Create a shared function to convert a SPI error code into a string (replacing near-duplicate code in several PLs), and use it anywhere that a SPI function call error is reported.
1 parent da4a0da commit ad4d2e9

File tree

7 files changed

+137
-225
lines changed

7 files changed

+137
-225
lines changed

src/backend/executor/spi.c

+63-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.121 2004/07/27 05:10:51 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.122 2004/07/31 20:55:41 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -989,6 +989,68 @@ SPI_is_cursor_plan(void *plan)
989989
return false;
990990
}
991991

992+
/*
993+
* SPI_result_code_string --- convert any SPI return code to a string
994+
*
995+
* This is often useful in error messages. Most callers will probably
996+
* only pass negative (error-case) codes, but for generality we recognize
997+
* the success codes too.
998+
*/
999+
const char *
1000+
SPI_result_code_string(int code)
1001+
{
1002+
static char buf[64];
1003+
1004+
switch (code)
1005+
{
1006+
case SPI_ERROR_CONNECT:
1007+
return "SPI_ERROR_CONNECT";
1008+
case SPI_ERROR_COPY:
1009+
return "SPI_ERROR_COPY";
1010+
case SPI_ERROR_OPUNKNOWN:
1011+
return "SPI_ERROR_OPUNKNOWN";
1012+
case SPI_ERROR_UNCONNECTED:
1013+
return "SPI_ERROR_UNCONNECTED";
1014+
case SPI_ERROR_CURSOR:
1015+
return "SPI_ERROR_CURSOR";
1016+
case SPI_ERROR_ARGUMENT:
1017+
return "SPI_ERROR_ARGUMENT";
1018+
case SPI_ERROR_PARAM:
1019+
return "SPI_ERROR_PARAM";
1020+
case SPI_ERROR_TRANSACTION:
1021+
return "SPI_ERROR_TRANSACTION";
1022+
case SPI_ERROR_NOATTRIBUTE:
1023+
return "SPI_ERROR_NOATTRIBUTE";
1024+
case SPI_ERROR_NOOUTFUNC:
1025+
return "SPI_ERROR_NOOUTFUNC";
1026+
case SPI_ERROR_TYPUNKNOWN:
1027+
return "SPI_ERROR_TYPUNKNOWN";
1028+
case SPI_OK_CONNECT:
1029+
return "SPI_OK_CONNECT";
1030+
case SPI_OK_FINISH:
1031+
return "SPI_OK_FINISH";
1032+
case SPI_OK_FETCH:
1033+
return "SPI_OK_FETCH";
1034+
case SPI_OK_UTILITY:
1035+
return "SPI_OK_UTILITY";
1036+
case SPI_OK_SELECT:
1037+
return "SPI_OK_SELECT";
1038+
case SPI_OK_SELINTO:
1039+
return "SPI_OK_SELINTO";
1040+
case SPI_OK_INSERT:
1041+
return "SPI_OK_INSERT";
1042+
case SPI_OK_DELETE:
1043+
return "SPI_OK_DELETE";
1044+
case SPI_OK_UPDATE:
1045+
return "SPI_OK_UPDATE";
1046+
case SPI_OK_CURSOR:
1047+
return "SPI_OK_CURSOR";
1048+
}
1049+
/* Unrecognized code ... return something useful ... */
1050+
sprintf(buf, "Unrecognized SPI code %d", code);
1051+
return buf;
1052+
}
1053+
9921054
/* =================== private functions =================== */
9931055

9941056
/*

src/include/executor/spi.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
*
33
* spi.h
44
*
5-
* $PostgreSQL: pgsql/src/include/executor/spi.h,v 1.45 2004/07/01 00:51:41 tgl Exp $
5+
* $PostgreSQL: pgsql/src/include/executor/spi.h,v 1.46 2004/07/31 20:55:42 tgl Exp $
66
*
77
*-------------------------------------------------------------------------
88
*/
@@ -93,6 +93,7 @@ extern int SPI_freeplan(void *plan);
9393
extern Oid SPI_getargtypeid(void *plan, int argIndex);
9494
extern int SPI_getargcount(void *plan);
9595
extern bool SPI_is_cursor_plan(void *plan);
96+
extern const char *SPI_result_code_string(int code);
9697

9798
extern HeapTuple SPI_copytuple(HeapTuple tuple);
9899
extern HeapTupleHeader SPI_returntuple(HeapTuple tuple, TupleDesc tupdesc);

src/pl/plperl/spi_internal.c

+16-75
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@
99

1010
#include "spi_internal.h"
1111

12-
static char* plperl_spi_status_string(int);
13-
1412
static HV* plperl_spi_execute_fetch_result(SPITupleTable*, int, int );
1513

14+
1615
int
1716
spi_DEBUG(void)
1817
{
@@ -93,93 +92,35 @@ plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc)
9392
static HV*
9493
plperl_spi_execute_fetch_result(SPITupleTable *tuptable, int processed, int status)
9594
{
96-
9795
HV *result;
98-
AV *rows;
99-
int i;
10096

10197
result = newHV();
102-
rows = newAV();
10398

104-
if (status == SPI_OK_UTILITY)
105-
{
106-
hv_store(result, "status", strlen("status"), newSVpv("SPI_OK_UTILITY",0), 0);
107-
hv_store(result, "processed", strlen("processed"), newSViv(processed), 0);
108-
}
109-
else if (status != SPI_OK_SELECT)
110-
{
111-
hv_store(result, "status", strlen("status"), newSVpv((char*)plperl_spi_status_string(status),0), 0);
112-
hv_store(result, "processed", strlen("processed"), newSViv(processed), 0);
113-
}
114-
else
99+
hv_store(result, "status", strlen("status"),
100+
newSVpv((char*)SPI_result_code_string(status),0), 0);
101+
hv_store(result, "processed", strlen("processed"),
102+
newSViv(processed), 0);
103+
104+
if (status == SPI_OK_SELECT)
115105
{
116-
hv_store(result, "status", strlen("status"), newSVpv((char*)plperl_spi_status_string(status),0), 0);
117-
hv_store(result, "processed", strlen("processed"), newSViv(processed), 0);
118106
if (processed)
119107
{
108+
AV *rows;
120109
HV *row;
110+
int i;
111+
112+
rows = newAV();
121113
for (i = 0; i < processed; i++)
122114
{
123115
row = plperl_hash_from_tuple(tuptable->vals[i], tuptable->tupdesc);
124-
av_store(rows, i, newRV_noinc((SV*)row));
116+
av_store(rows, i, newRV_noinc((SV*)row));
125117
}
126-
hv_store(result, "rows", strlen("rows"), newRV_noinc((SV*)rows), 0);
127-
SPI_freetuptable(tuptable);
118+
hv_store(result, "rows", strlen("rows"),
119+
newRV_noinc((SV*)rows), 0);
128120
}
129121
}
130-
return result;
131-
}
132122

133-
static char*
134-
plperl_spi_status_string(int status)
135-
{
136-
switch(status){
137-
/*errors*/
138-
case SPI_ERROR_TYPUNKNOWN:
139-
return "SPI_ERROR_TYPUNKNOWN";
140-
case SPI_ERROR_NOOUTFUNC:
141-
return "SPI_ERROR_NOOUTFUNC";
142-
case SPI_ERROR_NOATTRIBUTE:
143-
return "SPI_ERROR_NOATTRIBUTE";
144-
case SPI_ERROR_TRANSACTION:
145-
return "SPI_ERROR_TRANSACTION";
146-
case SPI_ERROR_PARAM:
147-
return "SPI_ERROR_PARAM";
148-
case SPI_ERROR_ARGUMENT:
149-
return "SPI_ERROR_ARGUMENT";
150-
case SPI_ERROR_CURSOR:
151-
return "SPI_ERROR_CURSOR";
152-
case SPI_ERROR_UNCONNECTED:
153-
return "SPI_ERROR_UNCONNECTED";
154-
case SPI_ERROR_OPUNKNOWN:
155-
return "SPI_ERROR_OPUNKNOWN";
156-
case SPI_ERROR_COPY:
157-
return "SPI_ERROR_COPY";
158-
case SPI_ERROR_CONNECT:
159-
return "SPI_ERROR_CONNECT";
160-
/*ok*/
161-
case SPI_OK_CONNECT:
162-
return "SPI_OK_CONNECT";
163-
case SPI_OK_FINISH:
164-
return "SPI_OK_FINISH";
165-
case SPI_OK_FETCH:
166-
return "SPI_OK_FETCH";
167-
case SPI_OK_UTILITY:
168-
return "SPI_OK_UTILITY";
169-
case SPI_OK_SELECT:
170-
return "SPI_OK_SELECT";
171-
case SPI_OK_SELINTO:
172-
return "SPI_OK_SELINTO";
173-
case SPI_OK_INSERT:
174-
return "SPI_OK_INSERT";
175-
case SPI_OK_DELETE:
176-
return "SPI_OK_DELETE";
177-
case SPI_OK_UPDATE:
178-
return "SPI_OK_UPDATE";
179-
case SPI_OK_CURSOR:
180-
return "SPI_OK_CURSOR";
181-
}
123+
SPI_freetuptable(tuptable);
182124

183-
return "Unknown or Invalid code";
125+
return result;
184126
}
185-

src/pl/plpgsql/src/pl_exec.c

+26-18
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.109 2004/07/31 07:39:20 tgl Exp $
6+
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.110 2004/07/31 20:55:44 tgl Exp $
77
*
88
* This software is copyrighted by Jan Wieck - Hamburg.
99
*
@@ -904,6 +904,7 @@ exec_stmt_block(PLpgSQL_execstate * estate, PLpgSQL_stmt_block * block)
904904
*/
905905
MemoryContext oldcontext = CurrentMemoryContext;
906906
volatile bool caught = false;
907+
int xrc;
907908

908909
/*
909910
* Start a subtransaction, and re-connect to SPI within it
@@ -912,8 +913,9 @@ exec_stmt_block(PLpgSQL_execstate * estate, PLpgSQL_stmt_block * block)
912913
BeginInternalSubTransaction(NULL);
913914
/* Want to run statements inside function's memory context */
914915
MemoryContextSwitchTo(oldcontext);
915-
if (SPI_connect() != SPI_OK_CONNECT)
916-
elog(ERROR, "SPI_connect failed");
916+
if ((xrc = SPI_connect()) != SPI_OK_CONNECT)
917+
elog(ERROR, "SPI_connect failed: %s",
918+
SPI_result_code_string(xrc));
917919

918920
PG_TRY();
919921
{
@@ -961,8 +963,9 @@ exec_stmt_block(PLpgSQL_execstate * estate, PLpgSQL_stmt_block * block)
961963
/* Commit the inner transaction, return to outer xact context */
962964
if (!caught)
963965
{
964-
if (SPI_finish() != SPI_OK_FINISH)
965-
elog(ERROR, "SPI_finish failed");
966+
if ((xrc = SPI_finish()) != SPI_OK_FINISH)
967+
elog(ERROR, "SPI_finish failed: %s",
968+
SPI_result_code_string(xrc));
966969
ReleaseCurrentSubTransaction();
967970
MemoryContextSwitchTo(oldcontext);
968971
SPI_pop();
@@ -2069,7 +2072,8 @@ exec_prepare_plan(PLpgSQL_execstate * estate,
20692072
*/
20702073
plan = SPI_prepare(expr->query, expr->nparams, argtypes);
20712074
if (plan == NULL)
2072-
elog(ERROR, "SPI_prepare() failed on \"%s\"", expr->query);
2075+
elog(ERROR, "SPI_prepare failed for \"%s\": %s",
2076+
expr->query, SPI_result_code_string(SPI_result));
20732077
expr->plan = SPI_saveplan(plan);
20742078
spi_plan = (_SPI_plan *) expr->plan;
20752079
expr->plan_argtypes = spi_plan->argtypes;
@@ -2151,7 +2155,8 @@ exec_stmt_execsql(PLpgSQL_execstate * estate,
21512155
errhint("If you want to discard the results, use PERFORM instead.")));
21522156

21532157
default:
2154-
elog(ERROR, "error executing query \"%s\"", expr->query);
2158+
elog(ERROR, "SPI_execp failed executing query \"%s\": %s",
2159+
expr->query, SPI_result_code_string(rc));
21552160
}
21562161

21572162
/*
@@ -2250,8 +2255,8 @@ exec_stmt_dynexecute(PLpgSQL_execstate * estate,
22502255
}
22512256

22522257
default:
2253-
elog(ERROR, "unexpected error %d in EXECUTE of query \"%s\"",
2254-
exec_res, querystr);
2258+
elog(ERROR, "SPI_exec failed executing query \"%s\": %s",
2259+
querystr, SPI_result_code_string(exec_res));
22552260
break;
22562261
}
22572262

@@ -2321,11 +2326,12 @@ exec_stmt_dynfors(PLpgSQL_execstate * estate, PLpgSQL_stmt_dynfors * stmt)
23212326
*/
23222327
plan = SPI_prepare(querystr, 0, NULL);
23232328
if (plan == NULL)
2324-
elog(ERROR, "SPI_prepare() failed for dynamic query \"%s\"", querystr);
2329+
elog(ERROR, "SPI_prepare failed for \"%s\": %s",
2330+
querystr, SPI_result_code_string(SPI_result));
23252331
portal = SPI_cursor_open(NULL, plan, NULL, NULL);
23262332
if (portal == NULL)
2327-
elog(ERROR, "failed to open implicit cursor for dynamic query \"%s\"",
2328-
querystr);
2333+
elog(ERROR, "could not open implicit cursor for query \"%s\": %s",
2334+
querystr, SPI_result_code_string(SPI_result));
23292335
pfree(querystr);
23302336
SPI_freeplan(plan);
23312337

@@ -2512,11 +2518,12 @@ exec_stmt_open(PLpgSQL_execstate * estate, PLpgSQL_stmt_open * stmt)
25122518
*/
25132519
curplan = SPI_prepare(querystr, 0, NULL);
25142520
if (curplan == NULL)
2515-
elog(ERROR, "SPI_prepare() failed for dynamic query \"%s\"",
2516-
querystr);
2521+
elog(ERROR, "SPI_prepare failed for \"%s\": %s",
2522+
querystr, SPI_result_code_string(SPI_result));
25172523
portal = SPI_cursor_open(curname, curplan, NULL, NULL);
25182524
if (portal == NULL)
2519-
elog(ERROR, "failed to open cursor");
2525+
elog(ERROR, "could not open cursor for query \"%s\": %s",
2526+
querystr, SPI_result_code_string(SPI_result));
25202527
pfree(querystr);
25212528
SPI_freeplan(curplan);
25222529

@@ -2609,7 +2616,8 @@ exec_stmt_open(PLpgSQL_execstate * estate, PLpgSQL_stmt_open * stmt)
26092616
*/
26102617
portal = SPI_cursor_open(curname, query->plan, values, nulls);
26112618
if (portal == NULL)
2612-
elog(ERROR, "failed to open cursor");
2619+
elog(ERROR, "could not open cursor: %s",
2620+
SPI_result_code_string(SPI_result));
26132621

26142622
pfree(values);
26152623
pfree(nulls);
@@ -3454,8 +3462,8 @@ exec_run_select(PLpgSQL_execstate * estate,
34543462
{
34553463
*portalP = SPI_cursor_open(NULL, expr->plan, values, nulls);
34563464
if (*portalP == NULL)
3457-
elog(ERROR, "failed to open implicit cursor for \"%s\"",
3458-
expr->query);
3465+
elog(ERROR, "could not open implicit cursor for query \"%s\": %s",
3466+
expr->query, SPI_result_code_string(SPI_result));
34593467
pfree(values);
34603468
pfree(nulls);
34613469
return SPI_OK_CURSOR;

0 commit comments

Comments
 (0)