plperl.c 42.7 KB
Newer Older
1 2 3 4 5 6
/**********************************************************************
 * plperl.c - perl as a procedural language for PostgreSQL
 *
 * IDENTIFICATION
 *
 *	  This software is copyrighted by Mark Hollomon
7
 *	  but is shameless cribbed from pltcl.c by Jan Wieck.
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
 *
 *	  The author hereby grants permission  to  use,  copy,	modify,
 *	  distribute,  and	license this software and its documentation
 *	  for any purpose, provided that existing copyright notices are
 *	  retained	in	all  copies  and  that	this notice is included
 *	  verbatim in any distributions. No written agreement, license,
 *	  or  royalty  fee	is required for any of the authorized uses.
 *	  Modifications to this software may be  copyrighted  by  their
 *	  author  and  need  not  follow  the licensing terms described
 *	  here, provided that the new terms are  clearly  indicated  on
 *	  the first page of each file where they apply.
 *
 *	  IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
 *	  PARTY  FOR  DIRECT,	INDIRECT,	SPECIAL,   INCIDENTAL,	 OR
 *	  CONSEQUENTIAL   DAMAGES  ARISING	OUT  OF  THE  USE  OF  THIS
 *	  SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
 *	  IF  THE  AUTHOR  HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
 *	  DAMAGE.
 *
 *	  THE  AUTHOR  AND	DISTRIBUTORS  SPECIFICALLY	 DISCLAIM	ANY
 *	  WARRANTIES,  INCLUDING,  BUT	NOT  LIMITED  TO,  THE	IMPLIED
 *	  WARRANTIES  OF  MERCHANTABILITY,	FITNESS  FOR  A  PARTICULAR
 *	  PURPOSE,	AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON
 *	  AN "AS IS" BASIS, AND THE AUTHOR	AND  DISTRIBUTORS  HAVE  NO
 *	  OBLIGATION   TO	PROVIDE   MAINTENANCE,	 SUPPORT,  UPDATES,
 *	  ENHANCEMENTS, OR MODIFICATIONS.
 *
35
 * IDENTIFICATION
B
Bruce Momjian 已提交
36
 *	  $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.93 2005/10/15 02:49:49 momjian Exp $
37
 *
38 39
 **********************************************************************/

40
#include "postgres.h"
41
/* Defined by Perl */
42
#undef _
43 44

/* system stuff */
45
#include <ctype.h>
46
#include <fcntl.h>
47
#include <unistd.h>
48 49

/* postgreSQL stuff */
50 51
#include "commands/trigger.h"
#include "executor/spi.h"
52
#include "funcapi.h"
53
#include "utils/lsyscache.h"
54
#include "utils/memutils.h"
55
#include "utils/typcache.h"
56
#include "miscadmin.h"
57
#include "mb/pg_wchar.h"
58 59

/* perl stuff */
B
Bruce Momjian 已提交
60 61
#include "EXTERN.h"
#include "perl.h"
62
#include "XSUB.h"
63
#include "ppport.h"
64
#include "spi_internal.h"
65

66 67 68 69 70 71
/* just in case these symbols aren't provided */
#ifndef pTHX_
#define pTHX_
#define pTHX void
#endif

72 73 74 75 76 77 78

/**********************************************************************
 * The information we cache about loaded procedures
 **********************************************************************/
typedef struct plperl_proc_desc
{
	char	   *proname;
79 80
	TransactionId fn_xmin;
	CommandId	fn_cmin;
81
	bool		fn_readonly;
82
	bool		lanpltrusted;
83
	bool		fn_retistuple;	/* true, if function returns tuple */
B
Bruce Momjian 已提交
84
	bool		fn_retisset;	/* true, if function returns set */
B
Bruce Momjian 已提交
85
	bool		fn_retisarray;	/* true if function returns array */
86
	Oid			result_oid;		/* Oid of result type */
B
Bruce Momjian 已提交
87
	FmgrInfo	result_in_func; /* I/O function and arg for result type */
88
	Oid			result_typioparam;
89 90
	int			nargs;
	FmgrInfo	arg_out_func[FUNC_MAX_ARGS];
91
	bool		arg_is_rowtype[FUNC_MAX_ARGS];
92
	SV		   *reference;
B
Bruce Momjian 已提交
93
}	plperl_proc_desc;
94 95 96 97 98 99


/**********************************************************************
 * Global data
 **********************************************************************/
static int	plperl_firstcall = 1;
100
static bool plperl_safe_init_done = false;
101
static PerlInterpreter *plperl_interp = NULL;
102 103
static HV  *plperl_proc_hash = NULL;

104 105
static bool plperl_use_strict = false;

106
/* these are saved and restored by plperl_call_handler */
107
static plperl_proc_desc *plperl_current_prodesc = NULL;
108 109 110
static FunctionCallInfo plperl_current_caller_info;
static Tuplestorestate *plperl_current_tuple_store;
static TupleDesc plperl_current_tuple_desc;
111

112 113 114 115
/**********************************************************************
 * Forward declarations
 **********************************************************************/
static void plperl_init_all(void);
116
static void plperl_init_interp(void);
117

B
Bruce Momjian 已提交
118
Datum		plperl_call_handler(PG_FUNCTION_ARGS);
119
Datum		plperl_validator(PG_FUNCTION_ARGS);
120
void		plperl_init(void);
121

122
HV		   *plperl_spi_exec(char *query, int limit);
123
SV		   *plperl_spi_query(char *);
124

125
static Datum plperl_func_handler(PG_FUNCTION_ARGS);
126

127
static Datum plperl_trigger_handler(PG_FUNCTION_ARGS);
128 129
static plperl_proc_desc *compile_plperl_function(Oid fn_oid, bool is_trigger);

130
static SV  *plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc);
131
static void plperl_init_shared_libs(pTHX);
132
static HV  *plperl_spi_execute_fetch_result(SPITupleTable *, int, int);
133

B
Bruce Momjian 已提交
134
void		plperl_return_next(SV *);
135

136 137 138 139 140 141 142
/*
 * This routine is a crock, and so is everyplace that calls it.  The problem
 * is that the cached form of plperl functions/queries is allocated permanently
 * (mostly via malloc()) and never released until backend exit.  Subsidiary
 * data structures such as fmgr info records therefore must live forever
 * as well.  A better implementation would store all this stuff in a per-
 * function memory context that could be reclaimed at need.  In the meantime,
143 144 145
 * fmgr_info_cxt must be called specifying TopMemoryContext so that whatever
 * it might allocate, and whatever the eventual function might allocate using
 * fn_mcxt, will live forever too.
146 147 148 149
 */
static void
perm_fmgr_info(Oid functionId, FmgrInfo *finfo)
{
150
	fmgr_info_cxt(functionId, finfo, TopMemoryContext);
151 152
}

153 154 155

/* Perform initialization during postmaster startup. */

156 157
void
plperl_init(void)
158 159 160 161
{
	if (!plperl_firstcall)
		return;

162
	DefineCustomBoolVariable(
B
Bruce Momjian 已提交
163 164 165 166 167 168
							 "plperl.use_strict",
	  "If true, will compile trusted and untrusted perl code in strict mode",
							 NULL,
							 &plperl_use_strict,
							 PGC_USERSET,
							 NULL, NULL);
169 170

	EmitWarningsOnPlaceholders("plperl");
171

172
	plperl_init_interp();
173 174 175
	plperl_firstcall = 0;
}

176 177 178

/* Perform initialization during backend startup. */

179 180 181 182 183 184
static void
plperl_init_all(void)
{
	if (plperl_firstcall)
		plperl_init();

185
	/* We don't need to do anything yet when a new backend starts. */
186 187
}

188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
/* Each of these macros must represent a single string literal */

