plperl.c 41.3 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 Weick.
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.67 2005/01/14 16:25:42 tgl Exp $
37
 *
38 39
 **********************************************************************/

40
#include "postgres.h"
41 42

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

/* postgreSQL stuff */
48 49
#include "commands/trigger.h"
#include "executor/spi.h"
50
#include "funcapi.h"
51
#include "utils/lsyscache.h"
52
#include "utils/typcache.h"
53 54

/* perl stuff */
B
Bruce Momjian 已提交
55 56
#include "EXTERN.h"
#include "perl.h"
57
#include "XSUB.h"
58
#include "ppport.h"
59

60 61 62 63 64 65
/* just in case these symbols aren't provided */
#ifndef pTHX_
#define pTHX_
#define pTHX void
#endif

66 67 68 69 70 71 72

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


/**********************************************************************
 * Global data
 **********************************************************************/
static int	plperl_firstcall = 1;
94
static bool plperl_safe_init_done = false;
95
static PerlInterpreter *plperl_interp = NULL;
96 97
static HV  *plperl_proc_hash = NULL;

98 99 100
/* this is saved and restored by plperl_call_handler */
static plperl_proc_desc *plperl_current_prodesc = NULL;

101 102 103 104
/**********************************************************************
 * Forward declarations
 **********************************************************************/
static void plperl_init_all(void);
105
static void plperl_init_interp(void);
106

B
Bruce Momjian 已提交
107
Datum		plperl_call_handler(PG_FUNCTION_ARGS);
108
void		plperl_init(void);
109

110 111
HV		   *plperl_spi_exec(char *query, int limit);

112
static Datum plperl_func_handler(PG_FUNCTION_ARGS);
113

114
static Datum plperl_trigger_handler(PG_FUNCTION_ARGS);
115 116
static plperl_proc_desc *compile_plperl_function(Oid fn_oid, bool is_trigger);

117
static SV  *plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc);
118
static void plperl_init_shared_libs(pTHX);
119
static HV  *plperl_spi_execute_fetch_result(SPITupleTable *, int, int);
120 121


122 123 124 125 126 127 128
/*
 * 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,
129 130 131
 * 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.
132 133 134 135
 */
static void
perm_fmgr_info(Oid functionId, FmgrInfo *finfo)
{
136
	fmgr_info_cxt(functionId, finfo, TopMemoryContext);
137 138
}

139
/**********************************************************************
140 141 142 143 144
 * plperl_init()			- Initialize everything that can be
 *							  safely initialized during postmaster
 *							  startup.
 *
 * DO NOT make this static --- it has to be callable by preload
145
 **********************************************************************/
146 147
void
plperl_init(void)
148 149 150 151 152 153 154
{
	/************************************************************
	 * Do initialization only once
	 ************************************************************/
	if (!plperl_firstcall)
		return;

155
	/************************************************************
156
	 * Create the Perl interpreter
157
	 ************************************************************/
158
	plperl_init_interp();
159 160 161 162

	plperl_firstcall = 0;
}

163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
/**********************************************************************
 * plperl_init_all()		- Initialize all
 **********************************************************************/
static void
plperl_init_all(void)
{

	/************************************************************
	 * Execute postmaster-startup safe initialization
	 ************************************************************/
	if (plperl_firstcall)
		plperl_init();

	/************************************************************
	 * Any other initialization that must be done each time a new
	 * backend starts -- currently none
	 ************************************************************/

}

183 184

/**********************************************************************
185
 * plperl_init_interp() - Create the Perl interpreter
186 187
 **********************************************************************/
static void
188
plperl_init_interp(void)
189
{
190
	static char	   *embedding[3] = {
B
Bruce Momjian 已提交
191 192 193
		"", "-e",

		/*
B
Bruce Momjian 已提交
194 195
		 * no commas between the next lines please. They are supposed to
		 * be one string
B
Bruce Momjian 已提交
196
		 */
197
		"SPI::bootstrap(); use vars qw(%_SHARED);"
198
		"sub ::mkunsafefunc {return eval(qq[ sub { $_[0] $_[1] } ]); }"
B
Bruce Momjian 已提交
199
	};
200

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

205 206 207
	perl_construct(plperl_interp);
	perl_parse(plperl_interp, plperl_init_shared_libs, 3, embedding, NULL);
	perl_run(plperl_interp);
208 209

	/************************************************************
210
	 * Initialize the procedure hash table
211
	 ************************************************************/
212
	plperl_proc_hash = newHV();
213 214
}

215 216 217 218

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

B
Bruce Momjian 已提交
222 223
	static char *safe_ok =
	"use vars qw($PLContainer); $PLContainer = new Safe('PLPerl');"
224 225 226 227
	"$PLContainer->permit_only(':default');"
	"$PLContainer->permit(qw[:base_math !:base_io sort time]);"
	"$PLContainer->share(qw[&elog &spi_exec_query &DEBUG &LOG "
    "&INFO &NOTICE &WARNING &ERROR %SHARED ]);"
B
Bruce Momjian 已提交
228 229
	"sub ::mksafefunc { return $PLContainer->reval(qq[sub { $_[0] $_[1]}]); }"
			   ;
230

B
Bruce Momjian 已提交
231 232
	static char *safe_bad =
	"use vars qw($PLContainer); $PLContainer = new Safe('PLPerl');"
233 234
	"$PLContainer->permit_only(':default');"
	"$PLContainer->share(qw[&elog &ERROR ]);"
B
Bruce Momjian 已提交
235
	"sub ::mksafefunc { return $PLContainer->reval(qq[sub { "
236 237
	"elog(ERROR,'trusted Perl functions disabled - "
    "please upgrade Perl Safe module to version 2.09 or later');}]); }"
B
Bruce Momjian 已提交
238
			   ;
