]> granicus.if.org Git - postgresql/blobdiff - src/backend/tcop/postgres.c
pgindent run for 8.3.
[postgresql] / src / backend / tcop / postgres.c
index 94fd65e5d448cf3e691964c6cd24538565b0d688..43435966c95033162048422816f6dfadec1541ce 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.534 2007/06/23 22:12:52 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.538 2007/11/15 21:14:38 momjian Exp $
  *
  * NOTES
  *       this is the "main" module of the postgres backend and
@@ -51,6 +51,7 @@
 #include "optimizer/planner.h"
 #include "parser/analyze.h"
 #include "parser/parser.h"
+#include "postmaster/autovacuum.h"
 #include "rewrite/rewriteHandler.h"
 #include "storage/freespace.h"
 #include "storage/ipc.h"
@@ -141,6 +142,7 @@ static bool ignore_till_sync = false;
  * in order to reduce overhead for short-lived queries.
  */
 static CachedPlanSource *unnamed_stmt_psrc = NULL;
+
 /* workspace for building a new unnamed statement in */
 static MemoryContext unnamed_stmt_context = NULL;
 
@@ -163,6 +165,7 @@ static int  UseNewLine = 0;         /* Use EOF as query delimiters */
  * ----------------------------------------------------------------
  */
 static int     InteractiveBackend(StringInfo inBuf);
+static int     interactive_getc(void);
 static int     SocketBackend(StringInfo inBuf);
 static int     ReadCommand(StringInfo inBuf);
 static List *pg_rewrite_query(Query *query);
@@ -209,64 +212,61 @@ InteractiveBackend(StringInfo inBuf)
 
        resetStringInfo(inBuf);
 
-       for (;;)
+       if (UseNewLine)
        {
-               if (UseNewLine)
+               /*
+                * if we are using \n as a delimiter, then read characters until the
+                * \n.
+                */
+               while ((c = interactive_getc()) != EOF)
                {
-                       /*
-                        * if we are using \n as a delimiter, then read characters until
-                        * the \n.
-                        */
-                       while ((c = getc(stdin)) != EOF)
+                       if (c == '\n')
                        {
-                               if (c == '\n')
+                               if (backslashSeen)
                                {
-                                       if (backslashSeen)
-                                       {
-                                               /* discard backslash from inBuf */
-                                               inBuf->data[--inBuf->len] = '\0';
-                                               backslashSeen = false;
-                                               continue;
-                                       }
-                                       else
-                                       {
-                                               /* keep the newline character */
-                                               appendStringInfoChar(inBuf, '\n');
-                                               break;
-                                       }
+                                       /* discard backslash from inBuf */
+                                       inBuf->data[--inBuf->len] = '\0';
+                                       backslashSeen = false;
+                                       continue;
                                }
-                               else if (c == '\\')
-                                       backslashSeen = true;
                                else
-                                       backslashSeen = false;
-
-                               appendStringInfoChar(inBuf, (char) c);
+                               {
+                                       /* keep the newline character */
+                                       appendStringInfoChar(inBuf, '\n');
+                                       break;
+                               }
                        }
+                       else if (c == '\\')
+                               backslashSeen = true;
+                       else
+                               backslashSeen = false;
 
-                       if (c == EOF)
-                               end = true;
-               }
-               else
-               {
-                       /*
-                        * otherwise read characters until EOF.
-                        */
-                       while ((c = getc(stdin)) != EOF)
-                               appendStringInfoChar(inBuf, (char) c);
-
-                       if (inBuf->len == 0)
-                               end = true;
+                       appendStringInfoChar(inBuf, (char) c);
                }
 
-               if (end)
-                       return EOF;
-
+               if (c == EOF)
+                       end = true;
+       }
+       else
+       {
                /*
-                * otherwise we have a user query so process it.
+                * otherwise read characters until EOF.
                 */
-               break;
+               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');
 
@@ -280,6 +280,24 @@ InteractiveBackend(StringInfo inBuf)
        return 'Q';
 }
 
