00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "postgres.h"
00021
00022 #include <fcntl.h>
00023 #include <limits.h>
00024 #include <signal.h>
00025 #include <time.h>
00026 #include <unistd.h>
00027 #include <sys/socket.h>
00028 #ifdef HAVE_SYS_SELECT_H
00029 #include <sys/select.h>
00030 #endif
00031 #ifdef HAVE_SYS_RESOURCE_H
00032 #include <sys/time.h>
00033 #include <sys/resource.h>
00034 #endif
00035 #ifdef HAVE_GETOPT_H
00036 #include <getopt.h>
00037 #endif
00038
00039 #ifndef HAVE_GETRUSAGE
00040 #include "rusagestub.h"
00041 #endif
00042
00043 #include "access/printtup.h"
00044 #include "access/xact.h"
00045 #include "catalog/pg_type.h"
00046 #include "commands/async.h"
00047 #include "commands/prepare.h"
00048 #include "libpq/libpq.h"
00049 #include "libpq/pqformat.h"
00050 #include "libpq/pqsignal.h"
00051 #include "miscadmin.h"
00052 #include "nodes/print.h"
00053 #include "optimizer/planner.h"
00054 #include "pgstat.h"
00055 #include "pg_trace.h"
00056 #include "parser/analyze.h"
00057 #include "parser/parser.h"
00058 #include "postmaster/autovacuum.h"
00059 #include "postmaster/postmaster.h"
00060 #include "replication/walsender.h"
00061 #include "rewrite/rewriteHandler.h"
00062 #include "storage/bufmgr.h"
00063 #include "storage/ipc.h"
00064 #include "storage/proc.h"
00065 #include "storage/procsignal.h"
00066 #include "storage/sinval.h"
00067 #include "tcop/fastpath.h"
00068 #include "tcop/pquery.h"
00069 #include "tcop/tcopprot.h"
00070 #include "tcop/utility.h"
00071 #include "utils/lsyscache.h"
00072 #include "utils/memutils.h"
00073 #include "utils/ps_status.h"
00074 #include "utils/snapmgr.h"
00075 #include "utils/timeout.h"
00076 #include "utils/timestamp.h"
00077 #include "mb/pg_wchar.h"
00078
00079
00080 extern char *optarg;
00081 extern int optind;
00082
00083 #ifdef HAVE_INT_OPTRESET
00084 extern int optreset;
00085 #endif
00086
00087
00088
00089
00090
00091
00092 const char *debug_query_string;
00093
00094
00095 CommandDest whereToSendOutput = DestDebug;
00096
00097
00098 bool Log_disconnections = false;
00099
00100 int log_statement = LOGSTMT_NONE;
00101
00102
00103 int max_stack_depth = 100;
00104
00105
00106 int PostAuthDelay = 0;
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116 static long max_stack_depth_bytes = 100 * 1024L;
00117
00118
00119
00120
00121
00122
00123
00124 char *stack_base_ptr = NULL;
00125
00126
00127
00128
00129 #if defined(__ia64__) || defined(__ia64)
00130 char *register_stack_base_ptr = NULL;
00131 #endif
00132
00133
00134
00135
00136
00137
00138 static volatile sig_atomic_t got_SIGHUP = false;
00139
00140
00141
00142
00143
00144 static bool xact_started = false;
00145
00146
00147
00148
00149
00150
00151 static bool DoingCommandRead = false;
00152
00153
00154
00155
00156
00157 static bool doing_extended_query_message = false;
00158 static bool ignore_till_sync = false;
00159
00160
00161
00162
00163
00164
00165 static CachedPlanSource *unnamed_stmt_psrc = NULL;
00166
00167
00168 static const char *userDoption = NULL;
00169
00170 static bool EchoQuery = false;
00171
00172
00173
00174
00175
00176 #ifndef TCOP_DONTUSENEWLINE
00177 static int UseNewLine = 1;
00178 #else
00179 static int UseNewLine = 0;
00180 #endif
00181
00182
00183 static bool RecoveryConflictPending = false;
00184 static bool RecoveryConflictRetryable = true;
00185 static ProcSignalReason RecoveryConflictReason;
00186
00187
00188
00189
00190
00191 static int InteractiveBackend(StringInfo inBuf);
00192 static int interactive_getc(void);
00193 static int SocketBackend(StringInfo inBuf);
00194 static int ReadCommand(StringInfo inBuf);
00195 static void forbidden_in_wal_sender(char firstchar);
00196 static List *pg_rewrite_query(Query *query);
00197 static bool check_log_statement(List *stmt_list);
00198 static int errdetail_execute(List *raw_parsetree_list);
00199 static int errdetail_params(ParamListInfo params);
00200 static int errdetail_abort(void);
00201 static int errdetail_recovery_conflict(void);
00202 static void start_xact_command(void);
00203 static void finish_xact_command(void);
00204 static bool IsTransactionExitStmt(Node *parsetree);
00205 static bool IsTransactionExitStmtList(List *parseTrees);
00206 static bool IsTransactionStmtList(List *parseTrees);
00207 static void drop_unnamed_stmt(void);
00208 static void SigHupHandler(SIGNAL_ARGS);
00209 static void log_disconnections(int code, Datum arg);
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 static int
00228 InteractiveBackend(StringInfo inBuf)
00229 {
00230 int c;
00231 bool end = false;
00232 bool backslashSeen = false;
00233
00234
00235
00236
00237 printf("backend> ");
00238 fflush(stdout);
00239
00240 resetStringInfo(inBuf);
00241
00242 if (UseNewLine)
00243 {
00244
00245
00246
00247
00248 while ((c = interactive_getc()) != EOF)
00249 {
00250 if (c == '\n')
00251 {
00252 if (backslashSeen)
00253 {
00254
00255 inBuf->data[--inBuf->len] = '\0';
00256 backslashSeen = false;
00257 continue;
00258 }
00259 else
00260 {
00261
00262 appendStringInfoChar(inBuf, '\n');
00263 break;
00264 }
00265 }
00266 else if (c == '\\')
00267 backslashSeen = true;
00268 else
00269 backslashSeen = false;
00270
00271 appendStringInfoChar(inBuf, (char) c);
00272 }
00273
00274 if (c == EOF)
00275 end = true;
00276 }
00277 else
00278 {
00279
00280
00281
00282 while ((c = interactive_getc()) != EOF)
00283 appendStringInfoChar(inBuf, (char) c);
00284
00285
00286 if (inBuf->len == 0)
00287 end = true;
00288 }
00289
00290 if (end)
00291 return EOF;
00292
00293
00294
00295
00296
00297
00298 appendStringInfoChar(inBuf, (char) '\0');
00299
00300
00301
00302
00303 if (EchoQuery)
00304 printf("statement: %s\n", inBuf->data);
00305 fflush(stdout);
00306
00307 return 'Q';
00308 }
00309
00310
00311
00312
00313
00314
00315
00316
00317 static int
00318 interactive_getc(void)
00319 {
00320 int c;
00321
00322 prepare_for_client_read();
00323 c = getc(stdin);
00324 client_read_ended();
00325 return c;
00326 }
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336 static int
00337 SocketBackend(StringInfo inBuf)
00338 {
00339 int qtype;
00340
00341
00342
00343
00344 qtype = pq_getbyte();
00345
00346 if (qtype == EOF)
00347 {
00348 if (IsTransactionState())
00349 ereport(COMMERROR,
00350 (errcode(ERRCODE_CONNECTION_FAILURE),
00351 errmsg("unexpected EOF on client connection with an open transaction")));
00352 else
00353 {
00354
00355
00356
00357
00358
00359 whereToSendOutput = DestNone;
00360 ereport(DEBUG1,
00361 (errcode(ERRCODE_CONNECTION_DOES_NOT_EXIST),
00362 errmsg("unexpected EOF on client connection")));
00363 }
00364 return qtype;
00365 }
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375 switch (qtype)
00376 {
00377 case 'Q':
00378 doing_extended_query_message = false;
00379 if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
00380 {
00381
00382 if (pq_getstring(inBuf))
00383 {
00384 if (IsTransactionState())
00385 ereport(COMMERROR,
00386 (errcode(ERRCODE_CONNECTION_FAILURE),
00387 errmsg("unexpected EOF on client connection with an open transaction")));
00388 else
00389 {
00390
00391
00392
00393
00394
00395 whereToSendOutput = DestNone;
00396 ereport(DEBUG1,
00397 (errcode(ERRCODE_CONNECTION_DOES_NOT_EXIST),
00398 errmsg("unexpected EOF on client connection")));
00399 }
00400 return EOF;
00401 }
00402 }
00403 break;
00404
00405 case 'F':
00406
00407 doing_extended_query_message = false;
00408 break;
00409
00410 case 'X':
00411 doing_extended_query_message = false;
00412 ignore_till_sync = false;
00413 break;
00414
00415 case 'B':
00416 case 'C':
00417 case 'D':
00418 case 'E':
00419 case 'H':
00420 case 'P':
00421 doing_extended_query_message = true;
00422
00423 if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
00424 ereport(FATAL,
00425 (errcode(ERRCODE_PROTOCOL_VIOLATION),
00426 errmsg("invalid frontend message type %d", qtype)));
00427 break;
00428
00429 case 'S':
00430
00431 ignore_till_sync = false;
00432
00433 doing_extended_query_message = false;
00434
00435 if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
00436 ereport(FATAL,
00437 (errcode(ERRCODE_PROTOCOL_VIOLATION),
00438 errmsg("invalid frontend message type %d", qtype)));
00439 break;
00440
00441 case 'd':
00442 case 'c':
00443 case 'f':
00444 doing_extended_query_message = false;
00445
00446 if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
00447 ereport(FATAL,
00448 (errcode(ERRCODE_PROTOCOL_VIOLATION),
00449 errmsg("invalid frontend message type %d", qtype)));
00450 break;
00451
00452 default:
00453
00454
00455
00456
00457
00458
00459 ereport(FATAL,
00460 (errcode(ERRCODE_PROTOCOL_VIOLATION),
00461 errmsg("invalid frontend message type %d", qtype)));
00462 break;
00463 }
00464
00465
00466
00467
00468
00469
00470 if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3)
00471 {
00472 if (pq_getmessage(inBuf, 0))
00473 return EOF;
00474 }
00475
00476 return qtype;
00477 }
00478
00479
00480
00481
00482
00483
00484
00485
00486 static int
00487 ReadCommand(StringInfo inBuf)
00488 {
00489 int result;
00490
00491 if (whereToSendOutput == DestRemote)
00492 result = SocketBackend(inBuf);
00493 else
00494 result = InteractiveBackend(inBuf);
00495 return result;
00496 }
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510 void
00511 prepare_for_client_read(void)
00512 {
00513 if (DoingCommandRead)
00514 {
00515
00516 EnableNotifyInterrupt();
00517 EnableCatchupInterrupt();
00518
00519
00520 ImmediateInterruptOK = true;
00521
00522
00523 CHECK_FOR_INTERRUPTS();
00524 }
00525 }
00526
00527
00528
00529
00530 void
00531 client_read_ended(void)
00532 {
00533 if (DoingCommandRead)
00534 {
00535 ImmediateInterruptOK = false;
00536
00537 DisableNotifyInterrupt();
00538 DisableCatchupInterrupt();
00539 }
00540 }
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556 List *
00557 pg_parse_query(const char *query_string)
00558 {
00559 List *raw_parsetree_list;
00560
00561 TRACE_POSTGRESQL_QUERY_PARSE_START(query_string);
00562
00563 if (log_parser_stats)
00564 ResetUsage();
00565
00566 raw_parsetree_list = raw_parser(query_string);
00567
00568 if (log_parser_stats)
00569 ShowUsage("PARSER STATISTICS");
00570
00571 #ifdef COPY_PARSE_PLAN_TREES
00572
00573 {
00574 List *new_list = (List *) copyObject(raw_parsetree_list);
00575
00576
00577 if (!equal(new_list, raw_parsetree_list))
00578 elog(WARNING, "copyObject() failed to produce an equal raw parse tree");
00579 else
00580 raw_parsetree_list = new_list;
00581 }
00582 #endif
00583
00584 TRACE_POSTGRESQL_QUERY_PARSE_DONE(query_string);
00585
00586 return raw_parsetree_list;
00587 }
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598 List *
00599 pg_analyze_and_rewrite(Node *parsetree, const char *query_string,
00600 Oid *paramTypes, int numParams)
00601 {
00602 Query *query;
00603 List *querytree_list;
00604
00605 TRACE_POSTGRESQL_QUERY_REWRITE_START(query_string);
00606
00607
00608
00609
00610 if (log_parser_stats)
00611 ResetUsage();
00612
00613 query = parse_analyze(parsetree, query_string, paramTypes, numParams);
00614
00615 if (log_parser_stats)
00616 ShowUsage("PARSE ANALYSIS STATISTICS");
00617
00618
00619
00620
00621 querytree_list = pg_rewrite_query(query);
00622
00623 TRACE_POSTGRESQL_QUERY_REWRITE_DONE(query_string);
00624
00625 return querytree_list;
00626 }
00627
00628
00629
00630
00631
00632
00633 List *
00634 pg_analyze_and_rewrite_params(Node *parsetree,
00635 const char *query_string,
00636 ParserSetupHook parserSetup,
00637 void *parserSetupArg)
00638 {
00639 ParseState *pstate;
00640 Query *query;
00641 List *querytree_list;
00642
00643 Assert(query_string != NULL);
00644
00645 TRACE_POSTGRESQL_QUERY_REWRITE_START(query_string);
00646
00647
00648
00649
00650 if (log_parser_stats)
00651 ResetUsage();
00652
00653 pstate = make_parsestate(NULL);
00654 pstate->p_sourcetext = query_string;
00655 (*parserSetup) (pstate, parserSetupArg);
00656
00657 query = transformTopLevelStmt(pstate, parsetree);
00658
00659 if (post_parse_analyze_hook)
00660 (*post_parse_analyze_hook) (pstate, query);
00661
00662 free_parsestate(pstate);
00663
00664 if (log_parser_stats)
00665 ShowUsage("PARSE ANALYSIS STATISTICS");
00666
00667
00668
00669
00670 querytree_list = pg_rewrite_query(query);
00671
00672 TRACE_POSTGRESQL_QUERY_REWRITE_DONE(query_string);
00673
00674 return querytree_list;
00675 }
00676
00677
00678
00679
00680
00681
00682
00683 static List *
00684 pg_rewrite_query(Query *query)
00685 {
00686 List *querytree_list;
00687
00688 if (Debug_print_parse)
00689 elog_node_display(LOG, "parse tree", query,
00690 Debug_pretty_print);
00691
00692 if (log_parser_stats)
00693 ResetUsage();
00694
00695 if (query->commandType == CMD_UTILITY)
00696 {
00697
00698 querytree_list = list_make1(query);
00699 }
00700 else
00701 {
00702
00703 querytree_list = QueryRewrite(query);
00704 }
00705
00706 if (log_parser_stats)
00707 ShowUsage("REWRITER STATISTICS");
00708
00709 #ifdef COPY_PARSE_PLAN_TREES
00710
00711 {
00712 List *new_list;
00713
00714 new_list = (List *) copyObject(querytree_list);
00715
00716 if (!equal(new_list, querytree_list))
00717 elog(WARNING, "copyObject() failed to produce equal parse tree");
00718 else
00719 querytree_list = new_list;
00720 }
00721 #endif
00722
00723 if (Debug_print_rewritten)
00724 elog_node_display(LOG, "rewritten parse tree", querytree_list,
00725 Debug_pretty_print);
00726
00727 return querytree_list;
00728 }
00729
00730
00731
00732
00733
00734
00735 PlannedStmt *
00736 pg_plan_query(Query *querytree, int cursorOptions, ParamListInfo boundParams)
00737 {
00738 PlannedStmt *plan;
00739
00740
00741 if (querytree->commandType == CMD_UTILITY)
00742 return NULL;
00743
00744
00745 Assert(ActiveSnapshotSet());
00746
00747 TRACE_POSTGRESQL_QUERY_PLAN_START();
00748
00749 if (log_planner_stats)
00750 ResetUsage();
00751
00752
00753 plan = planner(querytree, cursorOptions, boundParams);
00754
00755 if (log_planner_stats)
00756 ShowUsage("PLANNER STATISTICS");
00757
00758 #ifdef COPY_PARSE_PLAN_TREES
00759
00760 {
00761 PlannedStmt *new_plan = (PlannedStmt *) copyObject(plan);
00762
00763
00764
00765
00766
00767 #ifdef NOT_USED
00768
00769 if (!equal(new_plan, plan))
00770 elog(WARNING, "copyObject() failed to produce an equal plan tree");
00771 else
00772 #endif
00773 plan = new_plan;
00774 }
00775 #endif
00776
00777
00778
00779
00780 if (Debug_print_plan)
00781 elog_node_display(LOG, "plan", plan, Debug_pretty_print);
00782
00783 TRACE_POSTGRESQL_QUERY_PLAN_DONE();
00784
00785 return plan;
00786 }
00787
00788
00789
00790
00791
00792
00793
00794 List *
00795 pg_plan_queries(List *querytrees, int cursorOptions, ParamListInfo boundParams)
00796 {
00797 List *stmt_list = NIL;
00798 ListCell *query_list;
00799
00800 foreach(query_list, querytrees)
00801 {
00802 Query *query = (Query *) lfirst(query_list);
00803 Node *stmt;
00804
00805 if (query->commandType == CMD_UTILITY)
00806 {
00807
00808 stmt = query->utilityStmt;
00809 }
00810 else
00811 {
00812 stmt = (Node *) pg_plan_query(query, cursorOptions, boundParams);
00813 }
00814
00815 stmt_list = lappend(stmt_list, stmt);
00816 }
00817
00818 return stmt_list;
00819 }
00820
00821
00822
00823
00824
00825
00826
00827 static void
00828 exec_simple_query(const char *query_string)
00829 {
00830 CommandDest dest = whereToSendOutput;
00831 MemoryContext oldcontext;
00832 List *parsetree_list;
00833 ListCell *parsetree_item;
00834 bool save_log_statement_stats = log_statement_stats;
00835 bool was_logged = false;
00836 bool isTopLevel;
00837 char msec_str[32];
00838
00839
00840
00841
00842
00843 debug_query_string = query_string;
00844
00845 pgstat_report_activity(STATE_RUNNING, query_string);
00846
00847 TRACE_POSTGRESQL_QUERY_START(query_string);
00848
00849
00850
00851
00852
00853 if (save_log_statement_stats)
00854 ResetUsage();
00855
00856
00857
00858
00859
00860
00861
00862
00863 start_xact_command();
00864
00865
00866
00867
00868
00869
00870
00871 drop_unnamed_stmt();
00872
00873
00874
00875
00876 oldcontext = MemoryContextSwitchTo(MessageContext);
00877
00878
00879
00880
00881
00882 parsetree_list = pg_parse_query(query_string);
00883
00884
00885 if (check_log_statement(parsetree_list))
00886 {
00887 ereport(LOG,
00888 (errmsg("statement: %s", query_string),
00889 errhidestmt(true),
00890 errdetail_execute(parsetree_list)));
00891 was_logged = true;
00892 }
00893
00894
00895
00896
00897 MemoryContextSwitchTo(oldcontext);
00898
00899
00900
00901
00902
00903
00904
00905
00906 isTopLevel = (list_length(parsetree_list) == 1);
00907
00908
00909
00910
00911 foreach(parsetree_item, parsetree_list)
00912 {
00913 Node *parsetree = (Node *) lfirst(parsetree_item);
00914 bool snapshot_set = false;
00915 const char *commandTag;
00916 char completionTag[COMPLETION_TAG_BUFSIZE];
00917 List *querytree_list,
00918 *plantree_list;
00919 Portal portal;
00920 DestReceiver *receiver;
00921 int16 format;
00922
00923
00924
00925
00926
00927
00928
00929 commandTag = CreateCommandTag(parsetree);
00930
00931 set_ps_display(commandTag, false);
00932
00933 BeginCommand(commandTag, dest);
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943 if (IsAbortedTransactionBlockState() &&
00944 !IsTransactionExitStmt(parsetree))
00945 ereport(ERROR,
00946 (errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
00947 errmsg("current transaction is aborted, "
00948 "commands ignored until end of transaction block"),
00949 errdetail_abort()));
00950
00951
00952 start_xact_command();
00953
00954
00955 CHECK_FOR_INTERRUPTS();
00956
00957
00958
00959
00960 if (analyze_requires_snapshot(parsetree))
00961 {
00962 PushActiveSnapshot(GetTransactionSnapshot());
00963 snapshot_set = true;
00964 }
00965
00966
00967
00968
00969
00970
00971
00972 oldcontext = MemoryContextSwitchTo(MessageContext);
00973
00974 querytree_list = pg_analyze_and_rewrite(parsetree, query_string,
00975 NULL, 0);
00976
00977 plantree_list = pg_plan_queries(querytree_list, 0, NULL);
00978
00979
00980 if (snapshot_set)
00981 PopActiveSnapshot();
00982
00983
00984 CHECK_FOR_INTERRUPTS();
00985
00986
00987
00988
00989
00990 portal = CreatePortal("", true, true);
00991
00992 portal->visible = false;
00993
00994
00995
00996
00997
00998
00999 PortalDefineQuery(portal,
01000 NULL,
01001 query_string,
01002 commandTag,
01003 plantree_list,
01004 NULL);
01005
01006
01007
01008
01009 PortalStart(portal, NULL, 0, InvalidSnapshot);
01010
01011
01012
01013
01014
01015
01016
01017 format = 0;
01018 if (IsA(parsetree, FetchStmt))
01019 {
01020 FetchStmt *stmt = (FetchStmt *) parsetree;
01021
01022 if (!stmt->ismove)
01023 {
01024 Portal fportal = GetPortalByName(stmt->portalname);
01025
01026 if (PortalIsValid(fportal) &&
01027 (fportal->cursorOptions & CURSOR_OPT_BINARY))
01028 format = 1;
01029 }
01030 }
01031 PortalSetResultFormat(portal, 1, &format);
01032
01033
01034
01035
01036 receiver = CreateDestReceiver(dest);
01037 if (dest == DestRemote)
01038 SetRemoteDestReceiverParams(receiver, portal);
01039
01040
01041
01042
01043 MemoryContextSwitchTo(oldcontext);
01044
01045
01046
01047
01048 (void) PortalRun(portal,
01049 FETCH_ALL,
01050 isTopLevel,
01051 receiver,
01052 receiver,
01053 completionTag);
01054
01055 (*receiver->rDestroy) (receiver);
01056
01057 PortalDrop(portal, false);
01058
01059 if (IsA(parsetree, TransactionStmt))
01060 {
01061
01062
01063
01064
01065 finish_xact_command();
01066 }
01067 else if (lnext(parsetree_item) == NULL)
01068 {
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079 finish_xact_command();
01080 }
01081 else
01082 {
01083
01084
01085
01086
01087 CommandCounterIncrement();
01088 }
01089
01090
01091
01092
01093
01094
01095
01096 EndCommand(completionTag, dest);
01097 }
01098
01099
01100
01101
01102 finish_xact_command();
01103
01104
01105
01106
01107 if (!parsetree_list)
01108 NullCommand(dest);
01109
01110
01111
01112
01113 switch (check_log_duration(msec_str, was_logged))
01114 {
01115 case 1:
01116 ereport(LOG,
01117 (errmsg("duration: %s ms", msec_str),
01118 errhidestmt(true)));
01119 break;
01120 case 2:
01121 ereport(LOG,
01122 (errmsg("duration: %s ms statement: %s",
01123 msec_str, query_string),
01124 errhidestmt(true),
01125 errdetail_execute(parsetree_list)));
01126 break;
01127 }
01128
01129 if (save_log_statement_stats)
01130 ShowUsage("QUERY STATISTICS");
01131
01132 TRACE_POSTGRESQL_QUERY_DONE(query_string);
01133
01134 debug_query_string = NULL;
01135 }
01136
01137
01138
01139
01140
01141
01142 static void
01143 exec_parse_message(const char *query_string,
01144 const char *stmt_name,
01145 Oid *paramTypes,
01146 int numParams)
01147 {
01148 MemoryContext unnamed_stmt_context = NULL;
01149 MemoryContext oldcontext;
01150 List *parsetree_list;
01151 Node *raw_parse_tree;
01152 const char *commandTag;
01153 List *querytree_list;
01154 CachedPlanSource *psrc;
01155 bool is_named;
01156 bool save_log_statement_stats = log_statement_stats;
01157 char msec_str[32];
01158
01159
01160
01161
01162 debug_query_string = query_string;
01163
01164 pgstat_report_activity(STATE_RUNNING, query_string);
01165
01166 set_ps_display("PARSE", false);
01167
01168 if (save_log_statement_stats)
01169 ResetUsage();
01170
01171 ereport(DEBUG2,
01172 (errmsg("parse %s: %s",
01173 *stmt_name ? stmt_name : "<unnamed>",
01174 query_string)));
01175
01176
01177
01178
01179
01180
01181 start_xact_command();
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196 is_named = (stmt_name[0] != '\0');
01197 if (is_named)
01198 {
01199
01200 oldcontext = MemoryContextSwitchTo(MessageContext);
01201 }
01202 else
01203 {
01204
01205 drop_unnamed_stmt();
01206
01207 unnamed_stmt_context =
01208 AllocSetContextCreate(MessageContext,
01209 "unnamed prepared statement",
01210 ALLOCSET_DEFAULT_MINSIZE,
01211 ALLOCSET_DEFAULT_INITSIZE,
01212 ALLOCSET_DEFAULT_MAXSIZE);
01213 oldcontext = MemoryContextSwitchTo(unnamed_stmt_context);
01214 }
01215
01216
01217
01218
01219
01220 parsetree_list = pg_parse_query(query_string);
01221
01222
01223
01224
01225
01226
01227 if (list_length(parsetree_list) > 1)
01228 ereport(ERROR,
01229 (errcode(ERRCODE_SYNTAX_ERROR),
01230 errmsg("cannot insert multiple commands into a prepared statement")));
01231
01232 if (parsetree_list != NIL)
01233 {
01234 Query *query;
01235 bool snapshot_set = false;
01236 int i;
01237
01238 raw_parse_tree = (Node *) linitial(parsetree_list);
01239
01240
01241
01242
01243 commandTag = CreateCommandTag(raw_parse_tree);
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253 if (IsAbortedTransactionBlockState() &&
01254 !IsTransactionExitStmt(raw_parse_tree))
01255 ereport(ERROR,
01256 (errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
01257 errmsg("current transaction is aborted, "
01258 "commands ignored until end of transaction block"),
01259 errdetail_abort()));
01260
01261
01262
01263
01264
01265 psrc = CreateCachedPlan(raw_parse_tree, query_string, commandTag);
01266
01267
01268
01269
01270 if (analyze_requires_snapshot(raw_parse_tree))
01271 {
01272 PushActiveSnapshot(GetTransactionSnapshot());
01273 snapshot_set = true;
01274 }
01275
01276
01277
01278
01279
01280
01281 if (log_parser_stats)
01282 ResetUsage();
01283
01284 query = parse_analyze_varparams(raw_parse_tree,
01285 query_string,
01286 ¶mTypes,
01287 &numParams);
01288
01289
01290
01291
01292 for (i = 0; i < numParams; i++)
01293 {
01294 Oid ptype = paramTypes[i];
01295
01296 if (ptype == InvalidOid || ptype == UNKNOWNOID)
01297 ereport(ERROR,
01298 (errcode(ERRCODE_INDETERMINATE_DATATYPE),
01299 errmsg("could not determine data type of parameter $%d",
01300 i + 1)));
01301 }
01302
01303 if (log_parser_stats)
01304 ShowUsage("PARSE ANALYSIS STATISTICS");
01305
01306 querytree_list = pg_rewrite_query(query);
01307
01308
01309 if (snapshot_set)
01310 PopActiveSnapshot();
01311 }
01312 else
01313 {
01314
01315 raw_parse_tree = NULL;
01316 commandTag = NULL;
01317 psrc = CreateCachedPlan(raw_parse_tree, query_string, commandTag);
01318 querytree_list = NIL;
01319 }
01320
01321
01322
01323
01324
01325
01326
01327 if (unnamed_stmt_context)
01328 MemoryContextSetParent(psrc->context, MessageContext);
01329
01330
01331 CompleteCachedPlan(psrc,
01332 querytree_list,
01333 unnamed_stmt_context,
01334 paramTypes,
01335 numParams,
01336 NULL,
01337 NULL,
01338 0,
01339 true);
01340
01341
01342 CHECK_FOR_INTERRUPTS();
01343
01344 if (is_named)
01345 {
01346
01347
01348
01349 StorePreparedStatement(stmt_name, psrc, false);
01350 }
01351 else
01352 {
01353
01354
01355
01356 SaveCachedPlan(psrc);
01357 unnamed_stmt_psrc = psrc;
01358 }
01359
01360 MemoryContextSwitchTo(oldcontext);
01361
01362
01363
01364
01365
01366
01367 CommandCounterIncrement();
01368
01369
01370
01371
01372 if (whereToSendOutput == DestRemote)
01373 pq_putemptymessage('1');
01374
01375
01376
01377
01378 switch (check_log_duration(msec_str, false))
01379 {
01380 case 1:
01381 ereport(LOG,
01382 (errmsg("duration: %s ms", msec_str),
01383 errhidestmt(true)));
01384 break;
01385 case 2:
01386 ereport(LOG,
01387 (errmsg("duration: %s ms parse %s: %s",
01388 msec_str,
01389 *stmt_name ? stmt_name : "<unnamed>",
01390 query_string),
01391 errhidestmt(true)));
01392 break;
01393 }
01394
01395 if (save_log_statement_stats)
01396 ShowUsage("PARSE MESSAGE STATISTICS");
01397
01398 debug_query_string = NULL;
01399 }
01400
01401
01402
01403
01404
01405
01406 static void
01407 exec_bind_message(StringInfo input_message)
01408 {
01409 const char *portal_name;
01410 const char *stmt_name;
01411 int numPFormats;
01412 int16 *pformats = NULL;
01413 int numParams;
01414 int numRFormats;
01415 int16 *rformats = NULL;
01416 CachedPlanSource *psrc;
01417 CachedPlan *cplan;
01418 Portal portal;
01419 char *query_string;
01420 char *saved_stmt_name;
01421 ParamListInfo params;
01422 MemoryContext oldContext;
01423 bool save_log_statement_stats = log_statement_stats;
01424 bool snapshot_set = false;
01425 char msec_str[32];
01426
01427
01428 portal_name = pq_getmsgstring(input_message);
01429 stmt_name = pq_getmsgstring(input_message);
01430
01431 ereport(DEBUG2,
01432 (errmsg("bind %s to %s",
01433 *portal_name ? portal_name : "<unnamed>",
01434 *stmt_name ? stmt_name : "<unnamed>")));
01435
01436
01437 if (stmt_name[0] != '\0')
01438 {
01439 PreparedStatement *pstmt;
01440
01441 pstmt = FetchPreparedStatement(stmt_name, true);
01442 psrc = pstmt->plansource;
01443 }
01444 else
01445 {
01446
01447 psrc = unnamed_stmt_psrc;
01448 if (!psrc)
01449 ereport(ERROR,
01450 (errcode(ERRCODE_UNDEFINED_PSTATEMENT),
01451 errmsg("unnamed prepared statement does not exist")));
01452 }
01453
01454
01455
01456
01457 debug_query_string = psrc->query_string;
01458
01459 pgstat_report_activity(STATE_RUNNING, psrc->query_string);
01460
01461 set_ps_display("BIND", false);
01462
01463 if (save_log_statement_stats)
01464 ResetUsage();
01465
01466
01467
01468
01469
01470
01471 start_xact_command();
01472
01473
01474 MemoryContextSwitchTo(MessageContext);
01475
01476
01477 numPFormats = pq_getmsgint(input_message, 2);
01478 if (numPFormats > 0)
01479 {
01480 int i;
01481
01482 pformats = (int16 *) palloc(numPFormats * sizeof(int16));
01483 for (i = 0; i < numPFormats; i++)
01484 pformats[i] = pq_getmsgint(input_message, 2);
01485 }
01486
01487
01488 numParams = pq_getmsgint(input_message, 2);
01489
01490 if (numPFormats > 1 && numPFormats != numParams)
01491 ereport(ERROR,
01492 (errcode(ERRCODE_PROTOCOL_VIOLATION),
01493 errmsg("bind message has %d parameter formats but %d parameters",
01494 numPFormats, numParams)));
01495
01496 if (numParams != psrc->num_params)
01497 ereport(ERROR,
01498 (errcode(ERRCODE_PROTOCOL_VIOLATION),
01499 errmsg("bind message supplies %d parameters, but prepared statement \"%s\" requires %d",
01500 numParams, stmt_name, psrc->num_params)));
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510 if (IsAbortedTransactionBlockState() &&
01511 (!IsTransactionExitStmt(psrc->raw_parse_tree) ||
01512 numParams != 0))
01513 ereport(ERROR,
01514 (errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
01515 errmsg("current transaction is aborted, "
01516 "commands ignored until end of transaction block"),
01517 errdetail_abort()));
01518
01519
01520
01521
01522
01523 if (portal_name[0] == '\0')
01524 portal = CreatePortal(portal_name, true, true);
01525 else
01526 portal = CreatePortal(portal_name, false, false);
01527
01528
01529
01530
01531
01532
01533
01534 oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
01535
01536
01537 query_string = pstrdup(psrc->query_string);
01538
01539
01540 if (stmt_name[0])
01541 saved_stmt_name = pstrdup(stmt_name);
01542 else
01543 saved_stmt_name = NULL;
01544
01545
01546
01547
01548
01549
01550
01551
01552 if (numParams > 0 || analyze_requires_snapshot(psrc->raw_parse_tree))
01553 {
01554 PushActiveSnapshot(GetTransactionSnapshot());
01555 snapshot_set = true;
01556 }
01557
01558
01559
01560
01561 if (numParams > 0)
01562 {
01563 int paramno;
01564
01565
01566 params = (ParamListInfo) palloc(sizeof(ParamListInfoData) +
01567 (numParams - 1) * sizeof(ParamExternData));
01568
01569 params->paramFetch = NULL;
01570 params->paramFetchArg = NULL;
01571 params->parserSetup = NULL;
01572 params->parserSetupArg = NULL;
01573 params->numParams = numParams;
01574
01575 for (paramno = 0; paramno < numParams; paramno++)
01576 {
01577 Oid ptype = psrc->param_types[paramno];
01578 int32 plength;
01579 Datum pval;
01580 bool isNull;
01581 StringInfoData pbuf;
01582 char csave;
01583 int16 pformat;
01584
01585 plength = pq_getmsgint(input_message, 4);
01586 isNull = (plength == -1);
01587
01588 if (!isNull)
01589 {
01590 const char *pvalue = pq_getmsgbytes(input_message, plength);
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600 pbuf.data = (char *) pvalue;
01601 pbuf.maxlen = plength + 1;
01602 pbuf.len = plength;
01603 pbuf.cursor = 0;
01604
01605 csave = pbuf.data[plength];
01606 pbuf.data[plength] = '\0';
01607 }
01608 else
01609 {
01610 pbuf.data = NULL;
01611 csave = 0;
01612 }
01613
01614 if (numPFormats > 1)
01615 pformat = pformats[paramno];
01616 else if (numPFormats > 0)
01617 pformat = pformats[0];
01618 else
01619 pformat = 0;
01620
01621 if (pformat == 0)
01622 {
01623 Oid typinput;
01624 Oid typioparam;
01625 char *pstring;
01626
01627 getTypeInputInfo(ptype, &typinput, &typioparam);
01628
01629
01630
01631
01632
01633 if (isNull)
01634 pstring = NULL;
01635 else
01636 pstring = pg_client_to_server(pbuf.data, plength);
01637
01638 pval = OidInputFunctionCall(typinput, pstring, typioparam, -1);
01639
01640
01641 if (pstring && pstring != pbuf.data)
01642 pfree(pstring);
01643 }
01644 else if (pformat == 1)
01645 {
01646 Oid typreceive;
01647 Oid typioparam;
01648 StringInfo bufptr;
01649
01650
01651
01652
01653 getTypeBinaryInputInfo(ptype, &typreceive, &typioparam);
01654
01655 if (isNull)
01656 bufptr = NULL;
01657 else
01658 bufptr = &pbuf;
01659
01660 pval = OidReceiveFunctionCall(typreceive, bufptr, typioparam, -1);
01661
01662
01663 if (!isNull && pbuf.cursor != pbuf.len)
01664 ereport(ERROR,
01665 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
01666 errmsg("incorrect binary data format in bind parameter %d",
01667 paramno + 1)));
01668 }
01669 else
01670 {
01671 ereport(ERROR,
01672 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
01673 errmsg("unsupported format code: %d",
01674 pformat)));
01675 pval = 0;
01676 }
01677
01678
01679 if (!isNull)
01680 pbuf.data[plength] = csave;
01681
01682 params->params[paramno].value = pval;
01683 params->params[paramno].isnull = isNull;
01684
01685
01686
01687
01688
01689 params->params[paramno].pflags = PARAM_FLAG_CONST;
01690 params->params[paramno].ptype = ptype;
01691 }
01692 }
01693 else
01694 params = NULL;
01695
01696
01697 MemoryContextSwitchTo(oldContext);
01698
01699
01700 numRFormats = pq_getmsgint(input_message, 2);
01701 if (numRFormats > 0)
01702 {
01703 int i;
01704
01705 rformats = (int16 *) palloc(numRFormats * sizeof(int16));
01706 for (i = 0; i < numRFormats; i++)
01707 rformats[i] = pq_getmsgint(input_message, 2);
01708 }
01709
01710 pq_getmsgend(input_message);
01711
01712
01713
01714
01715
01716
01717 cplan = GetCachedPlan(psrc, params, false);
01718
01719
01720
01721
01722
01723
01724
01725 PortalDefineQuery(portal,
01726 saved_stmt_name,
01727 query_string,
01728 psrc->commandTag,
01729 cplan->stmt_list,
01730 cplan);
01731
01732
01733 if (snapshot_set)
01734 PopActiveSnapshot();
01735
01736
01737
01738
01739 PortalStart(portal, params, 0, InvalidSnapshot);
01740
01741
01742
01743
01744 PortalSetResultFormat(portal, numRFormats, rformats);
01745
01746
01747
01748
01749 if (whereToSendOutput == DestRemote)
01750 pq_putemptymessage('2');
01751
01752
01753
01754
01755 switch (check_log_duration(msec_str, false))
01756 {
01757 case 1:
01758 ereport(LOG,
01759 (errmsg("duration: %s ms", msec_str),
01760 errhidestmt(true)));
01761 break;
01762 case 2:
01763 ereport(LOG,
01764 (errmsg("duration: %s ms bind %s%s%s: %s",
01765 msec_str,
01766 *stmt_name ? stmt_name : "<unnamed>",
01767 *portal_name ? "/" : "",
01768 *portal_name ? portal_name : "",
01769 psrc->query_string),
01770 errhidestmt(true),
01771 errdetail_params(params)));
01772 break;
01773 }
01774
01775 if (save_log_statement_stats)
01776 ShowUsage("BIND MESSAGE STATISTICS");
01777
01778 debug_query_string = NULL;
01779 }
01780
01781
01782
01783
01784
01785
01786 static void
01787 exec_execute_message(const char *portal_name, long max_rows)
01788 {
01789 CommandDest dest;
01790 DestReceiver *receiver;
01791 Portal portal;
01792 bool completed;
01793 char completionTag[COMPLETION_TAG_BUFSIZE];
01794 const char *sourceText;
01795 const char *prepStmtName;
01796 ParamListInfo portalParams;
01797 bool save_log_statement_stats = log_statement_stats;
01798 bool is_xact_command;
01799 bool execute_is_fetch;
01800 bool was_logged = false;
01801 char msec_str[32];
01802
01803
01804 dest = whereToSendOutput;
01805 if (dest == DestRemote)
01806 dest = DestRemoteExecute;
01807
01808 portal = GetPortalByName(portal_name);
01809 if (!PortalIsValid(portal))
01810 ereport(ERROR,
01811 (errcode(ERRCODE_UNDEFINED_CURSOR),
01812 errmsg("portal \"%s\" does not exist", portal_name)));
01813
01814
01815
01816
01817
01818 if (portal->commandTag == NULL)
01819 {
01820 Assert(portal->stmts == NIL);
01821 NullCommand(dest);
01822 return;
01823 }
01824
01825
01826 is_xact_command = IsTransactionStmtList(portal->stmts);
01827
01828
01829
01830
01831
01832
01833 if (is_xact_command)
01834 {
01835 sourceText = pstrdup(portal->sourceText);
01836 if (portal->prepStmtName)
01837 prepStmtName = pstrdup(portal->prepStmtName);
01838 else
01839 prepStmtName = "<unnamed>";
01840
01841
01842
01843
01844
01845 portalParams = NULL;
01846 }
01847 else
01848 {
01849 sourceText = portal->sourceText;
01850 if (portal->prepStmtName)
01851 prepStmtName = portal->prepStmtName;
01852 else
01853 prepStmtName = "<unnamed>";
01854 portalParams = portal->portalParams;
01855 }
01856
01857
01858
01859
01860 debug_query_string = sourceText;
01861
01862 pgstat_report_activity(STATE_RUNNING, sourceText);
01863
01864 set_ps_display(portal->commandTag, false);
01865
01866 if (save_log_statement_stats)
01867 ResetUsage();
01868
01869 BeginCommand(portal->commandTag, dest);
01870
01871
01872
01873
01874
01875 receiver = CreateDestReceiver(dest);
01876 if (dest == DestRemoteExecute)
01877 SetRemoteDestReceiverParams(receiver, portal);
01878
01879
01880
01881
01882
01883 start_xact_command();
01884
01885
01886
01887
01888
01889
01890
01891 execute_is_fetch = !portal->atStart;
01892
01893
01894 if (check_log_statement(portal->stmts))
01895 {
01896 ereport(LOG,
01897 (errmsg("%s %s%s%s: %s",
01898 execute_is_fetch ?
01899 _("execute fetch from") :
01900 _("execute"),
01901 prepStmtName,
01902 *portal_name ? "/" : "",
01903 *portal_name ? portal_name : "",
01904 sourceText),
01905 errhidestmt(true),
01906 errdetail_params(portalParams)));
01907 was_logged = true;
01908 }
01909
01910
01911
01912
01913
01914 if (IsAbortedTransactionBlockState() &&
01915 !IsTransactionExitStmtList(portal->stmts))
01916 ereport(ERROR,
01917 (errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
01918 errmsg("current transaction is aborted, "
01919 "commands ignored until end of transaction block"),
01920 errdetail_abort()));
01921
01922
01923 CHECK_FOR_INTERRUPTS();
01924
01925
01926
01927
01928 if (max_rows <= 0)
01929 max_rows = FETCH_ALL;
01930
01931 completed = PortalRun(portal,
01932 max_rows,
01933 true,
01934 receiver,
01935 receiver,
01936 completionTag);
01937
01938 (*receiver->rDestroy) (receiver);
01939
01940 if (completed)
01941 {
01942 if (is_xact_command)
01943 {
01944
01945
01946
01947
01948 finish_xact_command();
01949 }
01950 else
01951 {
01952
01953
01954
01955
01956 CommandCounterIncrement();
01957 }
01958
01959
01960 EndCommand(completionTag, dest);
01961 }
01962 else
01963 {
01964
01965 if (whereToSendOutput == DestRemote)
01966 pq_putemptymessage('s');
01967 }
01968
01969
01970
01971
01972 switch (check_log_duration(msec_str, was_logged))
01973 {
01974 case 1:
01975 ereport(LOG,
01976 (errmsg("duration: %s ms", msec_str),
01977 errhidestmt(true)));
01978 break;
01979 case 2:
01980 ereport(LOG,
01981 (errmsg("duration: %s ms %s %s%s%s: %s",
01982 msec_str,
01983 execute_is_fetch ?
01984 _("execute fetch from") :
01985 _("execute"),
01986 prepStmtName,
01987 *portal_name ? "/" : "",
01988 *portal_name ? portal_name : "",
01989 sourceText),
01990 errhidestmt(true),
01991 errdetail_params(portalParams)));
01992 break;
01993 }
01994
01995 if (save_log_statement_stats)
01996 ShowUsage("EXECUTE MESSAGE STATISTICS");
01997
01998 debug_query_string = NULL;
01999 }
02000
02001
02002
02003
02004
02005
02006
02007
02008 static bool
02009 check_log_statement(List *stmt_list)
02010 {
02011 ListCell *stmt_item;
02012
02013 if (log_statement == LOGSTMT_NONE)
02014 return false;
02015 if (log_statement == LOGSTMT_ALL)
02016 return true;
02017
02018
02019 foreach(stmt_item, stmt_list)
02020 {
02021 Node *stmt = (Node *) lfirst(stmt_item);
02022
02023 if (GetCommandLogLevel(stmt) <= log_statement)
02024 return true;
02025 }
02026
02027 return false;
02028 }
02029
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045 int
02046 check_log_duration(char *msec_str, bool was_logged)
02047 {
02048 if (log_duration || log_min_duration_statement >= 0)
02049 {
02050 long secs;
02051 int usecs;
02052 int msecs;
02053 bool exceeded;
02054
02055 TimestampDifference(GetCurrentStatementStartTimestamp(),
02056 GetCurrentTimestamp(),
02057 &secs, &usecs);
02058 msecs = usecs / 1000;
02059
02060
02061
02062
02063
02064
02065 exceeded = (log_min_duration_statement == 0 ||
02066 (log_min_duration_statement > 0 &&
02067 (secs > log_min_duration_statement / 1000 ||
02068 secs * 1000 + msecs >= log_min_duration_statement)));
02069
02070 if (exceeded || log_duration)
02071 {
02072 snprintf(msec_str, 32, "%ld.%03d",
02073 secs * 1000 + msecs, usecs % 1000);
02074 if (exceeded && !was_logged)
02075 return 2;
02076 else
02077 return 1;
02078 }
02079 }
02080
02081 return 0;
02082 }
02083
02084
02085
02086
02087
02088
02089
02090 static int
02091 errdetail_execute(List *raw_parsetree_list)
02092 {
02093 ListCell *parsetree_item;
02094
02095 foreach(parsetree_item, raw_parsetree_list)
02096 {
02097 Node *parsetree = (Node *) lfirst(parsetree_item);
02098
02099 if (IsA(parsetree, ExecuteStmt))
02100 {
02101 ExecuteStmt *stmt = (ExecuteStmt *) parsetree;
02102 PreparedStatement *pstmt;
02103
02104 pstmt = FetchPreparedStatement(stmt->name, false);
02105 if (pstmt)
02106 {
02107 errdetail("prepare: %s", pstmt->plansource->query_string);
02108 return 0;
02109 }
02110 }
02111 }
02112
02113 return 0;
02114 }
02115
02116
02117
02118
02119
02120
02121 static int
02122 errdetail_params(ParamListInfo params)
02123 {
02124
02125 if (params && params->numParams > 0 && !IsAbortedTransactionBlockState())
02126 {
02127 StringInfoData param_str;
02128 MemoryContext oldcontext;
02129 int paramno;
02130
02131
02132 oldcontext = MemoryContextSwitchTo(MessageContext);
02133
02134 initStringInfo(¶m_str);
02135
02136 for (paramno = 0; paramno < params->numParams; paramno++)
02137 {
02138 ParamExternData *prm = ¶ms->params[paramno];
02139 Oid typoutput;
02140 bool typisvarlena;
02141 char *pstring;
02142 char *p;
02143
02144 appendStringInfo(¶m_str, "%s$%d = ",
02145 paramno > 0 ? ", " : "",
02146 paramno + 1);
02147
02148 if (prm->isnull || !OidIsValid(prm->ptype))
02149 {
02150 appendStringInfoString(¶m_str, "NULL");
02151 continue;
02152 }
02153
02154 getTypeOutputInfo(prm->ptype, &typoutput, &typisvarlena);
02155
02156 pstring = OidOutputFunctionCall(typoutput, prm->value);
02157
02158 appendStringInfoCharMacro(¶m_str, '\'');
02159 for (p = pstring; *p; p++)
02160 {
02161 if (*p == '\'')
02162 appendStringInfoCharMacro(¶m_str, *p);
02163 appendStringInfoCharMacro(¶m_str, *p);
02164 }
02165 appendStringInfoCharMacro(¶m_str, '\'');
02166
02167 pfree(pstring);
02168 }
02169
02170 errdetail("parameters: %s", param_str.data);
02171
02172 pfree(param_str.data);
02173
02174 MemoryContextSwitchTo(oldcontext);
02175 }
02176
02177 return 0;
02178 }
02179
02180
02181
02182
02183
02184
02185 static int
02186 errdetail_abort(void)
02187 {
02188 if (MyProc->recoveryConflictPending)
02189 errdetail("abort reason: recovery conflict");
02190
02191 return 0;
02192 }
02193
02194
02195
02196
02197
02198
02199 static int
02200 errdetail_recovery_conflict(void)
02201 {
02202 switch (RecoveryConflictReason)
02203 {
02204 case PROCSIG_RECOVERY_CONFLICT_BUFFERPIN:
02205 errdetail("User was holding shared buffer pin for too long.");
02206 break;
02207 case PROCSIG_RECOVERY_CONFLICT_LOCK:
02208 errdetail("User was holding a relation lock for too long.");
02209 break;
02210 case PROCSIG_RECOVERY_CONFLICT_TABLESPACE:
02211 errdetail("User was or might have been using tablespace that must be dropped.");
02212 break;
02213 case PROCSIG_RECOVERY_CONFLICT_SNAPSHOT:
02214 errdetail("User query might have needed to see row versions that must be removed.");
02215 break;
02216 case PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK:
02217 errdetail("User transaction caused buffer deadlock with recovery.");
02218 break;
02219 case PROCSIG_RECOVERY_CONFLICT_DATABASE:
02220 errdetail("User was connected to a database that must be dropped.");
02221 break;
02222 default:
02223 break;
02224
02225 }
02226
02227 return 0;
02228 }
02229
02230
02231
02232
02233
02234
02235 static void
02236 exec_describe_statement_message(const char *stmt_name)
02237 {
02238 CachedPlanSource *psrc;
02239 StringInfoData buf;
02240 int i;
02241
02242
02243
02244
02245
02246 start_xact_command();
02247
02248
02249 MemoryContextSwitchTo(MessageContext);
02250
02251
02252 if (stmt_name[0] != '\0')
02253 {
02254 PreparedStatement *pstmt;
02255
02256 pstmt = FetchPreparedStatement(stmt_name, true);
02257 psrc = pstmt->plansource;
02258 }
02259 else
02260 {
02261
02262 psrc = unnamed_stmt_psrc;
02263 if (!psrc)
02264 ereport(ERROR,
02265 (errcode(ERRCODE_UNDEFINED_PSTATEMENT),
02266 errmsg("unnamed prepared statement does not exist")));
02267 }
02268
02269
02270 Assert(psrc->fixed_result);
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281 if (IsAbortedTransactionBlockState() &&
02282 psrc->resultDesc)
02283 ereport(ERROR,
02284 (errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
02285 errmsg("current transaction is aborted, "
02286 "commands ignored until end of transaction block"),
02287 errdetail_abort()));
02288
02289 if (whereToSendOutput != DestRemote)
02290 return;
02291
02292
02293
02294
02295 pq_beginmessage(&buf, 't');
02296 pq_sendint(&buf, psrc->num_params, 2);
02297
02298 for (i = 0; i < psrc->num_params; i++)
02299 {
02300 Oid ptype = psrc->param_types[i];
02301
02302 pq_sendint(&buf, (int) ptype, 4);
02303 }
02304 pq_endmessage(&buf);
02305
02306
02307
02308
02309 if (psrc->resultDesc)
02310 {
02311 List *tlist;
02312
02313
02314 tlist = CachedPlanGetTargetList(psrc);
02315
02316 SendRowDescriptionMessage(psrc->resultDesc, tlist, NULL);
02317 }
02318 else
02319 pq_putemptymessage('n');
02320
02321 }
02322
02323
02324
02325
02326
02327
02328 static void
02329 exec_describe_portal_message(const char *portal_name)
02330 {
02331 Portal portal;
02332
02333
02334
02335
02336
02337 start_xact_command();
02338
02339
02340 MemoryContextSwitchTo(MessageContext);
02341
02342 portal = GetPortalByName(portal_name);
02343 if (!PortalIsValid(portal))
02344 ereport(ERROR,
02345 (errcode(ERRCODE_UNDEFINED_CURSOR),
02346 errmsg("portal \"%s\" does not exist", portal_name)));
02347
02348
02349
02350
02351
02352
02353
02354
02355
02356 if (IsAbortedTransactionBlockState() &&
02357 portal->tupDesc)
02358 ereport(ERROR,
02359 (errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
02360 errmsg("current transaction is aborted, "
02361 "commands ignored until end of transaction block"),
02362 errdetail_abort()));
02363
02364 if (whereToSendOutput != DestRemote)
02365 return;
02366
02367 if (portal->tupDesc)
02368 SendRowDescriptionMessage(portal->tupDesc,
02369 FetchPortalTargetList(portal),
02370 portal->formats);
02371 else
02372 pq_putemptymessage('n');
02373 }
02374
02375
02376
02377
02378
02379 static void
02380 start_xact_command(void)
02381 {
02382 if (!xact_started)
02383 {
02384 ereport(DEBUG3,
02385 (errmsg_internal("StartTransactionCommand")));
02386 StartTransactionCommand();
02387
02388
02389
02390 if (StatementTimeout > 0)
02391 enable_timeout_after(STATEMENT_TIMEOUT, StatementTimeout);
02392 else
02393 disable_timeout(STATEMENT_TIMEOUT, false);
02394
02395 xact_started = true;
02396 }
02397 }
02398
02399 static void
02400 finish_xact_command(void)
02401 {
02402 if (xact_started)
02403 {
02404
02405 disable_timeout(STATEMENT_TIMEOUT, false);
02406
02407
02408 ereport(DEBUG3,
02409 (errmsg_internal("CommitTransactionCommand")));
02410
02411 CommitTransactionCommand();
02412
02413 #ifdef MEMORY_CONTEXT_CHECKING
02414
02415
02416 MemoryContextCheck(TopMemoryContext);
02417 #endif
02418
02419 #ifdef SHOW_MEMORY_STATS
02420
02421 MemoryContextStats(TopMemoryContext);
02422 #endif
02423
02424 xact_started = false;
02425 }
02426 }
02427
02428
02429
02430
02431
02432
02433
02434
02435 static bool
02436 IsTransactionExitStmt(Node *parsetree)
02437 {
02438 if (parsetree && IsA(parsetree, TransactionStmt))
02439 {
02440 TransactionStmt *stmt = (TransactionStmt *) parsetree;
02441
02442 if (stmt->kind == TRANS_STMT_COMMIT ||
02443 stmt->kind == TRANS_STMT_PREPARE ||
02444 stmt->kind == TRANS_STMT_ROLLBACK ||
02445 stmt->kind == TRANS_STMT_ROLLBACK_TO)
02446 return true;
02447 }
02448 return false;
02449 }
02450
02451
02452 static bool
02453 IsTransactionExitStmtList(List *parseTrees)
02454 {
02455 if (list_length(parseTrees) == 1)
02456 {
02457 Node *stmt = (Node *) linitial(parseTrees);
02458
02459 if (IsA(stmt, Query))
02460 {
02461 Query *query = (Query *) stmt;
02462
02463 if (query->commandType == CMD_UTILITY &&
02464 IsTransactionExitStmt(query->utilityStmt))
02465 return true;
02466 }
02467 else if (IsTransactionExitStmt(stmt))
02468 return true;
02469 }
02470 return false;
02471 }
02472
02473
02474 static bool
02475 IsTransactionStmtList(List *parseTrees)
02476 {
02477 if (list_length(parseTrees) == 1)
02478 {
02479 Node *stmt = (Node *) linitial(parseTrees);
02480
02481 if (IsA(stmt, Query))
02482 {
02483 Query *query = (Query *) stmt;
02484
02485 if (query->commandType == CMD_UTILITY &&
02486 IsA(query->utilityStmt, TransactionStmt))
02487 return true;
02488 }
02489 else if (IsA(stmt, TransactionStmt))
02490 return true;
02491 }
02492 return false;
02493 }
02494
02495
02496 static void
02497 drop_unnamed_stmt(void)
02498 {
02499
02500 if (unnamed_stmt_psrc)
02501 {
02502 CachedPlanSource *psrc = unnamed_stmt_psrc;
02503
02504 unnamed_stmt_psrc = NULL;
02505 DropCachedPlan(psrc);
02506 }
02507 }
02508
02509
02510
02511
02512
02513
02514
02515
02516
02517
02518
02519
02520
02521 void
02522 quickdie(SIGNAL_ARGS)
02523 {
02524 sigaddset(&BlockSig, SIGQUIT);
02525 PG_SETMASK(&BlockSig);
02526
02527
02528
02529
02530
02531
02532
02533 if (ClientAuthInProgress && whereToSendOutput == DestRemote)
02534 whereToSendOutput = DestNone;
02535
02536
02537
02538
02539
02540 ereport(WARNING,
02541 (errcode(ERRCODE_CRASH_SHUTDOWN),
02542 errmsg("terminating connection because of crash of another server process"),
02543 errdetail("The postmaster has commanded this server process to roll back"
02544 " the current transaction and exit, because another"
02545 " server process exited abnormally and possibly corrupted"
02546 " shared memory."),
02547 errhint("In a moment you should be able to reconnect to the"
02548 " database and repeat your command.")));
02549
02550
02551
02552
02553
02554
02555
02556
02557
02558 on_exit_reset();
02559
02560
02561
02562
02563
02564
02565
02566
02567
02568 exit(2);
02569 }
02570
02571
02572
02573
02574
02575 void
02576 die(SIGNAL_ARGS)
02577 {
02578 int save_errno = errno;
02579
02580
02581 if (!proc_exit_inprogress)
02582 {
02583 InterruptPending = true;
02584 ProcDiePending = true;
02585
02586
02587
02588
02589
02590 if (ImmediateInterruptOK && InterruptHoldoffCount == 0 &&
02591 CritSectionCount == 0)
02592 {
02593
02594
02595 InterruptHoldoffCount++;
02596 LockErrorCleanup();
02597 DisableNotifyInterrupt();
02598 DisableCatchupInterrupt();
02599 InterruptHoldoffCount--;
02600 ProcessInterrupts();
02601 }
02602 }
02603
02604
02605 if (MyProc)
02606 SetLatch(&MyProc->procLatch);
02607
02608 errno = save_errno;
02609 }
02610
02611
02612
02613
02614
02615 void
02616 StatementCancelHandler(SIGNAL_ARGS)
02617 {
02618 int save_errno = errno;
02619
02620
02621
02622
02623 if (!proc_exit_inprogress)
02624 {
02625 InterruptPending = true;
02626 QueryCancelPending = true;
02627
02628
02629
02630
02631
02632 if (ImmediateInterruptOK && InterruptHoldoffCount == 0 &&
02633 CritSectionCount == 0)
02634 {
02635
02636
02637 InterruptHoldoffCount++;
02638 LockErrorCleanup();
02639 DisableNotifyInterrupt();
02640 DisableCatchupInterrupt();
02641 InterruptHoldoffCount--;
02642 ProcessInterrupts();
02643 }
02644 }
02645
02646
02647 if (MyProc)
02648 SetLatch(&MyProc->procLatch);
02649
02650 errno = save_errno;
02651 }
02652
02653
02654 void
02655 FloatExceptionHandler(SIGNAL_ARGS)
02656 {
02657
02658 ereport(ERROR,
02659 (errcode(ERRCODE_FLOATING_POINT_EXCEPTION),
02660 errmsg("floating-point exception"),
02661 errdetail("An invalid floating-point operation was signaled. "
02662 "This probably means an out-of-range result or an "
02663 "invalid operation, such as division by zero.")));
02664 }
02665
02666
02667 static void
02668 SigHupHandler(SIGNAL_ARGS)
02669 {
02670 int save_errno = errno;
02671
02672 got_SIGHUP = true;
02673 if (MyProc)
02674 SetLatch(&MyProc->procLatch);
02675
02676 errno = save_errno;
02677 }
02678
02679
02680
02681
02682
02683
02684
02685 void
02686 RecoveryConflictInterrupt(ProcSignalReason reason)
02687 {
02688 int save_errno = errno;
02689
02690
02691
02692
02693 if (!proc_exit_inprogress)
02694 {
02695 RecoveryConflictReason = reason;
02696 switch (reason)
02697 {
02698 case PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK:
02699
02700
02701
02702
02703 if (!IsWaitingForLock())
02704 return;
02705
02706
02707
02708 case PROCSIG_RECOVERY_CONFLICT_BUFFERPIN:
02709
02710
02711
02712
02713
02714 if (!HoldingBufferPinThatDelaysRecovery())
02715 return;
02716
02717 MyProc->recoveryConflictPending = true;
02718
02719
02720
02721 case PROCSIG_RECOVERY_CONFLICT_LOCK:
02722 case PROCSIG_RECOVERY_CONFLICT_TABLESPACE:
02723 case PROCSIG_RECOVERY_CONFLICT_SNAPSHOT:
02724
02725
02726
02727
02728 if (!IsTransactionOrTransactionBlock())
02729 return;
02730
02731
02732
02733
02734
02735
02736
02737
02738
02739
02740
02741
02742
02743
02744
02745
02746
02747 if (!IsSubTransaction())
02748 {
02749
02750
02751
02752
02753
02754 if (IsAbortedTransactionBlockState())
02755 return;
02756
02757 RecoveryConflictPending = true;
02758 QueryCancelPending = true;
02759 InterruptPending = true;
02760 break;
02761 }
02762
02763
02764
02765 case PROCSIG_RECOVERY_CONFLICT_DATABASE:
02766 RecoveryConflictPending = true;
02767 ProcDiePending = true;
02768 InterruptPending = true;
02769 break;
02770
02771 default:
02772 elog(FATAL, "unrecognized conflict mode: %d",
02773 (int) reason);
02774 }
02775
02776 Assert(RecoveryConflictPending && (QueryCancelPending || ProcDiePending));
02777
02778
02779
02780
02781
02782
02783
02784 if (reason == PROCSIG_RECOVERY_CONFLICT_DATABASE)
02785 RecoveryConflictRetryable = false;
02786
02787
02788
02789
02790
02791 if (ImmediateInterruptOK && InterruptHoldoffCount == 0 &&
02792 CritSectionCount == 0)
02793 {
02794
02795
02796 InterruptHoldoffCount++;
02797 LockErrorCleanup();
02798 DisableNotifyInterrupt();
02799 DisableCatchupInterrupt();
02800 InterruptHoldoffCount--;
02801 ProcessInterrupts();
02802 }
02803 }
02804
02805 errno = save_errno;
02806 }
02807
02808
02809
02810
02811
02812
02813
02814
02815 void
02816 ProcessInterrupts(void)
02817 {
02818
02819 if (InterruptHoldoffCount != 0 || CritSectionCount != 0)
02820 return;
02821 InterruptPending = false;
02822 if (ProcDiePending)
02823 {
02824 ProcDiePending = false;
02825 QueryCancelPending = false;
02826 ImmediateInterruptOK = false;
02827 DisableNotifyInterrupt();
02828 DisableCatchupInterrupt();
02829
02830 if (ClientAuthInProgress && whereToSendOutput == DestRemote)
02831 whereToSendOutput = DestNone;
02832 if (IsAutoVacuumWorkerProcess())
02833 ereport(FATAL,
02834 (errcode(ERRCODE_ADMIN_SHUTDOWN),
02835 errmsg("terminating autovacuum process due to administrator command")));
02836 else if (RecoveryConflictPending && RecoveryConflictRetryable)
02837 {
02838 pgstat_report_recovery_conflict(RecoveryConflictReason);
02839 ereport(FATAL,
02840 (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
02841 errmsg("terminating connection due to conflict with recovery"),
02842 errdetail_recovery_conflict()));
02843 }
02844 else if (RecoveryConflictPending)
02845 {
02846
02847 Assert(RecoveryConflictReason == PROCSIG_RECOVERY_CONFLICT_DATABASE);
02848 pgstat_report_recovery_conflict(RecoveryConflictReason);
02849 ereport(FATAL,
02850 (errcode(ERRCODE_DATABASE_DROPPED),
02851 errmsg("terminating connection due to conflict with recovery"),
02852 errdetail_recovery_conflict()));
02853 }
02854 else
02855 ereport(FATAL,
02856 (errcode(ERRCODE_ADMIN_SHUTDOWN),
02857 errmsg("terminating connection due to administrator command")));
02858 }
02859 if (ClientConnectionLost)
02860 {
02861 QueryCancelPending = false;
02862 ImmediateInterruptOK = false;
02863 DisableNotifyInterrupt();
02864 DisableCatchupInterrupt();
02865
02866 whereToSendOutput = DestNone;
02867 ereport(FATAL,
02868 (errcode(ERRCODE_CONNECTION_FAILURE),
02869 errmsg("connection to client lost")));
02870 }
02871 if (QueryCancelPending)
02872 {
02873 QueryCancelPending = false;
02874 if (ClientAuthInProgress)
02875 {
02876 ImmediateInterruptOK = false;
02877 DisableNotifyInterrupt();
02878 DisableCatchupInterrupt();
02879
02880 if (whereToSendOutput == DestRemote)
02881 whereToSendOutput = DestNone;
02882 ereport(ERROR,
02883 (errcode(ERRCODE_QUERY_CANCELED),
02884 errmsg("canceling authentication due to timeout")));
02885 }
02886
02887
02888
02889
02890
02891 if (get_timeout_indicator(LOCK_TIMEOUT, true))
02892 {
02893 ImmediateInterruptOK = false;
02894 (void) get_timeout_indicator(STATEMENT_TIMEOUT, true);
02895 DisableNotifyInterrupt();
02896 DisableCatchupInterrupt();
02897 ereport(ERROR,
02898 (errcode(ERRCODE_QUERY_CANCELED),
02899 errmsg("canceling statement due to lock timeout")));
02900 }
02901 if (get_timeout_indicator(STATEMENT_TIMEOUT, true))
02902 {
02903 ImmediateInterruptOK = false;
02904 DisableNotifyInterrupt();
02905 DisableCatchupInterrupt();
02906 ereport(ERROR,
02907 (errcode(ERRCODE_QUERY_CANCELED),
02908 errmsg("canceling statement due to statement timeout")));
02909 }
02910 if (IsAutoVacuumWorkerProcess())
02911 {
02912 ImmediateInterruptOK = false;
02913 DisableNotifyInterrupt();
02914 DisableCatchupInterrupt();
02915 ereport(ERROR,
02916 (errcode(ERRCODE_QUERY_CANCELED),
02917 errmsg("canceling autovacuum task")));
02918 }
02919 if (RecoveryConflictPending)
02920 {
02921 ImmediateInterruptOK = false;
02922 RecoveryConflictPending = false;
02923 DisableNotifyInterrupt();
02924 DisableCatchupInterrupt();
02925 pgstat_report_recovery_conflict(RecoveryConflictReason);
02926 if (DoingCommandRead)
02927 ereport(FATAL,
02928 (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
02929 errmsg("terminating connection due to conflict with recovery"),
02930 errdetail_recovery_conflict(),
02931 errhint("In a moment you should be able to reconnect to the"
02932 " database and repeat your command.")));
02933 else
02934 ereport(ERROR,
02935 (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
02936 errmsg("canceling statement due to conflict with recovery"),
02937 errdetail_recovery_conflict()));
02938 }
02939
02940
02941
02942
02943
02944
02945 if (!DoingCommandRead)
02946 {
02947 ImmediateInterruptOK = false;
02948 DisableNotifyInterrupt();
02949 DisableCatchupInterrupt();
02950 ereport(ERROR,
02951 (errcode(ERRCODE_QUERY_CANCELED),
02952 errmsg("canceling statement due to user request")));
02953 }
02954 }
02955
02956 }
02957
02958
02959
02960
02961
02962
02963
02964 #if defined(__ia64__) || defined(__ia64)
02965
02966 #if defined(__hpux) && !defined(__GNUC__) && !defined __INTEL_COMPILER
02967 #include <ia64/sys/inline.h>
02968 #define ia64_get_bsp() ((char *) (_Asm_mov_from_ar(_AREG_BSP, _NO_FENCE)))
02969 #else
02970
02971 #ifdef __INTEL_COMPILER
02972 #include <asm/ia64regs.h>
02973 #endif
02974
02975 static __inline__ char *
02976 ia64_get_bsp(void)
02977 {
02978 char *ret;
02979
02980 #ifndef __INTEL_COMPILER
02981
02982 __asm__ __volatile__(
02983 ";;\n"
02984 " mov %0=ar.bsp \n"
02985 : "=r"(ret));
02986 #else
02987 ret = (char *) __getReg(_IA64_REG_AR_BSP);
02988 #endif
02989 return ret;
02990 }
02991 #endif
02992 #endif
02993
02994
02995
02996
02997
02998
02999
03000 pg_stack_base_t
03001 set_stack_base(void)
03002 {
03003 char stack_base;
03004 pg_stack_base_t old;
03005
03006 #if defined(__ia64__) || defined(__ia64)
03007 old.stack_base_ptr = stack_base_ptr;
03008 old.register_stack_base_ptr = register_stack_base_ptr;
03009 #else
03010 old = stack_base_ptr;
03011 #endif
03012
03013
03014 stack_base_ptr = &stack_base;
03015 #if defined(__ia64__) || defined(__ia64)
03016 register_stack_base_ptr = ia64_get_bsp();
03017 #endif
03018
03019 return old;
03020 }
03021
03022
03023
03024
03025
03026
03027
03028
03029
03030
03031 void
03032 restore_stack_base(pg_stack_base_t base)
03033 {
03034 #if defined(__ia64__) || defined(__ia64)
03035 stack_base_ptr = base.stack_base_ptr;
03036 register_stack_base_ptr = base.register_stack_base_ptr;
03037 #else
03038 stack_base_ptr = base;
03039 #endif
03040 }
03041
03042
03043
03044
03045
03046
03047
03048
03049
03050 void
03051 check_stack_depth(void)
03052 {
03053 char stack_top_loc;
03054 long stack_depth;
03055
03056
03057
03058
03059 stack_depth = (long) (stack_base_ptr - &stack_top_loc);
03060
03061
03062
03063
03064 if (stack_depth < 0)
03065 stack_depth = -stack_depth;
03066
03067
03068
03069
03070
03071
03072
03073
03074
03075 if (stack_depth > max_stack_depth_bytes &&
03076 stack_base_ptr != NULL)
03077 {
03078 ereport(ERROR,
03079 (errcode(ERRCODE_STATEMENT_TOO_COMPLEX),
03080 errmsg("stack depth limit exceeded"),
03081 errhint("Increase the configuration parameter \"max_stack_depth\" (currently %dkB), "
03082 "after ensuring the platform's stack depth limit is adequate.",
03083 max_stack_depth)));
03084 }
03085
03086
03087
03088
03089
03090
03091
03092
03093
03094 #if defined(__ia64__) || defined(__ia64)
03095 stack_depth = (long) (ia64_get_bsp() - register_stack_base_ptr);
03096
03097 if (stack_depth > max_stack_depth_bytes &&
03098 register_stack_base_ptr != NULL)
03099 {
03100 ereport(ERROR,
03101 (errcode(ERRCODE_STATEMENT_TOO_COMPLEX),
03102 errmsg("stack depth limit exceeded"),
03103 errhint("Increase the configuration parameter \"max_stack_depth\" (currently %dkB), "
03104 "after ensuring the platform's stack depth limit is adequate.",
03105 max_stack_depth)));
03106 }
03107 #endif
03108 }
03109
03110
03111 bool
03112 check_max_stack_depth(int *newval, void **extra, GucSource source)
03113 {
03114 long newval_bytes = *newval * 1024L;
03115 long stack_rlimit = get_stack_depth_rlimit();
03116
03117 if (stack_rlimit > 0 && newval_bytes > stack_rlimit - STACK_DEPTH_SLOP)
03118 {
03119 GUC_check_errdetail("\"max_stack_depth\" must not exceed %ldkB.",
03120 (stack_rlimit - STACK_DEPTH_SLOP) / 1024L);
03121 GUC_check_errhint("Increase the platform's stack depth limit via \"ulimit -s\" or local equivalent.");
03122 return false;
03123 }
03124 return true;
03125 }
03126
03127
03128 void
03129 assign_max_stack_depth(int newval, void *extra)
03130 {
03131 long newval_bytes = newval * 1024L;
03132
03133 max_stack_depth_bytes = newval_bytes;
03134 }
03135
03136
03137
03138
03139
03140
03141
03142
03143 void
03144 set_debug_options(int debug_flag, GucContext context, GucSource source)
03145 {
03146 if (debug_flag > 0)
03147 {
03148 char debugstr[64];
03149
03150 sprintf(debugstr, "debug%d", debug_flag);
03151 SetConfigOption("log_min_messages", debugstr, context, source);
03152 }
03153 else
03154 SetConfigOption("log_min_messages", "notice", context, source);
03155
03156 if (debug_flag >= 1 && context == PGC_POSTMASTER)
03157 {
03158 SetConfigOption("log_connections", "true", context, source);
03159 SetConfigOption("log_disconnections", "true", context, source);
03160 }
03161 if (debug_flag >= 2)
03162 SetConfigOption("log_statement", "all", context, source);
03163 if (debug_flag >= 3)
03164 SetConfigOption("debug_print_parse", "true", context, source);
03165 if (debug_flag >= 4)
03166 SetConfigOption("debug_print_plan", "true", context, source);
03167 if (debug_flag >= 5)
03168 SetConfigOption("debug_print_rewritten", "true", context, source);
03169 }
03170
03171
03172 bool
03173 set_plan_disabling_options(const char *arg, GucContext context, GucSource source)
03174 {
03175 const char *tmp = NULL;
03176
03177 switch (arg[0])
03178 {
03179 case 's':
03180 tmp = "enable_seqscan";
03181 break;
03182 case 'i':
03183 tmp = "enable_indexscan";
03184 break;
03185 case 'o':
03186 tmp = "enable_indexonlyscan";
03187 break;
03188 case 'b':
03189 tmp = "enable_bitmapscan";
03190 break;
03191 case 't':
03192 tmp = "enable_tidscan";
03193 break;
03194 case 'n':
03195 tmp = "enable_nestloop";
03196 break;
03197 case 'm':
03198 tmp = "enable_mergejoin";
03199 break;
03200 case 'h':
03201 tmp = "enable_hashjoin";
03202 break;
03203 }
03204 if (tmp)
03205 {
03206 SetConfigOption(tmp, "false", context, source);
03207 return true;
03208 }
03209 else
03210 return false;
03211 }
03212
03213
03214 const char *
03215 get_stats_option_name(const char *arg)
03216 {
03217 switch (arg[0])
03218 {
03219 case 'p':
03220 if (optarg[1] == 'a')
03221 return "log_parser_stats";
03222 else if (optarg[1] == 'l')
03223 return "log_planner_stats";
03224 break;
03225
03226 case 'e':
03227 return "log_executor_stats";
03228 break;
03229 }
03230
03231 return NULL;
03232 }
03233
03234
03235
03236
03237
03238
03239
03240
03241
03242
03243
03244
03245
03246
03247
03248
03249
03250
03251
03252
03253
03254 void
03255 process_postgres_switches(int argc, char *argv[], GucContext ctx,
03256 const char **dbname)
03257 {
03258 bool secure = (ctx == PGC_POSTMASTER);
03259 int errs = 0;
03260 GucSource gucsource;
03261 int flag;
03262
03263 if (secure)
03264 {
03265 gucsource = PGC_S_ARGV;
03266
03267
03268 if (argc > 1 && strcmp(argv[1], "--single") == 0)
03269 {
03270 argv++;
03271 argc--;
03272 }
03273 }
03274 else
03275 {
03276 gucsource = PGC_S_CLIENT;
03277 }
03278
03279 #ifdef HAVE_INT_OPTERR
03280
03281
03282
03283
03284
03285
03286 opterr = 0;
03287 #endif
03288
03289
03290
03291
03292
03293
03294 while ((flag = getopt(argc, argv, "A:B:bc:C:D:d:EeFf:h:ijk:lN:nOo:Pp:r:S:sTt:v:W:-:")) != -1)
03295 {
03296 switch (flag)
03297 {
03298 case 'A':
03299 SetConfigOption("debug_assertions", optarg, ctx, gucsource);
03300 break;
03301
03302 case 'B':
03303 SetConfigOption("shared_buffers", optarg, ctx, gucsource);
03304 break;
03305
03306 case 'b':
03307
03308 if (secure)
03309 IsBinaryUpgrade = true;
03310 break;
03311
03312 case 'C':
03313
03314 break;
03315
03316 case 'D':
03317 if (secure)
03318 userDoption = strdup(optarg);
03319 break;
03320
03321 case 'd':
03322 set_debug_options(atoi(optarg), ctx, gucsource);
03323 break;
03324
03325 case 'E':
03326 if (secure)
03327 EchoQuery = true;
03328 break;
03329
03330 case 'e':
03331 SetConfigOption("datestyle", "euro", ctx, gucsource);
03332 break;
03333
03334 case 'F':
03335 SetConfigOption("fsync", "false", ctx, gucsource);
03336 break;
03337
03338 case 'f':
03339 if (!set_plan_disabling_options(optarg, ctx, gucsource))
03340 errs++;
03341 break;
03342
03343 case 'h':
03344 SetConfigOption("listen_addresses", optarg, ctx, gucsource);
03345 break;
03346
03347 case 'i':
03348 SetConfigOption("listen_addresses", "*", ctx, gucsource);
03349 break;
03350
03351 case 'j':
03352 if (secure)
03353 UseNewLine = 0;
03354 break;
03355
03356 case 'k':
03357 SetConfigOption("unix_socket_directories", optarg, ctx, gucsource);
03358 break;
03359
03360 case 'l':
03361 SetConfigOption("ssl", "true", ctx, gucsource);
03362 break;
03363
03364 case 'N':
03365 SetConfigOption("max_connections", optarg, ctx, gucsource);
03366 break;
03367
03368 case 'n':
03369
03370 break;
03371
03372 case 'O':
03373 SetConfigOption("allow_system_table_mods", "true", ctx, gucsource);
03374 break;
03375
03376 case 'o':
03377 errs++;
03378 break;
03379
03380 case 'P':
03381 SetConfigOption("ignore_system_indexes", "true", ctx, gucsource);
03382 break;
03383
03384 case 'p':
03385 SetConfigOption("port", optarg, ctx, gucsource);
03386 break;
03387
03388 case 'r':
03389
03390 if (secure)
03391 strlcpy(OutputFileName, optarg, MAXPGPATH);
03392 break;
03393
03394 case 'S':
03395 SetConfigOption("work_mem", optarg, ctx, gucsource);
03396 break;
03397
03398 case 's':
03399 SetConfigOption("log_statement_stats", "true", ctx, gucsource);
03400 break;
03401
03402 case 'T':
03403
03404 break;
03405
03406 case 't':
03407 {
03408 const char *tmp = get_stats_option_name(optarg);
03409
03410 if (tmp)
03411 SetConfigOption(tmp, "true", ctx, gucsource);
03412 else
03413 errs++;
03414 break;
03415 }
03416
03417 case 'v':
03418
03419
03420
03421
03422
03423
03424
03425
03426 if (secure)
03427 FrontendProtocol = (ProtocolVersion) atoi(optarg);
03428 break;
03429
03430 case 'W':
03431 SetConfigOption("post_auth_delay", optarg, ctx, gucsource);
03432 break;
03433
03434 case 'c':
03435 case '-':
03436 {
03437 char *name,
03438 *value;
03439
03440 ParseLongOption(optarg, &name, &value);
03441 if (!value)
03442 {
03443 if (flag == '-')
03444 ereport(ERROR,
03445 (errcode(ERRCODE_SYNTAX_ERROR),
03446 errmsg("--%s requires a value",
03447 optarg)));
03448 else
03449 ereport(ERROR,
03450 (errcode(ERRCODE_SYNTAX_ERROR),
03451 errmsg("-c %s requires a value",
03452 optarg)));
03453 }
03454 SetConfigOption(name, value, ctx, gucsource);
03455 free(name);
03456 if (value)
03457 free(value);
03458 break;
03459 }
03460
03461 default:
03462 errs++;
03463 break;
03464 }
03465
03466 if (errs)
03467 break;
03468 }
03469
03470
03471
03472
03473 if (!errs && dbname && *dbname == NULL && argc - optind >= 1)
03474 *dbname = strdup(argv[optind++]);
03475
03476 if (errs || argc != optind)
03477 {
03478 if (errs)
03479 optind--;
03480
03481
03482 if (IsUnderPostmaster)
03483 ereport(FATAL,
03484 (errcode(ERRCODE_SYNTAX_ERROR),
03485 errmsg("invalid command-line argument for server process: %s", argv[optind]),
03486 errhint("Try \"%s --help\" for more information.", progname)));
03487 else
03488 ereport(FATAL,
03489 (errcode(ERRCODE_SYNTAX_ERROR),
03490 errmsg("%s: invalid command-line argument: %s",
03491 progname, argv[optind]),
03492 errhint("Try \"%s --help\" for more information.", progname)));
03493 }
03494
03495
03496
03497
03498
03499 optind = 1;
03500 #ifdef HAVE_INT_OPTRESET
03501 optreset = 1;
03502 #endif
03503 }
03504
03505
03506
03507
03508
03509
03510
03511
03512
03513
03514
03515
03516
03517 void
03518 PostgresMain(int argc, char *argv[],
03519 const char *dbname,
03520 const char *username)
03521 {
03522 int firstchar;
03523 StringInfoData input_message;
03524 sigjmp_buf local_sigjmp_buf;
03525 volatile bool send_ready_for_query = true;
03526
03527
03528
03529
03530
03531 if (!IsUnderPostmaster)
03532 {
03533 MyProcPid = getpid();
03534
03535 MyStartTime = time(NULL);
03536 }
03537
03538
03539
03540
03541
03542
03543 if (!IsUnderPostmaster)
03544 MemoryContextInit();
03545
03546 SetProcessingMode(InitProcessing);
03547
03548
03549 if (my_exec_path[0] == '\0')
03550 {
03551 if (find_my_exec(argv[0], my_exec_path) < 0)
03552 elog(FATAL, "%s: could not locate my own executable path",
03553 argv[0]);
03554 }
03555
03556 if (pkglib_path[0] == '\0')
03557 get_pkglib_path(my_exec_path, pkglib_path);
03558
03559
03560
03561
03562 if (!IsUnderPostmaster)
03563 InitializeGUCOptions();
03564
03565
03566
03567
03568 process_postgres_switches(argc, argv, PGC_POSTMASTER, &dbname);
03569
03570
03571 if (dbname == NULL)
03572 {
03573 dbname = username;
03574 if (dbname == NULL)
03575 ereport(FATAL,
03576 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
03577 errmsg("%s: no database nor user name specified",
03578 progname)));
03579 }
03580
03581
03582 if (!IsUnderPostmaster)
03583 {
03584 if (!SelectConfigFiles(userDoption, progname))
03585 proc_exit(1);
03586 }
03587
03588
03589
03590
03591
03592
03593
03594
03595
03596
03597
03598
03599
03600
03601
03602
03603
03604
03605
03606
03607 if (am_walsender)
03608 WalSndSignals();
03609 else
03610 {
03611 pqsignal(SIGHUP, SigHupHandler);
03612
03613 pqsignal(SIGINT, StatementCancelHandler);
03614 pqsignal(SIGTERM, die);
03615
03616
03617
03618
03619
03620
03621 if (IsUnderPostmaster)
03622 pqsignal(SIGQUIT, quickdie);
03623 else
03624 pqsignal(SIGQUIT, die);
03625 InitializeTimeouts();
03626
03627
03628
03629
03630
03631
03632
03633 pqsignal(SIGPIPE, SIG_IGN);
03634 pqsignal(SIGUSR1, procsignal_sigusr1_handler);
03635 pqsignal(SIGUSR2, SIG_IGN);
03636 pqsignal(SIGFPE, FloatExceptionHandler);
03637
03638
03639
03640
03641
03642 pqsignal(SIGCHLD, SIG_DFL);
03643
03644 }
03645
03646 pqinitmask();
03647
03648 if (IsUnderPostmaster)
03649 {
03650
03651 sigdelset(&BlockSig, SIGQUIT);
03652 }
03653
03654 PG_SETMASK(&BlockSig);
03655
03656 if (!IsUnderPostmaster)
03657 {
03658
03659
03660
03661
03662 Assert(DataDir);
03663 ValidatePgVersion(DataDir);
03664
03665
03666 ChangeToDataDir();
03667
03668
03669
03670
03671 CreateDataDirLockFile(false);
03672
03673
03674 InitializeMaxBackends();
03675 }
03676
03677
03678 BaseInit();
03679
03680
03681
03682
03683
03684
03685
03686 #ifdef EXEC_BACKEND
03687 if (!IsUnderPostmaster)
03688 InitProcess();
03689 #else
03690 InitProcess();
03691 #endif
03692
03693
03694 PG_SETMASK(&UnBlockSig);
03695
03696
03697
03698
03699
03700
03701
03702
03703 InitPostgres(dbname, InvalidOid, username, NULL);
03704
03705
03706
03707
03708
03709
03710
03711
03712 if (PostmasterContext)
03713 {
03714 MemoryContextDelete(PostmasterContext);
03715 PostmasterContext = NULL;
03716 }
03717
03718 SetProcessingMode(NormalProcessing);
03719
03720
03721
03722
03723
03724 BeginReportingGUCOptions();
03725
03726
03727
03728
03729
03730 if (IsUnderPostmaster && Log_disconnections)
03731 on_proc_exit(log_disconnections, 0);
03732
03733
03734 if (am_walsender)
03735 InitWalSender();
03736
03737
03738
03739
03740
03741 process_local_preload_libraries();
03742
03743
03744
03745
03746 if (whereToSendOutput == DestRemote &&
03747 PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)
03748 {
03749 StringInfoData buf;
03750
03751 pq_beginmessage(&buf, 'K');
03752 pq_sendint(&buf, (int32) MyProcPid, sizeof(int32));
03753 pq_sendint(&buf, (int32) MyCancelKey, sizeof(int32));
03754 pq_endmessage(&buf);
03755
03756 }
03757
03758
03759 if (whereToSendOutput == DestDebug)
03760 printf("\nPostgreSQL stand-alone backend %s\n", PG_VERSION);
03761
03762
03763
03764
03765
03766
03767
03768 MessageContext = AllocSetContextCreate(TopMemoryContext,
03769 "MessageContext",
03770 ALLOCSET_DEFAULT_MINSIZE,
03771 ALLOCSET_DEFAULT_INITSIZE,
03772 ALLOCSET_DEFAULT_MAXSIZE);
03773
03774
03775
03776
03777 if (!IsUnderPostmaster)
03778 PgStartTime = GetCurrentTimestamp();
03779
03780
03781
03782
03783
03784
03785
03786
03787
03788
03789
03790
03791
03792
03793
03794
03795 if (sigsetjmp(local_sigjmp_buf, 1) != 0)
03796 {
03797
03798
03799
03800
03801
03802
03803
03804
03805
03806 error_context_stack = NULL;
03807
03808
03809 HOLD_INTERRUPTS();
03810
03811
03812
03813
03814
03815 QueryCancelPending = false;
03816 disable_all_timeouts(false);
03817 QueryCancelPending = false;
03818
03819
03820
03821
03822
03823
03824 DoingCommandRead = false;
03825 DisableNotifyInterrupt();
03826 DisableCatchupInterrupt();
03827
03828
03829 pq_comm_reset();
03830
03831
03832 EmitErrorReport();
03833
03834
03835
03836
03837
03838 debug_query_string = NULL;
03839
03840
03841
03842
03843 AbortCurrentTransaction();
03844
03845 if (am_walsender)
03846 WalSndErrorCleanup();
03847
03848
03849
03850
03851
03852 MemoryContextSwitchTo(TopMemoryContext);
03853 FlushErrorState();
03854
03855
03856
03857
03858
03859
03860 if (doing_extended_query_message)
03861 ignore_till_sync = true;
03862
03863
03864 xact_started = false;
03865
03866
03867 RESUME_INTERRUPTS();
03868 }
03869
03870
03871 PG_exception_stack = &local_sigjmp_buf;
03872
03873 if (!ignore_till_sync)
03874 send_ready_for_query = true;
03875
03876
03877
03878
03879
03880 for (;;)
03881 {
03882
03883
03884
03885
03886 doing_extended_query_message = false;
03887
03888
03889
03890
03891
03892 MemoryContextSwitchTo(MessageContext);
03893 MemoryContextResetAndDeleteChildren(MessageContext);
03894
03895 initStringInfo(&input_message);
03896
03897
03898
03899
03900
03901
03902
03903
03904
03905
03906
03907
03908
03909
03910 if (send_ready_for_query)
03911 {
03912 if (IsAbortedTransactionBlockState())
03913 {
03914 set_ps_display("idle in transaction (aborted)", false);
03915 pgstat_report_activity(STATE_IDLEINTRANSACTION_ABORTED, NULL);
03916 }
03917 else if (IsTransactionOrTransactionBlock())
03918 {
03919 set_ps_display("idle in transaction", false);
03920 pgstat_report_activity(STATE_IDLEINTRANSACTION, NULL);
03921 }
03922 else
03923 {
03924 ProcessCompletedNotifies();
03925 pgstat_report_stat(false);
03926
03927 set_ps_display("idle", false);
03928 pgstat_report_activity(STATE_IDLE, NULL);
03929 }
03930
03931 ReadyForQuery(whereToSendOutput);
03932 send_ready_for_query = false;
03933 }
03934
03935
03936
03937
03938
03939
03940
03941 DoingCommandRead = true;
03942
03943
03944
03945
03946 firstchar = ReadCommand(&input_message);
03947
03948
03949
03950
03951 DoingCommandRead = false;
03952
03953
03954
03955
03956
03957 if (got_SIGHUP)
03958 {
03959 got_SIGHUP = false;
03960 ProcessConfigFile(PGC_SIGHUP);
03961 }
03962
03963
03964
03965
03966
03967 if (ignore_till_sync && firstchar != EOF)
03968 continue;
03969
03970 switch (firstchar)
03971 {
03972 case 'Q':
03973 {
03974 const char *query_string;
03975
03976
03977 SetCurrentStatementStartTimestamp();
03978
03979 query_string = pq_getmsgstring(&input_message);
03980 pq_getmsgend(&input_message);
03981
03982 if (am_walsender)
03983 exec_replication_command(query_string);
03984 else
03985 exec_simple_query(query_string);
03986
03987 send_ready_for_query = true;
03988 }
03989 break;
03990
03991 case 'P':
03992 {
03993 const char *stmt_name;
03994 const char *query_string;
03995 int numParams;
03996 Oid *paramTypes = NULL;
03997
03998 forbidden_in_wal_sender(firstchar);
03999
04000
04001 SetCurrentStatementStartTimestamp();
04002
04003 stmt_name = pq_getmsgstring(&input_message);
04004 query_string = pq_getmsgstring(&input_message);
04005 numParams = pq_getmsgint(&input_message, 2);
04006 if (numParams > 0)
04007 {
04008 int i;
04009
04010 paramTypes = (Oid *) palloc(numParams * sizeof(Oid));
04011 for (i = 0; i < numParams; i++)
04012 paramTypes[i] = pq_getmsgint(&input_message, 4);
04013 }
04014 pq_getmsgend(&input_message);
04015
04016 exec_parse_message(query_string, stmt_name,
04017 paramTypes, numParams);
04018 }
04019 break;
04020
04021 case 'B':
04022 forbidden_in_wal_sender(firstchar);
04023
04024
04025 SetCurrentStatementStartTimestamp();
04026
04027
04028
04029
04030
04031 exec_bind_message(&input_message);
04032 break;
04033
04034 case 'E':
04035 {
04036 const char *portal_name;
04037 int max_rows;
04038
04039 forbidden_in_wal_sender(firstchar);
04040
04041
04042 SetCurrentStatementStartTimestamp();
04043
04044 portal_name = pq_getmsgstring(&input_message);
04045 max_rows = pq_getmsgint(&input_message, 4);
04046 pq_getmsgend(&input_message);
04047
04048 exec_execute_message(portal_name, max_rows);
04049 }
04050 break;
04051
04052 case 'F':
04053 forbidden_in_wal_sender(firstchar);
04054
04055
04056 SetCurrentStatementStartTimestamp();
04057
04058
04059 pgstat_report_activity(STATE_FASTPATH, NULL);
04060 set_ps_display("<FASTPATH>", false);
04061
04062
04063 start_xact_command();
04064
04065
04066
04067
04068
04069
04070
04071
04072
04073
04074
04075 MemoryContextSwitchTo(MessageContext);
04076
04077 if (HandleFunctionRequest(&input_message) == EOF)
04078 {
04079
04080
04081
04082
04083
04084
04085 if (whereToSendOutput == DestRemote)
04086 whereToSendOutput = DestNone;
04087
04088 proc_exit(0);
04089 }
04090
04091
04092 finish_xact_command();
04093
04094 send_ready_for_query = true;
04095 break;
04096
04097 case 'C':
04098 {
04099 int close_type;
04100 const char *close_target;
04101
04102 forbidden_in_wal_sender(firstchar);
04103
04104 close_type = pq_getmsgbyte(&input_message);
04105 close_target = pq_getmsgstring(&input_message);
04106 pq_getmsgend(&input_message);
04107
04108 switch (close_type)
04109 {
04110 case 'S':
04111 if (close_target[0] != '\0')
04112 DropPreparedStatement(close_target, false);
04113 else
04114 {
04115
04116 drop_unnamed_stmt();
04117 }
04118 break;
04119 case 'P':
04120 {
04121 Portal portal;
04122
04123 portal = GetPortalByName(close_target);
04124 if (PortalIsValid(portal))
04125 PortalDrop(portal, false);
04126 }
04127 break;
04128 default:
04129 ereport(ERROR,
04130 (errcode(ERRCODE_PROTOCOL_VIOLATION),
04131 errmsg("invalid CLOSE message subtype %d",
04132 close_type)));
04133 break;
04134 }
04135
04136 if (whereToSendOutput == DestRemote)
04137 pq_putemptymessage('3');
04138 }
04139 break;
04140
04141 case 'D':
04142 {
04143 int describe_type;
04144 const char *describe_target;
04145
04146 forbidden_in_wal_sender(firstchar);
04147
04148
04149 SetCurrentStatementStartTimestamp();
04150
04151 describe_type = pq_getmsgbyte(&input_message);
04152 describe_target = pq_getmsgstring(&input_message);
04153 pq_getmsgend(&input_message);
04154
04155 switch (describe_type)
04156 {
04157 case 'S':
04158 exec_describe_statement_message(describe_target);
04159 break;
04160 case 'P':
04161 exec_describe_portal_message(describe_target);
04162 break;
04163 default:
04164 ereport(ERROR,
04165 (errcode(ERRCODE_PROTOCOL_VIOLATION),
04166 errmsg("invalid DESCRIBE message subtype %d",
04167 describe_type)));
04168 break;
04169 }
04170 }
04171 break;
04172
04173 case 'H':
04174 pq_getmsgend(&input_message);
04175 if (whereToSendOutput == DestRemote)
04176 pq_flush();
04177 break;
04178
04179 case 'S':
04180 pq_getmsgend(&input_message);
04181 finish_xact_command();
04182 send_ready_for_query = true;
04183 break;
04184
04185
04186
04187
04188
04189
04190 case 'X':
04191 case EOF:
04192
04193
04194
04195
04196
04197 if (whereToSendOutput == DestRemote)
04198 whereToSendOutput = DestNone;
04199
04200
04201
04202
04203
04204
04205
04206
04207 proc_exit(0);
04208
04209 case 'd':
04210 case 'c':
04211 case 'f':
04212
04213
04214
04215
04216
04217
04218 break;
04219
04220 default:
04221 ereport(FATAL,
04222 (errcode(ERRCODE_PROTOCOL_VIOLATION),
04223 errmsg("invalid frontend message type %d",
04224 firstchar)));
04225 }
04226 }
04227 }
04228
04229
04230
04231
04232
04233
04234
04235
04236 static void
04237 forbidden_in_wal_sender(char firstchar)
04238 {
04239 if (am_walsender)
04240 {
04241 if (firstchar == 'F')
04242 ereport(ERROR,
04243 (errcode(ERRCODE_PROTOCOL_VIOLATION),
04244 errmsg("fastpath function calls not supported in a replication connection")));
04245 else
04246 ereport(ERROR,
04247 (errcode(ERRCODE_PROTOCOL_VIOLATION),
04248 errmsg("extended query protocol not supported in a replication connection")));
04249 }
04250 }
04251
04252
04253
04254
04255
04256
04257
04258 long
04259 get_stack_depth_rlimit(void)
04260 {
04261 #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_STACK)
04262 static long val = 0;
04263
04264
04265 if (val == 0)
04266 {
04267 struct rlimit rlim;
04268
04269 if (getrlimit(RLIMIT_STACK, &rlim) < 0)
04270 val = -1;
04271 else if (rlim.rlim_cur == RLIM_INFINITY)
04272 val = LONG_MAX;
04273
04274 else if (rlim.rlim_cur >= LONG_MAX)
04275 val = LONG_MAX;
04276 else
04277 val = rlim.rlim_cur;
04278 }
04279 return val;
04280 #else
04281 #if defined(WIN32) || defined(__CYGWIN__)
04282
04283 return WIN32_STACK_RLIMIT;
04284 #else
04285 return -1;
04286 #endif
04287 #endif
04288 }
04289
04290
04291 static struct rusage Save_r;
04292 static struct timeval Save_t;
04293
04294 void
04295 ResetUsage(void)
04296 {
04297 getrusage(RUSAGE_SELF, &Save_r);
04298 gettimeofday(&Save_t, NULL);
04299 }
04300
04301 void
04302 ShowUsage(const char *title)
04303 {
04304 StringInfoData str;
04305 struct timeval user,
04306 sys;
04307 struct timeval elapse_t;
04308 struct rusage r;
04309
04310 getrusage(RUSAGE_SELF, &r);
04311 gettimeofday(&elapse_t, NULL);
04312 memcpy((char *) &user, (char *) &r.ru_utime, sizeof(user));
04313 memcpy((char *) &sys, (char *) &r.ru_stime, sizeof(sys));
04314 if (elapse_t.tv_usec < Save_t.tv_usec)
04315 {
04316 elapse_t.tv_sec--;
04317 elapse_t.tv_usec += 1000000;
04318 }
04319 if (r.ru_utime.tv_usec < Save_r.ru_utime.tv_usec)
04320 {
04321 r.ru_utime.tv_sec--;
04322 r.ru_utime.tv_usec += 1000000;
04323 }
04324 if (r.ru_stime.tv_usec < Save_r.ru_stime.tv_usec)
04325 {
04326 r.ru_stime.tv_sec--;
04327 r.ru_stime.tv_usec += 1000000;
04328 }
04329
04330
04331
04332
04333
04334
04335
04336
04337 initStringInfo(&str);
04338
04339 appendStringInfo(&str, "! system usage stats:\n");
04340 appendStringInfo(&str,
04341 "!\t%ld.%06ld elapsed %ld.%06ld user %ld.%06ld system sec\n",
04342 (long) (elapse_t.tv_sec - Save_t.tv_sec),
04343 (long) (elapse_t.tv_usec - Save_t.tv_usec),
04344 (long) (r.ru_utime.tv_sec - Save_r.ru_utime.tv_sec),
04345 (long) (r.ru_utime.tv_usec - Save_r.ru_utime.tv_usec),
04346 (long) (r.ru_stime.tv_sec - Save_r.ru_stime.tv_sec),
04347 (long) (r.ru_stime.tv_usec - Save_r.ru_stime.tv_usec));
04348 appendStringInfo(&str,
04349 "!\t[%ld.%06ld user %ld.%06ld sys total]\n",
04350 (long) user.tv_sec,
04351 (long) user.tv_usec,
04352 (long) sys.tv_sec,
04353 (long) sys.tv_usec);
04354 #if defined(HAVE_GETRUSAGE)
04355 appendStringInfo(&str,
04356 "!\t%ld/%ld [%ld/%ld] filesystem blocks in/out\n",
04357 r.ru_inblock - Save_r.ru_inblock,
04358
04359 r.ru_oublock - Save_r.ru_oublock,
04360 r.ru_inblock, r.ru_oublock);
04361 appendStringInfo(&str,
04362 "!\t%ld/%ld [%ld/%ld] page faults/reclaims, %ld [%ld] swaps\n",
04363 r.ru_majflt - Save_r.ru_majflt,
04364 r.ru_minflt - Save_r.ru_minflt,
04365 r.ru_majflt, r.ru_minflt,
04366 r.ru_nswap - Save_r.ru_nswap,
04367 r.ru_nswap);
04368 appendStringInfo(&str,
04369 "!\t%ld [%ld] signals rcvd, %ld/%ld [%ld/%ld] messages rcvd/sent\n",
04370 r.ru_nsignals - Save_r.ru_nsignals,
04371 r.ru_nsignals,
04372 r.ru_msgrcv - Save_r.ru_msgrcv,
04373 r.ru_msgsnd - Save_r.ru_msgsnd,
04374 r.ru_msgrcv, r.ru_msgsnd);
04375 appendStringInfo(&str,
04376 "!\t%ld/%ld [%ld/%ld] voluntary/involuntary context switches\n",
04377 r.ru_nvcsw - Save_r.ru_nvcsw,
04378 r.ru_nivcsw - Save_r.ru_nivcsw,
04379 r.ru_nvcsw, r.ru_nivcsw);
04380 #endif
04381
04382
04383 if (str.data[str.len - 1] == '\n')
04384 str.data[--str.len] = '\0';
04385
04386 ereport(LOG,
04387 (errmsg_internal("%s", title),
04388 errdetail_internal("%s", str.data)));
04389
04390 pfree(str.data);
04391 }
04392
04393
04394
04395
04396 static void
04397 log_disconnections(int code, Datum arg)
04398 {
04399 Port *port = MyProcPort;
04400 long secs;
04401 int usecs;
04402 int msecs;
04403 int hours,
04404 minutes,
04405 seconds;
04406
04407 TimestampDifference(port->SessionStartTime,
04408 GetCurrentTimestamp(),
04409 &secs, &usecs);
04410 msecs = usecs / 1000;
04411
04412 hours = secs / SECS_PER_HOUR;
04413 secs %= SECS_PER_HOUR;
04414 minutes = secs / SECS_PER_MINUTE;
04415 seconds = secs % SECS_PER_MINUTE;
04416
04417 ereport(LOG,
04418 (errmsg("disconnection: session time: %d:%02d:%02d.%03d "
04419 "user=%s database=%s host=%s%s%s",
04420 hours, minutes, seconds, msecs,
04421 port->user_name, port->database_name, port->remote_host,
04422 port->remote_port[0] ? " port=" : "", port->remote_port)));
04423 }