#define PERLBOOT \
	"SPI::bootstrap(); use vars qw(%_SHARED);" \
	"sub ::plperl_warn { my $msg = shift; " \
	"       $msg =~ s/\\(eval \\d+\\) //g; &elog(&NOTICE, $msg); } " \
	"$SIG{__WARN__} = \\&::plperl_warn; " \
	"sub ::plperl_die { my $msg = shift; " \
	"       $msg =~ s/\\(eval \\d+\\) //g; die $msg; } " \
	"$SIG{__DIE__} = \\&::plperl_die; " \
	"sub ::mkunsafefunc {" \
	"      my $ret = eval(qq[ sub { $_[0] $_[1] } ]); " \
	"      $@ =~ s/\\(eval \\d+\\) //g if $@; return $ret; }" \
	"use strict; " \
	"sub ::mk_strict_unsafefunc {" \
	"      my $ret = eval(qq[ sub { use strict; $_[0] $_[1] } ]); " \
	"      $@ =~ s/\\(eval \\d+\\) //g if $@; return $ret; } " \
	"sub ::_plperl_to_pg_array {" \
	"  my $arg = shift; ref $arg eq 'ARRAY' || return $arg; " \
	"  my $res = ''; my $first = 1; " \
	"  foreach my $elem (@$arg) " \
	"  { " \
	"    $res .= ', ' unless $first; $first = undef; " \
	"    if (ref $elem) " \
	"    { " \
	"      $res .= _plperl_to_pg_array($elem); " \
	"    } " \
	"    else " \
	"    { " \
	"      my $str = qq($elem); " \
	"      $str =~ s/([\"\\\\])/\\\\$1/g; " \
	"      $res .= qq(\"$str\"); " \
	"    } " \
	"  } " \
	"  return qq({$res}); " \
	"} "

#define SAFE_MODULE \
	"require Safe; $Safe::VERSION"

#define SAFE_OK \
	"use vars qw($PLContainer); $PLContainer = new Safe('PLPerl');" \
	"$PLContainer->permit_only(':default');" \
	"$PLContainer->permit(qw[:base_math !:base_io sort time]);" \
	"$PLContainer->share(qw[&elog &spi_exec_query &return_next " \
	"&spi_query &spi_fetchrow " \
	"&_plperl_to_pg_array " \
	"&DEBUG &LOG &INFO &NOTICE &WARNING &ERROR %_SHARED ]);" \
	"sub ::mksafefunc {" \
	"      my $ret = $PLContainer->reval(qq[sub { $_[0] $_[1] }]); " \
	"      $@ =~ s/\\(eval \\d+\\) //g if $@; return $ret; }" \
	"$PLContainer->permit('require'); $PLContainer->reval('use strict;');" \
	"$PLContainer->deny('require');" \
	"sub ::mk_strict_safefunc {" \
	"      my $ret = $PLContainer->reval(qq[sub { BEGIN { strict->import(); } $_[0] $_[1] }]); " \
B
Bruce Momjian 已提交
243
	"      $@ =~ s/\\(eval \\d+\\) //g if $@; return $ret; }"
244 245 246 247 248 249 250 251 252 253 254 255

#define SAFE_BAD \
	"use vars qw($PLContainer); $PLContainer = new Safe('PLPerl');" \
	"$PLContainer->permit_only(':default');" \
	"$PLContainer->share(qw[&elog &ERROR ]);" \
	"sub ::mksafefunc { return $PLContainer->reval(qq[sub { " \
	"      elog(ERROR,'trusted Perl functions disabled - " \
	"      please upgrade Perl Safe module to version 2.09 or later');}]); }" \
	"sub ::mk_strict_safefunc { return $PLContainer->reval(qq[sub { " \
	"      elog(ERROR,'trusted Perl functions disabled - " \
	"      please upgrade Perl Safe module to version 2.09 or later');}]); }"

256 257

static void
258
plperl_init_interp(void)
259
{
B
Bruce Momjian 已提交
260
	static char *embedding[3] = {
261
		"", "-e", PERLBOOT
262 263
	};

264 265
	plperl_interp = perl_alloc();
	if (!plperl_interp)
266
		elog(ERROR, "could not allocate Perl interpreter");
267

268
	perl_construct(plperl_interp);
269
	perl_parse(plperl_interp, plperl_init_shared_libs, 3, embedding, NULL);
270
	perl_run(plperl_interp);
271

272
	plperl_proc_hash = newHV();
273 274
}

275 276 277 278

static void
plperl_safe_init(void)
{
B
Bruce Momjian 已提交
279
	SV		   *res;
280
	double		safe_version;
281

282
	res = eval_pv(SAFE_MODULE, FALSE);	/* TRUE = croak if failure */
283 284 285

	safe_version = SvNV(res);

286 287 288 289 290
	/*
	 * We actually want to reject safe_version < 2.09, but it's risky to
	 * assume that floating-point comparisons are exact, so use a slightly
	 * smaller comparison value.
	 */
B
Bruce Momjian 已提交
291
	if (safe_version < 2.0899)
292 293
	{
		/* not safe, so disallow all trusted funcs */
294
		eval_pv(SAFE_BAD, FALSE);
295 296 297
	}
	else
	{
298
		eval_pv(SAFE_OK, FALSE);
299
	}
300 301 302 303

	plperl_safe_init_done = true;
}

304

305 306 307 308 309 310
/*
 * Perl likes to put a newline after its error messages; clean up such
 */
static char *
strip_trailing_ws(const char *msg)
{
B
Bruce Momjian 已提交
311 312
	char	   *res = pstrdup(msg);
	int			len = strlen(res);
313

B
Bruce Momjian 已提交
314
	while (len > 0 && isspace((unsigned char) res[len - 1]))
315 316 317 318 319
		res[--len] = '\0';
	return res;
}


320 321
/* Build a tuple from a hash. */

322
static HeapTuple
B
Bruce Momjian 已提交
323
plperl_build_tuple_result(HV * perlhash, AttInMetadata *attinmeta)
324
{
325 326 327 328 329 330
	TupleDesc	td = attinmeta->tupdesc;
	char	  **values;
	SV		   *val;
	char	   *key;
	I32			klen;
	HeapTuple	tup;
331

332
	values = (char **) palloc0(td->natts * sizeof(char *));
333

334 335 336
	hv_iterinit(perlhash);
	while ((val = hv_iternextsv(perlhash, &key, &klen)))
	{
B
Bruce Momjian 已提交
337
		int			attn = SPI_fnumber(td, key);
338

339
		if (attn <= 0 || td->attrs[attn - 1]->attisdropped)
340 341 342 343
			ereport(ERROR,
					(errcode(ERRCODE_UNDEFINED_COLUMN),
					 errmsg("Perl hash contains nonexistent column \"%s\"",
							key)));
344
		if (SvOK(val) && SvTYPE(val) != SVt_NULL)
345
			values[attn - 1] = SvPV(val, PL_na);
346
	}
347 348 349 350 351
	hv_iterinit(perlhash);

	tup = BuildTupleFromCStrings(attinmeta, values);
	pfree(values);
	return tup;
352 353
}

354 355 356
/*
 * convert perl array to postgres string representation
 */
B
Bruce Momjian 已提交
357 358
static SV  *
plperl_convert_to_pg_array(SV * src)
359
{
B
Bruce Momjian 已提交
360 361 362 363
	SV		   *rv;
	int			count;

	dSP;
364

B
Bruce Momjian 已提交
365
	PUSHMARK(SP);
366
	XPUSHs(src);
B
Bruce Momjian 已提交
367
	PUTBACK;
368

369
	count = call_pv("::_plperl_to_pg_array", G_SCALAR);
370

B
Bruce Momjian 已提交
371
	SPAGAIN;
372 373

	if (count != 1)
374
		elog(ERROR, "unexpected _plperl_to_pg_array failure");
375 376 377

	rv = POPs;

B
Bruce Momjian 已提交
378 379 380
	PUTBACK;

	return rv;
381 382
}

383

384 385
/* Set up the arguments for a trigger call. */