239

B
Bruce Momjian 已提交
240
	SV		   *res;
241
	double		safe_version;
242

B
Bruce Momjian 已提交
243
	res = eval_pv(safe_module, FALSE);	/* TRUE = croak if failure */
244 245 246

	safe_version = SvNV(res);

247 248 249 250 251 252
	/*
	 * 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.
	 */
	eval_pv((safe_version < 2.0899 ? safe_bad : safe_ok), FALSE);
253 254 255 256

	plperl_safe_init_done = true;
}

257

258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
/*
 * 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;
}


273 274 275 276 277
/*
 * Build a tuple from a hash
 */
static HeapTuple
plperl_build_tuple_result(HV *perlhash, AttInMetadata *attinmeta)
278
{
279 280 281 282 283 284
	TupleDesc	td = attinmeta->tupdesc;
	char	  **values;
	SV		   *val;
	char	   *key;
	I32			klen;
	HeapTuple	tup;
285

286
	values = (char **) palloc0(td->natts * sizeof(char *));
287

288 289 290 291
	hv_iterinit(perlhash);
	while ((val = hv_iternextsv(perlhash, &key, &klen)))
	{
		int			attn = SPI_fnumber(td, key);
292

293
		if (attn <= 0 || td->attrs[attn - 1]->attisdropped)
294 295 296 297
			ereport(ERROR,
					(errcode(ERRCODE_UNDEFINED_COLUMN),
					 errmsg("Perl hash contains nonexistent column \"%s\"",
							key)));
298
		if (SvOK(val) && SvTYPE(val) != SVt_NULL)
299
			values[attn - 1] = SvPV(val, PL_na);
300
	}
301 302 303 304 305
	hv_iterinit(perlhash);

	tup = BuildTupleFromCStrings(attinmeta, values);
	pfree(values);
	return tup;
306 307
}

308

309 310 311 312 313 314 315 316
/**********************************************************************
 * set up arguments for a trigger call
 **********************************************************************/
static SV  *
plperl_trigger_build_args(FunctionCallInfo fcinfo)
{
	TriggerData *tdata;
	TupleDesc	tupdesc;
317
	int			i;
318 319 320 321 322
	char	   *level;
	char	   *event;
	char	   *relid;
	char	   *when;
	HV		   *hv;
323

324
	hv = newHV();
325 326 327 328

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

329
	relid = DatumGetCString(
330 331
				DirectFunctionCall1(oidout,
									ObjectIdGetDatum(tdata->tg_relation->rd_id)
332 333 334 335 336
				)
			);

	hv_store(hv, "name", 4, newSVpv(tdata->tg_trigger->tgname, 0), 0);
	hv_store(hv, "relid", 5, newSVpv(relid, 0), 0);
337 338 339

	if (TRIGGER_FIRED_BY_INSERT(tdata->tg_event))
	{
340
		event = "INSERT";
341 342 343 344
		if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event))
			hv_store(hv, "new", 3,
					 plperl_hash_from_tuple(tdata->tg_trigtuple, tupdesc),
					 0);
345 346 347
	}
	else if (TRIGGER_FIRED_BY_DELETE(tdata->tg_event))
	{
348
		event = "DELETE";
349 350 351 352
		if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event))
			hv_store(hv, "old", 3,
					 plperl_hash_from_tuple(tdata->tg_trigtuple, tupdesc),
					 0);
353 354 355
	}
	else if (TRIGGER_FIRED_BY_UPDATE(tdata->tg_event))
	{
356
		event = "UPDATE";
357 358 359 360 361 362 363 364 365
		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);
		}
366
	}
367
	else
368
		event = "UNKNOWN";
369

370 371
	hv_store(hv, "event", 5, newSVpv(event, 0), 0);
	hv_store(hv, "argc", 4, newSViv(tdata->tg_trigger->tgnargs), 0);
372

373
	if (tdata->tg_trigger->tgnargs > 0)
374
	{
375 376 377
		AV *av = newAV();
		for (i=0; i < tdata->tg_trigger->tgnargs; i++)
			av_push(av, newSVpv(tdata->tg_trigger->tgargs[i], 0));
378
		hv_store(hv, "args", 4, newRV_noinc((SV *)av), 0);
379
	}
380 381 382

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

	if (TRIGGER_FIRED_BEFORE(tdata->tg_event))
385
		when = "BEFORE";
386
	else if (TRIGGER_FIRED_AFTER(tdata->tg_event))
387
		when = "AFTER";
388
	else
389 390
		when = "UNKNOWN";
	hv_store(hv, "when", 4, newSVpv(when, 0), 0);
391 392

	if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event))
393
		level = "ROW";
394
	else if (TRIGGER_FIRED_FOR_STATEMENT(tdata->tg_event))
395
		level = "STATEMENT";
396
	else
397 398
		level = "UNKNOWN";
	hv_store(hv, "level", 5, newSVpv(level, 0), 0);
399

400
	return newRV_noinc((SV*)hv);
401 402 403
}


404 405 406 407 408 409 410 411 412 413 414 415 416 417
/*
 * Obtain tuple descriptor for a function returning tuple
 *
 * NB: copy the result if needed for any great length of time
 */
static TupleDesc
get_function_tupdesc(Oid result_type, ReturnSetInfo *rsinfo)
{
	if (result_type == RECORDOID)
	{
		/* We must get the information from call context */
		if (!rsinfo || !IsA(rsinfo, ReturnSetInfo) ||
			rsinfo->expectedDesc == NULL)
			ereport(ERROR,
418 419 420
					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
					 errmsg("function returning record called in context "
							"that cannot accept type record")));
421 422 423 424 425 426
		return rsinfo->expectedDesc;
	}
	else				/* ordinary composite type */
		return lookup_rowtype_tupdesc(result_type, -1);
}

