plperl.c 37.2 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
36
 *	  $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.75 2005/06/04 20:33:06 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 58

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

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

70 71 72 73 74 75 76

/**********************************************************************
 * The information we cache about loaded procedures
 **********************************************************************/
typedef struct plperl_proc_desc
{
	char	   *proname;
77 78
	TransactionId fn_xmin;
	CommandId	fn_cmin;
79
	bool		fn_readonly;
80
	bool		lanpltrusted;
81
	bool		fn_retistuple;	/* true, if function returns tuple */
B
Bruce Momjian 已提交
82
	bool		fn_retisset;	/* true, if function returns set */
83 84
	Oid			result_oid;		/* Oid of result type */
	FmgrInfo	result_in_func;	/* I/O function and arg for result type */
85
	Oid			result_typioparam;
86 87
	int			nargs;
	FmgrInfo	arg_out_func[FUNC_MAX_ARGS];
88
	bool		arg_is_rowtype[FUNC_MAX_ARGS];
89
	SV		   *reference;
90 91 92
	FunctionCallInfo caller_info;
	Tuplestorestate *tuple_store;
	TupleDesc tuple_desc;
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 107 108
/* this is saved and restored by plperl_call_handler */
static plperl_proc_desc *plperl_current_prodesc = NULL;

109 110 111 112
/**********************************************************************
 * Forward declarations
 **********************************************************************/
static void plperl_init_all(void);
113
static void plperl_init_interp(void);
114

B
Bruce Momjian 已提交
115
Datum		plperl_call_handler(PG_FUNCTION_ARGS);
116
void		plperl_init(void);
117

118 119
HV		   *plperl_spi_exec(char *query, int limit);

120
static Datum plperl_func_handler(PG_FUNCTION_ARGS);
121

122
static Datum plperl_trigger_handler(PG_FUNCTION_ARGS);
123 124
static plperl_proc_desc *compile_plperl_function(Oid fn_oid, bool is_trigger);

125
static SV  *plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc);
126
static void plperl_init_shared_libs(pTHX);
127
static HV  *plperl_spi_execute_fetch_result(SPITupleTable *, int, int);
128

129
void plperl_return_next(SV *);
130

131 132 133 134 135 136 137
/*
 * 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,
138 139 140
 * 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.
141 142 143 144
 */
static void
perm_fmgr_info(Oid functionId, FmgrInfo *finfo)
{
145
	fmgr_info_cxt(functionId, finfo, TopMemoryContext);
146 147
}

148 149 150

/* Perform initialization during postmaster startup. */

151 152
void
plperl_init(void)
153 154 155 156
{
	if (!plperl_firstcall)
		return;

157 158 159 160 161 162 163 164 165
	DefineCustomBoolVariable(
		"plperl.use_strict",
		"If true, will compile trusted and untrusted perl code in strict mode",
		NULL,
		&plperl_use_strict,
		PGC_USERSET,
		NULL, NULL);

	EmitWarningsOnPlaceholders("plperl");
166

167
	plperl_init_interp();
168 169 170
	plperl_firstcall = 0;
}

171 172 173

/* Perform initialization during backend startup. */

174 175 176 177 178 179
static void
plperl_init_all(void)
{
	if (plperl_firstcall)
		plperl_init();

180
	/* We don't need to do anything yet when a new backend starts. */
181 182
}

183 184

static void
185
plperl_init_interp(void)
186
{
187
	static char	   *loose_embedding[3] = {
B
Bruce Momjian 已提交
188
		"", "-e",
189
		/* all one string follows (no commas please) */
190
		"SPI::bootstrap(); use vars qw(%_SHARED);"
191
		"sub ::mkunsafefunc {return eval(qq[ sub { $_[0] $_[1] } ]); }"
B
Bruce Momjian 已提交
192
	};
193

194 195 196 197 198 199 200 201
	static char	   *strict_embedding[3] = {
		"", "-e",
		/* all one string follows (no commas please) */
		"SPI::bootstrap(); use vars qw(%_SHARED);"
		"sub ::mkunsafefunc {return eval("
		"qq[ sub { use strict; $_[0] $_[1] } ]); }"
	};

202 203
	plperl_interp = perl_alloc();
	if (!plperl_interp)
204
		elog(ERROR, "could not allocate Perl interpreter");
205

206
	perl_construct(plperl_interp);
207 208
	perl_parse(plperl_interp, plperl_init_shared_libs, 3 ,
			   (plperl_use_strict ? strict_embedding : loose_embedding), NULL);
209
	perl_run(plperl_interp);
210

211
	plperl_proc_hash = newHV();
212 213
}

214 215 216 217

