postgres.c 85.7 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * postgres.c
4
 *	  POSTGRES C Backend Interface
5
 *
Bruce Momjian's avatar
Bruce Momjian committed
6
 * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
Bruce Momjian's avatar
Add:  
Bruce Momjian committed
7
 * Portions Copyright (c) 1994, Regents of the University of California
8 9 10
 *
 *
 * IDENTIFICATION
11
 *	  $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.431 2004/09/10 18:39:59 tgl Exp $
12 13
 *
 * NOTES
14 15
 *	  this is the "main" module of the postgres backend and
 *	  hence the main module of the "traffic cop".
16 17 18
 *
 *-------------------------------------------------------------------------
 */
Bruce Momjian's avatar
Bruce Momjian committed
19

20 21
#include "postgres.h"

Bruce Momjian's avatar
Bruce Momjian committed
22
#include <unistd.h>
23
#include <signal.h>
Bruce Momjian's avatar
Bruce Momjian committed
24
#include <fcntl.h>
25
#include <sys/socket.h>
26
#if HAVE_SYS_SELECT_H
27
#include <sys/select.h>
28
#endif
29
#ifdef HAVE_GETOPT_H
Bruce Momjian's avatar
Bruce Momjian committed
30
#include <getopt.h>
31
#endif
32

33
#include "access/printtup.h"
34
#include "access/xlog.h"
35
#include "catalog/pg_type.h"
36
#include "commands/async.h"
37
#include "commands/prepare.h"
38
#include "commands/trigger.h"
39
#include "libpq/libpq.h"
40
#include "libpq/pqformat.h"
41
#include "libpq/pqsignal.h"
Bruce Momjian's avatar
Bruce Momjian committed
42
#include "miscadmin.h"
43 44
#include "nodes/print.h"
#include "optimizer/cost.h"
45
#include "optimizer/planner.h"
46
#include "parser/analyze.h"
47
#include "parser/parser.h"
Bruce Momjian's avatar
Bruce Momjian committed
48
#include "rewrite/rewriteHandler.h"
49
#include "storage/freespace.h"
50
#include "storage/ipc.h"
51
#include "storage/pg_shmem.h"
52
#include "storage/proc.h"
53
#include "storage/sinval.h"
54 55
#include "tcop/fastpath.h"
#include "tcop/pquery.h"
Bruce Momjian's avatar
Bruce Momjian committed
56
#include "tcop/tcopprot.h"
57
#include "tcop/utility.h"
58
#include "utils/guc.h"
59
#include "utils/lsyscache.h"
60
#include "utils/memutils.h"
61
#include "utils/ps_status.h"
Bruce Momjian's avatar
Bruce Momjian committed
62
#include "mb/pg_wchar.h"
63

64
#include "pgstat.h"
65

66 67 68
extern int	optind;
extern char *optarg;

69
/* ----------------
70
 *		global variables
71 72
 * ----------------
 */
73
const char *debug_query_string; /* for pgmonitor and
Bruce Momjian's avatar
Bruce Momjian committed
74
								 * log_min_error_statement */
75

76
/* Note: whereToSendOutput is initialized for the bootstrap/standalone case */
77
CommandDest whereToSendOutput = Debug;
78

79
/* flag for logging end of session */
Bruce Momjian's avatar
Bruce Momjian committed
80
bool		Log_disconnections = false;
81

82 83
LogStmtLevel log_statement = LOGSTMT_NONE;

84 85 86 87
/* GUC variable for maximum stack depth (measured in kilobytes) */
int			max_stack_depth = 2048;


88 89 90 91
/* ----------------
 *		private variables
 * ----------------
 */
92

93
/* max_stack_depth converted to bytes for speed of checking */
Bruce Momjian's avatar
Bruce Momjian committed
94
static int	max_stack_depth_bytes = 2048 * 1024;
95 96 97 98 99

/* stack base pointer (initialized by PostgresMain) */
static char *stack_base_ptr = NULL;


100 101 102 103 104
/*
 * Flag to mark SIGHUP. Whenever the main loop comes around it
 * will reread the configuration file. (Better than doing the
 * reading in the signal handler, ey?)
 */
105
static volatile sig_atomic_t got_SIGHUP = false;
106

107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
/*
 * Flag to keep track of whether we have started a transaction.
 * For extended query protocol this has to be remembered across messages.
 */
static bool xact_started = false;

/*
 * Flags to implement skip-till-Sync-after-error behavior for messages of
 * the extended query protocol.
 */
static bool doing_extended_query_message = false;
static bool ignore_till_sync = false;

/*
 * If an unnamed prepared statement exists, it's stored here.
 * We keep it separate from the hashtable kept by commands/prepare.c
 * in order to reduce overhead for short-lived queries.
 */
static MemoryContext unnamed_stmt_context = NULL;
static PreparedStatement *unnamed_stmt_pstmt = NULL;


static bool EchoQuery = false;	/* default don't echo */

/*
 * people who want to use EOF should #define DONTUSENEWLINE in
 * tcop/tcopdebug.h
134 135
 */
#ifndef TCOP_DONTUSENEWLINE
136
static int	UseNewLine = 1;		/* Use newlines query delimiters (the
137
								 * default) */
Bruce Momjian's avatar
Bruce Momjian committed
138

139
#else
140
static int	UseNewLine = 0;		/* Use EOF as query delimiters */
141
#endif   /* TCOP_DONTUSENEWLINE */
142 143 144


/* ----------------------------------------------------------------
145
 *		decls for routines only used in this file
146 147
 * ----------------------------------------------------------------
 */
148 149 150
static int	InteractiveBackend(StringInfo inBuf);
static int	SocketBackend(StringInfo inBuf);
static int	ReadCommand(StringInfo inBuf);
151
static void start_xact_command(void);
152
static void finish_xact_command(void);
153 154
static void SigHupHandler(SIGNAL_ARGS);
static void FloatExceptionHandler(SIGNAL_ARGS);
155
static void log_disconnections(int code, Datum arg);
156 157 158


/* ----------------------------------------------------------------
159
 *		routines to obtain user input
160 161 162 163
 * ----------------------------------------------------------------
 */

/* ----------------
164
 *	InteractiveBackend() is called for user interactive connections
165 166 167
 *
 *	the string entered by the user is placed in its parameter inBuf,
 *	and we act like a Q message was received.
168
 *
169
 *	EOF is returned if end-of-file input is seen; time to shut down.
170 171 172
 * ----------------
 */

173
static int
174
InteractiveBackend(StringInfo inBuf)
175
{
176 177 178
	int			c;				/* character read from getc() */
	bool		end = false;	/* end-of-input flag */
	bool		backslashSeen = false;	/* have we seen a \ ? */
179

180 181
	/*
	 * display a prompt and obtain input from the user
182
	 */
183
	printf("backend> ");
184
	fflush(stdout);
185

186 187 188
	/* Reset inBuf to empty */
	inBuf->len = 0;
	inBuf->data[0] = '\0';
189
	inBuf->cursor = 0;
190

191 192 193 194
	for (;;)
	{
		if (UseNewLine)
		{
195 196 197
			/*
			 * if we are using \n as a delimiter, then read characters
			 * until the \n.
198 199 200 201 202 203 204
			 */
			while ((c = getc(stdin)) != EOF)
			{
				if (c == '\n')
				{
					if (backslashSeen)
					{
205 206 207
						/* discard backslash from inBuf */
						inBuf->data[--inBuf->len] = '\0';
						backslashSeen = false;
208 209 210 211 212
						continue;
					}
					else
					{
						/* keep the newline character */
213
						appendStringInfoChar(inBuf, '\n');
214 215 216 217 218 219 220 221
						break;
					}
				}
				else if (c == '\\')
					backslashSeen = true;
				else
					backslashSeen = false;

222
				appendStringInfoChar(inBuf, (char) c);
223 224 225 226 227 228 229
			}

			if (c == EOF)
				end = true;
		}
		else
		{
230 231
			/*
			 * otherwise read characters until EOF.
232 233
			 */
			while ((c = getc(stdin)) != EOF)
234
				appendStringInfoChar(inBuf, (char) c);
235

236
			if (inBuf->len == 0)
237 238 239 240
				end = true;
		}

		if (end)
241
			return EOF;
242

243 244
		/*
		 * otherwise we have a user query so process it.
245 246 247 248
		 */
		break;
	}

249 250 251
	/* Add '\0' to make it look the same as message case. */
	appendStringInfoChar(inBuf, (char) '\0');

252 253
	/*
	 * if the query echo flag was given, print the query..
254 255
	 */
	if (EchoQuery)
256
		printf("statement: %s\n", inBuf->data);
257
	fflush(stdout);
258

259
	return 'Q';
260 261 262
}

/* ----------------
263
 *	SocketBackend()		Is called for frontend-backend connections
264
 *
265
 *	Returns the message type code, and loads message body data into inBuf.
266
 *
267
 *	EOF is returned if the connection is lost.
268 269
 * ----------------
 */
270
static int
271
SocketBackend(StringInfo inBuf)
272
{
273
	int			qtype;
274

275
	/*
276
	 * Get message type code from the frontend.
277
	 */
278
	qtype = pq_getbyte();
279

280 281
	if (qtype == EOF)			/* frontend disconnected */
	{
282 283 284
		ereport(COMMERROR,
				(errcode(ERRCODE_PROTOCOL_VIOLATION),
				 errmsg("unexpected EOF on client connection")));
285 286 287 288 289
		return qtype;
	}

	/*
	 * Validate message type code before trying to read body; if we have
Bruce Momjian's avatar
Bruce Momjian committed
290 291
	 * lost sync, better to say "command unknown" than to run out of
	 * memory because we used garbage as a length word.
292 293 294
	 *
	 * This also gives us a place to set the doing_extended_query_message
	 * flag as soon as possible.
295
	 */
296
	switch (qtype)
297
	{
298
		case 'Q':				/* simple query */
299
			doing_extended_query_message = false;
300 301 302 303 304
			if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
			{
				/* old style without length word; convert */
				if (pq_getstring(inBuf))
				{
305 306
					ereport(COMMERROR,
							(errcode(ERRCODE_PROTOCOL_VIOLATION),
Bruce Momjian's avatar
Bruce Momjian committed
307
						 errmsg("unexpected EOF on client connection")));
308 309 310
					return EOF;
				}
			}
311 312
			break;

313
		case 'F':				/* fastpath function call */
314 315
			/* we let fastpath.c cope with old-style input of this */
			doing_extended_query_message = false;
316
			break;
317

318
		case 'X':				/* terminate */
319
			doing_extended_query_message = false;
320
			ignore_till_sync = false;
321 322 323 324 325 326 327 328 329 330 331
			break;

		case 'B':				/* bind */
		case 'C':				/* close */
		case 'D':				/* describe */
		case 'E':				/* execute */
		case 'H':				/* flush */
		case 'P':				/* parse */
			doing_extended_query_message = true;
			/* these are only legal in protocol 3 */
			if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
332 333
				ereport(FATAL,
						(errcode(ERRCODE_PROTOCOL_VIOLATION),
Bruce Momjian's avatar
Bruce Momjian committed
334
					 errmsg("invalid frontend message type %d", qtype)));
335 336 337 338 339 340 341 342 343
			break;

		case 'S':				/* sync */
			/* stop any active skip-till-Sync */
			ignore_till_sync = false;
			/* mark not-extended, so that a new error doesn't begin skip */
			doing_extended_query_message = false;
			/* only legal in protocol 3 */
			if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
344 345
				ereport(FATAL,
						(errcode(ERRCODE_PROTOCOL_VIOLATION),
Bruce Momjian's avatar
Bruce Momjian committed
346
					 errmsg("invalid frontend message type %d", qtype)));
347
			break;
348

349 350 351
		case 'd':				/* copy data */
		case 'c':				/* copy done */
		case 'f':				/* copy fail */
352 353 354
			doing_extended_query_message = false;
			/* these are only legal in protocol 3 */
			if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
355 356
				ereport(FATAL,
						(errcode(ERRCODE_PROTOCOL_VIOLATION),
Bruce Momjian's avatar
Bruce Momjian committed
357
					 errmsg("invalid frontend message type %d", qtype)));
358
			break;
359

360
		default:
Bruce Momjian's avatar
Bruce Momjian committed
361

362
			/*
Bruce Momjian's avatar
Bruce Momjian committed
363 364 365
			 * Otherwise we got garbage from the frontend.	We treat this
			 * as fatal because we have probably lost message boundary
			 * sync, and there's no good way to recover.
366
			 */
367 368 369
			ereport(FATAL,
					(errcode(ERRCODE_PROTOCOL_VIOLATION),
					 errmsg("invalid frontend message type %d", qtype)));
370
			break;
371
	}
372

373 374 375 376 377 378 379 380 381 382 383
	/*
	 * In protocol version 3, all frontend messages have a length word
	 * next after the type code; we can read the message contents
	 * independently of the type.
	 */
	if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3)
	{
		if (pq_getmessage(inBuf, 0))
			return EOF;			/* suitable message already logged */
	}

384
	return qtype;
385 386 387
}

/* ----------------
388
 *		ReadCommand reads a command from either the frontend or
389 390 391
 *		standard input, places it in inBuf, and returns the
 *		message type code (first byte of the message).
 *		EOF is returned if end of file.
392 393
 * ----------------
 */
394
static int
395
ReadCommand(StringInfo inBuf)
396
{
397
	int			result;
398

399
	if (whereToSendOutput == Remote)
400
		result = SocketBackend(inBuf);
401
	else
402 403
		result = InteractiveBackend(inBuf);
	return result;
404 405
}

406 407 408 409 410 411

/*
 * Parse a query string and pass it through the rewriter.
 *
 * A list of Query nodes is returned, since the string might contain
 * multiple queries and/or the rewriter might expand one query to several.
412 413 414
 *
 * NOTE: this routine is no longer used for processing interactive queries,
 * but it is still needed for parsing of SQL function bodies.
415
 */
416
List *
Bruce Momjian's avatar
Bruce Momjian committed
417
pg_parse_and_rewrite(const char *query_string,	/* string to execute */
418
					 Oid *paramTypes,	/* parameter types */
Bruce Momjian's avatar
Bruce Momjian committed
419
					 int numParams)		/* number of parameters */
420
{
421
	List	   *raw_parsetree_list;
422
	List	   *querytree_list;
423
	ListCell   *list_item;
424

425 426
	/*
	 * (1) parse the request string into a list of raw parse trees.
427
	 */
428
	raw_parsetree_list = pg_parse_query(query_string);
429

430 431
	/*
	 * (2) Do parse analysis and rule rewrite.
432 433 434 435
	 */
	querytree_list = NIL;
	foreach(list_item, raw_parsetree_list)
	{
436
		Node	   *parsetree = (Node *) lfirst(list_item);
437

438
		querytree_list = list_concat(querytree_list,
Bruce Momjian's avatar
Bruce Momjian committed
439 440 441
									 pg_analyze_and_rewrite(parsetree,
															paramTypes,
															numParams));
442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459
	}

	return querytree_list;
}

/*
 * Do raw parsing (only).
 *
 * A list of parsetrees is returned, since there might be multiple
 * commands in the given string.
 *
 * NOTE: for interactive queries, it is important to keep this routine
 * separate from the analysis & rewrite stages.  Analysis and rewriting
 * cannot be done in an aborted transaction, since they require access to
 * database tables.  So, we rely on the raw parser to determine whether
 * we've seen a COMMIT or ABORT command; when we are in abort state, other
 * commands are not processed any further than the raw parse stage.
 */