427 428 429 430
/**********************************************************************
 * set up the new tuple returned from a trigger
 **********************************************************************/
static HeapTuple
431
plperl_modify_tuple(HV *hvTD, TriggerData *tdata, HeapTuple otup)
432 433 434 435
{
	SV		  **svp;
	HV		   *hvNew;
	HeapTuple	rtup;
436 437 438 439 440 441 442 443
	SV		   *val;
	char	   *key;
	I32			klen;
	int			slotsused;
	int		   *modattrs;
	Datum	   *modvalues;
	char	   *modnulls;

444 445 446 447 448
	TupleDesc	tupdesc;

	tupdesc = tdata->tg_relation->rd_att;

	svp = hv_fetch(hvTD, "new", 3, FALSE);
449
	if (!svp)
450 451 452
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_COLUMN),
				 errmsg("$_TD->{new} does not exist")));
453
	if (!SvOK(*svp) || SvTYPE(*svp) != SVt_RV || SvTYPE(SvRV(*svp)) != SVt_PVHV)
454 455 456
		ereport(ERROR,
				(errcode(ERRCODE_DATATYPE_MISMATCH),
				 errmsg("$_TD->{new} is not a hash reference")));
457 458
	hvNew = (HV *) SvRV(*svp);

459 460 461 462
	modattrs = palloc(tupdesc->natts * sizeof(int));
	modvalues = palloc(tupdesc->natts * sizeof(Datum));
	modnulls = palloc(tupdesc->natts * sizeof(char));
	slotsused = 0;
463

464 465
	hv_iterinit(hvNew);
	while ((val = hv_iternextsv(hvNew, &key, &klen)))
466
	{
467
		int			attn = SPI_fnumber(tupdesc, key);
468

469
		if (attn <= 0 || tupdesc->attrs[attn - 1]->attisdropped)
470 471 472 473
			ereport(ERROR,
					(errcode(ERRCODE_UNDEFINED_COLUMN),
					 errmsg("Perl hash contains nonexistent column \"%s\"",
							key)));
474
		if (SvOK(val) && SvTYPE(val) != SVt_NULL)
475
		{
476 477 478 479 480 481 482 483 484 485 486 487 488
			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] = ' ';
489 490 491
		}
		else
		{
492 493
			modvalues[slotsused] = (Datum) 0;
			modnulls[slotsused] = 'n';
494
		}
495 496
		modattrs[slotsused] = attn;
		slotsused++;
497
	}
498 499 500 501
	hv_iterinit(hvNew);

	rtup = SPI_modifytuple(tdata->tg_relation, otup, slotsused,
						   modattrs, modvalues, modnulls);
502 503 504 505

	pfree(modattrs);
	pfree(modvalues);
	pfree(modnulls);
506

507
	if (rtup == NULL)
508
		elog(ERROR, "SPI_modifytuple failed: %s",
509
			 SPI_result_code_string(SPI_result));
510 511 512

	return rtup;
}
513 514 515 516 517 518 519 520

/**********************************************************************
 * plperl_call_handler		- This is the only visible function
 *				  of the PL interpreter. The PostgreSQL
 *				  function manager and trigger manager
 *				  call this function for execution of
 *				  perl procedures.
 **********************************************************************/
521
PG_FUNCTION_INFO_V1(plperl_call_handler);
522 523 524

