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 + -
显示快捷键?