460
List *
461
pg_parse_query(const char *query_string)
462
{
463 464
	List	   *raw_parsetree_list;
	ListCell   *parsetree_item;
465

466
	if (log_statement == LOGSTMT_ALL)
467
		ereport(LOG,
468
				(errmsg("statement: %s", query_string)));
469

Bruce Momjian's avatar
Bruce Momjian committed
470
	if (log_parser_stats)
471 472
		ResetUsage();

473
	raw_parsetree_list = raw_parser(query_string);
474

475 476 477 478 479 480 481 482
	/* do log_statement tests for mod and ddl */
	if (log_statement == LOGSTMT_MOD ||
		log_statement == LOGSTMT_DDL)
	{
		foreach(parsetree_item, raw_parsetree_list)
		{
			Node	   *parsetree = (Node *) lfirst(parsetree_item);
			const char *commandTag;
Bruce Momjian's avatar
Bruce Momjian committed
483

484
			if (IsA(parsetree, ExplainStmt) &&
Bruce Momjian's avatar
Bruce Momjian committed
485 486 487
				((ExplainStmt *) parsetree)->analyze)
				parsetree = (Node *) (((ExplainStmt *) parsetree)->query);

488
			if (IsA(parsetree, PrepareStmt))
Bruce Momjian's avatar
Bruce Momjian committed
489 490
				parsetree = (Node *) (((PrepareStmt *) parsetree)->query);

491
			if (IsA(parsetree, SelectStmt))
Bruce Momjian's avatar
Bruce Momjian committed
492 493
				continue;		/* optimization for frequent command */

494 495 496 497 498 499
			if (log_statement == LOGSTMT_MOD &&
				(IsA(parsetree, InsertStmt) ||
				 IsA(parsetree, UpdateStmt) ||
				 IsA(parsetree, DeleteStmt) ||
				 IsA(parsetree, TruncateStmt) ||
				 (IsA(parsetree, CopyStmt) &&
Bruce Momjian's avatar
Bruce Momjian committed
500
				  ((CopyStmt *) parsetree)->is_from)))	/* COPY FROM */
501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519
			{
				ereport(LOG,
						(errmsg("statement: %s", query_string)));
				break;
			}
			commandTag = CreateCommandTag(parsetree);
			if (strncmp(commandTag, "CREATE ", strlen("CREATE ")) == 0 ||
				strncmp(commandTag, "ALTER ", strlen("ALTER ")) == 0 ||
				strncmp(commandTag, "DROP ", strlen("DROP ")) == 0 ||
				IsA(parsetree, GrantStmt) ||	/* GRANT or REVOKE */
				IsA(parsetree, CommentStmt))
			{
				ereport(LOG,
						(errmsg("statement: %s", query_string)));
				break;
			}
		}
	}

Bruce Momjian's avatar
Bruce Momjian committed
520
	if (log_parser_stats)
521
		ShowUsage("PARSER STATISTICS");
522 523 524 525 526

	return raw_parsetree_list;
}

/*
527 528
 * Given a raw parsetree (gram.y output), and optionally information about
 * types of parameter symbols ($n), perform parse analysis and rule rewriting.
529 530 531 532 533 534
 *
 * A list of Query nodes is returned, since either the analyzer or the
 * rewriter might expand one query to several.
 *
 * NOTE: for reasons mentioned above, this must be separate from raw parsing.
 */
535
List *
536
pg_analyze_and_rewrite(Node *parsetree, Oid *paramTypes, int numParams)
537 538 539
{
	List	   *querytree_list;

540 541
	/*
	 * (1) Perform parse analysis.
542
	 */
Bruce Momjian's avatar
Bruce Momjian committed
543
	if (log_parser_stats)
544 545
		ResetUsage();

546
	querytree_list = parse_analyze(parsetree, paramTypes, numParams);
547

Bruce Momjian's avatar
Bruce Momjian committed
548
	if (log_parser_stats)
549
		ShowUsage("PARSE ANALYSIS STATISTICS");
550

551 552
	/*
	 * (2) Rewrite the queries, as necessary
553 554 555 556 557 558 559 560 561 562 563 564 565
	 */
	querytree_list = pg_rewrite_queries(querytree_list);

	return querytree_list;
}

/*
 * Perform rewriting of a list of queries produced by parse analysis.
 */
List *
pg_rewrite_queries(List *querytree_list)
{
	List	   *new_list = NIL;
566
	ListCell   *list_item;
567 568 569 570 571

	if (log_parser_stats)
		ResetUsage();

	/*
Bruce Momjian's avatar
Bruce Momjian committed
572 573
	 * rewritten queries are collected in new_list.  Note there may be
	 * more or fewer than in the original list.
574
	 */
575
	foreach(list_item, querytree_list)
576
	{
577
		Query	   *querytree = (Query *) lfirst(list_item);
578

579
		if (Debug_print_parse)
580
			elog_node_display(DEBUG1, "parse tree", querytree,
581
							  Debug_pretty_print);
582 583 584

		if (querytree->commandType == CMD_UTILITY)
		{
585 586
			/* don't rewrite utilities, just dump 'em into new_list */
			new_list = lappend(new_list, querytree);
587
		}
588
		else
589
		{
590
			/* rewrite regular queries */
591 592
			List	   *rewritten = QueryRewrite(querytree);

593
			new_list = list_concat(new_list, rewritten);
594 595 596 597 598
		}
	}

	querytree_list = new_list;

Bruce Momjian's avatar
Bruce Momjian committed
599
	if (log_parser_stats)
600
		ShowUsage("REWRITER STATISTICS");
601

602
#ifdef COPY_PARSE_PLAN_TREES
603 604 605 606 607

	/*
	 * Optional debugging check: pass querytree output through
	 * copyObject()
	 */
608 609
	new_list = (List *) copyObject(querytree_list);
	/* This checks both copyObject() and the equal() routines... */
610
	if (!equal(new_list, querytree_list))
611
		elog(WARNING, "copyObject() failed to produce an equal parse tree");
612 613
	else
		querytree_list = new_list;
614 615
#endif

616
	if (Debug_print_rewritten)
617
		elog_node_display(DEBUG1, "rewritten parse tree", querytree_list,
618
						  Debug_pretty_print);
619

620 621
	return querytree_list;
}
622 623


624
/* Generate a plan for a single already-rewritten query. */
625
Plan *
626
pg_plan_query(Query *querytree, ParamListInfo boundParams)
627 628
{
	Plan	   *plan;
629

630 631 632
	/* Utility commands have no plans. */
	if (querytree->commandType == CMD_UTILITY)
		return NULL;
633

Bruce Momjian's avatar
Bruce Momjian committed
634
	if (log_planner_stats)
635
		ResetUsage();
636

637
	/* call the optimizer */
638
	plan = planner(querytree, false, 0, boundParams);
639

Bruce Momjian's avatar
Bruce Momjian committed
640
	if (log_planner_stats)
641
		ShowUsage("PLANNER STATISTICS");
642

643 644 645
#ifdef COPY_PARSE_PLAN_TREES
	/* Optional debugging check: pass plan output through copyObject() */
	{
646
		Plan	   *new_plan = (Plan *) copyObject(plan);
647

648 649
		/*
		 * equal() currently does not have routines to compare Plan nodes,
650 651 652 653
		 * so don't try to test equality here.  Perhaps fix someday?
		 */
#ifdef NOT_USED
		/* This checks both copyObject() and the equal() routines... */
654
		if (!equal(new_plan, plan))
655
			elog(WARNING, "copyObject() failed to produce an equal plan tree");
656 657 658 659 660 661
		else
#endif
			plan = new_plan;
	}
#endif

662 663
	/*
	 * Print plan if debugging.
664
	 */
665
	if (Debug_print_plan)
666
		elog_node_display(DEBUG1, "plan", plan, Debug_pretty_print);
667

668
	return plan;
669 670
}

671 672
/*
 * Generate plans for a list of already-rewritten queries.
673
 *
674 675 676 677 678 679 680 681 682
 * If needSnapshot is TRUE, we haven't yet set a snapshot for the current
 * query.  A snapshot must be set before invoking the planner, since it
 * might try to evaluate user-defined functions.  But we must not set a
 * snapshot if the list contains only utility statements, because some
 * utility statements depend on not having frozen the snapshot yet.
 * (We assume that such statements cannot appear together with plannable
 * statements in the rewriter's output.)
 */
List *
683 684
pg_plan_queries(List *querytrees, ParamListInfo boundParams,
				bool needSnapshot)
685 686
{
	List	   *plan_list = NIL;
687
	ListCell   *query_list;
688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705

	foreach(query_list, querytrees)
	{
		Query	   *query = (Query *) lfirst(query_list);
		Plan	   *plan;

		if (query->commandType == CMD_UTILITY)
		{
			/* Utility commands have no plans. */
			plan = NULL;
		}
		else
		{
			if (needSnapshot)
			{
				SetQuerySnapshot();
				needSnapshot = false;
			}
706
			plan = pg_plan_query(query, boundParams);
707 708 709 710 711 712 713 714 715 716
		}

		plan_list = lappend(plan_list, plan);
	}

	return plan_list;
}


/*
717
 * exec_simple_query
718
 *
719
 * Execute a "simple Query" protocol message.
720
 */
721
static void
722
exec_simple_query(const char *query_string)
723
{
Bruce Momjian's avatar
Bruce Momjian committed
724
	CommandDest dest = whereToSendOutput;
725
	MemoryContext oldcontext;
726 727
	List	   *parsetree_list;
	ListCell   *parsetree_item;
Bruce Momjian's avatar
Bruce Momjian committed
728 729
	struct timeval start_t,
				stop_t;
Bruce Momjian's avatar
Bruce Momjian committed
730
	bool		save_log_duration = log_duration;
731
	int			save_log_min_duration_statement = log_min_duration_statement;
732
	bool		save_log_statement_stats = log_statement_stats;
733

734 735 736
	/*
	 * Report query to various monitoring facilities.
	 */
737
	debug_query_string = query_string;
738

739 740
	pgstat_report_activity(query_string);

741
	/*
Bruce Momjian's avatar
Bruce Momjian committed
742 743 744 745
	 * We use save_log_* so "SET log_duration = true"  and "SET
	 * log_min_duration_statement = true" don't report incorrect time
	 * because gettimeofday() wasn't called. Similarly,
	 * log_statement_stats has to be captured once.
746
	 */
747
	if (save_log_duration || save_log_min_duration_statement != -1)
748
		gettimeofday(&start_t, NULL);
749

750 751 752
	if (save_log_statement_stats)
		ResetUsage();

753
	/*
754 755 756 757
	 * Start up a transaction command.	All queries generated by the
	 * query_string will be in this same command block, *unless* we find a
	 * BEGIN/COMMIT/ABORT statement; we have to force a new xact command
	 * after one of those, else bad things will happen in xact.c. (Note
758
	 * that this will normally change current memory context.)
759 760
	 */
	start_xact_command();
761 762

	/*
Bruce Momjian's avatar
Bruce Momjian committed
763 764 765 766
	 * Zap any pre-existing unnamed statement.	(While not strictly
	 * necessary, it seems best to define simple-Query mode as if it used
	 * the unnamed statement and portal; this ensures we recover any
	 * storage used by prior unnamed operations.)
767 768 769 770 771 772 773 774
	 */
	unnamed_stmt_pstmt = NULL;
	if (unnamed_stmt_context)
	{
		DropDependentPortals(unnamed_stmt_context);
		MemoryContextDelete(unnamed_stmt_context);
	}
	unnamed_stmt_context = NULL;
775

776 777 778
	/*
	 * Switch to appropriate context for constructing parsetrees.
	 */
779
	oldcontext = MemoryContextSwitchTo(MessageContext);
780

781 782
	QueryContext = CurrentMemoryContext;

Bruce Momjian's avatar
Bruce Momjian committed
783
	/*
784 785
	 * Do basic parsing of the query or queries (this should be safe even
	 * if we are in aborted transaction state!)
786
	 */
787
	parsetree_list = pg_parse_query(query_string);
788

789
	/*
790
	 * Switch back to transaction context to enter the loop.
791 792 793 794
	 */
	MemoryContextSwitchTo(oldcontext);

	/*
795
	 * Run through the raw parsetree(s) and process each one.
796
	 */
797
	foreach(parsetree_item, parsetree_list)
798
	{
799
		Node	   *parsetree = (Node *) lfirst(parsetree_item);
800 801
		const char *commandTag;
		char		completionTag[COMPLETION_TAG_BUFSIZE];
802
		List	   *querytree_list,
803 804
				   *plantree_list;
		Portal		portal;
805 806
		DestReceiver *receiver;
		int16		format;
807

808
		/*
Bruce Momjian's avatar
Bruce Momjian committed
809 810 811 812
		 * Get the command name for use in status display (it also becomes
		 * the default completion tag, down inside PortalRun).	Set
		 * ps_status and do any special start-of-SQL-command processing
		 * needed by the destination.
813 814 815 816 817
		 */
		commandTag = CreateCommandTag(parsetree);

		set_ps_display(commandTag);

818
		BeginCommand(commandTag, dest);
819

820
		/*
821
		 * If we are in an aborted transaction, reject all commands except
822 823
		 * COMMIT/ABORT.  It is important that this test occur before we
		 * try to do parse analysis, rewrite, or planning, since all those
824 825 826
		 * phases try to do database accesses, which may fail in abort
		 * state. (It might be safe to allow some additional utility
		 * commands in this state, but not many...)
827 828
		 */
		if (IsAbortedTransactionBlockState())
829
		{
830
			bool		allowit = false;
831

832
			if (IsA(parsetree, TransactionStmt))
833 834 835
			{
				TransactionStmt *stmt = (TransactionStmt *) parsetree;

836
				if (stmt->kind == TRANS_STMT_COMMIT ||
837 838
					stmt->kind == TRANS_STMT_ROLLBACK ||
					stmt->kind == TRANS_STMT_ROLLBACK_TO)
839
					allowit = true;
840
			}
841

842
			if (!allowit)
843 844 845
				ereport(ERROR,
						(errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
						 errmsg("current transaction is aborted, "
Bruce Momjian's avatar
Bruce Momjian committed
846
					"commands ignored until end of transaction block")));
847
		}
848

849
		/* Make sure we are in a transaction command */
850
		start_xact_command();
851

852
		/* If we got a cancel signal in parsing or prior command, quit */
853
		CHECK_FOR_INTERRUPTS();
854 855

		/*
856
		 * OK to analyze, rewrite, and plan this query.
857
		 *
858 859
		 * Switch to appropriate context for constructing querytrees (again,
		 * these must outlive the execution context).
860
		 */
861
		oldcontext = MemoryContextSwitchTo(MessageContext);
862

863
		querytree_list = pg_analyze_and_rewrite(parsetree, NULL, 0);
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
864

865
		plantree_list = pg_plan_queries(querytree_list, NULL, true);
866 867 868 869

		/* If we got a cancel signal in analysis or planning, quit */
		CHECK_FOR_INTERRUPTS();

870
		/*
Bruce Momjian's avatar
Bruce Momjian committed
871 872
		 * Create unnamed portal to run the query or queries in. If there
		 * already is one, silently drop it.
873
		 */
874
		portal = CreatePortal("", true, true);
875

876 877 878 879 880 881
		PortalDefineQuery(portal,
						  query_string,
						  commandTag,
						  querytree_list,
						  plantree_list,
						  MessageContext);
882

883
		/*
884
		 * Start the portal.  No parameters here.
885 886
		 */
		PortalStart(portal, NULL);
887

888 889
		/*
		 * Select the appropriate output format: text unless we are doing
Bruce Momjian's avatar
Bruce Momjian committed
890 891 892
		 * a FETCH from a binary cursor.  (Pretty grotty to have to do
		 * this here --- but it avoids grottiness in other places.	Ah,
		 * the joys of backward compatibility...)
893 894 895 896 897 898 899 900 901 902 903 904
		 */
		format = 0;				/* TEXT is default */
		if (IsA(parsetree, FetchStmt))
		{
			FetchStmt  *stmt = (FetchStmt *) parsetree;

			if (!stmt->ismove)
			{
				Portal		fportal = GetPortalByName(stmt->portalname);

				if (PortalIsValid(fportal) &&
					(fportal->cursorOptions & CURSOR_OPT_BINARY))
Bruce Momjian's avatar
Bruce Momjian committed
905
					format = 1; /* BINARY */
906 907 908 909 910 911 912 913 914 915 916 917 918 919 920
			}
		}
		PortalSetResultFormat(portal, 1, &format);

		/*
		 * Now we can create the destination receiver object.
		 */
		receiver = CreateDestReceiver(dest, portal);

		/*
		 * Switch back to transaction context for execution.
		 */
		MemoryContextSwitchTo(oldcontext);

		/*
Bruce Momjian's avatar
Bruce Momjian committed
921 922
		 * Run the portal to completion, and then drop it (and the
		 * receiver).
923
		 */
924 925
		(void) PortalRun(portal,
						 FETCH_ALL,
926 927
						 receiver,
						 receiver,
928
						 completionTag);
929

930
		(*receiver->rDestroy) (receiver);
931

932
		PortalDrop(portal, false);
933

934
		if (IsA(parsetree, TransactionStmt))
935
		{
936
			/*
Bruce Momjian's avatar
Bruce Momjian committed
937 938 939
			 * If this was a transaction control statement, commit it. We
			 * will start a new xact command for the next command (if
			 * any).
940
			 */
941
			finish_xact_command();
942
		}
943
		else if (lnext(parsetree_item) == NULL)
944
		{
945
			/*
Bruce Momjian's avatar
Bruce Momjian committed
946 947 948 949 950 951 952 953 954
			 * If this is the last parsetree of the query string, close
			 * down transaction statement before reporting
			 * command-complete.  This is so that any end-of-transaction
			 * errors are reported before the command-complete message is
			 * issued, to avoid confusing clients who will expect either a
			 * command-complete message or an error, not one and then the
			 * other.  But for compatibility with historical Postgres
			 * behavior, we do not force a transaction boundary between
			 * queries appearing in a single query string.
955
			 */
956
			finish_xact_command();
957
		}
958
		else
959
		{
960
			/*
Bruce Momjian's avatar
Bruce Momjian committed
961 962
			 * We need a CommandCounterIncrement after every query, except
			 * those that start or end a transaction block.
963 964
			 */
			CommandCounterIncrement();
965
		}
966 967 968

		/*
		 * Tell client that we're done with this query.  Note we emit
Bruce Momjian's avatar
Bruce Momjian committed
969 970 971 972
		 * exactly one EndCommand report for each raw parsetree, thus one
		 * for each SQL command the client sent, regardless of rewriting.
		 * (But a command aborted by error will not send an EndCommand
		 * report at all.)
973
		 */
974
		EndCommand(completionTag, dest);
975
	}							/* end loop over parsetrees */
976

977 978 979 980 981
	/*
	 * Close down transaction statement, if one is open.
	 */
	finish_xact_command();

982 983 984
	/*
	 * If there were no parsetrees, return EmptyQueryResponse message.
	 */
985
	if (!parsetree_list)
986 987
		NullCommand(dest);

988
	QueryContext = NULL;
989

990
	/*
Bruce Momjian's avatar
Bruce Momjian committed
991 992
	 * Combine processing here as we need to calculate the query duration
	 * in both instances.
993
	 */
994
	if (save_log_duration || save_log_min_duration_statement != -1)
995
	{
Bruce Momjian's avatar
Bruce Momjian committed
996 997
		long		usecs;

998
		gettimeofday(&stop_t, NULL);
999 1000 1001 1002 1003
		if (stop_t.tv_usec < start_t.tv_usec)
		{
			stop_t.tv_sec--;
			stop_t.tv_usec += 1000000;
		}
1004 1005
		usecs = (long) (stop_t.tv_sec - start_t.tv_sec) * 1000000 + (long) (stop_t.tv_usec - start_t.tv_usec);

1006 1007 1008
		if (save_log_duration)
			ereport(LOG,
					(errmsg("duration: %ld.%03ld ms",
Bruce Momjian's avatar
Bruce Momjian committed
1009 1010 1011
						(long) ((stop_t.tv_sec - start_t.tv_sec) * 1000 +
							  (stop_t.tv_usec - start_t.tv_usec) / 1000),
					 (long) (stop_t.tv_usec - start_t.tv_usec) % 1000)));
1012

Bruce Momjian's avatar
Bruce Momjian committed
1013
		/*
Bruce Momjian's avatar
Bruce Momjian committed
1014 1015
		 * Output a duration_statement to the log if the query has
		 * exceeded the min duration, or if we are to print all durations.
1016
		 */
1017 1018 1019
		if (save_log_min_duration_statement == 0 ||
			(save_log_min_duration_statement > 0 &&
			 usecs >= save_log_min_duration_statement * 1000))
1020
			ereport(LOG,
1021
					(errmsg("duration: %ld.%03ld ms  statement: %s",
Bruce Momjian's avatar
Bruce Momjian committed
1022 1023 1024
						(long) ((stop_t.tv_sec - start_t.tv_sec) * 1000 +
							  (stop_t.tv_usec - start_t.tv_usec) / 1000),
						(long) (stop_t.tv_usec - start_t.tv_usec) % 1000,
1025
							query_string)));
1026
	}
1027

1028 1029 1030
	if (save_log_statement_stats)
		ShowUsage("QUERY STATISTICS");

1031
	debug_query_string = NULL;
1032 1033
}

