plperl.c 40.0 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.82 2005/07/10 15:19:43 momjian Exp $
37
 *
38 39
 **********************************************************************/

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

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

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

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

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
HV		   *plperl_spi_exec(char *query, int limit);
121
SV		   *plperl_spi_query(char *);
122

123
static Datum plperl_func_handler(PG_FUNCTION_ARGS);
124

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

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

132
void plperl_return_next(SV *);
133

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

151 152 153

/* Perform initialization during postmaster startup. */

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

160 161 162 163 164 165 166 167 168
	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");
169

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

174 175 176

/* Perform initialization during backend startup. */

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

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

186 187

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

199 200 201 202
	static char	   *strict_embedding[3] = {
		"", "-e",
		/* all one string follows (no commas please) */
		"SPI::bootstrap(); use vars qw(%_SHARED);"
203 204
		"sub ::plperl_warn { my $msg = shift; &elog(&NOTICE, $msg); } "
		"$SIG{__WARN__} = \\&::plperl_warn; "
205 206 207 208
		"sub ::mkunsafefunc {return eval("
		"qq[ sub { use strict; $_[0] $_[1] } ]); }"
	};

209 210
	plperl_interp = perl_alloc();
	if (!plperl_interp)
211
		elog(ERROR, "could not allocate Perl interpreter");
212

213
	perl_construct(plperl_interp);
214 215
	perl_parse(plperl_interp, plperl_init_shared_libs, 3 ,
			   (plperl_use_strict ? strict_embedding : loose_embedding), NULL);
216
	perl_run(plperl_interp);
217

218
	plperl_proc_hash = newHV();
219 220
}

221 222 223 224

static void
plperl_safe_init(void)
{
B
Bruce Momjian 已提交
225 226
	static char *safe_module =
	"require Safe; $Safe::VERSION";
227

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

237 238 239 240 241 242 243 244 245 246 247 248
	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 已提交
249 250
	static char *safe_bad =
	"use vars qw($PLContainer); $PLContainer = new Safe('PLPerl');"
251 252
	"$PLContainer->permit_only(':default');"
	"$PLContainer->share(qw[&elog &ERROR ]);"
B
Bruce Momjian 已提交
253
	"sub ::mksafefunc { return $PLContainer->reval(qq[sub { "
254
	"elog(ERROR,'trusted Perl functions disabled - "
255
	"please upgrade Perl Safe module to version 2.09 or later');}]); }"
B
Bruce Momjian 已提交
256
			   ;
257

B
Bruce Momjian 已提交
258
	SV		   *res;
259
	double		safe_version;
260

B
Bruce Momjian 已提交
261
	res = eval_pv(safe_module, FALSE);	/* TRUE = croak if failure */
262 263 264

	safe_version = SvNV(res);

265 266 267 268 269
	/*
	 * 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.
	 */
270 271 272 273 274 275 276 277 278 279
	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);
	}
280 281 282 283

	plperl_safe_init_done = true;
}

284

285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
/*
 * 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;
}


300 301
/* Build a tuple from a hash. */

302 303
static HeapTuple
plperl_build_tuple_result(HV *perlhash, AttInMetadata *attinmeta)
304
{
305 306 307 308 309 310
	TupleDesc	td = attinmeta->tupdesc;
	char	  **values;
	SV		   *val;
	char	   *key;
	I32			klen;
	HeapTuple	tup;
311

312
	values = (char **) palloc0(td->natts * sizeof(char *));
313

314 315 316
	hv_iterinit(perlhash);
	while ((val = hv_iternextsv(perlhash, &key, &klen)))
	{
317
		int	attn = SPI_fnumber(td, key);
318

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

	tup = BuildTupleFromCStrings(attinmeta, values);
	pfree(values);
	return tup;
332 333
}

334

335 336
/* Set up the arguments for a trigger call. */

337 338 339 340 341
static SV  *
plperl_trigger_build_args(FunctionCallInfo fcinfo)
{
	TriggerData *tdata;
	TupleDesc	tupdesc;
342
	int			i;
343 344 345 346 347
	char	   *level;
	char	   *event;
	char	   *relid;
	char	   *when;
	HV		   *hv;
348

349
	hv = newHV();
350 351 352 353

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

354
	relid = DatumGetCString(
355 356
				DirectFunctionCall1(oidout,
									ObjectIdGetDatum(tdata->tg_relation->rd_id)
357 358 359 360 361
				)
			);

	hv_store(hv, "name", 4, newSVpv(tdata->tg_trigger->tgname, 0), 0);
	hv_store(hv, "relid", 5, newSVpv(relid, 0), 0);
362 363 364

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

395 396
	hv_store(hv, "event", 5, newSVpv(event, 0), 0);
	hv_store(hv, "argc", 4, newSViv(tdata->tg_trigger->tgnargs), 0);
397

398
	if (tdata->tg_trigger->tgnargs > 0)
399
	{
400 401 402
		AV *av = newAV();
		for (i=0; i < tdata->tg_trigger->tgnargs; i++)
			av_push(av, newSVpv(tdata->tg_trigger->tgargs[i], 0));
403
		hv_store(hv, "args", 4, newRV_noinc((SV *)av), 0);
404
	}
405 406 407

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

	if (TRIGGER_FIRED_BEFORE(tdata->tg_event))
410
		when = "BEFORE";
411
	else if (TRIGGER_FIRED_AFTER(tdata->tg_event))
412
		when = "AFTER";
413
	else
414 415
		when = "UNKNOWN";
	hv_store(hv, "when", 4, newSVpv(when, 0), 0);
416 417

	if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event))