/* keep non-static */
Datum
525
plperl_call_handler(PG_FUNCTION_ARGS)
526 527
{
	Datum		retval;
528
	plperl_proc_desc *save_prodesc;
529

530 531 532
	/*
	 * Initialize interpreter if first time through
	 */
533
	plperl_init_all();
534

535 536 537 538
	/*
	 * Ensure that static pointers are saved/restored properly
	 */
	save_prodesc = plperl_current_prodesc;
539

540 541
	PG_TRY();
	{
542
		/*
543 544
		 * Determine if called as function or trigger and
		 * call appropriate subhandler
545
		 */
546 547 548 549 550 551 552 553 554 555 556 557 558
		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;
559 560 561 562 563 564 565

	return retval;
}


/**********************************************************************
 * plperl_create_sub()		- calls the perl interpreter to
566 567
 *		create the anonymous subroutine whose text is in the SV.
 *		Returns the SV containing the RV to the closure.
568
 **********************************************************************/
B
Bruce Momjian 已提交
569
static SV  *
570
plperl_create_sub(char *s, bool trusted)
571
{
572
	dSP;
573
	SV		   *subref;
B
Bruce Momjian 已提交
574
	int			count;
575

B
Bruce Momjian 已提交
576
	if (trusted && !plperl_safe_init_done)
577
	{
578
		plperl_safe_init();
579 580
		SPAGAIN;
	}
581

582 583 584
	ENTER;
	SAVETMPS;
	PUSHMARK(SP);
585
	XPUSHs(sv_2mortal(newSVpv("my $_TD=$_[0]; shift;", 0)));
B
Bruce Momjian 已提交
586
	XPUSHs(sv_2mortal(newSVpv(s, 0)));
B
Bruce Momjian 已提交
587
	PUTBACK;
B
Bruce Momjian 已提交
588

589 590
	/*
	 * G_KEEPERR seems to be needed here, else we don't recognize compile
B
Bruce Momjian 已提交
591 592
	 * errors properly.  Perhaps it's because there's another level of
	 * eval inside mksafefunc?
593
	 */
594 595
	count = perl_call_pv((trusted ? "mksafefunc" : "mkunsafefunc"),
						 G_SCALAR | G_EVAL | G_KEEPERR);
596 597
	SPAGAIN;

598 599 600 601 602
	if (count != 1)
	{
		PUTBACK;
		FREETMPS;
		LEAVE;
603
		elog(ERROR, "didn't get a return item from mksafefunc");
604 605
	}

606
	if (SvTRUE(ERRSV))
607
	{
608
		(void) POPs;
609 610 611
		PUTBACK;
		FREETMPS;
		LEAVE;
612 613 614 615
		ereport(ERROR,
				(errcode(ERRCODE_SYNTAX_ERROR),
				 errmsg("creation of Perl function failed: %s",
						strip_trailing_ws(SvPV(ERRSV, PL_na)))));
616 617 618
	}

	/*
619 620
	 * need to make a deep copy of the return. it comes off the stack as a
	 * temporary.
621 622 623
	 */
	subref = newSVsv(POPs);

624 625
	if (!SvROK(subref))
	{
626 627 628
		PUTBACK;
		FREETMPS;
		LEAVE;
629

630 631 632 633
		/*
		 * subref is our responsibility because it is not mortal
		 */
		SvREFCNT_dec(subref);
634
		elog(ERROR, "didn't get a code ref");
635 636 637 638 639
	}

	PUTBACK;
	FREETMPS;
	LEAVE;
640

641 642 643 644
	return subref;
}

/**********************************************************************
645
 * plperl_init_shared_libs()		-
646 647 648 649
 *
 * 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.
650
 *
651 652
 **********************************************************************/

653 654
EXTERN_C void boot_DynaLoader(pTHX_ CV *cv);
EXTERN_C void boot_SPI(pTHX_ CV *cv);
655

656
static void
657
plperl_init_shared_libs(pTHX)
658
{
659 660
	char	   *file = __FILE__;

661
	newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
662
	newXS("SPI::bootstrap", boot_SPI, file);
663 664 665 666
}

/**********************************************************************
 * plperl_call_perl_func()		- calls a perl function through the RV
667
 *	stored in the prodesc structure. massages the input parms properly
668
 **********************************************************************/
B
Bruce Momjian 已提交
669
static SV  *
670
plperl_call_perl_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo)
671 672
{
	dSP;
673 674 675
	SV		   *retval;
	int			i;
	int			count;
676 677 678 679

	ENTER;
	SAVETMPS;

680
	PUSHMARK(SP);
681 682 683

	XPUSHs(sv_2mortal(newSVpv("undef", 0))); /* no trigger data */

684 685
	for (i = 0; i < desc->nargs; i++)
	{
686 687 688
		if (fcinfo->argnull[i])
			XPUSHs(&PL_sv_undef);
		else if (desc->arg_is_rowtype[i])
689
		{
690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705
			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;

706 707
			hashref = plperl_hash_from_tuple(&tmptup, tupdesc);
			XPUSHs(sv_2mortal(hashref));
708 709 710
		}
		else
		{
711 712 713 714 715 716 717 718
			char	   *tmp;

			tmp = DatumGetCString(FunctionCall3(&(desc->arg_out_func[i]),
												fcinfo->arg[i],
									ObjectIdGetDatum(desc->arg_typioparam[i]),
												Int32GetDatum(-1)));
			XPUSHs(sv_2mortal(newSVpv(tmp, 0)));
			pfree(tmp);
719 720 721
		}
	}
	PUTBACK;
722 723 724

	/* Do NOT use G_KEEPERR here */
	count = perl_call_sv(desc->reference, G_SCALAR | G_EVAL);
725 726 727

	SPAGAIN;

728 729 730 731
	if (count != 1)
	{
		PUTBACK;
		FREETMPS;
732
		LEAVE;
733
		elog(ERROR, "didn't get a return item from function");
734 735
	}

736
	if (SvTRUE(ERRSV))
737
	{
738
		(void) POPs;
739 740
		PUTBACK;
		FREETMPS;
741
		LEAVE;
742 743 744 745
		/* 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)))));
746 747 748 749
	}

	retval = newSVsv(POPs);

750 751 752
	PUTBACK;
	FREETMPS;
	LEAVE;
753 754 755 756

	return retval;
}

757
/**********************************************************************
758 759
 * plperl_call_perl_trigger_func()	- calls a perl trigger function
 *	through the RV stored in the prodesc structure.
760 761
 **********************************************************************/
static SV  *
762 763
plperl_call_perl_trigger_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo,
							  SV *td)
764 765 766
{
	dSP;
	SV		   *retval;
767
	Trigger    *tg_trigger;
768 769 770 771 772 773 774
	int			i;
	int			count;

	ENTER;
	SAVETMPS;

	PUSHMARK(sp);
775

776
	XPUSHs(td);
777

778 779 780
	tg_trigger = ((TriggerData *) fcinfo->context)->tg_trigger;
	for (i = 0; i < tg_trigger->tgnargs; i++)
		XPUSHs(sv_2mortal(newSVpv(tg_trigger->tgargs[i], 0)));
781 782
	PUTBACK;

783 784
	/* Do NOT use G_KEEPERR here */
	count = perl_call_sv(desc->reference, G_SCALAR | G_EVAL);
785 786 787 788 789 790 791 792

	SPAGAIN;

	if (count != 1)
	{
		PUTBACK;
		FREETMPS;
		LEAVE;
793
		elog(ERROR, "didn't get a return item from trigger function");
794 795 796 797
	}

	if (SvTRUE(ERRSV))
	{
798
		(void) POPs;
799 800 801
		PUTBACK;
		FREETMPS;
		LEAVE;
802 803 804 805
		/* 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)))));
806 807 808 809 810 811 812 813 814 815
	}

	retval = newSVsv(POPs);

	PUTBACK;
	FREETMPS;
	LEAVE;

	return retval;
}
816

817 818 819 820
/**********************************************************************
 * plperl_func_handler()		- Handler for regular function calls
 **********************************************************************/
static Datum
821
plperl_func_handler(PG_FUNCTION_ARGS)
822 823
{
	plperl_proc_desc *prodesc;
824 825
	SV		   *perlret;
	Datum		retval;
826

827 828 829 830
	/* Connect to SPI manager */
	if (SPI_connect() != SPI_OK_CONNECT)
		elog(ERROR, "could not connect to SPI manager");

831 832
	/* Find or compile the function */
	prodesc = compile_plperl_function(fcinfo->flinfo->fn_oid, false);
833 834 835

	plperl_current_prodesc = prodesc;

836
	/************************************************************
837
	 * Call the Perl function if not returning set
838
	 ************************************************************/
B
Bruce Momjian 已提交
839 840
	if (!prodesc->fn_retisset)
		perlret = plperl_call_perl_func(prodesc, fcinfo);
841 842
	else if (SRF_IS_FIRSTCALL())
		perlret = plperl_call_perl_func(prodesc, fcinfo);
B
Bruce Momjian 已提交
843
	else
844
	{
845 846
		/* Get back the SV stashed on initial call */
		FuncCallContext *funcctx = (FuncCallContext *) fcinfo->flinfo->fn_extra;
847

848
		perlret = (SV *) funcctx->user_fctx;
849
	}
850 851 852 853 854 855 856 857

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

B
Bruce Momjian 已提交
860
	if (!(perlret && SvOK(perlret) && SvTYPE(perlret) != SVt_NULL))
861
	{
862
		/* return NULL if Perl code returned undef */
863 864 865 866 867 868 869
		ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;

		if (perlret)
			SvREFCNT_dec(perlret);
		if (rsi && IsA(rsi, ReturnSetInfo))
			rsi->isDone = ExprEndResult;
		PG_RETURN_NULL();
870
	}
871

872
	if (prodesc->fn_retisset && prodesc->fn_retistuple)
873
	{
874
		/* set of tuples */
875
		AV		   *ret_av;
876 877 878 879
		FuncCallContext *funcctx;
		TupleDesc	tupdesc;
		AttInMetadata *attinmeta;

880
		if (!SvOK(perlret) || SvTYPE(perlret) != SVt_RV || SvTYPE(SvRV(perlret)) != SVt_PVAV)
881 882 883
			ereport(ERROR,
					(errcode(ERRCODE_DATATYPE_MISMATCH),
					 errmsg("set-returning Perl function must return reference to array")));
884 885
		ret_av = (AV *) SvRV(perlret);

886 887 888 889 890 891
		if (SRF_IS_FIRSTCALL())
		{
			MemoryContext oldcontext;

			funcctx = SRF_FIRSTCALL_INIT();

892
			funcctx->user_fctx = (void *) perlret;
893

894
			funcctx->max_calls = av_len(ret_av) + 1;
895

896 897 898 899 900 901
			/* Cache a copy of the result's tupdesc and attinmeta */
			oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
			tupdesc = get_function_tupdesc(prodesc->result_oid,
										(ReturnSetInfo *) fcinfo->resultinfo);
			tupdesc = CreateTupleDescCopy(tupdesc);
			funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
902 903 904 905 906
			MemoryContextSwitchTo(oldcontext);
		}

		funcctx = SRF_PERCALL_SETUP();
		attinmeta = funcctx->attinmeta;
907
		tupdesc = attinmeta->tupdesc;
908

909
		if (funcctx->call_cntr < funcctx->max_calls)
910
		{
911 912
			SV		  **svp;
			HV		   *row_hv;
913 914
			HeapTuple	tuple;

915
			svp = av_fetch(ret_av, funcctx->call_cntr, FALSE);
916
			Assert(svp != NULL);
917

918
			if (!SvOK(*svp) || SvTYPE(*svp) != SVt_RV || SvTYPE(SvRV(*svp)) != SVt_PVHV)
919 920 921
				ereport(ERROR,
						(errcode(ERRCODE_DATATYPE_MISMATCH),
						 errmsg("elements of Perl result array must be reference to hash")));
922
			row_hv = (HV *) SvRV(*svp);
923

924
			tuple = plperl_build_tuple_result(row_hv, attinmeta);
925 926
			retval = HeapTupleGetDatum(tuple);
			SRF_RETURN_NEXT(funcctx, retval);
927 928 929 930 931 932 933
		}
		else
		{
			SvREFCNT_dec(perlret);
			SRF_RETURN_DONE(funcctx);
		}
	}
934
	else if (prodesc->fn_retisset)
935
	{
936
		/* set of non-tuples */
937
		AV		   *ret_av;
B
Bruce Momjian 已提交
938 939
		FuncCallContext *funcctx;

940
		if (!SvOK(perlret) || SvTYPE(perlret) != SVt_RV || SvTYPE(SvRV(perlret)) != SVt_PVAV)
941 942 943
			ereport(ERROR,
					(errcode(ERRCODE_DATATYPE_MISMATCH),
					 errmsg("set-returning Perl function must return reference to array")));
944 945
		ret_av = (AV *) SvRV(perlret);

946 947 948 949
		if (SRF_IS_FIRSTCALL())
		{
			funcctx = SRF_FIRSTCALL_INIT();

950 951 952
			funcctx->user_fctx = (void *) perlret;

			funcctx->max_calls = av_len(ret_av) + 1;
953
		}
B
Bruce Momjian 已提交
954

955
		funcctx = SRF_PERCALL_SETUP();
B
Bruce Momjian 已提交
956

957 958
		if (funcctx->call_cntr < funcctx->max_calls)
		{
B
Bruce Momjian 已提交
959
			SV		  **svp;
960

961
			svp = av_fetch(ret_av, funcctx->call_cntr, FALSE);
962
			Assert(svp != NULL);
963

964
			if (SvOK(*svp) && SvTYPE(*svp) != SVt_NULL)
965
			{
966 967
				char	   *val = SvPV(*svp, PL_na);

968
				fcinfo->isnull = false;
969 970
				retval = FunctionCall3(&prodesc->result_in_func,
									   PointerGetDatum(val),
B
Bruce Momjian 已提交
971 972
							ObjectIdGetDatum(prodesc->result_typioparam),
									   Int32GetDatum(-1));
973
			}
974 975 976
			else
			{
				fcinfo->isnull = true;
977
				retval = (Datum) 0;
978
			}
979
			SRF_RETURN_NEXT(funcctx, retval);
B
Bruce Momjian 已提交
980
		}
981 982
		else
		{
983
			SvREFCNT_dec(perlret);
984 985
			SRF_RETURN_DONE(funcctx);
		}
B
Bruce Momjian 已提交
986
	}
987
	else if (prodesc->fn_retistuple)
988
	{
989
		/* singleton perl hash to Datum */
990
		HV		   *perlhash;
991 992 993 994
		TupleDesc	td;
		AttInMetadata *attinmeta;
		HeapTuple	tup;

995
		if (!SvOK(perlret) || SvTYPE(perlret) != SVt_RV || SvTYPE(SvRV(perlret)) != SVt_PVHV)
996 997 998
			ereport(ERROR,
					(errcode(ERRCODE_DATATYPE_MISMATCH),
					 errmsg("composite-returning Perl function must return reference to hash")));
999 1000
		perlhash = (HV *) SvRV(perlret);

1001
		/*
1002
		 * XXX should cache the attinmeta data instead of recomputing
1003 1004 1005 1006 1007 1008
		 */
		td = get_function_tupdesc(prodesc->result_oid,
								  (ReturnSetInfo *) fcinfo->resultinfo);
		/* td = CreateTupleDescCopy(td); */
		attinmeta = TupleDescGetAttInMetadata(td);

1009
		tup = plperl_build_tuple_result(perlhash, attinmeta);
1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020
		retval = HeapTupleGetDatum(tup);
	}
	else
	{
		/* perl string to Datum */
		char	   *val = SvPV(perlret, PL_na);

		retval = FunctionCall3(&prodesc->result_in_func,
							   CStringGetDatum(val),
							   ObjectIdGetDatum(prodesc->result_typioparam),
							   Int32GetDatum(-1));
1021
	}
1022 1023 1024 1025 1026

	SvREFCNT_dec(perlret);
	return retval;
}

1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038
/**********************************************************************
 * plperl_trigger_handler()		- Handler for trigger function calls
 **********************************************************************/
static Datum
plperl_trigger_handler(PG_FUNCTION_ARGS)
{
	plperl_proc_desc *prodesc;
	SV		   *perlret;
	Datum		retval;
	SV		   *svTD;
	HV		   *hvTD;

1039 1040 1041 1042
	/* Connect to SPI manager */
	if (SPI_connect() != SPI_OK_CONNECT)
		elog(ERROR, "could not connect to SPI manager");

1043 1044 1045
	/* Find or compile the function */
	prodesc = compile_plperl_function(fcinfo->flinfo->fn_oid, true);

1046 1047
	plperl_current_prodesc = prodesc;

1048 1049 1050
	/************************************************************
	* Call the Perl function
	************************************************************/
B
Bruce Momjian 已提交
1051

1052
	/*
B
Bruce Momjian 已提交
1053 1054
	 * call perl trigger function and build TD hash
	 */
1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067
	svTD = plperl_trigger_build_args(fcinfo);
	perlret = plperl_call_perl_trigger_func(prodesc, fcinfo, svTD);

	hvTD = (HV *) SvRV(svTD);	/* convert SV TD structure to Perl Hash
								 * structure */

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

1070
	if (!(perlret && SvOK(perlret) && SvTYPE(perlret) != SVt_NULL))
1071
	{
1072
		/* undef result means go ahead with original tuple */
1073 1074 1075 1076 1077 1078 1079 1080
		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;
1081 1082
		else
			retval = (Datum) 0;	/* can this happen? */
1083 1084 1085
	}
	else
	{
1086 1087
		HeapTuple	trv;
		char	   *tmp;
1088

1089
		tmp = SvPV(perlret, PL_na);
1090

1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102
		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);
1103 1104
			else
			{
1105 1106 1107
				ereport(WARNING,
						(errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
						 errmsg("ignoring modified tuple in DELETE trigger")));
1108 1109 1110
				trv = NULL;
			}
		}
1111
		else
1112
		{
1113 1114 1115
			ereport(ERROR,
					(errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
					 errmsg("result of Perl trigger function must be undef, \"SKIP\" or \"MODIFY\"")));
1116 1117 1118
			trv = NULL;
		}
		retval = PointerGetDatum(trv);
1119 1120
	}

1121 1122 1123
	SvREFCNT_dec(svTD);
	if (perlret)
		SvREFCNT_dec(perlret);
1124 1125 1126

	return retval;
}
1127 1128

/**********************************************************************
1129
 * compile_plperl_function	- compile (or hopefully just look up) function
1130
 **********************************************************************/
1131 1132
static plperl_proc_desc *
compile_plperl_function(Oid fn_oid, bool is_trigger)
1133
{
1134 1135 1136 1137 1138
	HeapTuple	procTup;
	Form_pg_proc procStruct;
	char		internal_proname[64];
	int			proname_len;
	plperl_proc_desc *prodesc = NULL;
1139
	int			i;
1140
	SV			**svp;
1141

1142 1143 1144 1145 1146
	/* We'll need the pg_proc tuple in any case... */
	procTup = SearchSysCache(PROCOID,
							 ObjectIdGetDatum(fn_oid),
							 0, 0, 0);
	if (!HeapTupleIsValid(procTup))
1147
		elog(ERROR, "cache lookup failed for function %u", fn_oid);
1148
	procStruct = (Form_pg_proc) GETSTRUCT(procTup);
1149 1150 1151 1152

	/************************************************************
	 * Build our internal proc name from the functions Oid
	 ************************************************************/
1153 1154 1155 1156
	if (!is_trigger)
		sprintf(internal_proname, "__PLPerl_proc_%u", fn_oid);
	else
		sprintf(internal_proname, "__PLPerl_proc_%u_trigger", fn_oid);
1157

1158
	proname_len = strlen(internal_proname);
1159 1160 1161 1162

	/************************************************************
	 * Lookup the internal proc name in the hashtable
	 ************************************************************/
1163 1164
	svp = hv_fetch(plperl_proc_hash, internal_proname, proname_len, FALSE);
	if (svp)
1165
	{
1166 1167
		bool		uptodate;

1168
		prodesc = (plperl_proc_desc *) SvIV(*svp);
1169

1170
		/************************************************************
1171 1172 1173
		 * 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.
1174
		 ************************************************************/
1175
		uptodate = (prodesc->fn_xmin == HeapTupleHeaderGetXmin(procTup->t_data) &&
B
Bruce Momjian 已提交
1176
			prodesc->fn_cmin == HeapTupleHeaderGetCmin(procTup->t_data));
1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198

		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;
1199 1200
		Datum		prosrcdatum;
		bool		isnull;
1201 1202 1203 1204 1205 1206
		char	   *proc_source;

		/************************************************************
		 * Allocate a new procedure description block
		 ************************************************************/
		prodesc = (plperl_proc_desc *) malloc(sizeof(plperl_proc_desc));
1207
		if (prodesc == NULL)
1208 1209 1210
			ereport(ERROR,
					(errcode(ERRCODE_OUT_OF_MEMORY),
					 errmsg("out of memory")));
1211 1212
		MemSet(prodesc, 0, sizeof(plperl_proc_desc));
		prodesc->proname = strdup(internal_proname);
1213 1214
		prodesc->fn_xmin = HeapTupleHeaderGetXmin(procTup->t_data);
		prodesc->fn_cmin = HeapTupleHeaderGetCmin(procTup->t_data);
1215

1216 1217 1218 1219
		/* Remember if function is STABLE/IMMUTABLE */
		prodesc->fn_readonly =
			(procStruct->provolatile != PROVOLATILE_VOLATILE);

1220
		/************************************************************
1221
		 * Lookup the pg_language tuple by Oid
1222
		 ************************************************************/
1223 1224
		langTup = SearchSysCache(LANGOID,
								 ObjectIdGetDatum(procStruct->prolang),
1225
								 0, 0, 0);
1226
		if (!HeapTupleIsValid(langTup))
1227 1228 1229
		{
			free(prodesc->proname);
			free(prodesc);
1230
			elog(ERROR, "cache lookup failed for language %u",
1231
				 procStruct->prolang);
1232
		}
1233 1234 1235
		langStruct = (Form_pg_language) GETSTRUCT(langTup);
		prodesc->lanpltrusted = langStruct->lanpltrusted;
		ReleaseSysCache(langTup);
1236 1237

		/************************************************************
1238 1239
		 * Get the required information for input conversion of the
		 * return value.
1240
		 ************************************************************/
1241 1242 1243
		if (!is_trigger)
		{
			typeTup = SearchSysCache(TYPEOID,
1244
								ObjectIdGetDatum(procStruct->prorettype),
1245 1246 1247 1248 1249
									 0, 0, 0);
			if (!HeapTupleIsValid(typeTup))
			{
				free(prodesc->proname);
				free(prodesc);
1250
				elog(ERROR, "cache lookup failed for type %u",
1251
					 procStruct->prorettype);
1252 1253 1254
			}
			typeStruct = (Form_pg_type) GETSTRUCT(typeTup);

1255
			/* Disallow pseudotype result, except VOID or RECORD */
1256 1257
			if (typeStruct->typtype == 'p')
			{
1258 1259
				if (procStruct->prorettype == VOIDOID ||
					procStruct->prorettype == RECORDOID)
B
Bruce Momjian 已提交
1260
					 /* okay */ ;
1261
				else if (procStruct->prorettype == TRIGGEROID)
1262 1263 1264
				{
					free(prodesc->proname);
					free(prodesc);
1265 1266 1267
					ereport(ERROR,
							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
							 errmsg("trigger functions may only be called as triggers")));
1268 1269 1270 1271 1272
				}
				else
				{
					free(prodesc->proname);
					free(prodesc);
1273 1274
					ereport(ERROR,
							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
B
Bruce Momjian 已提交
1275 1276
						 errmsg("plperl functions cannot return type %s",
								format_type_be(procStruct->prorettype))));
1277 1278 1279
				}
			}

1280 1281 1282 1283
			prodesc->result_oid = procStruct->prorettype;
			prodesc->fn_retisset = procStruct->proretset;
			prodesc->fn_retistuple = (typeStruct->typtype == 'c' ||
									  procStruct->prorettype == RECORDOID);
1284 1285

			perm_fmgr_info(typeStruct->typinput, &(prodesc->result_in_func));
1286
			prodesc->result_typioparam = getTypeIOParam(typeTup);
1287 1288 1289

			ReleaseSysCache(typeTup);
		}
1290 1291

		/************************************************************
1292 1293
		 * Get the required information for output conversion
		 * of all procedure arguments
1294
		 ************************************************************/
1295 1296 1297 1298 1299 1300
		if (!is_trigger)
		{
			prodesc->nargs = procStruct->pronargs;
			for (i = 0; i < prodesc->nargs; i++)
			{
				typeTup = SearchSysCache(TYPEOID,
1301
							ObjectIdGetDatum(procStruct->proargtypes[i]),
1302 1303 1304 1305 1306
										 0, 0, 0);
				if (!HeapTupleIsValid(typeTup))
				{
					free(prodesc->proname);
					free(prodesc);
1307
					elog(ERROR, "cache lookup failed for type %u",
1308
						 procStruct->proargtypes[i]);
1309 1310 1311
				}
				typeStruct = (Form_pg_type) GETSTRUCT(typeTup);

1312 1313 1314 1315 1316
				/* Disallow pseudotype argument */
				if (typeStruct->typtype == 'p')
				{
					free(prodesc->proname);
					free(prodesc);
1317 1318
					ereport(ERROR,
							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
B
Bruce Momjian 已提交
1319 1320
						   errmsg("plperl functions cannot take type %s",
						   format_type_be(procStruct->proargtypes[i]))));
1321 1322
				}

1323 1324
				if (typeStruct->typtype == 'c')
					prodesc->arg_is_rowtype[i] = true;
1325
				else
1326 1327 1328 1329
				{
					prodesc->arg_is_rowtype[i] = false;
					perm_fmgr_info(typeStruct->typoutput,
								   &(prodesc->arg_out_func[i]));
1330
					prodesc->arg_typioparam[i] = getTypeIOParam(typeTup);
1331
				}
1332 1333 1334 1335

				ReleaseSysCache(typeTup);
			}
		}
