8000 WIP · johto/postgres@d9e3a12 · GitHub
[go: up one dir, main page]

Skip to content

Commit d9e3a12

Browse files
committed
WIP
1 parent 4477704 commit d9e3a12

File tree

4 files changed

+106
-5
lines changed

4 files changed

+106
-5
lines changed

src/pl/plperl/Util.xs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,37 @@ do_util_elog(int level, SV *msg)
6363
PG_END_TRY();
6464
}
6565

66+
/*
67+
* Implementation of plperl's ereport() function
68+
*
69+
* This is exactly like elog(), except the second argument is a hash which may
70+
* contain of the components of an error.
71+
*/
72+
static void
73+
do_util_ereport(int level, SV *error)
74+
{
75+
MemoryContext oldcontext = CurrentMemoryContext;
76+
77+
PG_TRY();
78+
{
79+
plperl_ereport(level, error);
80+
}
81+
PG_CATCH();
82+
{
83+
ErrorData *edata;
84+
85+
/* Must reset elog.c's state */
86+
MemoryContextSwitchTo(oldcontext);
87+
edata = CopyErrorData();
88+
FlushErrorState();
89+
90+
/* Punt the error to Perl */
91+
plperl_croak_edata(edata);
92+
}
93+
PG_END_TRY();
94+
}
95+
96+
6697
static text *
6798
sv2text(SV *sv)
6899
{
@@ -107,6 +138,17 @@ util_elog(level, msg)
107138
level = DEBUG5;
108139
do_util_elog(level, msg);
109140

141+
void
142+
util_ereport(level, error)
143+
int level
144+
SV *error
145+
CODE:
146+
if (level > ERROR) /* no PANIC allowed thanks */
147+
level = ERROR;
148+
if (level < DEBUG5)
149+
level = DEBUG5;
150+
do_util_ereport(level, error);
151+
110152
SV *
111153
util_quote_literal(sv)
112154
SV *sv

src/pl/plperl/plc_perlboot.pl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,18 @@ sub ::encode_array_constructor
117117

118118
1;
119119
}
120+
121+
{
122+
123+
package PostgreSQL::InServer::ERROR;
124+
use strict;
125+
use warnings;
126+
127+
use overload
128+
'""' => \&to_str;
129+
130+
sub to_str
131+
{
132+
return shift->{'message'};
133+
}
134+
}

src/pl/plperl/plperl.c

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2134,9 +2134,11 @@ plperl_call_perl_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo)
21342134
PUTBACK;
21352135
FREETMPS;
21362136
LEAVE;
2137-
/* XXX need to find a way to assign an errcode here */
2138-
ereport(ERROR,
2139-
(errmsg("%s", strip_trailing_ws(sv2cstr(ERRSV)))));
2137+
if (SvOK(ERRSV) && SvROK(ERRSV) && sv_isa(ERRSV, "PostgreSQL::InServer::ERROR"))
2138+
plperl_ereport(ERROR, ERRSV);
2139+
else
2140+
ereport(ERROR,
2141+
(errmsg("%s", strip_trailing_ws(sv2cstr(ERRSV)))));
21402142
}
21412143

21422144
retval = newSVsv(POPs);
@@ -3004,7 +3006,7 @@ plperl_spi_exec(char *query, int limit)
30043006
SPI_restore_connection();
30053007

30063008
/* Punt the error to Perl */
3007-
croak("%s", edata->message);
3009+
plperl_croak_edata(edata);
30083010

30093011
/* Can't get here, but keep compiler quiet */
30103012
return NULL;
@@ -3014,7 +3016,6 @@ plperl_spi_exec(char *query, int limit)
30143016
return ret_hv;
30153017
}
30163018

3017-
30183019
static HV *
30193020
plperl_spi_execute_fetch_result(SPITupleTable *tuptable, int processed,
30203021
int status)
@@ -3164,6 +3165,47 @@ plperl_return_next(SV *sv)
31643165
MemoryContextReset(current_call_data->tmp_cxt);
31653166
}
31663167

3168+
void
3169+
plperl_croak_edata(const ErrorData *edata)
3170+
{
3171+
HV *hv;
3172+
3173+
hv = newHV();
3174+
(void) hv_store(hv, "message", 7, newSVpv(edata->message, 0), 0);
3175+
(void) hv_store(hv, "context", 7, newSVpv(edata->context, 0), 0);
3176+
(void) hv_store(hv, "hint", 4, newSVpv(edata->hint, 0), 0);
3177+
3178+
croak_sv(sv_bless(newRV_noinc((SV *) hv),
3179+
gv_stashpv("PostgreSQL::InServer::ERROR", 0)));
3180+
}
3181+
3182+
void
3183+
plperl_ereport(int level, SV *error)
3184+
{
3185+
HV *hv;
3186+
SV **sv;
3187+
const char *err_message;
3188+
const char *err_hint = NULL;
3189+
3190+
if (!SvOK(error) || !SvROK(error))
3191+
elog(ERROR, "wtf bro");
3192+
if (SvTYPE(SvRV(error)) != SVt_PVHV)
3193+
elog(ERROR, "gimme a hash yo");
3194+
3195+
hv = (HV *) SvRV(error);
3196+
sv = hv_fetch_string(hv, "message");
3197+
if (sv && *sv && SvOK(*sv))
3198+
err_message = sv2cstr(*sv);
3199+
sv = hv_fetch_string(hv, "hint");
3200+
if (sv && *sv && SvOK(*sv))
3201+
err_hint = sv2cstr(*sv);
3202+
3203+
ereport(level,
3204+
/* TODO: handle all cases */
3205+
(errmsg_internal("%s", err_message),
3206+
(err_hint != NULL) ? errhint("%s", err_hint) : 0));
3207+
}
3208+
31673209

31683210
SV *
31693211
plperl_spi_query(char *query)

src/pl/plperl/plperl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@
9393
/* declare routines from plperl.c for access by .xs files */
9494
HV *plperl_spi_exec(char *, int);
9595
void plperl_return_next(SV *);
96+
void plperl_croak_edata(const ErrorData *);
97+
void plperl_ereport(int, SV *);
9698
SV *plperl_spi_query(char *);
9799
SV *plperl_spi_fetchrow(char *);
98100
SV *plperl_spi_prepare(char *, int, SV **);

0 commit comments

Comments
 (0)
0