386 387 388 389 390
static SV  *
plperl_trigger_build_args(FunctionCallInfo fcinfo)
{
	TriggerData *tdata;
	TupleDesc	tupdesc;
391
	int			i;
392 393 394 395 396
	char	   *level;
	char	   *event;
	char	   *relid;
	char	   *when;
	HV		   *hv;
397

398
	hv = newHV();
399 400 401 402

	tdata = (TriggerData *) fcinfo->context;
	tupdesc = tdata->tg_relation->rd_att;

403
	relid = DatumGetCString(
B
Bruce Momjian 已提交
404 405 406 407
							DirectFunctionCall1(oidout,
								  ObjectIdGetDatum(tdata->tg_relation->rd_id)
												)
		);
408 409 410

	hv_store(hv, "name", 4, newSVpv(tdata->tg_trigger->tgname, 0), 0);
	hv_store(hv, "relid", 5, newSVpv(relid, 0), 0);
411 412 413

	if (TRIGGER_FIRED_BY_INSERT(tdata->tg_event))
	{
414
		event = "INSERT";
415 416 417 418
		if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event))
			hv_store(hv, "new", 3,
					 plperl_hash_from_tuple(tdata->tg_trigtuple, tupdesc),
					 0);
419 420 421
	}
	else if (TRIGGER_FIRED_BY_DELETE(tdata->tg_event))
	{
422
		event = "DELETE";
423 424 425 426
		if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event))
			hv_store(hv, "old", 3,
					 plperl_hash_from_tuple(tdata->tg_trigtuple, tupdesc),
					 0);
427 428 429
	}
	else if (TRIGGER_FIRED_BY_UPDATE(tdata->tg_event))
	{
430
		event = "UPDATE";
431 432 433 434 435 436 437 438 439
		if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event))
		{
			hv_store(hv, "old", 3,
					 plperl_hash_from_tuple(tdata->tg_trigtuple, tupdesc),
					 0);
			hv_store(hv, "new", 3,
					 plperl_hash_from_tuple(tdata->tg_newtuple, tupdesc),
					 0);
		}
440
	}
441
	else
442
		event = "UNKNOWN";
443

444 445
	hv_store(hv, "event", 5, newSVpv(event, 0), 0);
	hv_store(hv, "argc", 4, newSViv(tdata->tg_trigger->tgnargs), 0);
446

447
	if (tdata->tg_trigger->tgnargs > 0)
448
	{
B
Bruce Momjian 已提交
449 450 451
		AV		   *av = newAV();

		for (i = 0; i < tdata->tg_trigger->tgnargs; i++)
452
			av_push(av, newSVpv(tdata->tg_trigger->tgargs[i], 0));
B
Bruce Momjian 已提交
453
		hv_store(hv, "args", 4, newRV_noinc((SV *) av), 0);
454
	}
455 456 457

	hv_store(hv, "relname", 7,
			 newSVpv(SPI_getrelname(tdata->tg_relation), 0), 0);
458 459

	if (TRIGGER_FIRED_BEFORE(tdata->tg_event))
460
		when = "BEFORE";
461
	else if (TRIGGER_FIRED_AFTER(tdata->tg_event))
462
		when = "AFTER";
463
	else
464 465
		when = "UNKNOWN";
	hv_store(hv, "when", 4, newSVpv(when, 0), 0);
466 467

	if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event))
468
		level = "ROW";
469
	else if (TRIGGER_FIRED_FOR_STATEMENT(tdata->tg_event))
470
		level = "STATEMENT";
471
	else
472 473
		level = "UNKNOWN";
	hv_store(hv, "level", 5, newSVpv(level, 0), 0);
474

B
Bruce Momjian 已提交
475
	return newRV_noinc((SV *) hv);
476 477 478
}


479
/* Set up the new tuple returned from a trigger. */
480

481
static HeapTuple
B
Bruce Momjian 已提交
482
plperl_modify_tuple(HV * hvTD, TriggerData *tdata, HeapTuple otup)
483 484 485 486
{
	SV		  **svp;
	HV		   *hvNew;
	HeapTuple	rtup;
487 488 489 490 491 492 493 494
	SV		   *val;
	char	   *key;
	I32			klen;
	int			slotsused;
	int		   *modattrs;
	Datum	   *modvalues;
	char	   *modnulls;

495 496 497 498 499
	TupleDesc	tupdesc;

	tupdesc = tdata->tg_relation->rd_att;

	svp = hv_fetch(hvTD, "new", 3, FALSE);
500
	if (!svp)
501 502 503
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_COLUMN),
				 errmsg("$_TD->{new} does not exist")));
504
	if (!SvOK(*svp) || SvTYPE(*svp) != SVt_RV || SvTYPE(SvRV(*svp)) != SVt_PVHV)
505 506 507
		ereport(ERROR,
				(errcode(ERRCODE_DATATYPE_MISMATCH),
				 errmsg("$_TD->{new} is not a hash reference")));
508 509
	hvNew = (HV *) SvRV(*svp);

510 511 512 513
	modattrs = palloc(tupdesc->natts * sizeof(int));
	modvalues = palloc(tupdesc->natts * sizeof(Datum));
	modnulls = palloc(tupdesc->natts * sizeof(char));
	slotsused = 0;
514

515 516
	hv_iterinit(hvNew);
	while ((val = hv_iternextsv(hvNew, &key, &klen)))
517
	{
518
		int			attn = SPI_fnumber(tupdesc, key);
519

520
		if (attn <= 0 || tupdesc->attrs[attn - 1]->attisdropped)
521 522 523 524
			ereport(ERROR,
					(errcode(ERRCODE_UNDEFINED_COLUMN),
					 errmsg("Perl hash contains nonexistent column \"%s\"",
							key)));
525
		if (SvOK(val) && SvTYPE(val) != SVt_NULL)
526
		{
527 528 529 530 531 532 533 534 535
			Oid			typinput;
			Oid			typioparam;
			FmgrInfo	finfo;

			/* XXX would be better to cache these lookups */
			getTypeInputInfo(tupdesc->attrs[attn - 1]->atttypid,
							 &typinput, &typioparam);
			fmgr_info(typinput, &finfo);
			modvalues[slotsused] = FunctionCall3(&finfo,
B
Bruce Momjian 已提交
536 537
										   CStringGetDatum(SvPV(val, PL_na)),
												 ObjectIdGetDatum(typioparam),
538 539
						 Int32GetDatum(tupdesc->attrs[attn - 1]->atttypmod));
			modnulls[slotsused] = ' ';
540 541 542
		}
		else
		{
543 544
			modvalues[slotsused] = (Datum) 0;
			modnulls[slotsused] = 'n';
545
		}
546 547
		modattrs[slotsused] = attn;
		slotsused++;
548
	}
549 550 551 552
	hv_iterinit(hvNew);

	rtup = SPI_modifytuple(tdata->tg_relation, otup, slotsused,
						   modattrs, modvalues, modnulls);
553 554 555 556

	pfree(modattrs);
	pfree(modvalues);
	pfree(modnulls);
557

558
	if (rtup == NULL)
559
		elog(ERROR, "SPI_modifytuple failed: %s",
560
			 SPI_result_code_string(SPI_result));
561 562 563

	return rtup;
}
564

565

566 567
/*
 * This is the only externally-visible part of the plperl call interface.
568
 * The Postgres function and trigger managers call it to execute a
569 570
 * perl function.
 */
571
PG_FUNCTION_INFO_V1(plperl_call_handler);
572 573

Datum
574
plperl_call_handler(PG_FUNCTION_ARGS)
575
{
B
Bruce Momjian 已提交
576
	Datum		retval;
577
	plperl_proc_desc *save_prodesc;
578 579
	FunctionCallInfo save_caller_info;
	Tuplestorestate *save_tuple_store;
B
Bruce Momjian 已提交
580
	TupleDesc	save_tuple_desc;
581

582
	plperl_init_all();
583

584
	save_prodesc = plperl_current_prodesc;
585 586 587
	save_caller_info = plperl_current_caller_info;
	save_tuple_store = plperl_current_tuple_store;
	save_tuple_desc = plperl_current_tuple_desc;
588

589 590 591 592 593 594 595 596 597 598
	PG_TRY();
	{
		if (CALLED_AS_TRIGGER(fcinfo))
			retval = PointerGetDatum(plperl_trigger_handler(fcinfo));
		else
			retval = plperl_func_handler(fcinfo);
	}
	PG_CATCH();
	{
		plperl_current_prodesc = save_prodesc;
599 600 601
		plperl_current_caller_info = save_caller_info;
		plperl_current_tuple_store = save_tuple_store;
		plperl_current_tuple_desc = save_tuple_desc;
602 603 604 605 606
		PG_RE_THROW();
	}
	PG_END_TRY();

	plperl_current_prodesc = save_prodesc;
607 608 609
	plperl_current_caller_info = save_caller_info;
	plperl_current_tuple_store = save_tuple_store;
	plperl_current_tuple_desc = save_tuple_desc;
610 611 612 613

	return retval;
}

