plperl.c 38.5 KB
Newer Older
1 2 3 4 5 6
/**********************************************************************
 * plperl.c - perl as a procedural language for PostgreSQL
 *
 * IDENTIFICATION
 *
 *	  This software is copyrighted by Mark Hollomon
7
 *	  but is shameless cribbed from pltcl.c by Jan Wieck.
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
 *
 *	  The author hereby grants permission  to  use,  copy,	modify,
 *	  distribute,  and	license this software and its documentation
 *	  for any purpose, provided that existing copyright notices are
 *	  retained	in	all  copies  and  that	this notice is included
 *	  verbatim in any distributions. No written agreement, license,
 *	  or  royalty  fee	is required for any of the authorized uses.
 *	  Modifications to this software may be  copyrighted  by  their
 *	  author  and  need  not  follow  the licensing terms described
 *	  here, provided that the new terms are  clearly  indicated  on
 *	  the first page of each file where they apply.
 *
 *	  IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
 *	  PARTY  FOR  DIRECT,	INDIRECT,	SPECIAL,   INCIDENTAL,	 OR
 *	  CONSEQUENTIAL   DAMAGES  ARISING	OUT  OF  THE  USE  OF  THIS
 *	  SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
 *	  IF  THE  AUTHOR  HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
 *	  DAMAGE.
 *
 *	  THE  AUTHOR  AND	DISTRIBUTORS  SPECIFICALLY	 DISCLAIM	ANY
 *	  WARRANTIES,  INCLUDING,  BUT	NOT  LIMITED  TO,  THE	IMPLIED
 *	  WARRANTIES  OF  MERCHANTABILITY,	FITNESS  FOR  A  PARTICULAR
 *	  PURPOSE,	AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON
 *	  AN "AS IS" BASIS, AND THE AUTHOR	AND  DISTRIBUTORS  HAVE  NO
 *	  OBLIGATION   TO	PROVIDE   MAINTENANCE,	 SUPPORT,  UPDATES,
 *	  ENHANCEMENTS, OR MODIFICATIONS.
 *
35
 * IDENTIFICATION
36
 *	  $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.78 2005/06/22 16:45:51 tgl Exp $
37
 *
38 39
 **********************************************************************/

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

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

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

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

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

71 72 73 74 75 76 77

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


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

105 106
static bool plperl_use_strict = false;

107 108 109
/* this is saved and restored by plperl_call_handler */
static plperl_proc_desc *plperl_current_prodesc = NULL;

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

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

120 121
HV		   *plperl_spi_exec(char *query, int limit);

122
static Datum plperl_func_handler(PG_FUNCTION_ARGS);
123

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

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

131
void plperl_return_next(SV *);
132

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

150 151 152

/* Perform initialization during postmaster startup. */

153 154
void
plperl_init(void)
155 156 157 158
{
	if (!plperl_firstcall)
		return;

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

	EmitWarningsOnPlaceholders("plperl");
168

169
	plperl_init_interp();
170 171 172
	plperl_firstcall = 0;
}

173 174 175

/* Perform initialization during backend startup. */

176 177 178 179 180 181
static void
plperl_init_all(void)
{
	if (plperl_firstcall)
		plperl_init();

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

185 186

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

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

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

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

213
	plperl_proc_hash = newHV();
214 215
}

216 217 218 219

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

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

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

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

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

B
Bruce Momjian 已提交
252
	SV		   *res;
253
	double		safe_version;
254

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

	safe_version = SvNV(res);

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

	plperl_safe_init_done = true;
}

278

279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
/*
 * 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;
}


294 295
/* Build a tuple from a hash. */

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

306
	values = (char **) palloc0(td->natts * sizeof(char *));
307

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

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

	tup = BuildTupleFromCStrings(attinmeta, values);
	pfree(values);
	return tup;
326 327
}

328

329 330
/* Set up the arguments for a trigger call. */

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

343
	hv = newHV();