static void
plperl_safe_init(void)
{
B
Bruce Momjian 已提交
218 219
	static char *safe_module =
	"require Safe; $Safe::VERSION";
220

221
	static char *common_safe_ok =
B
Bruce Momjian 已提交
222
	"use vars qw($PLContainer); $PLContainer = new Safe('PLPerl');"
223 224
	"$PLContainer->permit_only(':default');"
	"$PLContainer->permit(qw[:base_math !:base_io sort time]);"
225 226
	"$PLContainer->share(qw[&elog &spi_exec_query &spi_return_next "
	"&DEBUG &LOG &INFO &NOTICE &WARNING &ERROR %_SHARED ]);"
B
Bruce Momjian 已提交
227
			   ;
228

229 230 231 232 233 234 235 236 237 238 239 240
	static char * strict_safe_ok =
		"$PLContainer->permit('require');$PLContainer->reval('use strict;');"
		"$PLContainer->deny('require');"
		"sub ::mksafefunc { return $PLContainer->reval(qq[ "
		"             sub { BEGIN { strict->import(); } $_[0] $_[1]}]); }"
		;

	static char * loose_safe_ok =
		"sub ::mksafefunc { return $PLContainer->reval(qq[ "
		"             sub { $_[0] $_[1]}]); }"
		;

B
Bruce Momjian 已提交
241 242
	static char *safe_bad =
	"use vars qw($PLContainer); $PLContainer = new Safe('PLPerl');"
243 244
	"$PLContainer->permit_only(':default');"
	"$PLContainer->share(qw[&elog &ERROR ]);"
B
Bruce Momjian 已提交
245
	"sub ::mksafefunc { return $PLContainer->reval(qq[sub { "
246
	"elog(ERROR,'trusted Perl functions disabled - "
247
	"please upgrade Perl Safe module to version 2.09 or later');}]); }"
B
Bruce Momjian 已提交
248
			   ;
249

B
Bruce Momjian 已提交
250
	SV		   *res;
251
	double		safe_version;
252

B
Bruce Momjian 已提交
253
	res = eval_pv(safe_module, FALSE);	/* TRUE = croak if failure */
254 255 256

	safe_version = SvNV(res);

257 258 259 260 261
	/*
	 * 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.
	 */
262 263 264 265 266 267 268 269 270 271
	if (safe_version < 2.0899 )
	{
		/* not safe, so disallow all trusted funcs */
		eval_pv(safe_bad, FALSE);
	}
	else
	{
		eval_pv(common_safe_ok, FALSE);
		eval_pv((plperl_use_strict ? strict_safe_ok : loose_safe_ok), FALSE);
	}
272 273 274 275

	plperl_safe_init_done = true;
}

276

277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
/*
 * Perl likes to put a newline after its error messages; clean up such
 */
static char *
strip_trailing_ws(const char *msg)
{
	char   *res = pstrdup(msg);
	int		len = strlen(res);

	while (len > 0 && isspace((unsigned char) res[len-1]))
		res[--len] = '\0';
	return res;
}


292 293
/* Build a tuple from a hash. */

294 295
static HeapTuple
plperl_build_tuple_result(HV *perlhash, AttInMetadata *attinmeta)
296
{
297 298 299 300 301 302
	TupleDesc	td = attinmeta->tupdesc;
	char	  **values;
	SV		   *val;
	char	   *key;
	I32			klen;
	HeapTuple	tup;
303

304
	values = (char **) palloc0(td->natts * sizeof(char *));
305

306 307 308
	hv_iterinit(perlhash);
	while ((val = hv_iternextsv(perlhash, &key, &klen)))
	{
309
		int	attn = SPI_fnumber(td, key);
310

311
		if (attn <= 0 || td->attrs[attn - 1]->attisdropped)
312 313 314 315
			ereport(ERROR,
					(errcode(ERRCODE_UNDEFINED_COLUMN),
					 errmsg("Perl hash contains nonexistent column \"%s\"",
							key)));
316
		if (SvOK(val) && SvTYPE(val) != SVt_NULL)
317
			values[attn - 1] = SvPV(val, PL_na);
318
	}
319 320 321 322 323
	hv_iterinit(perlhash);

	tup = BuildTupleFromCStrings(attinmeta, values);
	pfree(values);
	return tup;
324 325
}

326

327 328
/* Set up the arguments for a trigger call. */

329 330 331 332 333
static SV  *
plperl_trigger_build_args(FunctionCallInfo fcinfo)
{
	TriggerData *tdata;
	TupleDesc	tupdesc;
334
	int			i;
335 336 337 338 339
	char	   *level;
	char	   *event;
	char	   *relid;
	char	   *when;
	HV		   *hv;
340

341
	hv = newHV();
342 343 344 345

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

346
	relid = DatumGetCString(
347 348
				DirectFunctionCall1(oidout,
									ObjectIdGetDatum(tdata->tg_relation->rd_id)
349 350 351 352 353
				)
			);

	hv_store(hv, "name", 4, newSVpv(tdata->tg_trigger->tgname, 0), 0);
	hv_store(hv, "relid", 5, newSVpv(relid, 0), 0);
354 355 356

	if (TRIGGER_FIRED_BY_INSERT(tdata->tg_event))
	{
357
		event = "INSERT";
358 359 360 361
		if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event))
			hv_store(hv, "new", 3,
					 plperl_hash_from_tuple(tdata->tg_trigtuple, tupdesc),
					 0);
362 363 364
	}
	else if (TRIGGER_FIRED_BY_DELETE(tdata->tg_event))
	{
365
		event = "DELETE";
366 367 368 369
		if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event))
			hv_store(hv, "old", 3,
					 plperl_hash_from_tuple(tdata->tg_trigtuple, tupdesc),
					 0);
370 371 372
	}
	else if (TRIGGER_FIRED_BY_UPDATE(tdata->tg_event))
	{
373
		event = "UPDATE";
374 375 376 377 378 379 380 381 382
		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);
		}
383
	}
