postgres.c

来自「PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统」· C语言 代码 · 共 2,390 行 · 第 1/5 页

C
2,390
字号
	if (tupdesc)		SendRowDescriptionMessage(tupdesc,								  FetchPreparedStatementTargetList(pstmt),								  NULL);	else		pq_putemptymessage('n');	/* NoData */}/* * exec_describe_portal_message * * Process a "Describe" message for a portal */static voidexec_describe_portal_message(const char *portal_name){	Portal		portal;	/*	 * Start up a transaction command. (Note that this will normally change	 * current memory context.) Nothing happens if we are already in one.	 */	start_xact_command();	/* Switch back to message context */	MemoryContextSwitchTo(MessageContext);	portal = GetPortalByName(portal_name);	if (!PortalIsValid(portal))		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_CURSOR),				 errmsg("portal \"%s\" does not exist", portal_name)));	/*	 * If we are in aborted transaction state, we can't run	 * SendRowDescriptionMessage(), because that needs catalog accesses.	 * Hence, refuse to Describe portals that return data.  (We shouldn't just	 * refuse all Describes, since that might break the ability of some	 * clients to issue COMMIT or ROLLBACK commands, if they use code that	 * blindly Describes whatever it does.)	 */	if (IsAbortedTransactionBlockState() &&		portal->tupDesc)		ereport(ERROR,				(errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),				 errmsg("current transaction is aborted, "						"commands ignored until end of transaction block")));	if (whereToSendOutput != DestRemote)		return;					/* can't actually do anything... */	if (portal->tupDesc)		SendRowDescriptionMessage(portal->tupDesc,								  FetchPortalTargetList(portal),								  portal->formats);	else		pq_putemptymessage('n');	/* NoData */}/* * Convenience routines for starting/committing a single command. */static voidstart_xact_command(void){	if (!xact_started)	{		ereport(DEBUG3,				(errmsg_internal("StartTransactionCommand")));		StartTransactionCommand();		/* Set statement timeout running, if any */		if (StatementTimeout > 0)			enable_sig_alarm(StatementTimeout, true);		else			cancel_from_timeout = false;		xact_started = true;	}}static voidfinish_xact_command(void){	if (xact_started)	{		/* Cancel any active statement timeout before committing */		disable_sig_alarm(true);		/* Now commit the command */		ereport(DEBUG3,				(errmsg_internal("CommitTransactionCommand")));		CommitTransactionCommand();#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#ifdef SHOW_MEMORY_STATS		/* Print mem stats after each commit for leak tracking */		if (ShowStats)			MemoryContextStats(TopMemoryContext);#endif		xact_started = false;	}}/* * Convenience routines for checking whether a statement is one of the * ones that we allow in transaction-aborted state. */static boolIsTransactionExitStmt(Node *parsetree){	if (parsetree && IsA(parsetree, TransactionStmt))	{		TransactionStmt *stmt = (TransactionStmt *) parsetree;		if (stmt->kind == TRANS_STMT_COMMIT ||			stmt->kind == TRANS_STMT_PREPARE ||			stmt->kind == TRANS_STMT_ROLLBACK ||			stmt->kind == TRANS_STMT_ROLLBACK_TO)			return true;	}	return false;}static boolIsTransactionExitStmtList(List *parseTrees){	if (list_length(parseTrees) == 1)	{		Query	   *query = (Query *) linitial(parseTrees);		if (query->commandType == CMD_UTILITY &&			IsTransactionExitStmt(query->utilityStmt))			return true;	}	return false;}static boolIsTransactionStmtList(List *parseTrees){	if (list_length(parseTrees) == 1)	{		Query	   *query = (Query *) linitial(parseTrees);		if (query->commandType == CMD_UTILITY &&			query->utilityStmt && IsA(query->utilityStmt, TransactionStmt))			return true;	}	return false;}/* -------------------------------- *		signal handler routines used in PostgresMain() * -------------------------------- *//* * quickdie() occurs when signalled SIGQUIT by the postmaster. * * Some backend has bought the farm, * so we need to stop what we're doing and exit. */voidquickdie(SIGNAL_ARGS){	PG_SETMASK(&BlockSig);	/*	 * Ideally this should be ereport(FATAL), but then we'd not get control	 * back...	 */	ereport(WARNING,			(errcode(ERRCODE_CRASH_SHUTDOWN),			 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."),			 errhint("In a moment you should be able to reconnect to the"					 " database and repeat your command.")));	/*	 * 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.	 *	 * 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.	 */	exit(1);}/* * Shutdown signal from postmaster: abort transaction and exit * at soonest convenient time */voiddie(SIGNAL_ARGS){	int			save_errno = errno;	/* Don't joggle the elbow of proc_exit */	if (!proc_exit_inprogress)	{		InterruptPending = true;		ProcDiePending = true;		/*		 * If it's safe to interrupt, and we're waiting for input or a lock,		 * service the interrupt immediately		 */		if (ImmediateInterruptOK && InterruptHoldoffCount == 0 &&			CritSectionCount == 0)		{			/* bump holdoff count to make ProcessInterrupts() a no-op */			/* until we are done getting ready for it */			InterruptHoldoffCount++;			DisableNotifyInterrupt();			DisableCatchupInterrupt();			/* Make sure CheckDeadLock won't run while shutting down... */			LockWaitCancel();			InterruptHoldoffCount--;			ProcessInterrupts();		}	}	errno = save_errno;}/* * Timeout or shutdown signal from postmaster during client authentication. * Simply exit(0). * * XXX: possible future improvement: try to send a message indicating * why we are disconnecting.  Problem is to be sure we don't block while * doing so, nor mess up the authentication message exchange. */voidauthdie(SIGNAL_ARGS){	exit(0);}/* * Query-cancel signal from postmaster: abort current transaction * at soonest convenient time */voidStatementCancelHandler(SIGNAL_ARGS){	int			save_errno = errno;	/*	 * Don't joggle the elbow of proc_exit	 */	if (!proc_exit_inprogress)	{		InterruptPending = true;		QueryCancelPending = true;		/*		 * If it's safe to interrupt, and we're waiting for a lock, service		 * the interrupt immediately.  No point in interrupting if we're		 * waiting for input, however.		 */		if (ImmediateInterruptOK && InterruptHoldoffCount == 0 &&			CritSectionCount == 0)		{			/* bump holdoff count to make ProcessInterrupts() a no-op */			/* until we are done getting ready for it */			InterruptHoldoffCount++;			if (LockWaitCancel())			{				DisableNotifyInterrupt();				DisableCatchupInterrupt();				InterruptHoldoffCount--;				ProcessInterrupts();			}			else				InterruptHoldoffCount--;		}	}	errno = save_errno;}/* signal handler for floating point exception */voidFloatExceptionHandler(SIGNAL_ARGS){	ereport(ERROR,			(errcode(ERRCODE_FLOATING_POINT_EXCEPTION),			 errmsg("floating-point exception"),			 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.")));}/* SIGHUP: set flag to re-read config file at next convenient time */static voidSigHupHandler(SIGNAL_ARGS){	got_SIGHUP = true;}/* * 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. */voidProcessInterrupts(void){	/* OK to accept interrupt now? */	if (InterruptHoldoffCount != 0 || CritSectionCount != 0)		return;	InterruptPending = false;	if (ProcDiePending)	{		ProcDiePending = false;		QueryCancelPending = false;		/* ProcDie trumps QueryCancel */		ImmediateInterruptOK = false;	/* not idle anymore */		DisableNotifyInterrupt();		DisableCatchupInterrupt();		ereport(FATAL,				(errcode(ERRCODE_ADMIN_SHUTDOWN),			 errmsg("terminating connection due to administrator command")));	}	if (QueryCancelPending)	{		QueryCancelPending = false;		ImmediateInterruptOK = false;	/* not idle anymore */		DisableNotifyInterrupt();		DisableCatchupInterrupt();		if (cancel_from_timeout)			ereport(ERROR,					(errcode(ERRCODE_QUERY_CANCELED),					 errmsg("canceling statement due to statement timeout")));		else			ereport(ERROR,					(errcode(ERRCODE_QUERY_CANCELED),					 errmsg("canceling statement due to user request")));	}	/* If we get here, do nothing (probably, QueryCancelPending was reset) */}/* * 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 ... */voidcheck_stack_depth(void){	char		stack_top_loc;	int			stack_depth;	/*	 * Compute distance from PostgresMain's local variables to my own	 *	 * Note: in theory stack_depth should be ptrdiff_t or some such, but since	 * the whole point of this code is to bound the value to something much	 * less than integer-sized, int should work fine.	 */	stack_depth = (int) (stack_base_ptr - &stack_top_loc);	/*	 * Take abs value, since stacks grow up on some machines, down on others	 */	if (stack_depth < 0)		stack_depth = -stack_depth;	/*	 * Trouble?	 *	 * The test on stack_base_ptr prevents us from erroring out if called	 * 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.	 */	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 */boolassign_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;}static voidusage(const char *progname){	printf(_("%s is the PostgreSQL stand-alone backend.  It is not\nintended to be used by normal users.\n\n"), progname);	printf(_("Usage:\n  %s [OPTION]... [DBNAME]\n\n"), progname);	printf(_("Options:\n"));#ifdef USE_ASSERT_CHECKING	printf(_("  -A 1|0          enable/disable run-time assert checking\n"));#endif	printf(_("  -B NBUFFERS     number of shared buffers\n"));	printf(_("  -c NAME=VALUE   set run-time parameter\n"));	printf(_("  -d 0-5          debugging level (0 is off)\n"));	printf(_("  -D DATADIR      database directory\n"));	printf(_("  -e              use European date input format (DMY)\n"));	printf(_("  -E              echo query before execution\n"));	printf(_("  -F              turn fsync off\n"));	printf(_("  -N              do not use newline as interactive query delimiter\n"));	printf(_("  -o FILENAME     send stdout and stderr to given file\n"));	printf(_("  -P              disable system indexes\n"));	printf(_("  -s              show statistics after each query\n"));	printf(_("  -S WORK-MEM     set amount of memory for sorts (in kB)\n"));	printf(_("  --describe-config  describe configuration parameters, then exit\n"));	printf(_("  --help          show this help, then exit\n"));	printf(_("  --version       output version information, then exit\n"));	printf(_("\nDeveloper options:\n"));	printf(_("  -f s|i|n|m|h    forbid use of some plan types\n"));	printf(_("  -i              do not execute queries\n"));	printf(_("  -O              allow system table structure changes\n"));	printf(_("  -t pa|pl|ex     show timings after each query\n"));	printf(_("  -W NUM          wait NUM seconds to allow attach from a debugger\n"));	printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));}/* * set_debug_options --- apply "-d N" command line option * * -d is not quite the same as setting log_min_messages because it enables * other output options. */voidset_debug_options(int debug_flag, GucContext context, GucSource source){	if (debug_flag > 0)	{		char		debugstr[64];		sprintf(debugstr, "debug%d", debug_flag);		SetConfigOption("log_min_messages", debugstr, context, source);	}	else		SetConfigOption("log_min_m

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?