postgres.c
来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 2,551 行 · 第 1/5 页
C
2,551 行
{ Query *query = (Query *) lfirst(portal->parseTrees); 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 || stmt->kind == TRANS_STMT_ROLLBACK) is_trans_exit = true; } } /* * Create dest receiver in MessageContext (we don't want it in * transaction context, because that may get deleted if portal * contains VACUUM). */ receiver = CreateDestReceiver(dest, portal); /* * Ensure we are in a transaction command (this should normally be the * case already due to prior BIND). */ 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) ereport(ERROR, (errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION), errmsg("current transaction is aborted, " "commands ignored until end of transaction block"))); } /* 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, receiver, receiver, completionTag); (*receiver->rDestroy) (receiver); if (completed) { if (is_trans_stmt) { /* * If this was a transaction control statement, commit it. We * will start a new xact command for the next command (if * any). */ finish_xact_command(); } else { /* * We need a CommandCounterIncrement after every query, except * those that start or end a transaction block. */ 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 voidexec_describe_statement_message(const char *stmt_name){ PreparedStatement *pstmt; TupleDesc tupdesc; List *l; 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) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_PSTATEMENT), errmsg("unnamed prepared statement does not exist"))); } if (whereToSendOutput != Remote) return; /* can't actually do anything... */ /* * First describe the parameters... */ pq_beginmessage(&buf, 't'); /* parameter description message type */ pq_sendint(&buf, length(pstmt->argtype_list), 2); foreach(l, pstmt->argtype_list) { Oid ptype = lfirsto(l); pq_sendint(&buf, (int) ptype, 4); } pq_endmessage(&buf); /* * Next send RowDescription or NoData to describe the result... */ tupdesc = FetchPreparedStatementResultDesc(pstmt); if (tupdesc) { List *targetlist; if (ChoosePortalStrategy(pstmt->query_list) == PORTAL_ONE_SELECT) targetlist = ((Query *) lfirst(pstmt->query_list))->targetList; else targetlist = NIL; SendRowDescriptionMessage(tupdesc, targetlist, 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; portal = GetPortalByName(portal_name); if (!PortalIsValid(portal)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_CURSOR), errmsg("portal \"%s\" does not exist", portal_name))); if (whereToSendOutput != Remote) return; /* can't actually do anything... */ if (portal->tupDesc) { List *targetlist; if (portal->strategy == PORTAL_ONE_SELECT) targetlist = ((Query *) lfirst(portal->parseTrees))->targetList; else targetlist = NIL; SendRowDescriptionMessage(portal->tupDesc, targetlist, 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); xact_started = true; }}static voidfinish_xact_command(void){ if (xact_started) { /* Invoke IMMEDIATE constraint triggers */ DeferredTriggerEndQuery(); /* 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; }}/* -------------------------------- * 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 (perhaps could fix by doing local sigsetjmp?) */ 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(); /* 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 */static voidStatementCancelHandler(SIGNAL_ARGS){ int save_errno = errno; /* * Don't joggle the elbow of proc_exit, nor an already-in-progress * abort */ if (!proc_exit_inprogress && !InError) { 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(); InterruptHoldoffCount--; ProcessInterrupts(); } else InterruptHoldoffCount--; } } errno = save_errno;}/* signal handler for floating point exception */static 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(); ereport(FATAL, (errcode(ERRCODE_ADMIN_SHUTDOWN), errmsg("terminating connection due to administrator command"))); } if (QueryCancelPending) { QueryCancelPending = false; ImmediateInterruptOK = false; /* not idle anymore */ DisableNotifyInterrupt(); ereport(ERROR, (errcode(ERRCODE_QUERY_CANCELED), errmsg("canceling query due to user request"))); } /* If we get here, do nothing (probably, QueryCancelPending was reset) */}static voidusage(char *progname){ printf(gettext("%s is the PostgreSQL stand-alone backend. It is not\nintended to be used by normal users.\n\n"), progname); printf(gettext("Usage:\n %s [OPTION]... [DBNAME]\n\n"), progname); printf(gettext("Options:\n"));#ifdef USE_ASSERT_CHECKING printf(gettext(" -A 1|0 enable/disable run-time assert checking\n"));#endif 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")); printf(gettext(" -S SORT-MEM set amount of memory for sorts (in kbytes)\n")); printf(gettext(" --describe-config describe configuration parameters, then exit\n")); 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"));}/* ---------------------------------------------------------------- * PostgresMain * postgres main loop -- all backends, interactive or otherwise start here * * 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. * ---------------------------------------------------------------- */intPostgresMain(int argc, char *argv[], const char *username){ int flag; const char *dbname = NULL; char *potential_DataDir = NULL; bool secure; int errs = 0; int debug_flag = 0; GucContext ctx, debug_context; GucSource gucsource; char *tmp; int firstchar; StringInfoData input_message; volatile bool send_rfq = true; /* * Catch standard options before doing much else. This even works on * systems without getopt_long. */ if (!IsUnderPostmaster && argc > 1) { if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0) { usage(argv[0]); exit(0); } if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?