home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / tcop / postgres.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-01  |  39.8 KB  |  1,619 lines

  1. /* ****************************************************************
  2.  *   FILE
  3.  *    postgres.c
  4.  *    
  5.  *   DESCRIPTION
  6.  *    POSTGRES C Backend Interface
  7.  *
  8.  *   INTERFACE ROUTINES
  9.  *    
  10.  *   NOTES
  11.  *    this is the "main" module of the postgres backend and
  12.  *    hence the main module of the "traffic cop".
  13.  *
  14.  *   IDENTIFICATION
  15.  *    $Header: /users/mer/pg/src/tcop/RCS/postgres.c,v 1.150 1992/08/27 09:36:38 mer Exp $
  16.  * ****************************************************************
  17.  */
  18. #include <signal.h>
  19. #include <setjmp.h>
  20. #include <stdio.h>
  21. #include <sys/time.h>
  22.  
  23. #include "tmp/postgres.h"
  24. #include "parser/parse.h"
  25. #include "catalog/catname.h"
  26.  
  27. RcsId("$Header: /users/mer/pg/src/tcop/RCS/postgres.c,v 1.150 1992/08/27 09:36:38 mer Exp $");
  28.  
  29. /* ----------------
  30.  *    FILE INCLUDE ORDER GUIDELINES
  31.  *
  32.  *    1) tcopdebug.h
  33.  *    2) various support files ("everything else")
  34.  *    3) node files
  35.  *    4) catalog/ files
  36.  *    5) execdefs.h and execmisc.h, if necessary.
  37.  *    6) extern files come last.
  38.  * ----------------
  39.  */
  40. #include "tcop/tcopdebug.h"
  41.  
  42. #include "tcop/slaves.h"
  43. #include "parser/parsetree.h"
  44. #include "executor/execdebug.h"
  45. #include "executor/x_execstats.h"
  46. #include "nodes/relation.h"
  47. #include "planner/costsize.h"
  48. #include "planner/planner.h"
  49. #include "planner/xfunc.h"
  50. #include "nodes/plannodes.h"
  51. #include "nodes/plannodes.a.h"
  52.  
  53. #include "storage/bufmgr.h"
  54. #include "utils/fmgr.h"
  55. #include "utils/log.h"
  56. #include "utils/rel.h"
  57. #include "tmp/miscadmin.h"
  58.  
  59. #include "nodes/pg_lisp.h"
  60. #include "tcop/dest.h"
  61. #include "nodes/mnodes.h"
  62. #include "utils/mcxt.h"
  63. #include "tcop/pquery.h"
  64. #include "tcop/utility.h"
  65. #include "tcop/fastpath.h"
  66. #include "tcop/parsev.h"
  67.  
  68. #ifdef PARALLELDEBUG
  69. #include <usclkc.h>
  70. #endif
  71.  
  72. #ifdef NOFIXADE
  73. #include <sys/syscall.h>
  74. #include <sys/sysmips.h>
  75. #endif
  76.  
  77. extern int on_exitpg();
  78.  
  79. /* ----------------
  80.  *    global variables
  81.  * ----------------
  82.  */
  83. int        Warnings = 0;
  84. int        ShowTime = 0;
  85. bool        DebugPrintPlan = false;
  86. bool        DebugPrintParse = false;
  87. bool        DebugPrintRewrittenParsetree = false;
  88. static bool    EnableRewrite = true;
  89. int        ShowStats;
  90. CommandDest whereToSendOutput;
  91.  
  92. #ifdef    EBUG
  93. int        ShowLock = 0;
  94. #endif
  95.  
  96. /* User info  */
  97.  
  98. extern char    *PG_username;
  99.  
  100. /* in elog.c */
  101. bool IsEmptyQuery = false;
  102.  
  103. /* this global is defined in utils/init/postinit.c */
  104. extern int    testFlag;
  105. extern int    lockingOff;
  106. static int    confirmExecute = 0;
  107. int        ProcessAffinityOn = 0;
  108.  
  109. Relation    reldesc;        /* current relation descritor */
  110. char        relname[80];        /* current relation name */
  111. jmp_buf        Warn_restart;
  112. extern int    NBuffers;
  113. time_t        tim;
  114. bool         override = false;
  115. int        EchoQuery = 0;        /* default don't echo */
  116. char pg_pathname[256];
  117. int        MasterPid;
  118. static int    ShowParserStats;
  119. static int    ShowPlannerStats;
  120. int    ShowExecutorStats;
  121. extern FILE    *StatFp;
  122.  
  123.  
  124. /* ----------------
  125.  *    for memory leak debugging
  126.  * ----------------
  127.  */
  128. int query_tuple_count = 0;
  129. int xact_tuple_count = 0;
  130. int query_tuple_max = 0;
  131. int xact_tuple_max = 0;
  132.  
  133. /* ----------------
  134.  *    people who want to use EOF should #define DONTUSENEWLINE in
  135.  *    tcop/tcopdebug.h
  136.  * ----------------
  137.  */
  138. #ifndef TCOP_DONTUSENEWLINE
  139. int UseNewLine = 1;  /* Use newlines query delimiters (the default) */
  140. #else
  141. int UseNewLine = 0;  /* Use EOF as query delimiters */
  142. #endif TCOP_DONTUSENEWLINE
  143.  
  144. /* ----------------
  145.  *    this is now defined by the executor
  146.  * ----------------
  147.  */
  148. extern int Quiet;
  149.  
  150. /* ----------------
  151.  *    bushy tree plan flag: if true planner will generate bushy-tree
  152.  *    plans
  153.  * ----------------
  154.  */
  155. int BushyPlanFlag = 0; /* default to false -- consider only left-deep trees */
  156. ParallelismModes ParallelismMode = INTER_W_ADJ;
  157.  
  158. /*
  159. ** Flags for expensive function optimization -- JMH 3/9/92
  160. */
  161. int XfuncMode = 0;
  162.  
  163. /* ----------------------------------------------------------------
  164.  *            support functions
  165.  * ----------------------------------------------------------------
  166.  */
  167.  
  168. /* ----------------
  169.  * If we are running under the Postmaster, we cannot in general be sure that
  170.  * USER is set to the actual name of the user.  (After all, in theory there
  171.  * may be Postgres users that don't exist as Unix users on the database server
  172.  * machine.)  Therefore, the Postmaster sets the PG_USER environment variable
  173.  * so that the actual user can be determined.
  174.  * ----------------
  175.  */
  176.  
  177. void
  178. GetUserName()
  179. {
  180.     char *t;
  181.  
  182.     if (IsUnderPostmaster)
  183.     {
  184.         t = (char *) getenv("PG_USER");
  185.         if (t == NULL)
  186.             elog(FATAL, "GetUserName(): Can\'t get PG_USER environment name");
  187.         
  188.     }
  189.     else
  190.     {
  191.         t = (char *) getenv("USER");
  192.     }
  193.  
  194.     /*
  195.      * Valid Postgres username can be at most 16
  196.      * characters - leave one for null
  197.      * 
  198.      * DO NOT REMOVE THIS MALLOC - apparently some getenv's reuse space and
  199.      * this hozed on a Sparcstation.
  200.      */
  201.  
  202.     PG_username = (char *) malloc(17);
  203.     strcpy(PG_username, t);
  204. }
  205.  
  206. void
  207. get_pathname(argv)
  208.     char **argv;
  209. {
  210.     char buffer[256];
  211.  
  212.     if (argv[0][0] == '/') { /* ie, from execve in postmaster */
  213.     strcpy(pg_pathname, argv[0]);
  214.     } else {
  215.     getwd(buffer);
  216.     sprintf(pg_pathname, "%s/%s", buffer, argv[0]);
  217.     }
  218. }
  219.  
  220.  
  221. /* ----------------------------------------------------------------
  222.  *    routines to obtain user input
  223.  * ----------------------------------------------------------------
  224.  */
  225.  
  226. /* ----------------
  227.  *  InteractiveBackend() is called for user interactive connections
  228.  *  the string entered by the user is placed in its parameter inBuf.
  229.  * ----------------
  230.  */
  231.  
  232. char
  233. InteractiveBackend(inBuf)
  234.     char *inBuf;
  235. {
  236.     String stuff = inBuf;        /* current place in input buffer */
  237.     char c;                /* character read from getc() */
  238.     bool end = false;            /* end-of-input flag */
  239.     bool backslashSeen = false;        /* have we seen a \ ? */
  240.  
  241.     /* ----------------
  242.      *    display a prompt and obtain input from the user
  243.      * ----------------
  244.      */
  245.     printf("> ");
  246.     
  247.     for (;;) {
  248.     if (UseNewLine) {
  249.         /* ----------------
  250.          *    if we are using \n as a delimiter, then read
  251.          *  characters until the \n.
  252.          * ----------------
  253.          */
  254.         while ( (c = (char) getc(stdin)) != EOF) {
  255.         if (c == '\n') {
  256.             if (backslashSeen) {
  257.             stuff--;
  258.             continue;
  259.             } else {
  260.             *stuff++ = '\0';
  261.             break;
  262.             }
  263.         } else if (c == '\\')
  264.             backslashSeen = true;
  265.         else
  266.             backslashSeen = false;
  267.  
  268.         *stuff++ = c;
  269.         }
  270.         
  271.         if (c == EOF)
  272.         end = true;
  273.     } else {
  274.         /* ----------------
  275.          *    otherwise read characters until EOF.
  276.          * ----------------
  277.          */
  278.         while ( (c = (char)getc(stdin)) != EOF )
  279.         *stuff++ = c;
  280.  
  281.         if ( stuff == inBuf )
  282.         end = true;
  283.     }
  284.  
  285.     if (end) {
  286.         if (!Quiet) puts("EOF");
  287.         IsEmptyQuery = true;
  288.         exitpg(0);
  289.     }
  290.  
  291. #ifdef EXEC_DEBUGINTERACTIVE
  292.     /* ----------------
  293.      *  We have some input, now see if it's a debugging command...
  294.      * ----------------
  295.      */
  296.     {
  297.         char s[1024];
  298.     
  299.         if (sscanf(inBuf, "DEBUG %s", s) == 1) {
  300.         if (!DebugVariableProcessCommand(inBuf))
  301.             printf("DEBUG [%s] not recognised\n", inBuf);
  302.         else
  303.             stuff = inBuf;
  304.         
  305.         printf("> ");
  306.         continue;
  307.         }
  308.     }
  309. #endif EXEC_DEBUGINTERACTIVE
  310.  
  311.     /* ----------------
  312.      *  otherwise we have a user query so process it.
  313.      * ----------------
  314.      */
  315.     break;
  316.     }
  317.     
  318.     /* ----------------
  319.      *    if the query echo flag was given, print the query..
  320.      * ----------------
  321.      */
  322.     if (EchoQuery)
  323.     printf("query is: %s\n", inBuf);
  324.     
  325.     return('Q');
  326. }
  327.  
  328. /* ----------------
  329.  *  SocketBackend()    Is called for frontend-backend connections
  330.  *
  331.  *  If the input is a query (case 'Q') then the string entered by
  332.  *  the user is placed in its parameter inBuf.
  333.  *
  334.  *  If the input is a fastpath function call (case 'F') then
  335.  *  the function call is processed in HandleFunctionRequest().
  336.  *  (now called from PostgresMain())
  337.  * ----------------
  338.  */
  339.  
  340. char SocketBackend(inBuf)
  341.     char *inBuf;
  342. {
  343.     /*
  344.      * Don't use overwritable strings!
  345.      */
  346.     /* char *qtype = "?"; */
  347.     char qtype[1];
  348.     int pq_qid;
  349.  
  350.     /* ----------------
  351.      *    get input from the frontend
  352.      * ----------------
  353.      */
  354.     qtype[0] = '?';
  355.     if (pq_getnchar(qtype,0,1) == EOF) {
  356.     /* ------------
  357.      *  when front-end applications quits/dies
  358.      * ------------
  359.      */
  360.     exitpg(0);
  361.     }
  362.  
  363.     switch(*qtype) {
  364.     /* ----------------
  365.      *  'Q': user entered a query
  366.      * ----------------
  367.      */
  368.     case 'Q':
  369.     pq_qid = pq_getint(4);
  370.     pq_getstr(inBuf, MAX_PARSE_BUFFER);
  371.     return('Q');
  372.     break;
  373.  
  374.     /* ----------------
  375.      *  'F':  calling user/system functions
  376.      * ----------------
  377.      */
  378.     case 'F':    
  379.         return('F');
  380.         break;
  381.  
  382.     /* ----------------
  383.      *  'X':  frontend is exiting
  384.      * ----------------
  385.      */
  386.     case 'X':
  387.     return('X');
  388.     break;
  389.  
  390.     /* ----------------
  391.      *  otherwise we got garbage from the frontend.
  392.      *
  393.      *  XXX are we certain that we want to do an elog(FATAL) here?
  394.      *      -cim 1/24/90
  395.      * ----------------
  396.      */
  397.     default:
  398.     elog(FATAL, "Socket command type %c unknown\n", *qtype);
  399.     break;
  400.     }
  401. }
  402.  
  403. /* ----------------
  404.  *    ReadCommand reads a command from either the frontend or
  405.  *    standard input, places it in inBuf, and returns a char
  406.  *    representing whether the string is a 'Q'uery or a 'F'astpath
  407.  *    call.
  408.  * ----------------
  409.  */
  410. char ReadCommand(inBuf)
  411.     char *inBuf;
  412. {
  413.     if (IsUnderPostmaster == true)
  414.     return SocketBackend(inBuf);
  415.     else
  416.     return InteractiveBackend(inBuf);
  417. }
  418.  
  419. /* ----------------------------------------------------------------
  420.  *    pg_eval()
  421.  *    
  422.  *    Takes a querystring, runs the parser/utilities or
  423.  *    parser/planner/executor over it as necessary
  424.  *    Begin Transaction Should have been called before this
  425.  *    and CommitTransaction After this is called
  426.  *    This is strictly because we do not allow for nested xactions.
  427.  *
  428.  *    NON-OBVIOUS-RESTRICTIONS
  429.  *     this function _MUST_ allocate a new "parsetree" each time, 
  430.  *     since it may be stored in a named portal and should not 
  431.  *     change its value.
  432.  *
  433.  * ----------------------------------------------------------------
  434.  */
  435. extern int _exec_repeat_;
  436. GlobalMemory ParserPlannerContext;
  437.  
  438. List
  439. pg_plan(query_string, typev, nargs, parsetreeP, dest)
  440.     String    query_string;    /* string to execute */
  441.     ObjectId    *typev;        /* argument types */
  442.     int        nargs;        /* number of arguments */
  443.     LispValue    *parsetreeP;    /* pointer to the parse trees */
  444.     CommandDest dest;        /* where results should go */
  445. {
  446.     LispValue parsetree_list = lispList();
  447.     List plan_list = LispNil;
  448.     Plan plan;
  449.     List parsetree;
  450.     LispValue i, x;
  451.     int j;
  452.     List new_list = LispNil;
  453.     List rewritten = LispNil;
  454.     MemoryContext oldcontext;
  455.  
  456.     if (testFlag) {
  457.     ParserPlannerContext = CreateGlobalMemory("ParserPlannerContext");
  458.     oldcontext = MemoryContextSwitchTo((MemoryContext)ParserPlannerContext);
  459.       }
  460.  
  461.     /* ----------------
  462.      *    (1) parse the request string into a list of parse trees
  463.      * ----------------
  464.      */
  465.     if (ShowParserStats)
  466.     ResetUsage();
  467.     
  468.     parser(query_string, parsetree_list, typev, nargs);
  469.     
  470.     if (ShowParserStats) {
  471.     fprintf(stderr, "! Parser Stats:\n");
  472.     ShowUsage();
  473.     }
  474.     
  475.     /* ----------------
  476.      *    (2) rewrite the queries, as necessary
  477.      * ----------------
  478.      */
  479.     foreach (i, parsetree_list ) {
  480.     LispValue parsetree = CAR(i);
  481.     
  482.     extern List QueryRewrite();
  483.  
  484.     ValidateParse(parsetree);
  485.  
  486.     /* don't rewrite utilites */
  487.     if (atom(CAR(parsetree))) {
  488.         new_list = nappend1(new_list,parsetree);
  489.         continue;
  490.     }
  491.     
  492.     if ( DebugPrintParse == true ) {
  493.         printf("\ninput string is %s\n",query_string);
  494.         printf("\n---- \tparser outputs :\n");
  495.         lispDisplay(parsetree);
  496.         printf("\n");
  497.     }
  498.  
  499.         /*
  500.          * This crap is here because the notify statement 
  501.      * has to look like a query to work as a rule action.
  502.      */
  503.  
  504.      if (NOTIFY == LISPVALUE_INTEGER(CAR(CDR(CAR(parsetree))))) {
  505.        new_list = nappend1(new_list,CDR(CAR(parsetree)));
  506.        continue;
  507.      }
  508.     
  509.     /* rewrite queries (retrieve, append, delete, replace) */
  510.     if (EnableRewrite ) {
  511.         rewritten = QueryRewrite ( parsetree );
  512.         if (rewritten != LispNil) {
  513.         new_list = append(new_list, rewritten);
  514.         }
  515.         continue;
  516.     }
  517.     else  {
  518.         new_list = nappend1(new_list, parsetree);
  519.     }
  520.  
  521.     }
  522.  
  523.     parsetree_list = new_list;
  524.  
  525.     /* ----------------
  526.      * Fix time range quals
  527.      * this _must_ go here, because it must take place after rewrites
  528.      * ( if they take place ) so that time quals are usable by the executor
  529.      *
  530.      * Also, need to frob the range table entries here to plan union
  531.      * queries for archived relations.
  532.      * ----------------
  533.      */
  534.     foreach ( i , parsetree_list ) {
  535.     List parsetree = CAR(i);
  536.     List l;
  537.     List rt = NULL;
  538.     extern List MakeTimeRange();
  539.     
  540.     /* ----------------
  541.      *  utilities don't have time ranges
  542.      * ----------------
  543.      */
  544.     if (atom(CAR(parsetree))) 
  545.         continue;
  546.  
  547.     rt = root_rangetable(parse_root(parsetree));
  548.  
  549.     foreach (l, rt) {
  550.         List timequal = rt_time(CAR(l));
  551.         if ( timequal && consp(timequal) )
  552.         rt_time(CAR(l)) = MakeTimeRange(CAR(timequal),
  553.                         CADR(timequal),
  554.                         CInteger(CADDR(timequal)));
  555.     }
  556.  
  557.     /* check for archived relations */
  558.     plan_archive(rt);
  559.     }
  560.     
  561.     if (DebugPrintRewrittenParsetree == true) {
  562.     List i;
  563.     printf("\n=================\n");
  564.     printf("  After Rewriting\n");
  565.     printf("=================\n");
  566.     lispDisplay(parsetree_list); /* takes one arg, not two */
  567.     }
  568.  
  569.     /* ----------------
  570.      *    (3) for each parse tree, plan the query or process
  571.      *      the utility request.
  572.      *      we now plan all the queries in parsetree_list
  573.      *      and get plan_list.  this gives you the possibility
  574.      *      of inter-query parallelism.
  575.      * ----------------
  576.      */
  577.         
  578.     foreach(i, parsetree_list) {
  579.     int       which_util;
  580.     LispValue parsetree = CAR(i);
  581.  
  582.     /*
  583.      *  For each query that isn't a utility invocation,
  584.      *  generate a plan.
  585.      */
  586.  
  587.     if (!atom(CAR(parsetree))) {
  588.  
  589.         if (IsAbortedTransactionBlockState()) {
  590.         /* ----------------
  591.          *   the EndCommand() stuff is to tell the frontend
  592.          *   that the command ended. -cim 6/1/90
  593.          * ----------------
  594.          */
  595.         char *tag = "*ABORT STATE*";
  596.         EndCommand(tag, dest);
  597.         
  598.         elog(NOTICE, "(transaction aborted): %s",
  599.              "queries ignored until END");
  600.         
  601.         *parsetreeP = (List)NULL;
  602.         return (List)NULL;
  603.         }
  604.  
  605.         if (! Quiet)
  606.         puts("\tinit_planner()..");
  607.  
  608.         init_planner();
  609.         
  610.         if (ShowPlannerStats) ResetUsage();
  611.         plan = planner(parsetree);
  612.         if (ShowPlannerStats) {
  613.         fprintf(stderr, "! Planner Stats:\n");
  614.         ShowUsage();
  615.         }
  616.         plan_list = nappend1(plan_list, (LispValue)plan);
  617.     }
  618.     }
  619.  
  620.     if (testFlag)
  621.        MemoryContextSwitchTo(oldcontext);
  622.  
  623.     if (parsetreeP != (LispValue *) NULL)
  624.     *parsetreeP = parsetree_list;
  625.  
  626.     return (plan_list);
  627. }
  628.  
  629. void
  630. pg_eval(query_string, argv, typev, nargs)
  631.     String query_string;
  632.     char *argv;
  633.     ObjectId *typev;
  634.     int nargs;
  635. {
  636.     extern CommandDest whereToSendOutput;
  637.     extern void pg_eval_dest();
  638.  
  639.     pg_eval_dest(query_string, argv, typev, nargs, whereToSendOutput);
  640. }
  641.  
  642. void
  643. pg_eval_dest(query_string, argv, typev, nargs, dest)
  644.     String    query_string;    /* string to execute */
  645.     char    *argv;        /* arguments */
  646.     ObjectId    *typev;        /* argument types */
  647.     int        nargs;        /* number of arguments */
  648.     CommandDest dest;        /* where results should go */
  649. {
  650.     LispValue parsetree_list;
  651.     List plan_list;
  652.     Plan plan;
  653.     List parsetree;
  654.     int j;
  655.     int which_util;
  656.  
  657.     /* plan the queries */
  658.     plan_list = pg_plan(query_string, typev, nargs, &parsetree_list, dest);
  659.  
  660.     if (ParallelExecutorEnabled()) {
  661.  
  662.     /*
  663.      *  XXX:  ParallelProcessQueries needs to be rewritten to handle
  664.      *  utility invocations.  Until then, THIS IS BROKEN!!!
  665.      */
  666.  
  667.     elog(WARN, "hey wei, you need to talk to mao.");
  668.  
  669.     /* -----------------
  670.      *  execute the plans in plan_list in parallel
  671.      * -----------------
  672.      */
  673.     if (ShowExecutorStats)
  674.         ResetUsage();
  675.     ParallelProcessQueries(parsetree_list, plan_list, dest);
  676.     if (ShowExecutorStats) {
  677.         fprintf(stderr, "! Executor Stats:\n");
  678.         ShowUsage();
  679.     }
  680.     return;
  681.     }
  682.  
  683.     /* ------------------
  684.      *  parallel executor is not enabled, execute the plans in plan_list
  685.      *  one after another
  686.      * ------------------
  687.      */
  688.  
  689.     while (parsetree_list != LispNil) {
  690.     parsetree = CAR(parsetree_list);
  691.     parsetree_list = CDR(parsetree_list);
  692.  
  693.     if (atom(CAR(parsetree))) {
  694.         /* ----------------
  695.          *   process utility functions (create, destroy, etc..)
  696.          *
  697.          *   Note: we do not check for the transaction aborted state
  698.          *   because that is done in ProcessUtility.
  699.          * ----------------
  700.          */
  701.         if (! Quiet) {
  702.         time(&tim);
  703.         printf("\tProcessUtility() at %s\n", ctime(&tim));
  704.         }
  705.         
  706.         which_util = LISPVALUE_INTEGER(CAR(parsetree));
  707.         ProcessUtility(which_util, CDR(parsetree), query_string, dest);
  708.  
  709.         /*
  710.          *  XXX -- ugly hack:  vacuum spans transactions (it calls
  711.          *  Commit and Start itself), and so if this was a vacuum
  712.          *  command, all the memory we were using is gone.  the right
  713.          *  thing to do is to allocate the parse tree in a distinguished
  714.          *  memory context.  until i get around to doing that, just
  715.          *  bounce out of here after vacuuming.  --mao 4 may 91
  716.          */
  717.  
  718.         if (which_util == VACUUM)
  719.         return;
  720.     } else {
  721.         plan = (Plan) CAR(plan_list);
  722.         plan_list = CDR(plan_list);
  723.  
  724.         /* ----------------
  725.          *    print plan if debugging
  726.          * ----------------
  727.          */
  728.         if ( DebugPrintPlan == true ) {
  729.         printf("\nPlan is :\n");
  730.         lispDisplay((LispValue)plan);
  731.         printf("\n");
  732.         }
  733.  
  734.         if (testFlag && IsA(plan,Choose)) {
  735.         /* ----------------
  736.          *     this is my experiment stuff, will be taken away soon.
  737.          *   ignore it. -- Wei
  738.          * ----------------
  739.          */
  740.         Plan       p;
  741.         List       planlist;
  742.         LispValue x;
  743.         List       setRealPlanStats();
  744.         List       pruneHashJoinPlans();
  745.  
  746.         planlist = get_chooseplanlist((Choose)plan);
  747.         planlist = setRealPlanStats(parsetree, planlist);
  748.         planlist = pruneHashJoinPlans(planlist);
  749.         
  750.         foreach (x, planlist) {
  751.             char s[10];
  752.             p = (Plan) CAR(x);
  753.             p_plan(p);
  754.             if (confirmExecute) {
  755.             printf("execute (y/n/q)? ");
  756.             scanf("%s", s);
  757.             if (s[0] == 'n') continue;
  758.             if (s[0] == 'q') break;
  759.             }
  760.             BufferPoolBlowaway();
  761.             
  762.             CommitTransactionCommand();
  763.             StartTransactionCommand();
  764.             
  765.             ResetUsage();
  766.             ProcessQuery(parsetree, p, argv, typev, nargs, dest);
  767.             ShowUsage();
  768.         }
  769.          GlobalMemoryDestroy(ParserPlannerContext);
  770.         } else {
  771.         /* ----------------
  772.          *   execute the plan
  773.          *
  774.          *   Note: _exec_repeat_ defaults to 1 but may be changed
  775.          *       by a DEBUG command.   If you set this to a large
  776.          *       number N, run a single query, and then set it
  777.          *       back to 1 and run N queries, you can get an idea
  778.          *       of how much time is being spent in the parser and
  779.          *       planner b/c in the first case this overhead only
  780.          *       happens once.  -cim 6/9/91
  781.          * ----------------
  782.          */
  783.         if (ShowExecutorStats)
  784.             ResetUsage();
  785.         
  786.         for (j = 0; j < _exec_repeat_; j++) {
  787.             if (! Quiet) {
  788.             time(&tim);
  789.             printf("\tProcessQuery() at %s\n", ctime(&tim));
  790.             }
  791.             ProcessQuery(parsetree, plan, argv, typev, nargs, dest);
  792.         }
  793.         
  794.         if (ShowExecutorStats) {
  795.             fprintf(stderr, "! Executor Stats:\n");
  796.             ShowUsage();
  797.         }
  798.         }
  799.     }
  800.     /*
  801.      *  In a query block, we want to increment the command counter
  802.      *  between queries so that the effects of early queries are
  803.      *  visible to subsequent ones.
  804.      */
  805.  
  806.     if (parsetree_list != LispNil)
  807.          CommandCounterIncrement();
  808.     }
  809. }
  810.     
  811. /* ----------------------------------------------------------------
  812.  *            postgres main loop
  813.  * ----------------------------------------------------------------
  814.  */
  815.  
  816. /* --------------------------------
  817.  *    signal handler routines used in PostgresMain()
  818.  *
  819.  *    handle_warn() is used to catch kill(getpid(),1) which
  820.  *    occurs when elog(WARN) is called.
  821.  *
  822.  *      quickdie() occurs when signalled by the postmaster, some backend
  823.  *      has bought the farm we need to stop what we're doing and exit.
  824.  *
  825.  *    die() preforms an orderly cleanup via ExitPostgres()
  826.  * --------------------------------
  827.  */
  828.  
  829. void
  830. handle_warn()
  831. {
  832.     longjmp(Warn_restart,1);
  833. }
  834.  
  835. void
  836. quickdie()
  837. {
  838.   elog(NOTICE, "I have been signalled by the postmaster.");
  839.   elog(NOTICE, "Some backend process has died unexpectedly and possibly");
  840.   elog(NOTICE, "corrupted shared memory.  The current transaction was");
  841.   elog(NOTICE, "aborted, and I am going to exit.  Please resend the");
  842.   elog(NOTICE, "last query. -- The postgres backend");
  843.   ExitPostgres(0);
  844. }
  845.  
  846. void
  847. die()
  848. {
  849.     ExitPostgres(0);
  850. }
  851.  
  852. /* --------------------------------
  853.  *    PostgresMain
  854.  * --------------------------------
  855.  */
  856.  
  857. PostgresMain(argc, argv)
  858.     int    argc;
  859.     char    *argv[];
  860. {
  861.     register     int    i;
  862.     int            flagC;
  863.     int            flagQ;
  864.     int            flagM;
  865.     int            flagS;
  866.     int            flagE;
  867.     int            flag;
  868.  
  869.     int            numslaves;
  870.     int            errs = 0;
  871.     char        *DatabaseName;
  872.  
  873.     char        firstchar;
  874.     char        parser_input[MAX_PARSE_BUFFER];
  875.     
  876.     extern    int    Noversion;        /* util/version.c */
  877.     extern    int    Quiet;
  878.     extern    jmp_buf    Warn_restart;
  879.     extern    int    optind;
  880.     extern    char    *optarg;
  881.     extern      char    *DBName; /* a global name for current database */
  882.     extern    short    DebugLvl;
  883.  
  884. #ifdef NOFIXADE
  885.     /* under ultrix, disable unaligned address fixups */
  886.     syscall(SYS_sysmips, MIPS_FIXADE, 0, NULL, NULL, NULL);
  887. #endif
  888.  
  889.     /* ----------------
  890.      *     register signal handlers.
  891.      * ----------------
  892.      */
  893.     signal(SIGHUP, die);
  894.     signal(SIGINT, die);
  895.     signal(SIGTERM, die);
  896.     signal(SIGUSR1, quickdie);
  897.     /*
  898.      * Turn of async portals for 4.0.1
  899.      */
  900. #if 0
  901.     {                /* asynchronous notification */
  902.     extern void Async_NotifyFrontEnd();
  903.     signal(SIGUSR2, Async_NotifyFrontEnd);
  904.     }
  905. #endif
  906.  
  907. #ifdef PARALLELDEBUG
  908.     usclk_init();
  909. #endif
  910. #ifdef sequent
  911.     /* -------------------
  912.      * increase the maximum number of file descriptors on sequent
  913.      * the default is only 20.
  914.      * the following call may not guarantee to give you 256 file descriptors
  915.      * usually you only get 64.
  916.      * ------------------
  917.      */
  918.     setdtablesize(256);
  919. #endif
  920.  
  921.     /* ----------------
  922.      *    initialize palloc memory tracing
  923.      * ----------------
  924.      */
  925.     set_palloc_debug(false, false);
  926.     
  927.     /* ----------------
  928.      *    parse command line arguments
  929.      * ----------------
  930.      */
  931.     numslaves = 0;
  932.     flagC = flagQ = flagM = flagS = flagE = ShowStats = 0;
  933.     ShowParserStats = ShowPlannerStats = ShowExecutorStats = 0;
  934.     MasterPid = getpid();
  935.     
  936.     while ((flag = getopt(argc, argv, "aA:B:bCd:EGM:NnOP:pQSsLit:Tf:F:x:")) != EOF)
  937.       switch (flag) {
  938.             
  939.       case 'A':
  940.       /* ----------------
  941.        *    tell postgres to turn on memory tracing
  942.        *
  943.        *    -An = print alloctions/deallocations when they occur
  944.        *    -Ar = record activity silently in a list
  945.        *    -Ab = record and print activity
  946.        *    -AQ# = dump activity list every # tuples processed (per query)
  947.        *    -AX# = dump activity list every # transactions processed
  948.        * ----------------
  949.        */
  950.       switch (optarg[0]) {
  951.       case 'n':  set_palloc_debug(true, false);  break;
  952.       case 'r':  set_palloc_debug(false, true);  break;
  953.       case 'b':  set_palloc_debug(true, true);   break;
  954.       case 'Q':  set_palloc_debug(false, true);
  955.              query_tuple_max = atoi(&optarg[1]); break;
  956.       case 'X':  set_palloc_debug(false, true);
  957.              xact_tuple_max = atoi(&optarg[1]); break;
  958.       default:   errs++; break;
  959.       } 
  960.       break;
  961.       
  962.       case 'b':
  963.       /* ----------------
  964.        *    set BushyPlanFlag to true.
  965.        * ----------------
  966.        */
  967.       BushyPlanFlag = 1;
  968.       break;
  969.       case 'B':
  970.       /* ----------------
  971.        *    specify the size of buffer pool
  972.        * ----------------
  973.        */
  974.       NBuffers = atoi(optarg);
  975.       break;
  976.       
  977.       case 'C':
  978.       /* ----------------
  979.        *    I don't know what this does -cim 5/12/90
  980.        * ----------------
  981.        */
  982.       flagC = 1;
  983.       break;
  984.       
  985.       /* ----------------
  986.        *    -debug mode
  987.        * ----------------
  988.        */
  989.       case 'd':
  990.       /* DebugMode = true;  */
  991.       flagQ = 0;
  992.       DebugPrintPlan = true;
  993.       DebugPrintParse = true;
  994.       DebugPrintRewrittenParsetree = true;
  995.       DebugLvl = (short)atoi(optarg);
  996.       break;
  997.       
  998.       case 'E':
  999.       /* ----------------
  1000.        *    E - echo the query the user entered
  1001.        * ----------------
  1002.        */
  1003.       flagE = 1;
  1004.       break;
  1005.             
  1006.       case 'G':
  1007.       /* ----------------
  1008.        *    G - use cacheoffgetattr instead of fastgetattr
  1009.        * ----------------
  1010.        */
  1011.       set_use_cacheoffgetattr(1);
  1012.       break;
  1013.             
  1014.       case 'M':
  1015.       /* ----------------
  1016.        *    M # - process queries in parallel.  The system
  1017.        *          will initially fork several slave backends
  1018.        *          and the initial backend will plan parallel
  1019.        *          queries and pass them to the slaves. -cim 5/12/90
  1020.        * ----------------
  1021.        */
  1022.       numslaves = atoi(optarg);
  1023.       if (numslaves > 0) {
  1024.           SetParallelExecutorEnabled(true);
  1025.           SetNumberSlaveBackends(numslaves);
  1026.       } else
  1027.           errs += 1;
  1028.       flagM = 1;
  1029.       _enable_mergesort_ = 0;  /* don't support parallel mergesort yet */
  1030.       break;
  1031.       
  1032.       case 'n':
  1033.       /* ----------------
  1034.        *    does nothing - obsolete this! -cim 2/10/91
  1035.        * ----------------
  1036.        */
  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.        *    O - override transaction system.  This used
  1050.        *        to be used to set the AMI_OVERRIDE flag for
  1051.        *        creation of initial system relations at
  1052.        *        bootstrap time.  I think MikeH changed its
  1053.        *        meaning and am not sure it works now.. -cim 5/12/90
  1054.        * ----------------
  1055.        */
  1056.       override = true;
  1057.       break;
  1058.       
  1059.       case 'p':    /* started by postmaster */
  1060.       /* ----------------
  1061.        *    p - special flag passed if backend was forked
  1062.        *        by a postmaster.
  1063.        * ----------------
  1064.        */
  1065.       IsUnderPostmaster = true;
  1066.       break;
  1067.       
  1068.       case 'P':
  1069.       /* ----------------
  1070.        *    P - Use the passed file descriptor number as the port
  1071.        *    on which to communicate with the user.  This is ONLY
  1072.        *    useful for debugging when fired up by the postmaster.
  1073.        * ----------------
  1074.        */
  1075.           Portfd = atoi(optarg);
  1076.       break;
  1077.       
  1078.       case 'Q':
  1079.       /* ----------------
  1080.        *    Q - set Quiet mode (reduce debugging output)
  1081.        * ----------------
  1082.        */
  1083.       flagQ = 1;
  1084.       break;
  1085.  
  1086.       case 'S':
  1087.       /* ----------------
  1088.        *    S - assume stable main memory
  1089.        *        (don't flush all pages at end transaction)
  1090.        * ----------------
  1091.        */
  1092.       flagS = 1;
  1093.       SetTransactionFlushEnabled(false);
  1094.       break;
  1095.       
  1096.       case 's':
  1097.           /* ----------------
  1098.            *    s - report usage statistics (timings) after each query
  1099.            * ----------------
  1100.            */
  1101.           ShowStats = 1;
  1102.       StatFp = stderr;
  1103.           break;
  1104.  
  1105.       case 't':
  1106.       /* ----------------
  1107.        *    tell postgres to report usage statistics (timings) for
  1108.        *    each query
  1109.        *
  1110.        *    -tpa[rser] = print stats for parser time of each query
  1111.        *    -tpl[anner] = print stats for planner time of each query
  1112.        *    -te[xecutor] = print stats for executor time of each query
  1113.        *    caution: -s can not be used together with -t.
  1114.        * ----------------
  1115.        */
  1116.       StatFp = stderr;
  1117.       switch (optarg[0]) {
  1118.       case 'p':  if (optarg[1] == 'a')
  1119.             ShowParserStats = 1;
  1120.              else if (optarg[1] == 'l')
  1121.             ShowPlannerStats = 1;
  1122.              else
  1123.             errs++;
  1124.              break;
  1125.       case 'e':  ShowExecutorStats = 1;   break;
  1126.       default:   errs++; break;
  1127.       } 
  1128.       break;
  1129.       
  1130.       case 'T':
  1131.           /* ----------------
  1132.            *    T - Testing mode: execute all the possible plans instead
  1133.            *    of just the optimal one
  1134.        *
  1135.        *    XXX not implemented yet,  currently it will just print
  1136.        *    the statistics of the executor, like the -s option
  1137.        *    but does not include parsing and planning time.
  1138.            * ---------------
  1139.            */
  1140.           testFlag = 1;
  1141.           break;
  1142.       
  1143.       case 'f':
  1144.           /* -----------------
  1145.            *    f - forbid generation of certain plans
  1146.            * -----------------
  1147.            */
  1148.           switch (optarg[0]) {
  1149.           case 's': /* seqscan */
  1150.                 _enable_seqscan_ = false;
  1151.                 break;
  1152.           case 'i': /* indexscan */
  1153.                 _enable_indexscan_ = false;
  1154.                 break;
  1155.           case 'n': /* nestloop */
  1156.                 _enable_nestloop_ = false;
  1157.                 break;
  1158.           case 'm': /* mergejoin */
  1159.                 _enable_mergesort_ = false;
  1160.                 break;
  1161.           case 'h': /* hashjoin */
  1162.                 _enable_hashjoin_ = false;
  1163.                 break;
  1164.           default:
  1165.                 errs++;
  1166.           }
  1167.       break;
  1168.  
  1169.        case 'L':
  1170.       /* --------------------
  1171.        *  turn off locking
  1172.        * --------------------
  1173.        */
  1174.       lockingOff = 1;
  1175.       break;
  1176.  
  1177.       case 'i':
  1178.       confirmExecute = 1;
  1179.       break;
  1180.       case 'a':
  1181.       /* ----------------
  1182.        *    turn on process affinity: bind processes to processors
  1183.        *    this is a sequent-specific option
  1184.        * ----------------
  1185.        */
  1186. #ifdef sequent
  1187.           ProcessAffinityOn = 1;
  1188. #else
  1189.           fprintf(stderr, "-a is a sequent-specific flag.\n");
  1190.           errs++;
  1191. #endif
  1192.           break;
  1193.       case 'F':
  1194.       if (strcmp(optarg, "intra_only") == 0)
  1195.           ParallelismMode = INTRA_ONLY;
  1196.       else if (strcmp(optarg, "inter_w_adj") == 0)
  1197.           ParallelismMode = INTER_W_ADJ;
  1198.       else if (strcmp(optarg, "inter_wo_adj") == 0)
  1199.           ParallelismMode = INTER_WO_ADJ;
  1200.       else {
  1201.           fprintf(stderr, "use -F {intra_only,inter_w_adj,inter_wo_adj}\n");
  1202.           errs++;
  1203.         }
  1204.       break;
  1205.       case 'x':
  1206.       if (strcmp(optarg, "off") == 0)
  1207.         XfuncMode = XFUNC_OFF;
  1208.       else if (strcmp(optarg, "nor") == 0)
  1209.         XfuncMode = XFUNC_NOR;
  1210.       else if (strcmp(optarg, "nopull") == 0)
  1211.         XfuncMode = XFUNC_NOPULL;
  1212.       else
  1213.        {
  1214.            fprintf(stderr, "use -x {off,nor,nopull}\n");
  1215.            errs++;
  1216.        }
  1217.       break;
  1218.       default:
  1219.       /* ----------------
  1220.        *    default: bad command line option
  1221.        * ----------------
  1222.        */
  1223.       errs++;
  1224.       }
  1225.  
  1226.       if (ShowStats && 
  1227.       (ShowParserStats || ShowPlannerStats || ShowExecutorStats)) {
  1228.       fprintf(stderr, "-s can not be used together with -t.\n");
  1229.       exitpg(1);
  1230.     }
  1231.     /* ----------------
  1232.      *    get user name and pathname and check command line validity
  1233.      * ----------------
  1234.      */
  1235.     GetUserName();
  1236.     get_pathname(argv);
  1237.  
  1238.     if (errs || argc - optind > 1) {
  1239.     fputs("Usage: postgres [-C] [-M #] [-O] [-Q] [-N] [datname]\n",stderr);
  1240.     fputs("    -C   =  ??? \n", stderr);
  1241.     fputs(" -M # =  Enable Parallel Query Execution\n", stderr);
  1242.     fputs("          (# is number of slave backends)\n", stderr);
  1243.     fputs(" -B # =  Set Buffer Pool Size\n", stderr);
  1244.     fputs("          (# is number of buffer pages)\n", stderr);
  1245.     fputs(" -O   =  Override Transaction System\n", stderr);
  1246.     fputs(" -S   =  assume Stable Main Memory\n", stderr);
  1247.     fputs(" -Q   =  Quiet mode (less debugging output)\n", stderr);
  1248.     fputs(" -N   =  use ^D as query delimiter\n", stderr);
  1249.     fputs(" -E   =  echo the query entered\n", stderr);
  1250.     exitpg(1);
  1251.     } else if (argc - optind == 1) {
  1252.     DBName = DatabaseName = argv[optind];
  1253.     } else if ((DBName = DatabaseName = PG_username) == NULL) {
  1254.     fputs("amiint: failed getenv(\"USER\") and no database specified\n",
  1255.           stderr);
  1256.     exitpg(1);
  1257.     }
  1258.  
  1259.     Noversion = flagC;
  1260.     Quiet = flagQ;
  1261.     EchoQuery = flagE;
  1262.     
  1263.     /* ----------------
  1264.      *     print flags
  1265.      * ----------------
  1266.      */
  1267.     if (! Quiet) {
  1268.     puts("\t---debug info---");
  1269.     printf("\tQuiet =        %c\n", Quiet       ? 't' : 'f');
  1270.     printf("\tNoversion =    %c\n", Noversion ? 't' : 'f');
  1271.     printf("\toverride  =    %c\n", override  ? 't' : 'f');
  1272.     printf("\tstable    =    %c\n", flagS     ? 't' : 'f');
  1273.     printf("\tparallel  =    %c\n", flagM     ? 't' : 'f');
  1274.     printf("\ttimings   =    %c\n", ShowStats ? 't' : 'f');
  1275.     printf("\tbufsize   =    %d\n", NBuffers);
  1276.     if (flagM)
  1277.         printf("\t# slaves  =    %d\n", numslaves);
  1278.     
  1279.     printf("\tquery echo =   %c\n", EchoQuery ? 't' : 'f');
  1280.     printf("\tDatabaseName = [%s]\n", DatabaseName);
  1281.     puts("\t----------------\n");
  1282.     }
  1283.     
  1284.     if (! Quiet && ! override)
  1285.     puts("\t**** Transaction System Active ****");
  1286.     
  1287.     /* ----------------
  1288.      *    initialize portal file descriptors
  1289.      * ----------------
  1290.      */
  1291.     if (IsUnderPostmaster == true) {
  1292.     if (Portfd < 0) {
  1293.         fprintf(stderr,
  1294.             "Postmaster flag set, but no port number specified\n");
  1295.         exitpg(1);
  1296.     }
  1297.     pq_init(Portfd);
  1298.     }
  1299.     
  1300.     if (IsUnderPostmaster)
  1301.     {
  1302.     whereToSendOutput = Remote;
  1303.     }
  1304.     else 
  1305.     {
  1306.     whereToSendOutput = Debug;
  1307.     }
  1308.  
  1309.     /* ----------------
  1310.      *    set processing mode appropriately depending on weather or
  1311.      *  not we want the transaction system running.  When the
  1312.      *  transaction system is not running, all transactions are
  1313.      *  assumed to have successfully committed and we never go to
  1314.      *  the transaction log.
  1315.      * ----------------
  1316.      */
  1317.     /* XXX the -C version flag should be removed and combined with -O */
  1318.     SetProcessingMode((override) ? BootstrapProcessing : InitProcessing);
  1319.     
  1320.     /* ----------------
  1321.      *    InitPostgres()
  1322.      * ----------------
  1323.      */
  1324.     if (! Quiet)
  1325.     puts("\tInitPostgres()..");
  1326.     InitPostgres(DatabaseName);
  1327.  
  1328.     /* ----------------
  1329.      *  Initialize the Master/Slave shared memory allocator,
  1330.      *    fork and initialize the parallel slave backends, and
  1331.      *  register the Master semaphore/shared memory cleanup
  1332.      *  procedures.
  1333.      * ----------------
  1334.      */
  1335.     if (ParallelExecutorEnabled()) {
  1336.     extern void IPCPrivateSemaphoreKill();
  1337.     extern void IPCPrivateMemoryKill();
  1338.     
  1339.     if (! Quiet)
  1340.         puts("\tInitializing Slave Backends...");
  1341.     SlaveBackendsInit();
  1342.  
  1343.     if (! Quiet)
  1344.         puts("\tRegistering Master IPC Cleanup Procedures...");
  1345.     ExecSemaphoreOnExit(IPCPrivateSemaphoreKill);
  1346.     ExecSharedMemoryOnExit(IPCPrivateMemoryKill);
  1347.     }
  1348.     
  1349.     /* ----------------
  1350.      *    if an exception is encountered, processing resumes here
  1351.      *  so we abort the current transaction and start a new one.
  1352.      *  This must be done after we initialize the slave backends
  1353.      *  so that the slaves signal the master to abort the transaction
  1354.      *  rather than calling AbortCurrentTransaction() themselves.
  1355.      *
  1356.      *  Note:  elog(WARN) causes a kill(getpid(),1) to occur sending
  1357.      *         us back here.
  1358.      * ----------------
  1359.      */
  1360. #ifdef linux
  1361.     {
  1362.     struct sigaction action;
  1363.     action.sa_handler = (void *) handle_warn;
  1364.     sigemptyset(&action.sa_mask);
  1365.     action.sa_flags = SA_NOMASK;
  1366.     sigaction(SIGHUP, &action, 0);
  1367.     }
  1368. #else
  1369.     signal(SIGHUP, handle_warn);
  1370. #endif
  1371.     
  1372.     if (setjmp(Warn_restart) != 0) {
  1373.     Warnings++;
  1374.     time(&tim);
  1375.     
  1376.     if (ParallelExecutorEnabled()) {
  1377.         if (! Quiet)
  1378.         printf("\tSlaveBackendsAbort() at %s\n", ctime(&tim));
  1379.  
  1380.         SlaveBackendsAbort();
  1381.     } else {
  1382.         if (! Quiet)
  1383.         printf("\tAbortCurrentTransaction() at %s\n", ctime(&tim));
  1384.  
  1385.         for ( i = 0 ; i < MAX_PARSE_BUFFER ; i++ ) 
  1386.           parser_input[i] = 0;
  1387.  
  1388.         AbortCurrentTransaction();
  1389.     }
  1390.     }
  1391.     
  1392.     /* ----------------
  1393.      *    POSTGRES main processing loop begins here
  1394.      * ----------------
  1395.      */
  1396.     if (IsUnderPostmaster == false) {
  1397.     puts("\nPOSTGRES backend interactive interface");
  1398.     puts("$Revision: 1.150 $ $Date: 1992/08/27 09:36:38 $");
  1399.     }
  1400.  
  1401.     /* ----------------
  1402.      * if stable main memory is assumed (-S flag is set), it is necessary
  1403.      * to flush all dirty shared buffers before exit
  1404.      * plai 8/7/90
  1405.      * ----------------
  1406.      */
  1407.     if (!TransactionFlushEnabled())
  1408.         on_exitpg(FlushBufferPool, (caddr_t) 0);
  1409.  
  1410.     for (;;) {
  1411.     /* ----------------
  1412.      *   (1) read a command. 
  1413.      * ----------------
  1414.      */
  1415.     for (i=0; i< MAX_PARSE_BUFFER; i++) 
  1416.         parser_input[i] = 0;
  1417.  
  1418.     firstchar = ReadCommand(parser_input);
  1419.  
  1420.     /* process the command */
  1421.     switch (firstchar) {
  1422.         /* ----------------
  1423.          *    'F' incicates a fastpath call.
  1424.          *      XXX HandleFunctionRequest
  1425.          * ----------------
  1426.          */
  1427.     case 'F':
  1428.         IsEmptyQuery = false;
  1429.  
  1430.         /* start an xact for this funciton invocation */
  1431.         if (! Quiet) {
  1432.         time(&tim);
  1433.         printf("\tStartTransactionCommand() at %s\n", ctime(&tim));
  1434.         }
  1435.  
  1436.         StartTransactionCommand();
  1437.         HandleFunctionRequest();
  1438.         break;
  1439.         
  1440.         /* ----------------
  1441.          *    'Q' indicates a user query
  1442.          * ----------------
  1443.          */
  1444.     case 'Q':
  1445.         fflush(stdout);
  1446.  
  1447.         if ( parser_input[0] ==  ' ' && parser_input[1] == '\0' ) {
  1448.         /* ----------------
  1449.          *  if there is nothing in the input buffer, don't bother
  1450.          *  trying to parse and execute anything..
  1451.          * ----------------
  1452.          */
  1453.         IsEmptyQuery = true;
  1454.         } else {
  1455.         /* ----------------
  1456.          *  otherwise, process the input string.
  1457.          * ----------------
  1458.          */
  1459.             IsEmptyQuery = false;
  1460.         if (ShowStats)
  1461.             ResetUsage();
  1462.  
  1463.         /* start an xact for this query */
  1464.         if (! Quiet) {
  1465.             time(&tim);
  1466.             printf("\tStartTransactionCommand() at %s\n", ctime(&tim));
  1467.         }
  1468.         StartTransactionCommand();
  1469.  
  1470.         pg_eval(parser_input, (char *) NULL, (ObjectId *) NULL, 0);
  1471.  
  1472.         if (ShowStats)
  1473.             ShowUsage();
  1474.         }
  1475.         break;
  1476.         
  1477.     /* ----------------
  1478.      *    'X' means that the frontend is closing down the socket
  1479.      * ----------------
  1480.      */
  1481.     case 'X':
  1482.         IsEmptyQuery = true;
  1483.         pq_close();
  1484.         break;
  1485.  
  1486.     default:
  1487.         elog(WARN,"unknown frontend message was recieved");
  1488.     }
  1489.  
  1490.     /* ----------------
  1491.      *   (3) commit the current transaction
  1492.      *
  1493.      *   Note: if we had an empty input buffer, then we didn't
  1494.      *   call pg_eval, so we don't bother to commit this transaction.
  1495.      * ----------------
  1496.      */
  1497.     if (! IsEmptyQuery) {
  1498.         if (! Quiet) {
  1499.         time(&tim);
  1500.         printf("\tCommitTransactionCommand() at %s\n", ctime(&tim));
  1501.         }
  1502.         CommitTransactionCommand();
  1503.  
  1504. #ifdef PALLOC_DEBUG    
  1505.         /* ----------------
  1506.          *    if debugging memory allocations, print memory dump
  1507.          *    every so often
  1508.          * ----------------
  1509.          */
  1510.         if (xact_tuple_max && xact_tuple_max == ++xact_tuple_count) {
  1511.         xact_tuple_count = 0;
  1512.         dump_palloc_list("PostgresMain", true);
  1513.         }
  1514. #endif PALLOC_DEBUG
  1515.     
  1516.     } else {
  1517.         if (IsUnderPostmaster)
  1518.         NullCommand(Remote);
  1519.     }
  1520.  
  1521.     }
  1522. }
  1523.  
  1524. #include <sys/resource.h>
  1525.  
  1526. struct rusage Save_r;
  1527. struct timeval Save_t;
  1528.  
  1529. ResetUsage()
  1530. {
  1531.         struct timezone tz;
  1532.     getrusage(RUSAGE_SELF, &Save_r);
  1533.         gettimeofday(&Save_t, &tz);
  1534.     ResetBufferUsage();
  1535.     ResetTupleCount();
  1536. #ifdef PARALLELDEBUG
  1537.         ResetParallelDebugInfo();
  1538. #endif
  1539. }
  1540.  
  1541. ShowUsage()
  1542. {
  1543.     struct rusage r;
  1544.     struct timeval user, sys;
  1545.         struct timeval elapse_t;
  1546.         struct timezone tz;
  1547.  
  1548.     getrusage(RUSAGE_SELF, &r);
  1549.     gettimeofday(&elapse_t, &tz);
  1550.     bcopy(&r.ru_utime, &user, sizeof(user));
  1551.     bcopy(&r.ru_stime, &sys, sizeof(sys));
  1552.         if (elapse_t.tv_usec < Save_t.tv_usec) {
  1553.                 elapse_t.tv_sec--;
  1554.                 elapse_t.tv_usec += 1000000;
  1555.         }
  1556.     if (r.ru_utime.tv_usec < Save_r.ru_utime.tv_usec) {
  1557.         r.ru_utime.tv_sec--;
  1558.         r.ru_utime.tv_usec += 1000000;
  1559.     }
  1560.     if (r.ru_stime.tv_usec < Save_r.ru_stime.tv_usec) {
  1561.         r.ru_stime.tv_sec--;
  1562.         r.ru_stime.tv_usec += 1000000;
  1563.     }
  1564.  
  1565.     /*
  1566.      *  the only stat we don't show here are for memory usage -- i can't
  1567.      *  figure out how to interpret the relevant fields in the rusage
  1568.      *  struct, and they change names across o/s platforms, anyway.
  1569.      *  if you can figure out what the entries mean, you can somehow
  1570.      *  extract resident set size, shared text size, and unshared data
  1571.      *  and stack sizes.
  1572.      */
  1573.  
  1574.     fprintf(StatFp, "! system usage stats:\n");
  1575.         fprintf(StatFp, 
  1576.         "!\t%ld.%06ld elapsed %ld.%06ld user %ld.%06ld system sec\n",
  1577.                 elapse_t.tv_sec - Save_t.tv_sec,
  1578.                 elapse_t.tv_usec - Save_t.tv_usec,
  1579.         r.ru_utime.tv_sec - Save_r.ru_utime.tv_sec,
  1580.         r.ru_utime.tv_usec - Save_r.ru_utime.tv_usec,
  1581.         r.ru_stime.tv_sec - Save_r.ru_stime.tv_sec,
  1582.         r.ru_stime.tv_usec - Save_r.ru_stime.tv_usec);
  1583.     fprintf(StatFp,
  1584.         "!\t[%ld.%06ld user %ld.%06ld sys total]\n",
  1585.         user.tv_sec, user.tv_usec, sys.tv_sec, sys.tv_usec);
  1586.     fprintf(StatFp, 
  1587.         "!\t%d/%d [%d/%d] filesystem blocks in/out\n",
  1588.         r.ru_inblock - Save_r.ru_inblock,
  1589.         /* they only drink coffee at dec */
  1590.         r.ru_oublock - Save_r.ru_oublock,
  1591.         r.ru_inblock, r.ru_oublock);
  1592.     fprintf(StatFp, 
  1593.         "!\t%d/%d [%d/%d] page faults/reclaims, %d [%d] swaps\n",
  1594.         r.ru_majflt - Save_r.ru_majflt,
  1595.         r.ru_minflt - Save_r.ru_minflt,
  1596.         r.ru_majflt, r.ru_minflt,
  1597.         r.ru_nswap - Save_r.ru_nswap,
  1598.         r.ru_nswap);
  1599.     fprintf(StatFp, 
  1600.         "!\t%d [%d] signals rcvd, %d/%d [%d/%d] messages rcvd/sent\n",
  1601.         r.ru_nsignals - Save_r.ru_nsignals,
  1602.         r.ru_nsignals,
  1603.         r.ru_msgrcv - Save_r.ru_msgrcv,
  1604.         r.ru_msgsnd - Save_r.ru_msgsnd,
  1605.         r.ru_msgrcv, r.ru_msgsnd);
  1606.     fprintf(StatFp, 
  1607.         "!\t%d/%d [%d/%d] voluntary/involuntary context switches\n",
  1608.         r.ru_nvcsw - Save_r.ru_nvcsw,
  1609.         r.ru_nivcsw - Save_r.ru_nivcsw,
  1610.         r.ru_nvcsw, r.ru_nivcsw);
  1611.     fprintf(StatFp, "! postgres usage stats:\n");
  1612.     PrintBufferUsage(StatFp);
  1613.     DisplayTupleCount(StatFp);
  1614. #ifdef PARALLELDEBUG
  1615.         PrintParallelDebugInfo(StatFp);
  1616. #endif
  1617.     ShowPrs2Stats(StatFp);
  1618. }
  1619.