📄 postgres.c
字号:
TPRINTF(TRACE_PRETTY_PLAN, "plan:"); nodeDisplay(plan); } else { TPRINTF(TRACE_PLAN, "plan:"); printf("\n%s\n\n", nodeToString(plan)); } }#endif } /* * If the command is an utility append a null plan. This is needed * to keep the plan_list aligned with the querytree_list or the * function executor will crash. DZ - 30-8-1996 */ else plan_list = lappend(plan_list, NULL); } if (queryListP) *queryListP = querytree_list; return plan_list;}/* ---------------------------------------------------------------- * pg_exec_query() * * Takes a querystring, runs the parser/utilities or * parser/planner/executor over it as necessary * Begin Transaction Should have been called before this * and CommitTransaction After this is called * This is strictly because we do not allow for nested xactions. * * NON-OBVIOUS-RESTRICTIONS * this function _MUST_ allocate a new "parsetree" each time, * since it may be stored in a named portal and should not * change its value. * * ---------------------------------------------------------------- */static voidpg_exec_query(char *query_string){ pg_exec_query_dest(query_string, whereToSendOutput, FALSE);}voidpg_exec_query_acl_override(char *query_string){ pg_exec_query_dest(query_string, whereToSendOutput, TRUE);}voidpg_exec_query_dest(char *query_string, /* string to execute */ CommandDest dest, /* where results should go */ bool aclOverride) /* to give utility commands power * of superusers */{ List *querytree_list; List *plan_list; Query *querytree; Plan *plan; int j; /* plan the queries */ plan_list = pg_parse_and_plan(query_string, NULL, 0, &querytree_list, dest, aclOverride); /* if we got a cancel signal whilst planning, quit */ if (QueryCancel) CancelQuery(); /* OK, do it to it! */ /* * NOTE: we do not use "foreach" here because we want to be sure the * list pointers have been advanced before the query is executed. We * need to do that because VACUUM has a nasty little habit of doing * CommitTransactionCommand at startup, and that will release the * memory holding our parse/plan lists :-(. This needs a better * solution --- currently, the code will crash if someone submits * "vacuum; something-else" in a single query string. But memory * allocation needs redesigned anyway, so this will have to do for * now. */ while (querytree_list) { querytree = (Query *) lfirst(querytree_list); querytree_list = lnext(querytree_list); plan = (Plan *) lfirst(plan_list); plan_list = lnext(plan_list); if (querytree->commandType == CMD_UTILITY) { /* ---------------- * process utility functions (create, destroy, etc..) * * Note: we do not check for the transaction aborted state * because that is done in ProcessUtility. * ---------------- */ if (DebugPrintQuery) TPRINTF(TRACE_QUERY, "ProcessUtility: %s", query_string); else if (Verbose) TPRINTF(TRACE_VERBOSE, "ProcessUtility"); /* * We have to set query SnapShot in the case of FETCH or COPY TO. */ if (nodeTag(querytree->utilityStmt) == T_FetchStmt || (nodeTag(querytree->utilityStmt) == T_CopyStmt && ((CopyStmt *)(querytree->utilityStmt))->direction != FROM)) SetQuerySnapshot(); ProcessUtility(querytree->utilityStmt, dest); } else {#ifdef INDEXSCAN_PATCH /* * Print moved in pg_parse_and_plan. DZ - 27-8-1996 */#else /* ---------------- * print plan if debugging * ---------------- */ if (DebugPrintPlan || DebugPPrintPlan) { if (DebugPPrintPlan) { TPRINTF(TRACE_PRETTY_PLAN, "plan:"); nodeDisplay(plan); } else { TPRINTF(TRACE_PLAN, "plan:"); printf("\n%s\n\n", nodeToString(plan)); } }#endif SetQuerySnapshot(); /* * execute the plan */ if (ShowExecutorStats) ResetUsage(); for (j = 0; j < _exec_repeat_; j++) { if (Verbose) TPRINTF(TRACE_VERBOSE, "ProcessQuery"); ProcessQuery(querytree, plan, dest); } if (ShowExecutorStats) { fprintf(stderr, "! Executor Stats:\n"); ShowUsage(); } } /* * In a query block, we want to increment the command counter * between queries so that the effects of early queries are * visible to subsequent ones. */ CommandCounterIncrement(); }}/* -------------------------------- * signal handler routines used in PostgresMain() * * handle_warn() catches SIGQUIT. It forces control back to the main * loop, just as if an internal error (elog(ERROR,...)) had occurred. * elog() used to actually use kill(2) to induce a SIGQUIT to get here! * But that's not 100% reliable on some systems, so now it does its own * siglongjmp() instead. * We still provide the signal catcher so that an error quit can be * forced externally. This should be done only with great caution, * however, since an asynchronous signal could leave the system in * who-knows-what inconsistent state. * * quickdie() occurs when signalled by the postmaster. * Some backend has bought the farm, * so we need to stop what we're doing and exit. * * die() performs an orderly cleanup via ExitPostgres() * -------------------------------- */voidhandle_warn(SIGNAL_ARGS){ siglongjmp(Warn_restart, 1);}voidquickdie(SIGNAL_ARGS){ elog(NOTICE, "Message from PostgreSQL backend:" "\n\tThe Postmaster has informed me that some other backend" " died abnormally and possibly corrupted shared memory." "\n\tI have rolled back the current transaction and am" " going to terminate your database system connection and exit." "\n\tPlease reconnect to the database system and repeat your query."); /* * DO NOT ExitPostgres(0) -- we're here because shared memory may be * corrupted, so we don't want to flush any shared state to stable * storage. Just nail the windows shut and get out of town. */ exit(0);}voiddie(SIGNAL_ARGS){ ExitPostgres(0);}/* signal handler for floating point exception */voidFloatExceptionHandler(SIGNAL_ARGS){ elog(ERROR, "floating point exception!" " The last floating point operation either exceeded legal ranges" " or was a divide by zero");}/* signal handler for query cancel signal from postmaster */static voidQueryCancelHandler(SIGNAL_ARGS){ QueryCancel = true;}voidCancelQuery(void){ /* * QueryCancel flag will be reset in main loop, which we reach by * longjmp from elog(). */ elog(ERROR, "Query was cancelled.");}static voidusage(char *progname){ fprintf(stderr, "Usage: %s [options] [dbname]\n", progname);#ifdef USE_ASSERT_CHECKING fprintf(stderr, "\t-A on\t\tenable/disable assert checking\n");#endif fprintf(stderr, "\t-B buffers\tset number of buffers in buffer pool\n"); fprintf(stderr, "\t-C \t\tsuppress version info\n"); fprintf(stderr, "\t-D dir\t\tdata directory\n"); fprintf(stderr, "\t-E \t\techo query before execution\n"); fprintf(stderr, "\t-F \t\tturn off fsync\n");#ifdef LOCK_MGR_DEBUG fprintf(stderr, "\t-K lev\t\tset locking debug level [0|1|2]\n");#endif fprintf(stderr, "\t-L \t\tturn off locking\n"); fprintf(stderr, "\t-N \t\tdon't use newline as interactive query delimiter\n"); fprintf(stderr, "\t-O \t\tallow system table structure changes\n"); fprintf(stderr, "\t-Q \t\tsuppress informational messages\n"); fprintf(stderr, "\t-S kbytes\tset amount of memory for sorts (in kbytes)\n"); fprintf(stderr, "\t-T options\tspecify pg_options\n"); fprintf(stderr, "\t-W sec\t\twait N seconds to allow attach from a debugger\n"); fprintf(stderr, "\t-d [1|2|3]\tset debug level\n"); fprintf(stderr, "\t-e \t\tturn on European date format\n"); fprintf(stderr, "\t-f [s|i|n|m|h]\tforbid use of some plan types\n"); fprintf(stderr, "\t-i \t\tdon't execute queries\n"); fprintf(stderr, "\t-o file\t\tsend stdout and stderr to given filename\n"); fprintf(stderr, "\t-p database\tbackend is started under a postmaster\n"); fprintf(stderr, "\t-s \t\tshow stats after each query\n"); fprintf(stderr, "\t-t [pa|pl|ex]\tshow timings after each query\n"); fprintf(stderr, "\t-v version\tset protocol version being used by frontend\n");}/* ---------------------------------------------------------------- * PostgresMain * postgres main loop * all backends, interactive or otherwise start here * * argc/argv are the command line arguments to be used. When being forked * by the postmaster, these are not the original argv array of the process. * real_argc/real_argv point to the original argv array, which is needed by * PS_INIT_STATUS on some platforms. * ---------------------------------------------------------------- */intPostgresMain(int argc, char *argv[], int real_argc, char *real_argv[]){ int flag; char *DBName = NULL; bool secure = true; int errs = 0; char firstchar; char parser_input[MAX_PARSE_BUFFER]; char *userName; /* Used if verbose is set, must be initialized */ char *remote_info = "interactive"; char *remote_host = ""; unsigned short remote_port = 0; char *DBDate = NULL; extern int optind; extern char *optarg; extern short DebugLvl; /* * Set default values for command-line options. */ IsUnderPostmaster = false; ShowStats = 0; ShowParserStats = ShowPlannerStats = ShowExecutorStats = 0; DeadlockCheckTimer = DEADLOCK_CHECK_TIMER; Noversion = false; EchoQuery = false;#ifdef LOCK_MGR_DEBUG LockDebug = 0;#endif DataDir = getenv("PGDATA"); /* * Try to get initial values for date styles and formats. Does not do * a complete job, but should be good enough for backend. Cannot call * parse_date() since palloc/pfree memory is not set up yet. */ DBDate = getenv("PGDATESTYLE"); if (DBDate != NULL) { if (strcasecmp(DBDate, "ISO") == 0) DateStyle = USE_ISO_DATES; else if (strcasecmp(DBDate, "SQL") == 0) DateStyle = USE_SQL_DATES; else if (strcasecmp(DBDate, "POSTGRES") == 0) DateStyle = USE_POSTGRES_DATES; else if (strcasecmp(DBDate, "GERMAN") == 0) { DateStyle = USE_GERMAN_DATES; EuroDates = TRUE; } else if (strcasecmp(DBDate, "NONEURO") == 0) EuroDates = FALSE; else if (strcasecmp(DBDate, "EURO") == 0) EuroDates = TRUE; } /* * Read default pg_options from file $DATADIR/pg_options. */ if (DataDir) read_pg_options(0); /* ---------------- * parse command line arguments * * There are now two styles of command line layout for the backend: * * For interactive use (not started from postmaster) the format is * postgres [switches] [databasename] * If the databasename is omitted it is taken to be the user name. * * When started from the postmaster, the format is * postgres [secure switches] -p databasename [insecure switches] * Switches appearing after -p came from the client (via "options" * field of connection request). For security reasons we restrict * what these switches can do. * ---------------- */ optind = 1; /* reset after postmaster's usage */ while ((flag = getopt(argc, argv, "A:B:CD:d:EeFf:iK:LNOo:p:QS:sT:t:v:W:x:")) != EOF) switch (flag) { case 'A': /* ---------------- * enable/disable assert checking. * ---------------- */#ifdef USE_ASSERT_CHECKING assert_enabled = atoi(optarg);#else fprintf(stderr, "Assert checking is not enabled\n");#endif break; case 'B': /* ---------------- * specify the size of buffer pool * ---------------- */ if (secure) NBuffers = atoi(optarg); break; case 'C': /* ---------------- * don't print version string * ---------------- */ Noversion = true; break; case 'D': /* PGDATA directory */ if (secure) { if (!DataDir) { DataDir = optarg; /* must be done after DataDir is defined */ read_pg_options(0); } DataDir = optarg; } break; case 'd': /* debug level */ DebugLvl = (short) atoi(optarg); if (DebugLvl >= 1) Verbose = DebugLvl; if (DebugLvl >= 2) DebugPrintQuery = true; if (DebugLvl >= 3) DebugPrintQuery = DebugLvl; if (DebugLvl >= 4) { DebugPrintParse = true; DebugPrintPlan = true; DebugPrintRewrittenParsetree = true; } if (DebugLvl >= 5) { DebugPPrintParse = true; DebugPPrintPlan = true; DebugPPrintRewrittenParsetree = true; } break; case 'E': /* ---------------- * E - echo the query the user entered * ---------------- */ EchoQuery = true; break; case 'e': /* -------------------------- * Use european date formats. * -------------------------- */ EuroDates = true; break; case 'F': /* -------------------- * turn off fsync * -------------------- */ if (secure) disableFsync = true; break; case 'f': /* ----------------- * f - forbid generation of certain plans * ----------------- */ switch (optarg[0]) { case 's': /* seqscan */ _enable_seqscan_ = false; break; case 'i': /* indexscan */ _enable_indexscan_ = false; break; case 'n': /* nestloop */ _enable_nestloop_ = false; break; case 'm': /* mergejoin */ _enable_mergejoin_ = false; break; case 'h': /* hashjoin */ _enable_hashjoin_ = false; break; default: errs++; } break; case 'i': dontExecute = 1; break; case 'K':#ifdef LOCK_MGR_DEBUG LockDebug = atoi(optarg);#else fprintf(stderr, "Lock debug not compiled in\n");#endif break; case 'L': /* -------------------- * turn off locking * -------------------- */ if (secure) lockingOff = 1; break; case 'N': /* ---------------- * N - Don't use newline as a query delimiter * ---------------- */ UseNewLine = 0; break; case 'O': /* -------------------- * allow system table structure modifications * -------------------- */ if (secure) /* XXX safe to allow from client??? */ allowSystemTableMods = true; break; case 'o': /* ---------------- * o - send output (stdout and stderr) to the given file * ---------------- */ if (secure) StrNCpy(OutputFileName, optarg, MAXPGPATH); break; case 'p': /* ---------------- * p - special flag passed if backend was forked * by a postmaster. * ---------------- */ if (secure) { IsUnderPostmaster = true; DBName = optarg; secure = false; /* subsequent switches are NOT * secure */ } break; case 'Q': /* ---------------- * Q - set Quiet mode (reduce debugging output) * ---------------- */ Verbose = 0; break; case 'S': /* ---------------- * S - amount of sort memory to use in 1k bytes * ---------------- */ { int S; S = atoi(optarg); if (S >= 4 * BLCKSZ / 1024) SortMem = S; } break; case 's': /* ---------------- * s - report usage statistics (timings) after each query * ---------------- */ ShowStats = 1; StatFp = stderr; break; case 'T':
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -