plperl.c 41.4 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.68 2005/02/22 04:42:44 momjian Exp $
37
 *
38 39
 **********************************************************************/

40
#include "postgres.h"
41 42
/* Defined by Perl */
#undef _(x)
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/typcache.h"
55 56

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

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

68 69 70 71 72 73 74

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


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

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

103 104 105 106
/**********************************************************************
 * Forward declarations
 **********************************************************************/
static void plperl_init_all(void);
107
static void plperl_init_interp(void);
108

B
Bruce Momjian 已提交
109
Datum		plperl_call_handler(PG_FUNCTION_ARGS);
110
void		plperl_init(void);
111

112 113
HV		   *plperl_spi_exec(char *query, int limit);

114
static Datum plperl_func_handler(PG_FUNCTION_ARGS);
115

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

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


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

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

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

	plperl_firstcall = 0;
}

165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
/**********************************************************************
 * 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
	 ************************************************************/

}

185 186

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

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

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

207 208 209
	perl_construct(plperl_interp);
	perl_parse(plperl_interp, plperl_init_shared_libs, 3, embedding, NULL);
	perl_run(plperl_interp);
210 211

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

217 218 219 220

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

B
Bruce Momjian 已提交
224 225
	static char *safe_ok =
	"use vars qw($PLContainer); $PLContainer = new Safe('PLPerl');"
226 227 228 229
	"$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 已提交
230 231
	"sub ::mksafefunc { return $PLContainer->reval(qq[sub { $_[0] $_[1]}]); }"
			   ;
232

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

B
Bruce Momjian 已提交
242
	SV		   *res;
243
	double		safe_version;
244

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

	safe_version = SvNV(res);

249 250 251 252 253 254
	/*
	 * 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);
255 256 257 258

	plperl_safe_init_done = true;
}

259

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


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

288
	values = (char **) palloc0(td->natts * sizeof(char *));
289

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

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

	tup = BuildTupleFromCStrings(attinmeta, values);
	pfree(values);
	return tup;
308 309
}

310

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

326
	hv = newHV();
327 328 329 330

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

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

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

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

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

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

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

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

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

402
	return newRV_noinc((SV*)hv);
403 404 405
}


406 407 408 409 410 411 412 413 414 415 416 417 418 419
/*
 * 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,
420 421 422
					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
					 errmsg("function returning record called in context "
							"that cannot accept type record")));
423 424 425 426 427 428
		return rsinfo->expectedDesc;
	}
	else				/* ordinary composite type */
		return lookup_rowtype_tupdesc(result_type, -1);
}

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

446 447 448 449 450
	TupleDesc	tupdesc;

	tupdesc = tdata->tg_relation->rd_att;

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

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

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

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

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

	pfree(modattrs);
	pfree(modvalues);
	pfree(modnulls);
508

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

	return rtup;
}
515 516 517 518 519 520 521 522

/**********************************************************************
 * 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.
 **********************************************************************/
523
PG_FUNCTION_INFO_V1(plperl_call_handler);
524 525 526

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

532 533 534
	/*
	 * Initialize interpreter if first time through
	 */
535
	plperl_init_all();
536

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

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

	return retval;
}


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

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

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

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

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

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

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

626 627
	if (!SvROK(subref))
	{
628 629 630
		PUTBACK;
		FREETMPS;
		LEAVE;
631

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

	PUTBACK;
	FREETMPS;
	LEAVE;
642

643 644 645 646
	return subref;
}

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

655 656
EXTERN_C void boot_DynaLoader(pTHX_ CV *cv);
EXTERN_C void boot_SPI(pTHX_ CV *cv);
657

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

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

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

	ENTER;
	SAVETMPS;

682
	PUSHMARK(SP);
683 684 685

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

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

708 709
			hashref = plperl_hash_from_tuple(&tmptup, tupdesc);
			XPUSHs(sv_2mortal(hashref));
710 711 712
		}
		else
		{
713 714 715 716 717 718 719 720
			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);
721 722 723
		}
	}
	PUTBACK;
724 725 726

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

	SPAGAIN;

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

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

	retval = newSVsv(POPs);

752 753 754
	PUTBACK;
	FREETMPS;
	LEAVE;
755 756 757 758

	return retval;
}

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

	ENTER;
	SAVETMPS;

	PUSHMARK(sp);
777

778
	XPUSHs(td);
779

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

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

	SPAGAIN;

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

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

	retval = newSVsv(POPs);

	PUTBACK;
	FREETMPS;
	LEAVE;

	return retval;
}
818

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

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

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

	plperl_current_prodesc = prodesc;

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

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

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

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

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

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

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

888 889 890 891 892 893
		if (SRF_IS_FIRSTCALL())
		{
			MemoryContext oldcontext;

			funcctx = SRF_FIRSTCALL_INIT();

894
			funcctx->user_fctx = (void *) perlret;
895

896
			funcctx->max_calls = av_len(ret_av) + 1;
897

898 899 900 901 902 903
			/* 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);
904 905 906 907 908
			MemoryContextSwitchTo(oldcontext);
		}

		funcctx = SRF_PERCALL_SETUP();
		attinmeta = funcctx->attinmeta;
909
		tupdesc = attinmeta->tupdesc;
910

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

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

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

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

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

948 949 950 951
		if (SRF_IS_FIRSTCALL())
		{
			funcctx = SRF_FIRSTCALL_INIT();

952 953 954
			funcctx->user_fctx = (void *) perlret;

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

957
		funcctx = SRF_PERCALL_SETUP();
B
Bruce Momjian 已提交
958

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

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

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

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

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

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

1011
		tup = plperl_build_tuple_result(perlhash, attinmeta);
1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022
		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));
1023
	}
1024 1025 1026 1027 1028

	SvREFCNT_dec(perlret);
	return retval;
}

1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040
/**********************************************************************
 * 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;

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

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

1048 1049
	plperl_current_prodesc = prodesc;

1050 1051 1052
	/************************************************************
	* Call the Perl function
	************************************************************/
B
Bruce Momjian 已提交
1053

1054
	/*
B
Bruce Momjian 已提交
1055 1056
	 * call perl trigger function and build TD hash
	 */
1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069
	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)
1070
		elog(ERROR, "SPI_finish() failed");
1071

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

1091
		tmp = SvPV(perlret, PL_na);
1092

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

1123 1124 1125
	SvREFCNT_dec(svTD);
	if (perlret)
		SvREFCNT_dec(perlret);
1126 1127 1128

	return retval;
}
1129 1130

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

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

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

1160
	proname_len = strlen(internal_proname);
1161 1162 1163 1164

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

1170
		prodesc = (plperl_proc_desc *) SvIV(*svp);
1171

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

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

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

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

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

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

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

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

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

			ReleaseSysCache(typeTup);
		}
1292 1293

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

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

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

				ReleaseSysCache(typeTup);
			}
		}
1338

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

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

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

1371
	ReleaseSysCache(procTup);
1372

1373 1374
	return prodesc;
}
1375 1376 1377


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

1387
	hv = newHV();
1388 1389 1390

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

1400 1401 1402
		if (tupdesc->attrs[i]->attisdropped)
			continue;

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

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

1413
		/* XXX should have a way to cache these lookups */
1414

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

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

		hv_store(hv, attname, namelen, newSVpv(outputstr, 0), 0);
1424
	}
1425

1426
	return newRV_noinc((SV *) hv);
1427
}
1428 1429


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

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 1494 1495
	/*
	 * 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();
1496 1497 1498 1499 1500

	return ret_hv;
}

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

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

	SPI_freetuptable(tuptable);

	return result;
}