1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
/* this must be first: */
#include "postgres.h"
/* Defined by Perl */
#undef _
/* perl stuff */
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#include "spi_internal.h"
/*
* Implementation of plperl's elog() function
*
* If the error level is less than ERROR, we'll just emit the message and
* return. When it is ERROR, elog() will longjmp, which we catch and
* turn into a Perl croak(). Note we are assuming that elog() can't have
* any internal failures that are so bad as to require a transaction abort.
*
* This is out-of-line to suppress "might be clobbered by longjmp" warnings.
*/
static void
do_spi_elog(int level, char *message)
{
MemoryContext oldcontext = CurrentMemoryContext;
PG_TRY();
{
elog(level, "%s", message);
}
PG_CATCH();
{
ErrorData *edata;
/* Must reset elog.c's state */
MemoryContextSwitchTo(oldcontext);
edata = CopyErrorData();
FlushErrorState();
/* Punt the error to Perl */
croak("%s", edata->message);
}
PG_END_TRY();
}
MODULE = SPI PREFIX = spi_
PROTOTYPES: ENABLE
VERSIONCHECK: DISABLE
void
spi_elog(level, message)
int level
char* message
CODE:
if (level > ERROR) /* no PANIC allowed thanks */
level = ERROR;
if (level < DEBUG5)
level = DEBUG5;
do_spi_elog(level, message);
int
spi_DEBUG()
int
spi_LOG()
int
spi_INFO()
int
spi_NOTICE()
int
spi_WARNING()
int
spi_ERROR()
SV*
spi_spi_exec_query(query, ...)
char* query;
PREINIT:
HV *ret_hash;
int limit = 0;
CODE:
if (items > 2)
croak("Usage: spi_exec_query(query, limit) or spi_exec_query(query)");
if (items == 2)
limit = SvIV(ST(1));
ret_hash = plperl_spi_exec(query, limit);
RETVAL = newRV_noinc((SV*) ret_hash);
OUTPUT:
RETVAL
void
spi_return_next(rv)
SV *rv;
CODE:
plperl_return_next(rv);
BOOT:
items = 0; /* avoid 'unused variable' warning */
|