344 345 346 347

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

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

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

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

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

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

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

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

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

419
	return newRV_noinc((SV*)hv);
420 421 422
}


423
/* Set up the new tuple returned from a trigger. */
424

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

439 440 441 442 443
	TupleDesc	tupdesc;

	tupdesc = tdata->tg_relation->rd_att;

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

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

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

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

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

	pfree(modattrs);
	pfree(modvalues);
	pfree(modnulls);
501

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

	return rtup;
}
508

509

510 511
/*
 * This is the only externally-visible part of the plperl call interface.
512
 * The Postgres function and trigger managers call it to execute a
513 514
 * perl function.
 */
515
PG_FUNCTION_INFO_V1(plperl_call_handler);
516 517

Datum
518
plperl_call_handler(PG_FUNCTION_ARGS)
519
{
520
	Datum retval;
521
	plperl_proc_desc *save_prodesc;
522

523
	plperl_init_all();
524

525
	save_prodesc = plperl_current_prodesc;
526

527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
	PG_TRY();
	{
		if (CALLED_AS_TRIGGER(fcinfo))
			retval = PointerGetDatum(plperl_trigger_handler(fcinfo));
		else
			retval = plperl_func_handler(fcinfo);
	}
	PG_CATCH();
	{
		plperl_current_prodesc = save_prodesc;
		PG_RE_THROW();
	}
	PG_END_TRY();

	plperl_current_prodesc = save_prodesc;
542 543 544 545

	return retval;
}

546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583
/*
 * This is the other externally visible function - it is called when CREATE
 * FUNCTION is issued to validate the function being created/replaced.
 */
PG_FUNCTION_INFO_V1(plperl_validator);

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

	plperl_init_all();

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

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

	ReleaseSysCache(tuple);

	prodesc = compile_plperl_function(funcoid, istrigger);

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

584

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

B
Bruce Momjian 已提交
588
static SV  *
589
plperl_create_sub(char *s, bool trusted)
590
{
591
	dSP;
592
	SV		   *subref;
B
Bruce Momjian 已提交
593
	int			count;
594

B
Bruce Momjian 已提交
595
	if (trusted && !plperl_safe_init_done)
596
	{
597
		plperl_safe_init();
598 599
		SPAGAIN;
	}
600

601 602 603
	ENTER;
	SAVETMPS;
	PUSHMARK(SP);
604
	XPUSHs(sv_2mortal(newSVpv("my $_TD=$_[0]; shift;", 0)));
B
Bruce Momjian 已提交
605
	XPUSHs(sv_2mortal(newSVpv(s, 0)));
B
Bruce Momjian 已提交
606
	PUTBACK;
B
Bruce Momjian 已提交
607

608 609
	/*
	 * G_KEEPERR seems to be needed here, else we don't recognize compile
B
Bruce Momjian 已提交
610 611
	 * errors properly.  Perhaps it's because there's another level of
	 * eval inside mksafefunc?
612
	 */
613 614
	count = perl_call_pv((trusted ? "mksafefunc" : "mkunsafefunc"),
						 G_SCALAR | G_EVAL | G_KEEPERR);
615 616
	SPAGAIN;

617 618 619 620 621
	if (count != 1)
	{
		PUTBACK;
		FREETMPS;
		LEAVE;
622
		elog(ERROR, "didn't get a return item from mksafefunc");
623 624
	}

625
	if (SvTRUE(ERRSV))
626
	{
627
		(void) POPs;
628 629 630
		PUTBACK;
		FREETMPS;
		LEAVE;
631 632 633 634
		ereport(ERROR,
				(errcode(ERRCODE_SYNTAX_ERROR),
				 errmsg("creation of Perl function failed: %s",
						strip_trailing_ws(SvPV(ERRSV, PL_na)))));
635 636 637
	}

	/*
638 639
	 * need to make a deep copy of the return. it comes off the stack as a
	 * temporary.
640 641 642
	 */
	subref = newSVsv(POPs);

643
	if (!SvROK(subref) || SvTYPE(SvRV(subref)) != SVt_PVCV)
644
	{
645 646 647
		PUTBACK;
		FREETMPS;
		LEAVE;
648

649 650 651 652
		/*
		 * subref is our responsibility because it is not mortal
		 */
		SvREFCNT_dec(subref);
653
		elog(ERROR, "didn't get a code ref");
654 655 656 657 658
	}

	PUTBACK;
	FREETMPS;
	LEAVE;
659

660 661 662
	return subref;
}