+/*
+ * interactive_getc -- collect one character from stdin
+ *
+ * Even though we are not reading from a "client" process, we still want to
+ * respond to signals, particularly SIGTERM/SIGQUIT.  Hence we must use
+ * prepare_for_client_read and client_read_ended.
+ */
+static int
+interactive_getc(void)
+{
+       int                     c;
+
+       prepare_for_client_read();
+       c = getc(stdin);
+       client_read_ended();
+       return c;
+}
+
 /* ----------------
  *     SocketBackend()         Is called for frontend-backend connections
  *
@@ -816,10 +834,10 @@ exec_simple_query(const char *query_string)
        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
+        * 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);
@@ -1156,8 +1174,8 @@ exec_parse_message(const char *query_string,      /* string to execute */
                 * originally specified parameter set is not required to be complete,
                 * so we have to use parse_analyze_varparams().
                 *
-                * XXX must use copyObject here since parse analysis scribbles on
-                * its input, and we need the unmodified raw parse tree for possible
+                * XXX must use copyObject here since parse analysis scribbles on its
+                * input, and we need the unmodified raw parse tree for possible
                 * replanning later.
                 */
                if (log_parser_stats)
@@ -1225,7 +1243,7 @@ exec_parse_message(const char *query_string,      /* string to execute */
                                                           commandTag,
                                                           paramTypes,
                                                           numParams,
-                                                          0,                           /* default cursor options */
+                                                          0,           /* default cursor options */
                                                           stmt_list,
                                                           false);
        }
@@ -1235,7 +1253,7 @@ exec_parse_message(const char *query_string,      /* string to execute */
                 * paramTypes and query_string need to be copied into
                 * unnamed_stmt_context.  The rest is there already
                 */
-               Oid        *newParamTypes;
+               Oid                *newParamTypes;
 
                if (numParams > 0)
                {
@@ -1250,7 +1268,7 @@ exec_parse_message(const char *query_string,      /* string to execute */
                                                                                                 commandTag,
                                                                                                 newParamTypes,
                                                                                                 numParams,
-                                                                                                0,     /* cursor options */
+                                                                                                0,             /* cursor options */
                                                                                                 stmt_list,
                                                                                                 fully_planned,
                                                                                                 true,
@@ -1396,7 +1414,7 @@ exec_bind_message(StringInfo input_message)
                ereport(ERROR,
                                (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                 errmsg("bind message supplies %d parameters, but prepared statement \"%s\" requires %d",
-                                  numParams, stmt_name, psrc->num_params)));
+                                               numParams, stmt_name, psrc->num_params)));
 
        /*
         * If we are in aborted transaction state, the only portals we can
@@ -1580,8 +1598,8 @@ exec_bind_message(StringInfo input_message)
        {
                /*
                 * Revalidate the cached plan; this may result in replanning.  Any
-                * cruft will be generated in MessageContext.  The plan refcount
-                * will be assigned to the Portal, so it will be released at portal
+                * cruft will be generated in MessageContext.  The plan refcount will
+                * be assigned to the Portal, so it will be released at portal
                 * destruction.
                 */
                cplan = RevalidateCachedPlan(psrc, false);
@@ -1663,7 +1681,7 @@ exec_bind_message(StringInfo input_message)
                                                        *stmt_name ? stmt_name : "<unnamed>",
                                                        *portal_name ? "/" : "",
                                                        *portal_name ? portal_name : "",
-                                                       psrc->query_string ? psrc->query_string : "<source not stored>"),
+                       psrc->query_string ? psrc->query_string : "<source not stored>"),
                                         errhidestmt(true),
                                         errdetail_params(params)));
                        break;
@@ -1825,7 +1843,7 @@ exec_execute_message(const char *portal_name, long max_rows)
 
        completed = PortalRun(portal,
                                                  max_rows,
-                                                 true,                                 /* always top level */
+                                                 true, /* always top level */
                                                  receiver,
                                                  receiver,
                                                  completionTag);