1034 1035 1036 1037 1038 1039 1040 1041
/*
 * exec_parse_message
 *
 * Execute a "Parse" protocol message.
 */
static void
exec_parse_message(const char *query_string,	/* string to execute */
				   const char *stmt_name,		/* name for prepared stmt */
Bruce Momjian's avatar
Bruce Momjian committed
1042 1043
				   Oid *paramTypes,		/* parameter types */
				   int numParams)		/* number of parameters */
1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075
{
	MemoryContext oldcontext;
	List	   *parsetree_list;
	const char *commandTag;
	List	   *querytree_list,
			   *plantree_list,
			   *param_list;
	bool		is_named;
	bool		save_log_statement_stats = log_statement_stats;

	/*
	 * Report query to various monitoring facilities.
	 */
	debug_query_string = query_string;

	pgstat_report_activity(query_string);

	set_ps_display("PARSE");

	if (save_log_statement_stats)
		ResetUsage();

	/*
	 * Start up a transaction command so we can run parse analysis etc.
	 * (Note that this will normally change current memory context.)
	 * Nothing happens if we are already in one.
	 */
	start_xact_command();

	/*
	 * Switch to appropriate context for constructing parsetrees.
	 *
Bruce Momjian's avatar
Bruce Momjian committed
1076 1077 1078 1079 1080 1081 1082 1083 1084 1085
	 * We have two strategies depending on whether the prepared statement is
	 * named or not.  For a named prepared statement, we do parsing in
	 * MessageContext and copy the finished trees into the prepared
	 * statement's private context; then the reset of MessageContext
	 * releases temporary space used by parsing and planning.  For an
	 * unnamed prepared statement, we assume the statement isn't going to
	 * hang around long, so getting rid of temp space quickly is probably
	 * not worth the costs of copying parse/plan trees.  So in this case,
	 * we set up a special context for the unnamed statement, and do all
	 * the parsing/planning therein.
1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121
	 */
	is_named = (stmt_name[0] != '\0');
	if (is_named)
	{
		/* Named prepared statement --- parse in MessageContext */
		oldcontext = MemoryContextSwitchTo(MessageContext);
	}
	else
	{
		/* Unnamed prepared statement --- release any prior unnamed stmt */
		unnamed_stmt_pstmt = NULL;
		if (unnamed_stmt_context)
		{
			DropDependentPortals(unnamed_stmt_context);
			MemoryContextDelete(unnamed_stmt_context);
		}
		unnamed_stmt_context = NULL;
		/* create context for parsing/planning */
		unnamed_stmt_context =
			AllocSetContextCreate(TopMemoryContext,
								  "unnamed prepared statement",
								  ALLOCSET_DEFAULT_MINSIZE,
								  ALLOCSET_DEFAULT_INITSIZE,
								  ALLOCSET_DEFAULT_MAXSIZE);
		oldcontext = MemoryContextSwitchTo(unnamed_stmt_context);
	}

	QueryContext = CurrentMemoryContext;

	/*
	 * Do basic parsing of the query or queries (this should be safe even
	 * if we are in aborted transaction state!)
	 */
	parsetree_list = pg_parse_query(query_string);

	/*
Bruce Momjian's avatar
Bruce Momjian committed
1122 1123 1124
	 * We only allow a single user statement in a prepared statement. This
	 * is mainly to keep the protocol simple --- otherwise we'd need to
	 * worry about multiple result tupdescs and things like that.
1125
	 */
1126
	if (list_length(parsetree_list) > 1)
1127 1128 1129
		ereport(ERROR,
				(errcode(ERRCODE_SYNTAX_ERROR),
				 errmsg("cannot insert multiple commands into a prepared statement")));
1130 1131 1132

	if (parsetree_list != NIL)
	{
1133
		Node	   *parsetree = (Node *) linitial(parsetree_list);
Bruce Momjian's avatar
Bruce Momjian committed
1134
		int			i;
1135 1136 1137 1138 1139 1140 1141 1142

		/*
		 * Get the command name for possible use in status display.
		 */
		commandTag = CreateCommandTag(parsetree);

		/*
		 * If we are in an aborted transaction, reject all commands except
Bruce Momjian's avatar
Bruce Momjian committed
1143 1144 1145 1146
		 * COMMIT/ROLLBACK.  It is important that this test occur before
		 * we try to do parse analysis, rewrite, or planning, since all
		 * those phases try to do database accesses, which may fail in
		 * abort state. (It might be safe to allow some additional utility
1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157
		 * commands in this state, but not many...)
		 */
		if (IsAbortedTransactionBlockState())
		{
			bool		allowit = false;

			if (IsA(parsetree, TransactionStmt))
			{
				TransactionStmt *stmt = (TransactionStmt *) parsetree;

				if (stmt->kind == TRANS_STMT_COMMIT ||
1158 1159
					stmt->kind == TRANS_STMT_ROLLBACK ||
					stmt->kind == TRANS_STMT_ROLLBACK_TO)
1160 1161 1162 1163
					allowit = true;
			}

			if (!allowit)
1164 1165 1166
				ereport(ERROR,
						(errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
						 errmsg("current transaction is aborted, "
Bruce Momjian's avatar
Bruce Momjian committed
1167
					"commands ignored until end of transaction block")));
1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188
		}

		/*
		 * OK to analyze, rewrite, and plan this query.  Note that the
		 * originally specified parameter set is not required to be
		 * complete, so we have to use parse_analyze_varparams().
		 */
		if (log_parser_stats)
			ResetUsage();

		querytree_list = parse_analyze_varparams(parsetree,
												 &paramTypes,
												 &numParams);

		/*
		 * Check all parameter types got determined, and convert array
		 * representation to a list for storage.
		 */
		param_list = NIL;
		for (i = 0; i < numParams; i++)
		{
Bruce Momjian's avatar
Bruce Momjian committed
1189
			Oid			ptype = paramTypes[i];
1190 1191

			if (ptype == InvalidOid || ptype == UNKNOWNOID)
1192 1193
				ereport(ERROR,
						(errcode(ERRCODE_INDETERMINATE_DATATYPE),
Bruce Momjian's avatar
Bruce Momjian committed
1194 1195
				 errmsg("could not determine data type of parameter $%d",
						i + 1)));
1196
			param_list = lappend_oid(param_list, ptype);
1197 1198 1199 1200 1201 1202 1203
		}

		if (log_parser_stats)
			ShowUsage("PARSE ANALYSIS STATISTICS");

		querytree_list = pg_rewrite_queries(querytree_list);

1204 1205 1206 1207 1208 1209 1210 1211
		/*
		 * If this is the unnamed statement and it has parameters, defer
		 * query planning until Bind.  Otherwise do it now.
		 */
		if (!is_named && numParams > 0)
			plantree_list = NIL;
		else
			plantree_list = pg_plan_queries(querytree_list, NULL, true);
1212 1213 1214
	}
	else
	{
Bruce Momjian's avatar
Bruce Momjian committed
1215
		/* Empty input string.	This is legal. */
1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258
		commandTag = NULL;
		querytree_list = NIL;
		plantree_list = NIL;
		param_list = NIL;
	}

	/* If we got a cancel signal in analysis or planning, quit */
	CHECK_FOR_INTERRUPTS();

	/*
	 * Store the query as a prepared statement.  See above comments.
	 */
	if (is_named)
	{
		StorePreparedStatement(stmt_name,
							   query_string,
							   commandTag,
							   querytree_list,
							   plantree_list,
							   param_list);
	}
	else
	{
		PreparedStatement *pstmt;

		pstmt = (PreparedStatement *) palloc0(sizeof(PreparedStatement));
		/* query_string needs to be copied into unnamed_stmt_context */
		pstmt->query_string = pstrdup(query_string);
		/* the rest is there already */
		pstmt->commandTag = commandTag;
		pstmt->query_list = querytree_list;
		pstmt->plan_list = plantree_list;
		pstmt->argtype_list = param_list;
		pstmt->context = unnamed_stmt_context;
		/* Now the unnamed statement is complete and valid */
		unnamed_stmt_pstmt = pstmt;
	}

	MemoryContextSwitchTo(oldcontext);

	QueryContext = NULL;

	/*
Bruce Momjian's avatar
Bruce Momjian committed
1259 1260 1261 1262
	 * We do NOT close the open transaction command here; that only
	 * happens when the client sends Sync.	Instead, do
	 * CommandCounterIncrement just in case something happened during
	 * parse/plan.
1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287
	 */
	CommandCounterIncrement();

	/*
	 * Send ParseComplete.
	 */
	if (whereToSendOutput == Remote)
		pq_putemptymessage('1');

	if (save_log_statement_stats)
		ShowUsage("PARSE MESSAGE STATISTICS");

	debug_query_string = NULL;
}

/*
 * exec_bind_message
 *
 * Process a "Bind" message to create a portal from a prepared statement
 */