614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651
/*
 * This is the other externally visible function - it is called when CREATE
 * FUNCTION is issued to validate the function being created/replaced.
 */
PG_FUNCTION_INFO_V1(plperl_validator);

Datum
plperl_validator(PG_FUNCTION_ARGS)
{
	Oid			funcoid = PG_GETARG_OID(0);
	HeapTuple	tuple;
	Form_pg_proc proc;
	bool		istrigger = false;
	plperl_proc_desc *prodesc;

	plperl_init_all();

	/* Get the new function's pg_proc entry */
	tuple = SearchSysCache(PROCOID,
						   ObjectIdGetDatum(funcoid),
						   0, 0, 0);
	if (!HeapTupleIsValid(tuple))
		elog(ERROR, "cache lookup failed for function %u", funcoid);
	proc = (Form_pg_proc) GETSTRUCT(tuple);

	/* we assume OPAQUE with no arguments means a trigger */
	if (proc->prorettype == TRIGGEROID ||
		(proc->prorettype == OPAQUEOID && proc->pronargs == 0))
		istrigger = true;

	ReleaseSysCache(tuple);

	prodesc = compile_plperl_function(funcoid, istrigger);

	/* the result of a validator is ignored */
	PG_RETURN_VOID();
}

652

653 654 655
/* Uses mksafefunc/mkunsafefunc to create an anonymous sub whose text is
 * supplied in s, and returns a reference to the closure. */

B
Bruce Momjian 已提交
656
static SV  *
657
plperl_create_sub(char *s, bool trusted)
658
{
659
	dSP;
660
	SV		   *subref;
B
Bruce Momjian 已提交
661
	int			count;
B
Bruce Momjian 已提交
662
	char	   *compile_sub;
663

B
Bruce Momjian 已提交
664
	if (trusted && !plperl_safe_init_done)
665
	{
666
		plperl_safe_init();
667 668
		SPAGAIN;
	}
669

670 671 672
	ENTER;
	SAVETMPS;
	PUSHMARK(SP);
673
	XPUSHs(sv_2mortal(newSVpv("my $_TD=$_[0]; shift;", 0)));
B
Bruce Momjian 已提交
674
	XPUSHs(sv_2mortal(newSVpv(s, 0)));
B
Bruce Momjian 已提交
675
	PUTBACK;
B
Bruce Momjian 已提交
676

677 678
	/*
	 * G_KEEPERR seems to be needed here, else we don't recognize compile
B
Bruce Momjian 已提交
679 680
	 * errors properly.  Perhaps it's because there's another level of eval
	 * inside mksafefunc?
681
	 */
682 683 684 685 686 687 688 689 690 691 692

	if (trusted && plperl_use_strict)
		compile_sub = "::mk_strict_safefunc";
	else if (plperl_use_strict)
		compile_sub = "::mk_strict_unsafefunc";
	else if (trusted)
		compile_sub = "::mksafefunc";
	else
		compile_sub = "::mkunsafefunc";

	count = perl_call_pv(compile_sub, G_SCALAR | G_EVAL | G_KEEPERR);
693 694
	SPAGAIN;

695 696 697 698 699
	if (count != 1)
	{
		PUTBACK;
		FREETMPS;
		LEAVE;
700
		elog(ERROR, "didn't get a return item from mksafefunc");
701 702
	}

703
	if (SvTRUE(ERRSV))
704
	{
705
		(void) POPs;
706 707 708
		PUTBACK;
		FREETMPS;
		LEAVE;
709 710 711 712
		ereport(ERROR,
				(errcode(ERRCODE_SYNTAX_ERROR),
				 errmsg("creation of Perl function failed: %s",
						strip_trailing_ws(SvPV(ERRSV, PL_na)))));
713 714 715
	}

	/*
716 717
	 * need to make a deep copy of the return. it comes off the stack as a
	 * temporary.
718 719 720
	 */
	subref = newSVsv(POPs);

721
	if (!SvROK(subref) || SvTYPE(SvRV(subref)) != SVt_PVCV)
722
	{
723 724 725
		PUTBACK;
		FREETMPS;
		LEAVE;
726

727 728 729 730
		/*
		 * subref is our responsibility because it is not mortal
		 */
		SvREFCNT_dec(subref);
731
		elog(ERROR, "didn't get a code ref");
732 733 734 735 736
	}

	PUTBACK;
	FREETMPS;
	LEAVE;
737

738 739 740
	return subref;
}

741

742
/**********************************************************************
743
 * plperl_init_shared_libs()		-
744 745 746 747
 *
 * We cannot use the DynaLoader directly to get at the Opcode
 * module (used by Safe.pm). So, we link Opcode into ourselves
 * and do the initialization behind perl's back.
748
 *
749 750
 **********************************************************************/

B
Bruce Momjian 已提交
751 752
EXTERN_C void boot_DynaLoader(pTHX_ CV * cv);
EXTERN_C void boot_SPI(pTHX_ CV * cv);
753

754
static void
755
plperl_init_shared_libs(pTHX)
756
{
757 758
	char	   *file = __FILE__;

759
	newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
760
	newXS("SPI::bootstrap", boot_SPI, file);
761 762
}

763

B
Bruce Momjian 已提交
764
static SV  *
B
Bruce Momjian 已提交
765
plperl_call_perl_func(plperl_proc_desc * desc, FunctionCallInfo fcinfo)
766 767
{
	dSP;
768 769 770
	SV		   *retval;
	int			i;
	int			count;
B
Bruce Momjian 已提交
771
	SV		   *sv;
772 773 774 775

	ENTER;
	SAVETMPS;

776
	PUSHMARK(SP);
777

B
Bruce Momjian 已提交
778
	XPUSHs(&PL_sv_undef);		/* no trigger data */
779

780 781
	for (i = 0; i < desc->nargs; i++)
	{
782 783 784
		if (fcinfo->argnull[i])
			XPUSHs(&PL_sv_undef);
		else if (desc->arg_is_rowtype[i])
785
		{
786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801
			HeapTupleHeader td;
			Oid			tupType;
			int32		tupTypmod;
			TupleDesc	tupdesc;
			HeapTupleData tmptup;
			SV		   *hashref;

			td = DatumGetHeapTupleHeader(fcinfo->arg[i]);
			/* Extract rowtype info and find a tupdesc */
			tupType = HeapTupleHeaderGetTypeId(td);
			tupTypmod = HeapTupleHeaderGetTypMod(td);
			tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
			/* Build a temporary HeapTuple control structure */
			tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
			tmptup.t_data = td;

802 803
			hashref = plperl_hash_from_tuple(&tmptup, tupdesc);
			XPUSHs(sv_2mortal(hashref));
804 805 806
		}
		else
		{
807 808
			char	   *tmp;

809 810
			tmp = DatumGetCString(FunctionCall1(&(desc->arg_out_func[i]),
												fcinfo->arg[i]));
811 812
			sv = newSVpv(tmp, 0);
#if PERL_BCDVERSION >= 0x5006000L
B
Bruce Momjian 已提交
813 814
			if (GetDatabaseEncoding() == PG_UTF8)
				SvUTF8_on(sv);
815 816
#endif
			XPUSHs(sv_2mortal(sv));
817
			pfree(tmp);
818 819 820
		}
	}
	PUTBACK;
821 822 823

	/* Do NOT use G_KEEPERR here */
	count = perl_call_sv(desc->reference, G_SCALAR | G_EVAL);
824 825 826

	SPAGAIN;

827 828 829 830
	if (count != 1)
	{
		PUTBACK;
		FREETMPS;
831
		LEAVE;
832
		elog(ERROR, "didn't get a return item from function");
833 834
	}

835
	if (SvTRUE(ERRSV))
836
	{
837
		(void) POPs;
838 839
		PUTBACK;
		FREETMPS;
840
		LEAVE;
841 842 843 844
		/* XXX need to find a way to assign an errcode here */
		ereport(ERROR,
				(errmsg("error from Perl function: %s",
						strip_trailing_ws(SvPV(ERRSV, PL_na)))));
845 846 847 848
	}

	retval = newSVsv(POPs);

849 850 851
	PUTBACK;
	FREETMPS;
	LEAVE;
852 853 854 855

	return retval;
}