418
		level = "ROW";
419
	else if (TRIGGER_FIRED_FOR_STATEMENT(tdata->tg_event))
420
		level = "STATEMENT";
421
	else
422 423
		level = "UNKNOWN";
	hv_store(hv, "level", 5, newSVpv(level, 0), 0);
424

425
	return newRV_noinc((SV*)hv);
426 427 428
}


429
/* Set up the new tuple returned from a trigger. */
430

431
static HeapTuple
432
plperl_modify_tuple(HV *hvTD, TriggerData *tdata, HeapTuple otup)
433 434 435 436
{
	SV		  **svp;
	HV		   *hvNew;
	HeapTuple	rtup;
437 438 439 440 441 442 443 444
	SV		   *val;
	char	   *key;
	I32			klen;
	int			slotsused;
	int		   *modattrs;
	Datum	   *modvalues;
	char	   *modnulls;

445 446 447 448 449
	TupleDesc	tupdesc;

	tupdesc = tdata->tg_relation->rd_att;

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

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

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

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

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

	pfree(modattrs);
	pfree(modvalues);
	pfree(modnulls);
507

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

	return rtup;
}
514

515

516 517
/*
 * This is the only externally-visible part of the plperl call interface.
518
 * The Postgres function and trigger managers call it to execute a
519 520
 * perl function.
 */
521
PG_FUNCTION_INFO_V1(plperl_call_handler);
522 523

Datum
524
plperl_call_handler(PG_FUNCTION_ARGS)
525
{
526
	Datum retval;
527
	plperl_proc_desc *save_prodesc;
528

529
	plperl_init_all();
530

531
	save_prodesc = plperl_current_prodesc;
532

533 534 535 536 537 538 539 540 541 542 543 544 545 546 547
	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;
548 549 550 551

	return retval;
}

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 584 585 586 587 588 589
/*
 * 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();
}

590

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

B
Bruce Momjian 已提交
594
static SV  *
595
plperl_create_sub(char *s, bool trusted)
596
{
597
	dSP;
598
	SV		   *subref;
B
Bruce Momjian 已提交
599
	int			count;
600

B
Bruce Momjian 已提交
601
	if (trusted && !plperl_safe_init_done)
602
	{
603
		plperl_safe_init();
604 605
		SPAGAIN;
	}
606

607 608 609
	ENTER;
	SAVETMPS;
	PUSHMARK(SP);
610
	XPUSHs(sv_2mortal(newSVpv("my $_TD=$_[0]; shift;", 0)));
B
Bruce Momjian 已提交
611
	XPUSHs(sv_2mortal(newSVpv(s, 0)));
B
Bruce Momjian 已提交
612
	PUTBACK;
B
Bruce Momjian 已提交
613

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

623 624 625 626 627
	if (count != 1)
	{
		PUTBACK;
		FREETMPS;
		LEAVE;
628
		elog(ERROR, "didn't get a return item from mksafefunc");
629 630
	}

631
	if (SvTRUE(ERRSV))
632
	{
633
		(void) POPs;
634 635 636
		PUTBACK;
		FREETMPS;
		LEAVE;
637 638 639 640
		ereport(ERROR,
				(errcode(ERRCODE_SYNTAX_ERROR),
				 errmsg("creation of Perl function failed: %s",
						strip_trailing_ws(SvPV(ERRSV, PL_na)))));
641 642 643
	}

	/*
644 645
	 * need to make a deep copy of the return. it comes off the stack as a
	 * temporary.
646 647 648
	 */
	subref = newSVsv(POPs);