384
	else
385
		event = "UNKNOWN";
386

387 388
	hv_store(hv, "event", 5, newSVpv(event, 0), 0);
	hv_store(hv, "argc", 4, newSViv(tdata->tg_trigger->tgnargs), 0);
389

390
	if (tdata->tg_trigger->tgnargs > 0)
391
	{
392 393 394
		AV *av = newAV();
		for (i=0; i < tdata->tg_trigger->tgnargs; i++)
			av_push(av, newSVpv(tdata->tg_trigger->tgargs[i], 0));
395
		hv_store(hv, "args", 4, newRV_noinc((SV *)av), 0);
396
	}
397 398 399

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

	if (TRIGGER_FIRED_BEFORE(tdata->tg_event))
402
		when = "BEFORE";
403
	else if (TRIGGER_FIRED_AFTER(tdata->tg_event))
404
		when = "AFTER";
405
	else
406 407
		when = "UNKNOWN";
	hv_store(hv, "when", 4, newSVpv(when, 0), 0);
408 409

	if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event))
410
		level = "ROW";
411
	else if (TRIGGER_FIRED_FOR_STATEMENT(tdata->tg_event))
412
		level = "STATEMENT";
413
	else
414 415
		level = "UNKNOWN";
	hv_store(hv, "level", 5, newSVpv(level, 0), 0);
416

417
	return newRV_noinc((SV*)hv);
418 419 420
}


421
/* Set up the new tuple returned from a trigger. */
422

423
static HeapTuple
424
plperl_modify_tuple(HV *hvTD, TriggerData *tdata, HeapTuple otup)
425 426 427 428
{
	SV		  **svp;
	HV		   *hvNew;
	HeapTuple	rtup;
429 430 431 432 433 434 435 436
	SV		   *val;
	char	   *key;
	I32			klen;
	int			slotsused;
	int		   *modattrs;
	Datum	   *modvalues;
	char	   *modnulls;

437 438 439 440 441
	TupleDesc	tupdesc;

	tupdesc = tdata->tg_relation->rd_att;

	svp = hv_fetch(hvTD, "new", 3, FALSE);
442
	if (!svp)
443 444 445
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_COLUMN),
				 errmsg("$_TD->{new} does not exist")));
446
	if (!SvOK(*svp) || SvTYPE(*svp) != SVt_RV || SvTYPE(SvRV(*svp)) != SVt_PVHV)
447 448 449
		ereport(ERROR,
				(errcode(ERRCODE_DATATYPE_MISMATCH),
				 errmsg("$_TD->{new} is not a hash reference")));
450 451
	hvNew = (HV *) SvRV(*svp);

452 453 454 455
	modattrs = palloc(tupdesc->natts * sizeof(int));
	modvalues = palloc(tupdesc->natts * sizeof(Datum));
	modnulls = palloc(tupdesc->natts * sizeof(char));
	slotsused = 0;
456

457 458
	hv_iterinit(hvNew);
	while ((val = hv_iternextsv(hvNew, &key, &klen)))
459
	{
460
		int			attn = SPI_fnumber(tupdesc, key);
461

462
		if (attn <= 0 || tupdesc->attrs[attn - 1]->attisdropped)
463 464 465 466
			ereport(ERROR,
					(errcode(ERRCODE_UNDEFINED_COLUMN),
					 errmsg("Perl hash contains nonexistent column \"%s\"",
							key)));
467
		if (SvOK(val) && SvTYPE(val) != SVt_NULL)
468
		{
469 470 471 472 473 474 475 476 477 478 479 480 481
			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,
										 CStringGetDatum(SvPV(val, PL_na)),
										 ObjectIdGetDatum(typioparam),
						 Int32GetDatum(tupdesc->attrs[attn - 1]->atttypmod));
			modnulls[slotsused] = ' ';
482 483 484
		}
		else
		{
485 486
			modvalues[slotsused] = (Datum) 0;
			modnulls[slotsused] = 'n';
487
		}
488 489
		modattrs[slotsused] = attn;
		slotsused++;
490
	}
491 492 493 494
	hv_iterinit(hvNew);

	rtup = SPI_modifytuple(tdata->tg_relation, otup, slotsused,
						   modattrs, modvalues, modnulls);
495 496 497 498

	pfree(modattrs);
	pfree(modvalues);
	pfree(modnulls);
499

500
	if (rtup == NULL)
501
		elog(ERROR, "SPI_modifytuple failed: %s",
502
			 SPI_result_code_string(SPI_result));
503 504 505

	return rtup;
}
506

507 508 509 510 511

/* This is the only externally-visible part of the plperl interface.
 * The Postgres function and trigger managers call it to execute a
 * perl function. */

512
PG_FUNCTION_INFO_V1(plperl_call_handler);
513 514

Datum
515
plperl_call_handler(PG_FUNCTION_ARGS)
516
{
517
	Datum retval;
518
	plperl_proc_desc *save_prodesc;
519

520
	plperl_init_all();
521

522
	save_prodesc = plperl_current_prodesc;
523

524 525 526 527 528 529 530 531 532 533 534 535 536 537 538
	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;
		PG_RE_THROW();
	}
	PG_END_TRY();

	plperl_current_prodesc = save_prodesc;
539 540 541 542 543

	return retval;
}


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

B
Bruce Momjian 已提交
547
static SV  *
548
plperl_create_sub(char *s, bool trusted)
549
{
550
	dSP;
551
	SV		   *subref;
B
Bruce Momjian 已提交
552
	int			count;
553

B
Bruce Momjian 已提交
554
	if (trusted && !plperl_safe_init_done)
555
	{
556
		plperl_safe_init();
557 558
		SPAGAIN;
	}
559

560 561 562
	ENTER;
	SAVETMPS;
	PUSHMARK(SP);
563
	XPUSHs(sv_2mortal(newSVpv("my $_TD=$_[0]; shift;", 0)));
B
Bruce Momjian 已提交
564
	XPUSHs(sv_2mortal(newSVpv(s, 0)));
B
Bruce Momjian 已提交
565
	PUTBACK;
B
Bruce Momjian 已提交
566

567 568
	/*
	 * G_KEEPERR seems to be needed here, else we don't recognize compile
B
Bruce Momjian 已提交
569 570
	 * errors properly.  Perhaps it's because there's another level of
	 * eval inside mksafefunc?
571
	 */
572 573
	count = perl_call_pv((trusted ? "mksafefunc" : "mkunsafefunc"),
						 G_SCALAR | G_EVAL | G_KEEPERR);
574 575
	SPAGAIN;

576 577 578 579 580
	if (count != 1)
	{
		PUTBACK;
		FREETMPS;
		LEAVE;
581
		elog(ERROR, "didn't get a return item from mksafefunc");
582 583
	}

584
	if (SvTRUE(ERRSV))
585
	{
586
		(void) POPs;
587 588 589
		PUTBACK;
		FREETMPS;
		LEAVE;
590 591 592 593
		ereport(ERROR,
				(errcode(ERRCODE_SYNTAX_ERROR),
				 errmsg("creation of Perl function failed: %s",
						strip_trailing_ws(SvPV(ERRSV, PL_na)))));
594 595 596
	}

	/*
597 598
	 * need to make a deep copy of the return. it comes off the stack as a
	 * temporary.
599 600 601
	 */
	subref = newSVsv(POPs);

602 603
	if (!SvROK(subref))
	{
604 605 606
		PUTBACK;
		FREETMPS;
		LEAVE;
607

608 609 610 611
		/*
		 * subref is our responsibility because it is not mortal
		 */
		SvREFCNT_dec(subref);
612
		elog(ERROR, "didn't get a code ref");
613 614 615 616 617
	}

	PUTBACK;
	FREETMPS;
	LEAVE;
618

619 620 621
	return subref;
}

622

623
/**********************************************************************
624
 * plperl_init_shared_libs()		-
625 626 627 628
 *
 * 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.
629
 *
630 631
 **********************************************************************/

632 633
EXTERN_C void boot_DynaLoader(pTHX_ CV *cv);
EXTERN_C void boot_SPI(pTHX_ CV *cv);
634

635
static void
636
plperl_init_shared_libs(pTHX)
637
{
638 639
	char	   *file = __FILE__;

640
	newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
641
	newXS("SPI::bootstrap", boot_SPI, file);
642 643
}

644