856

857
static SV  *
B
Bruce Momjian 已提交
858 859
plperl_call_perl_trigger_func(plperl_proc_desc * desc, FunctionCallInfo fcinfo,
							  SV * td)
860 861 862
{
	dSP;
	SV		   *retval;
863
	Trigger    *tg_trigger;
864 865 866 867 868 869 870
	int			i;
	int			count;

	ENTER;
	SAVETMPS;

	PUSHMARK(sp);
871

872
	XPUSHs(td);
873

874 875 876
	tg_trigger = ((TriggerData *) fcinfo->context)->tg_trigger;
	for (i = 0; i < tg_trigger->tgnargs; i++)
		XPUSHs(sv_2mortal(newSVpv(tg_trigger->tgargs[i], 0)));
877 878
	PUTBACK;

879 880
	/* Do NOT use G_KEEPERR here */
	count = perl_call_sv(desc->reference, G_SCALAR | G_EVAL);
881 882 883 884 885 886 887 888

	SPAGAIN;

	if (count != 1)
	{
		PUTBACK;
		FREETMPS;
		LEAVE;
889
		elog(ERROR, "didn't get a return item from trigger function");
890 891 892 893
	}

	if (SvTRUE(ERRSV))
	{
894
		(void) POPs;
895 896 897
		PUTBACK;
		FREETMPS;
		LEAVE;
898 899 900 901
		/* XXX need to find a way to assign an errcode here */
		ereport(ERROR,
				(errmsg("error from Perl trigger function: %s",
						strip_trailing_ws(SvPV(ERRSV, PL_na)))));
902 903 904 905 906 907 908 909 910 911
	}

	retval = newSVsv(POPs);

	PUTBACK;
	FREETMPS;
	LEAVE;

	return retval;
}
912

913

914
static Datum
915
plperl_func_handler(PG_FUNCTION_ARGS)
916 917
{
	plperl_proc_desc *prodesc;
918 919
	SV		   *perlret;
	Datum		retval;
920
	ReturnSetInfo *rsi;
B
Bruce Momjian 已提交
921
	SV		   *array_ret = NULL;
922

923 924 925
	if (SPI_connect() != SPI_OK_CONNECT)
		elog(ERROR, "could not connect to SPI manager");

926
	prodesc = compile_plperl_function(fcinfo->flinfo->fn_oid, false);
927 928

	plperl_current_prodesc = prodesc;
929 930 931
	plperl_current_caller_info = fcinfo;
	plperl_current_tuple_store = 0;
	plperl_current_tuple_desc = 0;
932

B
Bruce Momjian 已提交
933
	rsi = (ReturnSetInfo *) fcinfo->resultinfo;
B
Bruce Momjian 已提交
934

T
Tom Lane 已提交
935
	if (prodesc->fn_retisset)
936
	{
T
Tom Lane 已提交
937 938 939 940 941 942 943 944
		/* Check context before allowing the call to go through */
		if (!rsi || !IsA(rsi, ReturnSetInfo) ||
			(rsi->allowedModes & SFRM_Materialize) == 0 ||
			rsi->expectedDesc == NULL)
			ereport(ERROR,
					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
					 errmsg("set-valued function called in context that "
							"cannot accept a set")));
945 946
	}

947
	perlret = plperl_call_perl_func(prodesc, fcinfo);
948 949 950 951 952 953 954 955

	/************************************************************
	 * Disconnect from SPI manager and then create the return
	 * values datum (if the input function does a palloc for it
	 * this must not be allocated in the SPI memory context
	 * because SPI_finish would free it).
	 ************************************************************/
	if (SPI_finish() != SPI_OK_FINISH)
956
		elog(ERROR, "SPI_finish() failed");
957

T
Tom Lane 已提交
958
	if (prodesc->fn_retisset)
959
	{
T
Tom Lane 已提交
960 961
		/*
		 * If the Perl function returned an arrayref, we pretend that it
B
Bruce Momjian 已提交
962 963 964
		 * called return_next() for each element of the array, to handle old
		 * SRFs that didn't know about return_next(). Any other sort of return
		 * value is an error.
T
Tom Lane 已提交
965
		 */
966 967
		if (SvTYPE(perlret) == SVt_RV &&
			SvTYPE(SvRV(perlret)) == SVt_PVAV)
968
		{
B
Bruce Momjian 已提交
969 970 971 972 973
			int			i = 0;
			SV		  **svp = 0;
			AV		   *rav = (AV *) SvRV(perlret);

			while ((svp = av_fetch(rav, i, FALSE)) != NULL)
974
			{
975 976 977
				plperl_return_next(*svp);
				i++;
			}
978
		}
979
		else if (SvTYPE(perlret) != SVt_NULL)
980
		{
981 982
			ereport(ERROR,
					(errcode(ERRCODE_DATATYPE_MISMATCH),
983 984
					 errmsg("set-returning Perl function must return "
							"reference to array or use return_next")));
985
		}
B
Bruce Momjian 已提交
986

987
		rsi->returnMode = SFRM_Materialize;
B
Bruce Momjian 已提交
988
		if (plperl_current_tuple_store)
989
		{
990 991
			rsi->setResult = plperl_current_tuple_store;
			rsi->setDesc = plperl_current_tuple_desc;
992
		}
B
Bruce Momjian 已提交
993
		retval = (Datum) 0;
994 995 996 997 998 999 1000
	}
	else if (SvTYPE(perlret) == SVt_NULL)
	{
		/* Return NULL if Perl code returned undef */
		if (rsi && IsA(rsi, ReturnSetInfo))
			rsi->isDone = ExprEndResult;
		fcinfo->isnull = true;
B
Bruce Momjian 已提交
1001
		retval = (Datum) 0;
B
Bruce Momjian 已提交
1002
	}
1003
	else if (prodesc->fn_retistuple)
1004
	{
1005
		/* Return a perl hash converted to a Datum */
B
Bruce Momjian 已提交
1006
		TupleDesc	td;
1007
		AttInMetadata *attinmeta;
B
Bruce Momjian 已提交
1008
		HeapTuple	tup;
1009

1010 1011 1012
		if (!SvOK(perlret) || SvTYPE(perlret) != SVt_RV ||
			SvTYPE(SvRV(perlret)) != SVt_PVHV)
		{
1013 1014
			ereport(ERROR,
					(errcode(ERRCODE_DATATYPE_MISMATCH),
1015 1016 1017
					 errmsg("composite-returning Perl function "
							"must return reference to hash")));
		}
1018

1019 1020 1021 1022 1023 1024 1025 1026
		/* XXX should cache the attinmeta data instead of recomputing */
		if (get_call_result_type(fcinfo, NULL, &td) != TYPEFUNC_COMPOSITE)
		{
			ereport(ERROR,
					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
					 errmsg("function returning record called in context "
							"that cannot accept type record")));
		}
1027

1028
		attinmeta = TupleDescGetAttInMetadata(td);
B
Bruce Momjian 已提交
1029
		tup = plperl_build_tuple_result((HV *) SvRV(perlret), attinmeta);
1030 1031 1032 1033
		retval = HeapTupleGetDatum(tup);
	}
	else
	{
B
Bruce Momjian 已提交
1034 1035 1036 1037
		/* Return a perl string converted to a Datum */
		char	   *val;

		if (prodesc->fn_retisarray && SvROK(perlret) &&
1038
			SvTYPE(SvRV(perlret)) == SVt_PVAV)
B
Bruce Momjian 已提交
1039 1040 1041 1042 1043
		{
			array_ret = plperl_convert_to_pg_array(perlret);
			SvREFCNT_dec(perlret);
			perlret = array_ret;
		}
1044 1045 1046

		val = SvPV(perlret, PL_na);

1047 1048 1049 1050
		retval = FunctionCall3(&prodesc->result_in_func,
							   CStringGetDatum(val),
							   ObjectIdGetDatum(prodesc->result_typioparam),
							   Int32GetDatum(-1));
1051
	}
