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

Lines changed: 63 additions & 1 deletion
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

Lines changed: 2 additions & 1 deletion
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

Lines changed: 16 additions & 75 deletions
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

Lines changed: 26 additions & 18 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.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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy