Skip to content

Commit 193a97c

Browse files
committed
Fix plperl's elog() function to convert elog(ERROR) into Perl croak(),
rather than longjmp'ing clear out of Perl and thereby leaving Perl in a broken state. Also some minor prettification of error messages. Still need to do something with spi_exec_query() error handling.
1 parent d5013ab commit 193a97c

File tree

2 files changed

+74
-16
lines changed

2 files changed

+74
-16
lines changed

src/pl/plperl/SPI.xs

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,40 @@
1010
#include "spi_internal.h"
1111

1212

13+
/*
14+
* Implementation of plperl's elog() function
15+
*
16+
* If the error level is less than ERROR, we'll just emit the message and
17+
* return. When it is ERROR, elog() will longjmp, which we catch and
18+
* turn into a Perl croak(). Note we are assuming that elog() can't have
19+
* any internal failures that are so bad as to require a transaction abort.
20+
*
21+
* This is out-of-line to suppress "might be clobbered by longjmp" warnings.
22+
*/
23+
static void
24+
do_spi_elog(int level, char *message)
25+
{
26+
MemoryContext oldcontext = CurrentMemoryContext;
27+
28+
PG_TRY();
29+
{
30+
elog(level, "%s", message);
31+
}
32+
PG_CATCH();
33+
{
34+
ErrorData *edata;
35+
36+
/* Must reset elog.c's state */
37+
MemoryContextSwitchTo(oldcontext);
38+
edata = CopyErrorData();
39+
FlushErrorState();
40+
41+
/* Punt the error to Perl */
42+
croak("%s", edata->message);
43+
}
44+
PG_END_TRY();
45+
}
46+
1347

1448
MODULE = SPI PREFIX = spi_
1549

@@ -21,8 +55,11 @@ spi_elog(level, message)
2155
int level
2256
char* message
2357
CODE:
24-
elog(level, message);
25-
58+
if (level > ERROR) /* no PANIC allowed thanks */
59+
level = ERROR;
60+
if (level < DEBUG5)
61+
level = DEBUG5;
62+
do_spi_elog(level, message);
2663

2764
int
2865
spi_DEBUG()
@@ -47,11 +84,13 @@ spi_spi_exec_query(query, ...)
4784
char* query;
4885
PREINIT:
4986
HV *ret_hash;
50-
int limit=0;
87+
int limit = 0;
5188
CODE:
52-
if (items>2) Perl_croak(aTHX_ "Usage: spi_exec_query(query, limit) or spi_exec_query(query)");
53-
if (items == 2) limit = SvIV(ST(1));
54-
ret_hash=plperl_spi_exec(query, limit);
55-
RETVAL = newRV_noinc((SV*)ret_hash);
89+
if (items > 2)
90+
croak("Usage: spi_exec_query(query, limit) or spi_exec_query(query)");
91+
if (items == 2)
92+
limit = SvIV(ST(1));
93+
ret_hash = plperl_spi_exec(query, limit);
94+
RETVAL = newRV_noinc((SV*) ret_hash);
5695
OUTPUT:
5796
RETVAL

src/pl/plperl/plperl.c

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,14 @@
3333
* ENHANCEMENTS, OR MODIFICATIONS.
3434
*
3535
* IDENTIFICATION
36-
* $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.58 2004/11/18 21:35:42 tgl Exp $
36+
* $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.59 2004/11/20 19:07:40 tgl Exp $
3737
*
3838
**********************************************************************/
3939

4040
#include "postgres.h"
4141

4242
/* system stuff */
43+
#include <ctype.h>
4344
#include <fcntl.h>
4445
#include <unistd.h>
4546

@@ -281,6 +282,21 @@ plperl_safe_init(void)
281282
}
282283

283284

285+
/*
286+
* Perl likes to put a newline after its error messages; clean up such
287+
*/
288+
static char *
289+
strip_trailing_ws(const char *msg)
290+
{
291+
char *res = pstrdup(msg);
292+
int len = strlen(res);
293+
294+
while (len > 0 && isspace((unsigned char) res[len-1]))
295+
res[--len] = '\0';
296+
return res;
297+
}
298+
299+
284300
static HV *
285301
plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc)
286302
{
@@ -496,7 +512,7 @@ plperl_get_elem(HV *hash, char *key)
496512
{
497513
SV **svp = hv_fetch(hash, key, strlen(key), FALSE);
498514
if (!svp)
499-
elog(ERROR, "plperl: key '%s' not found", key);
515+
elog(ERROR, "plperl: key \"%s\" not found", key);
500516
return SvTYPE(*svp) == SVt_NULL ? NULL : SvPV(*svp, PL_na);
501517
}
502518

@@ -533,7 +549,7 @@ plperl_modify_tuple(HV *hvTD, TriggerData *tdata, HeapTuple otup, Oid fn_oid)
533549
plkeys = plperl_get_keys(hvNew);
534550
natts = av_len(plkeys) + 1;
535551
if (natts != tupdesc->natts)
536-
elog(ERROR, "plperl: $_TD->{new} has an incorrect number of keys.");
552+
elog(ERROR, "plperl: $_TD->{new} has an incorrect number of keys");
537553

538554
modattrs = palloc0(natts * sizeof(int));
539555
modvalues = palloc0(natts * sizeof(Datum));
@@ -550,7 +566,7 @@ plperl_modify_tuple(HV *hvTD, TriggerData *tdata, HeapTuple otup, Oid fn_oid)
550566
attn = modattrs[i] = SPI_fnumber(tupdesc, platt);
551567

552568
if (attn == SPI_ERROR_NOATTRIBUTE)
553-
elog(ERROR, "plperl: invalid attribute `%s' in tuple.", platt);
569+
elog(ERROR, "plperl: invalid attribute \"%s\" in tuple", platt);
554570
atti = attn - 1;
555571

556572
plval = plperl_get_elem(hvNew, platt);
@@ -581,7 +597,7 @@ plperl_modify_tuple(HV *hvTD, TriggerData *tdata, HeapTuple otup, Oid fn_oid)
581597
pfree(modvalues);
582598
pfree(modnulls);
583599
if (rtup == NULL)
584-
elog(ERROR, "plperl: SPI_modifytuple failed -- error: %d", SPI_result);
600+
elog(ERROR, "plperl: SPI_modifytuple failed -- error: %d", SPI_result);
585601

586602
return rtup;
587603
}
@@ -690,7 +706,8 @@ plperl_create_sub(char *s, bool trusted)
690706
PUTBACK;
691707
FREETMPS;
692708
LEAVE;
693-
elog(ERROR, "creation of function failed: %s", SvPV(ERRSV, PL_na));
709+
elog(ERROR, "creation of function failed: %s",
710+
strip_trailing_ws(SvPV(ERRSV, PL_na)));
694711
}
695712

696713
/*
@@ -816,7 +833,8 @@ plperl_call_perl_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo)
816833
PUTBACK;
817834
FREETMPS;
818835
LEAVE;
819-
elog(ERROR, "error from function: %s", SvPV(ERRSV, PL_na));
836+
elog(ERROR, "error from function: %s",
837+
strip_trailing_ws(SvPV(ERRSV, PL_na)));
820838
}
821839

822840
retval = newSVsv(POPs);
@@ -860,7 +878,7 @@ plperl_call_perl_trigger_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo, S
860878
PUTBACK;
861879
FREETMPS;
862880
LEAVE;
863-
elog(ERROR, "plperl: didn't get a return item from function");
881+
elog(ERROR, "didn't get a return item from trigger function");
864882
}
865883

866884
if (SvTRUE(ERRSV))
@@ -869,7 +887,8 @@ plperl_call_perl_trigger_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo, S
869887
PUTBACK;
870888
FREETMPS;
871889
LEAVE;
872-
elog(ERROR, "plperl: error from function: %s", SvPV(ERRSV, PL_na));
890+
elog(ERROR, "error from trigger function: %s",
891+
strip_trailing_ws(SvPV(ERRSV, PL_na)));
873892
}
874893

875894
retval = newSVsv(POPs);

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