B
Bruce Momjian 已提交
645
static SV  *
646
plperl_call_perl_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo)
647 648
{
	dSP;
649 650 651
	SV		   *retval;
	int			i;
	int			count;
652 653 654 655

	ENTER;
	SAVETMPS;

656
	PUSHMARK(SP);
657

658
	XPUSHs(&PL_sv_undef); /* no trigger data */
659

660 661
	for (i = 0; i < desc->nargs; i++)
	{
662 663 664
		if (fcinfo->argnull[i])
			XPUSHs(&PL_sv_undef);
		else if (desc->arg_is_rowtype[i])
665
		{
666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681
			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;

682 683
			hashref = plperl_hash_from_tuple(&tmptup, tupdesc);
			XPUSHs(sv_2mortal(hashref));
684 685 686
		}
		else
		{
687 688
			char	   *tmp;

689 690
			tmp = DatumGetCString(FunctionCall1(&(desc->arg_out_func[i]),
												fcinfo->arg[i]));
691 692
			XPUSHs(sv_2mortal(newSVpv(tmp, 0)));
			pfree(tmp);
693 694 695
		}
	}
	PUTBACK;
696 697 698

	/* Do NOT use G_KEEPERR here */
	count = perl_call_sv(desc->reference, G_SCALAR | G_EVAL);
699 700 701

	SPAGAIN;

702 703 704 705
	if (count != 1)
	{
		PUTBACK;
		FREETMPS;
706
		LEAVE;
707
		elog(ERROR, "didn't get a return item from function");
708 709
	}

710
	if (SvTRUE(ERRSV))
711
	{
712
		(void) POPs;
713 714
		PUTBACK;
		FREETMPS;
715
		LEAVE;
716 717 718 719
		/* 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)))));
720 721 722 723
	}

	retval = newSVsv(POPs);

724 725 726
	PUTBACK;
	FREETMPS;
	LEAVE;
727 728 729 730

	return retval;
}

731

732
static SV  *
733 734
plperl_call_perl_trigger_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo,
							  SV *td)
735 736 737
{
	dSP;
	SV		   *retval;
738
	Trigger    *tg_trigger;
739 740 741 742 743 744 745
	int			i;
	int			count;

	ENTER;
	SAVETMPS;

	PUSHMARK(sp);
746

747
	XPUSHs(td);
748

749 750 751
	tg_trigger = ((TriggerData *) fcinfo->context)->tg_trigger;
	for (i = 0; i < tg_trigger->tgnargs; i++)
		XPUSHs(sv_2mortal(newSVpv(tg_trigger->tgargs[i], 0)));
752 753
	PUTBACK;

754 755
	/* Do NOT use G_KEEPERR here */
	count = perl_call_sv(desc->reference, G_SCALAR | G_EVAL);
756 757 758 759 760 761 762 763

	SPAGAIN;

	if (count != 1)
	{
		PUTBACK;
		FREETMPS;
		LEAVE;
764
		elog(ERROR, "didn't get a return item from trigger function");
765 766 767 768
	}

	if (SvTRUE(ERRSV))
	{
769
		(void) POPs;
770 771 772
		PUTBACK;
		FREETMPS;
		LEAVE;
773 774 775 776
		/* 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)))));
777 778 779 780 781 782 783 784 785 786
	}

	retval = newSVsv(POPs);

	PUTBACK;
	FREETMPS;
	LEAVE;

	return retval;
}
787

788

789
static Datum
790
plperl_func_handler(PG_FUNCTION_ARGS)
791 792
{
	plperl_proc_desc *prodesc;
793 794
	SV		   *perlret;
	Datum		retval;
795
	ReturnSetInfo *rsi;
796

797 798 799
	if (SPI_connect() != SPI_OK_CONNECT)
		elog(ERROR, "could not connect to SPI manager");

800
	prodesc = compile_plperl_function(fcinfo->flinfo->fn_oid, false);
801 802

	plperl_current_prodesc = prodesc;
803 804 805
	prodesc->caller_info = fcinfo;
	prodesc->tuple_store = 0;
	prodesc->tuple_desc = 0;
806

807
	perlret = plperl_call_perl_func(prodesc, fcinfo);
808 809 810 811 812 813 814 815

	/************************************************************
	 * 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)
816
		elog(ERROR, "SPI_finish() failed");
817

818
	rsi = (ReturnSetInfo *)fcinfo->resultinfo;
819

820 821 822 823
	if (prodesc->fn_retisset) {
		if (!rsi || !IsA(rsi, ReturnSetInfo) ||
			(rsi->allowedModes & SFRM_Materialize) == 0 ||
			rsi->expectedDesc == NULL)
824
		{
825 826 827 828
			ereport(ERROR,
					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
					 errmsg("set-valued function called in context that "
							"cannot accept a set")));
829 830
		}

831 832 833 834 835 836
		/* If the Perl function returned an arrayref, we pretend that it
		 * 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. */
		if (SvTYPE(perlret) == SVt_RV &&
			SvTYPE(SvRV(perlret)) == SVt_PVAV)
837
		{
838 839 840 841 842 843 844
			int i = 0;
			SV **svp = 0;
			AV *rav = (AV *)SvRV(perlret);
			while ((svp = av_fetch(rav, i, FALSE)) != NULL) {
				plperl_return_next(*svp);
				i++;
			}
845
		}
846
		else if (SvTYPE(perlret) != SVt_NULL)
847
		{
848 849
			ereport(ERROR,
					(errcode(ERRCODE_DATATYPE_MISMATCH),
850 851
					 errmsg("set-returning Perl function must return "
							"reference to array or use return_next")));
852
		}
B
Bruce Momjian 已提交
853

854 855 856 857
		rsi->returnMode = SFRM_Materialize;
		if (prodesc->tuple_store) {
			rsi->setResult = prodesc->tuple_store;
			rsi->setDesc = prodesc->tuple_desc;
858
		}
859 860 861 862 863 864 865 866 867
		retval = (Datum)0;
	}
	else if (SvTYPE(perlret) == SVt_NULL)
	{
		/* Return NULL if Perl code returned undef */
		if (rsi && IsA(rsi, ReturnSetInfo))
			rsi->isDone = ExprEndResult;
		fcinfo->isnull = true;
		retval = (Datum)0;
B
Bruce Momjian 已提交
868
	}
869
	else if (prodesc->fn_retistuple)
870
	{
871 872
		/* Return a perl hash converted to a Datum */
		TupleDesc td;
873
		AttInMetadata *attinmeta;
874
		HeapTuple tup;
875

876 877 878
		if (!SvOK(perlret) || SvTYPE(perlret) != SVt_RV ||
			SvTYPE(SvRV(perlret)) != SVt_PVHV)
		{
879 880
			ereport(ERROR,
					(errcode(ERRCODE_DATATYPE_MISMATCH),
881 882 883
					 errmsg("composite-returning Perl function "
							"must return reference to hash")));
		}
884

885 886 887 888 889 890 891 892
		/* 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")));
		}
893

894 895
		attinmeta = TupleDescGetAttInMetadata(td);
		tup = plperl_build_tuple_result((HV *)SvRV(perlret), attinmeta);
896 897 898 899
		retval = HeapTupleGetDatum(tup);
	}
	else
	{
900 901
		/* Return a perl string converted to a Datum */
		char *val = SvPV(perlret, PL_na);
902 903 904 905
		retval = FunctionCall3(&prodesc->result_in_func,
							   CStringGetDatum(val),
							   ObjectIdGetDatum(prodesc->result_typioparam),
							   Int32GetDatum(-1));
906
	}
907 908 909 910 911

	SvREFCNT_dec(perlret);
	return retval;
}

912

913 914 915 916 917 918 919 920 921
static Datum
plperl_trigger_handler(PG_FUNCTION_ARGS)
{
	plperl_proc_desc *prodesc;
	SV		   *perlret;
	Datum		retval;
	SV		   *svTD;
	HV		   *hvTD;

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

926 927 928
	/* Find or compile the function */
	prodesc = compile_plperl_function(fcinfo->flinfo->fn_oid, true);

929 930
	plperl_current_prodesc = prodesc;

931 932
	svTD = plperl_trigger_build_args(fcinfo);
	perlret = plperl_call_perl_trigger_func(prodesc, fcinfo, svTD);
933
	hvTD = (HV *) SvRV(svTD);
934 935 936 937 938 939 940 941

	/************************************************************
	* 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)
942
		elog(ERROR, "SPI_finish() failed");
943

944
	if (!(perlret && SvOK(perlret) && SvTYPE(perlret) != SVt_NULL))
945
	{
946
		/* undef result means go ahead with original tuple */
947 948 949 950 951 952 953 954
		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;
955 956
		else
			retval = (Datum) 0;	/* can this happen? */
957 958 959
	}
	else
	{
960 961
		HeapTuple	trv;
		char	   *tmp;
962

963
		tmp = SvPV(perlret, PL_na);
964

965 966 967 968 969 970 971 972 973 974 975 976
		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);
977 978
			else
			{
979 980 981
				ereport(WARNING,
						(errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
						 errmsg("ignoring modified tuple in DELETE trigger")));
982 983 984
				trv = NULL;
			}
		}