663

664
/**********************************************************************
665
 * plperl_init_shared_libs()		-
666 667 668 669
 *
 * 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.
670
 *
671 672
 **********************************************************************/

673 674
EXTERN_C void boot_DynaLoader(pTHX_ CV *cv);
EXTERN_C void boot_SPI(pTHX_ CV *cv);
675

676
static void
677
plperl_init_shared_libs(pTHX)
678
{
679 680
	char	   *file = __FILE__;

681
	newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
682
	newXS("SPI::bootstrap", boot_SPI, file);
683 684
}

685

B
Bruce Momjian 已提交
686
static SV  *
687
plperl_call_perl_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo)
688 689
{
	dSP;
690 691 692
	SV		   *retval;
	int			i;
	int			count;
693
	SV			*sv;
694 695 696 697

	ENTER;
	SAVETMPS;

698
	PUSHMARK(SP);
699

700
	XPUSHs(&PL_sv_undef); /* no trigger data */
701

702 703
	for (i = 0; i < desc->nargs; i++)
	{
704 705 706
		if (fcinfo->argnull[i])
			XPUSHs(&PL_sv_undef);
		else if (desc->arg_is_rowtype[i])
707
		{
708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723
			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;

724 725
			hashref = plperl_hash_from_tuple(&tmptup, tupdesc);
			XPUSHs(sv_2mortal(hashref));
726 727 728
		}
		else
		{
729 730
			char	   *tmp;

731 732
			tmp = DatumGetCString(FunctionCall1(&(desc->arg_out_func[i]),
												fcinfo->arg[i]));
733 734 735 736 737
			sv = newSVpv(tmp, 0);
#if PERL_BCDVERSION >= 0x5006000L
			if (GetDatabaseEncoding() == PG_UTF8) SvUTF8_on(sv);
#endif
			XPUSHs(sv_2mortal(sv));
738
			pfree(tmp);
739 740 741
		}
	}
	PUTBACK;
742 743 744

	/* Do NOT use G_KEEPERR here */
	count = perl_call_sv(desc->reference, G_SCALAR | G_EVAL);
745 746 747

	SPAGAIN;

748 749 750 751
	if (count != 1)
	{
		PUTBACK;
		FREETMPS;
752
		LEAVE;
753
		elog(ERROR, "didn't get a return item from function");
754 755
	}

756
	if (SvTRUE(ERRSV))
757
	{
758
		(void) POPs;
759 760
		PUTBACK;
		FREETMPS;
761
		LEAVE;
762 763 764 765
		/* 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)))));
766 767 768 769
	}

	retval = newSVsv(POPs);

770 771 772
	PUTBACK;
	FREETMPS;
	LEAVE;
773 774 775 776

	return retval;
}

777

778
static SV  *
779 780
plperl_call_perl_trigger_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo,
							  SV *td)
781 782 783
{
	dSP;
	SV		   *retval;
784
	Trigger    *tg_trigger;
785 786 787 788 789 790 791
	int			i;
	int			count;

	ENTER;
	SAVETMPS;

	PUSHMARK(sp);
792

793
	XPUSHs(td);
794

795 796 797
	tg_trigger = ((TriggerData *) fcinfo->context)->tg_trigger;
	for (i = 0; i < tg_trigger->tgnargs; i++)
		XPUSHs(sv_2mortal(newSVpv(tg_trigger->tgargs[i], 0)));
798 799
	PUTBACK;

800 801
	/* Do NOT use G_KEEPERR here */
	count = perl_call_sv(desc->reference, G_SCALAR | G_EVAL);
802 803 804 805 806 807 808 809

	SPAGAIN;

	if (count != 1)
	{
		PUTBACK;
		FREETMPS;
		LEAVE;
810
		elog(ERROR, "didn't get a return item from trigger function");
811 812 813 814
	}

	if (SvTRUE(ERRSV))
	{
815
		(void) POPs;
816 817 818
		PUTBACK;
		FREETMPS;
		LEAVE;
819 820 821 822
		/* 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)))));
823 824 825 826 827 828 829 830 831 832
	}

	retval = newSVsv(POPs);

	PUTBACK;
	FREETMPS;
	LEAVE;

	return retval;
}
833

834

835
static Datum
836
plperl_func_handler(PG_FUNCTION_ARGS)
837 838
{
	plperl_proc_desc *prodesc;
839 840
	SV		   *perlret;
	Datum		retval;
841
	ReturnSetInfo *rsi;
842

843 844 845
	if (SPI_connect() != SPI_OK_CONNECT)
		elog(ERROR, "could not connect to SPI manager");

846
	prodesc = compile_plperl_function(fcinfo->flinfo->fn_oid, false);
847 848

	plperl_current_prodesc = prodesc;
849 850 851
	prodesc->caller_info = fcinfo;
	prodesc->tuple_store = 0;
	prodesc->tuple_desc = 0;
852

853
	perlret = plperl_call_perl_func(prodesc, fcinfo);
854 855 856 857 858 859 860 861

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

864
	rsi = (ReturnSetInfo *)fcinfo->resultinfo;
865

866 867 868 869
	if (prodesc->fn_retisset) {
		if (!rsi || !IsA(rsi, ReturnSetInfo) ||
			(rsi->allowedModes & SFRM_Materialize) == 0 ||
			rsi->expectedDesc == NULL)
870
		{
871 872 873 874
			ereport(ERROR,
					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
					 errmsg("set-valued function called in context that "
							"cannot accept a set")));
875 876
		}

877 878 879 880 881 882
		/* If the Perl function returned an arrayref, we pretend that it
		 * called return_next() for each element of the array, to handle
		 * old SRFs that didn't know about return_next(). Any other sort
		 * of return value is an error. */
		if (SvTYPE(perlret) == SVt_RV &&
			SvTYPE(SvRV(perlret)) == SVt_PVAV)
883
		{
884 885 886 887 888 889 890
			int i = 0;
			SV **svp = 0;
			AV *rav = (AV *)SvRV(perlret);
			while ((svp = av_fetch(rav, i, FALSE)) != NULL) {
				plperl_return_next(*svp);
				i++;
			}
891
		}
892
		else if (SvTYPE(perlret) != SVt_NULL)
893
		{
894 895
			ereport(ERROR,
					(errcode(ERRCODE_DATATYPE_MISMATCH),
896 897
					 errmsg("set-returning Perl function must return "
							"reference to array or use return_next")));
898
		}
B
Bruce Momjian 已提交
899

900 901 902 903
		rsi->returnMode = SFRM_Materialize;
		if (prodesc->tuple_store) {
			rsi->setResult = prodesc->tuple_store;
			rsi->setDesc = prodesc->tuple_desc;
904
		}
905 906 907 908 909 910 911 912 913
		retval = (Datum)0;
	}
	else if (SvTYPE(perlret) == SVt_NULL)
	{
		/* Return NULL if Perl code returned undef */
		if (rsi && IsA(rsi, ReturnSetInfo))
			rsi->isDone = ExprEndResult;
		fcinfo->isnull = true;
		retval = (Datum)0;
B
Bruce Momjian 已提交
914
	}
915
	else if (prodesc->fn_retistuple)
916
	{
917 918
		/* Return a perl hash converted to a Datum */
		TupleDesc td;
919
		AttInMetadata *attinmeta;
920
		HeapTuple tup;
921

922 923 924
		if (!SvOK(perlret) || SvTYPE(perlret) != SVt_RV ||
			SvTYPE(SvRV(perlret)) != SVt_PVHV)
		{
925 926
			ereport(ERROR,
					(errcode(ERRCODE_DATATYPE_MISMATCH),
927 928 929
					 errmsg("composite-returning Perl function "
							"must return reference to hash")));
		}
930

931 932 933 934 935 936 937 938
		/* XXX should cache the attinmeta data instead of recomputing */
		if (get_call_result_type(fcinfo, NULL, &td) != TYPEFUNC_COMPOSITE)
		{
			ereport(ERROR,
					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
					 errmsg("function returning record called in context "
							"that cannot accept type record")));
		}
939

940 941
		attinmeta = TupleDescGetAttInMetadata(td);
		tup = plperl_build_tuple_result((HV *)SvRV(perlret), attinmeta);
942 943 944 945
		retval = HeapTupleGetDatum(tup);
	}
	else
	{
946 947
		/* Return a perl string converted to a Datum */
		char *val = SvPV(perlret, PL_na);
948 949 950 951
		retval = FunctionCall3(&prodesc->result_in_func,
							   CStringGetDatum(val),
							   ObjectIdGetDatum(prodesc->result_typioparam),
							   Int32GetDatum(-1));
952
	}
953 954 955 956 957

	SvREFCNT_dec(perlret);
	return retval;
}