static void
exec_bind_message(StringInfo input_message)
{
	const char *portal_name;
	const char *stmt_name;
1288 1289
	int			numPFormats;
	int16	   *pformats = NULL;
1290
	int			numParams;
1291 1292 1293
	int			numRFormats;
	int16	   *rformats = NULL;
	int			i;
1294 1295 1296
	PreparedStatement *pstmt;
	Portal		portal;
	ParamListInfo params;
1297
	bool		isaborted = IsAbortedTransactionBlockState();
1298 1299 1300 1301 1302 1303

	pgstat_report_activity("<BIND>");

	set_ps_display("BIND");

	/*
Bruce Momjian's avatar
Bruce Momjian committed
1304 1305 1306
	 * Start up a transaction command so we can call functions etc. (Note
	 * that this will normally change current memory context.) Nothing
	 * happens if we are already in one.
1307 1308 1309
	 */
	start_xact_command();

1310 1311 1312
	/* Switch back to message context */
	MemoryContextSwitchTo(MessageContext);

1313 1314 1315 1316
	/* Get the fixed part of the message */
	portal_name = pq_getmsgstring(input_message);
	stmt_name = pq_getmsgstring(input_message);

1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329
	/* Get the parameter format codes */
	numPFormats = pq_getmsgint(input_message, 2);
	if (numPFormats > 0)
	{
		pformats = (int16 *) palloc(numPFormats * sizeof(int16));
		for (i = 0; i < numPFormats; i++)
			pformats[i] = pq_getmsgint(input_message, 2);
	}

	/* Get the parameter value count */
	numParams = pq_getmsgint(input_message, 2);

	if (numPFormats > 1 && numPFormats != numParams)
1330 1331
		ereport(ERROR,
				(errcode(ERRCODE_PROTOCOL_VIOLATION),
Bruce Momjian's avatar
Bruce Momjian committed
1332 1333
		errmsg("bind message has %d parameter formats but %d parameters",
			   numPFormats, numParams)));
1334 1335 1336 1337 1338 1339 1340 1341 1342

	/* Find prepared statement */
	if (stmt_name[0] != '\0')
		pstmt = FetchPreparedStatement(stmt_name, true);
	else
	{
		/* special-case the unnamed statement */
		pstmt = unnamed_stmt_pstmt;
		if (!pstmt)
1343 1344
			ereport(ERROR,
					(errcode(ERRCODE_UNDEFINED_PSTATEMENT),
Bruce Momjian's avatar
Bruce Momjian committed
1345
				   errmsg("unnamed prepared statement does not exist")));
1346 1347
	}

1348
	if (numParams != list_length(pstmt->argtype_list))
1349 1350 1351
		ereport(ERROR,
				(errcode(ERRCODE_PROTOCOL_VIOLATION),
				 errmsg("bind message supplies %d parameters, but prepared statement \"%s\" requires %d",
Bruce Momjian's avatar
Bruce Momjian committed
1352
			   numParams, stmt_name, list_length(pstmt->argtype_list))));
1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365

	/*
	 * Create the portal.  Allow silent replacement of an existing portal
	 * only if the unnamed portal is specified.
	 */
	if (portal_name[0] == '\0')
		portal = CreatePortal(portal_name, true, true);
	else
		portal = CreatePortal(portal_name, false, false);

	/*
	 * Fetch parameters, if any, and store in the portal's memory context.
	 *
Bruce Momjian's avatar
Bruce Momjian committed
1366 1367 1368
	 * In an aborted transaction, we can't risk calling user-defined
	 * functions, but we can't fail to Bind either, so bind all parameters
	 * to null values.
1369 1370 1371
	 */
	if (numParams > 0)
	{
1372
		ListCell   *l;
1373 1374 1375 1376 1377 1378 1379
		MemoryContext oldContext;

		oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));

		params = (ParamListInfo)
			palloc0((numParams + 1) * sizeof(ParamListInfoData));

1380
		i = 0;
1381 1382
		foreach(l, pstmt->argtype_list)
		{
1383
			Oid			ptype = lfirst_oid(l);
1384
			int32		plength;
1385 1386
			bool		isNull;

1387 1388 1389
			plength = pq_getmsgint(input_message, 4);
			isNull = (plength == -1);

1390 1391
			if (!isNull)
			{
1392
				const char *pvalue = pq_getmsgbytes(input_message, plength);
1393 1394

				if (isaborted)
1395 1396
				{
					/* We don't bother to check the format in this case */
1397
					isNull = true;
1398
				}
1399 1400
				else
				{
Bruce Momjian's avatar
Bruce Momjian committed
1401
					int16		pformat;
1402
					StringInfoData pbuf;
Bruce Momjian's avatar
Bruce Momjian committed
1403
					char		csave;
1404 1405 1406 1407 1408 1409

					if (numPFormats > 1)
						pformat = pformats[i];
					else if (numPFormats > 0)
						pformat = pformats[0];
					else
Bruce Momjian's avatar
Bruce Momjian committed
1410
						pformat = 0;	/* default = text */
1411

1412
					/*
Bruce Momjian's avatar
Bruce Momjian committed
1413 1414 1415 1416 1417 1418 1419
					 * Rather than copying data around, we just set up a
					 * phony StringInfo pointing to the correct portion of
					 * the message buffer.	We assume we can scribble on
					 * the message buffer so as to maintain the convention
					 * that StringInfos have a trailing null.  This is
					 * grotty but is a big win when dealing with very
					 * large parameter strings.
1420 1421 1422 1423 1424 1425 1426 1427 1428
					 */
					pbuf.data = (char *) pvalue;
					pbuf.maxlen = plength + 1;
					pbuf.len = plength;
					pbuf.cursor = 0;

					csave = pbuf.data[plength];
					pbuf.data[plength] = '\0';

1429 1430
					if (pformat == 0)
					{
1431 1432
						Oid			typinput;
						Oid			typioparam;
1433 1434
						char	   *pstring;

1435
						getTypeInputInfo(ptype, &typinput, &typioparam);
Bruce Momjian's avatar
Bruce Momjian committed
1436

1437
						/*
Bruce Momjian's avatar
Bruce Momjian committed
1438 1439
						 * We have to do encoding conversion before
						 * calling the typinput routine.
1440 1441 1442 1443 1444
						 */
						pstring = (char *)
							pg_client_to_server((unsigned char *) pbuf.data,
												plength);
						params[i].value =
1445
							OidFunctionCall3(typinput,
1446
											 CStringGetDatum(pstring),
1447
											 ObjectIdGetDatum(typioparam),
1448 1449 1450 1451 1452 1453 1454
											 Int32GetDatum(-1));
						/* Free result of encoding conversion, if any */
						if (pstring != pbuf.data)
							pfree(pstring);
					}
					else if (pformat == 1)
					{
1455 1456
						Oid			typreceive;
						Oid			typioparam;
1457

Bruce Momjian's avatar
Bruce Momjian committed
1458 1459 1460 1461
						/*
						 * Call the parameter type's binary input
						 * converter
						 */
1462
						getTypeBinaryInputInfo(ptype, &typreceive, &typioparam);
1463 1464

						params[i].value =
1465
							OidFunctionCall2(typreceive,
1466
											 PointerGetDatum(&pbuf),
Bruce Momjian's avatar
Bruce Momjian committed
1467
										   ObjectIdGetDatum(typioparam));
1468 1469 1470

						/* Trouble if it didn't eat the whole buffer */
						if (pbuf.cursor != pbuf.len)
1471 1472 1473
							ereport(ERROR,
									(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
									 errmsg("incorrect binary data format in bind parameter %d",
Bruce Momjian's avatar
Bruce Momjian committed
1474
											i + 1)));
1475 1476 1477
					}
					else
					{
1478 1479 1480 1481
						ereport(ERROR,
								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
								 errmsg("unsupported format code: %d",
										pformat)));
1482
					}
1483 1484 1485

					/* Restore message buffer contents */
					pbuf.data[plength] = csave;
1486 1487
				}
			}
1488

1489 1490
			params[i].kind = PARAM_NUM;
			params[i].id = i + 1;
1491
			params[i].ptype = ptype;
1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503
			params[i].isnull = isNull;

			i++;
		}

		params[i].kind = PARAM_INVALID;

		MemoryContextSwitchTo(oldContext);
	}
	else
		params = NULL;

1504 1505 1506 1507 1508 1509 1510 1511 1512
	/* Get the result format codes */
	numRFormats = pq_getmsgint(input_message, 2);
	if (numRFormats > 0)
	{
		rformats = (int16 *) palloc(numRFormats * sizeof(int16));
		for (i = 0; i < numRFormats; i++)
			rformats[i] = pq_getmsgint(input_message, 2);
	}

1513 1514 1515
	pq_getmsgend(input_message);

	/*
1516 1517 1518
	 * If we didn't plan the query before, do it now.  This allows the
	 * planner to make use of the concrete parameter values we now have.
	 *
Bruce Momjian's avatar
Bruce Momjian committed
1519 1520
	 * This happens only for unnamed statements, and so switching into the
	 * statement context for planning is correct (see notes in
1521
	 * exec_parse_message).
1522
	 */
1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541
	if (pstmt->plan_list == NIL && pstmt->query_list != NIL &&
		!isaborted)
	{
		MemoryContext oldContext = MemoryContextSwitchTo(pstmt->context);

		pstmt->plan_list = pg_plan_queries(pstmt->query_list, params, true);
		MemoryContextSwitchTo(oldContext);
	}

	/*
	 * Define portal and start execution.
	 */
	PortalDefineQuery(portal,
					  pstmt->query_string,
					  pstmt->commandTag,
					  pstmt->query_list,
					  pstmt->plan_list,
					  pstmt->context);

1542 1543
	PortalStart(portal, params);

1544 1545 1546 1547 1548
	/*
	 * Apply the result format requests to the portal.
	 */
	PortalSetResultFormat(portal, numRFormats, rformats);

1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561
	/*
	 * Send BindComplete.
	 */
	if (whereToSendOutput == Remote)
		pq_putemptymessage('2');
}

/*
 * exec_execute_message
 *
 * Process an "Execute" message for a portal
 */
static void
1562
exec_execute_message(const char *portal_name, long max_rows)
1563
{
Bruce Momjian's avatar
Bruce Momjian committed
1564
	CommandDest dest;
1565
	DestReceiver *receiver;
1566 1567 1568 1569 1570 1571 1572 1573 1574
	Portal		portal;
	bool		is_trans_stmt = false;
	bool		is_trans_exit = false;
	bool		completed;
	char		completionTag[COMPLETION_TAG_BUFSIZE];

	/* Adjust destination to tell printtup.c what to do */
	dest = whereToSendOutput;
	if (dest == Remote)
1575
		dest = RemoteExecute;
1576 1577 1578

	portal = GetPortalByName(portal_name);
	if (!PortalIsValid(portal))
1579 1580 1581
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_CURSOR),
				 errmsg("portal \"%s\" does not exist", portal_name)));
1582 1583

	/*
Bruce Momjian's avatar
Bruce Momjian committed
1584 1585
	 * If the original query was a null string, just return
	 * EmptyQueryResponse.
1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609
	 */
	if (portal->commandTag == NULL)
	{
		Assert(portal->parseTrees == NIL);
		NullCommand(dest);
		return;
	}

	if (portal->sourceText)
	{
		debug_query_string = portal->sourceText;
		pgstat_report_activity(portal->sourceText);
	}
	else
	{
		debug_query_string = "execute message";
		pgstat_report_activity("<EXECUTE>");
	}

	set_ps_display(portal->commandTag);

	BeginCommand(portal->commandTag, dest);

	/* Check for transaction-control commands */
1610
	if (list_length(portal->parseTrees) == 1)
1611
	{
1612
		Query	   *query = (Query *) linitial(portal->parseTrees);
1613 1614 1615 1616 1617 1618 1619 1620 1621

		if (query->commandType == CMD_UTILITY &&
			query->utilityStmt != NULL &&
			IsA(query->utilityStmt, TransactionStmt))
		{
			TransactionStmt *stmt = (TransactionStmt *) query->utilityStmt;

			is_trans_stmt = true;
			if (stmt->kind == TRANS_STMT_COMMIT ||
1622 1623
				stmt->kind == TRANS_STMT_ROLLBACK ||
				stmt->kind == TRANS_STMT_ROLLBACK_TO)
1624 1625 1626 1627
				is_trans_exit = true;
		}
	}

1628
	/*
Bruce Momjian's avatar
Bruce Momjian committed
1629 1630 1631
	 * Create dest receiver in MessageContext (we don't want it in
	 * transaction context, because that may get deleted if portal
	 * contains VACUUM).
1632 1633 1634
	 */
	receiver = CreateDestReceiver(dest, portal);

1635
	/*
Bruce Momjian's avatar
Bruce Momjian committed
1636 1637
	 * Ensure we are in a transaction command (this should normally be the
	 * case already due to prior BIND).
1638 1639 1640 1641 1642 1643 1644 1645 1646 1647
	 */
	start_xact_command();

	/*
	 * If we are in aborted transaction state, the only portals we can
	 * actually run are those containing COMMIT or ROLLBACK commands.
	 */
	if (IsAbortedTransactionBlockState())
	{
		if (!is_trans_exit)
1648 1649 1650
			ereport(ERROR,
					(errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
					 errmsg("current transaction is aborted, "
Bruce Momjian's avatar
Bruce Momjian committed
1651
					"commands ignored until end of transaction block")));
1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664
	}

	/* Check for cancel signal before we start execution */
	CHECK_FOR_INTERRUPTS();

	/*
	 * Okay to run the portal.
	 */
	if (max_rows <= 0)
		max_rows = FETCH_ALL;

	completed = PortalRun(portal,
						  max_rows,
1665 1666
						  receiver,
						  receiver,
1667 1668
						  completionTag);

1669
	(*receiver->rDestroy) (receiver);
1670

1671 1672 1673 1674 1675
	if (completed)
	{
		if (is_trans_stmt)
		{
			/*
Bruce Momjian's avatar
Bruce Momjian committed
1676 1677 1678
			 * If this was a transaction control statement, commit it.	We
			 * will start a new xact command for the next command (if
			 * any).
1679
			 */
1680
			finish_xact_command();
1681 1682 1683 1684
		}
		else
		{
			/*
Bruce Momjian's avatar
Bruce Momjian committed
1685 1686
			 * We need a CommandCounterIncrement after every query, except
			 * those that start or end a transaction block.
1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712
			 */
			CommandCounterIncrement();
		}

		/* Send appropriate CommandComplete to client */
		EndCommand(completionTag, dest);
	}
	else
	{
		/* Portal run not complete, so send PortalSuspended */
		if (whereToSendOutput == Remote)
			pq_putemptymessage('s');
	}

	debug_query_string = NULL;
}

/*
 * exec_describe_statement_message
 *
 * Process a "Describe" message for a prepared statement
 */
static void
exec_describe_statement_message(const char *stmt_name)
{
	PreparedStatement *pstmt;
1713
	TupleDesc	tupdesc;
1714
	ListCell   *l;
1715 1716 1717 1718 1719 1720 1721 1722 1723 1724
	StringInfoData buf;

	/* Find prepared statement */
	if (stmt_name[0] != '\0')
		pstmt = FetchPreparedStatement(stmt_name, true);
	else
	{
		/* special-case the unnamed statement */
		pstmt = unnamed_stmt_pstmt;
		if (!pstmt)
1725 1726
			ereport(ERROR,
					(errcode(ERRCODE_UNDEFINED_PSTATEMENT),
Bruce Momjian's avatar
Bruce Momjian committed
1727
				   errmsg("unnamed prepared statement does not exist")));
1728 1729 1730 1731 1732
	}

	if (whereToSendOutput != Remote)
		return;					/* can't actually do anything... */

1733 1734 1735
	/*
	 * First describe the parameters...
	 */
Bruce Momjian's avatar
Bruce Momjian committed
1736
	pq_beginmessage(&buf, 't'); /* parameter description message type */
1737
	pq_sendint(&buf, list_length(pstmt->argtype_list), 2);
1738 1739 1740

	foreach(l, pstmt->argtype_list)
	{
1741
		Oid			ptype = lfirst_oid(l);
1742 1743 1744 1745

		pq_sendint(&buf, (int) ptype, 4);
	}
	pq_endmessage(&buf);
1746 1747 1748 1749 1750 1751 1752

	/*
	 * Next send RowDescription or NoData to describe the result...
	 */
	tupdesc = FetchPreparedStatementResultDesc(pstmt);
	if (tupdesc)
	{
Bruce Momjian's avatar
Bruce Momjian committed
1753
		List	   *targetlist;
1754 1755

		if (ChoosePortalStrategy(pstmt->query_list) == PORTAL_ONE_SELECT)
1756
			targetlist = ((Query *) linitial(pstmt->query_list))->targetList;
1757 1758
		else
			targetlist = NIL;
1759
		SendRowDescriptionMessage(tupdesc, targetlist, NULL);
1760 1761 1762 1763
	}
	else
		pq_putemptymessage('n');	/* NoData */

1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777
}