1336

1337 1338 1339 1340 1341
		/************************************************************
		 * create the text of the anonymous subroutine.
		 * we do not use a named subroutine so that we can call directly
		 * through the reference.
		 ************************************************************/
1342 1343 1344 1345
		prosrcdatum = SysCacheGetAttr(PROCOID, procTup,
									  Anum_pg_proc_prosrc, &isnull);
		if (isnull)
			elog(ERROR, "null prosrc");
1346
		proc_source = DatumGetCString(DirectFunctionCall1(textout,
1347
														  prosrcdatum));
1348 1349

		/************************************************************
1350
		 * Create the procedure in the interpreter
1351
		 ************************************************************/
1352 1353
		prodesc->reference = plperl_create_sub(proc_source, prodesc->lanpltrusted);
		pfree(proc_source);
1354
		if (!prodesc->reference) /* can this happen? */
1355 1356 1357
		{
			free(prodesc->proname);
			free(prodesc);
1358
			elog(ERROR, "could not create internal procedure \"%s\"",
1359
				 internal_proname);
1360 1361 1362 1363 1364
		}

		/************************************************************
		 * Add the proc description block to the hashtable
		 ************************************************************/
1365 1366
		hv_store(plperl_proc_hash, internal_proname, proname_len,
				 newSViv((IV) prodesc), 0);