958

959 960 961 962 963 964 965 966 967
static Datum
plperl_trigger_handler(PG_FUNCTION_ARGS)
{
	plperl_proc_desc *prodesc;
	SV		   *perlret;
	Datum		retval;
	SV		   *svTD;
	HV		   *hvTD;

968 969 970 971
	/* Connect to SPI manager */
	if (SPI_connect() != SPI_OK_CONNECT)
		elog(ERROR, "could not connect to SPI manager");

972 973 974
	/* Find or compile the function */
	prodesc = compile_plperl_function(fcinfo->flinfo->fn_oid, true);

975 976
	plperl_current_prodesc = prodesc;

977 978
	svTD = plperl_trigger_build_args(fcinfo);
	perlret = plperl_call_perl_trigger_func(prodesc, fcinfo, svTD);
979
	hvTD = (HV *) SvRV(svTD);
980 981 982 983 984 985 986 987

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

990
	if (!(perlret && SvOK(perlret) && SvTYPE(perlret) != SVt_NULL))
991
	{
992
		/* undef result means go ahead with original tuple */
993 994 995 996 997 998 999 1000
		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;
1001 1002
		else
			retval = (Datum) 0;	/* can this happen? */
1003 1004 1005
	}
	else
	{
1006 1007
		HeapTuple	trv;
		char	   *tmp;
1008

1009
		tmp = SvPV(perlret, PL_na);
1010

1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022
		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);
1023 1024
			else
			{
1025 1026 1027
				ereport(WARNING,
						(errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
						 errmsg("ignoring modified tuple in DELETE trigger")));
1028 1029 1030
				trv = NULL;
			}
		}