/*
 * exec_describe_portal_message
 *
 * Process a "Describe" message for a portal
 */
static void
exec_describe_portal_message(const char *portal_name)
{
	Portal		portal;

	portal = GetPortalByName(portal_name);
	if (!PortalIsValid(portal))
1778 1779 1780
		ereport(ERROR,
				(errcode(ERRCODE_UNDEFINED_CURSOR),
				 errmsg("portal \"%s\" does not exist", portal_name)));
1781 1782 1783 1784 1785

	if (whereToSendOutput != Remote)
		return;					/* can't actually do anything... */

	if (portal->tupDesc)
1786
	{
Bruce Momjian's avatar
Bruce Momjian committed
1787
		List	   *targetlist;
1788 1789

		if (portal->strategy == PORTAL_ONE_SELECT)
1790
			targetlist = ((Query *) linitial(portal->parseTrees))->targetList;
1791 1792
		else
			targetlist = NIL;
1793 1794
		SendRowDescriptionMessage(portal->tupDesc, targetlist,
								  portal->formats);
1795
	}
1796 1797 1798 1799 1800
	else
		pq_putemptymessage('n');	/* NoData */
}


1801 1802 1803 1804 1805 1806
/*
 * Convenience routines for starting/committing a single command.
 */
static void
start_xact_command(void)
{
1807 1808
	if (!xact_started)
	{
1809 1810
		ereport(DEBUG3,
				(errmsg_internal("StartTransactionCommand")));
1811
		StartTransactionCommand();
1812 1813 1814 1815

		/* Set statement timeout running, if any */
		if (StatementTimeout > 0)
			enable_sig_alarm(StatementTimeout, true);
1816

1817 1818
		xact_started = true;
	}
1819 1820 1821
}

static void
1822
finish_xact_command(void)
1823
{
1824 1825 1826 1827
	if (xact_started)
	{
		/* Cancel any active statement timeout before committing */
		disable_sig_alarm(true);
1828

1829
		/* Now commit the command */
1830 1831
		ereport(DEBUG3,
				(errmsg_internal("CommitTransactionCommand")));
1832

1833
		CommitTransactionCommand();
1834

1835 1836 1837 1838 1839 1840
#ifdef MEMORY_CONTEXT_CHECKING
		/* Check all memory contexts that weren't freed during commit */
		/* (those that were, were checked before being deleted) */
		MemoryContextCheck(TopMemoryContext);
#endif

1841
#ifdef SHOW_MEMORY_STATS
1842
		/* Print mem stats after each commit for leak tracking */
1843 1844
		if (ShowStats)
			MemoryContextStats(TopMemoryContext);
1845
#endif
1846 1847 1848

		xact_started = false;
	}
1849 1850 1851
}


1852
/* --------------------------------
1853
 *		signal handler routines used in PostgresMain()
1854 1855 1856
 * --------------------------------
 */

1857
/*
Tom Lane's avatar
Tom Lane committed
1858
 * quickdie() occurs when signalled SIGQUIT by the postmaster.
1859 1860 1861 1862
 *
 * Some backend has bought the farm,
 * so we need to stop what we're doing and exit.
 */
Tom Lane's avatar
Tom Lane committed
1863
void
1864
quickdie(SIGNAL_ARGS)
1865
{
1866
	PG_SETMASK(&BlockSig);
Bruce Momjian's avatar
Bruce Momjian committed
1867

1868
	/*
Bruce Momjian's avatar
Bruce Momjian committed
1869
	 * Ideally this should be ereport(FATAL), but then we'd not get
1870
	 * control back...
1871 1872 1873
	 */
	ereport(WARNING,
			(errcode(ERRCODE_CRASH_SHUTDOWN),
Bruce Momjian's avatar
Bruce Momjian committed
1874 1875 1876 1877 1878
			 errmsg("terminating connection because of crash of another server process"),
			 errdetail("The postmaster has commanded this server process to roll back"
					 " the current transaction and exit, because another"
			   " server process exited abnormally and possibly corrupted"
					   " shared memory."),
1879
			 errhint("In a moment you should be able to reconnect to the"
1880
					 " database and repeat your command.")));
Bruce Momjian's avatar
Bruce Momjian committed
1881

1882
	/*
1883 1884 1885 1886
	 * DO NOT proc_exit() -- we're here because shared memory may be
	 * corrupted, so we don't want to try to clean up our transaction.
	 * Just nail the windows shut and get out of town.
	 *
1887 1888 1889 1890
	 * Note we do exit(1) not exit(0).	This is to force the postmaster into
	 * a system reset cycle if some idiot DBA sends a manual SIGQUIT to a
	 * random backend.	This is necessary precisely because we don't clean
	 * up our shared memory state.
1891
	 */
1892
	exit(1);
1893 1894
}

1895
/*
1896 1897
 * Shutdown signal from postmaster: abort transaction and exit
 * at soonest convenient time
1898
 */
1899
void
1900
die(SIGNAL_ARGS)
1901
{
1902 1903 1904
	int			save_errno = errno;

	/* Don't joggle the elbow of proc_exit */
1905
	if (!proc_exit_inprogress)
1906
	{
1907
		InterruptPending = true;
1908
		ProcDiePending = true;
1909

1910
		/*
1911 1912
		 * If it's safe to interrupt, and we're waiting for input or a
		 * lock, service the interrupt immediately
1913
		 */
1914 1915
		if (ImmediateInterruptOK && InterruptHoldoffCount == 0 &&
			CritSectionCount == 0)
1916
		{
1917 1918 1919
			/* bump holdoff count to make ProcessInterrupts() a no-op */
			/* until we are done getting ready for it */
			InterruptHoldoffCount++;
1920
			DisableNotifyInterrupt();
1921
			DisableCatchupInterrupt();
1922
			/* Make sure CheckDeadLock won't run while shutting down... */
1923
			LockWaitCancel();
1924
			InterruptHoldoffCount--;
1925 1926
			ProcessInterrupts();
		}
1927
	}
1928 1929

	errno = save_errno;
1930 1931
}

1932
/*
1933
 * Timeout or shutdown signal from postmaster during client authentication.
1934
 * Simply exit(0).
1935 1936 1937
 *
 * XXX: possible future improvement: try to send a message indicating
 * why we are disconnecting.  Problem is to be sure we don't block while
1938
 * doing so, nor mess up the authentication message exchange.
1939 1940 1941 1942 1943 1944 1945
 */
void
authdie(SIGNAL_ARGS)
{
	exit(0);
}

1946
/*
1947 1948
 * Query-cancel signal from postmaster: abort current transaction
 * at soonest convenient time
1949
 */
1950
static void
1951
StatementCancelHandler(SIGNAL_ARGS)
1952
{
1953 1954
	int			save_errno = errno;

1955
	/*
1956
	 * Don't joggle the elbow of proc_exit
1957
	 */
1958
	if (!proc_exit_inprogress)
1959
	{
1960 1961
		InterruptPending = true;
		QueryCancelPending = true;
1962

1963
		/*
1964
		 * If it's safe to interrupt, and we're waiting for a lock,
1965 1966
		 * service the interrupt immediately.  No point in interrupting if
		 * we're waiting for input, however.
1967
		 */
1968
		if (ImmediateInterruptOK && InterruptHoldoffCount == 0 &&
1969
			CritSectionCount == 0)
1970
		{
1971 1972 1973 1974 1975 1976
			/* bump holdoff count to make ProcessInterrupts() a no-op */
			/* until we are done getting ready for it */
			InterruptHoldoffCount++;
			if (LockWaitCancel())
			{
				DisableNotifyInterrupt();
1977
				DisableCatchupInterrupt();
Tom Lane's avatar
Tom Lane committed
1978
				InterruptHoldoffCount--;
1979 1980 1981 1982
				ProcessInterrupts();
			}
			else
				InterruptHoldoffCount--;
1983
		}
1984 1985
	}

1986
	errno = save_errno;
1987 1988
}

1989 1990 1991 1992
/* signal handler for floating point exception */
static void
FloatExceptionHandler(SIGNAL_ARGS)
{
1993 1994 1995
	ereport(ERROR,
			(errcode(ERRCODE_FLOATING_POINT_EXCEPTION),
			 errmsg("floating-point exception"),
Bruce Momjian's avatar
Bruce Momjian committed
1996 1997 1998
		   errdetail("An invalid floating-point operation was signaled. "
					 "This probably means an out-of-range result or an "
					 "invalid operation, such as division by zero.")));
1999 2000
}

2001
/* SIGHUP: set flag to re-read config file at next convenient time */
2002
static void
2003
SigHupHandler(SIGNAL_ARGS)
2004
{
2005
	got_SIGHUP = true;
2006 2007
}

2008

2009 2010 2011 2012 2013 2014 2015 2016 2017 2018
/*
 * ProcessInterrupts: out-of-line portion of CHECK_FOR_INTERRUPTS() macro
 *
 * If an interrupt condition is pending, and it's safe to service it,
 * then clear the flag and accept the interrupt.  Called only when
 * InterruptPending is true.
 */
void
ProcessInterrupts(void)
{
2019 2020
	/* OK to accept interrupt now? */
	if (InterruptHoldoffCount != 0 || CritSectionCount != 0)
2021 2022 2023 2024 2025
		return;
	InterruptPending = false;
	if (ProcDiePending)
	{
		ProcDiePending = false;
2026 2027
		QueryCancelPending = false;		/* ProcDie trumps QueryCancel */
		ImmediateInterruptOK = false;	/* not idle anymore */
2028
		DisableNotifyInterrupt();
2029
		DisableCatchupInterrupt();
2030 2031
		ereport(FATAL,
				(errcode(ERRCODE_ADMIN_SHUTDOWN),
Bruce Momjian's avatar
Bruce Momjian committed
2032
		 errmsg("terminating connection due to administrator command")));
2033 2034 2035 2036
	}
	if (QueryCancelPending)
	{
		QueryCancelPending = false;
2037
		ImmediateInterruptOK = false;	/* not idle anymore */
2038
		DisableNotifyInterrupt();
2039
		DisableCatchupInterrupt();
2040 2041 2042
		ereport(ERROR,
				(errcode(ERRCODE_QUERY_CANCELED),
				 errmsg("canceling query due to user request")));
2043 2044 2045 2046
	}
	/* If we get here, do nothing (probably, QueryCancelPending was reset) */
}

2047

2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060
/*
 * check_stack_depth: check for excessively deep recursion
 *
 * This should be called someplace in any recursive routine that might possibly
 * recurse deep enough to overflow the stack.  Most Unixen treat stack
 * overflow as an unrecoverable SIGSEGV, so we want to error out ourselves
 * before hitting the hardware limit.  Unfortunately we have no direct way
 * to detect the hardware limit, so we have to rely on the admin to set a
 * GUC variable for it ...
 */
void
check_stack_depth(void)
{
Bruce Momjian's avatar
Bruce Momjian committed
2061 2062
	char		stack_top_loc;
	int			stack_depth;
2063 2064 2065 2066 2067

	/*
	 * Compute distance from PostgresMain's local variables to my own
	 *
	 * Note: in theory stack_depth should be ptrdiff_t or some such, but
Bruce Momjian's avatar
Bruce Momjian committed
2068 2069
	 * since the whole point of this code is to bound the value to
	 * something much less than integer-sized, int should work fine.
2070 2071
	 */
	stack_depth = (int) (stack_base_ptr - &stack_top_loc);
Bruce Momjian's avatar
Bruce Momjian committed
2072

2073
	/*
Bruce Momjian's avatar
Bruce Momjian committed
2074 2075
	 * Take abs value, since stacks grow up on some machines, down on
	 * others
2076 2077 2078
	 */
	if (stack_depth < 0)
		stack_depth = -stack_depth;
Bruce Momjian's avatar
Bruce Momjian committed
2079

2080 2081 2082 2083
	/*
	 * Trouble?
	 *
	 * The test on stack_base_ptr prevents us from erroring out if called
Bruce Momjian's avatar
Bruce Momjian committed
2084 2085 2086
	 * during process setup or in a non-backend process.  Logically it
	 * should be done first, but putting it here avoids wasting cycles
	 * during normal cases.
2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108
	 */
	if (stack_depth > max_stack_depth_bytes &&
		stack_base_ptr != NULL)
	{
		ereport(ERROR,
				(errcode(ERRCODE_STATEMENT_TOO_COMPLEX),
				 errmsg("stack depth limit exceeded"),
				 errhint("Increase the configuration parameter \"max_stack_depth\".")));
	}
}

/* GUC assign hook to update max_stack_depth_bytes from max_stack_depth */
bool
assign_max_stack_depth(int newval, bool doit, GucSource source)
{
	/* Range check was already handled by guc.c */
	if (doit)
		max_stack_depth_bytes = newval * 1024;
	return true;
}


2109
static void
2110
usage(const char *progname)
2111
{
2112
	printf(gettext("%s is the PostgreSQL stand-alone backend.  It is not\nintended to be used by normal users.\n\n"), progname);
2113

2114 2115
	printf(gettext("Usage:\n  %s [OPTION]... [DBNAME]\n\n"), progname);
	printf(gettext("Options:\n"));
2116
#ifdef USE_ASSERT_CHECKING
2117
	printf(gettext("  -A 1|0          enable/disable run-time assert checking\n"));
2118
#endif
2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129
	printf(gettext("  -B NBUFFERS     number of shared buffers\n"));
	printf(gettext("  -c NAME=VALUE   set run-time parameter\n"));
	printf(gettext("  -d 0-5          debugging level (0 is off)\n"));
	printf(gettext("  -D DATADIR      database directory\n"));
	printf(gettext("  -e              use European date input format (DMY)\n"));
	printf(gettext("  -E              echo query before execution\n"));
	printf(gettext("  -F              turn fsync off\n"));
	printf(gettext("  -N              do not use newline as interactive query delimiter\n"));
	printf(gettext("  -o FILENAME     send stdout and stderr to given file\n"));
	printf(gettext("  -P              disable system indexes\n"));
	printf(gettext("  -s              show statistics after each query\n"));
2130
	printf(gettext("  -S WORK-MEM     set amount of memory for sorts (in kbytes)\n"));
2131
	printf(gettext("  --describe-config  describe configuration parameters, then exit\n"));
2132 2133 2134 2135 2136 2137 2138 2139 2140
	printf(gettext("  --help          show this help, then exit\n"));
	printf(gettext("  --version       output version information, then exit\n"));
	printf(gettext("\nDeveloper options:\n"));
	printf(gettext("  -f s|i|n|m|h    forbid use of some plan types\n"));
	printf(gettext("  -i              do not execute queries\n"));
	printf(gettext("  -O              allow system table structure changes\n"));
	printf(gettext("  -t pa|pl|ex     show timings after each query\n"));
	printf(gettext("  -W NUM          wait NUM seconds to allow attach from a debugger\n"));
	printf(gettext("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
2141 2142
}

2143

2144
/* ----------------------------------------------------------------
2145
 * PostgresMain
2146
 *	   postgres main loop -- all backends, interactive or otherwise start here
2147
 *
2148 2149 2150 2151
 * argc/argv are the command line arguments to be used.  (When being forked
 * by the postmaster, these are not the original argv array of the process.)
 * username is the (possibly authenticated) PostgreSQL user name to be used
 * for the session.
2152 2153 2154
 * ----------------------------------------------------------------
 */
int
2155
PostgresMain(int argc, char *argv[], const char *username)
2156
{
2157
	int			flag;
2158
	const char *dbname = NULL;
2159
	char	   *userPGDATA = NULL;
2160
	bool		secure;
2161
	int			errs = 0;
2162
	int			debug_flag = 0;
Bruce Momjian's avatar
Bruce Momjian committed
2163 2164
	GucContext	ctx,
				debug_context;
2165
	GucSource	gucsource;
2166
	char	   *tmp;
2167
	int			firstchar;
2168
	char		stack_base;
Bruce Momjian's avatar
Bruce Momjian committed
2169
	StringInfoData input_message;
2170
	sigjmp_buf	local_sigjmp_buf;
2171
	volatile bool send_rfq = true;
Bruce Momjian's avatar
Bruce Momjian committed
2172

2173
	/*
2174 2175
	 * Catch standard options before doing much else.  This even works on
	 * systems without getopt_long.
2176 2177 2178
	 */
	if (!IsUnderPostmaster && argc > 1)
	{
2179
		if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
2180 2181 2182 2183
		{
			usage(argv[0]);
			exit(0);
		}
2184
		if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
2185
		{
2186
			puts(PG_VERSIONSTR);
2187 2188
			exit(0);
		}
2189
	}
2190

2191 2192 2193 2194 2195 2196
	/*
	 * initialize globals (already done if under postmaster, but not if
	 * standalone; cheap enough to do over)
	 */
	MyProcPid = getpid();

2197 2198 2199 2200 2201
	/*
	 * Fire up essential subsystems: error and memory management
	 *
	 * If we are running under the postmaster, this is done already.
	 */
2202
	if (!IsUnderPostmaster)
2203 2204
		MemoryContextInit();

2205 2206
	set_ps_display("startup");

2207 2208
	SetProcessingMode(InitProcessing);

2209 2210 2211
	/* Set up reference point for stack depth checking */
	stack_base_ptr = &stack_base;

2212 2213 2214 2215 2216 2217 2218
	/* Compute paths, if we didn't inherit them from postmaster */
	if (my_exec_path[0] == '\0')
	{
		if (find_my_exec(argv[0], my_exec_path) < 0)
			elog(FATAL, "%s: could not locate my own executable path",
				 argv[0]);
	}
Bruce Momjian's avatar
Bruce Momjian committed
2219

2220 2221
	if (pkglib_path[0] == '\0')
		get_pkglib_path(my_exec_path, pkglib_path);
2222

2223
	/*
2224
	 * Set default values for command-line options.
2225
	 */
2226
	EchoQuery = false;
2227

2228
	if (!IsUnderPostmaster)
2229
	{
2230
		InitializeGUCOptions();
2231
		userPGDATA = getenv("PGDATA");
2232
	}
2233

2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250
	/* ----------------
	 *	parse command line arguments
	 *
	 *	There are now two styles of command line layout for the backend:
	 *
	 *	For interactive use (not started from postmaster) the format is
	 *		postgres [switches] [databasename]
	 *	If the databasename is omitted it is taken to be the user name.
	 *
	 *	When started from the postmaster, the format is
	 *		postgres [secure switches] -p databasename [insecure switches]
	 *	Switches appearing after -p came from the client (via "options"
	 *	field of connection request).  For security reasons we restrict
	 *	what these switches can do.
	 * ----------------
	 */

2251 2252
	/* all options are allowed until '-p' */
	secure = true;
2253
	ctx = debug_context = PGC_POSTMASTER;
2254
	gucsource = PGC_S_ARGV;		/* initial switches came from command line */
2255

2256
	while ((flag = getopt(argc, argv, "A:B:c:D:d:Eef:FiNOPo:p:S:st:v:W:-:")) != -1)
2257 2258
		switch (flag)
		{
2259 2260
			case 'A':
#ifdef USE_ASSERT_CHECKING
2261
				SetConfigOption("debug_assertions", optarg, ctx, gucsource);
2262
#else
2263 2264 2265
				ereport(WARNING,
						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
						 errmsg("assert checking is not compiled in")));
2266 2267
#endif
				break;
2268

2269
			case 'B':
2270 2271 2272

				/*
				 * specify the size of buffer pool
2273
				 */
2274
				SetConfigOption("shared_buffers", optarg, ctx, gucsource);
2275
				break;
2276

2277
			case 'D':			/* PGDATA directory */
2278
				if (secure)
2279
					userPGDATA = optarg;
2280
				break;
2281

2282
			case 'd':			/* debug level */
2283
				{
2284
					/*
Bruce Momjian's avatar
Bruce Momjian committed
2285 2286 2287 2288 2289
					 * Client option can't decrease debug level. We have
					 * to do the test here because we group priv and
					 * client set GUC calls below, after we know the final
					 * debug value.
					 */
2290
					if (ctx != PGC_BACKEND || atoi(optarg) > debug_flag)
2291
					{
2292
						debug_flag = atoi(optarg);
Bruce Momjian's avatar
Bruce Momjian committed
2293 2294
						debug_context = ctx;	/* save context for use
												 * below */
2295 2296 2297 2298
						/* Set server debugging level. */
						if (debug_flag != 0)
						{
							char	   *debugstr = palloc(strlen("debug") + strlen(optarg) + 1);
Bruce Momjian's avatar
Bruce Momjian committed
2299

2300 2301 2302
							sprintf(debugstr, "debug%s", optarg);
							SetConfigOption("log_min_messages", debugstr, ctx, gucsource);
							pfree(debugstr);
Bruce Momjian's avatar
Bruce Momjian committed
2303

2304 2305
						}
						else
Bruce Momjian's avatar
Bruce Momjian committed
2306

2307 2308
							/*
							 * -d0 allows user to prevent postmaster debug
Bruce Momjian's avatar
Bruce Momjian committed
2309 2310 2311
							 * from propagating to backend.  It would be
							 * nice to set it to the postgresql.conf value
							 * here.
2312 2313 2314
							 */
							SetConfigOption("log_min_messages", "notice",
											ctx, gucsource);
2315 2316
					}
				}
2317
				break;
2318 2319

			case 'E':
2320 2321 2322

				/*
				 * E - echo the query the user entered
2323
				 */
2324
				EchoQuery = true;
2325
				break;
2326 2327

			case 'e':
2328 2329

				/*
2330
				 * Use European date input format (DMY)
2331
				 */
2332
				SetConfigOption("datestyle", "euro", ctx, gucsource);
2333
				break;
2334 2335

			case 'F':
2336 2337 2338

				/*
				 * turn off fsync
2339
				 */
2340
				SetConfigOption("fsync", "false", ctx, gucsource);
2341
				break;
2342 2343

			case 'f':
2344 2345 2346

				/*
				 * f - forbid generation of certain plans
2347
				 */
2348
				tmp = NULL;
2349 2350 2351
				switch (optarg[0])
				{
					case 's':	/* seqscan */
2352
						tmp = "enable_seqscan";
2353 2354
						break;
					case 'i':	/* indexscan */
2355
						tmp = "enable_indexscan";
2356 2357
						break;
					case 't':	/* tidscan */
2358
						tmp = "enable_tidscan";
2359 2360
						break;
					case 'n':	/* nestloop */
2361
						tmp = "enable_nestloop";
2362 2363
						break;
					case 'm':	/* mergejoin */
2364
						tmp = "enable_mergejoin";
2365 2366
						break;
					case 'h':	/* hashjoin */
2367
						tmp = "enable_hashjoin";
2368 2369 2370 2371
						break;
					default:
						errs++;
				}
2372
				if (tmp)
2373
					SetConfigOption(tmp, "false", ctx, gucsource);
2374 2375
				break;

2376
			case 'N':
2377 2378 2379

				/*
				 * N - Don't use newline as a query delimiter
2380 2381 2382
				 */
				UseNewLine = 0;
				break;
2383

2384
			case 'O':
2385 2386 2387

				/*
				 * allow system table structure modifications
2388
				 */
2389 2390
				if (secure)		/* XXX safe to allow from client??? */
					allowSystemTableMods = true;
2391 2392
				break;

Hiroshi Inoue's avatar
Hiroshi Inoue committed
2393
			case 'P':
2394 2395 2396

				/*
				 * ignore system indexes
2397
				 *
Bruce Momjian's avatar
Bruce Momjian committed
2398 2399 2400
				 * As of PG 7.4 this is safe to allow from the client, since
				 * it only disables reading the system indexes, not
				 * writing them.  Worst case consequence is slowness.
Hiroshi Inoue's avatar
Hiroshi Inoue committed
2401
				 */
2402
				IgnoreSystemIndexes(true);
Hiroshi Inoue's avatar
Hiroshi Inoue committed
2403 2404
				break;

2405
			case 'o':
2406 2407 2408

				/*
				 * o - send output (stdout and stderr) to the given file
2409
				 */
2410 2411
				if (secure)
					StrNCpy(OutputFileName, optarg, MAXPGPATH);
2412 2413
				break;

2414
			case 'p':
Bruce Momjian's avatar
Bruce Momjian committed
2415

2416 2417 2418
				/*
				 * p - special flag passed if backend was forked by a
				 * postmaster.
2419
				 */
2420 2421
				if (secure)
				{
2422
					dbname = strdup(optarg);
2423

Bruce Momjian's avatar
Bruce Momjian committed
2424 2425
					secure = false;		/* subsequent switches are NOT
										 * secure */
2426
					ctx = PGC_BACKEND;
2427
					gucsource = PGC_S_CLIENT;
2428
				}
2429
				break;
2430

2431
			case 'S':
2432 2433 2434

				/*
				 * S - amount of sort memory to use in 1k bytes
2435
				 */
2436
				SetConfigOption("work_mem", optarg, ctx, gucsource);
2437
				break;
2438 2439

			case 's':
2440 2441 2442

				/*
				 * s - report usage statistics (timings) after each query
2443
				 */
2444
				SetConfigOption("log_statement_stats", "true", ctx, gucsource);
2445 2446
				break;

2447
			case 't':
2448
				/* ---------------
2449 2450 2451 2452 2453 2454 2455 2456 2457
				 *	tell postgres to report usage statistics (timings) for
				 *	each query
				 *
				 *	-tpa[rser] = print stats for parser time of each query
				 *	-tpl[anner] = print stats for planner time of each query
				 *	-te[xecutor] = print stats for executor time of each query
				 *	caution: -s can not be used together with -t.
				 * ----------------
				 */
2458
				tmp = NULL;
2459 2460 2461 2462
				switch (optarg[0])
				{
					case 'p':
						if (optarg[1] == 'a')
Bruce Momjian's avatar
Bruce Momjian committed
2463
							tmp = "log_parser_stats";
2464
						else if (optarg[1] == 'l')
Bruce Momjian's avatar
Bruce Momjian committed
2465
							tmp = "log_planner_stats";
2466 2467 2468 2469
						else
							errs++;
						break;
					case 'e':
2470
						tmp = "log_executor_stats";
2471 2472 2473 2474 2475
						break;
					default:
						errs++;
						break;
				}
2476
				if (tmp)
2477
					SetConfigOption(tmp, "true", ctx, gucsource);
2478 2479
				break;

2480
			case 'v':
2481 2482
				if (secure)
					FrontendProtocol = (ProtocolVersion) atoi(optarg);
2483 2484
				break;

2485
			case 'W':
2486 2487 2488

				/*
				 * wait N seconds to allow attach from a debugger
2489
				 */
Bruce Momjian's avatar
Bruce Momjian committed
2490
				pg_usleep(atoi(optarg) * 1000000L);
2491 2492
				break;

2493
			case 'c':
2494
			case '-':
2495
				{
2496 2497
					char	   *name,
							   *value;
2498

2499 2500 2501 2502
					ParseLongOption(optarg, &name, &value);
					if (!value)
					{
						if (flag == '-')
2503 2504 2505 2506
							ereport(ERROR,
									(errcode(ERRCODE_SYNTAX_ERROR),
									 errmsg("--%s requires a value",
											optarg)));
2507
						else
2508 2509 2510 2511
							ereport(ERROR,
									(errcode(ERRCODE_SYNTAX_ERROR),
									 errmsg("-c %s requires a value",
											optarg)));
2512 2513
					}

2514
					SetConfigOption(name, value, ctx, gucsource);
2515 2516 2517 2518 2519
					free(name);
					if (value)
						free(value);
					break;
				}
2520

2521 2522
			default:
				errs++;
2523
				break;
2524 2525
		}

2526

2527
	/*
2528 2529
	 * -d is not the same as setting log_min_messages because it enables
	 * other output options.
2530 2531
	 */
	if (debug_flag >= 1)
2532
	{
2533
		SetConfigOption("log_connections", "true", debug_context, gucsource);
2534 2535
		SetConfigOption("log_disconnections", "true", debug_context, gucsource);
	}
2536
	if (debug_flag >= 2)
2537
		SetConfigOption("log_statement", "all", debug_context, gucsource);
2538
	if (debug_flag >= 3)
2539
		SetConfigOption("debug_print_parse", "true", debug_context, gucsource);
2540
	if (debug_flag >= 4)
2541
		SetConfigOption("debug_print_plan", "true", debug_context, gucsource);
2542
	if (debug_flag >= 5)
2543
		SetConfigOption("debug_print_rewritten", "true", debug_context, gucsource);
2544

2545
	/*
Bruce Momjian's avatar
Bruce Momjian committed
2546 2547
	 * Process any additional GUC variable settings passed in startup
	 * packet.
2548 2549 2550
	 */
	if (MyProcPort != NULL)
	{
2551
		ListCell   *gucopts = list_head(MyProcPort->guc_options);
2552 2553 2554

		while (gucopts)
		{
Bruce Momjian's avatar
Bruce Momjian committed
2555 2556
			char	   *name;
			char	   *value;
2557 2558 2559

			name = lfirst(gucopts);
			gucopts = lnext(gucopts);
2560

2561 2562
			value = lfirst(gucopts);
			gucopts = lnext(gucopts);
2563

2564 2565
			SetConfigOption(name, value, PGC_BACKEND, PGC_S_CLIENT);
		}
2566 2567 2568 2569 2570

		/*
		 * set up handler to log session end.
		 */
		if (IsUnderPostmaster && Log_disconnections)
2571
			on_proc_exit(log_disconnections, 0);
2572 2573
	}

2574
	if (!IsUnderPostmaster)
2575
	{
2576
		if (!userPGDATA)
2577
		{
2578 2579 2580 2581 2582
			write_stderr("%s does not know where to find the database system data.\n"
						 "You must specify the directory that contains the database system\n"
						 "either by specifying the -D invocation option or by setting the\n"
						 "PGDATA environment variable.\n",
						 argv[0]);
2583 2584
			proc_exit(1);
		}
2585
		SetDataDir(userPGDATA);
2586
	}
2587
	Assert(DataDir);
2588

2589 2590
	/* Acquire configuration parameters, unless inherited from postmaster */
	if (!IsUnderPostmaster)
2591 2592
	{
		ProcessConfigFile(PGC_POSTMASTER);
2593

2594 2595 2596
		/* If timezone is not set, determine what the OS uses */
		pg_timezone_initialize();
	}
2597

2598
	/*
2599
	 * Set up signal handlers and masks.
2600
	 *
2601
	 * Note that postmaster blocked all signals before forking child process,
2602 2603
	 * so there is no race condition whereby we might receive a signal
	 * before we have set up the handler.
Tom Lane's avatar
Tom Lane committed
2604 2605
	 *
	 * Also note: it's best not to use any signals that are SIG_IGNored in
2606
	 * the postmaster.	If such a signal arrives before we are able to
2607
	 * change the handler to non-SIG_IGN, it'll get dropped.  Instead,
Bruce Momjian's avatar
Bruce Momjian committed
2608 2609
	 * make a dummy handler in the postmaster to reserve the signal. (Of
	 * course, this isn't an issue for signals that are locally generated,
2610
	 * such as SIGALRM and SIGPIPE.)
2611
	 */
2612
	pqsignal(SIGHUP, SigHupHandler);	/* set flag to read config file */
Bruce Momjian's avatar
Bruce Momjian committed
2613
	pqsignal(SIGINT, StatementCancelHandler);	/* cancel current query */
2614
	pqsignal(SIGTERM, die);		/* cancel current query and exit */
2615
	pqsignal(SIGQUIT, quickdie);	/* hard crash time */
Bruce Momjian's avatar
Bruce Momjian committed
2616
	pqsignal(SIGALRM, handle_sig_alarm);		/* timeout conditions */
2617 2618 2619 2620 2621

	/*
	 * Ignore failure to write to frontend. Note: if frontend closes
	 * connection, we will notice it and exit cleanly when control next
	 * returns to outer loop.  This seems safer than forcing exit in the
2622 2623 2624
	 * midst of output during who-knows-what operation...
	 */
	pqsignal(SIGPIPE, SIG_IGN);
2625 2626
	pqsignal(SIGUSR1, CatchupInterruptHandler);
	pqsignal(SIGUSR2, NotifyInterruptHandler);
2627
	pqsignal(SIGFPE, FloatExceptionHandler);
2628 2629

	/*
2630 2631
	 * Reset some signals that are accepted by postmaster but not by
	 * backend
2632
	 */
2633 2634
	pqsignal(SIGCHLD, SIG_DFL); /* system() requires this on some
								 * platforms */
2635

2636 2637
	pqinitmask();

Tom Lane's avatar
Tom Lane committed
2638
	/* We allow SIGQUIT (quickdie) at all times */
2639
#ifdef HAVE_SIGPROCMASK
Tom Lane's avatar
Tom Lane committed
2640
	sigdelset(&BlockSig, SIGQUIT);
2641
#else
Tom Lane's avatar
Tom Lane committed
2642
	BlockSig &= ~(sigmask(SIGQUIT));
2643 2644
#endif

Tom Lane's avatar
Tom Lane committed
2645
	PG_SETMASK(&BlockSig);		/* block everything except SIGQUIT */
2646

2647

2648
	if (IsUnderPostmaster)
2649
	{
2650
		/* noninteractive case: nothing should be left after switches */
2651
		if (errs || argc != optind || dbname == NULL)
2652
		{
2653 2654
			ereport(FATAL,
					(errcode(ERRCODE_SYNTAX_ERROR),
Bruce Momjian's avatar
Bruce Momjian committed
2655 2656
			 errmsg("invalid command-line arguments for server process"),
			errhint("Try \"%s --help\" for more information.", argv[0])));
2657
		}
2658

2659 2660 2661
		XLOGPathInit();

		BaseInit();
2662
	}
2663
	else
2664
	{
2665 2666 2667
		/* interactive case: database name can be last arg on command line */
		if (errs || argc - optind > 1)
		{
2668 2669 2670 2671
			ereport(FATAL,
					(errcode(ERRCODE_SYNTAX_ERROR),
					 errmsg("%s: invalid command-line arguments",
							argv[0]),
Bruce Momjian's avatar
Bruce Momjian committed
2672
			errhint("Try \"%s --help\" for more information.", argv[0])));
2673 2674
		}
		else if (argc - optind == 1)
2675 2676
			dbname = argv[optind];
		else if ((dbname = username) == NULL)
2677
		{
2678 2679 2680 2681
			ereport(FATAL,
					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
					 errmsg("%s: no database nor user name specified",
							argv[0])));
2682
		}
2683

2684
		/*
2685 2686
		 * Validate we have been given a reasonable-looking DataDir (if
		 * under postmaster, assume postmaster did this already).
2687 2688 2689
		 */
		ValidatePgVersion(DataDir);

2690
		/*
2691
		 * Create lockfile for data directory.
2692
		 */
2693
		CreateDataDirLockFile(DataDir, false);
2694

2695
		XLOGPathInit();
2696
		BaseInit();
2697 2698 2699 2700 2701

		/*
		 * Start up xlog for standalone backend, and register to have it
		 * closed down at exit.
		 */
2702
		StartupXLOG();
2703
		on_shmem_exit(ShutdownXLOG, 0);
2704 2705 2706 2707 2708 2709 2710

		/*
		 * Read any existing FSM cache file, and register to write one out
		 * at exit.
		 */
		LoadFreeSpaceMap();
		on_shmem_exit(DumpFreeSpaceMap, 0);
2711 2712
	}

2713
	/*
2714 2715 2716 2717 2718
	 * General initialization.
	 *
	 * NOTE: if you are tempted to add code in this vicinity, consider
	 * putting it inside InitPostgres() instead.  In particular, anything
	 * that involves database access should be there, not here.
2719
	 */
2720 2721
	ereport(DEBUG3,
			(errmsg_internal("InitPostgres")));
2722
	InitPostgres(dbname, username);
2723

2724
	SetProcessingMode(NormalProcessing);
2725

2726 2727
	/*
	 * Send this backend's cancellation info to the frontend.
2728
	 */
2729 2730 2731
	if (whereToSendOutput == Remote &&
		PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)
	{
2732
		StringInfoData buf;
Bruce Momjian's avatar
Bruce Momjian committed
2733

2734
		pq_beginmessage(&buf, 'K');
2735 2736 2737
		pq_sendint(&buf, (int32) MyProcPid, sizeof(int32));
		pq_sendint(&buf, (int32) MyCancelKey, sizeof(int32));
		pq_endmessage(&buf);
2738 2739 2740
		/* Need not flush since ReadyForQuery will do it. */
	}

2741 2742
	/* Welcome banner for standalone case */
	if (whereToSendOutput == Debug)
2743
		printf("\nPostgreSQL stand-alone backend %s\n", PG_VERSION);
2744

2745 2746 2747
	/*
	 * Create the memory context we will use in the main loop.
	 *
2748 2749
	 * MessageContext is reset once per iteration of the main loop, ie, upon
	 * completion of processing of each command message from the client.
2750
	 */
2751 2752 2753 2754 2755
	MessageContext = AllocSetContextCreate(TopMemoryContext,
										   "MessageContext",
										   ALLOCSET_DEFAULT_MINSIZE,
										   ALLOCSET_DEFAULT_INITSIZE,
										   ALLOCSET_DEFAULT_MAXSIZE);
2756

2757 2758 2759 2760 2761 2762 2763
	/* ----------
	 * Tell the statistics collector that we're alive and
	 * to which database we belong.
	 * ----------
	 */
	pgstat_bestart();

2764 2765
	/*
	 * POSTGRES main processing loop begins here
2766
	 *
2767 2768
	 * If an exception is encountered, processing resumes here so we abort
	 * the current transaction and start a new one.
2769
	 *
Bruce Momjian's avatar
Bruce Momjian committed
2770 2771
	 * You might wonder why this isn't coded as an infinite loop around a
	 * PG_TRY construct.  The reason is that this is the bottom of the
2772 2773 2774
	 * exception stack, and so with PG_TRY there would be no exception
	 * handler in force at all during the CATCH part.  By leaving the
	 * outermost setjmp always active, we have at least some chance of
Bruce Momjian's avatar
Bruce Momjian committed
2775 2776
	 * recovering from an error during error recovery.	(If we get into an
	 * infinite loop thereby, it will soon be stopped by overflow of
2777
	 * elog.c's internal state stack.)
2778 2779
	 */

2780
	if (sigsetjmp(local_sigjmp_buf, 1) != 0)
2781
	{
2782
		/*
2783
		 * NOTE: if you are tempted to add more code in this if-block,
2784
		 * consider the high probability that it should be in
Bruce Momjian's avatar
Bruce Momjian committed
2785 2786 2787 2788
		 * AbortTransaction() instead.	The only stuff done directly here
		 * should be stuff that is guaranteed to apply *only* for
		 * outer-level error recovery, such as adjusting the FE/BE
		 * protocol status.
2789 2790 2791 2792 2793 2794 2795 2796 2797 2798
		 */

		/* Since not using PG_TRY, must reset error stack by hand */
		error_context_stack = NULL;

		/* Prevent interrupts while cleaning up */
		HOLD_INTERRUPTS();

		/*
		 * Forget any pending QueryCancel request, since we're returning
Bruce Momjian's avatar
Bruce Momjian committed
2799 2800
		 * to the idle loop anyway, and cancel the statement timer if
		 * running.
2801 2802
		 */
		QueryCancelPending = false;
2803
		disable_sig_alarm(true);
Bruce Momjian's avatar
Bruce Momjian committed
2804
		QueryCancelPending = false;		/* again in case timeout occurred */
2805 2806

		/*
Bruce Momjian's avatar
Bruce Momjian committed
2807 2808 2809
		 * Turn off these interrupts too.  This is only needed here and
		 * not in other exception-catching places since these interrupts
		 * are only enabled while we wait for client input.
2810
		 */
2811
		DisableNotifyInterrupt();
2812
		DisableCatchupInterrupt();
2813 2814 2815

		/* Report the error to the client and/or server log */
		EmitErrorReport();
2816

2817
		/*
Bruce Momjian's avatar
Bruce Momjian committed
2818 2819
		 * Make sure debug_query_string gets reset before we possibly
		 * clobber the storage it points at.
2820
		 */
2821
		debug_query_string = NULL;
2822

2823
		/*
2824
		 * Abort the current transaction in order to recover.
2825
		 */
2826
		AbortCurrentTransaction();
2827 2828

		/*
2829 2830
		 * Now return to normal top-level context and clear ErrorContext
		 * for next time.
2831 2832
		 */
		MemoryContextSwitchTo(TopMemoryContext);
2833
		FlushErrorState();
2834
		QueryContext = NULL;
2835

2836 2837
		/*
		 * If we were handling an extended-query-protocol message,
Bruce Momjian's avatar
Bruce Momjian committed
2838 2839
		 * initiate skip till next Sync.  This also causes us not to issue
		 * ReadyForQuery (until we get Sync).
2840 2841 2842
		 */
		if (doing_extended_query_message)
			ignore_till_sync = true;
2843

2844 2845 2846 2847
		/* We don't have a transaction command open anymore */
		xact_started = false;

		/* Now we can allow interrupts again */
2848
		RESUME_INTERRUPTS();
2849
	}
2850

2851 2852
	/* We can now handle ereport(ERROR) */
	PG_exception_stack = &local_sigjmp_buf;
2853

2854
	PG_SETMASK(&UnBlockSig);
2855

2856 2857
	if (!ignore_till_sync)
		send_rfq = true;		/* initially, or after error */
2858

2859 2860
	/*
	 * Non-error queries loop here.
2861 2862 2863 2864
	 */

	for (;;)
	{
2865
		/*
Bruce Momjian's avatar
Bruce Momjian committed
2866 2867
		 * At top of loop, reset extended-query-message flag, so that any
		 * errors encountered in "idle" state don't provoke skip.
2868 2869 2870
		 */
		doing_extended_query_message = false;

2871
		/*
2872
		 * Release storage left over from prior query cycle, and create a
2873
		 * new query input buffer in the cleared MessageContext.
2874
		 */
2875 2876
		MemoryContextSwitchTo(MessageContext);
		MemoryContextResetAndDeleteChildren(MessageContext);
2877

2878
		initStringInfo(&input_message);
2879

2880
		/*
2881 2882
		 * (1) If we've reached idle state, tell the frontend we're ready
		 * for a new query.
2883
		 *
2884
		 * Note: this includes fflush()'ing the last of the prior output.
2885 2886 2887
		 *
		 * This is also a good time to send collected statistics to the
		 * collector, and to update the PS stats display.  We avoid doing
Bruce Momjian's avatar
Bruce Momjian committed
2888 2889
		 * those every time through the message loop because it'd slow
		 * down processing of batched messages.
Bruce Momjian's avatar
Bruce Momjian committed
2890
		 */
2891 2892
		if (send_rfq)
		{
2893
			pgstat_report_tabstat();
Bruce Momjian's avatar
Bruce Momjian committed
2894

2895
			if (IsTransactionOrTransactionBlock())
2896 2897 2898 2899 2900 2901 2902 2903 2904
			{
				set_ps_display("idle in transaction");
				pgstat_report_activity("<IDLE> in transaction");
			}
			else
			{
				set_ps_display("idle");
				pgstat_report_activity("<IDLE>");
			}
2905

2906 2907
			ReadyForQuery(whereToSendOutput);
			send_rfq = false;
2908
		}
2909

2910 2911 2912 2913
		/*
		 * (2) deal with pending asynchronous NOTIFY from other backends,
		 * and enable async.c's signal handler to execute NOTIFY directly.
		 * Then set up other stuff needed before blocking for input.
2914
		 */
2915 2916
		QueryCancelPending = false;		/* forget any earlier CANCEL
										 * signal */
2917 2918

		EnableNotifyInterrupt();
2919
		EnableCatchupInterrupt();
2920

2921 2922 2923 2924 2925 2926
		/* Allow "die" interrupt to be processed while waiting */
		ImmediateInterruptOK = true;
		/* and don't forget to detect one that already arrived */
		QueryCancelPending = false;
		CHECK_FOR_INTERRUPTS();

2927 2928
		/*
		 * (3) read a command (loop blocks here)
2929
		 */
2930
		firstchar = ReadCommand(&input_message);
2931

2932 2933
		/*
		 * (4) disable async signal conditions again.
2934
		 */
2935
		ImmediateInterruptOK = false;
2936
		QueryCancelPending = false;		/* forget any CANCEL signal */
2937

2938
		DisableNotifyInterrupt();
2939
		DisableCatchupInterrupt();
2940

2941 2942 2943
		/*
		 * (5) check for any other interesting events that happened while
		 * we slept.
2944 2945 2946 2947 2948 2949 2950
		 */
		if (got_SIGHUP)
		{
			got_SIGHUP = false;
			ProcessConfigFile(PGC_SIGHUP);
		}

2951
		/*
Bruce Momjian's avatar
Bruce Momjian committed
2952 2953
		 * (6) process the command.  But ignore it if we're skipping till
		 * Sync.
2954
		 */
2955
		if (ignore_till_sync && firstchar != EOF)
2956 2957
			continue;

2958 2959
		switch (firstchar)
		{
2960
			case 'Q':			/* simple query */
2961
				{
2962 2963
					const char *query_string;

2964 2965
					query_string = pq_getmsgstring(&input_message);
					pq_getmsgend(&input_message);
2966

2967
					exec_simple_query(query_string);
2968

2969 2970
					send_rfq = true;
				}
2971 2972
				break;

2973 2974 2975 2976 2977 2978 2979
			case 'P':			/* parse */
				{
					const char *stmt_name;
					const char *query_string;
					int			numParams;
					Oid		   *paramTypes = NULL;

2980 2981 2982
					stmt_name = pq_getmsgstring(&input_message);
					query_string = pq_getmsgstring(&input_message);
					numParams = pq_getmsgint(&input_message, 2);
2983 2984
					if (numParams > 0)
					{
Bruce Momjian's avatar
Bruce Momjian committed
2985
						int			i;
2986 2987 2988

						paramTypes = (Oid *) palloc(numParams * sizeof(Oid));
						for (i = 0; i < numParams; i++)
2989
							paramTypes[i] = pq_getmsgint(&input_message, 4);
2990
					}
2991
					pq_getmsgend(&input_message);
2992 2993 2994 2995 2996 2997 2998

					exec_parse_message(query_string, stmt_name,
									   paramTypes, numParams);
				}
				break;

			case 'B':			/* bind */
Bruce Momjian's avatar
Bruce Momjian committed
2999

3000
				/*
Bruce Momjian's avatar
Bruce Momjian committed
3001 3002
				 * this message is complex enough that it seems best to
				 * put the field extraction out-of-line
3003
				 */
3004
				exec_bind_message(&input_message);
3005 3006 3007 3008 3009
				break;

			case 'E':			/* execute */
				{
					const char *portal_name;
Bruce Momjian's avatar
Bruce Momjian committed
3010
					int			max_rows;
3011

3012 3013 3014
					portal_name = pq_getmsgstring(&input_message);
					max_rows = pq_getmsgint(&input_message, 4);
					pq_getmsgend(&input_message);
3015

3016
					exec_execute_message(portal_name, max_rows);
3017 3018 3019
				}
				break;

3020 3021
			case 'F':			/* fastpath function call */
				/* Tell the collector what we're doing */
3022 3023
				pgstat_report_activity("<FASTPATH> function call");

3024
				/* start an xact for this function invocation */
3025
				start_xact_command();
3026

3027 3028 3029
				/* switch back to message context */
				MemoryContextSwitchTo(MessageContext);

3030
				if (HandleFunctionRequest(&input_message) == EOF)
3031 3032
				{
					/* lost frontend connection during F message input */
Bruce Momjian's avatar
Bruce Momjian committed
3033

3034
					/*
3035
					 * Reset whereToSendOutput to prevent ereport from
Bruce Momjian's avatar
Bruce Momjian committed
3036
					 * attempting to send any more messages to client.
3037 3038 3039 3040
					 */
					if (whereToSendOutput == Remote)
						whereToSendOutput = None;

3041
					proc_exit(0);
3042
				}
3043 3044

				/* commit the function-invocation transaction */
3045
				finish_xact_command();
3046

3047
				send_rfq = true;
3048 3049
				break;

Bruce Momjian's avatar
Bruce Momjian committed
3050
			case 'C':			/* close */
3051
				{
Bruce Momjian's avatar
Bruce Momjian committed
3052
					int			close_type;
3053 3054
					const char *close_target;

3055 3056 3057
					close_type = pq_getmsgbyte(&input_message);
					close_target = pq_getmsgstring(&input_message);
					pq_getmsgend(&input_message);
3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085

					switch (close_type)
					{
						case 'S':
							if (close_target[0] != '\0')
								DropPreparedStatement(close_target, false);
							else
							{
								/* special-case the unnamed statement */
								unnamed_stmt_pstmt = NULL;
								if (unnamed_stmt_context)
								{
									DropDependentPortals(unnamed_stmt_context);
									MemoryContextDelete(unnamed_stmt_context);
								}
								unnamed_stmt_context = NULL;
							}
							break;
						case 'P':
							{
								Portal		portal;

								portal = GetPortalByName(close_target);
								if (PortalIsValid(portal))
									PortalDrop(portal, false);
							}
							break;
						default:
3086 3087
							ereport(ERROR,
									(errcode(ERRCODE_PROTOCOL_VIOLATION),
Bruce Momjian's avatar
Bruce Momjian committed
3088 3089
							   errmsg("invalid CLOSE message subtype %d",
									  close_type)));
3090 3091 3092 3093
							break;
					}

					if (whereToSendOutput == Remote)
Bruce Momjian's avatar
Bruce Momjian committed
3094
						pq_putemptymessage('3');		/* CloseComplete */
3095 3096 3097 3098 3099
				}
				break;

			case 'D':			/* describe */
				{
Bruce Momjian's avatar
Bruce Momjian committed
3100
					int			describe_type;
3101 3102
					const char *describe_target;

3103 3104 3105
					describe_type = pq_getmsgbyte(&input_message);
					describe_target = pq_getmsgstring(&input_message);
					pq_getmsgend(&input_message);
3106 3107 3108 3109 3110 3111 3112 3113 3114 3115

					switch (describe_type)
					{
						case 'S':
							exec_describe_statement_message(describe_target);
							break;
						case 'P':
							exec_describe_portal_message(describe_target);
							break;
						default:
3116 3117
							ereport(ERROR,
									(errcode(ERRCODE_PROTOCOL_VIOLATION),
Bruce Momjian's avatar
Bruce Momjian committed
3118 3119
							errmsg("invalid DESCRIBE message subtype %d",
								   describe_type)));
3120 3121 3122 3123 3124
							break;
					}
				}
				break;

Bruce Momjian's avatar
Bruce Momjian committed
3125
			case 'H':			/* flush */
3126
				pq_getmsgend(&input_message);
3127 3128 3129 3130
				if (whereToSendOutput == Remote)
					pq_flush();
				break;

Bruce Momjian's avatar
Bruce Momjian committed
3131
			case 'S':			/* sync */
3132
				pq_getmsgend(&input_message);
3133
				finish_xact_command();
3134 3135 3136
				send_rfq = true;
				break;

3137
				/*
Bruce Momjian's avatar
Bruce Momjian committed
3138 3139 3140
				 * 'X' means that the frontend is closing down the socket.
				 * EOF means unexpected loss of frontend connection.
				 * Either way, perform normal shutdown.
3141 3142
				 */
			case 'X':
3143
			case EOF:
Bruce Momjian's avatar
Bruce Momjian committed
3144

3145
				/*
Bruce Momjian's avatar
Bruce Momjian committed
3146 3147
				 * Reset whereToSendOutput to prevent ereport from
				 * attempting to send any more messages to client.
3148 3149 3150
				 */
				if (whereToSendOutput == Remote)
					whereToSendOutput = None;
3151

3152 3153
				/*
				 * NOTE: if you are tempted to add more code here, DON'T!
3154 3155
				 * Whatever you had in mind to do should be set up as an
				 * on_proc_exit or on_shmem_exit callback, instead.
3156 3157 3158
				 * Otherwise it will fail to be called during other
				 * backend-shutdown scenarios.
				 */
3159
				proc_exit(0);
3160

Bruce Momjian's avatar
Bruce Momjian committed
3161 3162 3163 3164
			case 'd':			/* copy data */
			case 'c':			/* copy done */
			case 'f':			/* copy fail */

3165
				/*
Bruce Momjian's avatar
Bruce Momjian committed
3166 3167
				 * Accept but ignore these messages, per protocol spec; we
				 * probably got here because a COPY failed, and the
3168 3169 3170 3171
				 * frontend is still sending data.
				 */
				break;

3172
			default:
3173 3174 3175 3176
				ereport(FATAL,
						(errcode(ERRCODE_PROTOCOL_VIOLATION),
						 errmsg("invalid frontend message type %d",
								firstchar)));
3177
		}
3178
	}							/* end of input-reading loop */
3179

3180 3181
	/* can't get here because the above loop never exits */
	Assert(false);
3182

3183
	return 1;					/* keep compiler quiet */
3184 3185
}