1052

1053
	if (array_ret == NULL)
B
Bruce Momjian 已提交
1054
		SvREFCNT_dec(perlret);
1055

1056 1057 1058
	return retval;
}

1059

1060 1061 1062 1063 1064 1065 1066 1067 1068
static Datum
plperl_trigger_handler(PG_FUNCTION_ARGS)
{
	plperl_proc_desc *prodesc;
	SV		   *perlret;
	Datum		retval;
	SV		   *svTD;
	HV		   *hvTD;

1069 1070 1071 1072
	/* Connect to SPI manager */
	if (SPI_connect() != SPI_OK_CONNECT)
		elog(ERROR, "could not connect to SPI manager");

1073 1074 1075
	/* Find or compile the function */
	prodesc = compile_plperl_function(fcinfo->flinfo->fn_oid, true);

1076 1077
	plperl_current_prodesc = prodesc;

1078 1079
	svTD = plperl_trigger_build_args(fcinfo);
	perlret = plperl_call_perl_trigger_func(prodesc, fcinfo, svTD);
1080
	hvTD = (HV *) SvRV(svTD);
1081 1082 1083 1084 1085 1086 1087 1088

	/************************************************************
	* Disconnect from SPI manager and then create the return
	* values datum (if the input function does a palloc for it
	* this must not be allocated in the SPI memory context
	* because SPI_finish would free it).
	************************************************************/
	if (SPI_finish() != SPI_OK_FINISH)
1089
		elog(ERROR, "SPI_finish() failed");
1090

1091
	if (!(perlret && SvOK(perlret) && SvTYPE(perlret) != SVt_NULL))
1092
	{
1093
		/* undef result means go ahead with original tuple */
1094 1095 1096 1097 1098 1099 1100 1101
		TriggerData *trigdata = ((TriggerData *) fcinfo->context);

		if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
			retval = (Datum) trigdata->tg_trigtuple;
		else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
			retval = (Datum) trigdata->tg_newtuple;
		else if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event))
			retval = (Datum) trigdata->tg_trigtuple;
1102
		else
B
Bruce Momjian 已提交
1103
			retval = (Datum) 0; /* can this happen? */
1104 1105 1106
	}
	else
	{
1107 1108
		HeapTuple	trv;
		char	   *tmp;
1109

1110
		tmp = SvPV(perlret, PL_na);
1111

1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123
		if (pg_strcasecmp(tmp, "SKIP") == 0)
			trv = NULL;
		else if (pg_strcasecmp(tmp, "MODIFY") == 0)
		{
			TriggerData *trigdata = (TriggerData *) fcinfo->context;

			if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
				trv = plperl_modify_tuple(hvTD, trigdata,
										  trigdata->tg_trigtuple);
			else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
				trv = plperl_modify_tuple(hvTD, trigdata,
										  trigdata->tg_newtuple);
1124 1125
			else
			{
1126 1127
				ereport(WARNING,
						(errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
B
Bruce Momjian 已提交
1128
					   errmsg("ignoring modified tuple in DELETE trigger")));
1129 1130 1131
				trv = NULL;
			}
		}
1132
		else
1133
		{
1134 1135
			ereport(ERROR,
					(errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
1136 1137
					 errmsg("result of Perl trigger function must be undef, "
							"\"SKIP\" or \"MODIFY\"")));
1138 1139 1140
			trv = NULL;
		}
		retval = PointerGetDatum(trv);
1141 1142
	}

1143 1144 1145
	SvREFCNT_dec(svTD);
	if (perlret)
		SvREFCNT_dec(perlret);
1146 1147 1148

	return retval;
}
1149

1150

1151 1152
static plperl_proc_desc *
compile_plperl_function(Oid fn_oid, bool is_trigger)
1153
{
1154 1155 1156 1157 1158
	HeapTuple	procTup;
	Form_pg_proc procStruct;
	char		internal_proname[64];
	int			proname_len;
	plperl_proc_desc *prodesc = NULL;
1159
	int			i;
B
Bruce Momjian 已提交
1160
	SV		  **svp;
1161

1162 1163 1164 1165 1166
	/* We'll need the pg_proc tuple in any case... */
	procTup = SearchSysCache(PROCOID,
							 ObjectIdGetDatum(fn_oid),
							 0, 0, 0);
	if (!HeapTupleIsValid(procTup))
1167
		elog(ERROR, "cache lookup failed for function %u", fn_oid);
1168
	procStruct = (Form_pg_proc) GETSTRUCT(procTup);
1169 1170 1171 1172

	/************************************************************
	 * Build our internal proc name from the functions Oid
	 ************************************************************/
1173 1174 1175 1176
	if (!is_trigger)
		sprintf(internal_proname, "__PLPerl_proc_%u", fn_oid);
	else
		sprintf(internal_proname, "__PLPerl_proc_%u_trigger", fn_oid);
1177

1178
	proname_len = strlen(internal_proname);
1179 1180 1181 1182

	/************************************************************
	 * Lookup the internal proc name in the hashtable
	 ************************************************************/
1183 1184
	svp = hv_fetch(plperl_proc_hash, internal_proname, proname_len, FALSE);
	if (svp)
1185
	{
1186 1187
		bool		uptodate;

1188
		prodesc = (plperl_proc_desc *) SvIV(*svp);
1189

1190
		/************************************************************
1191 1192 1193
		 * If it's present, must check whether it's still up to date.
		 * This is needed because CREATE OR REPLACE FUNCTION can modify the
		 * function's pg_proc entry without changing its OID.
1194
		 ************************************************************/
1195
		uptodate = (prodesc->fn_xmin == HeapTupleHeaderGetXmin(procTup->t_data) &&
B
Bruce Momjian 已提交
1196
				prodesc->fn_cmin == HeapTupleHeaderGetCmin(procTup->t_data));
1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218

		if (!uptodate)
		{
			/* need we delete old entry? */
			prodesc = NULL;
		}
	}

	/************************************************************
	 * If we haven't found it in the hashtable, we analyze
	 * the functions arguments and returntype and store
	 * the in-/out-functions in the prodesc block and create
	 * a new hashtable entry for it.
	 *
	 * Then we load the procedure into the Perl interpreter.
	 ************************************************************/
	if (prodesc == NULL)
	{
		HeapTuple	langTup;
		HeapTuple	typeTup;
		Form_pg_language langStruct;
		Form_pg_type typeStruct;
1219 1220
		Datum		prosrcdatum;
		bool		isnull;
1221 1222 1223 1224 1225 1226
		char	   *proc_source;

		/************************************************************
		 * Allocate a new procedure description block
		 ************************************************************/
		prodesc = (plperl_proc_desc *) malloc(sizeof(plperl_proc_desc));
1227
		if (prodesc == NULL)
1228 1229 1230
			ereport(ERROR,
					(errcode(ERRCODE_OUT_OF_MEMORY),
					 errmsg("out of memory")));
1231 1232
		MemSet(prodesc, 0, sizeof(plperl_proc_desc));
		prodesc->proname = strdup(internal_proname);
1233 1234
		prodesc->fn_xmin = HeapTupleHeaderGetXmin(procTup->t_data);
		prodesc->fn_cmin = HeapTupleHeaderGetCmin(procTup->t_data);
1235

1236 1237 1238 1239
		/* Remember if function is STABLE/IMMUTABLE */
		prodesc->fn_readonly =
			(procStruct->provolatile != PROVOLATILE_VOLATILE);

1240
		/************************************************************
1241
		 * Lookup the pg_language tuple by Oid
1242
		 ************************************************************/
1243 1244
		langTup = SearchSysCache(LANGOID,
								 ObjectIdGetDatum(procStruct->prolang),
1245
								 0, 0, 0);
1246
		if (!HeapTupleIsValid(langTup))
1247 1248 1249
		{
			free(prodesc->proname);
			free(prodesc);
1250
			elog(ERROR, "cache lookup failed for language %u",
1251
				 procStruct->prolang);
1252
		}
1253 1254 1255
		langStruct = (Form_pg_language) GETSTRUCT(langTup);
		prodesc->lanpltrusted = langStruct->lanpltrusted;
		ReleaseSysCache(langTup);
1256 1257

		/************************************************************
1258 1259
		 * Get the required information for input conversion of the
		 * return value.
1260
		 ************************************************************/
1261 1262 1263
		if (!is_trigger)
		{
			typeTup = SearchSysCache(TYPEOID,
B
Bruce Momjian 已提交
1264
									 ObjectIdGetDatum(procStruct->prorettype),
1265 1266 1267 1268 1269
									 0, 0, 0);
			if (!HeapTupleIsValid(typeTup))
			{
				free(prodesc->proname);
				free(prodesc);
1270
				elog(ERROR, "cache lookup failed for type %u",
1271
					 procStruct->prorettype);
1272 1273 1274
			}
			typeStruct = (Form_pg_type) GETSTRUCT(typeTup);

1275
			/* Disallow pseudotype result, except VOID or RECORD */
1276 1277
			if (typeStruct->typtype == 'p')
			{
1278 1279
				if (procStruct->prorettype == VOIDOID ||
					procStruct->prorettype == RECORDOID)
B
Bruce Momjian 已提交
1280
					 /* okay */ ;
1281
				else if (procStruct->prorettype == TRIGGEROID)
1282 1283 1284
				{
					free(prodesc->proname);
					free(prodesc);
1285 1286
					ereport(ERROR,
							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1287 1288
							 errmsg("trigger functions may only be called "
									"as triggers")));
1289 1290 1291 1292 1293
				}
				else
				{
					free(prodesc->proname);
					free(prodesc);
1294 1295
					ereport(ERROR,
							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
B
Bruce Momjian 已提交
1296 1297
							 errmsg("plperl functions cannot return type %s",
									format_type_be(procStruct->prorettype))));
1298 1299 1300
				}
			}

1301 1302 1303 1304
			prodesc->result_oid = procStruct->prorettype;
			prodesc->fn_retisset = procStruct->proretset;
			prodesc->fn_retistuple = (typeStruct->typtype == 'c' ||
									  procStruct->prorettype == RECORDOID);
1305

B
Bruce Momjian 已提交
1306 1307
			prodesc->fn_retisarray =
				(typeStruct->typlen == -1 && typeStruct->typelem);
1308

1309
			perm_fmgr_info(typeStruct->typinput, &(prodesc->result_in_func));
1310
			prodesc->result_typioparam = getTypeIOParam(typeTup);
1311 1312 1313

			ReleaseSysCache(typeTup);
		}