1031
		else
1032
		{
1033 1034
			ereport(ERROR,
					(errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
1035 1036
					 errmsg("result of Perl trigger function must be undef, "
							"\"SKIP\" or \"MODIFY\"")));
1037 1038 1039
			trv = NULL;
		}
		retval = PointerGetDatum(trv);
1040 1041
	}

1042 1043 1044
	SvREFCNT_dec(svTD);
	if (perlret)
		SvREFCNT_dec(perlret);
1045 1046 1047

	return retval;
}
1048

1049

1050 1051
static plperl_proc_desc *
compile_plperl_function(Oid fn_oid, bool is_trigger)
1052
{
1053 1054 1055 1056 1057
	HeapTuple	procTup;
	Form_pg_proc procStruct;
	char		internal_proname[64];
	int			proname_len;
	plperl_proc_desc *prodesc = NULL;
1058
	int			i;
1059
	SV			**svp;
1060

1061 1062 1063 1064 1065
	/* We'll need the pg_proc tuple in any case... */
	procTup = SearchSysCache(PROCOID,
							 ObjectIdGetDatum(fn_oid),
							 0, 0, 0);
	if (!HeapTupleIsValid(procTup))
1066
		elog(ERROR, "cache lookup failed for function %u", fn_oid);
1067
	procStruct = (Form_pg_proc) GETSTRUCT(procTup);
1068 1069 1070 1071

	/************************************************************
	 * Build our internal proc name from the functions Oid
	 ************************************************************/
1072 1073 1074 1075
	if (!is_trigger)
		sprintf(internal_proname, "__PLPerl_proc_%u", fn_oid);
	else
		sprintf(internal_proname, "__PLPerl_proc_%u_trigger", fn_oid);
1076

1077
	proname_len = strlen(internal_proname);
1078 1079 1080 1081

	/************************************************************
	 * Lookup the internal proc name in the hashtable
	 ************************************************************/
1082 1083
	svp = hv_fetch(plperl_proc_hash, internal_proname, proname_len, FALSE);
	if (svp)
1084
	{
1085 1086
		bool		uptodate;

1087
		prodesc = (plperl_proc_desc *) SvIV(*svp);
1088

1089
		/************************************************************
1090 1091 1092
		 * 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.
1093
		 ************************************************************/
1094
		uptodate = (prodesc->fn_xmin == HeapTupleHeaderGetXmin(procTup->t_data) &&
B
Bruce Momjian 已提交
1095
			prodesc->fn_cmin == HeapTupleHeaderGetCmin(procTup->t_data));
1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117

		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;
1118 1119
		Datum		prosrcdatum;
		bool		isnull;
1120 1121 1122 1123 1124 1125
		char	   *proc_source;

		/************************************************************
		 * Allocate a new procedure description block
		 ************************************************************/
		prodesc = (plperl_proc_desc *) malloc(sizeof(plperl_proc_desc));
1126
		if (prodesc == NULL)
1127 1128 1129
			ereport(ERROR,
					(errcode(ERRCODE_OUT_OF_MEMORY),
					 errmsg("out of memory")));
1130 1131
		MemSet(prodesc, 0, sizeof(plperl_proc_desc));
		prodesc->proname = strdup(internal_proname);
1132 1133
		prodesc->fn_xmin = HeapTupleHeaderGetXmin(procTup->t_data);
		prodesc->fn_cmin = HeapTupleHeaderGetCmin(procTup->t_data);
1134

1135 1136 1137 1138
		/* Remember if function is STABLE/IMMUTABLE */
		prodesc->fn_readonly =
			(procStruct->provolatile != PROVOLATILE_VOLATILE);

1139
		/************************************************************
1140
		 * Lookup the pg_language tuple by Oid
1141
		 ************************************************************/
1142 1143
		langTup = SearchSysCache(LANGOID,
								 ObjectIdGetDatum(procStruct->prolang),
1144
								 0, 0, 0);
1145
		if (!HeapTupleIsValid(langTup))
1146 1147 1148
		{
			free(prodesc->proname);
			free(prodesc);
1149
			elog(ERROR, "cache lookup failed for language %u",
1150
				 procStruct->prolang);
1151
		}
1152 1153 1154
		langStruct = (Form_pg_language) GETSTRUCT(langTup);
		prodesc->lanpltrusted = langStruct->lanpltrusted;
		ReleaseSysCache(langTup);
1155 1156

		/************************************************************
1157 1158
		 * Get the required information for input conversion of the
		 * return value.
1159
		 ************************************************************/
1160 1161 1162
		if (!is_trigger)
		{
			typeTup = SearchSysCache(TYPEOID,
1163
								ObjectIdGetDatum(procStruct->prorettype),
1164 1165 1166 1167 1168
									 0, 0, 0);
			if (!HeapTupleIsValid(typeTup))
			{
				free(prodesc->proname);
				free(prodesc);
1169
				elog(ERROR, "cache lookup failed for type %u",
1170
					 procStruct->prorettype);
1171 1172 1173
			}
			typeStruct = (Form_pg_type) GETSTRUCT(typeTup);

1174
			/* Disallow pseudotype result, except VOID or RECORD */
1175 1176
			if (typeStruct->typtype == 'p')
			{
1177 1178
				if (procStruct->prorettype == VOIDOID ||
					procStruct->prorettype == RECORDOID)
B
Bruce Momjian 已提交
1179
					 /* okay */ ;
1180
				else if (procStruct->prorettype == TRIGGEROID)
1181 1182 1183
				{
					free(prodesc->proname);
					free(prodesc);
1184 1185
					ereport(ERROR,
							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1186 1187
							 errmsg("trigger functions may only be called "
									"as triggers")));
1188 1189 1190 1191 1192
				}
				else
				{
					free(prodesc->proname);
					free(prodesc);
1193 1194
					ereport(ERROR,
							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
B
Bruce Momjian 已提交
1195 1196
						 errmsg("plperl functions cannot return type %s",
								format_type_be(procStruct->prorettype))));
1197 1198 1199
				}
			}

1200 1201 1202 1203
			prodesc->result_oid = procStruct->prorettype;
			prodesc->fn_retisset = procStruct->proretset;
			prodesc->fn_retistuple = (typeStruct->typtype == 'c' ||
									  procStruct->prorettype == RECORDOID);
1204 1205

			perm_fmgr_info(typeStruct->typinput, &(prodesc->result_in_func));
1206
			prodesc->result_typioparam = getTypeIOParam(typeTup);
1207 1208 1209

			ReleaseSysCache(typeTup);
		}