3186
#ifndef HAVE_GETRUSAGE
Bruce Momjian's avatar
Bruce Momjian committed
3187 3188
#include "rusagestub.h"
#else
3189
#include <sys/resource.h>
3190
#endif   /* HAVE_GETRUSAGE */
3191

3192 3193
static struct rusage Save_r;
static struct timeval Save_t;
3194 3195

void
3196
ResetUsage(void)
3197
{
3198
	getrusage(RUSAGE_SELF, &Save_r);
3199
	gettimeofday(&Save_t, NULL);
3200
	ResetBufferUsage();
3201
	/* ResetTupleCount(); */
3202 3203 3204
}

void
3205
ShowUsage(const char *title)
3206
{
3207
	StringInfoData str;
3208 3209 3210 3211
	struct timeval user,
				sys;
	struct timeval elapse_t;
	struct rusage r;
Bruce Momjian's avatar
Bruce Momjian committed
3212
	char	   *bufusage;
3213 3214

	getrusage(RUSAGE_SELF, &r);
3215
	gettimeofday(&elapse_t, NULL);
3216 3217
	memcpy((char *) &user, (char *) &r.ru_utime, sizeof(user));
	memcpy((char *) &sys, (char *) &r.ru_stime, sizeof(sys));
3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241
	if (elapse_t.tv_usec < Save_t.tv_usec)
	{
		elapse_t.tv_sec--;
		elapse_t.tv_usec += 1000000;
	}
	if (r.ru_utime.tv_usec < Save_r.ru_utime.tv_usec)
	{
		r.ru_utime.tv_sec--;
		r.ru_utime.tv_usec += 1000000;
	}
	if (r.ru_stime.tv_usec < Save_r.ru_stime.tv_usec)
	{
		r.ru_stime.tv_sec--;
		r.ru_stime.tv_usec += 1000000;
	}

	/*
	 * the only stats we don't show here are for memory usage -- i can't
	 * figure out how to interpret the relevant fields in the rusage
	 * struct, and they change names across o/s platforms, anyway. if you
	 * can figure out what the entries mean, you can somehow extract
	 * resident set size, shared text size, and unshared data and stack
	 * sizes.
	 */
3242
	initStringInfo(&str);
3243

3244 3245
	appendStringInfo(&str, "! system usage stats:\n");
	appendStringInfo(&str,
3246
			"!\t%ld.%06ld elapsed %ld.%06ld user %ld.%06ld system sec\n",
3247 3248 3249
					 (long) (elapse_t.tv_sec - Save_t.tv_sec),
					 (long) (elapse_t.tv_usec - Save_t.tv_usec),
					 (long) (r.ru_utime.tv_sec - Save_r.ru_utime.tv_sec),
Bruce Momjian's avatar
Bruce Momjian committed
3250
				   (long) (r.ru_utime.tv_usec - Save_r.ru_utime.tv_usec),
3251
					 (long) (r.ru_stime.tv_sec - Save_r.ru_stime.tv_sec),
Bruce Momjian's avatar
Bruce Momjian committed
3252
				  (long) (r.ru_stime.tv_usec - Save_r.ru_stime.tv_usec));
3253
	appendStringInfo(&str,
Bruce Momjian's avatar
Bruce Momjian committed
3254
					 "!\t[%ld.%06ld user %ld.%06ld sys total]\n",
3255 3256 3257 3258
					 (long) user.tv_sec,
					 (long) user.tv_usec,
					 (long) sys.tv_sec,
					 (long) sys.tv_usec);
3259
/* BeOS has rusage but only has some fields, and not these... */
3260
#if defined(HAVE_GETRUSAGE)
3261
	appendStringInfo(&str,
Bruce Momjian's avatar
Bruce Momjian committed
3262 3263
					 "!\t%ld/%ld [%ld/%ld] filesystem blocks in/out\n",
					 r.ru_inblock - Save_r.ru_inblock,
3264
	/* they only drink coffee at dec */
Bruce Momjian's avatar
Bruce Momjian committed
3265 3266
					 r.ru_oublock - Save_r.ru_oublock,
					 r.ru_inblock, r.ru_oublock);
3267
	appendStringInfo(&str,
3268
		  "!\t%ld/%ld [%ld/%ld] page faults/reclaims, %ld [%ld] swaps\n",
Bruce Momjian's avatar
Bruce Momjian committed
3269 3270 3271 3272 3273
					 r.ru_majflt - Save_r.ru_majflt,
					 r.ru_minflt - Save_r.ru_minflt,
					 r.ru_majflt, r.ru_minflt,
					 r.ru_nswap - Save_r.ru_nswap,
					 r.ru_nswap);
3274
	appendStringInfo(&str,
3275
	 "!\t%ld [%ld] signals rcvd, %ld/%ld [%ld/%ld] messages rcvd/sent\n",
Bruce Momjian's avatar
Bruce Momjian committed
3276 3277 3278 3279 3280
					 r.ru_nsignals - Save_r.ru_nsignals,
					 r.ru_nsignals,
					 r.ru_msgrcv - Save_r.ru_msgrcv,
					 r.ru_msgsnd - Save_r.ru_msgsnd,
					 r.ru_msgrcv, r.ru_msgsnd);
3281
	appendStringInfo(&str,
3282
		 "!\t%ld/%ld [%ld/%ld] voluntary/involuntary context switches\n",
Bruce Momjian's avatar
Bruce Momjian committed
3283 3284 3285
					 r.ru_nvcsw - Save_r.ru_nvcsw,
					 r.ru_nivcsw - Save_r.ru_nivcsw,
					 r.ru_nvcsw, r.ru_nivcsw);
3286
#endif   /* HAVE_GETRUSAGE */
3287 3288

	bufusage = ShowBufferUsage();
3289
	appendStringInfo(&str, "! buffer usage stats:\n%s", bufusage);
3290 3291 3292
	pfree(bufusage);

	/* remove trailing newline */
Bruce Momjian's avatar
Bruce Momjian committed
3293
	if (str.data[str.len - 1] == '\n')
3294 3295
		str.data[--str.len] = '\0';

3296 3297 3298
	ereport(LOG,
			(errmsg_internal("%s", title),
			 errdetail("%s", str.data)));
3299 3300

	pfree(str.data);
3301
}
3302 3303 3304 3305

