#include "postgres.h"
#include <fcntl.h>
#include <limits.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>
#include <sys/socket.h>
#include "rusagestub.h"
#include "access/printtup.h"
#include "access/xact.h"
#include "catalog/pg_type.h"
#include "commands/async.h"
#include "commands/prepare.h"
#include "libpq/libpq.h"
#include "libpq/pqformat.h"
#include "libpq/pqsignal.h"
#include "miscadmin.h"
#include "nodes/print.h"
#include "optimizer/planner.h"
#include "pgstat.h"
#include "pg_trace.h"
#include "parser/analyze.h"
#include "parser/parser.h"
#include "postmaster/autovacuum.h"
#include "postmaster/postmaster.h"
#include "replication/walsender.h"
#include "rewrite/rewriteHandler.h"
#include "storage/bufmgr.h"
#include "storage/ipc.h"
#include "storage/proc.h"
#include "storage/procsignal.h"
#include "storage/sinval.h"
#include "tcop/fastpath.h"
#include "tcop/pquery.h"
#include "tcop/tcopprot.h"
#include "tcop/utility.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/ps_status.h"
#include "utils/snapmgr.h"
#include "utils/timeout.h"
#include "utils/timestamp.h"
#include "mb/pg_wchar.h"
Go to the source code of this file.
Functions | |
static int | InteractiveBackend (StringInfo inBuf) |
static int | interactive_getc (void) |
static int | SocketBackend (StringInfo inBuf) |
static int | ReadCommand (StringInfo inBuf) |
static void | forbidden_in_wal_sender (char firstchar) |
static List * | pg_rewrite_query (Query *query) |
static bool | check_log_statement (List *stmt_list) |
static int | errdetail_execute (List *raw_parsetree_list) |
static int | errdetail_params (ParamListInfo params) |
static int | errdetail_abort (void) |
static int | errdetail_recovery_conflict (void) |
static void | start_xact_command (void) |
static void | finish_xact_command (void) |
static bool | IsTransactionExitStmt (Node *parsetree) |
static bool | IsTransactionExitStmtList (List *parseTrees) |
static bool | IsTransactionStmtList (List *parseTrees) |
static void | drop_unnamed_stmt (void) |
static void | SigHupHandler (SIGNAL_ARGS) |
static void | log_disconnections (int code, Datum arg) |
void | prepare_for_client_read (void) |
void | client_read_ended (void) |
List * | pg_parse_query (const char *query_string) |
List * | pg_analyze_and_rewrite (Node *parsetree, const char *query_string, Oid *paramTypes, int numParams) |
List * | pg_analyze_and_rewrite_params (Node *parsetree, const char *query_string, ParserSetupHook parserSetup, void *parserSetupArg) |
PlannedStmt * | pg_plan_query (Query *querytree, int cursorOptions, ParamListInfo boundParams) |
List * | pg_plan_queries (List *querytrees, int cursorOptions, ParamListInfo boundParams) |
static void | exec_simple_query (const char *query_string) |
static void | exec_parse_message (const char *query_string, const char *stmt_name, Oid *paramTypes, int numParams) |
static void | exec_bind_message (StringInfo input_message) |
static void | exec_execute_message (const char *portal_name, long max_rows) |
int | check_log_duration (char *msec_str, bool was_logged) |
static void | exec_describe_statement_message (const char *stmt_name) |
static void | exec_describe_portal_message (const char *portal_name) |
void | quickdie (SIGNAL_ARGS) |
void | die (SIGNAL_ARGS) |
void | StatementCancelHandler (SIGNAL_ARGS) |
void | FloatExceptionHandler (SIGNAL_ARGS) |
void | RecoveryConflictInterrupt (ProcSignalReason reason) |
void | ProcessInterrupts (void) |
pg_stack_base_t | set_stack_base (void) |
void | restore_stack_base (pg_stack_base_t base) |
void | check_stack_depth (void) |
bool | check_max_stack_depth (int *newval, void **extra, GucSource source) |
void | assign_max_stack_depth (int newval, void *extra) |
void | set_debug_options (int debug_flag, GucContext context, GucSource source) |
bool | set_plan_disabling_options (const char *arg, GucContext context, GucSource source) |
const char * | get_stats_option_name (const char *arg) |
void | process_postgres_switches (int argc, char *argv[], GucContext ctx, const char **dbname) |
void | PostgresMain (int argc, char *argv[], const char *dbname, const char *username) |
long | get_stack_depth_rlimit (void) |
void | ResetUsage (void) |
void | ShowUsage (const char *title) |
Variables | |
char * | optarg |
int | optind |
const char * | debug_query_string |
CommandDest | whereToSendOutput = DestDebug |
bool | Log_disconnections = false |
int | log_statement = LOGSTMT_NONE |
int | max_stack_depth = 100 |
int | PostAuthDelay = 0 |
static long | max_stack_depth_bytes = 100 * 1024L |
char * | stack_base_ptr = NULL |
static volatile sig_atomic_t | got_SIGHUP = false |
static bool | xact_started = false |
static bool | DoingCommandRead = false |
static bool | doing_extended_query_message = false |
static bool | ignore_till_sync = false |
static CachedPlanSource * | unnamed_stmt_psrc = NULL |
static const char * | userDoption = NULL |
static bool | EchoQuery = false |
static int | UseNewLine = 1 |
static bool | RecoveryConflictPending = false |
static bool | RecoveryConflictRetryable = true |
static ProcSignalReason | RecoveryConflictReason |
static struct rusage | Save_r |
static struct timeval | Save_t |
void assign_max_stack_depth | ( | int | newval, | |
void * | extra | |||
) |
Definition at line 3129 of file postgres.c.
References max_stack_depth_bytes.
{ long newval_bytes = newval * 1024L; max_stack_depth_bytes = newval_bytes; }
int check_log_duration | ( | char * | msec_str, | |
bool | was_logged | |||
) |
Definition at line 2046 of file postgres.c.
References GetCurrentStatementStartTimestamp(), GetCurrentTimestamp(), log_duration, log_min_duration_statement, snprintf(), and TimestampDifference().
Referenced by exec_bind_message(), exec_execute_message(), exec_parse_message(), exec_simple_query(), and HandleFunctionRequest().
{ if (log_duration || log_min_duration_statement >= 0) { long secs; int usecs; int msecs; bool exceeded; TimestampDifference(GetCurrentStatementStartTimestamp(), GetCurrentTimestamp(), &secs, &usecs); msecs = usecs / 1000; /* * This odd-looking test for log_min_duration_statement being exceeded * is designed to avoid integer overflow with very long durations: * don't compute secs * 1000 until we've verified it will fit in int. */ exceeded = (log_min_duration_statement == 0 || (log_min_duration_statement > 0 && (secs > log_min_duration_statement / 1000 || secs * 1000 + msecs >= log_min_duration_statement))); if (exceeded || log_duration) { snprintf(msec_str, 32, "%ld.%03d", secs * 1000 + msecs, usecs % 1000); if (exceeded && !was_logged) return 2; else return 1; } } return 0; }
Definition at line 2009 of file postgres.c.
References GetCommandLogLevel(), lfirst, log_statement, LOGSTMT_ALL, and LOGSTMT_NONE.
Referenced by exec_execute_message(), and exec_simple_query().
{ ListCell *stmt_item; if (log_statement == LOGSTMT_NONE) return false; if (log_statement == LOGSTMT_ALL) return true; /* Else we have to inspect the statement(s) to see whether to log */ foreach(stmt_item, stmt_list) { Node *stmt = (Node *) lfirst(stmt_item); if (GetCommandLogLevel(stmt) <= log_statement) return true; } return false; }
Definition at line 3112 of file postgres.c.
References get_stack_depth_rlimit(), GUC_check_errdetail, GUC_check_errhint, and STACK_DEPTH_SLOP.
{ long newval_bytes = *newval * 1024L; long stack_rlimit = get_stack_depth_rlimit(); if (stack_rlimit > 0 && newval_bytes > stack_rlimit - STACK_DEPTH_SLOP) { GUC_check_errdetail("\"max_stack_depth\" must not exceed %ldkB.", (stack_rlimit - STACK_DEPTH_SLOP) / 1024L); GUC_check_errhint("Increase the platform's stack depth limit via \"ulimit -s\" or local equivalent."); return false; } return true; }
void check_stack_depth | ( | void | ) |
Definition at line 3051 of file postgres.c.
References ereport, errcode(), errhint(), errmsg(), ERROR, max_stack_depth, max_stack_depth_bytes, NULL, and stack_base_ptr.
Referenced by addone(), clean_fakeval_intree(), clean_NOT_intree(), cntsize(), contains_required_value(), copyObject(), Cover(), dofindsubquery(), EventTriggerInvoke(), ExecInitExpr(), ExecMakeFunctionResult(), ExecMakeFunctionResultNoSets(), execute(), expression_tree_mutator(), expression_tree_walker(), fillQT(), findoprnd_recurse(), freetree(), infix(), inline_set_returning_function(), JumbleExpr(), makepol(), plainnode(), plperl_hash_from_tuple(), plperl_sv_to_datum(), QT2QTN(), QTNBinary(), QTNClearFlags(), QTNCopy(), QTNFree(), QTNodeCompare(), QTNSort(), QTNTernary(), raw_expression_tree_walker(), split_array(), transformExprRecurse(), transformSetOperationTree(), TS_execute(), tsquery_opr_selec(), and tsquery_requires_match().
{ char stack_top_loc; long stack_depth; /* * Compute distance from reference point to my local variables */ stack_depth = (long) (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\" (currently %dkB), " "after ensuring the platform's stack depth limit is adequate.", max_stack_depth))); } /* * On IA64 there is a separate "register" stack that requires its own * independent check. For this, we have to measure the change in the * "BSP" pointer from PostgresMain to here. Logic is just as above, * except that we know IA64's register stack grows up. * * Note we assume that the same max_stack_depth applies to both stacks. */ #if defined(__ia64__) || defined(__ia64) stack_depth = (long) (ia64_get_bsp() - register_stack_base_ptr); if (stack_depth > max_stack_depth_bytes && register_stack_base_ptr != NULL) { ereport(ERROR, (errcode(ERRCODE_STATEMENT_TOO_COMPLEX), errmsg("stack depth limit exceeded"), errhint("Increase the configuration parameter \"max_stack_depth\" (currently %dkB), " "after ensuring the platform's stack depth limit is adequate.", max_stack_depth))); } #endif /* IA64 */ }
void client_read_ended | ( | void | ) |
Definition at line 531 of file postgres.c.
References DisableCatchupInterrupt(), DisableNotifyInterrupt(), DoingCommandRead, and ImmediateInterruptOK.
Referenced by interactive_getc(), and secure_read().
{ if (DoingCommandRead) { ImmediateInterruptOK = false; DisableNotifyInterrupt(); DisableCatchupInterrupt(); } }
void die | ( | SIGNAL_ARGS | ) |
Definition at line 2576 of file postgres.c.
References CritSectionCount, DisableCatchupInterrupt(), DisableNotifyInterrupt(), ImmediateInterruptOK, InterruptHoldoffCount, InterruptPending, LockErrorCleanup(), MyProc, proc_exit_inprogress, ProcDiePending, ProcessInterrupts(), PGPROC::procLatch, and SetLatch().
{ 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++; LockErrorCleanup(); /* prevent CheckDeadLock from running */ DisableNotifyInterrupt(); DisableCatchupInterrupt(); InterruptHoldoffCount--; ProcessInterrupts(); } } /* If we're still here, waken anything waiting on the process latch */ if (MyProc) SetLatch(&MyProc->procLatch); errno = save_errno; }
static void drop_unnamed_stmt | ( | void | ) | [static] |
Definition at line 2497 of file postgres.c.
References DropCachedPlan().
Referenced by exec_parse_message(), exec_simple_query(), and PostgresMain().
{ /* paranoia to avoid a dangling pointer in case of error */ if (unnamed_stmt_psrc) { CachedPlanSource *psrc = unnamed_stmt_psrc; unnamed_stmt_psrc = NULL; DropCachedPlan(psrc); } }
static int errdetail_abort | ( | void | ) | [static] |
Definition at line 2186 of file postgres.c.
References errdetail(), MyProc, and PGPROC::recoveryConflictPending.
Referenced by exec_bind_message(), exec_describe_portal_message(), exec_describe_statement_message(), exec_execute_message(), exec_parse_message(), and exec_simple_query().
{ if (MyProc->recoveryConflictPending) errdetail("abort reason: recovery conflict"); return 0; }
static int errdetail_execute | ( | List * | raw_parsetree_list | ) | [static] |
Definition at line 2091 of file postgres.c.
References errdetail(), FetchPreparedStatement(), IsA, lfirst, ExecuteStmt::name, PreparedStatement::plansource, and CachedPlanSource::query_string.
Referenced by exec_simple_query().
{ ListCell *parsetree_item; foreach(parsetree_item, raw_parsetree_list) { Node *parsetree = (Node *) lfirst(parsetree_item); if (IsA(parsetree, ExecuteStmt)) { ExecuteStmt *stmt = (ExecuteStmt *) parsetree; PreparedStatement *pstmt; pstmt = FetchPreparedStatement(stmt->name, false); if (pstmt) { errdetail("prepare: %s", pstmt->plansource->query_string); return 0; } } } return 0; }
static int errdetail_params | ( | ParamListInfo | params | ) | [static] |
Definition at line 2122 of file postgres.c.
References appendStringInfo(), appendStringInfoCharMacro, appendStringInfoString(), StringInfoData::data, errdetail(), getTypeOutputInfo(), initStringInfo(), IsAbortedTransactionBlockState(), ParamExternData::isnull, MemoryContextSwitchTo(), MessageContext, ParamListInfoData::numParams, OidIsValid, OidOutputFunctionCall(), ParamListInfoData::params, pfree(), ParamExternData::ptype, and ParamExternData::value.
Referenced by exec_bind_message(), and exec_execute_message().
{ /* We mustn't call user-defined I/O functions when in an aborted xact */ if (params && params->numParams > 0 && !IsAbortedTransactionBlockState()) { StringInfoData param_str; MemoryContext oldcontext; int paramno; /* Make sure any trash is generated in MessageContext */ oldcontext = MemoryContextSwitchTo(MessageContext); initStringInfo(¶m_str); for (paramno = 0; paramno < params->numParams; paramno++) { ParamExternData *prm = ¶ms->params[paramno]; Oid typoutput; bool typisvarlena; char *pstring; char *p; appendStringInfo(¶m_str, "%s$%d = ", paramno > 0 ? ", " : "", paramno + 1); if (prm->isnull || !OidIsValid(prm->ptype)) { appendStringInfoString(¶m_str, "NULL"); continue; } getTypeOutputInfo(prm->ptype, &typoutput, &typisvarlena); pstring = OidOutputFunctionCall(typoutput, prm->value); appendStringInfoCharMacro(¶m_str, '\''); for (p = pstring; *p; p++) { if (*p == '\'') /* double single quotes */ appendStringInfoCharMacro(¶m_str, *p); appendStringInfoCharMacro(¶m_str, *p); } appendStringInfoCharMacro(¶m_str, '\''); pfree(pstring); } errdetail("parameters: %s", param_str.data); pfree(param_str.data); MemoryContextSwitchTo(oldcontext); } return 0; }
static int errdetail_recovery_conflict | ( | void | ) | [static] |
Definition at line 2200 of file postgres.c.
References errdetail(), PROCSIG_RECOVERY_CONFLICT_BUFFERPIN, PROCSIG_RECOVERY_CONFLICT_DATABASE, PROCSIG_RECOVERY_CONFLICT_LOCK, PROCSIG_RECOVERY_CONFLICT_SNAPSHOT, PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK, PROCSIG_RECOVERY_CONFLICT_TABLESPACE, and RecoveryConflictReason.
Referenced by ProcessInterrupts().
{ switch (RecoveryConflictReason) { case PROCSIG_RECOVERY_CONFLICT_BUFFERPIN: errdetail("User was holding shared buffer pin for too long."); break; case PROCSIG_RECOVERY_CONFLICT_LOCK: errdetail("User was holding a relation lock for too long."); break; case PROCSIG_RECOVERY_CONFLICT_TABLESPACE: errdetail("User was or might have been using tablespace that must be dropped."); break; case PROCSIG_RECOVERY_CONFLICT_SNAPSHOT: errdetail("User query might have needed to see row versions that must be removed."); break; case PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK: errdetail("User transaction caused buffer deadlock with recovery."); break; case PROCSIG_RECOVERY_CONFLICT_DATABASE: errdetail("User was connected to a database that must be dropped."); break; default: break; /* no errdetail */ } return 0; }
static void exec_bind_message | ( | StringInfo | input_message | ) | [static] |
Definition at line 1407 of file postgres.c.
References analyze_requires_snapshot(), check_log_duration(), CachedPlanSource::commandTag, CreatePortal(), StringInfoData::cursor, StringInfoData::data, DEBUG2, debug_query_string, DestRemote, ereport, errcode(), errdetail_abort(), errdetail_params(), errhidestmt(), errmsg(), ERROR, FetchPreparedStatement(), GetCachedPlan(), GetTransactionSnapshot(), getTypeBinaryInputInfo(), getTypeInputInfo(), i, InvalidSnapshot, IsAbortedTransactionBlockState(), ParamExternData::isnull, IsTransactionExitStmt(), StringInfoData::len, LOG, log_statement_stats, StringInfoData::maxlen, MemoryContextSwitchTo(), MessageContext, CachedPlanSource::num_params, ParamListInfoData::numParams, OidInputFunctionCall(), OidReceiveFunctionCall(), palloc(), CachedPlanSource::param_types, ParamListInfoData::paramFetch, ParamListInfoData::paramFetchArg, ParamListInfoData::params, ParamListInfoData::parserSetup, ParamListInfoData::parserSetupArg, ParamExternData::pflags, pfree(), pg_client_to_server(), pgstat_report_activity(), PreparedStatement::plansource, PopActiveSnapshot(), PortalDefineQuery(), PortalGetHeapMemory, PortalSetResultFormat(), PortalStart(), pq_getmsgbytes(), pq_getmsgend(), pq_getmsgint(), pq_getmsgstring(), pq_putemptymessage(), pstrdup(), ParamExternData::ptype, PushActiveSnapshot(), CachedPlanSource::query_string, CachedPlanSource::raw_parse_tree, ResetUsage(), set_ps_display(), ShowUsage(), start_xact_command(), STATE_RUNNING, CachedPlan::stmt_list, ParamExternData::value, and whereToSendOutput.
Referenced by PostgresMain().
{ const char *portal_name; const char *stmt_name; int numPFormats; int16 *pformats = NULL; int numParams; int numRFormats; int16 *rformats = NULL; CachedPlanSource *psrc; CachedPlan *cplan; Portal portal; char *query_string; char *saved_stmt_name; ParamListInfo params; MemoryContext oldContext; bool save_log_statement_stats = log_statement_stats; bool snapshot_set = false; char msec_str[32]; /* Get the fixed part of the message */ portal_name = pq_getmsgstring(input_message); stmt_name = pq_getmsgstring(input_message); ereport(DEBUG2, (errmsg("bind %s to %s", *portal_name ? portal_name : "<unnamed>", *stmt_name ? stmt_name : "<unnamed>"))); /* Find prepared statement */ if (stmt_name[0] != '\0') { PreparedStatement *pstmt; pstmt = FetchPreparedStatement(stmt_name, true); psrc = pstmt->plansource; } else { /* special-case the unnamed statement */ psrc = unnamed_stmt_psrc; if (!psrc) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_PSTATEMENT), errmsg("unnamed prepared statement does not exist"))); } /* * Report query to various monitoring facilities. */ debug_query_string = psrc->query_string; pgstat_report_activity(STATE_RUNNING, psrc->query_string); set_ps_display("BIND", false); if (save_log_statement_stats) ResetUsage(); /* * 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. */ start_xact_command(); /* Switch back to message context */ MemoryContextSwitchTo(MessageContext); /* Get the parameter format codes */ numPFormats = pq_getmsgint(input_message, 2); if (numPFormats > 0) { int i; 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) ereport(ERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("bind message has %d parameter formats but %d parameters", numPFormats, numParams))); if (numParams != psrc->num_params) ereport(ERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("bind message supplies %d parameters, but prepared statement \"%s\" requires %d", numParams, stmt_name, psrc->num_params))); /* * If we are in aborted transaction state, the only portals we can * actually run are those containing COMMIT or ROLLBACK commands. We * disallow binding anything else to avoid problems with infrastructure * that expects to run inside a valid transaction. We also disallow * binding any parameters, since we can't risk calling user-defined I/O * functions. */ if (IsAbortedTransactionBlockState() && (!IsTransactionExitStmt(psrc->raw_parse_tree) || numParams != 0)) ereport(ERROR, (errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION), errmsg("current transaction is aborted, " "commands ignored until end of transaction block"), errdetail_abort())); /* * 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); /* * Prepare to copy stuff into the portal's memory context. We do all this * copying first, because it could possibly fail (out-of-memory) and we * don't want a failure to occur between GetCachedPlan and * PortalDefineQuery; that would result in leaking our plancache refcount. */ oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal)); /* Copy the plan's query string into the portal */ query_string = pstrdup(psrc->query_string); /* Likewise make a copy of the statement name, unless it's unnamed */ if (stmt_name[0]) saved_stmt_name = pstrdup(stmt_name); else saved_stmt_name = NULL; /* * Set a snapshot if we have parameters to fetch (since the input * functions might need it) or the query isn't a utility command (and * hence could require redoing parse analysis and planning). We keep the * snapshot active till we're done, so that plancache.c doesn't have to * take new ones. */ if (numParams > 0 || analyze_requires_snapshot(psrc->raw_parse_tree)) { PushActiveSnapshot(GetTransactionSnapshot()); snapshot_set = true; } /* * Fetch parameters, if any, and store in the portal's memory context. */ if (numParams > 0) { int paramno; /* sizeof(ParamListInfoData) includes the first array element */ params = (ParamListInfo) palloc(sizeof(ParamListInfoData) + (numParams - 1) * sizeof(ParamExternData)); /* we have static list of params, so no hooks needed */ params->paramFetch = NULL; params->paramFetchArg = NULL; params->parserSetup = NULL; params->parserSetupArg = NULL; params->numParams = numParams; for (paramno = 0; paramno < numParams; paramno++) { Oid ptype = psrc->param_types[paramno]; int32 plength; Datum pval; bool isNull; StringInfoData pbuf; char csave; int16 pformat; plength = pq_getmsgint(input_message, 4); isNull = (plength == -1); if (!isNull) { const char *pvalue = pq_getmsgbytes(input_message, plength); /* * 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. */ pbuf.data = (char *) pvalue; pbuf.maxlen = plength + 1; pbuf.len = plength; pbuf.cursor = 0; csave = pbuf.data[plength]; pbuf.data[plength] = '\0'; } else { pbuf.data = NULL; /* keep compiler quiet */ csave = 0; } if (numPFormats > 1) pformat = pformats[paramno]; else if (numPFormats > 0) pformat = pformats[0]; else pformat = 0; /* default = text */ if (pformat == 0) /* text mode */ { Oid typinput; Oid typioparam; char *pstring; getTypeInputInfo(ptype, &typinput, &typioparam); /* * We have to do encoding conversion before calling the * typinput routine. */ if (isNull) pstring = NULL; else pstring = pg_client_to_server(pbuf.data, plength); pval = OidInputFunctionCall(typinput, pstring, typioparam, -1); /* Free result of encoding conversion, if any */ if (pstring && pstring != pbuf.data) pfree(pstring); } else if (pformat == 1) /* binary mode */ { Oid typreceive; Oid typioparam; StringInfo bufptr; /* * Call the parameter type's binary input converter */ getTypeBinaryInputInfo(ptype, &typreceive, &typioparam); if (isNull) bufptr = NULL; else bufptr = &pbuf; pval = OidReceiveFunctionCall(typreceive, bufptr, typioparam, -1); /* Trouble if it didn't eat the whole buffer */ if (!isNull && pbuf.cursor != pbuf.len) ereport(ERROR, (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), errmsg("incorrect binary data format in bind parameter %d", paramno + 1))); } else { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("unsupported format code: %d", pformat))); pval = 0; /* keep compiler quiet */ } /* Restore message buffer contents */ if (!isNull) pbuf.data[plength] = csave; params->params[paramno].value = pval; params->params[paramno].isnull = isNull; /* * We mark the params as CONST. This ensures that any custom plan * makes full use of the parameter values. */ params->params[paramno].pflags = PARAM_FLAG_CONST; params->params[paramno].ptype = ptype; } } else params = NULL; /* Done storing stuff in portal's context */ MemoryContextSwitchTo(oldContext); /* Get the result format codes */ numRFormats = pq_getmsgint(input_message, 2); if (numRFormats > 0) { int i; rformats = (int16 *) palloc(numRFormats * sizeof(int16)); for (i = 0; i < numRFormats; i++) rformats[i] = pq_getmsgint(input_message, 2); } pq_getmsgend(input_message); /* * Obtain a plan from the CachedPlanSource. Any cruft from (re)planning * will be generated in MessageContext. The plan refcount will be * assigned to the Portal, so it will be released at portal destruction. */ cplan = GetCachedPlan(psrc, params, false); /* * Now we can define the portal. * * DO NOT put any code that could possibly throw an error between the * above GetCachedPlan call and here. */ PortalDefineQuery(portal, saved_stmt_name, query_string, psrc->commandTag, cplan->stmt_list, cplan); /* Done with the snapshot used for parameter I/O and parsing/planning */ if (snapshot_set) PopActiveSnapshot(); /* * And we're ready to start portal execution. */ PortalStart(portal, params, 0, InvalidSnapshot); /* * Apply the result format requests to the portal. */ PortalSetResultFormat(portal, numRFormats, rformats); /* * Send BindComplete. */ if (whereToSendOutput == DestRemote) pq_putemptymessage('2'); /* * Emit duration logging if appropriate. */ switch (check_log_duration(msec_str, false)) { case 1: ereport(LOG, (errmsg("duration: %s ms", msec_str), errhidestmt(true))); break; case 2: ereport(LOG, (errmsg("duration: %s ms bind %s%s%s: %s", msec_str, *stmt_name ? stmt_name : "<unnamed>", *portal_name ? "/" : "", *portal_name ? portal_name : "", psrc->query_string), errhidestmt(true), errdetail_params(params))); break; } if (save_log_statement_stats) ShowUsage("BIND MESSAGE STATISTICS"); debug_query_string = NULL; }
static void exec_describe_portal_message | ( | const char * | portal_name | ) | [static] |
Definition at line 2329 of file postgres.c.
References DestRemote, ereport, errcode(), errdetail_abort(), errmsg(), ERROR, FetchPortalTargetList(), PortalData::formats, GetPortalByName(), IsAbortedTransactionBlockState(), MemoryContextSwitchTo(), MessageContext, PortalIsValid, pq_putemptymessage(), SendRowDescriptionMessage(), start_xact_command(), PortalData::tupDesc, and whereToSendOutput.
Referenced by PostgresMain().
{ 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"), errdetail_abort())); if (whereToSendOutput != DestRemote) return; /* can't actually do anything... */ if (portal->tupDesc) SendRowDescriptionMessage(portal->tupDesc, FetchPortalTargetList(portal), portal->formats); else pq_putemptymessage('n'); /* NoData */ }
static void exec_describe_statement_message | ( | const char * | stmt_name | ) | [static] |
Definition at line 2236 of file postgres.c.
References Assert, buf, CachedPlanGetTargetList(), DestRemote, ereport, errcode(), errdetail_abort(), errmsg(), ERROR, FetchPreparedStatement(), CachedPlanSource::fixed_result, i, IsAbortedTransactionBlockState(), MemoryContextSwitchTo(), MessageContext, NULL, CachedPlanSource::num_params, CachedPlanSource::param_types, PreparedStatement::plansource, pq_beginmessage(), pq_endmessage(), pq_putemptymessage(), pq_sendint(), CachedPlanSource::resultDesc, SendRowDescriptionMessage(), start_xact_command(), and whereToSendOutput.
Referenced by PostgresMain().
{ CachedPlanSource *psrc; StringInfoData buf; int i; /* * 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); /* Find prepared statement */ if (stmt_name[0] != '\0') { PreparedStatement *pstmt; pstmt = FetchPreparedStatement(stmt_name, true); psrc = pstmt->plansource; } else { /* special-case the unnamed statement */ psrc = unnamed_stmt_psrc; if (!psrc) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_PSTATEMENT), errmsg("unnamed prepared statement does not exist"))); } /* Prepared statements shouldn't have changeable result descs */ Assert(psrc->fixed_result); /* * If we are in aborted transaction state, we can't run * SendRowDescriptionMessage(), because that needs catalog accesses. * Hence, refuse to Describe statements 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.) We can Describe parameters * without doing anything dangerous, so we don't restrict that. */ if (IsAbortedTransactionBlockState() && psrc->resultDesc) ereport(ERROR, (errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION), errmsg("current transaction is aborted, " "commands ignored until end of transaction block"), errdetail_abort())); if (whereToSendOutput != DestRemote) return; /* can't actually do anything... */ /* * First describe the parameters... */ pq_beginmessage(&buf, 't'); /* parameter description message type */ pq_sendint(&buf, psrc->num_params, 2); for (i = 0; i < psrc->num_params; i++) { Oid ptype = psrc->param_types[i]; pq_sendint(&buf, (int) ptype, 4); } pq_endmessage(&buf); /* * Next send RowDescription or NoData to describe the result... */ if (psrc->resultDesc) { List *tlist; /* Get the plan's primary targetlist */ tlist = CachedPlanGetTargetList(psrc); SendRowDescriptionMessage(psrc->resultDesc, tlist, NULL); } else pq_putemptymessage('n'); /* NoData */ }
static void exec_execute_message | ( | const char * | portal_name, | |
long | max_rows | |||
) | [static] |
Definition at line 1787 of file postgres.c.
References _, Assert, PortalData::atStart, BeginCommand(), CHECK_FOR_INTERRUPTS, check_log_duration(), check_log_statement(), CommandCounterIncrement(), PortalData::commandTag, CreateDestReceiver(), debug_query_string, DestRemote, DestRemoteExecute, EndCommand(), ereport, errcode(), errdetail_abort(), errdetail_params(), errhidestmt(), errmsg(), ERROR, finish_xact_command(), GetPortalByName(), IsAbortedTransactionBlockState(), IsTransactionExitStmtList(), IsTransactionStmtList(), LOG, log_statement_stats, NIL, NULL, NullCommand(), pgstat_report_activity(), PortalIsValid, PortalData::portalParams, PortalRun(), pq_putemptymessage(), PortalData::prepStmtName, pstrdup(), _DestReceiver::rDestroy, ResetUsage(), set_ps_display(), SetRemoteDestReceiverParams(), ShowUsage(), PortalData::sourceText, start_xact_command(), STATE_RUNNING, PortalData::stmts, and whereToSendOutput.
Referenced by PostgresMain().
{ CommandDest dest; DestReceiver *receiver; Portal portal; bool completed; char completionTag[COMPLETION_TAG_BUFSIZE]; const char *sourceText; const char *prepStmtName; ParamListInfo portalParams; bool save_log_statement_stats = log_statement_stats; bool is_xact_command; bool execute_is_fetch; bool was_logged = false; char msec_str[32]; /* Adjust destination to tell printtup.c what to do */ dest = whereToSendOutput; if (dest == DestRemote) dest = DestRemoteExecute; portal = GetPortalByName(portal_name); if (!PortalIsValid(portal)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_CURSOR), errmsg("portal \"%s\" does not exist", portal_name))); /* * If the original query was a null string, just return * EmptyQueryResponse. */ if (portal->commandTag == NULL) { Assert(portal->stmts == NIL); NullCommand(dest); return; } /* Does the portal contain a transaction command? */ is_xact_command = IsTransactionStmtList(portal->stmts); /* * We must copy the sourceText and prepStmtName into MessageContext in * case the portal is destroyed during finish_xact_command. Can avoid the * copy if it's not an xact command, though. */ if (is_xact_command) { sourceText = pstrdup(portal->sourceText); if (portal->prepStmtName) prepStmtName = pstrdup(portal->prepStmtName); else prepStmtName = "<unnamed>"; /* * An xact command shouldn't have any parameters, which is a good * thing because they wouldn't be around after finish_xact_command. */ portalParams = NULL; } else { sourceText = portal->sourceText; if (portal->prepStmtName) prepStmtName = portal->prepStmtName; else prepStmtName = "<unnamed>"; portalParams = portal->portalParams; } /* * Report query to various monitoring facilities. */ debug_query_string = sourceText; pgstat_report_activity(STATE_RUNNING, sourceText); set_ps_display(portal->commandTag, false); if (save_log_statement_stats) ResetUsage(); BeginCommand(portal->commandTag, dest); /* * 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); if (dest == DestRemoteExecute) SetRemoteDestReceiverParams(receiver, portal); /* * Ensure we are in a transaction command (this should normally be the * case already due to prior BIND). */ start_xact_command(); /* * If we re-issue an Execute protocol request against an existing portal, * then we are only fetching more rows rather than completely re-executing * the query from the start. atStart is never reset for a v3 portal, so we * are safe to use this check. */ execute_is_fetch = !portal->atStart; /* Log immediately if dictated by log_statement */ if (check_log_statement(portal->stmts)) { ereport(LOG, (errmsg("%s %s%s%s: %s", execute_is_fetch ? _("execute fetch from") : _("execute"), prepStmtName, *portal_name ? "/" : "", *portal_name ? portal_name : "", sourceText), errhidestmt(true), errdetail_params(portalParams))); was_logged = true; } /* * If we are in aborted transaction state, the only portals we can * actually run are those containing COMMIT or ROLLBACK commands. */ if (IsAbortedTransactionBlockState() && !IsTransactionExitStmtList(portal->stmts)) ereport(ERROR, (errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION), errmsg("current transaction is aborted, " "commands ignored until end of transaction block"), errdetail_abort())); /* 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, true, /* always top level */ receiver, receiver, completionTag); (*receiver->rDestroy) (receiver); if (completed) { if (is_xact_command) { /* * 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 == DestRemote) pq_putemptymessage('s'); } /* * Emit duration logging if appropriate. */ switch (check_log_duration(msec_str, was_logged)) { case 1: ereport(LOG, (errmsg("duration: %s ms", msec_str), errhidestmt(true))); break; case 2: ereport(LOG, (errmsg("duration: %s ms %s %s%s%s: %s", msec_str, execute_is_fetch ? _("execute fetch from") : _("execute"), prepStmtName, *portal_name ? "/" : "", *portal_name ? portal_name : "", sourceText), errhidestmt(true), errdetail_params(portalParams))); break; } if (save_log_statement_stats) ShowUsage("EXECUTE MESSAGE STATISTICS"); debug_query_string = NULL; }
static void exec_parse_message | ( | const char * | query_string, | |
const char * | stmt_name, | |||
Oid * | paramTypes, | |||
int | numParams | |||
) | [static] |
Definition at line 1143 of file postgres.c.
References ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, ALLOCSET_DEFAULT_MINSIZE, AllocSetContextCreate(), analyze_requires_snapshot(), CHECK_FOR_INTERRUPTS, check_log_duration(), CommandCounterIncrement(), CompleteCachedPlan(), CachedPlanSource::context, CreateCachedPlan(), CreateCommandTag(), DEBUG2, debug_query_string, DestRemote, drop_unnamed_stmt(), ereport, errcode(), errdetail_abort(), errhidestmt(), errmsg(), ERROR, GetTransactionSnapshot(), i, InvalidOid, IsAbortedTransactionBlockState(), IsTransactionExitStmt(), linitial, list_length(), LOG, log_parser_stats, log_statement_stats, MemoryContextSetParent(), MemoryContextSwitchTo(), MessageContext, NIL, NULL, parse_analyze_varparams(), pg_parse_query(), pg_rewrite_query(), pgstat_report_activity(), PopActiveSnapshot(), pq_putemptymessage(), PushActiveSnapshot(), ResetUsage(), SaveCachedPlan(), set_ps_display(), ShowUsage(), start_xact_command(), STATE_RUNNING, StorePreparedStatement(), UNKNOWNOID, and whereToSendOutput.
Referenced by PostgresMain().
{ MemoryContext unnamed_stmt_context = NULL; MemoryContext oldcontext; List *parsetree_list; Node *raw_parse_tree; const char *commandTag; List *querytree_list; CachedPlanSource *psrc; bool is_named; bool save_log_statement_stats = log_statement_stats; char msec_str[32]; /* * Report query to various monitoring facilities. */ debug_query_string = query_string; pgstat_report_activity(STATE_RUNNING, query_string); set_ps_display("PARSE", false); if (save_log_statement_stats) ResetUsage(); ereport(DEBUG2, (errmsg("parse %s: %s", *stmt_name ? stmt_name : "<unnamed>", query_string))); /* * 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. * * 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 plancache entry; then the reset of MessageContext releases * temporary space used by parsing and rewriting. 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 trees. So in this case, we create the plancache entry's * query_context here, and do all the parsing work therein. */ 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 */ drop_unnamed_stmt(); /* Create context for parsing */ unnamed_stmt_context = AllocSetContextCreate(MessageContext, "unnamed prepared statement", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); oldcontext = MemoryContextSwitchTo(unnamed_stmt_context); } /* * 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); /* * 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. */ if (list_length(parsetree_list) > 1) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("cannot insert multiple commands into a prepared statement"))); if (parsetree_list != NIL) { Query *query; bool snapshot_set = false; int i; raw_parse_tree = (Node *) linitial(parsetree_list); /* * Get the command name for possible use in status display. */ commandTag = CreateCommandTag(raw_parse_tree); /* * If we are in an aborted transaction, reject all commands except * 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 commands in this * state, but not many...) */ if (IsAbortedTransactionBlockState() && !IsTransactionExitStmt(raw_parse_tree)) ereport(ERROR, (errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION), errmsg("current transaction is aborted, " "commands ignored until end of transaction block"), errdetail_abort())); /* * Create the CachedPlanSource before we do parse analysis, since it * needs to see the unmodified raw parse tree. */ psrc = CreateCachedPlan(raw_parse_tree, query_string, commandTag); /* * Set up a snapshot if parse analysis will need one. */ if (analyze_requires_snapshot(raw_parse_tree)) { PushActiveSnapshot(GetTransactionSnapshot()); snapshot_set = true; } /* * Analyze and rewrite the 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(); query = parse_analyze_varparams(raw_parse_tree, query_string, ¶mTypes, &numParams); /* * Check all parameter types got determined. */ for (i = 0; i < numParams; i++) { Oid ptype = paramTypes[i]; if (ptype == InvalidOid || ptype == UNKNOWNOID) ereport(ERROR, (errcode(ERRCODE_INDETERMINATE_DATATYPE), errmsg("could not determine data type of parameter $%d", i + 1))); } if (log_parser_stats) ShowUsage("PARSE ANALYSIS STATISTICS"); querytree_list = pg_rewrite_query(query); /* Done with the snapshot used for parsing */ if (snapshot_set) PopActiveSnapshot(); } else { /* Empty input string. This is legal. */ raw_parse_tree = NULL; commandTag = NULL; psrc = CreateCachedPlan(raw_parse_tree, query_string, commandTag); querytree_list = NIL; } /* * CachedPlanSource must be a direct child of MessageContext before we * reparent unnamed_stmt_context under it, else we have a disconnected * circular subgraph. Klugy, but less so than flipping contexts even more * above. */ if (unnamed_stmt_context) MemoryContextSetParent(psrc->context, MessageContext); /* Finish filling in the CachedPlanSource */ CompleteCachedPlan(psrc, querytree_list, unnamed_stmt_context, paramTypes, numParams, NULL, NULL, 0, /* default cursor options */ true); /* fixed result */ /* If we got a cancel signal during analysis, quit */ CHECK_FOR_INTERRUPTS(); if (is_named) { /* * Store the query as a prepared statement. */ StorePreparedStatement(stmt_name, psrc, false); } else { /* * We just save the CachedPlanSource into unnamed_stmt_psrc. */ SaveCachedPlan(psrc); unnamed_stmt_psrc = psrc; } MemoryContextSwitchTo(oldcontext); /* * 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. */ CommandCounterIncrement(); /* * Send ParseComplete. */ if (whereToSendOutput == DestRemote) pq_putemptymessage('1'); /* * Emit duration logging if appropriate. */ switch (check_log_duration(msec_str, false)) { case 1: ereport(LOG, (errmsg("duration: %s ms", msec_str), errhidestmt(true))); break; case 2: ereport(LOG, (errmsg("duration: %s ms parse %s: %s", msec_str, *stmt_name ? stmt_name : "<unnamed>", query_string), errhidestmt(true))); break; } if (save_log_statement_stats) ShowUsage("PARSE MESSAGE STATISTICS"); debug_query_string = NULL; }
static void exec_simple_query | ( | const char * | query_string | ) | [static] |
Definition at line 828 of file postgres.c.
References analyze_requires_snapshot(), BeginCommand(), CHECK_FOR_INTERRUPTS, check_log_duration(), check_log_statement(), CommandCounterIncrement(), CreateCommandTag(), CreateDestReceiver(), CreatePortal(), CURSOR_OPT_BINARY, PortalData::cursorOptions, debug_query_string, DestRemote, drop_unnamed_stmt(), EndCommand(), ereport, errcode(), errdetail_abort(), errdetail_execute(), errhidestmt(), errmsg(), ERROR, FETCH_ALL, finish_xact_command(), format, GetPortalByName(), GetTransactionSnapshot(), InvalidSnapshot, IsA, IsAbortedTransactionBlockState(), FetchStmt::ismove, IsTransactionExitStmt(), lfirst, list_length(), lnext, LOG, log_statement_stats, MemoryContextSwitchTo(), MessageContext, NULL, NullCommand(), pg_analyze_and_rewrite(), pg_parse_query(), pg_plan_queries(), pgstat_report_activity(), PopActiveSnapshot(), PortalDefineQuery(), PortalDrop(), PortalIsValid, FetchStmt::portalname, PortalRun(), PortalSetResultFormat(), PortalStart(), PushActiveSnapshot(), _DestReceiver::rDestroy, ResetUsage(), set_ps_display(), SetRemoteDestReceiverParams(), ShowUsage(), start_xact_command(), STATE_RUNNING, PortalData::visible, and whereToSendOutput.
Referenced by PostgresMain().
{ CommandDest dest = whereToSendOutput; MemoryContext oldcontext; List *parsetree_list; ListCell *parsetree_item; bool save_log_statement_stats = log_statement_stats; bool was_logged = false; bool isTopLevel; char msec_str[32]; /* * Report query to various monitoring facilities. */ debug_query_string = query_string; pgstat_report_activity(STATE_RUNNING, query_string); TRACE_POSTGRESQL_QUERY_START(query_string); /* * We use save_log_statement_stats so ShowUsage doesn't report incorrect * results because ResetUsage wasn't called. */ if (save_log_statement_stats) ResetUsage(); /* * 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 that this * will normally change current memory context.) */ start_xact_command(); /* * 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.) */ drop_unnamed_stmt(); /* * Switch to appropriate context for constructing parsetrees. */ oldcontext = MemoryContextSwitchTo(MessageContext); /* * 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); /* Log immediately if dictated by log_statement */ if (check_log_statement(parsetree_list)) { ereport(LOG, (errmsg("statement: %s", query_string), errhidestmt(true), errdetail_execute(parsetree_list))); was_logged = true; } /* * Switch back to transaction context to enter the loop. */ MemoryContextSwitchTo(oldcontext); /* * We'll tell PortalRun it's a top-level command iff there's exactly one * raw parsetree. If more than one, it's effectively a transaction block * and we want PreventTransactionChain to reject unsafe commands. (Note: * we're assuming that query rewrite cannot add commands that are * significant to PreventTransactionChain.) */ isTopLevel = (list_length(parsetree_list) == 1); /* * Run through the raw parsetree(s) and process each one. */ foreach(parsetree_item, parsetree_list) { Node *parsetree = (Node *) lfirst(parsetree_item); bool snapshot_set = false; const char *commandTag; char completionTag[COMPLETION_TAG_BUFSIZE]; List *querytree_list, *plantree_list; Portal portal; DestReceiver *receiver; int16 format; /* * 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. */ commandTag = CreateCommandTag(parsetree); set_ps_display(commandTag, false); BeginCommand(commandTag, dest); /* * If we are in an aborted transaction, reject all commands except * COMMIT/ABORT. 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 commands in this * state, but not many...) */ if (IsAbortedTransactionBlockState() && !IsTransactionExitStmt(parsetree)) ereport(ERROR, (errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION), errmsg("current transaction is aborted, " "commands ignored until end of transaction block"), errdetail_abort())); /* Make sure we are in a transaction command */ start_xact_command(); /* If we got a cancel signal in parsing or prior command, quit */ CHECK_FOR_INTERRUPTS(); /* * Set up a snapshot if parse analysis/planning will need one. */ if (analyze_requires_snapshot(parsetree)) { PushActiveSnapshot(GetTransactionSnapshot()); snapshot_set = true; } /* * OK to analyze, rewrite, and plan this query. * * Switch to appropriate context for constructing querytrees (again, * these must outlive the execution context). */ oldcontext = MemoryContextSwitchTo(MessageContext); querytree_list = pg_analyze_and_rewrite(parsetree, query_string, NULL, 0); plantree_list = pg_plan_queries(querytree_list, 0, NULL); /* Done with the snapshot used for parsing/planning */ if (snapshot_set) PopActiveSnapshot(); /* If we got a cancel signal in analysis or planning, quit */ CHECK_FOR_INTERRUPTS(); /* * Create unnamed portal to run the query or queries in. If there * already is one, silently drop it. */ portal = CreatePortal("", true, true); /* Don't display the portal in pg_cursors */ portal->visible = false; /* * We don't have to copy anything into the portal, because everything * we are passing here is in MessageContext, which will outlive the * portal anyway. */ PortalDefineQuery(portal, NULL, query_string, commandTag, plantree_list, NULL); /* * Start the portal. No parameters here. */ PortalStart(portal, NULL, 0, InvalidSnapshot); /* * Select the appropriate output format: text unless we are doing 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...) */ 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)) format = 1; /* BINARY */ } } PortalSetResultFormat(portal, 1, &format); /* * Now we can create the destination receiver object. */ receiver = CreateDestReceiver(dest); if (dest == DestRemote) SetRemoteDestReceiverParams(receiver, portal); /* * Switch back to transaction context for execution. */ MemoryContextSwitchTo(oldcontext); /* * Run the portal to completion, and then drop it (and the receiver). */ (void) PortalRun(portal, FETCH_ALL, isTopLevel, receiver, receiver, completionTag); (*receiver->rDestroy) (receiver); PortalDrop(portal, false); if (IsA(parsetree, TransactionStmt)) { /* * 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 if (lnext(parsetree_item) == NULL) { /* * 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. */ finish_xact_command(); } else { /* * We need a CommandCounterIncrement after every query, except * those that start or end a transaction block. */ CommandCounterIncrement(); } /* * Tell client that we're done with this query. Note we emit 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.) */ EndCommand(completionTag, dest); } /* end loop over parsetrees */ /* * Close down transaction statement, if one is open. */ finish_xact_command(); /* * If there were no parsetrees, return EmptyQueryResponse message. */ if (!parsetree_list) NullCommand(dest); /* * Emit duration logging if appropriate. */ switch (check_log_duration(msec_str, was_logged)) { case 1: ereport(LOG, (errmsg("duration: %s ms", msec_str), errhidestmt(true))); break; case 2: ereport(LOG, (errmsg("duration: %s ms statement: %s", msec_str, query_string), errhidestmt(true), errdetail_execute(parsetree_list))); break; } if (save_log_statement_stats) ShowUsage("QUERY STATISTICS"); TRACE_POSTGRESQL_QUERY_DONE(query_string); debug_query_string = NULL; }
static void finish_xact_command | ( | void | ) | [static] |
Definition at line 2400 of file postgres.c.
References CommitTransactionCommand(), DEBUG3, disable_timeout(), ereport, errmsg_internal(), MemoryContextStats(), STATEMENT_TIMEOUT, TopMemoryContext, and xact_started.
Referenced by exec_execute_message(), exec_simple_query(), and PostgresMain().
{ if (xact_started) { /* Cancel any active statement timeout before committing */ disable_timeout(STATEMENT_TIMEOUT, false); /* 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 */ MemoryContextStats(TopMemoryContext); #endif xact_started = false; } }
void FloatExceptionHandler | ( | SIGNAL_ARGS | ) |
Definition at line 2655 of file postgres.c.
References ereport, errcode(), errdetail(), errmsg(), and ERROR.
Referenced by AutoVacLauncherMain(), AutoVacWorkerMain(), do_start_bgworker(), plperl_init_interp(), and PostgresMain().
{ /* We're not returning, so no need to save errno */ 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."))); }
static void forbidden_in_wal_sender | ( | char | firstchar | ) | [static] |
Definition at line 4237 of file postgres.c.
References am_walsender, ereport, errcode(), errmsg(), and ERROR.
Referenced by PostgresMain().
{ if (am_walsender) { if (firstchar == 'F') ereport(ERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("fastpath function calls not supported in a replication connection"))); else ereport(ERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("extended query protocol not supported in a replication connection"))); } }
long get_stack_depth_rlimit | ( | void | ) |
Definition at line 4259 of file postgres.c.
References val.
Referenced by check_max_stack_depth(), and InitializeGUCOptionsFromEnvironment().
{ #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_STACK) static long val = 0; /* This won't change after process launch, so check just once */ if (val == 0) { struct rlimit rlim; if (getrlimit(RLIMIT_STACK, &rlim) < 0) val = -1; else if (rlim.rlim_cur == RLIM_INFINITY) val = LONG_MAX; /* rlim_cur is probably of an unsigned type, so check for overflow */ else if (rlim.rlim_cur >= LONG_MAX) val = LONG_MAX; else val = rlim.rlim_cur; } return val; #else /* no getrlimit */ #if defined(WIN32) || defined(__CYGWIN__) /* On Windows we set the backend stack size in src/backend/Makefile */ return WIN32_STACK_RLIMIT; #else /* not windows ... give up */ return -1; #endif #endif }
const char* get_stats_option_name | ( | const char * | arg | ) |
Definition at line 3215 of file postgres.c.
References optarg.
Referenced by PostmasterMain(), and process_postgres_switches().
static int interactive_getc | ( | void | ) | [static] |
Definition at line 318 of file postgres.c.
References client_read_ended(), and prepare_for_client_read().
Referenced by InteractiveBackend().
{ int c; prepare_for_client_read(); c = getc(stdin); client_read_ended(); return c; }
static int InteractiveBackend | ( | StringInfo | inBuf | ) | [static] |
Definition at line 228 of file postgres.c.
References appendStringInfoChar(), StringInfoData::data, EchoQuery, end, interactive_getc(), StringInfoData::len, resetStringInfo(), and UseNewLine.
Referenced by ReadCommand().
{ int c; /* character read from getc() */ bool end = false; /* end-of-input flag */ bool backslashSeen = false; /* have we seen a \ ? */ /* * display a prompt and obtain input from the user */ printf("backend> "); fflush(stdout); resetStringInfo(inBuf); if (UseNewLine) { /* * if we are using \n as a delimiter, then read characters until the * \n. */ while ((c = interactive_getc()) != EOF) { if (c == '\n') { if (backslashSeen) { /* discard backslash from inBuf */ inBuf->data[--inBuf->len] = '\0'; backslashSeen = false; continue; } else { /* keep the newline character */ appendStringInfoChar(inBuf, '\n'); break; } } else if (c == '\\') backslashSeen = true; else backslashSeen = false; appendStringInfoChar(inBuf, (char) c); } if (c == EOF) end = true; } else { /* * otherwise read characters until EOF. */ while ((c = interactive_getc()) != EOF) appendStringInfoChar(inBuf, (char) c); /* No input before EOF signal means time to quit. */ if (inBuf->len == 0) end = true; } if (end) return EOF; /* * otherwise we have a user query so process it. */ /* Add '\0' to make it look the same as message case. */ appendStringInfoChar(inBuf, (char) '\0'); /* * if the query echo flag was given, print the query.. */ if (EchoQuery) printf("statement: %s\n", inBuf->data); fflush(stdout); return 'Q'; }
Definition at line 2436 of file postgres.c.
References IsA, TransactionStmt::kind, TRANS_STMT_COMMIT, TRANS_STMT_PREPARE, TRANS_STMT_ROLLBACK, and TRANS_STMT_ROLLBACK_TO.
Referenced by exec_bind_message(), exec_parse_message(), exec_simple_query(), and IsTransactionExitStmtList().
{ 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; }
Definition at line 2453 of file postgres.c.
References CMD_UTILITY, Query::commandType, IsA, IsTransactionExitStmt(), linitial, list_length(), and Query::utilityStmt.
Referenced by exec_execute_message().
{ if (list_length(parseTrees) == 1) { Node *stmt = (Node *) linitial(parseTrees); if (IsA(stmt, Query)) { Query *query = (Query *) stmt; if (query->commandType == CMD_UTILITY && IsTransactionExitStmt(query->utilityStmt)) return true; } else if (IsTransactionExitStmt(stmt)) return true; } return false; }
Definition at line 2475 of file postgres.c.
References CMD_UTILITY, Query::commandType, IsA, linitial, list_length(), and Query::utilityStmt.
Referenced by exec_execute_message().
{ if (list_length(parseTrees) == 1) { Node *stmt = (Node *) linitial(parseTrees); if (IsA(stmt, Query)) { Query *query = (Query *) stmt; if (query->commandType == CMD_UTILITY && IsA(query->utilityStmt, TransactionStmt)) return true; } else if (IsA(stmt, TransactionStmt)) return true; } return false; }
static void log_disconnections | ( | int | code, | |
Datum | arg | |||
) | [static] |
Definition at line 4397 of file postgres.c.
References Port::database_name, ereport, errmsg(), GetCurrentTimestamp(), LOG, MyProcPort, port, Port::remote_host, Port::remote_port, Port::SessionStartTime, TimestampDifference(), and Port::user_name.
Referenced by PostgresMain().
{ Port *port = MyProcPort; long secs; int usecs; int msecs; int hours, minutes, seconds; TimestampDifference(port->SessionStartTime, GetCurrentTimestamp(), &secs, &usecs); msecs = usecs / 1000; hours = secs / SECS_PER_HOUR; secs %= SECS_PER_HOUR; minutes = secs / SECS_PER_MINUTE; seconds = secs % SECS_PER_MINUTE; ereport(LOG, (errmsg("disconnection: session time: %d:%02d:%02d.%03d " "user=%s database=%s host=%s%s%s", hours, minutes, seconds, msecs, port->user_name, port->database_name, port->remote_host, port->remote_port[0] ? " port=" : "", port->remote_port))); }
List* pg_analyze_and_rewrite | ( | Node * | parsetree, | |
const char * | query_string, | |||
Oid * | paramTypes, | |||
int | numParams | |||
) |
Definition at line 599 of file postgres.c.
References log_parser_stats, parse_analyze(), pg_rewrite_query(), ResetUsage(), and ShowUsage().
Referenced by _SPI_execute_plan(), _SPI_prepare_plan(), BeginCopy(), exec_simple_query(), execute_sql_string(), and RevalidateCachedQuery().
{ Query *query; List *querytree_list; TRACE_POSTGRESQL_QUERY_REWRITE_START(query_string); /* * (1) Perform parse analysis. */ if (log_parser_stats) ResetUsage(); query = parse_analyze(parsetree, query_string, paramTypes, numParams); if (log_parser_stats) ShowUsage("PARSE ANALYSIS STATISTICS"); /* * (2) Rewrite the queries, as necessary */ querytree_list = pg_rewrite_query(query); TRACE_POSTGRESQL_QUERY_REWRITE_DONE(query_string); return querytree_list; }
List* pg_analyze_and_rewrite_params | ( | Node * | parsetree, | |
const char * | query_string, | |||
ParserSetupHook | parserSetup, | |||
void * | parserSetupArg | |||
) |
Definition at line 634 of file postgres.c.
References Assert, free_parsestate(), log_parser_stats, make_parsestate(), NULL, ParseState::p_sourcetext, pg_rewrite_query(), post_parse_analyze_hook, ResetUsage(), ShowUsage(), and transformTopLevelStmt().
Referenced by _SPI_execute_plan(), _SPI_prepare_plan(), fmgr_sql_validator(), init_sql_fcache(), inline_set_returning_function(), and RevalidateCachedQuery().
{ ParseState *pstate; Query *query; List *querytree_list; Assert(query_string != NULL); /* required as of 8.4 */ TRACE_POSTGRESQL_QUERY_REWRITE_START(query_string); /* * (1) Perform parse analysis. */ if (log_parser_stats) ResetUsage(); pstate = make_parsestate(NULL); pstate->p_sourcetext = query_string; (*parserSetup) (pstate, parserSetupArg); query = transformTopLevelStmt(pstate, parsetree); if (post_parse_analyze_hook) (*post_parse_analyze_hook) (pstate, query); free_parsestate(pstate); if (log_parser_stats) ShowUsage("PARSE ANALYSIS STATISTICS"); /* * (2) Rewrite the queries, as necessary */ querytree_list = pg_rewrite_query(query); TRACE_POSTGRESQL_QUERY_REWRITE_DONE(query_string); return querytree_list; }
List* pg_parse_query | ( | const char * | query_string | ) |
Definition at line 557 of file postgres.c.
References copyObject(), elog, equal(), log_parser_stats, new_list(), raw_parser(), ResetUsage(), ShowUsage(), and WARNING.
Referenced by _SPI_prepare_oneshot_plan(), _SPI_prepare_plan(), exec_parse_message(), exec_simple_query(), execute_sql_string(), fmgr_sql_validator(), init_sql_fcache(), inline_function(), and inline_set_returning_function().
{ List *raw_parsetree_list; TRACE_POSTGRESQL_QUERY_PARSE_START(query_string); if (log_parser_stats) ResetUsage(); raw_parsetree_list = raw_parser(query_string); if (log_parser_stats) ShowUsage("PARSER STATISTICS"); #ifdef COPY_PARSE_PLAN_TREES /* Optional debugging check: pass raw parsetrees through copyObject() */ { List *new_list = (List *) copyObject(raw_parsetree_list); /* This checks both copyObject() and the equal() routines... */ if (!equal(new_list, raw_parsetree_list)) elog(WARNING, "copyObject() failed to produce an equal raw parse tree"); else raw_parsetree_list = new_list; } #endif TRACE_POSTGRESQL_QUERY_PARSE_DONE(query_string); return raw_parsetree_list; }
List* pg_plan_queries | ( | List * | querytrees, | |
int | cursorOptions, | |||
ParamListInfo | boundParams | |||
) |
Definition at line 795 of file postgres.c.
References CMD_UTILITY, Query::commandType, lappend(), lfirst, pg_plan_query(), and Query::utilityStmt.
Referenced by BuildCachedPlan(), exec_simple_query(), and execute_sql_string().
{ List *stmt_list = NIL; ListCell *query_list; foreach(query_list, querytrees) { Query *query = (Query *) lfirst(query_list); Node *stmt; if (query->commandType == CMD_UTILITY) { /* Utility commands have no plans. */ stmt = query->utilityStmt; } else { stmt = (Node *) pg_plan_query(query, cursorOptions, boundParams); } stmt_list = lappend(stmt_list, stmt); } return stmt_list; }
PlannedStmt* pg_plan_query | ( | Query * | querytree, | |
int | cursorOptions, | |||
ParamListInfo | boundParams | |||
) |
Definition at line 736 of file postgres.c.
References ActiveSnapshotSet(), Assert, CMD_UTILITY, Query::commandType, copyObject(), Debug_pretty_print, Debug_print_plan, elog, elog_node_display(), equal(), LOG, log_planner_stats, planner(), ResetUsage(), ShowUsage(), and WARNING.
Referenced by ExecCreateTableAs(), ExplainOneQuery(), init_execution_state(), pg_plan_queries(), and refresh_matview_datafill().
{ PlannedStmt *plan; /* Utility commands have no plans. */ if (querytree->commandType == CMD_UTILITY) return NULL; /* Planner must have a snapshot in case it calls user-defined functions. */ Assert(ActiveSnapshotSet()); TRACE_POSTGRESQL_QUERY_PLAN_START(); if (log_planner_stats) ResetUsage(); /* call the optimizer */ plan = planner(querytree, cursorOptions, boundParams); if (log_planner_stats) ShowUsage("PLANNER STATISTICS"); #ifdef COPY_PARSE_PLAN_TREES /* Optional debugging check: pass plan output through copyObject() */ { PlannedStmt *new_plan = (PlannedStmt *) copyObject(plan); /* * equal() currently does not have routines to compare Plan nodes, so * don't try to test equality here. Perhaps fix someday? */ #ifdef NOT_USED /* This checks both copyObject() and the equal() routines... */ if (!equal(new_plan, plan)) elog(WARNING, "copyObject() failed to produce an equal plan tree"); else #endif plan = new_plan; } #endif /* * Print plan if debugging. */ if (Debug_print_plan) elog_node_display(LOG, "plan", plan, Debug_pretty_print); TRACE_POSTGRESQL_QUERY_PLAN_DONE(); return plan; }
Definition at line 684 of file postgres.c.
References CMD_UTILITY, Query::commandType, copyObject(), Debug_pretty_print, Debug_print_parse, Debug_print_rewritten, elog, elog_node_display(), equal(), list_make1, LOG, log_parser_stats, QueryRewrite(), ResetUsage(), ShowUsage(), and WARNING.
Referenced by exec_parse_message(), pg_analyze_and_rewrite(), and pg_analyze_and_rewrite_params().
{ List *querytree_list; if (Debug_print_parse) elog_node_display(LOG, "parse tree", query, Debug_pretty_print); if (log_parser_stats) ResetUsage(); if (query->commandType == CMD_UTILITY) { /* don't rewrite utilities, just dump 'em into result list */ querytree_list = list_make1(query); } else { /* rewrite regular queries */ querytree_list = QueryRewrite(query); } if (log_parser_stats) ShowUsage("REWRITER STATISTICS"); #ifdef COPY_PARSE_PLAN_TREES /* Optional debugging check: pass querytree output through copyObject() */ { List *new_list; new_list = (List *) copyObject(querytree_list); /* This checks both copyObject() and the equal() routines... */ if (!equal(new_list, querytree_list)) elog(WARNING, "copyObject() failed to produce equal parse tree"); else querytree_list = new_list; } #endif if (Debug_print_rewritten) elog_node_display(LOG, "rewritten parse tree", querytree_list, Debug_pretty_print); return querytree_list; }
void PostgresMain | ( | int | argc, | |
char * | argv[], | |||
const char * | dbname, | |||
const char * | username | |||
) |
Definition at line 3518 of file postgres.c.
References AbortCurrentTransaction(), ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, ALLOCSET_DEFAULT_MINSIZE, AllocSetContextCreate(), am_walsender, Assert, BaseInit(), BeginReportingGUCOptions(), BlockSig, buf, ChangeToDataDir(), CreateDataDirLockFile(), DataDir, debug_query_string, DestDebug, DestRemote, die(), disable_all_timeouts(), DisableCatchupInterrupt(), DisableNotifyInterrupt(), doing_extended_query_message, DoingCommandRead, drop_unnamed_stmt(), DropPreparedStatement(), elog, EmitErrorReport(), ereport, errcode(), errmsg(), ERROR, error_context_stack, exec_bind_message(), exec_describe_portal_message(), exec_describe_statement_message(), exec_execute_message(), exec_parse_message(), exec_replication_command(), exec_simple_query(), FATAL, find_my_exec(), finish_xact_command(), FloatExceptionHandler(), FlushErrorState(), forbidden_in_wal_sender(), FrontendProtocol, get_pkglib_path(), GetCurrentTimestamp(), GetPortalByName(), got_SIGHUP, HandleFunctionRequest(), HOLD_INTERRUPTS, i, ignore_till_sync, InitializeGUCOptions(), InitializeMaxBackends(), InitializeTimeouts(), InitPostgres(), InitProcess(), InitProcessing, initStringInfo(), InitWalSender(), InvalidOid, IsAbortedTransactionBlockState(), IsTransactionOrTransactionBlock(), IsUnderPostmaster, log_disconnections(), Log_disconnections, MemoryContextDelete(), MemoryContextInit(), MemoryContextResetAndDeleteChildren(), MemoryContextSwitchTo(), MessageContext, my_exec_path, MyCancelKey, MyProcPid, MyStartTime, NormalProcessing, NULL, on_proc_exit(), palloc(), PG_exception_stack, PG_PROTOCOL_MAJOR, PG_SETMASK, PGC_POSTMASTER, PGC_SIGHUP, PgStartTime, pgstat_report_activity(), pgstat_report_stat(), pkglib_path, PortalDrop(), PortalIsValid, PostmasterContext, pq_beginmessage(), pq_comm_reset(), pq_endmessage(), pq_flush(), pq_getmsgbyte(), pq_getmsgend(), pq_getmsgint(), pq_getmsgstring(), pq_putemptymessage(), pq_sendint(), pqinitmask(), pqsignal(), proc_exit(), process_local_preload_libraries(), process_postgres_switches(), ProcessCompletedNotifies(), ProcessConfigFile(), procsignal_sigusr1_handler(), progname, QueryCancelPending, quickdie(), ReadCommand(), ReadyForQuery(), RESUME_INTERRUPTS, SelectConfigFiles(), set_ps_display(), SetCurrentStatementStartTimestamp(), SetProcessingMode, SIG_DFL, SIG_IGN, SIGCHLD, sigdelset, SIGHUP, SigHupHandler(), sigjmp_buf, SIGPIPE, SIGQUIT, sigsetjmp, SIGUSR1, SIGUSR2, start_xact_command(), STATE_FASTPATH, STATE_IDLE, STATE_IDLEINTRANSACTION, STATE_IDLEINTRANSACTION_ABORTED, StatementCancelHandler(), TopMemoryContext, UnBlockSig, userDoption, ValidatePgVersion(), WalSndErrorCleanup(), WalSndSignals(), whereToSendOutput, and xact_started.
Referenced by BackendRun(), and main().
{ int firstchar; StringInfoData input_message; sigjmp_buf local_sigjmp_buf; volatile bool send_ready_for_query = true; /* * Initialize globals (already done if under postmaster, but not if * standalone). */ if (!IsUnderPostmaster) { MyProcPid = getpid(); MyStartTime = time(NULL); } /* * Fire up essential subsystems: error and memory management * * If we are running under the postmaster, this is done already. */ if (!IsUnderPostmaster) MemoryContextInit(); SetProcessingMode(InitProcessing); /* 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]); } if (pkglib_path[0] == '\0') get_pkglib_path(my_exec_path, pkglib_path); /* * Set default values for command-line options. */ if (!IsUnderPostmaster) InitializeGUCOptions(); /* * Parse command-line options. */ process_postgres_switches(argc, argv, PGC_POSTMASTER, &dbname); /* Must have gotten a database name, or have a default (the username) */ if (dbname == NULL) { dbname = username; if (dbname == NULL) ereport(FATAL, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("%s: no database nor user name specified", progname))); } /* Acquire configuration parameters, unless inherited from postmaster */ if (!IsUnderPostmaster) { if (!SelectConfigFiles(userDoption, progname)) proc_exit(1); } /* * You might expect to see a setsid() call here, but it's not needed, * because if we are under a postmaster then BackendInitialize() did it. */ /* * Set up signal handlers and masks. * * Note that postmaster blocked all signals before forking child process, * so there is no race condition whereby we might receive a signal before * we have set up the handler. * * Also note: it's best not to use any signals that are SIG_IGNored in the * postmaster. If such a signal arrives before we are able to change the * handler to non-SIG_IGN, it'll get dropped. Instead, make a dummy * handler in the postmaster to reserve the signal. (Of course, this isn't * an issue for signals that are locally generated, such as SIGALRM and * SIGPIPE.) */ if (am_walsender) WalSndSignals(); else { pqsignal(SIGHUP, SigHupHandler); /* set flag to read config * file */ pqsignal(SIGINT, StatementCancelHandler); /* cancel current query */ pqsignal(SIGTERM, die); /* cancel current query and exit */ /* * In a standalone backend, SIGQUIT can be generated from the keyboard * easily, while SIGTERM cannot, so we make both signals do die() * rather than quickdie(). */ if (IsUnderPostmaster) pqsignal(SIGQUIT, quickdie); /* hard crash time */ else pqsignal(SIGQUIT, die); /* cancel current query and exit */ InitializeTimeouts(); /* establishes SIGALRM handler */ /* * 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 * midst of output during who-knows-what operation... */ pqsignal(SIGPIPE, SIG_IGN); pqsignal(SIGUSR1, procsignal_sigusr1_handler); pqsignal(SIGUSR2, SIG_IGN); pqsignal(SIGFPE, FloatExceptionHandler); /* * Reset some signals that are accepted by postmaster but not by * backend */ pqsignal(SIGCHLD, SIG_DFL); /* system() requires this on some * platforms */ } pqinitmask(); if (IsUnderPostmaster) { /* We allow SIGQUIT (quickdie) at all times */ sigdelset(&BlockSig, SIGQUIT); } PG_SETMASK(&BlockSig); /* block everything except SIGQUIT */ if (!IsUnderPostmaster) { /* * Validate we have been given a reasonable-looking DataDir (if under * postmaster, assume postmaster did this already). */ Assert(DataDir); ValidatePgVersion(DataDir); /* Change into DataDir (if under postmaster, was done already) */ ChangeToDataDir(); /* * Create lockfile for data directory. */ CreateDataDirLockFile(false); /* Initialize MaxBackends (if under postmaster, was done already) */ InitializeMaxBackends(); } /* Early initialization */ BaseInit(); /* * Create a per-backend PGPROC struct in shared memory, except in the * EXEC_BACKEND case where this was done in SubPostmasterMain. We must do * this before we can use LWLocks (and in the EXEC_BACKEND case we already * had to do some stuff with LWLocks). */ #ifdef EXEC_BACKEND if (!IsUnderPostmaster) InitProcess(); #else InitProcess(); #endif /* We need to allow SIGINT, etc during the initial transaction */ PG_SETMASK(&UnBlockSig); /* * 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. */ InitPostgres(dbname, InvalidOid, username, NULL); /* * If the PostmasterContext is still around, recycle the space; we don't * need it anymore after InitPostgres completes. Note this does not trash * *MyProcPort, because ConnCreate() allocated that space with malloc() * ... else we'd need to copy the Port data first. Also, subsidiary data * such as the username isn't lost either; see ProcessStartupPacket(). */ if (PostmasterContext) { MemoryContextDelete(PostmasterContext); PostmasterContext = NULL; } SetProcessingMode(NormalProcessing); /* * Now all GUC states are fully set up. Report them to client if * appropriate. */ BeginReportingGUCOptions(); /* * Also set up handler to log session end; we have to wait till now to be * sure Log_disconnections has its final value. */ if (IsUnderPostmaster && Log_disconnections) on_proc_exit(log_disconnections, 0); /* Perform initialization specific to a WAL sender process. */ if (am_walsender) InitWalSender(); /* * process any libraries that should be preloaded at backend start (this * likewise can't be done until GUC settings are complete) */ process_local_preload_libraries(); /* * Send this backend's cancellation info to the frontend. */ if (whereToSendOutput == DestRemote && PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2) { StringInfoData buf; pq_beginmessage(&buf, 'K'); pq_sendint(&buf, (int32) MyProcPid, sizeof(int32)); pq_sendint(&buf, (int32) MyCancelKey, sizeof(int32)); pq_endmessage(&buf); /* Need not flush since ReadyForQuery will do it. */ } /* Welcome banner for standalone case */ if (whereToSendOutput == DestDebug) printf("\nPostgreSQL stand-alone backend %s\n", PG_VERSION); /* * Create the memory context we will use in the main loop. * * MessageContext is reset once per iteration of the main loop, ie, upon * completion of processing of each command message from the client. */ MessageContext = AllocSetContextCreate(TopMemoryContext, "MessageContext", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); /* * Remember stand-alone backend startup time */ if (!IsUnderPostmaster) PgStartTime = GetCurrentTimestamp(); /* * POSTGRES main processing loop begins here * * If an exception is encountered, processing resumes here so we abort the * current transaction and start a new one. * * 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 * 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 recovering from an error * during error recovery. (If we get into an infinite loop thereby, it * will soon be stopped by overflow of elog.c's internal state stack.) */ if (sigsetjmp(local_sigjmp_buf, 1) != 0) { /* * NOTE: if you are tempted to add more code in this if-block, * consider the high probability that it should be in * 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. */ /* 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 to * the idle loop anyway, and cancel any active timeout requests. */ QueryCancelPending = false; disable_all_timeouts(false); QueryCancelPending = false; /* again in case timeout occurred */ /* * 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. */ DoingCommandRead = false; DisableNotifyInterrupt(); DisableCatchupInterrupt(); /* Make sure libpq is in a good state */ pq_comm_reset(); /* Report the error to the client and/or server log */ EmitErrorReport(); /* * Make sure debug_query_string gets reset before we possibly clobber * the storage it points at. */ debug_query_string = NULL; /* * Abort the current transaction in order to recover. */ AbortCurrentTransaction(); if (am_walsender) WalSndErrorCleanup(); /* * Now return to normal top-level context and clear ErrorContext for * next time. */ MemoryContextSwitchTo(TopMemoryContext); FlushErrorState(); /* * If we were handling an extended-query-protocol message, initiate * skip till next Sync. This also causes us not to issue * ReadyForQuery (until we get Sync). */ if (doing_extended_query_message) ignore_till_sync = true; /* We don't have a transaction command open anymore */ xact_started = false; /* Now we can allow interrupts again */ RESUME_INTERRUPTS(); } /* We can now handle ereport(ERROR) */ PG_exception_stack = &local_sigjmp_buf; if (!ignore_till_sync) send_ready_for_query = true; /* initially, or after error */ /* * Non-error queries loop here. */ for (;;) { /* * At top of loop, reset extended-query-message flag, so that any * errors encountered in "idle" state don't provoke skip. */ doing_extended_query_message = false; /* * Release storage left over from prior query cycle, and create a new * query input buffer in the cleared MessageContext. */ MemoryContextSwitchTo(MessageContext); MemoryContextResetAndDeleteChildren(MessageContext); initStringInfo(&input_message); /* * (1) If we've reached idle state, tell the frontend we're ready for * a new query. * * Note: this includes fflush()'ing the last of the prior output. * * This is also a good time to send collected statistics to the * collector, and to update the PS stats display. We avoid doing * those every time through the message loop because it'd slow down * processing of batched messages, and because we don't want to report * uncommitted updates (that confuses autovacuum). The notification * processor wants a call too, if we are not in a transaction block. */ if (send_ready_for_query) { if (IsAbortedTransactionBlockState()) { set_ps_display("idle in transaction (aborted)", false); pgstat_report_activity(STATE_IDLEINTRANSACTION_ABORTED, NULL); } else if (IsTransactionOrTransactionBlock()) { set_ps_display("idle in transaction", false); pgstat_report_activity(STATE_IDLEINTRANSACTION, NULL); } else { ProcessCompletedNotifies(); pgstat_report_stat(false); set_ps_display("idle", false); pgstat_report_activity(STATE_IDLE, NULL); } ReadyForQuery(whereToSendOutput); send_ready_for_query = false; } /* * (2) Allow asynchronous signals to be executed immediately if they * come in while we are waiting for client input. (This must be * conditional since we don't want, say, reads on behalf of COPY FROM * STDIN doing the same thing.) */ DoingCommandRead = true; /* * (3) read a command (loop blocks here) */ firstchar = ReadCommand(&input_message); /* * (4) disable async signal conditions again. */ DoingCommandRead = false; /* * (5) check for any other interesting events that happened while we * slept. */ if (got_SIGHUP) { got_SIGHUP = false; ProcessConfigFile(PGC_SIGHUP); } /* * (6) process the command. But ignore it if we're skipping till * Sync. */ if (ignore_till_sync && firstchar != EOF) continue; switch (firstchar) { case 'Q': /* simple query */ { const char *query_string; /* Set statement_timestamp() */ SetCurrentStatementStartTimestamp(); query_string = pq_getmsgstring(&input_message); pq_getmsgend(&input_message); if (am_walsender) exec_replication_command(query_string); else exec_simple_query(query_string); send_ready_for_query = true; } break; case 'P': /* parse */ { const char *stmt_name; const char *query_string; int numParams; Oid *paramTypes = NULL; forbidden_in_wal_sender(firstchar); /* Set statement_timestamp() */ SetCurrentStatementStartTimestamp(); stmt_name = pq_getmsgstring(&input_message); query_string = pq_getmsgstring(&input_message); numParams = pq_getmsgint(&input_message, 2); if (numParams > 0) { int i; paramTypes = (Oid *) palloc(numParams * sizeof(Oid)); for (i = 0; i < numParams; i++) paramTypes[i] = pq_getmsgint(&input_message, 4); } pq_getmsgend(&input_message); exec_parse_message(query_string, stmt_name, paramTypes, numParams); } break; case 'B': /* bind */ forbidden_in_wal_sender(firstchar); /* Set statement_timestamp() */ SetCurrentStatementStartTimestamp(); /* * this message is complex enough that it seems best to put * the field extraction out-of-line */ exec_bind_message(&input_message); break; case 'E': /* execute */ { const char *portal_name; int max_rows; forbidden_in_wal_sender(firstchar); /* Set statement_timestamp() */ SetCurrentStatementStartTimestamp(); portal_name = pq_getmsgstring(&input_message); max_rows = pq_getmsgint(&input_message, 4); pq_getmsgend(&input_message); exec_execute_message(portal_name, max_rows); } break; case 'F': /* fastpath function call */ forbidden_in_wal_sender(firstchar); /* Set statement_timestamp() */ SetCurrentStatementStartTimestamp(); /* Report query to various monitoring facilities. */ pgstat_report_activity(STATE_FASTPATH, NULL); set_ps_display("<FASTPATH>", false); /* start an xact for this function invocation */ start_xact_command(); /* * Note: we may at this point be inside an aborted * transaction. We can't throw error for that until we've * finished reading the function-call message, so * HandleFunctionRequest() must check for it after doing so. * Be careful not to do anything that assumes we're inside a * valid transaction here. */ /* switch back to message context */ MemoryContextSwitchTo(MessageContext); if (HandleFunctionRequest(&input_message) == EOF) { /* lost frontend connection during F message input */ /* * Reset whereToSendOutput to prevent ereport from * attempting to send any more messages to client. */ if (whereToSendOutput == DestRemote) whereToSendOutput = DestNone; proc_exit(0); } /* commit the function-invocation transaction */ finish_xact_command(); send_ready_for_query = true; break; case 'C': /* close */ { int close_type; const char *close_target; forbidden_in_wal_sender(firstchar); close_type = pq_getmsgbyte(&input_message); close_target = pq_getmsgstring(&input_message); pq_getmsgend(&input_message); switch (close_type) { case 'S': if (close_target[0] != '\0') DropPreparedStatement(close_target, false); else { /* special-case the unnamed statement */ drop_unnamed_stmt(); } break; case 'P': { Portal portal; portal = GetPortalByName(close_target); if (PortalIsValid(portal)) PortalDrop(portal, false); } break; default: ereport(ERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("invalid CLOSE message subtype %d", close_type))); break; } if (whereToSendOutput == DestRemote) pq_putemptymessage('3'); /* CloseComplete */ } break; case 'D': /* describe */ { int describe_type; const char *describe_target; forbidden_in_wal_sender(firstchar); /* Set statement_timestamp() (needed for xact) */ SetCurrentStatementStartTimestamp(); describe_type = pq_getmsgbyte(&input_message); describe_target = pq_getmsgstring(&input_message); pq_getmsgend(&input_message); switch (describe_type) { case 'S': exec_describe_statement_message(describe_target); break; case 'P': exec_describe_portal_message(describe_target); break; default: ereport(ERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("invalid DESCRIBE message subtype %d", describe_type))); break; } } break; case 'H': /* flush */ pq_getmsgend(&input_message); if (whereToSendOutput == DestRemote) pq_flush(); break; case 'S': /* sync */ pq_getmsgend(&input_message); finish_xact_command(); send_ready_for_query = true; break; /* * 'X' means that the frontend is closing down the socket. EOF * means unexpected loss of frontend connection. Either way, * perform normal shutdown. */ case 'X': case EOF: /* * Reset whereToSendOutput to prevent ereport from attempting * to send any more messages to client. */ if (whereToSendOutput == DestRemote) whereToSendOutput = DestNone; /* * NOTE: if you are tempted to add more code here, DON'T! * Whatever you had in mind to do should be set up as an * on_proc_exit or on_shmem_exit callback, instead. Otherwise * it will fail to be called during other backend-shutdown * scenarios. */ proc_exit(0); case 'd': /* copy data */ case 'c': /* copy done */ case 'f': /* copy fail */ /* * Accept but ignore these messages, per protocol spec; we * probably got here because a COPY failed, and the frontend * is still sending data. */ break; default: ereport(FATAL, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("invalid frontend message type %d", firstchar))); } } /* end of input-reading loop */ }
void prepare_for_client_read | ( | void | ) |
Definition at line 511 of file postgres.c.
References CHECK_FOR_INTERRUPTS, DoingCommandRead, EnableCatchupInterrupt(), EnableNotifyInterrupt(), and ImmediateInterruptOK.
Referenced by interactive_getc(), and secure_read().
{ if (DoingCommandRead) { /* Enable immediate processing of asynchronous signals */ EnableNotifyInterrupt(); EnableCatchupInterrupt(); /* Allow cancel/die interrupts to be processed while waiting */ ImmediateInterruptOK = true; /* And don't forget to detect one that already arrived */ CHECK_FOR_INTERRUPTS(); } }
void process_postgres_switches | ( | int | argc, | |
char * | argv[], | |||
GucContext | ctx, | |||
const char ** | dbname | |||
) |
Definition at line 3255 of file postgres.c.
References EchoQuery, ereport, errcode(), errhint(), errmsg(), ERROR, FATAL, free, FrontendProtocol, get_stats_option_name(), getopt(), IsBinaryUpgrade, IsUnderPostmaster, MAXPGPATH, name, NULL, optarg, opterr, optind, OutputFileName, ParseLongOption(), progname, set_debug_options(), set_plan_disabling_options(), SetConfigOption(), strlcpy(), UseNewLine, userDoption, and value.
Referenced by PostgresMain(), and process_startup_options().
{ bool secure = (ctx == PGC_POSTMASTER); int errs = 0; GucSource gucsource; int flag; if (secure) { gucsource = PGC_S_ARGV; /* switches came from command line */ /* Ignore the initial --single argument, if present */ if (argc > 1 && strcmp(argv[1], "--single") == 0) { argv++; argc--; } } else { gucsource = PGC_S_CLIENT; /* switches came from client */ } #ifdef HAVE_INT_OPTERR /* * Turn this off because it's either printed to stderr and not the log * where we'd want it, or argv[0] is now "--single", which would make for * a weird error message. We print our own error message below. */ opterr = 0; #endif /* * Parse command-line options. CAUTION: keep this in sync with * postmaster/postmaster.c (the option sets should not conflict) and with * the common help() function in main/main.c. */ while ((flag = getopt(argc, argv, "A:B:bc:C:D:d:EeFf:h:ijk:lN:nOo:Pp:r:S:sTt:v:W:-:")) != -1) { switch (flag) { case 'A': SetConfigOption("debug_assertions", optarg, ctx, gucsource); break; case 'B': SetConfigOption("shared_buffers", optarg, ctx, gucsource); break; case 'b': /* Undocumented flag used for binary upgrades */ if (secure) IsBinaryUpgrade = true; break; case 'C': /* ignored for consistency with the postmaster */ break; case 'D': if (secure) userDoption = strdup(optarg); break; case 'd': set_debug_options(atoi(optarg), ctx, gucsource); break; case 'E': if (secure) EchoQuery = true; break; case 'e': SetConfigOption("datestyle", "euro", ctx, gucsource); break; case 'F': SetConfigOption("fsync", "false", ctx, gucsource); break; case 'f': if (!set_plan_disabling_options(optarg, ctx, gucsource)) errs++; break; case 'h': SetConfigOption("listen_addresses", optarg, ctx, gucsource); break; case 'i': SetConfigOption("listen_addresses", "*", ctx, gucsource); break; case 'j': if (secure) UseNewLine = 0; break; case 'k': SetConfigOption("unix_socket_directories", optarg, ctx, gucsource); break; case 'l': SetConfigOption("ssl", "true", ctx, gucsource); break; case 'N': SetConfigOption("max_connections", optarg, ctx, gucsource); break; case 'n': /* ignored for consistency with postmaster */ break; case 'O': SetConfigOption("allow_system_table_mods", "true", ctx, gucsource); break; case 'o': errs++; break; case 'P': SetConfigOption("ignore_system_indexes", "true", ctx, gucsource); break; case 'p': SetConfigOption("port", optarg, ctx, gucsource); break; case 'r': /* send output (stdout and stderr) to the given file */ if (secure) strlcpy(OutputFileName, optarg, MAXPGPATH); break; case 'S': SetConfigOption("work_mem", optarg, ctx, gucsource); break; case 's': SetConfigOption("log_statement_stats", "true", ctx, gucsource); break; case 'T': /* ignored for consistency with the postmaster */ break; case 't': { const char *tmp = get_stats_option_name(optarg); if (tmp) SetConfigOption(tmp, "true", ctx, gucsource); else errs++; break; } case 'v': /* * -v is no longer used in normal operation, since * FrontendProtocol is already set before we get here. We keep * the switch only for possible use in standalone operation, * in case we ever support using normal FE/BE protocol with a * standalone backend. */ if (secure) FrontendProtocol = (ProtocolVersion) atoi(optarg); break; case 'W': SetConfigOption("post_auth_delay", optarg, ctx, gucsource); break; case 'c': case '-': { char *name, *value; ParseLongOption(optarg, &name, &value); if (!value) { if (flag == '-') ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("--%s requires a value", optarg))); else ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("-c %s requires a value", optarg))); } SetConfigOption(name, value, ctx, gucsource); free(name); if (value) free(value); break; } default: errs++; break; } if (errs) break; } /* * Optional database name should be there only if *dbname is NULL. */ if (!errs && dbname && *dbname == NULL && argc - optind >= 1) *dbname = strdup(argv[optind++]); if (errs || argc != optind) { if (errs) optind--; /* complain about the previous argument */ /* spell the error message a bit differently depending on context */ if (IsUnderPostmaster) ereport(FATAL, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("invalid command-line argument for server process: %s", argv[optind]), errhint("Try \"%s --help\" for more information.", progname))); else ereport(FATAL, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("%s: invalid command-line argument: %s", progname, argv[optind]), errhint("Try \"%s --help\" for more information.", progname))); } /* * Reset getopt(3) library so that it will work correctly in subprocesses * or when this function is called a second time with another array. */ optind = 1; #ifdef HAVE_INT_OPTRESET optreset = 1; /* some systems need this too */ #endif }
void ProcessInterrupts | ( | void | ) |
Definition at line 2816 of file postgres.c.
References Assert, ClientAuthInProgress, ClientConnectionLost, CritSectionCount, DestRemote, DisableCatchupInterrupt(), DisableNotifyInterrupt(), DoingCommandRead, ereport, errcode(), errdetail_recovery_conflict(), errhint(), errmsg(), ERROR, FATAL, get_timeout_indicator(), ImmediateInterruptOK, InterruptHoldoffCount, InterruptPending, IsAutoVacuumWorkerProcess(), LOCK_TIMEOUT, pgstat_report_recovery_conflict(), ProcDiePending, PROCSIG_RECOVERY_CONFLICT_DATABASE, QueryCancelPending, RecoveryConflictPending, RecoveryConflictReason, RecoveryConflictRetryable, STATEMENT_TIMEOUT, and whereToSendOutput.
{ /* 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(); /* As in quickdie, don't risk sending to client during auth */ if (ClientAuthInProgress && whereToSendOutput == DestRemote) whereToSendOutput = DestNone; if (IsAutoVacuumWorkerProcess()) ereport(FATAL, (errcode(ERRCODE_ADMIN_SHUTDOWN), errmsg("terminating autovacuum process due to administrator command"))); else if (RecoveryConflictPending && RecoveryConflictRetryable) { pgstat_report_recovery_conflict(RecoveryConflictReason); ereport(FATAL, (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), errmsg("terminating connection due to conflict with recovery"), errdetail_recovery_conflict())); } else if (RecoveryConflictPending) { /* Currently there is only one non-retryable recovery conflict */ Assert(RecoveryConflictReason == PROCSIG_RECOVERY_CONFLICT_DATABASE); pgstat_report_recovery_conflict(RecoveryConflictReason); ereport(FATAL, (errcode(ERRCODE_DATABASE_DROPPED), errmsg("terminating connection due to conflict with recovery"), errdetail_recovery_conflict())); } else ereport(FATAL, (errcode(ERRCODE_ADMIN_SHUTDOWN), errmsg("terminating connection due to administrator command"))); } if (ClientConnectionLost) { QueryCancelPending = false; /* lost connection trumps QueryCancel */ ImmediateInterruptOK = false; /* not idle anymore */ DisableNotifyInterrupt(); DisableCatchupInterrupt(); /* don't send to client, we already know the connection to be dead. */ whereToSendOutput = DestNone; ereport(FATAL, (errcode(ERRCODE_CONNECTION_FAILURE), errmsg("connection to client lost"))); } if (QueryCancelPending) { QueryCancelPending = false; if (ClientAuthInProgress) { ImmediateInterruptOK = false; /* not idle anymore */ DisableNotifyInterrupt(); DisableCatchupInterrupt(); /* As in quickdie, don't risk sending to client during auth */ if (whereToSendOutput == DestRemote) whereToSendOutput = DestNone; ereport(ERROR, (errcode(ERRCODE_QUERY_CANCELED), errmsg("canceling authentication due to timeout"))); } /* * If LOCK_TIMEOUT and STATEMENT_TIMEOUT indicators are both set, we * prefer to report the former; but be sure to clear both. */ if (get_timeout_indicator(LOCK_TIMEOUT, true)) { ImmediateInterruptOK = false; /* not idle anymore */ (void) get_timeout_indicator(STATEMENT_TIMEOUT, true); DisableNotifyInterrupt(); DisableCatchupInterrupt(); ereport(ERROR, (errcode(ERRCODE_QUERY_CANCELED), errmsg("canceling statement due to lock timeout"))); } if (get_timeout_indicator(STATEMENT_TIMEOUT, true)) { ImmediateInterruptOK = false; /* not idle anymore */ DisableNotifyInterrupt(); DisableCatchupInterrupt(); ereport(ERROR, (errcode(ERRCODE_QUERY_CANCELED), errmsg("canceling statement due to statement timeout"))); } if (IsAutoVacuumWorkerProcess()) { ImmediateInterruptOK = false; /* not idle anymore */ DisableNotifyInterrupt(); DisableCatchupInterrupt(); ereport(ERROR, (errcode(ERRCODE_QUERY_CANCELED), errmsg("canceling autovacuum task"))); } if (RecoveryConflictPending) { ImmediateInterruptOK = false; /* not idle anymore */ RecoveryConflictPending = false; DisableNotifyInterrupt(); DisableCatchupInterrupt(); pgstat_report_recovery_conflict(RecoveryConflictReason); if (DoingCommandRead) ereport(FATAL, (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), errmsg("terminating connection due to conflict with recovery"), errdetail_recovery_conflict(), errhint("In a moment you should be able to reconnect to the" " database and repeat your command."))); else ereport(ERROR, (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), errmsg("canceling statement due to conflict with recovery"), errdetail_recovery_conflict())); } /* * If we are reading a command from the client, just ignore the cancel * request --- sending an extra error message won't accomplish * anything. Otherwise, go ahead and throw the error. */ if (!DoingCommandRead) { ImmediateInterruptOK = false; /* not idle anymore */ DisableNotifyInterrupt(); DisableCatchupInterrupt(); ereport(ERROR, (errcode(ERRCODE_QUERY_CANCELED), errmsg("canceling statement due to user request"))); } } /* If we get here, do nothing (probably, QueryCancelPending was reset) */ }
void quickdie | ( | SIGNAL_ARGS | ) |
Definition at line 2522 of file postgres.c.
References BlockSig, ClientAuthInProgress, DestRemote, ereport, errcode(), errdetail(), errhint(), errmsg(), on_exit_reset(), PG_SETMASK, sigaddset, SIGQUIT, WARNING, and whereToSendOutput.
Referenced by AutoVacLauncherMain(), AutoVacWorkerMain(), bootstrap_signals(), PostgresMain(), and WalSndSignals().
{ sigaddset(&BlockSig, SIGQUIT); /* prevent nested calls */ PG_SETMASK(&BlockSig); /* * If we're aborting out of client auth, don't risk trying to send * anything to the client; we will likely violate the protocol, not to * mention that we may have interrupted the guts of OpenSSL or some * authentication library. */ if (ClientAuthInProgress && whereToSendOutput == DestRemote) whereToSendOutput = DestNone; /* * 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."))); /* * We DO NOT want to run proc_exit() callbacks -- 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. Now that * there's an atexit callback to prevent third-party code from breaking * things by calling exit() directly, we have to reset the callbacks * explicitly to make this work as intended. */ on_exit_reset(); /* * Note we do exit(2) 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. (The "dead man switch" mechanism in pmsignal.c * should ensure the postmaster sees this as a crash, too, but no harm in * being doubly sure.) */ exit(2); }
static int ReadCommand | ( | StringInfo | inBuf | ) | [static] |
Definition at line 487 of file postgres.c.
References DestRemote, InteractiveBackend(), SocketBackend(), and whereToSendOutput.
Referenced by PostgresMain().
{ int result; if (whereToSendOutput == DestRemote) result = SocketBackend(inBuf); else result = InteractiveBackend(inBuf); return result; }
void RecoveryConflictInterrupt | ( | ProcSignalReason | reason | ) |
Definition at line 2686 of file postgres.c.
References Assert, CritSectionCount, DisableCatchupInterrupt(), DisableNotifyInterrupt(), elog, FATAL, HoldingBufferPinThatDelaysRecovery(), ImmediateInterruptOK, InterruptHoldoffCount, InterruptPending, IsAbortedTransactionBlockState(), IsSubTransaction(), IsTransactionOrTransactionBlock(), IsWaitingForLock(), LockErrorCleanup(), MyProc, proc_exit_inprogress, ProcDiePending, ProcessInterrupts(), PROCSIG_RECOVERY_CONFLICT_BUFFERPIN, PROCSIG_RECOVERY_CONFLICT_DATABASE, PROCSIG_RECOVERY_CONFLICT_LOCK, PROCSIG_RECOVERY_CONFLICT_SNAPSHOT, PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK, PROCSIG_RECOVERY_CONFLICT_TABLESPACE, QueryCancelPending, RecoveryConflictPending, PGPROC::recoveryConflictPending, RecoveryConflictReason, and RecoveryConflictRetryable.
Referenced by procsignal_sigusr1_handler().
{ int save_errno = errno; /* * Don't joggle the elbow of proc_exit */ if (!proc_exit_inprogress) { RecoveryConflictReason = reason; switch (reason) { case PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK: /* * If we aren't waiting for a lock we can never deadlock. */ if (!IsWaitingForLock()) return; /* Intentional drop through to check wait for pin */ case PROCSIG_RECOVERY_CONFLICT_BUFFERPIN: /* * If we aren't blocking the Startup process there is nothing * more to do. */ if (!HoldingBufferPinThatDelaysRecovery()) return; MyProc->recoveryConflictPending = true; /* Intentional drop through to error handling */ case PROCSIG_RECOVERY_CONFLICT_LOCK: case PROCSIG_RECOVERY_CONFLICT_TABLESPACE: case PROCSIG_RECOVERY_CONFLICT_SNAPSHOT: /* * If we aren't in a transaction any longer then ignore. */ if (!IsTransactionOrTransactionBlock()) return; /* * If we can abort just the current subtransaction then we are * OK to throw an ERROR to resolve the conflict. Otherwise * drop through to the FATAL case. * * XXX other times that we can throw just an ERROR *may* be * PROCSIG_RECOVERY_CONFLICT_LOCK if no locks are held in * parent transactions * * PROCSIG_RECOVERY_CONFLICT_SNAPSHOT if no snapshots are held * by parent transactions and the transaction is not * transaction-snapshot mode * * PROCSIG_RECOVERY_CONFLICT_TABLESPACE if no temp files or * cursors open in parent transactions */ if (!IsSubTransaction()) { /* * If we already aborted then we no longer need to cancel. * We do this here since we do not wish to ignore aborted * subtransactions, which must cause FATAL, currently. */ if (IsAbortedTransactionBlockState()) return; RecoveryConflictPending = true; QueryCancelPending = true; InterruptPending = true; break; } /* Intentional drop through to session cancel */ case PROCSIG_RECOVERY_CONFLICT_DATABASE: RecoveryConflictPending = true; ProcDiePending = true; InterruptPending = true; break; default: elog(FATAL, "unrecognized conflict mode: %d", (int) reason); } Assert(RecoveryConflictPending && (QueryCancelPending || ProcDiePending)); /* * All conflicts apart from database cause dynamic errors where the * command or transaction can be retried at a later point with some * potential for success. No need to reset this, since non-retryable * conflict errors are currently FATAL. */ if (reason == PROCSIG_RECOVERY_CONFLICT_DATABASE) RecoveryConflictRetryable = false; /* * 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++; LockErrorCleanup(); /* prevent CheckDeadLock from running */ DisableNotifyInterrupt(); DisableCatchupInterrupt(); InterruptHoldoffCount--; ProcessInterrupts(); } } errno = save_errno; }
void ResetUsage | ( | void | ) |
Definition at line 4295 of file postgres.c.
References getrusage(), gettimeofday(), NULL, RUSAGE_SELF, Save_r, and Save_t.
Referenced by _bt_leafbuild(), _SPI_pquery(), btbuild(), exec_bind_message(), exec_execute_message(), exec_parse_message(), exec_simple_query(), pg_analyze_and_rewrite(), pg_analyze_and_rewrite_params(), pg_parse_query(), pg_plan_query(), pg_rewrite_query(), PortalRun(), and PortalRunMulti().
{ getrusage(RUSAGE_SELF, &Save_r); gettimeofday(&Save_t, NULL); }
void restore_stack_base | ( | pg_stack_base_t | base | ) |
Definition at line 3032 of file postgres.c.
References stack_base_ptr.
{ #if defined(__ia64__) || defined(__ia64) stack_base_ptr = base.stack_base_ptr; register_stack_base_ptr = base.register_stack_base_ptr; #else stack_base_ptr = base; #endif }
void set_debug_options | ( | int | debug_flag, | |
GucContext | context, | |||
GucSource | source | |||
) |
Definition at line 3144 of file postgres.c.
References PGC_POSTMASTER, and SetConfigOption().
Referenced by PostmasterMain(), and process_postgres_switches().
{ if (debug_flag > 0) { char debugstr[64]; sprintf(debugstr, "debug%d", debug_flag); SetConfigOption("log_min_messages", debugstr, context, source); } else SetConfigOption("log_min_messages", "notice", context, source); if (debug_flag >= 1 && context == PGC_POSTMASTER) { SetConfigOption("log_connections", "true", context, source); SetConfigOption("log_disconnections", "true", context, source); } if (debug_flag >= 2) SetConfigOption("log_statement", "all", context, source); if (debug_flag >= 3) SetConfigOption("debug_print_parse", "true", context, source); if (debug_flag >= 4) SetConfigOption("debug_print_plan", "true", context, source); if (debug_flag >= 5) SetConfigOption("debug_print_rewritten", "true", context, source); }
bool set_plan_disabling_options | ( | const char * | arg, | |
GucContext | context, | |||
GucSource | source | |||
) |
Definition at line 3173 of file postgres.c.
References SetConfigOption().
Referenced by PostmasterMain(), and process_postgres_switches().
{ const char *tmp = NULL; switch (arg[0]) { case 's': /* seqscan */ tmp = "enable_seqscan"; break; case 'i': /* indexscan */ tmp = "enable_indexscan"; break; case 'o': /* indexonlyscan */ tmp = "enable_indexonlyscan"; break; case 'b': /* bitmapscan */ tmp = "enable_bitmapscan"; break; case 't': /* tidscan */ tmp = "enable_tidscan"; break; case 'n': /* nestloop */ tmp = "enable_nestloop"; break; case 'm': /* mergejoin */ tmp = "enable_mergejoin"; break; case 'h': /* hashjoin */ tmp = "enable_hashjoin"; break; } if (tmp) { SetConfigOption(tmp, "false", context, source); return true; } else return false; }
pg_stack_base_t set_stack_base | ( | void | ) |
Definition at line 3001 of file postgres.c.
References stack_base_ptr.
Referenced by PostmasterMain().
{ char stack_base; pg_stack_base_t old; #if defined(__ia64__) || defined(__ia64) old.stack_base_ptr = stack_base_ptr; old.register_stack_base_ptr = register_stack_base_ptr; #else old = stack_base_ptr; #endif /* Set up reference point for stack depth checking */ stack_base_ptr = &stack_base; #if defined(__ia64__) || defined(__ia64) register_stack_base_ptr = ia64_get_bsp(); #endif return old; }
void ShowUsage | ( | const char * | title | ) |
Definition at line 4302 of file postgres.c.
References appendStringInfo(), StringInfoData::data, ereport, errdetail_internal(), errmsg_internal(), getrusage(), gettimeofday(), initStringInfo(), StringInfoData::len, LOG, NULL, pfree(), rusage::ru_stime, rusage::ru_utime, RUSAGE_SELF, Save_r, and Save_t.
Referenced by _bt_leafbuild(), _SPI_pquery(), btbuild(), exec_bind_message(), exec_execute_message(), exec_parse_message(), exec_simple_query(), pg_analyze_and_rewrite(), pg_analyze_and_rewrite_params(), pg_parse_query(), pg_plan_query(), pg_rewrite_query(), PortalRun(), and PortalRunMulti().
{ StringInfoData str; struct timeval user, sys; struct timeval elapse_t; struct rusage r; getrusage(RUSAGE_SELF, &r); gettimeofday(&elapse_t, NULL); memcpy((char *) &user, (char *) &r.ru_utime, sizeof(user)); memcpy((char *) &sys, (char *) &r.ru_stime, sizeof(sys)); 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. */ initStringInfo(&str); appendStringInfo(&str, "! system usage stats:\n"); appendStringInfo(&str, "!\t%ld.%06ld elapsed %ld.%06ld user %ld.%06ld system sec\n", (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), (long) (r.ru_utime.tv_usec - Save_r.ru_utime.tv_usec), (long) (r.ru_stime.tv_sec - Save_r.ru_stime.tv_sec), (long) (r.ru_stime.tv_usec - Save_r.ru_stime.tv_usec)); appendStringInfo(&str, "!\t[%ld.%06ld user %ld.%06ld sys total]\n", (long) user.tv_sec, (long) user.tv_usec, (long) sys.tv_sec, (long) sys.tv_usec); #if defined(HAVE_GETRUSAGE) appendStringInfo(&str, "!\t%ld/%ld [%ld/%ld] filesystem blocks in/out\n", r.ru_inblock - Save_r.ru_inblock, /* they only drink coffee at dec */ r.ru_oublock - Save_r.ru_oublock, r.ru_inblock, r.ru_oublock); appendStringInfo(&str, "!\t%ld/%ld [%ld/%ld] page faults/reclaims, %ld [%ld] swaps\n", 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); appendStringInfo(&str, "!\t%ld [%ld] signals rcvd, %ld/%ld [%ld/%ld] messages rcvd/sent\n", 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); appendStringInfo(&str, "!\t%ld/%ld [%ld/%ld] voluntary/involuntary context switches\n", r.ru_nvcsw - Save_r.ru_nvcsw, r.ru_nivcsw - Save_r.ru_nivcsw, r.ru_nvcsw, r.ru_nivcsw); #endif /* HAVE_GETRUSAGE */ /* remove trailing newline */ if (str.data[str.len - 1] == '\n') str.data[--str.len] = '\0'; ereport(LOG, (errmsg_internal("%s", title), errdetail_internal("%s", str.data))); pfree(str.data); }
static void SigHupHandler | ( | SIGNAL_ARGS | ) | [static] |
Definition at line 2668 of file postgres.c.
References got_SIGHUP, MyProc, PGPROC::procLatch, and SetLatch().
Referenced by PostgresMain().
{ int save_errno = errno; got_SIGHUP = true; if (MyProc) SetLatch(&MyProc->procLatch); errno = save_errno; }
static int SocketBackend | ( | StringInfo | inBuf | ) | [static] |
Definition at line 337 of file postgres.c.
References COMMERROR, DEBUG1, doing_extended_query_message, ereport, errcode(), errmsg(), FATAL, FrontendProtocol, ignore_till_sync, IsTransactionState(), PG_PROTOCOL_MAJOR, pq_getbyte(), pq_getmessage(), pq_getstring(), and whereToSendOutput.
Referenced by ReadCommand().
{ int qtype; /* * Get message type code from the frontend. */ qtype = pq_getbyte(); if (qtype == EOF) /* frontend disconnected */ { if (IsTransactionState()) ereport(COMMERROR, (errcode(ERRCODE_CONNECTION_FAILURE), errmsg("unexpected EOF on client connection with an open transaction"))); else { /* * Can't send DEBUG log messages to client at this point. Since * we're disconnecting right away, we don't need to restore * whereToSendOutput. */ whereToSendOutput = DestNone; ereport(DEBUG1, (errcode(ERRCODE_CONNECTION_DOES_NOT_EXIST), errmsg("unexpected EOF on client connection"))); } return qtype; } /* * Validate message type code before trying to read body; if we have lost * sync, better to say "command unknown" than to run out of memory because * we used garbage as a length word. * * This also gives us a place to set the doing_extended_query_message flag * as soon as possible. */ switch (qtype) { case 'Q': /* simple query */ doing_extended_query_message = false; if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3) { /* old style without length word; convert */ if (pq_getstring(inBuf)) { if (IsTransactionState()) ereport(COMMERROR, (errcode(ERRCODE_CONNECTION_FAILURE), errmsg("unexpected EOF on client connection with an open transaction"))); else { /* * Can't send DEBUG log messages to client at this * point.Since we're disconnecting right away, we * don't need to restore whereToSendOutput. */ whereToSendOutput = DestNone; ereport(DEBUG1, (errcode(ERRCODE_CONNECTION_DOES_NOT_EXIST), errmsg("unexpected EOF on client connection"))); } return EOF; } } break; case 'F': /* fastpath function call */ /* we let fastpath.c cope with old-style input of this */ doing_extended_query_message = false; break; case 'X': /* terminate */ doing_extended_query_message = false; ignore_till_sync = false; 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) ereport(FATAL, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("invalid frontend message type %d", qtype))); 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) ereport(FATAL, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("invalid frontend message type %d", qtype))); break; case 'd': /* copy data */ case 'c': /* copy done */ case 'f': /* copy fail */ doing_extended_query_message = false; /* these are only legal in protocol 3 */ if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3) ereport(FATAL, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("invalid frontend message type %d", qtype))); break; default: /* * 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. */ ereport(FATAL, (errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("invalid frontend message type %d", qtype))); break; } /* * 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 */ } return qtype; }
static void start_xact_command | ( | void | ) | [static] |
Definition at line 2380 of file postgres.c.
References DEBUG3, disable_timeout(), enable_timeout_after(), ereport, errmsg_internal(), StartTransactionCommand(), STATEMENT_TIMEOUT, StatementTimeout, and xact_started.
Referenced by exec_bind_message(), exec_describe_portal_message(), exec_describe_statement_message(), exec_execute_message(), exec_parse_message(), exec_simple_query(), and PostgresMain().
{ if (!xact_started) { ereport(DEBUG3, (errmsg_internal("StartTransactionCommand"))); StartTransactionCommand(); /* Set statement timeout running, if any */ /* NB: this mustn't be enabled until we are within an xact */ if (StatementTimeout > 0) enable_timeout_after(STATEMENT_TIMEOUT, StatementTimeout); else disable_timeout(STATEMENT_TIMEOUT, false); xact_started = true; } }
void StatementCancelHandler | ( | SIGNAL_ARGS | ) |
Definition at line 2616 of file postgres.c.
References CritSectionCount, DisableCatchupInterrupt(), DisableNotifyInterrupt(), ImmediateInterruptOK, InterruptHoldoffCount, InterruptPending, LockErrorCleanup(), MyProc, proc_exit_inprogress, ProcessInterrupts(), PGPROC::procLatch, QueryCancelPending, and SetLatch().
Referenced by AutoVacLauncherMain(), AutoVacWorkerMain(), do_start_bgworker(), and PostgresMain().
{ 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 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++; LockErrorCleanup(); /* prevent CheckDeadLock from running */ DisableNotifyInterrupt(); DisableCatchupInterrupt(); InterruptHoldoffCount--; ProcessInterrupts(); } } /* If we're still here, waken anything waiting on the process latch */ if (MyProc) SetLatch(&MyProc->procLatch); errno = save_errno; }
const char* debug_query_string |
Definition at line 92 of file postgres.c.
Referenced by current_query(), errstart(), exec_bind_message(), exec_execute_message(), exec_parse_message(), exec_simple_query(), PostgresMain(), proc_exit_prepare(), send_message_to_server_log(), and write_csvlog().
bool doing_extended_query_message = false [static] |
Definition at line 157 of file postgres.c.
Referenced by PostgresMain(), and SocketBackend().
bool DoingCommandRead = false [static] |
Definition at line 151 of file postgres.c.
Referenced by client_read_ended(), PostgresMain(), prepare_for_client_read(), and ProcessInterrupts().
Definition at line 170 of file postgres.c.
Referenced by InteractiveBackend(), and process_postgres_switches().
volatile sig_atomic_t got_SIGHUP = false [static] |
Definition at line 138 of file postgres.c.
Referenced by PostgresMain(), and SigHupHandler().
bool ignore_till_sync = false [static] |
Definition at line 158 of file postgres.c.
Referenced by PostgresMain(), and SocketBackend().
bool Log_disconnections = false |
Definition at line 98 of file postgres.c.
Referenced by PostgresMain().
int log_statement = LOGSTMT_NONE |
Definition at line 100 of file postgres.c.
Referenced by check_log_statement(), and HandleFunctionRequest().
int max_stack_depth = 100 |
Definition at line 103 of file postgres.c.
Referenced by check_stack_depth().
long max_stack_depth_bytes = 100 * 1024L [static] |
Definition at line 116 of file postgres.c.
Referenced by assign_max_stack_depth(), and check_stack_depth().
int PostAuthDelay = 0 |
Definition at line 106 of file postgres.c.
Referenced by AutoVacLauncherMain(), AutoVacWorkerMain(), do_start_bgworker(), and InitPostgres().
bool RecoveryConflictPending = false [static] |
Definition at line 183 of file postgres.c.
Referenced by ProcessInterrupts(), and RecoveryConflictInterrupt().
ProcSignalReason RecoveryConflictReason [static] |
Definition at line 185 of file postgres.c.
Referenced by errdetail_recovery_conflict(), ProcessInterrupts(), and RecoveryConflictInterrupt().
bool RecoveryConflictRetryable = true [static] |
Definition at line 184 of file postgres.c.
Referenced by ProcessInterrupts(), and RecoveryConflictInterrupt().
Definition at line 4291 of file postgres.c.
Referenced by ResetUsage(), and ShowUsage().
struct timeval Save_t [static] |
Definition at line 4292 of file postgres.c.
Referenced by ResetUsage(), and ShowUsage().
char* stack_base_ptr = NULL |
Definition at line 124 of file postgres.c.
Referenced by check_stack_depth(), restore_stack_base(), and set_stack_base().
CachedPlanSource* unnamed_stmt_psrc = NULL [static] |
Definition at line 165 of file postgres.c.
int UseNewLine = 1 [static] |
Definition at line 177 of file postgres.c.
Referenced by InteractiveBackend(), and process_postgres_switches().
const char* userDoption = NULL [static] |
Definition at line 168 of file postgres.c.
Referenced by AuxiliaryProcessMain(), PostgresMain(), PostmasterMain(), and process_postgres_switches().
CommandDest whereToSendOutput = DestDebug |
Definition at line 95 of file postgres.c.
Referenced by BackendInitialize(), BeginCopyFrom(), BeginCopyTo(), BeginReportingGUCOptions(), DoCopyTo(), errfinish(), errstart(), exec_bind_message(), exec_describe_portal_message(), exec_describe_statement_message(), exec_execute_message(), exec_parse_message(), exec_simple_query(), HandleFunctionRequest(), NotifyMyFrontEnd(), pg_re_throw(), PostgresMain(), PostmasterMain(), ProcessInterrupts(), quickdie(), ReadCommand(), send_message_to_server_log(), SocketBackend(), SyncRepWaitForLSN(), and WalSndLoop().
bool xact_started = false [static] |
Definition at line 144 of file postgres.c.
Referenced by finish_xact_command(), PostgresMain(), and start_xact_command().