1210 1211

		/************************************************************
1212 1213
		 * Get the required information for output conversion
		 * of all procedure arguments
1214
		 ************************************************************/
1215 1216 1217 1218 1219 1220
		if (!is_trigger)
		{
			prodesc->nargs = procStruct->pronargs;
			for (i = 0; i < prodesc->nargs; i++)
			{
				typeTup = SearchSysCache(TYPEOID,
1221
							ObjectIdGetDatum(procStruct->proargtypes.values[i]),
1222 1223 1224 1225 1226
										 0, 0, 0);
				if (!HeapTupleIsValid(typeTup))
				{
					free(prodesc->proname);
					free(prodesc);
1227
					elog(ERROR, "cache lookup failed for type %u",
1228
						 procStruct->proargtypes.values[i]);
1229 1230 1231
				}
				typeStruct = (Form_pg_type) GETSTRUCT(typeTup);

1232 1233 1234 1235 1236
				/* Disallow pseudotype argument */
				if (typeStruct->typtype == 'p')
				{
					free(prodesc->proname);
					free(prodesc);
1237 1238
					ereport(ERROR,
							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
B
Bruce Momjian 已提交
1239
						   errmsg("plperl functions cannot take type %s",
1240
						   format_type_be(procStruct->proargtypes.values[i]))));
1241 1242
				}

1243 1244
				if (typeStruct->typtype == 'c')
					prodesc->arg_is_rowtype[i] = true;
1245
				else
1246 1247 1248 1249 1250
				{
					prodesc->arg_is_rowtype[i] = false;
					perm_fmgr_info(typeStruct->typoutput,
								   &(prodesc->arg_out_func[i]));
				}
1251 1252 1253 1254

				ReleaseSysCache(typeTup);
			}
		}