1367 1368
	}

1369
	ReleaseSysCache(procTup);
1370

1371 1372
	return prodesc;
}
1373 1374 1375


/**********************************************************************
1376
 * plperl_hash_from_tuple() - Build a ref to a hash
1377 1378
 *				  from all attributes of a given tuple
 **********************************************************************/
B
Bruce Momjian 已提交
1379
static SV  *
1380
plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc)
1381
{
1382
	HV		   *hv;
1383
	int			i;
1384

1385
	hv = newHV();
1386 1387 1388

	for (i = 0; i < tupdesc->natts; i++)
	{
1389 1390 1391 1392 1393 1394 1395 1396 1397
		Datum		attr;
		bool		isnull;
		char	   *attname;
		char	   *outputstr;
		Oid			typoutput;
		Oid			typioparam;
		bool		typisvarlena;
		int			namelen;

1398 1399 1400
		if (tupdesc->attrs[i]->attisdropped)
			continue;

1401
		attname = NameStr(tupdesc->attrs[i]->attname);
1402
		namelen = strlen(attname);
1403 1404
		attr = heap_getattr(tuple, i + 1, tupdesc, &isnull);

1405 1406 1407
		if (isnull) {
			/* Store (attname => undef) and move on. */
			hv_store(hv, attname, namelen, newSV(0), 0);
1408 1409 1410
			continue;
		}

1411
		/* XXX should have a way to cache these lookups */
1412

1413 1414
		getTypeOutputInfo(tupdesc->attrs[i]->atttypid,
						  &typoutput, &typioparam, &typisvarlena);
1415

1416 1417
		outputstr = DatumGetCString(OidFunctionCall3(typoutput,
													 attr,
B
Bruce Momjian 已提交
1418
											ObjectIdGetDatum(typioparam),
1419
						   Int32GetDatum(tupdesc->attrs[i]->atttypmod)));
1420 1421

		hv_store(hv, attname, namelen, newSVpv(outputstr, 0), 0);
1422
	}
1423

1424
	return newRV_noinc((SV *) hv);
1425
}
1426 1427


1428 1429 1430
/*
 * Implementation of spi_exec_query() Perl function
 */
1431 1432 1433 1434 1435
HV *
plperl_spi_exec(char *query, int limit)
{
	HV		   *ret_hv;

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 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493
	/*
	 * 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();
1494 1495 1496 1497 1498

	return ret_hv;
}

static HV  *
1499 1500
plperl_spi_execute_fetch_result(SPITupleTable *tuptable, int processed,
								int status)
1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512
{
	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)
	{
1513
		AV		   *rows;
1514
		SV		   *row;
1515
		int			i;
1516

1517 1518 1519 1520
		rows = newAV();
		for (i = 0; i < processed; i++)
		{
			row = plperl_hash_from_tuple(tuptable->vals[i], tuptable->tupdesc);
1521
			av_push(rows, row);
1522
		}
1523 1524
		hv_store(result, "rows", strlen("rows"),
				 newRV_noinc((SV *) rows), 0);
1525 1526 1527 1528 1529 1530
	}

	SPI_freetuptable(tuptable);

	return result;
}