1314 1315

		/************************************************************
1316 1317
		 * Get the required information for output conversion
		 * of all procedure arguments
1318
		 ************************************************************/
1319 1320 1321 1322 1323 1324
		if (!is_trigger)
		{
			prodesc->nargs = procStruct->pronargs;
			for (i = 0; i < prodesc->nargs; i++)
			{
				typeTup = SearchSysCache(TYPEOID,
B
Bruce Momjian 已提交
1325
						 ObjectIdGetDatum(procStruct->proargtypes.values[i]),
1326 1327 1328 1329 1330
										 0, 0, 0);
				if (!HeapTupleIsValid(typeTup))
				{
					free(prodesc->proname);
					free(prodesc);
1331
					elog(ERROR, "cache lookup failed for type %u",
1332
						 procStruct->proargtypes.values[i]);
1333 1334 1335
				}
				typeStruct = (Form_pg_type) GETSTRUCT(typeTup);

1336 1337 1338 1339 1340
				/* Disallow pseudotype argument */
				if (typeStruct->typtype == 'p')
				{
					free(prodesc->proname);
					free(prodesc);
1341 1342
					ereport(ERROR,
							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
B
Bruce Momjian 已提交
1343 1344
							 errmsg("plperl functions cannot take type %s",
						format_type_be(procStruct->proargtypes.values[i]))));
1345 1346
				}

1347 1348
				if (typeStruct->typtype == 'c')
					prodesc->arg_is_rowtype[i] = true;
1349
				else
1350 1351 1352 1353 1354
				{
					prodesc->arg_is_rowtype[i] = false;
					perm_fmgr_info(typeStruct->typoutput,
								   &(prodesc->arg_out_func[i]));
				}
1355 1356 1357 1358

				ReleaseSysCache(typeTup);
			}
		}
1359

1360 1361 1362 1363 1364
		/************************************************************
		 * create the text of the anonymous subroutine.
		 * we do not use a named subroutine so that we can call directly
		 * through the reference.
		 ************************************************************/
1365 1366 1367 1368
		prosrcdatum = SysCacheGetAttr(PROCOID, procTup,
									  Anum_pg_proc_prosrc, &isnull);
		if (isnull)
			elog(ERROR, "null prosrc");
1369
		proc_source = DatumGetCString(DirectFunctionCall1(textout,
1370
														  prosrcdatum));
1371 1372

		/************************************************************
1373
		 * Create the procedure in the interpreter
1374
		 ************************************************************/
1375 1376
		prodesc->reference = plperl_create_sub(proc_source, prodesc->lanpltrusted);
		pfree(proc_source);
B
Bruce Momjian 已提交
1377
		if (!prodesc->reference)	/* can this happen? */
1378 1379 1380
		{
			free(prodesc->proname);
			free(prodesc);
1381
			elog(ERROR, "could not create internal procedure \"%s\"",
1382
				 internal_proname);
1383 1384
		}

1385 1386
		hv_store(plperl_proc_hash, internal_proname, proname_len,
				 newSViv((IV) prodesc), 0);
1387 1388
	}

1389
	ReleaseSysCache(procTup);
1390

1391 1392
	return prodesc;
}
1393 1394


1395 1396
/* Build a hash from all attributes of a given tuple. */

B
Bruce Momjian 已提交
1397
static SV  *
1398
plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc)
1399
{
1400
	HV		   *hv;
1401
	int			i;
1402

1403
	hv = newHV();
1404 1405 1406

	for (i = 0; i < tupdesc->natts; i++)
	{
1407 1408 1409 1410 1411 1412 1413
		Datum		attr;
		bool		isnull;
		char	   *attname;
		char	   *outputstr;
		Oid			typoutput;
		bool		typisvarlena;
		int			namelen;
B
Bruce Momjian 已提交
1414
		SV		   *sv;
1415

1416 1417 1418
		if (tupdesc->attrs[i]->attisdropped)
			continue;

1419
		attname = NameStr(tupdesc->attrs[i]->attname);
1420
		namelen = strlen(attname);
1421 1422
		attr = heap_getattr(tuple, i + 1, tupdesc, &isnull);

B
Bruce Momjian 已提交
1423 1424
		if (isnull)
		{
1425 1426
			/* Store (attname => undef) and move on. */
			hv_store(hv, attname, namelen, newSV(0), 0);
1427 1428 1429
			continue;
		}

1430
		/* XXX should have a way to cache these lookups */
1431

1432
		getTypeOutputInfo(tupdesc->attrs[i]->atttypid,
1433
						  &typoutput, &typisvarlena);
1434

1435
		outputstr = DatumGetCString(OidFunctionCall1(typoutput, attr));
1436

1437 1438
		sv = newSVpv(outputstr, 0);
#if PERL_BCDVERSION >= 0x5006000L
1439 1440
		if (GetDatabaseEncoding() == PG_UTF8)
			SvUTF8_on(sv);
1441 1442
#endif
		hv_store(hv, attname, namelen, sv, 0);
1443 1444

		pfree(outputstr);
1445
	}
1446

1447
	return newRV_noinc((SV *) hv);
1448
}
1449 1450 1451 1452 1453 1454 1455