1255

1256 1257 1258 1259 1260
		/************************************************************
		 * create the text of the anonymous subroutine.
		 * we do not use a named subroutine so that we can call directly
		 * through the reference.
		 ************************************************************/
1261 1262 1263 1264
		prosrcdatum = SysCacheGetAttr(PROCOID, procTup,
									  Anum_pg_proc_prosrc, &isnull);
		if (isnull)
			elog(ERROR, "null prosrc");
1265
		proc_source = DatumGetCString(DirectFunctionCall1(textout,
1266
														  prosrcdatum));
1267 1268

		/************************************************************
1269
		 * Create the procedure in the interpreter
1270
		 ************************************************************/
1271 1272
		prodesc->reference = plperl_create_sub(proc_source, prodesc->lanpltrusted);
		pfree(proc_source);
1273
		if (!prodesc->reference) /* can this happen? */
1274 1275 1276
		{
			free(prodesc->proname);
			free(prodesc);
1277
			elog(ERROR, "could not create internal procedure \"%s\"",
1278
				 internal_proname);
1279 1280
		}

1281 1282
		hv_store(plperl_proc_hash, internal_proname, proname_len,
				 newSViv((IV) prodesc), 0);
1283 1284
	}

1285
	ReleaseSysCache(procTup);
1286