/*
 * on_proc_exit handler to log end of session
 */
Bruce Momjian's avatar
Bruce Momjian committed
3306
static void
3307
log_disconnections(int code, Datum arg)
3308
{
Bruce Momjian's avatar
Bruce Momjian committed
3309
	Port	   *port = MyProcPort;
3310
	struct timeval end;
Bruce Momjian's avatar
Bruce Momjian committed
3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323
	int			hours,
				minutes,
				seconds;

	char		session_time[20];
	char		uname[6 + NAMEDATALEN];
	char		dbname[10 + NAMEDATALEN];
	char		remote_host[7 + NI_MAXHOST];
	char		remote_port[7 + NI_MAXSERV];

	snprintf(uname, sizeof(uname), " user=%s", port->user_name);
	snprintf(dbname, sizeof(dbname), " database=%s", port->database_name);
	snprintf(remote_host, sizeof(remote_host), " host=%s",
3324
			 port->remote_host);
Bruce Momjian's avatar
Bruce Momjian committed
3325
	snprintf(remote_port, sizeof(remote_port), " port=%s", port->remote_port);
3326 3327


Bruce Momjian's avatar
Bruce Momjian committed
3328
	gettimeofday(&end, NULL);
3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345

	if (end.tv_usec < port->session_start.tv_usec)
	{
		end.tv_sec--;
		end.tv_usec += 1000000;
	}
	end.tv_sec -= port->session_start.tv_sec;
	end.tv_usec -= port->session_start.tv_usec;

	hours = end.tv_sec / 3600;
	end.tv_sec %= 3600;
	minutes = end.tv_sec / 60;
	seconds = end.tv_sec % 60;

	/* if time has gone backwards for some reason say so, or print time */

	if (end.tv_sec < 0)
Bruce Momjian's avatar
Bruce Momjian committed
3346
		snprintf(session_time, sizeof(session_time), "negative!");
3347
	else
Bruce Momjian's avatar
Bruce Momjian committed
3348 3349 3350 3351 3352

		/*
		 * for stricter accuracy here we could round - this is close
		 * enough
		 */
3353
		snprintf(session_time, sizeof(session_time),
Bruce Momjian's avatar
Bruce Momjian committed
3354 3355 3356
				 "%d:%02d:%02d.%02d",
				 hours, minutes, seconds, (int) (end.tv_usec / 10000));

3357
	ereport(
Bruce Momjian's avatar
Bruce Momjian committed
3358 3359 3360
			LOG,
			(errmsg("disconnection: session time: %s%s%s%s%s",
				session_time, uname, dbname, remote_host, remote_port)));
3361 3362

}