649
	if (!SvROK(subref) || SvTYPE(SvRV(subref)) != SVt_PVCV)
650
	{
651 652 653
		PUTBACK;
		FREETMPS;
		LEAVE;
654

655 656 657 658
		/*
		 * subref is our responsibility because it is not mortal
		 */
		SvREFCNT_dec(subref);
659
		elog(ERROR, "didn't get a code ref");
660 661 662 663 664
	}

	PUTBACK;
	FREETMPS;
	LEAVE;
665

666 667 668
	return subref;
}

669

670
/**********************************************************************
671
 * plperl_init_shared_libs()		-
672 673 674 675
 *
 * 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.
676
 *
677 678
 **********************************************************************/

679 680
EXTERN_C void boot_DynaLoader(pTHX_ CV *cv);
EXTERN_C void boot_SPI(pTHX_ CV *cv);
681

682
static void
683
plperl_init_shared_libs(pTHX)
684
{
685 686
	char	   *file = __FILE__;

687
	newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
688
	newXS("SPI::bootstrap", boot_SPI, file);
689 690
}

691

B
Bruce Momjian 已提交
692
static SV  *
693
plperl_call_perl_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo)
694 695
{
	dSP;
696 697 698
	SV		   *retval;
	int			i;
	int			count;
699
	SV			*sv;
700 701 702 703

	ENTER;
	SAVETMPS;

704
	PUSHMARK(SP);
705

706
	XPUSHs(&PL_sv_undef); /* no trigger data */
707

708 709
	for (i = 0; i < desc->nargs; i++)
	{
710 711 712
		if (fcinfo->argnull[i])
			XPUSHs(&PL_sv_undef);
		else if (desc->arg_is_rowtype[i])
713
		{
714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729
			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;

730 731
			hashref = plperl_hash_from_tuple(&tmptup, tupdesc);
			XPUSHs(sv_2mortal(hashref));
732 733 734
		}
		else
		{
735 736
			char	   *tmp;

737 738
			tmp = DatumGetCString(FunctionCall1(&(desc->arg_out_func[i]),
												fcinfo->arg[i]));
739 740 741 742 743
			sv = newSVpv(tmp, 0);
#if PERL_BCDVERSION >= 0x5006000L
			if (GetDatabaseEncoding() == PG_UTF8) SvUTF8_on(sv);
#endif
			XPUSHs(sv_2mortal(sv));
744
			pfree(tmp);
745 746 747
		}
	}
	PUTBACK;
748 749 750

	/* Do NOT use G_KEEPERR here */
	count = perl_call_sv(desc->reference, G_SCALAR | G_EVAL);
751 752 753

	SPAGAIN;

754 755 756 757
	if (count != 1)
	{
		PUTBACK;
		FREETMPS;
758
		LEAVE;
759
		elog(ERROR, "didn't get a return item from function");
760 761
	}

762
	if (SvTRUE(ERRSV))
763
	{
764
		(void) POPs;
765 766
		PUTBACK;
		FREETMPS;
767
		LEAVE;
768 769 770 771
		/* 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)))));
772 773 774 775
	}

	retval = newSVsv(POPs);

776 777 778
	PUTBACK;
	FREETMPS;
	LEAVE;
779 780 781 782

	return retval;
}

783

784
static SV  *
785 786
plperl_call_perl_trigger_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo,
							  SV *td)
787 788 789
{
	dSP;
	SV		   *retval;
790
	Trigger    *tg_trigger;
791 792 793 794 795 796 797
	int			i;
	int			count;

	ENTER;
	SAVETMPS;

	PUSHMARK(sp);
798

799
	XPUSHs(td);
800

801 802 803
	tg_trigger = ((TriggerData *) fcinfo->context)->tg_trigger;
	for (i = 0; i < tg_trigger->tgnargs; i++)
		XPUSHs(sv_2mortal(newSVpv(tg_trigger->tgargs[i], 0)));
804 805
	PUTBACK;

806 807
	/* Do NOT use G_KEEPERR here */
	count = perl_call_sv(desc->reference, G_SCALAR | G_EVAL);
808 809 810 811 812 813 814 815

	SPAGAIN;

	if (count != 1)
	{
		PUTBACK;
		FREETMPS;
		LEAVE;
816
		elog(ERROR, "didn't get a return item from trigger function");
817 818 819 820
	}

	if (SvTRUE(ERRSV))
	{
821
		(void) POPs;
822 823 824
		PUTBACK;
		FREETMPS;
		LEAVE;
825 826 827 828
		/* 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)))));
829 830 831 832 833 834 835 836 837 838
	}

	retval = newSVsv(POPs);

	PUTBACK;
	FREETMPS;
	LEAVE;

	return retval;
}
839

840

841
static Datum
842
plperl_func_handler(PG_FUNCTION_ARGS)
843 844
{
	plperl_proc_desc *prodesc;
845 846
	SV		   *perlret;
	Datum		retval;
847
	ReturnSetInfo *rsi;
848

849 850 851
	if (SPI_connect() != SPI_OK_CONNECT)
		elog(ERROR, "could not connect to SPI manager");

852
	prodesc = compile_plperl_function(fcinfo->flinfo->fn_oid, false);
853 854

	plperl_current_prodesc = prodesc;
855 856 857
	prodesc->caller_info = fcinfo;
	prodesc->tuple_store = 0;
	prodesc->tuple_desc = 0;
858

859
	perlret = plperl_call_perl_func(prodesc, fcinfo);
860 861 862 863 864 865 866 867

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

870
	rsi = (ReturnSetInfo *)fcinfo->resultinfo;
871

872 873 874 875
	if (prodesc->fn_retisset) {
		if (!rsi || !IsA(rsi, ReturnSetInfo) ||
			(rsi->allowedModes & SFRM_Materialize) == 0 ||
			rsi->expectedDesc == NULL)
876
		{
877 878 879 880
			ereport(ERROR,
					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
					 errmsg("set-valued function called in context that "
							"cannot accept a set")));
881 882
		}

883 884 885 886 887 888
		/* 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)
889
		{
890 891 892 893 894 895 896
			int i = 0;
			SV **svp = 0;
			AV *rav = (AV *)SvRV(perlret);
			while ((svp = av_fetch(rav, i, FALSE)) != NULL) {
				plperl_return_next(*svp);
				i++;
			}
897
		}
898
		else if (SvTYPE(perlret) != SVt_NULL)
899
		{
900 901
			ereport(ERROR,
					(errcode(ERRCODE_DATATYPE_MISMATCH),
902 903
					 errmsg("set-returning Perl function must return "
							"reference to array or use return_next")));
904
		}
B
Bruce Momjian 已提交
905

906 907 908 909
		rsi->returnMode = SFRM_Materialize;
		if (prodesc->tuple_store) {
			rsi->setResult = prodesc->tuple_store;
			rsi->setDesc = prodesc->tuple_desc;
910
		}
911 912 913 914 915 916 917 918 919
		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 已提交
920
	}
921
	else if (prodesc->fn_retistuple)
922
	{
923 924
		/* Return a perl hash converted to a Datum */
		TupleDesc td;
925
		AttInMetadata *attinmeta;
926
		HeapTuple tup;
927

928 929 930
		if (!SvOK(perlret) || SvTYPE(perlret) != SVt_RV ||
			SvTYPE(SvRV(perlret)) != SVt_PVHV)
		{
931 932
			ereport(ERROR,
					(errcode(ERRCODE_DATATYPE_MISMATCH),
933 934 935
					 errmsg("composite-returning Perl function "
							"must return reference to hash")));
		}
936

937 938 939 940 941 942 943 944
		/* 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")));
		}
945

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

	SvREFCNT_dec(perlret);
	return retval;
}

964

965 966 967 968 969 970 971 972 973
static Datum
plperl_trigger_handler(PG_FUNCTION_ARGS)
{
	plperl_proc_desc *prodesc;
	SV		   *perlret;
	Datum		retval;
	SV		   *svTD;
	HV		   *hvTD;

974 975 976 977
	/* Connect to SPI manager */
	if (SPI_connect() != SPI_OK_CONNECT)
		elog(ERROR, "could not connect to SPI manager");

978 979 980
	/* Find or compile the function */
	prodesc = compile_plperl_function(fcinfo->flinfo->fn_oid, true);

981 982
	plperl_current_prodesc = prodesc;

983 984
	svTD = plperl_trigger_build_args(fcinfo);
	perlret = plperl_call_perl_trigger_func(prodesc, fcinfo, svTD);
985
	hvTD = (HV *) SvRV(svTD);
986 987 988 989 990 991 992 993

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

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

1015
		tmp = SvPV(perlret, PL_na);
1016

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

1048 1049 1050
	SvREFCNT_dec(svTD);
	if (perlret)
		SvREFCNT_dec(perlret);
1051 1052 1053

	return retval;
}
1054

1055

1056 1057
static plperl_proc_desc *
compile_plperl_function(Oid fn_oid, bool is_trigger)
1058
{
1059 1060 1061 1062 1063
	HeapTuple	procTup;
	Form_pg_proc procStruct;
	char		internal_proname[64];
	int			proname_len;
	plperl_proc_desc *prodesc = NULL;
1064
	int			i;
1065
	SV			**svp;
1066

1067 1068 1069 1070 1071
	/* We'll need the pg_proc tuple in any case... */
	procTup = SearchSysCache(PROCOID,
							 ObjectIdGetDatum(fn_oid),
							 0, 0, 0);
	if (!HeapTupleIsValid(procTup))
1072
		elog(ERROR, "cache lookup failed for function %u", fn_oid);
1073
	procStruct = (Form_pg_proc) GETSTRUCT(procTup);
1074 1075 1076 1077

	/************************************************************
	 * Build our internal proc name from the functions Oid
	 ************************************************************/
1078 1079 1080 1081
	if (!is_trigger)
		sprintf(internal_proname, "__PLPerl_proc_%u", fn_oid);
	else
		sprintf(internal_proname, "__PLPerl_proc_%u_trigger", fn_oid);
1082

1083
	proname_len = strlen(internal_proname);
1084 1085 1086 1087

	/************************************************************
	 * Lookup the internal proc name in the hashtable
	 ************************************************************/
1088 1089
	svp = hv_fetch(plperl_proc_hash, internal_proname, proname_len, FALSE);
	if (svp)
1090
	{
1091 1092
		bool		uptodate;

1093
		prodesc = (plperl_proc_desc *) SvIV(*svp);
1094

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

		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;
1124 1125
		Datum		prosrcdatum;
		bool		isnull;
1126 1127 1128 1129 1130 1131
		char	   *proc_source;

		/************************************************************
		 * Allocate a new procedure description block
		 ************************************************************/
		prodesc = (plperl_proc_desc *) malloc(sizeof(plperl_proc_desc));
1132
		if (prodesc == NULL)
1133 1134 1135
			ereport(ERROR,
					(errcode(ERRCODE_OUT_OF_MEMORY),
					 errmsg("out of memory")));
1136 1137
		MemSet(prodesc, 0, sizeof(plperl_proc_desc));
		prodesc->proname = strdup(internal_proname);
1138 1139
		prodesc->fn_xmin = HeapTupleHeaderGetXmin(procTup->t_data);
		prodesc->fn_cmin = HeapTupleHeaderGetCmin(procTup->t_data);
1140

1141 1142 1143 1144
		/* Remember if function is STABLE/IMMUTABLE */
		prodesc->fn_readonly =
			(procStruct->provolatile != PROVOLATILE_VOLATILE);

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

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

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

1206 1207 1208 1209
			prodesc->result_oid = procStruct->prorettype;
			prodesc->fn_retisset = procStruct->proretset;
			prodesc->fn_retistuple = (typeStruct->typtype == 'c' ||
									  procStruct->prorettype == RECORDOID);
1210 1211

			perm_fmgr_info(typeStruct->typinput, &(prodesc->result_in_func));
1212
			prodesc->result_typioparam = getTypeIOParam(typeTup);
1213 1214 1215

			ReleaseSysCache(typeTup);
		}
1216 1217

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

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

1249 1250
				if (typeStruct->typtype == 'c')
					prodesc->arg_is_rowtype[i] = true;
1251
				else
1252 1253 1254 1255 1256
				{
					prodesc->arg_is_rowtype[i] = false;
					perm_fmgr_info(typeStruct->typoutput,
								   &(prodesc->arg_out_func[i]));
				}
1257 1258 1259 1260

				ReleaseSysCache(typeTup);
			}
		}
1261

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

		/************************************************************
1275
		 * Create the procedure in the interpreter
1276
		 ************************************************************/
1277 1278
		prodesc->reference = plperl_create_sub(proc_source, prodesc->lanpltrusted);
		pfree(proc_source);
1279
		if (!prodesc->reference) /* can this happen? */
1280 1281 1282
		{
			free(prodesc->proname);
			free(prodesc);
1283
			elog(ERROR, "could not create internal procedure \"%s\"",
1284
				 internal_proname);
1285 1286
		}

1287 1288
		hv_store(plperl_proc_hash, internal_proname, proname_len,
				 newSViv((IV) prodesc), 0);
1289 1290
	}