HV *
plperl_spi_exec(char *query, int limit)
{
	HV		   *ret_hv;

1456
	/*
B
Bruce Momjian 已提交
1457 1458
	 * Execute the query inside a sub-transaction, so we can cope with errors
	 * sanely
1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479
	 */
	MemoryContext oldcontext = CurrentMemoryContext;
	ResourceOwner oldowner = CurrentResourceOwner;

	BeginInternalSubTransaction(NULL);
	/* Want to run inside function's memory context */
	MemoryContextSwitchTo(oldcontext);

	PG_TRY();
	{
		int			spi_rv;

		spi_rv = SPI_execute(query, plperl_current_prodesc->fn_readonly,
							 limit);
		ret_hv = plperl_spi_execute_fetch_result(SPI_tuptable, SPI_processed,
												 spi_rv);

		/* Commit the inner transaction, return to outer xact context */
		ReleaseCurrentSubTransaction();
		MemoryContextSwitchTo(oldcontext);
		CurrentResourceOwner = oldowner;
B
Bruce Momjian 已提交
1480

1481
		/*
B
Bruce Momjian 已提交
1482 1483
		 * AtEOSubXact_SPI() should not have popped any SPI context, but just
		 * in case it did, make sure we remain connected.
1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501
		 */
		SPI_restore_connection();
	}
	PG_CATCH();
	{
		ErrorData  *edata;

		/* Save error info */
		MemoryContextSwitchTo(oldcontext);
		edata = CopyErrorData();
		FlushErrorState();

		/* Abort the inner transaction */
		RollbackAndReleaseCurrentSubTransaction();
		MemoryContextSwitchTo(oldcontext);
		CurrentResourceOwner = oldowner;

		/*
B
Bruce Momjian 已提交
1502 1503 1504
		 * If AtEOSubXact_SPI() popped any SPI context of the subxact, it will
		 * have left us in a disconnected state.  We need this hack to return
		 * to connected state.
1505 1506 1507 1508 1509 1510 1511 1512 1513 1514
		 */
		SPI_restore_connection();

		/* Punt the error to Perl */
		croak("%s", edata->message);

		/* Can't get here, but keep compiler quiet */
		return NULL;
	}
	PG_END_TRY();
1515 1516 1517 1518

	return ret_hv;
}

1519

1520
static HV  *
1521 1522
plperl_spi_execute_fetch_result(SPITupleTable *tuptable, int processed,
								int status)
1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534
{
	HV		   *result;

	result = newHV();

	hv_store(result, "status", strlen("status"),
			 newSVpv((char *) SPI_result_code_string(status), 0), 0);
	hv_store(result, "processed", strlen("processed"),
			 newSViv(processed), 0);

	if (status == SPI_OK_SELECT)
	{
1535
		AV		   *rows;
1536
		SV		   *row;
1537
		int			i;
1538

1539 1540 1541 1542
		rows = newAV();
		for (i = 0; i < processed; i++)
		{
			row = plperl_hash_from_tuple(tuptable->vals[i], tuptable->tupdesc);
1543
			av_push(rows, row);
1544
		}
1545 1546
		hv_store(result, "rows", strlen("rows"),
				 newRV_noinc((SV *) rows), 0);
1547 1548 1549 1550 1551 1552
	}

	SPI_freetuptable(tuptable);

	return result;
}
1553 1554 1555


void
B
Bruce Momjian 已提交
1556
plperl_return_next(SV * sv)
1557 1558
{
	plperl_proc_desc *prodesc = plperl_current_prodesc;
1559
	FunctionCallInfo fcinfo = plperl_current_caller_info;
B
Bruce Momjian 已提交
1560
	ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
1561
	MemoryContext cxt;
B
Bruce Momjian 已提交
1562 1563
	HeapTuple	tuple;
	TupleDesc	tupdesc;
1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585

	if (!sv)
		return;

	if (!prodesc->fn_retisset)
	{
		ereport(ERROR,
				(errcode(ERRCODE_SYNTAX_ERROR),
				 errmsg("cannot use return_next in a non-SETOF function")));
	}

	if (prodesc->fn_retistuple &&
		!(SvOK(sv) && SvTYPE(sv) == SVt_RV && SvTYPE(SvRV(sv)) == SVt_PVHV))
	{
		ereport(ERROR,
				(errcode(ERRCODE_DATATYPE_MISMATCH),
				 errmsg("setof-composite-returning Perl function "
						"must call return_next with reference to hash")));
	}

	cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);

1586
	if (!plperl_current_tuple_store)
B
Bruce Momjian 已提交
1587
		plperl_current_tuple_store =
1588
			tuplestore_begin_heap(true, false, work_mem);
1589 1590 1591 1592 1593 1594 1595 1596 1597

	if (prodesc->fn_retistuple)
	{
		TypeFuncClass rettype;
		AttInMetadata *attinmeta;

		rettype = get_call_result_type(fcinfo, NULL, &tupdesc);
		tupdesc = CreateTupleDescCopy(tupdesc);
		attinmeta = TupleDescGetAttInMetadata(tupdesc);
B
Bruce Momjian 已提交
1598
		tuple = plperl_build_tuple_result((HV *) SvRV(sv), attinmeta);
1599 1600 1601
	}
	else
	{
B
Bruce Momjian 已提交
1602 1603
		Datum		ret;
		bool		isNull;
1604 1605 1606 1607 1608

		tupdesc = CreateTupleDescCopy(rsi->expectedDesc);

		if (SvOK(sv) && SvTYPE(sv) != SVt_NULL)
		{
B
Bruce Momjian 已提交
1609 1610
			char	   *val = SvPV(sv, PL_na);

1611 1612 1613 1614 1615 1616
			ret = FunctionCall3(&prodesc->result_in_func,
								PointerGetDatum(val),
								ObjectIdGetDatum(prodesc->result_typioparam),
								Int32GetDatum(-1));
			isNull = false;
		}
B
Bruce Momjian 已提交
1617 1618 1619
		else
		{
			ret = (Datum) 0;
1620 1621 1622 1623 1624 1625
			isNull = true;
		}

		tuple = heap_form_tuple(tupdesc, &ret, &isNull);
	}

1626 1627
	if (!plperl_current_tuple_desc)
		plperl_current_tuple_desc = tupdesc;
1628

1629
	tuplestore_puttuple(plperl_current_tuple_store, tuple);
1630 1631 1632
	heap_freetuple(tuple);
	MemoryContextSwitchTo(cxt);
}
1633 1634 1635 1636 1637


SV *
plperl_spi_query(char *query)
{
B
Bruce Momjian 已提交
1638
	SV		   *cursor;
1639 1640 1641 1642 1643 1644 1645 1646 1647

	MemoryContext oldcontext = CurrentMemoryContext;
	ResourceOwner oldowner = CurrentResourceOwner;

	BeginInternalSubTransaction(NULL);
	MemoryContextSwitchTo(oldcontext);

	PG_TRY();
	{
B
Bruce Momjian 已提交
1648 1649
		void	   *plan;
		Portal		portal = NULL;
1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688

		plan = SPI_prepare(query, 0, NULL);
		if (plan)
			portal = SPI_cursor_open(NULL, plan, NULL, NULL, false);
		if (portal)
			cursor = newSVpv(portal->name, 0);
		else
			cursor = newSV(0);

		ReleaseCurrentSubTransaction();
		MemoryContextSwitchTo(oldcontext);
		CurrentResourceOwner = oldowner;
		SPI_restore_connection();
	}
	PG_CATCH();
	{
		ErrorData  *edata;

		MemoryContextSwitchTo(oldcontext);
		edata = CopyErrorData();
		FlushErrorState();

		RollbackAndReleaseCurrentSubTransaction();
		MemoryContextSwitchTo(oldcontext);
		CurrentResourceOwner = oldowner;

		SPI_restore_connection();
		croak("%s", edata->message);
		return NULL;
	}
	PG_END_TRY();

	return cursor;
}


SV *
plperl_spi_fetchrow(char *cursor)
{
B
Bruce Momjian 已提交
1689 1690
	SV		   *row = newSV(0);
	Portal		p = SPI_cursor_find(cursor);
1691 1692 1693 1694 1695

	if (!p)
		return row;

	SPI_cursor_fetch(p, true, 1);
B
Bruce Momjian 已提交
1696 1697
	if (SPI_processed == 0)
	{
1698 1699 1700 1701 1702 1703 1704 1705 1706 1707
		SPI_cursor_close(p);
		return row;
	}

	row = plperl_hash_from_tuple(SPI_tuptable->vals[0],
								 SPI_tuptable->tupdesc);
	SPI_freetuptable(SPI_tuptable);

	return row;
}