@@ -2117,8 +2135,8 @@ exec_describe_statement_message(const char *stmt_name)
 
        /*
         * If we are in aborted transaction state, we can't run
-        * SendRowDescriptionMessage(), because that needs catalog accesses.
-        * (We can't do RevalidateCachedPlan, either, but that's a lesser problem.)
+        * SendRowDescriptionMessage(), because that needs catalog accesses. (We
+        * can't do RevalidateCachedPlan, either, but that's a lesser problem.)
         * 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
@@ -2351,6 +2369,7 @@ drop_unnamed_stmt(void)
        if (unnamed_stmt_psrc)
                DropCachedPlan(unnamed_stmt_psrc);
        unnamed_stmt_psrc = NULL;
+
        /*
         * If we failed while trying to build a prior unnamed statement, we may
         * have a memory context that wasn't assigned to a completed plancache
@@ -2540,8 +2559,13 @@ ProcessInterrupts(void)
                ImmediateInterruptOK = false;   /* not idle anymore */
                DisableNotifyInterrupt();
                DisableCatchupInterrupt();
-               ereport(FATAL,
-                               (errcode(ERRCODE_ADMIN_SHUTDOWN),
+               if (IsAutoVacuumWorkerProcess())
+                       ereport(FATAL,
+                                       (errcode(ERRCODE_ADMIN_SHUTDOWN),
+                                        errmsg("terminating autovacuum process due to administrator command")));
+               else
+                       ereport(FATAL,
+                                       (errcode(ERRCODE_ADMIN_SHUTDOWN),
                         errmsg("terminating connection due to administrator command")));
        }
        if (QueryCancelPending)
@@ -2602,8 +2626,8 @@ check_stack_depth(void)
                ereport(ERROR,
                                (errcode(ERRCODE_STATEMENT_TOO_COMPLEX),
                                 errmsg("stack depth limit exceeded"),
-                                errhint("Increase the configuration parameter \"max_stack_depth\", "
-                                                "after ensuring the platform's stack depth limit is adequate.")));
+                errhint("Increase the configuration parameter \"max_stack_depth\", "
+                  "after ensuring the platform's stack depth limit is adequate.")));
        }
 }
 
@@ -2764,6 +2788,8 @@ PostgresMain(int argc, char *argv[], const char *username)
         */
        MyProcPid = getpid();
 
+       MyStartTime = time(NULL);
+
        /*
         * Fire up essential subsystems: error and memory management
         *
@@ -2828,9 +2854,9 @@ PostgresMain(int argc, char *argv[], const char *username)
        gucsource = PGC_S_ARGV;         /* initial switches came from command line */
 
        /*
-        * 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.
+        * 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:c:D:d:EeFf:h:ijk:lN:nOo:Pp:r:S:sTt:v:W:y:-:")) != -1)
        {
@@ -3086,7 +3112,16 @@ PostgresMain(int argc, char *argv[], const char *username)
        pqsignal(SIGHUP, SigHupHandler);        /* set flag to read config file */
        pqsignal(SIGINT, StatementCancelHandler);       /* cancel current query */
        pqsignal(SIGTERM, die);         /* cancel current query and exit */
-       pqsignal(SIGQUIT, quickdie);    /* hard crash time */
+
+       /*
+        * 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 */
        pqsignal(SIGALRM, handle_sig_alarm);            /* timeout conditions */
 
        /*
@@ -3107,12 +3142,15 @@ PostgresMain(int argc, char *argv[], const char *username)
 
        pqinitmask();
 
-       /* We allow SIGQUIT (quickdie) at all times */
+       if (IsUnderPostmaster)
+       {
+               /* We allow SIGQUIT (quickdie) at all times */
 #ifdef HAVE_SIGPROCMASK
-       sigdelset(&BlockSig, SIGQUIT);
+               sigdelset(&BlockSig, SIGQUIT);
 #else
-       BlockSig &= ~(sigmask(SIGQUIT));
+               BlockSig &= ~(sigmask(SIGQUIT));
 #endif
+       }
 
        PG_SETMASK(&BlockSig);          /* block everything except SIGQUIT */
 
@@ -3751,11 +3789,11 @@ get_stack_depth_rlimit(void)
                        val = rlim.rlim_cur;
        }
        return val;
-#else /* no getrlimit */
+#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 */
+#else                                                  /* not windows ... give up */
        return -1;
 #endif
 #endif