985
		else
986
		{
987 988
			ereport(ERROR,
					(errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
989 990
					 errmsg("result of Perl trigger function must be undef, "
							"\"SKIP\" or \"MODIFY\"")));
991 992 993
			trv = NULL;
		}
		retval = PointerGetDatum(trv);
994 995
	}

996 997 998
	SvREFCNT_dec(svTD);
	if (perlret)
		SvREFCNT_dec(perlret);
999 1000 1001

	return retval;
}
1002

1003

1004 1005
static plperl_proc_desc *
compile_plperl_function(Oid fn_oid, bool is_trigger)
1006
{
1007 1008 1009 1010 1011
	HeapTuple	procTup;
	Form_pg_proc procStruct;
	char		internal_proname[64];
	int			proname_len;
	plperl_proc_desc *prodesc = NULL;
1012
	int			i;
1013
	SV			**svp;
1014

1015 1016 1017 1018 1019
	/* We'll need the pg_proc tuple in any case... */
	procTup = SearchSysCache(PROCOID,
							 ObjectIdGetDatum(fn_oid),
							 0, 0, 0);
	if (!HeapTupleIsValid(procTup))
1020
		elog(ERROR, "cache lookup failed for function %u", fn_oid);
1021
	procStruct = (Form_pg_proc) GETSTRUCT(procTup);
1022 1023 1024 1025

	/************************************************************
	 * Build our internal proc name from the functions Oid
	 ************************************************************/
1026 1027 1028 1029
	if (!is_trigger)
		sprintf(internal_proname, "__PLPerl_proc_%u", fn_oid);
	else
		sprintf(internal_proname, "__PLPerl_proc_%u_trigger", fn_oid);
1030

1031
	proname_len = strlen(internal_proname);
1032 1033 1034 1035

	/************************************************************
	 * Lookup the internal proc name in the hashtable
	 ************************************************************/
1036 1037
	svp = hv_fetch(plperl_proc_hash, internal_proname, proname_len, FALSE);
	if (svp)
1038
	{
1039 1040
		bool		uptodate;

1041
		prodesc = (plperl_proc_desc *) SvIV(*svp);
1042

1043
		/************************************************************
1044 1045 1046
		 * 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.
1047
		 ************************************************************/
1048
		uptodate = (prodesc->fn_xmin == HeapTupleHeaderGetXmin(procTup->t_data) &&
B
Bruce Momjian 已提交
1049
			prodesc->fn_cmin == HeapTupleHeaderGetCmin(procTup->t_data));
1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071

		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;
1072 1073
		Datum		prosrcdatum;
		bool		isnull;
1074 1075 1076 1077 1078 1079
		char	   *proc_source;

		/************************************************************
		 * Allocate a new procedure description block
		 ************************************************************/
		prodesc = (plperl_proc_desc *) malloc(sizeof(plperl_proc_desc));
1080
		if (prodesc == NULL)
1081 1082 1083
			ereport(ERROR,
					(errcode(ERRCODE_OUT_OF_MEMORY),
					 errmsg("out of memory")));
1084 1085
		MemSet(prodesc, 0, sizeof(plperl_proc_desc));
		prodesc->proname = strdup(internal_proname);
1086 1087
		prodesc->fn_xmin = HeapTupleHeaderGetXmin(procTup->t_data);
		prodesc->fn_cmin = HeapTupleHeaderGetCmin(procTup->t_data);
1088

1089 1090 1091 1092
		/* Remember if function is STABLE/IMMUTABLE */
		prodesc->fn_readonly =
			(procStruct->provolatile != PROVOLATILE_VOLATILE);

1093
		/************************************************************
1094
		 * Lookup the pg_language tuple by Oid
1095
		 ************************************************************/
1096 1097
		langTup = SearchSysCache(LANGOID,
								 ObjectIdGetDatum(procStruct->prolang),
1098
								 0, 0, 0);
1099
		if (!HeapTupleIsValid(langTup))
1100 1101 1102
		{
			free(prodesc->proname);
			free(prodesc);
1103
			elog(ERROR, "cache lookup failed for language %u",
1104
				 procStruct->prolang);
1105
		}
1106 1107 1108
		langStruct = (Form_pg_language) GETSTRUCT(langTup);
		prodesc->lanpltrusted = langStruct->lanpltrusted;
		ReleaseSysCache(langTup);
1109 1110

		/************************************************************
1111 1112
		 * Get the required information for input conversion of the
		 * return value.
1113
		 ************************************************************/
1114 1115 1116
		if (!is_trigger)
		{
			typeTup = SearchSysCache(TYPEOID,
1117
								ObjectIdGetDatum(procStruct->prorettype),
1118 1119 1120 1121 1122
									 0, 0, 0);
			if (!HeapTupleIsValid(typeTup))
			{
				free(prodesc->proname);
				free(prodesc);
1123
				elog(ERROR, "cache lookup failed for type %u",
1124
					 procStruct->prorettype);
1125 1126 1127
			}
			typeStruct = (Form_pg_type) GETSTRUCT(typeTup);

1128
			/* Disallow pseudotype result, except VOID or RECORD */
1129 1130
			if (typeStruct->typtype == 'p')
			{
1131 1132
				if (procStruct->prorettype == VOIDOID ||
					procStruct->prorettype == RECORDOID)
B
Bruce Momjian 已提交
1133
					 /* okay */ ;
1134
				else if (procStruct->prorettype == TRIGGEROID)
1135 1136 1137
				{
					free(prodesc->proname);
					free(prodesc);
1138 1139
					ereport(ERROR,
							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1140 1141
							 errmsg("trigger functions may only be called "
									"as triggers")));
1142 1143 1144 1145 1146
				}
				else
				{
					free(prodesc->proname);
					free(prodesc);
1147 1148
					ereport(ERROR,
							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
B
Bruce Momjian 已提交
1149 1150
						 errmsg("plperl functions cannot return type %s",
								format_type_be(procStruct->prorettype))));
1151 1152 1153
				}
			}

1154 1155 1156 1157
			prodesc->result_oid = procStruct->prorettype;
			prodesc->fn_retisset = procStruct->proretset;
			prodesc->fn_retistuple = (typeStruct->typtype == 'c' ||
									  procStruct->prorettype == RECORDOID);
1158 1159

			perm_fmgr_info(typeStruct->typinput, &(prodesc->result_in_func));
1160
			prodesc->result_typioparam = getTypeIOParam(typeTup);
1161 1162 1163

			ReleaseSysCache(typeTup);
		}