1291
	ReleaseSysCache(procTup);
1292

1293 1294
	return prodesc;
}
1295 1296


1297 1298
/* Build a hash from all attributes of a given tuple. */

B
Bruce Momjian 已提交
1299
static SV  *
1300
plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc)
1301
{
1302
	HV		   *hv;
1303
	int			i;
1304

1305
	hv = newHV();
1306 1307 1308

	for (i = 0; i < tupdesc->natts; i++)
	{
1309 1310 1311 1312 1313 1314 1315
		Datum		attr;
		bool		isnull;
		char	   *attname;
		char	   *outputstr;
		Oid			typoutput;
		bool		typisvarlena;
		int			namelen;
1316
		SV			*sv;
1317

1318 1319 1320
		if (tupdesc->attrs[i]->attisdropped)
			continue;

1321
		attname = NameStr(tupdesc->attrs[i]->attname);
1322
		namelen = strlen(attname);
1323 1324
		attr = heap_getattr(tuple, i + 1, tupdesc, &isnull);

1325 1326 1327
		if (isnull) {
			/* Store (attname => undef) and move on. */
			hv_store(hv, attname, namelen, newSV(0), 0);
1328 1329 1330
			continue;
		}

1331
		/* XXX should have a way to cache these lookups */
1332

1333
		getTypeOutputInfo(tupdesc->attrs[i]->atttypid,
1334
						  &typoutput, &typisvarlena);
1335

1336
		outputstr = DatumGetCString(OidFunctionCall1(typoutput, attr));
1337

1338 1339
		sv = newSVpv(outputstr, 0);
#if PERL_BCDVERSION >= 0x5006000L
1340 1341
		if (GetDatabaseEncoding() == PG_UTF8)
			SvUTF8_on(sv);
1342 1343
#endif
		hv_store(hv, attname, namelen, sv, 0);
1344 1345

		pfree(outputstr);
1346
	}
1347

1348
	return newRV_noinc((SV *) hv);
1349
}
1350 1351 1352 1353 1354 1355 1356


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

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 1407 1408 1409 1410 1411 1412 1413 1414
	/*
	 * 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();
1415 1416 1417 1418

	return ret_hv;
}

1419

1420
static HV  *
1421 1422
plperl_spi_execute_fetch_result(SPITupleTable *tuptable, int processed,
								int status)
1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434
{
	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)
	{
1435
		AV		   *rows;
1436
		SV		   *row;
1437
		int			i;
1438

1439 1440 1441 1442
		rows = newAV();
		for (i = 0; i < processed; i++)
		{
			row = plperl_hash_from_tuple(tuptable->vals[i], tuptable->tupdesc);
1443
			av_push(rows, row);
1444
		}
1445 1446
		hv_store(result, "rows", strlen("rows"),
				 newRV_noinc((SV *) rows), 0);
1447 1448 1449 1450 1451 1452
	}

	SPI_freetuptable(tuptable);

	return result;
}
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 1522 1523 1524 1525 1526 1527 1528 1529


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);
}
1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603


SV *
plperl_spi_query(char *query)
{
	SV *cursor;

	MemoryContext oldcontext = CurrentMemoryContext;
	ResourceOwner oldowner = CurrentResourceOwner;

	BeginInternalSubTransaction(NULL);
	MemoryContextSwitchTo(oldcontext);

	PG_TRY();
	{
		void *plan;
		Portal portal = NULL;

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

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

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

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

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

	return cursor;
}


SV *
plperl_spi_fetchrow(char *cursor)
{
	SV *row = newSV(0);
	Portal p = SPI_cursor_find(cursor);

	if (!p)
		return row;

	SPI_cursor_fetch(p, true, 1);
	if (SPI_processed == 0) {
		SPI_cursor_close(p);
		return row;
	}

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

	return row;
}