1287 1288
	return prodesc;
}
1289 1290


1291 1292
/* Build a hash from all attributes of a given tuple. */

B
Bruce Momjian 已提交
1293
static SV  *
1294
plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc)
1295
{
1296
	HV		   *hv;
1297
	int			i;
1298

1299
	hv = newHV();
1300 1301 1302

	for (i = 0; i < tupdesc->natts; i++)
	{
1303 1304 1305 1306 1307 1308 1309
		Datum		attr;
		bool		isnull;
		char	   *attname;
		char	   *outputstr;
		Oid			typoutput;
		bool		typisvarlena;
		int			namelen;
1310
		SV			*sv;
1311

1312 1313 1314
		if (tupdesc->attrs[i]->attisdropped)
			continue;

1315
		attname = NameStr(tupdesc->attrs[i]->attname);
1316
		namelen = strlen(attname);
1317 1318
		attr = heap_getattr(tuple, i + 1, tupdesc, &isnull);

1319 1320 1321
		if (isnull) {
			/* Store (attname => undef) and move on. */
			hv_store(hv, attname, namelen, newSV(0), 0);
1322 1323 1324
			continue;
		}

1325
		/* XXX should have a way to cache these lookups */
1326

1327
		getTypeOutputInfo(tupdesc->attrs[i]->atttypid,
1328
						  &typoutput, &typisvarlena);
1329

1330 1331
		outputstr = DatumGetCString(OidFunctionCall1(typoutput,
													 attr));
1332

1333 1334 1335 1336 1337
		sv = newSVpv(outputstr, 0);
#if PERL_BCDVERSION >= 0x5006000L
		if (GetDatabaseEncoding() == PG_UTF8) SvUTF8_on(sv);
#endif
		hv_store(hv, attname, namelen, sv, 0);
1338
	}
1339

1340
	return newRV_noinc((SV *) hv);
1341
}
1342 1343 1344 1345 1346 1347 1348


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

1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406
	/*
	 * 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();
1407 1408 1409 1410

	return ret_hv;
}

1411

1412
static HV  *
1413 1414
plperl_spi_execute_fetch_result(SPITupleTable *tuptable, int processed,
								int status)
1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426
{
	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)
	{
1427
		AV		   *rows;
1428
		SV		   *row;
1429
		int			i;
1430

1431 1432 1433 1434
		rows = newAV();
		for (i = 0; i < processed; i++)
		{
			row = plperl_hash_from_tuple(tuptable->vals[i], tuptable->tupdesc);
1435
			av_push(rows, row);
1436
		}
1437 1438
		hv_store(result, "rows", strlen("rows"),
				 newRV_noinc((SV *) rows), 0);
1439 1440 1441 1442 1443 1444
	}

	SPI_freetuptable(tuptable);

	return result;
}
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 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521


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

	if (!sv)
		return;

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

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

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

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

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

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

		tupdesc = CreateTupleDescCopy(rsi->expectedDesc);

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

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

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

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