]> granicus.if.org Git - postgresql/blob - src/backend/tcop/postgres.c
Fix bug noted by Bruce: FETCH in an already-aborted transaction block
[postgresql] / src / backend / tcop / postgres.c
1 /*-------------------------------------------------------------------------
2  *
3  * postgres.c
4  *        POSTGRES C Backend Interface
5  *
6  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.149 2000/04/04 21:44:39 tgl Exp $
12  *
13  * NOTES
14  *        this is the "main" module of the postgres backend and
15  *        hence the main module of the "traffic cop".
16  *
17  *-------------------------------------------------------------------------
18  */
19
20 #include <unistd.h>
21 #include <signal.h>
22 #include <time.h>
23 #include <sys/time.h>
24 #include <sys/types.h>
25 #include <fcntl.h>
26 #include <sys/socket.h>
27
28 #include "postgres.h"
29
30 #include <errno.h>
31 #if HAVE_SYS_SELECT_H
32 #include <sys/select.h>
33 #endif   /* aix */
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
36 #include <netdb.h>
37 #ifdef HAVE_GETOPT_H
38 #include <getopt.h>
39 #endif
40
41 #include "commands/async.h"
42 #include "commands/trigger.h"
43 #include "commands/variable.h"
44 #include "libpq/libpq.h"
45 #include "libpq/pqformat.h"
46 #include "libpq/pqsignal.h"
47 #include "miscadmin.h"
48 #include "nodes/print.h"
49 #include "optimizer/cost.h"
50 #include "optimizer/planner.h"
51 #include "parser/parser.h"
52 #include "rewrite/rewriteHandler.h"
53 #include "tcop/fastpath.h"
54 #include "tcop/pquery.h"
55 #include "tcop/tcopprot.h"
56 #include "tcop/utility.h"
57 #include "storage/proc.h"
58 #include "utils/ps_status.h"
59 #include "utils/temprel.h"
60 #include "utils/trace.h"
61
62 #include "../backend/parser/parse.h"
63
64 #ifdef MULTIBYTE
65 #include "mb/pg_wchar.h"
66 #endif
67
68 /*
69  * Trace flags, see backend/utils/misc/trace.c
70  */
71 #define Verbose                         pg_options[TRACE_VERBOSE]
72 #define DebugPrintQuery         pg_options[TRACE_QUERY]
73 #define DebugPrintPlan          pg_options[TRACE_PLAN]
74 #define DebugPrintParse         pg_options[TRACE_PARSE]
75 #define DebugPrintRewrittenParsetree \
76                                                         pg_options[TRACE_REWRITTEN]
77 #define DebugPPrintPlan         pg_options[TRACE_PRETTY_PLAN]
78 #define DebugPPrintParse        pg_options[TRACE_PRETTY_PARSE]
79 #define DebugPPrintRewrittenParsetree \
80                                                         pg_options[TRACE_PRETTY_REWRITTEN]
81 #define ShowParserStats         pg_options[TRACE_PARSERSTATS]
82 #define ShowPlannerStats        pg_options[TRACE_PLANNERSTATS]
83 #define ShowExecutorStats       pg_options[TRACE_EXECUTORSTATS]
84 #ifdef LOCK_MGR_DEBUG
85 #define LockDebug                       pg_options[TRACE_LOCKS]
86 #endif
87
88 #define DeadlockCheckTimer      pg_options[OPT_DEADLOCKTIMEOUT]
89 #define HostnameLookup          pg_options[OPT_HOSTLOOKUP]
90 #define ShowPortNumber          pg_options[OPT_SHOWPORTNUMBER]
91
92 /* ----------------
93  *              global variables
94  * ----------------
95  */
96
97 CommandDest whereToSendOutput = Debug;
98
99 /* Define status buffer needed by PS_SET_STATUS */
100 #ifdef PS_DEFINE_BUFFER
101 PS_DEFINE_BUFFER;
102 #endif
103
104 extern void             BaseInit(void);
105 extern void             StartupXLOG(void);
106 extern void             ShutdownXLOG(void);
107
108 extern void             HandleDeadLock(SIGNAL_ARGS);
109
110 extern char             XLogDir[];
111 extern char             ControlFilePath[];
112
113 extern int      lockingOff;
114 extern int      NBuffers;
115
116 int                     dontExecute = 0;
117 static int      ShowStats;
118 static bool IsEmptyQuery = false;
119
120 /* note: these declarations had better match tcopprot.h */
121 DLLIMPORT sigjmp_buf Warn_restart;
122
123 bool            Warn_restart_ready = false;
124 bool            InError = false;
125 bool            ExitAfterAbort = false;
126
127 extern int      NBuffers;
128
129 static bool     EchoQuery = false;              /* default don't echo */
130 time_t          tim;
131 char            pg_pathname[MAXPGPATH];
132 FILE       *StatFp;
133
134 /* ----------------
135  *              people who want to use EOF should #define DONTUSENEWLINE in
136  *              tcop/tcopdebug.h
137  * ----------------
138  */
139 #ifndef TCOP_DONTUSENEWLINE
140 int                     UseNewLine = 1;         /* Use newlines query delimiters (the
141                                                                  * default) */
142
143 #else
144 int                     UseNewLine = 0;         /* Use EOF as query delimiters */
145
146 #endif   /* TCOP_DONTUSENEWLINE */
147
148 /*
149 ** Flags for expensive function optimization -- JMH 3/9/92
150 */
151 int                     XfuncMode = 0;
152
153 /*
154  * ----------------
155  *       Note: _exec_repeat_ defaults to 1 but may be changed
156  *                 by a DEBUG command.   If you set this to a large
157  *                 number N, run a single query, and then set it
158  *                 back to 1 and run N queries, you can get an idea
159  *                 of how much time is being spent in the parser and
160  *                 planner b/c in the first case this overhead only
161  *                 happens once.  -cim 6/9/91
162  * ----------------
163 */
164 int                     _exec_repeat_ = 1;
165
166 /* ----------------------------------------------------------------
167  *              decls for routines only used in this file
168  * ----------------------------------------------------------------
169  */
170 static int InteractiveBackend(StringInfo inBuf);
171 static int SocketBackend(StringInfo inBuf);
172 static int ReadCommand(StringInfo inBuf);
173 static void pg_exec_query(char *query_string);
174
175
176 /* ----------------------------------------------------------------
177  *              routines to obtain user input
178  * ----------------------------------------------------------------
179  */
180
181 /* ----------------
182  *      InteractiveBackend() is called for user interactive connections
183  *      the string entered by the user is placed in its parameter inBuf.
184  *
185  *  EOF is returned if end-of-file input is seen; time to shut down.
186  * ----------------
187  */
188
189 static int
190 InteractiveBackend(StringInfo inBuf)
191 {
192         int                     c;                              /* character read from getc() */
193         bool            end = false;    /* end-of-input flag */
194         bool            backslashSeen = false;  /* have we seen a \ ? */
195
196         /* ----------------
197          *      display a prompt and obtain input from the user
198          * ----------------
199          */
200         printf("backend> ");
201         fflush(stdout);
202
203         /* Reset inBuf to empty */
204         inBuf->len = 0;
205         inBuf->data[0] = '\0';
206
207         for (;;)
208         {
209                 if (UseNewLine)
210                 {
211                         /* ----------------
212                          *      if we are using \n as a delimiter, then read
213                          *      characters until the \n.
214                          * ----------------
215                          */
216                         while ((c = getc(stdin)) != EOF)
217                         {
218                                 if (c == '\n')
219                                 {
220                                         if (backslashSeen)
221                                         {
222                                                 /* discard backslash from inBuf */
223                                                 inBuf->data[--inBuf->len] = '\0';
224                                                 backslashSeen = false;
225                                                 continue;
226                                         }
227                                         else
228                                         {
229                                                 /* keep the newline character */
230                                                 appendStringInfoChar(inBuf, '\n');
231                                                 break;
232                                         }
233                                 }
234                                 else if (c == '\\')
235                                         backslashSeen = true;
236                                 else
237                                         backslashSeen = false;
238
239                                 appendStringInfoChar(inBuf, (char) c);
240                         }
241
242                         if (c == EOF)
243                                 end = true;
244                 }
245                 else
246                 {
247                         /* ----------------
248                          *      otherwise read characters until EOF.
249                          * ----------------
250                          */
251                         while ((c = getc(stdin)) != EOF)
252                                 appendStringInfoChar(inBuf, (char) c);
253
254                         if (inBuf->len == 0)
255                                 end = true;
256                 }
257
258                 if (end)
259                 {
260                         if (Verbose)
261                                 puts("EOF");
262                         return EOF;
263                 }
264
265                 /* ----------------
266                  *      otherwise we have a user query so process it.
267                  * ----------------
268                  */
269                 break;
270         }
271
272         /* ----------------
273          *      if the query echo flag was given, print the query..
274          * ----------------
275          */
276         if (EchoQuery)
277                 printf("query: %s\n", inBuf->data);
278         fflush(stdout);
279
280         return 'Q';
281 }
282
283 /* ----------------
284  *      SocketBackend()         Is called for frontend-backend connections
285  *
286  *      If the input is a query (case 'Q') then the string entered by
287  *      the user is placed in its parameter inBuf.
288  *
289  *      If the input is a fastpath function call (case 'F') then
290  *      the function call is processed in HandleFunctionRequest()
291  *      (now called from PostgresMain()).
292  *
293  *  EOF is returned if the connection is lost.
294  * ----------------
295  */
296
297 static int
298 SocketBackend(StringInfo inBuf)
299 {
300         char            qtype;
301         char            result = '\0';
302
303         /* ----------------
304          *      get input from the frontend
305          * ----------------
306          */
307         qtype = '?';
308         if (pq_getbytes(&qtype, 1) == EOF)
309                 return EOF;
310
311         switch (qtype)
312         {
313                         /* ----------------
314                          *      'Q': user entered a query
315                          * ----------------
316                          */
317                 case 'Q':
318                         if (pq_getstr(inBuf))
319                                 return EOF;
320                         result = 'Q';
321                         break;
322
323                         /* ----------------
324                          *      'F':  calling user/system functions
325                          * ----------------
326                          */
327                 case 'F':
328                         if (pq_getstr(inBuf))
329                                 return EOF;             /* ignore "string" at start of F message */
330                         result = 'F';
331                         break;
332
333                         /* ----------------
334                          *      'X':  frontend is exiting
335                          * ----------------
336                          */
337                 case 'X':
338                         result = 'X';
339                         break;
340
341                         /* ----------------
342                          *      otherwise we got garbage from the frontend.
343                          *
344                          *      XXX are we certain that we want to do an elog(FATAL) here?
345                          *              -cim 1/24/90
346                          * ----------------
347                          */
348                 default:
349                         elog(FATAL, "Socket command type %c unknown", qtype);
350                         break;
351         }
352         return result;
353 }
354
355 /* ----------------
356  *              ReadCommand reads a command from either the frontend or
357  *              standard input, places it in inBuf, and returns a char
358  *              representing whether the string is a 'Q'uery or a 'F'astpath
359  *              call.  EOF is returned if end of file.
360  * ----------------
361  */
362 static int
363 ReadCommand(StringInfo inBuf)
364 {
365         MemoryContext   oldcontext;
366         int                             result;
367
368         /* Make sure any expansion of inBuf happens in permanent memory context,
369          * so that we can keep using it for future command cycles.
370          */
371         oldcontext = MemoryContextSwitchTo(TopMemoryContext);
372         if (IsUnderPostmaster)
373                 result = SocketBackend(inBuf);
374         else
375                 result = InteractiveBackend(inBuf);
376         MemoryContextSwitchTo(oldcontext);
377         return result;
378 }
379
380
381 /*
382  * Parse a query string and pass it through the rewriter.
383  *
384  * A list of Query nodes is returned, since the string might contain
385  * multiple queries and/or the rewriter might expand one query to several.
386  */
387 List *
388 pg_parse_and_rewrite(char *query_string,        /* string to execute */
389                                          Oid *typev,                    /* argument types */
390                                          int nargs,                             /* number of arguments */
391                                          bool aclOverride)
392 {
393         List       *querytree_list;
394         List       *querytree_list_item;
395         Query      *querytree;
396         List       *new_list;
397
398         if (DebugPrintQuery)
399         {
400                 TPRINTF(TRACE_QUERY, "query: %s", query_string);
401         }
402
403         /* ----------------
404          *      (1) parse the request string into a list of parse trees
405          * ----------------
406          */
407         if (ShowParserStats)
408                 ResetUsage();
409
410         querytree_list = parser(query_string, typev, nargs);
411
412         if (ShowParserStats)
413         {
414                 fprintf(stderr, "! Parser Stats:\n");
415                 ShowUsage();
416         }
417
418         /* ----------------
419          *      (2) rewrite the queries, as necessary
420          *
421          *      rewritten queries are collected in new_list.  Note there may be
422          *      more or fewer than in the original list.
423          * ----------------
424          */
425         new_list = NIL;
426         foreach(querytree_list_item, querytree_list)
427         {
428                 querytree = (Query *) lfirst(querytree_list_item);
429
430                 if (DebugPrintParse || DebugPPrintParse)
431                 {
432                         if (DebugPPrintParse)
433                         {
434                                 TPRINTF(TRACE_PRETTY_PARSE, "parser outputs:");
435                                 nodeDisplay(querytree);
436                         }
437                         else
438                         {
439                                 TPRINTF(TRACE_PARSE, "parser outputs:");
440                                 printf("\n%s\n\n", nodeToString(querytree));
441                         }
442                 }
443
444                 if (querytree->commandType == CMD_UTILITY)
445                 {
446                         /* don't rewrite utilities, just dump 'em into new_list */
447                         new_list = lappend(new_list, querytree);
448                 }
449                 else
450                 {
451                         /* rewrite regular queries */
452                         List *rewritten = QueryRewrite(querytree);
453                         new_list = nconc(new_list, rewritten);
454                 }
455         }
456
457         querytree_list = new_list;
458
459         /* ----------------
460          *      (3) If ACL override is requested, mark queries for no ACL check.
461          * ----------------
462          */
463         if (aclOverride)
464         {
465                 foreach(querytree_list_item, querytree_list)
466                 {
467                         List       *l;
468
469                         querytree = (Query *) lfirst(querytree_list_item);
470
471                         if (querytree->commandType == CMD_UTILITY)
472                                 continue;
473
474                         foreach(l, querytree->rtable)
475                         {
476                                 RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
477
478                                 rte->skipAcl = TRUE;
479                         }
480                 }
481         }
482
483         if (DebugPrintRewrittenParsetree || DebugPPrintRewrittenParsetree)
484         {
485                 if (DebugPPrintRewrittenParsetree)
486                 {
487                         TPRINTF(TRACE_PRETTY_REWRITTEN, "after rewriting:");
488
489                         foreach(querytree_list_item, querytree_list)
490                         {
491                                 querytree = (Query *) lfirst(querytree_list_item);
492                                 nodeDisplay(querytree);
493                                 printf("\n");
494                         }
495                 }
496                 else
497                 {
498                         TPRINTF(TRACE_REWRITTEN, "after rewriting:");
499
500                         foreach(querytree_list_item, querytree_list)
501                         {
502                                 querytree = (Query *) lfirst(querytree_list_item);
503                                 printf("\n%s\n\n", nodeToString(querytree));
504                         }
505                 }
506         }
507
508         return querytree_list;
509 }
510
511
512 /* Generate a plan for a single query. */
513 Plan *
514 pg_plan_query(Query *querytree)
515 {
516         Plan       *plan;
517
518         /* Utility commands have no plans. */
519         if (querytree->commandType == CMD_UTILITY)
520                 return NULL;
521
522         if (ShowPlannerStats)
523                 ResetUsage();
524
525         /* call that optimizer */
526         plan = planner(querytree);
527
528         if (ShowPlannerStats)
529         {
530                 fprintf(stderr, "! Planner Stats:\n");
531                 ShowUsage();
532         }
533
534         /* ----------------
535          *      Print plan if debugging.
536          * ----------------
537          */
538         if (DebugPrintPlan || DebugPPrintPlan)
539         {
540                 if (DebugPPrintPlan)
541                 {
542                         TPRINTF(TRACE_PRETTY_PLAN, "plan:");
543                         nodeDisplay(plan);
544                 }
545                 else
546                 {
547                         TPRINTF(TRACE_PLAN, "plan:");
548                         printf("\n%s\n\n", nodeToString(plan));
549                 }
550         }
551
552         return plan;
553 }
554
555
556 /* ----------------------------------------------------------------
557  *              pg_exec_query()
558  *
559  *              Takes a querystring, runs the parser/utilities or
560  *              parser/planner/executor over it as necessary
561  *              Begin Transaction Should have been called before this
562  *              and CommitTransaction After this is called
563  *              This is strictly because we do not allow for nested xactions.
564  *
565  *              NON-OBVIOUS-RESTRICTIONS
566  *              this function _MUST_ allocate a new "parsetree" each time,
567  *              since it may be stored in a named portal and should not
568  *              change its value.
569  *
570  * ----------------------------------------------------------------
571  */
572
573 static void
574 pg_exec_query(char *query_string)
575 {
576         pg_exec_query_dest(query_string, whereToSendOutput, FALSE);
577 }
578
579 void
580 pg_exec_query_acl_override(char *query_string)
581 {
582         pg_exec_query_dest(query_string, whereToSendOutput, TRUE);
583 }
584
585 void
586 pg_exec_query_dest(char *query_string,  /* string to execute */
587                                    CommandDest dest,    /* where results should go */
588                                    bool aclOverride)    /* to give utility commands power
589                                                                                  * of superusers */
590 {
591         List       *querytree_list;
592
593         /* parse and rewrite the queries */
594         querytree_list = pg_parse_and_rewrite(query_string, NULL, 0,
595                                                                                   aclOverride);
596
597         /*
598          * NOTE: we do not use "foreach" here because we want to be sure the
599          * list pointer has been advanced before the query is executed. We
600          * need to do that because VACUUM has a nasty little habit of doing
601          * CommitTransactionCommand at startup, and that will release the
602          * memory holding our parse list :-(.  This needs a better
603          * solution --- currently, the code will crash if someone submits
604          * "vacuum; something-else" in a single query string.  But memory
605          * allocation needs redesigned anyway, so this will have to do for
606          * now.
607          */
608         while (querytree_list)
609         {
610                 Query      *querytree = (Query *) lfirst(querytree_list);
611
612                 querytree_list = lnext(querytree_list);
613
614                 /* if we got a cancel signal in parsing or prior command, quit */
615                 if (QueryCancel)
616                         CancelQuery();
617
618                 if (querytree->commandType == CMD_UTILITY)
619                 {
620                         /* ----------------
621                          *       process utility functions (create, destroy, etc..)
622                          *
623                          *       Note: we do not check for the transaction aborted state
624                          *       because that is done in ProcessUtility.
625                          * ----------------
626                          */
627                         if (DebugPrintQuery)
628                                 TPRINTF(TRACE_QUERY, "ProcessUtility: %s", query_string);
629                         else if (Verbose)
630                                 TPRINTF(TRACE_VERBOSE, "ProcessUtility");
631
632                         ProcessUtility(querytree->utilityStmt, dest);
633                 }
634                 else
635                 {
636                         Plan       *plan;
637                         int                     j;
638
639                         /* If aborted transaction, quit now */
640                         if (IsAbortedTransactionBlockState())
641                         {
642                                 /* ----------------
643                                  *       the EndCommand() stuff is to tell the frontend
644                                  *       that the command ended. -cim 6/1/90
645                                  * ----------------
646                                  */
647                                 char       *tag = "*ABORT STATE*";
648
649                                 elog(NOTICE, "current transaction is aborted, "
650                                          "queries ignored until end of transaction block");
651
652                                 EndCommand(tag, dest);
653
654                                 break;
655                         }
656
657                         plan = pg_plan_query(querytree);
658
659                         /* if we got a cancel signal whilst planning, quit */
660                         if (QueryCancel)
661                                 CancelQuery();
662
663                         /* Initialize snapshot state for query */
664                         SetQuerySnapshot();
665
666                         /*
667                          * execute the plan
668                          */
669                         if (ShowExecutorStats)
670                                 ResetUsage();
671
672                         for (j = 0; j < _exec_repeat_; j++)
673                         {
674                                 if (Verbose)
675                                         TPRINTF(TRACE_VERBOSE, "ProcessQuery");
676                                 ProcessQuery(querytree, plan, dest);
677                         }
678
679                         if (ShowExecutorStats)
680                         {
681                                 fprintf(stderr, "! Executor Stats:\n");
682                                 ShowUsage();
683                         }
684                 }
685
686                 /*
687                  * In a query block, we want to increment the command counter
688                  * between queries so that the effects of early queries are
689                  * visible to subsequent ones.
690                  */
691
692                 CommandCounterIncrement();
693         }
694 }
695
696 /* --------------------------------
697  *              signal handler routines used in PostgresMain()
698  *
699  *              handle_warn() catches SIGQUIT.  It forces control back to the main
700  *              loop, just as if an internal error (elog(ERROR,...)) had occurred.
701  *              elog() used to actually use kill(2) to induce a SIGQUIT to get here!
702  *              But that's not 100% reliable on some systems, so now it does its own
703  *              siglongjmp() instead.
704  *              We still provide the signal catcher so that an error quit can be
705  *              forced externally.      This should be done only with great caution,
706  *              however, since an asynchronous signal could leave the system in
707  *              who-knows-what inconsistent state.
708  *
709  *              quickdie() occurs when signalled by the postmaster.
710  *              Some backend has bought the farm,
711  *              so we need to stop what we're doing and exit.
712  *
713  *              die() performs an orderly cleanup via proc_exit()
714  * --------------------------------
715  */
716
717 void
718 handle_warn(SIGNAL_ARGS)
719 {
720         siglongjmp(Warn_restart, 1);
721 }
722
723 void
724 quickdie(SIGNAL_ARGS)
725 {
726         PG_SETMASK(&BlockSig);
727         elog(NOTICE, "Message from PostgreSQL backend:"
728                  "\n\tThe Postmaster has informed me that some other backend"
729                  " died abnormally and possibly corrupted shared memory."
730                  "\n\tI have rolled back the current transaction and am"
731                  " going to terminate your database system connection and exit."
732         "\n\tPlease reconnect to the database system and repeat your query.");
733
734
735         /*
736          * DO NOT proc_exit(0) -- we're here because shared memory may be
737          * corrupted, so we don't want to flush any shared state to stable
738          * storage.  Just nail the windows shut and get out of town.
739          */
740
741         exit(1);
742 }
743
744 /*
745  * Abort transaction and exit
746  */
747 void
748 die(SIGNAL_ARGS)
749 {
750         PG_SETMASK(&BlockSig);
751         /*
752          * If ERROR/FATAL is in progress...
753          */
754         if (InError)
755         {
756                 ExitAfterAbort = true;
757                 return;
758         }
759         elog(FATAL, "The system is shutting down");
760 }
761
762 /* signal handler for floating point exception */
763 void
764 FloatExceptionHandler(SIGNAL_ARGS)
765 {
766         elog(ERROR, "floating point exception!"
767                  " The last floating point operation either exceeded legal ranges"
768                  " or was a divide by zero");
769 }
770
771 /* signal handler for query cancel signal from postmaster */
772 static void
773 QueryCancelHandler(SIGNAL_ARGS)
774 {
775         QueryCancel = true;
776         LockWaitCancel();
777 }
778
779 void
780 CancelQuery(void)
781 {
782
783         /*
784          * QueryCancel flag will be reset in main loop, which we reach by
785          * longjmp from elog().
786          */
787         elog(ERROR, "Query was cancelled.");
788 }
789
790
791 static void
792 usage(char *progname)
793 {
794         fprintf(stderr,
795                         "Usage: %s [options] [dbname]\n", progname);
796 #ifdef USE_ASSERT_CHECKING
797         fprintf(stderr, "\t-A on\t\tenable/disable assert checking\n");
798 #endif
799         fprintf(stderr, "\t-B buffers\tset number of buffers in buffer pool\n");
800         fprintf(stderr, "\t-C \t\tsuppress version info\n");
801         fprintf(stderr, "\t-D dir\t\tdata directory\n");
802         fprintf(stderr, "\t-E \t\techo query before execution\n");
803         fprintf(stderr, "\t-F \t\tturn off fsync\n");
804 #ifdef LOCK_MGR_DEBUG
805         fprintf(stderr, "\t-K lev\t\tset locking debug level [0|1|2]\n");
806 #endif
807         fprintf(stderr, "\t-L \t\tturn off locking\n");
808         fprintf(stderr, "\t-N \t\tdon't use newline as interactive query delimiter\n");
809         fprintf(stderr, "\t-O \t\tallow system table structure changes\n");
810         fprintf(stderr, "\t-Q \t\tsuppress informational messages\n");
811         fprintf(stderr, "\t-S kbytes\tset amount of memory for sorts (in kbytes)\n");
812         fprintf(stderr, "\t-T options\tspecify pg_options\n");
813         fprintf(stderr, "\t-W sec\t\twait N seconds to allow attach from a debugger\n");
814         fprintf(stderr, "\t-d [1-5]\tset debug level\n");
815         fprintf(stderr, "\t-e \t\tturn on European date format\n");
816         fprintf(stderr, "\t-f [s|i|n|m|h]\tforbid use of some plan types\n");
817         fprintf(stderr, "\t-i \t\tdon't execute queries\n");
818         fprintf(stderr, "\t-o file\t\tsend stdout and stderr to given filename\n");
819         fprintf(stderr, "\t-p database\tbackend is started under a postmaster\n");
820         fprintf(stderr, "\t-s \t\tshow stats after each query\n");
821         fprintf(stderr, "\t-t [pa|pl|ex]\tshow timings after each query\n");
822         fprintf(stderr, "\t-v version\tset protocol version being used by frontend\n");
823 }
824
825 /* ----------------------------------------------------------------
826  *      PostgresMain
827  *              postgres main loop
828  *              all backends, interactive or otherwise start here
829  *
830  *      argc/argv are the command line arguments to be used.  When being forked
831  *      by the postmaster, these are not the original argv array of the process.
832  *      real_argc/real_argv point to the original argv array, which is needed by
833  *      PS_INIT_STATUS on some platforms.
834  * ----------------------------------------------------------------
835  */
836 int
837 PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
838 {
839         int                     flag;
840
841         char       *DBName = NULL;
842         bool            secure = true;
843         int                     errs = 0;
844
845         int                     firstchar;
846         StringInfo      parser_input;
847         char       *userName;
848
849         /* Used if verbose is set, must be initialized */
850         char       *remote_info = "interactive";
851         char       *remote_host = "";
852         unsigned short remote_port = 0;
853
854         extern int      optind;
855         extern char *optarg;
856         extern int  DebugLvl;
857
858         /*
859          * Set default values for command-line options.
860          */
861         IsUnderPostmaster = false;
862         ShowStats = 0;
863         ShowParserStats = ShowPlannerStats = ShowExecutorStats = 0;
864         DeadlockCheckTimer = DEADLOCK_CHECK_TIMER;
865         Noversion = false;
866         EchoQuery = false;
867 #ifdef LOCK_MGR_DEBUG
868         LockDebug = 0;
869 #endif
870         DataDir = getenv("PGDATA");
871
872         SetProcessingMode(InitProcessing);
873
874         /* Check for PGDATESTYLE environment variable */
875         set_default_datestyle();
876
877         /*
878          * Read default pg_options from file $DATADIR/pg_options.
879          */
880         if (DataDir)
881                 read_pg_options(0);
882
883         /* ----------------
884          *      parse command line arguments
885          *
886          *      There are now two styles of command line layout for the backend:
887          *
888          *      For interactive use (not started from postmaster) the format is
889          *              postgres [switches] [databasename]
890          *      If the databasename is omitted it is taken to be the user name.
891          *
892          *      When started from the postmaster, the format is
893          *              postgres [secure switches] -p databasename [insecure switches]
894          *      Switches appearing after -p came from the client (via "options"
895          *      field of connection request).  For security reasons we restrict
896          *      what these switches can do.
897          * ----------------
898          */
899
900         optind = 1;                                     /* reset after postmaster's usage */
901
902         while ((flag = getopt(argc, argv,
903                                                   "A:B:CD:d:EeFf:iK:LNOPo:p:QS:sT:t:v:W:x:"))
904                    != EOF)
905                 switch (flag)
906                 {
907                         case 'A':
908                                 /* ----------------
909                                  *      enable/disable assert checking.
910                                  * ----------------
911                                  */
912 #ifdef USE_ASSERT_CHECKING
913                                 assert_enabled = atoi(optarg);
914 #else
915                                 fprintf(stderr, "Assert checking is not enabled\n");
916 #endif
917                                 break;
918
919                         case 'B':
920                                 /* ----------------
921                                  *      specify the size of buffer pool
922                                  * ----------------
923                                  */
924                                 if (secure)
925                                         NBuffers = atoi(optarg);
926                                 break;
927
928                         case 'C':
929                                 /* ----------------
930                                  *      don't print version string
931                                  * ----------------
932                                  */
933                                 Noversion = true;
934                                 break;
935
936                         case 'D':                       /* PGDATA directory */
937                                 if (secure)
938                                 {
939                                         if (!DataDir)
940                                         {
941                                                 DataDir = optarg;
942                                                 /* must be done after DataDir is defined */
943                                                 read_pg_options(0);
944                                         }
945                                         DataDir = optarg;
946                                 }
947                                 break;
948
949                         case 'd':                       /* debug level */
950                                 DebugLvl = atoi(optarg);
951                                 if (DebugLvl >= 1)
952                                         Verbose = true;
953                                 if (DebugLvl >= 2)
954                                         DebugPrintQuery = true;
955                                 if (DebugLvl >= 3)
956                                         DebugPrintParse = true;
957                                 if (DebugLvl >= 4)
958                                         DebugPrintPlan = true;
959                                 if (DebugLvl >= 5)
960                                         DebugPPrintRewrittenParsetree = true;
961                                 break;
962
963                         case 'E':
964                                 /* ----------------
965                                  *      E - echo the query the user entered
966                                  * ----------------
967                                  */
968                                 EchoQuery = true;
969                                 break;
970
971                         case 'e':
972                                 /* --------------------------
973                                  * Use european date formats.
974                                  * --------------------------
975                                  */
976                                 EuroDates = true;
977                                 break;
978
979                         case 'F':
980                                 /* --------------------
981                                  *      turn off fsync
982                                  * --------------------
983                                  */
984                                 if (secure)
985                                         disableFsync = true;
986                                 break;
987
988                         case 'f':
989                                 /* -----------------
990                                  *        f - forbid generation of certain plans
991                                  * -----------------
992                                  */
993                                 switch (optarg[0])
994                                 {
995                                         case 's':       /* seqscan */
996                                                 enable_seqscan = false;
997                                                 break;
998                                         case 'i':       /* indexscan */
999                                                 enable_indexscan = false;
1000                                                 break;
1001                                         case 't':       /* tidscan */
1002                                                 enable_tidscan = false;
1003                                                 break;
1004                                         case 'n':       /* nestloop */
1005                                                 enable_nestloop = false;
1006                                                 break;
1007                                         case 'm':       /* mergejoin */
1008                                                 enable_mergejoin = false;
1009                                                 break;
1010                                         case 'h':       /* hashjoin */
1011                                                 enable_hashjoin = false;
1012                                                 break;
1013                                         default:
1014                                                 errs++;
1015                                 }
1016                                 break;
1017
1018                         case 'i':
1019                                 dontExecute = 1;
1020                                 break;
1021
1022                         case 'K':
1023 #ifdef LOCK_MGR_DEBUG
1024                                 LockDebug = atoi(optarg);
1025 #else
1026                                 fprintf(stderr, "Lock debug not compiled in\n");
1027 #endif
1028                                 break;
1029
1030                         case 'L':
1031                                 /* --------------------
1032                                  *      turn off locking
1033                                  * --------------------
1034                                  */
1035                                 if (secure)
1036                                         lockingOff = 1;
1037                                 break;
1038
1039                         case 'N':
1040                                 /* ----------------
1041                                  *      N - Don't use newline as a query delimiter
1042                                  * ----------------
1043                                  */
1044                                 UseNewLine = 0;
1045                                 break;
1046
1047                         case 'O':
1048                                 /* --------------------
1049                                  *      allow system table structure modifications
1050                                  * --------------------
1051                                  */
1052                                 if (secure)             /* XXX safe to allow from client??? */
1053                                         allowSystemTableMods = true;
1054                                 break;
1055
1056                         case 'P':
1057                                 /* --------------------
1058                                  *      ignore system indexes
1059                                  * --------------------
1060                                  */
1061                                 if (secure)             /* XXX safe to allow from client??? */
1062                                         IgnoreSystemIndexes(true);
1063                                 break;
1064
1065                         case 'o':
1066                                 /* ----------------
1067                                  *      o - send output (stdout and stderr) to the given file
1068                                  * ----------------
1069                                  */
1070                                 if (secure)
1071                                         StrNCpy(OutputFileName, optarg, MAXPGPATH);
1072                                 break;
1073
1074                         case 'p':
1075                                 /* ----------------
1076                                  *      p - special flag passed if backend was forked
1077                                  *              by a postmaster.
1078                                  * ----------------
1079                                  */
1080                                 if (secure)
1081                                 {
1082                                         IsUnderPostmaster = true;
1083                                         DBName = optarg;
1084                                         secure = false;         /* subsequent switches are NOT
1085                                                                                  * secure */
1086                                 }
1087                                 break;
1088
1089                         case 'Q':
1090                                 /* ----------------
1091                                  *      Q - set Quiet mode (reduce debugging output)
1092                                  * ----------------
1093                                  */
1094                                 Verbose = false;
1095                                 break;
1096
1097                         case 'S':
1098                                 /* ----------------
1099                                  *      S - amount of sort memory to use in 1k bytes
1100                                  * ----------------
1101                                  */
1102                                 {
1103                                         int                     S;
1104
1105                                         S = atoi(optarg);
1106                                         if (S >= 4 * BLCKSZ / 1024)
1107                                                 SortMem = S;
1108                                 }
1109                                 break;
1110
1111                         case 's':
1112                                 /* ----------------
1113                                  *        s - report usage statistics (timings) after each query
1114                                  * ----------------
1115                                  */
1116                                 ShowStats = 1;
1117                                 StatFp = stderr;
1118                                 break;
1119
1120                         case 'T':
1121                                 /* ----------------
1122                                  *      T - tracing options
1123                                  * ----------------
1124                                  */
1125                                 parse_options(optarg, secure);
1126                                 break;
1127
1128                         case 't':
1129                                 /* ----------------
1130                                  *      tell postgres to report usage statistics (timings) for
1131                                  *      each query
1132                                  *
1133                                  *      -tpa[rser] = print stats for parser time of each query
1134                                  *      -tpl[anner] = print stats for planner time of each query
1135                                  *      -te[xecutor] = print stats for executor time of each query
1136                                  *      caution: -s can not be used together with -t.
1137                                  * ----------------
1138                                  */
1139                                 StatFp = stderr;
1140                                 switch (optarg[0])
1141                                 {
1142                                         case 'p':
1143                                                 if (optarg[1] == 'a')
1144                                                         ShowParserStats = 1;
1145                                                 else if (optarg[1] == 'l')
1146                                                         ShowPlannerStats = 1;
1147                                                 else
1148                                                         errs++;
1149                                                 break;
1150                                         case 'e':
1151                                                 ShowExecutorStats = 1;
1152                                                 break;
1153                                         default:
1154                                                 errs++;
1155                                                 break;
1156                                 }
1157                                 break;
1158
1159                         case 'v':
1160                                 if (secure)
1161                                         FrontendProtocol = (ProtocolVersion) atoi(optarg);
1162                                 break;
1163
1164                         case 'W':
1165                                 /* ----------------
1166                                  *      wait N seconds to allow attach from a debugger
1167                                  * ----------------
1168                                  */
1169                                 sleep(atoi(optarg));
1170                                 break;
1171
1172                         case 'x':
1173 #ifdef NOT_USED                                 /* planner/xfunc.h */
1174
1175                                 /*
1176                                  * control joey hellerstein's expensive function
1177                                  * optimization
1178                                  */
1179                                 if (XfuncMode != 0)
1180                                 {
1181                                         fprintf(stderr, "only one -x flag is allowed\n");
1182                                         errs++;
1183                                         break;
1184                                 }
1185                                 if (strcmp(optarg, "off") == 0)
1186                                         XfuncMode = XFUNC_OFF;
1187                                 else if (strcmp(optarg, "nor") == 0)
1188                                         XfuncMode = XFUNC_NOR;
1189                                 else if (strcmp(optarg, "nopull") == 0)
1190                                         XfuncMode = XFUNC_NOPULL;
1191                                 else if (strcmp(optarg, "nopm") == 0)
1192                                         XfuncMode = XFUNC_NOPM;
1193                                 else if (strcmp(optarg, "pullall") == 0)
1194                                         XfuncMode = XFUNC_PULLALL;
1195                                 else if (strcmp(optarg, "wait") == 0)
1196                                         XfuncMode = XFUNC_WAIT;
1197                                 else
1198                                 {
1199                                         fprintf(stderr, "use -x {off,nor,nopull,nopm,pullall,wait}\n");
1200                                         errs++;
1201                                 }
1202 #endif
1203                                 break;
1204
1205                         default:
1206                                 /* ----------------
1207                                  *      default: bad command line option
1208                                  * ----------------
1209                                  */
1210                                 errs++;
1211                                 break;
1212                 }
1213
1214         if (ShowStats &&
1215                 (ShowParserStats || ShowPlannerStats || ShowExecutorStats))
1216         {
1217                 fprintf(stderr, "-s can not be used together with -t.\n");
1218                 proc_exit(0);
1219         }
1220
1221         if (!DataDir)
1222         {
1223                 fprintf(stderr, "%s does not know where to find the database system "
1224                                 "data.  You must specify the directory that contains the "
1225                                 "database system either by specifying the -D invocation "
1226                                 "option or by setting the PGDATA environment variable.\n\n",
1227                                 argv[0]);
1228                 proc_exit(1);
1229         }
1230
1231         /*
1232          * 1. Set BlockSig and UnBlockSig masks. 
1233          * 2. Set up signal handlers.
1234          * 3. Allow only SIGUSR1 signal (we never block it) 
1235          *    during initialization.
1236          *
1237          * Note that postmaster already blocked ALL signals to make us happy.
1238          */
1239         if (!IsUnderPostmaster)
1240         {
1241                 PG_INITMASK();
1242                 PG_SETMASK(&BlockSig);
1243         }
1244
1245 #ifdef HAVE_SIGPROCMASK
1246         sigdelset(&BlockSig, SIGUSR1);
1247 #else
1248         BlockSig &= ~(sigmask(SIGUSR1));
1249 #endif
1250
1251         pqsignal(SIGHUP, read_pg_options);              /* update pg_options from file */
1252         pqsignal(SIGINT, QueryCancelHandler);   /* cancel current query */
1253         pqsignal(SIGQUIT, handle_warn);                 /* handle error */
1254         pqsignal(SIGTERM, die);
1255         pqsignal(SIGALRM, HandleDeadLock);
1256         /* 
1257          * Ignore failure to write to frontend. Note: if frontend closes 
1258          * connection, we will notice it and exit cleanly when control next 
1259          * returns to outer loop.  This seems safer than forcing exit in the 
1260          * midst of output during who-knows-what operation...
1261          */
1262         pqsignal(SIGPIPE, SIG_IGN);
1263         pqsignal(SIGUSR1, quickdie);
1264         pqsignal(SIGUSR2, Async_NotifyHandler); /* flush also sinval cache */
1265         pqsignal(SIGFPE, FloatExceptionHandler);
1266         pqsignal(SIGCHLD, SIG_IGN);                             /* ignored, sent by LockOwners */
1267         pqsignal(SIGTTIN, SIG_DFL);
1268         pqsignal(SIGTTOU, SIG_DFL);
1269         pqsignal(SIGCONT, SIG_DFL);
1270
1271         PG_SETMASK(&BlockSig);          /* block everything except SIGUSR1 */
1272
1273         /*
1274          * Get user name (needed now in case it is the default database name)
1275          * and check command line validity
1276          */
1277         SetPgUserName();
1278         userName = GetPgUserName();
1279
1280         if (IsUnderPostmaster)
1281         {
1282                 /* noninteractive case: nothing should be left after switches */
1283                 if (errs || argc != optind || DBName == NULL)
1284                 {
1285                         usage(argv[0]);
1286                         proc_exit(0);
1287                 }
1288                 pq_init();                              /* initialize libpq at backend startup */
1289                 whereToSendOutput = Remote;
1290                 BaseInit();
1291         }
1292         else
1293         {
1294                 /* interactive case: database name can be last arg on command line */
1295                 whereToSendOutput = Debug;
1296                 if (errs || argc - optind > 1)
1297                 {
1298                         usage(argv[0]);
1299                         proc_exit(0);
1300                 }
1301                 else if (argc - optind == 1)
1302                         DBName = argv[optind];
1303                 else if ((DBName = userName) == NULL)
1304                 {
1305                         fprintf(stderr, "%s: USER undefined and no database specified\n",
1306                                         argv[0]);
1307                         proc_exit(0);
1308                 }
1309
1310                 /*
1311                  * Try to create pid file.
1312                  */
1313                 SetPidFname(DataDir);
1314                 if (SetPidFile(-getpid())) {
1315                         proc_exit(0);
1316                 }
1317                 /*
1318                  * Register clean up proc.
1319                  */
1320                 on_proc_exit(UnlinkPidFile, NULL);
1321
1322                 BaseInit();
1323                 snprintf(XLogDir, MAXPGPATH, "%s%cpg_xlog",
1324                                  DataDir, SEP_CHAR);
1325                 snprintf(ControlFilePath, MAXPGPATH, "%s%cpg_control",
1326                                  DataDir, SEP_CHAR);
1327                 StartupXLOG();
1328         }
1329
1330         /*
1331          * Set up additional info.
1332          */
1333
1334 #ifdef CYR_RECODE
1335         SetCharSet();
1336 #endif
1337
1338         /* On some systems our dynloader code needs the executable's pathname */
1339         if (FindExec(pg_pathname, argv[0], "postgres") < 0)
1340                 elog(FATAL, "%s: could not locate executable, bailing out...",
1341                          argv[0]);
1342
1343         /*
1344          * Find remote host name or address.
1345          */
1346         if (IsUnderPostmaster)
1347         {
1348                 switch (MyProcPort->raddr.sa.sa_family)
1349                 {
1350                                 struct hostent *host_ent;
1351
1352                         case AF_INET:
1353                                 remote_info = remote_host = malloc(48);
1354                                 remote_port = ntohs(MyProcPort->raddr.in.sin_port);
1355                                 strcpy(remote_host, inet_ntoa(MyProcPort->raddr.in.sin_addr));
1356                                 if (HostnameLookup)
1357                                 {
1358                                         host_ent = \
1359                                                 gethostbyaddr((char *) &MyProcPort->raddr.in.sin_addr,
1360                                                                    sizeof(MyProcPort->raddr.in.sin_addr),
1361                                                                           AF_INET);
1362                                         if (host_ent)
1363                                         {
1364                                                 strncpy(remote_host, host_ent->h_name, 48);
1365                                                 *(remote_host + 47) = '\0';
1366                                         }
1367                                 }
1368                                 if (ShowPortNumber)
1369                                 {
1370                                         remote_info = malloc(strlen(remote_host) + 6);
1371                                         sprintf(remote_info, "%s:%d", remote_host, remote_port);
1372                                 }
1373                                 break;
1374                         case AF_UNIX:
1375                                 remote_info = remote_host = "localhost";
1376                                 break;
1377                         default:
1378                                 remote_info = remote_host = "unknown";
1379                                 break;
1380                 }
1381                 /*
1382                  * Set process params for ps
1383                  */
1384                 PS_INIT_STATUS(real_argc, real_argv, argv[0],
1385                                            remote_info, userName, DBName);
1386                 PS_SET_STATUS("startup");
1387         }
1388
1389
1390         /* ----------------
1391          *      print flags
1392          * ----------------
1393          */
1394         if (Verbose)
1395         {
1396                 if (Verbose)
1397                 {
1398                         TPRINTF(TRACE_VERBOSE, "started: host=%s user=%s database=%s",
1399                                         remote_host, userName, DBName);
1400                 }
1401                 else
1402                 {
1403                         TPRINTF(TRACE_VERBOSE, "debug info:");
1404                         TPRINTF(TRACE_VERBOSE, "\tUser         = %s", userName);
1405                         TPRINTF(TRACE_VERBOSE, "\tRemoteHost   = %s", remote_host);
1406                         TPRINTF(TRACE_VERBOSE, "\tRemotePort   = %d", remote_port);
1407                         TPRINTF(TRACE_VERBOSE, "\tDatabaseName = %s", DBName);
1408                         TPRINTF(TRACE_VERBOSE, "\tDebug Level  = %d", DebugLvl);
1409                         TPRINTF(TRACE_VERBOSE, "\tNoversion    = %c", Noversion ? 't' : 'f');
1410                         TPRINTF(TRACE_VERBOSE, "\ttimings      = %c", ShowStats ? 't' : 'f');
1411                         TPRINTF(TRACE_VERBOSE, "\tdates        = %s",
1412                                         EuroDates ? "European" : "Normal");
1413                         TPRINTF(TRACE_VERBOSE, "\tbufsize      = %d", NBuffers);
1414                         TPRINTF(TRACE_VERBOSE, "\tsortmem      = %d", SortMem);
1415                         TPRINTF(TRACE_VERBOSE, "\tquery echo   = %c", EchoQuery ? 't' : 'f');
1416                 }
1417         }
1418
1419
1420         /*
1421          * general initialization
1422          */
1423
1424         if (Verbose)
1425                 TPRINTF(TRACE_VERBOSE, "InitPostgres");
1426
1427         InitPostgres(DBName);
1428
1429 #ifdef MULTIBYTE
1430         /* set default client encoding */
1431         if (Verbose)
1432                 TPRINTF(TRACE_VERBOSE, "reset_client_encoding()..");
1433         reset_client_encoding();
1434         if (Verbose)
1435                 TPRINTF(TRACE_VERBOSE, "reset_client_encoding() done.");
1436 #endif
1437
1438         on_shmem_exit(remove_all_temp_relations, NULL);
1439
1440         {
1441                 MemoryContext   oldcontext = MemoryContextSwitchTo(TopMemoryContext);
1442                 parser_input = makeStringInfo(); /* initialize input buffer */
1443                 MemoryContextSwitchTo(oldcontext);
1444         }
1445
1446         /* 
1447          * Send this backend's cancellation info to the frontend. 
1448          */
1449         if (whereToSendOutput == Remote &&
1450                 PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)
1451         {
1452                 StringInfoData buf;
1453
1454                 pq_beginmessage(&buf);
1455                 pq_sendbyte(&buf, 'K');
1456                 pq_sendint(&buf, (int32) MyProcPid, sizeof(int32));
1457                 pq_sendint(&buf, (int32) MyCancelKey, sizeof(int32));
1458                 pq_endmessage(&buf);
1459                 /* Need not flush since ReadyForQuery will do it. */
1460         }
1461
1462         if (!IsUnderPostmaster)
1463         {
1464                 puts("\nPOSTGRES backend interactive interface ");
1465                 puts("$Revision: 1.149 $ $Date: 2000/04/04 21:44:39 $\n");
1466         }
1467
1468         /*
1469          * Initialize the deferred trigger manager
1470          */
1471         if (DeferredTriggerInit() != 0)
1472                 proc_exit(0);
1473
1474         SetProcessingMode(NormalProcessing);
1475
1476         /*
1477          * POSTGRES main processing loop begins here
1478          *
1479          * If an exception is encountered, processing resumes here
1480          * so we abort the current transaction and start a new one.
1481          */
1482
1483         if (sigsetjmp(Warn_restart, 1) != 0)
1484         {
1485                 time(&tim);
1486
1487                 if (Verbose)
1488                         TPRINTF(TRACE_VERBOSE, "AbortCurrentTransaction");
1489
1490                 AbortCurrentTransaction();
1491                 InError = false;
1492                 if (ExitAfterAbort)
1493                 {
1494                         ProcReleaseLocks();             /* Just to be sure... */
1495                         proc_exit(0);
1496                 }
1497         }
1498
1499         Warn_restart_ready = true;      /* we can now handle elog(ERROR) */
1500
1501         PG_SETMASK(&UnBlockSig);
1502
1503         /*
1504          * Non-error queries loop here.
1505          */
1506
1507         for (;;)
1508         {
1509                 PS_SET_STATUS("idle");
1510
1511                 /* ----------------
1512                  *       (1) tell the frontend we're ready for a new query.
1513                  *
1514                  *       Note: this includes fflush()'ing the last of the prior output.
1515                  * ----------------
1516                  */
1517                 ReadyForQuery(whereToSendOutput);
1518
1519                 /* ----------------
1520                  *       (2) deal with pending asynchronous NOTIFY from other backends,
1521                  *       and enable async.c's signal handler to execute NOTIFY directly.
1522                  * ----------------
1523                  */
1524                 QueryCancel = false;    /* forget any earlier CANCEL signal */
1525                 SetWaitingForLock(false);
1526
1527                 EnableNotifyInterrupt();
1528
1529                 /* ----------------
1530                  *       (3) read a command.
1531                  * ----------------
1532                  */
1533                 firstchar = ReadCommand(parser_input);
1534
1535                 QueryCancel = false;    /* forget any earlier CANCEL signal */
1536
1537                 /* ----------------
1538                  *       (4) disable async.c's signal handler.
1539                  * ----------------
1540                  */
1541                 DisableNotifyInterrupt();
1542
1543                 /* ----------------
1544                  *       (5) process the command.
1545                  * ----------------
1546                  */
1547                 switch (firstchar)
1548                 {
1549                                 /* ----------------
1550                                  *      'F' indicates a fastpath call.
1551                                  *              XXX HandleFunctionRequest
1552                                  * ----------------
1553                                  */
1554                         case 'F':
1555                                 IsEmptyQuery = false;
1556
1557                                 /* start an xact for this function invocation */
1558                                 if (Verbose)
1559                                         TPRINTF(TRACE_VERBOSE, "StartTransactionCommand");
1560                                 StartTransactionCommand();
1561
1562                                 if (HandleFunctionRequest() == EOF)
1563                                 {
1564                                         /* lost frontend connection during F message input */
1565                                         pq_close();
1566                                         proc_exit(0);
1567                                 }
1568                                 break;
1569
1570                                 /* ----------------
1571                                  *      'Q' indicates a user query
1572                                  * ----------------
1573                                  */
1574                         case 'Q':
1575                                 if (strspn(parser_input->data, " \t\n") == parser_input->len)
1576                                 {
1577                                         /* ----------------
1578                                          *      if there is nothing in the input buffer, don't bother
1579                                          *      trying to parse and execute anything..
1580                                          * ----------------
1581                                          */
1582                                         IsEmptyQuery = true;
1583                                 }
1584                                 else
1585                                 {
1586                                         /* ----------------
1587                                          *      otherwise, process the input string.
1588                                          * ----------------
1589                                          */
1590                                         IsEmptyQuery = false;
1591                                         if (ShowStats)
1592                                                 ResetUsage();
1593
1594                                         /* start an xact for this query */
1595                                         if (Verbose)
1596                                                 TPRINTF(TRACE_VERBOSE, "StartTransactionCommand");
1597                                         StartTransactionCommand();
1598
1599                                         pg_exec_query(parser_input->data);
1600
1601                                         /*
1602                                          * Invoke IMMEDIATE constraint triggers
1603                                          *
1604                                          */
1605                                         DeferredTriggerEndQuery();
1606
1607                                         if (ShowStats)
1608                                                 ShowUsage();
1609                                 }
1610                                 break;
1611
1612                                 /* ----------------
1613                                  *      'X' means that the frontend is closing down the socket.
1614                                  *      EOF means unexpected loss of frontend connection.
1615                                  *      Either way, perform normal shutdown.
1616                                  * ----------------
1617                                  */
1618                         case 'X':
1619                         case EOF:
1620                                 if (!IsUnderPostmaster)
1621                                         ShutdownXLOG();
1622                                 pq_close();
1623                                 proc_exit(0);
1624                                 break;
1625
1626                         default:
1627                                 elog(ERROR, "unknown frontend message was received");
1628                 }
1629
1630                 /* ----------------
1631                  *       (6) commit the current transaction
1632                  *
1633                  *       Note: if we had an empty input buffer, then we didn't
1634                  *       call pg_exec_query, so we don't bother to commit this transaction.
1635                  * ----------------
1636                  */
1637                 if (!IsEmptyQuery)
1638                 {
1639                         if (Verbose)
1640                                 TPRINTF(TRACE_VERBOSE, "CommitTransactionCommand");
1641                         PS_SET_STATUS("commit");
1642                         CommitTransactionCommand();
1643                 }
1644                 else
1645                 {
1646                         if (IsUnderPostmaster)
1647                                 NullCommand(Remote);
1648                 }
1649         }                                                       /* infinite for-loop */
1650
1651         proc_exit(0);                           /* shouldn't get here... */
1652         return 1;
1653 }
1654
1655 #ifndef HAVE_GETRUSAGE
1656 #include "rusagestub.h"
1657 #else
1658 #include <sys/resource.h>
1659 #endif   /* HAVE_GETRUSAGE */
1660
1661 struct rusage Save_r;
1662 struct timeval Save_t;
1663
1664 void
1665 ResetUsage(void)
1666 {
1667         struct timezone tz;
1668
1669         getrusage(RUSAGE_SELF, &Save_r);
1670         gettimeofday(&Save_t, &tz);
1671         ResetBufferUsage();
1672 /*        ResetTupleCount(); */
1673 }
1674
1675 void
1676 ShowUsage(void)
1677 {
1678         struct timeval user,
1679                                 sys;
1680         struct timeval elapse_t;
1681         struct timezone tz;
1682         struct rusage r;
1683
1684         getrusage(RUSAGE_SELF, &r);
1685         gettimeofday(&elapse_t, &tz);
1686         memmove((char *) &user, (char *) &r.ru_utime, sizeof(user));
1687         memmove((char *) &sys, (char *) &r.ru_stime, sizeof(sys));
1688         if (elapse_t.tv_usec < Save_t.tv_usec)
1689         {
1690                 elapse_t.tv_sec--;
1691                 elapse_t.tv_usec += 1000000;
1692         }
1693         if (r.ru_utime.tv_usec < Save_r.ru_utime.tv_usec)
1694         {
1695                 r.ru_utime.tv_sec--;
1696                 r.ru_utime.tv_usec += 1000000;
1697         }
1698         if (r.ru_stime.tv_usec < Save_r.ru_stime.tv_usec)
1699         {
1700                 r.ru_stime.tv_sec--;
1701                 r.ru_stime.tv_usec += 1000000;
1702         }
1703
1704         /*
1705          * the only stats we don't show here are for memory usage -- i can't
1706          * figure out how to interpret the relevant fields in the rusage
1707          * struct, and they change names across o/s platforms, anyway. if you
1708          * can figure out what the entries mean, you can somehow extract
1709          * resident set size, shared text size, and unshared data and stack
1710          * sizes.
1711          */
1712
1713         fprintf(StatFp, "! system usage stats:\n");
1714         fprintf(StatFp,
1715                         "!\t%ld.%06ld elapsed %ld.%06ld user %ld.%06ld system sec\n",
1716                         (long int) elapse_t.tv_sec - Save_t.tv_sec,
1717                         (long int) elapse_t.tv_usec - Save_t.tv_usec,
1718                         (long int) r.ru_utime.tv_sec - Save_r.ru_utime.tv_sec,
1719                         (long int) r.ru_utime.tv_usec - Save_r.ru_utime.tv_usec,
1720                         (long int) r.ru_stime.tv_sec - Save_r.ru_stime.tv_sec,
1721                         (long int) r.ru_stime.tv_usec - Save_r.ru_stime.tv_usec);
1722         fprintf(StatFp,
1723                         "!\t[%ld.%06ld user %ld.%06ld sys total]\n",
1724                         (long int) user.tv_sec,
1725                         (long int) user.tv_usec,
1726                         (long int) sys.tv_sec,
1727                         (long int) sys.tv_usec);
1728 #ifdef HAVE_GETRUSAGE
1729         fprintf(StatFp,
1730                         "!\t%ld/%ld [%ld/%ld] filesystem blocks in/out\n",
1731                         r.ru_inblock - Save_r.ru_inblock,
1732         /* they only drink coffee at dec */
1733                         r.ru_oublock - Save_r.ru_oublock,
1734                         r.ru_inblock, r.ru_oublock);
1735         fprintf(StatFp,
1736                   "!\t%ld/%ld [%ld/%ld] page faults/reclaims, %ld [%ld] swaps\n",
1737                         r.ru_majflt - Save_r.ru_majflt,
1738                         r.ru_minflt - Save_r.ru_minflt,
1739                         r.ru_majflt, r.ru_minflt,
1740                         r.ru_nswap - Save_r.ru_nswap,
1741                         r.ru_nswap);
1742         fprintf(StatFp,
1743          "!\t%ld [%ld] signals rcvd, %ld/%ld [%ld/%ld] messages rcvd/sent\n",
1744                         r.ru_nsignals - Save_r.ru_nsignals,
1745                         r.ru_nsignals,
1746                         r.ru_msgrcv - Save_r.ru_msgrcv,
1747                         r.ru_msgsnd - Save_r.ru_msgsnd,
1748                         r.ru_msgrcv, r.ru_msgsnd);
1749         fprintf(StatFp,
1750                  "!\t%ld/%ld [%ld/%ld] voluntary/involuntary context switches\n",
1751                         r.ru_nvcsw - Save_r.ru_nvcsw,
1752                         r.ru_nivcsw - Save_r.ru_nivcsw,
1753                         r.ru_nvcsw, r.ru_nivcsw);
1754 #endif   /* HAVE_GETRUSAGE */
1755         fprintf(StatFp, "! postgres usage stats:\n");
1756         PrintBufferUsage(StatFp);
1757 /*         DisplayTupleCount(StatFp); */
1758 }
1759
1760 #ifdef USE_ASSERT_CHECKING
1761 int
1762 assertEnable(int val)
1763 {
1764         assert_enabled = val;
1765         return val;
1766 }
1767
1768 #ifdef ASSERT_CHECKING_TEST
1769 int
1770 assertTest(int val)
1771 {
1772         Assert(val == 0);
1773
1774         if (assert_enabled)
1775         {
1776                 /* val != 0 should be trapped by previous Assert */
1777                 elog(NOTICE, "Assert test successfull (val = %d)", val);
1778         }
1779         else
1780                 elog(NOTICE, "Assert checking is disabled (val = %d)", val);
1781
1782         return val;
1783 }
1784
1785 #endif
1786 #endif