1164 1165

		/************************************************************
1166 1167
		 * Get the required information for output conversion
		 * of all procedure arguments
1168
		 ************************************************************/
1169 1170 1171 1172 1173 1174
		if (!is_trigger)
		{
			prodesc->nargs = procStruct->pronargs;
			for (i = 0; i < prodesc->nargs; i++)
			{
				typeTup = SearchSysCache(TYPEOID,
1175
							ObjectIdGetDatum(procStruct->proargtypes.values[i]),
1176 1177 1178 1179 1180
										 0, 0, 0);
				if (!HeapTupleIsValid(typeTup))
				{
					free(prodesc->proname);
					free(prodesc);
1181
					elog(ERROR, "cache lookup failed for type %u",
1182
						 procStruct->proargtypes.values[i]);
1183 1184 1185
				}
				typeStruct = (Form_pg_type) GETSTRUCT(typeTup);

1186 1187 1188 1189 1190
				/* Disallow pseudotype argument */
				if (typeStruct->typtype == 'p')
				{
					free(prodesc->proname);
					free(prodesc);
1191 1192
					ereport(ERROR,
							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
B
Bruce Momjian 已提交
1193
						   errmsg("plperl functions cannot take type %s",
1194
						   format_type_be(procStruct->proargtypes.values[i]))));
1195 1196
				}

1197 1198
				if (typeStruct->typtype == 'c')
					prodesc->arg_is_rowtype[i] = true;
1199
				else
1200 1201 1202 1203 1204
				{
					prodesc->arg_is_rowtype[i] = false;
					perm_fmgr_info(typeStruct->typoutput,
								   &(prodesc->arg_out_func[i]));
				}
1205 1206 1207 1208

				ReleaseSysCache(typeTup);
			}
		}
1209

1210 1211 1212 1213 1214
		/************************************************************
		 * create the text of the anonymous subroutine.
		 * we do not use a named subroutine so that we can call directly
		 * through the reference.
		 ************************************************************/
1215 1216 1217 1218
		prosrcdatum = SysCacheGetAttr(PROCOID, procTup,
									  Anum_pg_proc_prosrc, &isnull);
		if (isnull)
			elog(ERROR, "null prosrc");
1219
		proc_source = DatumGetCString(DirectFunctionCall1(textout,
1220
														  prosrcdatum));
1221 1222

		/************************************************************
1223
		 * Create the procedure in the interpreter
1224
		 ************************************************************/
1225 1226
		prodesc->reference = plperl_create_sub(proc_source, prodesc->lanpltrusted);
		pfree(proc_source);
1227
		if (!prodesc->reference) /* can this happen? */
1228 1229 1230
		{
			free(prodesc->proname);
			free(prodesc);
1231
			elog(ERROR, "could not create internal procedure \"%s\"",
1232
				 internal_proname);
1233 1234
		}

1235 1236
		hv_store(plperl_proc_hash, internal_proname, proname_len,
				 newSViv((IV) prodesc), 0);
1237 1238
	}

1239
	ReleaseSysCache(procTup);
1240

1241 1242
	return prodesc;
}
1243 1244


1245 1246
/* Build a hash from all attributes of a given tuple. */

B
Bruce Momjian 已提交
1247
static SV  *
1248
plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc)
1249
{
1250
	HV		   *hv;
1251
	int			i;
1252

1253
	hv = newHV();
1254 1255 1256

	for (i = 0; i < tupdesc->natts; i++)
	{
1257 1258 1259 1260 1261 1262 1263 1264
		Datum		attr;
		bool		isnull;
		char	   *attname;
		char	   *outputstr;
		Oid			typoutput;
		bool		typisvarlena;
		int			namelen;

1265 1266 1267
		if (tupdesc->attrs[i]->attisdropped)
			continue;

1268
		attname = NameStr(tupdesc->attrs[i]->attname);
1269
		namelen = strlen(attname);
1270 1271
		attr = heap_getattr(tuple, i + 1, tupdesc, &isnull);

1272 1273 1274
		if (isnull) {
			/* Store (attname => undef) and move on. */
			hv_store(hv, attname, namelen, newSV(0), 0);
1275 1276 1277
			continue;
		}

1278
		/* XXX should have a way to cache these lookups */
1279

1280
		getTypeOutputInfo(tupdesc->attrs[i]->atttypid,
1281
						  &typoutput, &typisvarlena);
1282

1283 1284
		outputstr = DatumGetCString(OidFunctionCall1(typoutput,
													 attr));
1285 1286

		hv_store(hv, attname, namelen, newSVpv(outputstr, 0), 0);
1287
	}
1288

1289
	return newRV_noinc((SV *) hv);
1290
}
1291 1292 1293 1294 1295 1296 1297


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

1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355
	/*
	 * Execute the query inside a sub-transaction, so we can cope with
	 * errors sanely
	 */
	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;
		/*
		 * AtEOSubXact_SPI() should not have popped any SPI context,
		 * but just in case it did, make sure we remain connected.
		 */
		SPI_restore_connection();
	}
	PG_CATCH();
	{
		ErrorData  *edata;

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

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

		/*
		 * 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.
		 */
		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();
1356 1357 1358 1359

	return ret_hv;
}

1360

1361
static HV  *
1362 1363
plperl_spi_execute_fetch_result(SPITupleTable *tuptable, int processed,
								int status)
1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375
{
	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)
	{
1376
		AV		   *rows;
1377
		SV		   *row;
1378
		int			i;
1379

1380 1381 1382 1383
		rows = newAV();
		for (i = 0; i < processed; i++)
		{
			row = plperl_hash_from_tuple(tuptable->vals[i], tuptable->tupdesc);
1384
			av_push(rows, row);
1385
		}
1386 1387
		hv_store(result, "rows", strlen("rows"),
				 newRV_noinc((SV *) rows), 0);
1388 1389 1390 1391 1392 1393
	}

	SPI_freetuptable(tuptable);

	return result;
}
1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470


void
plperl_return_next(SV *sv)
{
	plperl_proc_desc *prodesc = plperl_current_prodesc;
	FunctionCallInfo fcinfo = prodesc->caller_info;
	ReturnSetInfo *rsi = (ReturnSetInfo *)fcinfo->resultinfo;
	MemoryContext cxt;
	HeapTuple tuple;
	TupleDesc tupdesc;

	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);

	if (!prodesc->tuple_store)
		prodesc->tuple_store = tuplestore_begin_heap(true, false, work_mem);

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

		rettype = get_call_result_type(fcinfo, NULL, &tupdesc);
		tupdesc = CreateTupleDescCopy(tupdesc);
		attinmeta = TupleDescGetAttInMetadata(tupdesc);
		tuple = plperl_build_tuple_result((HV *)SvRV(sv), attinmeta);
	}
	else
	{
		Datum ret;
		bool isNull;

		tupdesc = CreateTupleDescCopy(rsi->expectedDesc);

		if (SvOK(sv) && SvTYPE(sv) != SVt_NULL)
		{
			char *val = SvPV(sv, PL_na);
			ret = FunctionCall3(&prodesc->result_in_func,
								PointerGetDatum(val),
								ObjectIdGetDatum(prodesc->result_typioparam),
								Int32GetDatum(-1));
			isNull = false;
		}
		else {
			ret = (Datum)0;
			isNull = true;
		}

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

	if (!prodesc->tuple_desc)
		prodesc->tuple_desc = tupdesc;

	tuplestore_puttuple(prodesc->tuple_store, tuple);
	heap_freetuple(tuple);
	MemoryContextSwitchTo(cxt);
}