00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 #include "postgres.h"
00056
00057 #include <fcntl.h>
00058 #include <time.h>
00059 #include <unistd.h>
00060 #include <signal.h>
00061 #include <ctype.h>
00062 #ifdef HAVE_SYSLOG
00063 #include <syslog.h>
00064 #endif
00065
00066 #include "access/transam.h"
00067 #include "access/xact.h"
00068 #include "libpq/libpq.h"
00069 #include "libpq/pqformat.h"
00070 #include "mb/pg_wchar.h"
00071 #include "miscadmin.h"
00072 #include "postmaster/postmaster.h"
00073 #include "postmaster/syslogger.h"
00074 #include "storage/ipc.h"
00075 #include "storage/proc.h"
00076 #include "tcop/tcopprot.h"
00077 #include "utils/guc.h"
00078 #include "utils/memutils.h"
00079 #include "utils/ps_status.h"
00080
00081
00082 #undef _
00083 #define _(x) err_gettext(x)
00084
00085 static const char *
00086 err_gettext(const char *str)
00087
00088
00089 __attribute__((format_arg(1)));
00090 static void set_errdata_field(char **ptr, const char *str);
00091
00092
00093 ErrorContextCallback *error_context_stack = NULL;
00094
00095 sigjmp_buf *PG_exception_stack = NULL;
00096
00097 extern bool redirection_done;
00098
00099
00100
00101
00102
00103
00104
00105
00106 emit_log_hook_type emit_log_hook = NULL;
00107
00108
00109 int Log_error_verbosity = PGERROR_VERBOSE;
00110 char *Log_line_prefix = NULL;
00111 int Log_destination = LOG_DESTINATION_STDERR;
00112
00113 #ifdef HAVE_SYSLOG
00114
00115
00116
00117
00118
00119
00120
00121
00122 #ifndef PG_SYSLOG_LIMIT
00123 #define PG_SYSLOG_LIMIT 900
00124 #endif
00125
00126 static bool openlog_done = false;
00127 static char *syslog_ident = NULL;
00128 static int syslog_facility = LOG_LOCAL0;
00129
00130 static void write_syslog(int level, const char *line);
00131 #endif
00132
00133 static void write_console(const char *line, int len);
00134
00135 #ifdef WIN32
00136 extern char *event_source;
00137 static void write_eventlog(int level, const char *line, int len);
00138 #endif
00139
00140
00141 #define ERRORDATA_STACK_SIZE 5
00142
00143 static ErrorData errordata[ERRORDATA_STACK_SIZE];
00144
00145 static int errordata_stack_depth = -1;
00146
00147 static int recursion_depth = 0;
00148
00149
00150
00151
00152
00153 #define FORMATTED_TS_LEN 128
00154 static char formatted_start_time[FORMATTED_TS_LEN];
00155 static char formatted_log_time[FORMATTED_TS_LEN];
00156
00157
00158
00159 #define CHECK_STACK_DEPTH() \
00160 do { \
00161 if (errordata_stack_depth < 0) \
00162 { \
00163 errordata_stack_depth = -1; \
00164 ereport(ERROR, (errmsg_internal("errstart was not called"))); \
00165 } \
00166 } while (0)
00167
00168
00169 static void log_line_prefix(StringInfo buf, ErrorData *edata);
00170 static void send_message_to_server_log(ErrorData *edata);
00171 static void send_message_to_frontend(ErrorData *edata);
00172 static char *expand_fmt_string(const char *fmt, ErrorData *edata);
00173 static const char *useful_strerror(int errnum);
00174 static const char *error_severity(int elevel);
00175 static void append_with_tabs(StringInfo buf, const char *str);
00176 static bool is_log_level_output(int elevel, int log_min_level);
00177 static void write_pipe_chunks(char *data, int len, int dest);
00178 static void write_csvlog(ErrorData *edata);
00179 static void setup_formatted_log_time(void);
00180 static void setup_formatted_start_time(void);
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190 bool
00191 in_error_recursion_trouble(void)
00192 {
00193
00194 return (recursion_depth > 2);
00195 }
00196
00197
00198
00199
00200
00201
00202 static inline const char *
00203 err_gettext(const char *str)
00204 {
00205 #ifdef ENABLE_NLS
00206 if (in_error_recursion_trouble())
00207 return str;
00208 else
00209 return gettext(str);
00210 #else
00211 return str;
00212 #endif
00213 }
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 bool
00228 errstart(int elevel, const char *filename, int lineno,
00229 const char *funcname, const char *domain)
00230 {
00231 ErrorData *edata;
00232 bool output_to_server;
00233 bool output_to_client = false;
00234 int i;
00235
00236
00237
00238
00239
00240 if (elevel >= ERROR)
00241 {
00242
00243
00244
00245
00246 if (CritSectionCount > 0)
00247 elevel = PANIC;
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261 if (elevel == ERROR)
00262 {
00263 if (PG_exception_stack == NULL ||
00264 ExitOnAnyError ||
00265 proc_exit_inprogress)
00266 elevel = FATAL;
00267 }
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277 for (i = 0; i <= errordata_stack_depth; i++)
00278 elevel = Max(elevel, errordata[i].elevel);
00279 }
00280
00281
00282
00283
00284
00285
00286
00287
00288 if (IsPostmasterEnvironment)
00289 output_to_server = is_log_level_output(elevel, log_min_messages);
00290 else
00291
00292 output_to_server = (elevel >= log_min_messages);
00293
00294
00295 if (whereToSendOutput == DestRemote && elevel != COMMERROR)
00296 {
00297
00298
00299
00300
00301
00302
00303 if (ClientAuthInProgress)
00304 output_to_client = (elevel >= ERROR);
00305 else
00306 output_to_client = (elevel >= client_min_messages ||
00307 elevel == INFO);
00308 }
00309
00310
00311 if (elevel < ERROR && !output_to_server && !output_to_client)
00312 return false;
00313
00314
00315
00316
00317
00318 if (recursion_depth++ > 0 && elevel >= ERROR)
00319 {
00320
00321
00322
00323
00324
00325 MemoryContextReset(ErrorContext);
00326
00327
00328
00329
00330
00331
00332
00333 if (in_error_recursion_trouble())
00334 {
00335 error_context_stack = NULL;
00336 debug_query_string = NULL;
00337 }
00338 }
00339 if (++errordata_stack_depth >= ERRORDATA_STACK_SIZE)
00340 {
00341
00342
00343
00344
00345
00346 errordata_stack_depth = -1;
00347 ereport(PANIC, (errmsg_internal("ERRORDATA_STACK_SIZE exceeded")));
00348 }
00349
00350
00351 edata = &errordata[errordata_stack_depth];
00352 MemSet(edata, 0, sizeof(ErrorData));
00353 edata->elevel = elevel;
00354 edata->output_to_server = output_to_server;
00355 edata->output_to_client = output_to_client;
00356 if (filename)
00357 {
00358 const char *slash;
00359
00360
00361 slash = strrchr(filename, '/');
00362 if (slash)
00363 filename = slash + 1;
00364 }
00365 edata->filename = filename;
00366 edata->lineno = lineno;
00367 edata->funcname = funcname;
00368
00369 edata->domain = domain ? domain : PG_TEXTDOMAIN("postgres");
00370
00371 if (elevel >= ERROR)
00372 edata->sqlerrcode = ERRCODE_INTERNAL_ERROR;
00373 else if (elevel == WARNING)
00374 edata->sqlerrcode = ERRCODE_WARNING;
00375 else
00376 edata->sqlerrcode = ERRCODE_SUCCESSFUL_COMPLETION;
00377
00378 edata->saved_errno = errno;
00379
00380 recursion_depth--;
00381 return true;
00382 }
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392 void
00393 errfinish(int dummy,...)
00394 {
00395 ErrorData *edata = &errordata[errordata_stack_depth];
00396 int elevel = edata->elevel;
00397 MemoryContext oldcontext;
00398 ErrorContextCallback *econtext;
00399
00400 recursion_depth++;
00401 CHECK_STACK_DEPTH();
00402
00403
00404
00405
00406
00407 oldcontext = MemoryContextSwitchTo(ErrorContext);
00408
00409
00410
00411
00412
00413
00414 for (econtext = error_context_stack;
00415 econtext != NULL;
00416 econtext = econtext->previous)
00417 (*econtext->callback) (econtext->arg);
00418
00419
00420
00421
00422
00423 if (elevel == ERROR)
00424 {
00425
00426
00427
00428
00429
00430
00431 ImmediateInterruptOK = false;
00432
00433
00434
00435
00436
00437
00438
00439
00440 InterruptHoldoffCount = 0;
00441
00442 CritSectionCount = 0;
00443
00444
00445
00446
00447
00448
00449 recursion_depth--;
00450 PG_RE_THROW();
00451 }
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462 if (elevel >= FATAL && whereToSendOutput == DestRemote)
00463 pq_endcopyout(true);
00464
00465
00466 EmitErrorReport();
00467
00468
00469 if (edata->message)
00470 pfree(edata->message);
00471 if (edata->detail)
00472 pfree(edata->detail);
00473 if (edata->detail_log)
00474 pfree(edata->detail_log);
00475 if (edata->hint)
00476 pfree(edata->hint);
00477 if (edata->context)
00478 pfree(edata->context);
00479 if (edata->schema_name)
00480 pfree(edata->schema_name);
00481 if (edata->table_name)
00482 pfree(edata->table_name);
00483 if (edata->column_name)
00484 pfree(edata->column_name);
00485 if (edata->datatype_name)
00486 pfree(edata->datatype_name);
00487 if (edata->constraint_name)
00488 pfree(edata->constraint_name);
00489 if (edata->internalquery)
00490 pfree(edata->internalquery);
00491
00492 errordata_stack_depth--;
00493
00494
00495 MemoryContextSwitchTo(oldcontext);
00496 recursion_depth--;
00497
00498
00499
00500
00501 if (elevel == FATAL)
00502 {
00503
00504
00505
00506 ImmediateInterruptOK = false;
00507
00508
00509
00510
00511
00512 if (PG_exception_stack == NULL && whereToSendOutput == DestRemote)
00513 whereToSendOutput = DestNone;
00514
00515
00516
00517
00518
00519
00520
00521 fflush(stdout);
00522 fflush(stderr);
00523
00524
00525
00526
00527
00528
00529 proc_exit(1);
00530 }
00531
00532 if (elevel >= PANIC)
00533 {
00534
00535
00536
00537
00538
00539
00540
00541 ImmediateInterruptOK = false;
00542 fflush(stdout);
00543 fflush(stderr);
00544 abort();
00545 }
00546
00547
00548
00549
00550
00551
00552
00553
00554 CHECK_FOR_INTERRUPTS();
00555 }
00556
00557
00558
00559
00560
00561
00562
00563 int
00564 errcode(int sqlerrcode)
00565 {
00566 ErrorData *edata = &errordata[errordata_stack_depth];
00567
00568
00569 CHECK_STACK_DEPTH();
00570
00571 edata->sqlerrcode = sqlerrcode;
00572
00573 return 0;
00574 }
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586 int
00587 errcode_for_file_access(void)
00588 {
00589 ErrorData *edata = &errordata[errordata_stack_depth];
00590
00591
00592 CHECK_STACK_DEPTH();
00593
00594 switch (edata->saved_errno)
00595 {
00596
00597 case EPERM:
00598 case EACCES:
00599 #ifdef EROFS
00600 case EROFS:
00601 #endif
00602 edata->sqlerrcode = ERRCODE_INSUFFICIENT_PRIVILEGE;
00603 break;
00604
00605
00606 case ENOENT:
00607 edata->sqlerrcode = ERRCODE_UNDEFINED_FILE;
00608 break;
00609
00610
00611 case EEXIST:
00612 edata->sqlerrcode = ERRCODE_DUPLICATE_FILE;
00613 break;
00614
00615
00616 case ENOTDIR:
00617 case EISDIR:
00618 #if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST)
00619 case ENOTEMPTY:
00620 #endif
00621 edata->sqlerrcode = ERRCODE_WRONG_OBJECT_TYPE;
00622 break;
00623
00624
00625 case ENOSPC:
00626 edata->sqlerrcode = ERRCODE_DISK_FULL;
00627 break;
00628
00629 case ENFILE:
00630 case EMFILE:
00631 edata->sqlerrcode = ERRCODE_INSUFFICIENT_RESOURCES;
00632 break;
00633
00634
00635 case EIO:
00636 edata->sqlerrcode = ERRCODE_IO_ERROR;
00637 break;
00638
00639
00640 default:
00641 edata->sqlerrcode = ERRCODE_INTERNAL_ERROR;
00642 break;
00643 }
00644
00645 return 0;
00646 }
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657 int
00658 errcode_for_socket_access(void)
00659 {
00660 ErrorData *edata = &errordata[errordata_stack_depth];
00661
00662
00663 CHECK_STACK_DEPTH();
00664
00665 switch (edata->saved_errno)
00666 {
00667
00668 case EPIPE:
00669 #ifdef ECONNRESET
00670 case ECONNRESET:
00671 #endif
00672 edata->sqlerrcode = ERRCODE_CONNECTION_FAILURE;
00673 break;
00674
00675
00676 default:
00677 edata->sqlerrcode = ERRCODE_INTERNAL_ERROR;
00678 break;
00679 }
00680
00681 return 0;
00682 }
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697 #define EVALUATE_MESSAGE(domain, targetfield, appendval, translateit) \
00698 { \
00699 char *fmtbuf; \
00700 StringInfoData buf; \
00701 \
00702 if (translateit && !in_error_recursion_trouble()) \
00703 fmt = dgettext((domain), fmt); \
00704 \
00705 fmtbuf = expand_fmt_string(fmt, edata); \
00706 initStringInfo(&buf); \
00707 if ((appendval) && edata->targetfield) { \
00708 appendStringInfoString(&buf, edata->targetfield); \
00709 appendStringInfoChar(&buf, '\n'); \
00710 } \
00711 \
00712 for (;;) \
00713 { \
00714 va_list args; \
00715 bool success; \
00716 va_start(args, fmt); \
00717 success = appendStringInfoVA(&buf, fmtbuf, args); \
00718 va_end(args); \
00719 if (success) \
00720 break; \
00721 enlargeStringInfo(&buf, buf.maxlen); \
00722 } \
00723 \
00724 pfree(fmtbuf); \
00725 \
00726 if (edata->targetfield) \
00727 pfree(edata->targetfield); \
00728 edata->targetfield = pstrdup(buf.data); \
00729 pfree(buf.data); \
00730 }
00731
00732
00733
00734
00735
00736
00737 #define EVALUATE_MESSAGE_PLURAL(domain, targetfield, appendval) \
00738 { \
00739 const char *fmt; \
00740 char *fmtbuf; \
00741 StringInfoData buf; \
00742 \
00743 if (!in_error_recursion_trouble()) \
00744 fmt = dngettext((domain), fmt_singular, fmt_plural, n); \
00745 else \
00746 fmt = (n == 1 ? fmt_singular : fmt_plural); \
00747 \
00748 fmtbuf = expand_fmt_string(fmt, edata); \
00749 initStringInfo(&buf); \
00750 if ((appendval) && edata->targetfield) { \
00751 appendStringInfoString(&buf, edata->targetfield); \
00752 appendStringInfoChar(&buf, '\n'); \
00753 } \
00754 \
00755 for (;;) \
00756 { \
00757 va_list args; \
00758 bool success; \
00759 va_start(args, n); \
00760 success = appendStringInfoVA(&buf, fmtbuf, args); \
00761 va_end(args); \
00762 if (success) \
00763 break; \
00764 enlargeStringInfo(&buf, buf.maxlen); \
00765 } \
00766 \
00767 pfree(fmtbuf); \
00768 \
00769 if (edata->targetfield) \
00770 pfree(edata->targetfield); \
00771 edata->targetfield = pstrdup(buf.data); \
00772 pfree(buf.data); \
00773 }
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785 int
00786 errmsg(const char *fmt,...)
00787 {
00788 ErrorData *edata = &errordata[errordata_stack_depth];
00789 MemoryContext oldcontext;
00790
00791 recursion_depth++;
00792 CHECK_STACK_DEPTH();
00793 oldcontext = MemoryContextSwitchTo(ErrorContext);
00794
00795 EVALUATE_MESSAGE(edata->domain, message, false, true);
00796
00797 MemoryContextSwitchTo(oldcontext);
00798 recursion_depth--;
00799 return 0;
00800 }
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814 int
00815 errmsg_internal(const char *fmt,...)
00816 {
00817 ErrorData *edata = &errordata[errordata_stack_depth];
00818 MemoryContext oldcontext;
00819
00820 recursion_depth++;
00821 CHECK_STACK_DEPTH();
00822 oldcontext = MemoryContextSwitchTo(ErrorContext);
00823
00824 EVALUATE_MESSAGE(edata->domain, message, false, false);
00825
00826 MemoryContextSwitchTo(oldcontext);
00827 recursion_depth--;
00828 return 0;
00829 }
00830
00831
00832
00833
00834
00835
00836 int
00837 errmsg_plural(const char *fmt_singular, const char *fmt_plural,
00838 unsigned long n,...)
00839 {
00840 ErrorData *edata = &errordata[errordata_stack_depth];
00841 MemoryContext oldcontext;
00842
00843 recursion_depth++;
00844 CHECK_STACK_DEPTH();
00845 oldcontext = MemoryContextSwitchTo(ErrorContext);
00846
00847 EVALUATE_MESSAGE_PLURAL(edata->domain, message, false);
00848
00849 MemoryContextSwitchTo(oldcontext);
00850 recursion_depth--;
00851 return 0;
00852 }
00853
00854
00855
00856
00857
00858 int
00859 errdetail(const char *fmt,...)
00860 {
00861 ErrorData *edata = &errordata[errordata_stack_depth];
00862 MemoryContext oldcontext;
00863
00864 recursion_depth++;
00865 CHECK_STACK_DEPTH();
00866 oldcontext = MemoryContextSwitchTo(ErrorContext);
00867
00868 EVALUATE_MESSAGE(edata->domain, detail, false, true);
00869
00870 MemoryContextSwitchTo(oldcontext);
00871 recursion_depth--;
00872 return 0;
00873 }
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885 int
00886 errdetail_internal(const char *fmt,...)
00887 {
00888 ErrorData *edata = &errordata[errordata_stack_depth];
00889 MemoryContext oldcontext;
00890
00891 recursion_depth++;
00892 CHECK_STACK_DEPTH();
00893 oldcontext = MemoryContextSwitchTo(ErrorContext);
00894
00895 EVALUATE_MESSAGE(edata->domain, detail, false, false);
00896
00897 MemoryContextSwitchTo(oldcontext);
00898 recursion_depth--;
00899 return 0;
00900 }
00901
00902
00903
00904
00905
00906 int
00907 errdetail_log(const char *fmt,...)
00908 {
00909 ErrorData *edata = &errordata[errordata_stack_depth];
00910 MemoryContext oldcontext;
00911
00912 recursion_depth++;
00913 CHECK_STACK_DEPTH();
00914 oldcontext = MemoryContextSwitchTo(ErrorContext);
00915
00916 EVALUATE_MESSAGE(edata->domain, detail_log, false, true);
00917
00918 MemoryContextSwitchTo(oldcontext);
00919 recursion_depth--;
00920 return 0;
00921 }
00922
00923
00924
00925
00926
00927
00928 int
00929 errdetail_plural(const char *fmt_singular, const char *fmt_plural,
00930 unsigned long n,...)
00931 {
00932 ErrorData *edata = &errordata[errordata_stack_depth];
00933 MemoryContext oldcontext;
00934
00935 recursion_depth++;
00936 CHECK_STACK_DEPTH();
00937 oldcontext = MemoryContextSwitchTo(ErrorContext);
00938
00939 EVALUATE_MESSAGE_PLURAL(edata->domain, detail, false);
00940
00941 MemoryContextSwitchTo(oldcontext);
00942 recursion_depth--;
00943 return 0;
00944 }
00945
00946
00947
00948
00949
00950 int
00951 errhint(const char *fmt,...)
00952 {
00953 ErrorData *edata = &errordata[errordata_stack_depth];
00954 MemoryContext oldcontext;
00955
00956 recursion_depth++;
00957 CHECK_STACK_DEPTH();
00958 oldcontext = MemoryContextSwitchTo(ErrorContext);
00959
00960 EVALUATE_MESSAGE(edata->domain, hint, false, true);
00961
00962 MemoryContextSwitchTo(oldcontext);
00963 recursion_depth--;
00964 return 0;
00965 }
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975 int
00976 errcontext_msg(const char *fmt,...)
00977 {
00978 ErrorData *edata = &errordata[errordata_stack_depth];
00979 MemoryContext oldcontext;
00980
00981 recursion_depth++;
00982 CHECK_STACK_DEPTH();
00983 oldcontext = MemoryContextSwitchTo(ErrorContext);
00984
00985 EVALUATE_MESSAGE(edata->context_domain, context, true, true);
00986
00987 MemoryContextSwitchTo(oldcontext);
00988 recursion_depth--;
00989 return 0;
00990 }
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001 int
01002 set_errcontext_domain(const char *domain)
01003 {
01004 ErrorData *edata = &errordata[errordata_stack_depth];
01005
01006
01007 CHECK_STACK_DEPTH();
01008
01009 edata->context_domain = domain;
01010
01011 return 0;
01012 }
01013
01014
01015
01016
01017
01018
01019
01020 int
01021 errhidestmt(bool hide_stmt)
01022 {
01023 ErrorData *edata = &errordata[errordata_stack_depth];
01024
01025
01026 CHECK_STACK_DEPTH();
01027
01028 edata->hide_stmt = hide_stmt;
01029
01030 return 0;
01031 }
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041 int
01042 errfunction(const char *funcname)
01043 {
01044 ErrorData *edata = &errordata[errordata_stack_depth];
01045
01046
01047 CHECK_STACK_DEPTH();
01048
01049 edata->funcname = funcname;
01050 edata->show_funcname = true;
01051
01052 return 0;
01053 }
01054
01055
01056
01057
01058 int
01059 errposition(int cursorpos)
01060 {
01061 ErrorData *edata = &errordata[errordata_stack_depth];
01062
01063
01064 CHECK_STACK_DEPTH();
01065
01066 edata->cursorpos = cursorpos;
01067
01068 return 0;
01069 }
01070
01071
01072
01073
01074 int
01075 internalerrposition(int cursorpos)
01076 {
01077 ErrorData *edata = &errordata[errordata_stack_depth];
01078
01079
01080 CHECK_STACK_DEPTH();
01081
01082 edata->internalpos = cursorpos;
01083
01084 return 0;
01085 }
01086
01087
01088
01089
01090
01091
01092
01093
01094 int
01095 internalerrquery(const char *query)
01096 {
01097 ErrorData *edata = &errordata[errordata_stack_depth];
01098
01099
01100 CHECK_STACK_DEPTH();
01101
01102 if (edata->internalquery)
01103 {
01104 pfree(edata->internalquery);
01105 edata->internalquery = NULL;
01106 }
01107
01108 if (query)
01109 edata->internalquery = MemoryContextStrdup(ErrorContext, query);
01110
01111 return 0;
01112 }
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124 int
01125 err_generic_string(int field, const char *str)
01126 {
01127 ErrorData *edata = &errordata[errordata_stack_depth];
01128
01129
01130 CHECK_STACK_DEPTH();
01131
01132 switch (field)
01133 {
01134 case PG_DIAG_SCHEMA_NAME:
01135 set_errdata_field(&edata->schema_name, str);
01136 break;
01137 case PG_DIAG_TABLE_NAME:
01138 set_errdata_field(&edata->table_name, str);
01139 break;
01140 case PG_DIAG_COLUMN_NAME:
01141 set_errdata_field(&edata->column_name, str);
01142 break;
01143 case PG_DIAG_DATATYPE_NAME:
01144 set_errdata_field(&edata->datatype_name, str);
01145 break;
01146 case PG_DIAG_CONSTRAINT_NAME:
01147 set_errdata_field(&edata->constraint_name, str);
01148 break;
01149 default:
01150 elog(ERROR, "unsupported ErrorData field id: %d", field);
01151 break;
01152 }
01153
01154 return 0;
01155 }
01156
01157
01158
01159
01160 static void
01161 set_errdata_field(char **ptr, const char *str)
01162 {
01163 Assert(*ptr == NULL);
01164 *ptr = MemoryContextStrdup(ErrorContext, str);
01165 }
01166
01167
01168
01169
01170
01171
01172
01173 int
01174 geterrcode(void)
01175 {
01176 ErrorData *edata = &errordata[errordata_stack_depth];
01177
01178
01179 CHECK_STACK_DEPTH();
01180
01181 return edata->sqlerrcode;
01182 }
01183
01184
01185
01186
01187
01188
01189
01190 int
01191 geterrposition(void)
01192 {
01193 ErrorData *edata = &errordata[errordata_stack_depth];
01194
01195
01196 CHECK_STACK_DEPTH();
01197
01198 return edata->cursorpos;
01199 }
01200
01201
01202
01203
01204
01205
01206
01207 int
01208 getinternalerrposition(void)
01209 {
01210 ErrorData *edata = &errordata[errordata_stack_depth];
01211
01212
01213 CHECK_STACK_DEPTH();
01214
01215 return edata->internalpos;
01216 }
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231 void
01232 elog_start(const char *filename, int lineno, const char *funcname)
01233 {
01234 ErrorData *edata;
01235
01236 if (++errordata_stack_depth >= ERRORDATA_STACK_SIZE)
01237 {
01238
01239
01240
01241
01242
01243
01244
01245 errordata_stack_depth = -1;
01246 ereport(PANIC, (errmsg_internal("ERRORDATA_STACK_SIZE exceeded")));
01247 }
01248
01249 edata = &errordata[errordata_stack_depth];
01250 if (filename)
01251 {
01252 const char *slash;
01253
01254
01255 slash = strrchr(filename, '/');
01256 if (slash)
01257 filename = slash + 1;
01258 }
01259 edata->filename = filename;
01260 edata->lineno = lineno;
01261 edata->funcname = funcname;
01262
01263 edata->saved_errno = errno;
01264 }
01265
01266
01267
01268
01269 void
01270 elog_finish(int elevel, const char *fmt,...)
01271 {
01272 ErrorData *edata = &errordata[errordata_stack_depth];
01273 MemoryContext oldcontext;
01274
01275 CHECK_STACK_DEPTH();
01276
01277
01278
01279
01280 errordata_stack_depth--;
01281 errno = edata->saved_errno;
01282 if (!errstart(elevel, edata->filename, edata->lineno, edata->funcname, NULL))
01283 return;
01284
01285
01286
01287
01288 recursion_depth++;
01289 oldcontext = MemoryContextSwitchTo(ErrorContext);
01290
01291 EVALUATE_MESSAGE(edata->domain, message, false, false);
01292
01293 MemoryContextSwitchTo(oldcontext);
01294 recursion_depth--;
01295
01296
01297
01298
01299 errfinish(0);
01300 }
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321 static int save_format_errnumber;
01322 static const char *save_format_domain;
01323
01324 void
01325 pre_format_elog_string(int errnumber, const char *domain)
01326 {
01327
01328 save_format_errnumber = errnumber;
01329
01330 save_format_domain = domain;
01331 }
01332
01333 char *
01334 format_elog_string(const char *fmt,...)
01335 {
01336 ErrorData errdata;
01337 ErrorData *edata;
01338 MemoryContext oldcontext;
01339
01340
01341 edata = &errdata;
01342 MemSet(edata, 0, sizeof(ErrorData));
01343
01344 edata->domain = save_format_domain ? save_format_domain : PG_TEXTDOMAIN("postgres");
01345
01346 edata->saved_errno = save_format_errnumber;
01347
01348 oldcontext = MemoryContextSwitchTo(ErrorContext);
01349
01350 EVALUATE_MESSAGE(edata->domain, message, false, true);
01351
01352 MemoryContextSwitchTo(oldcontext);
01353
01354 return edata->message;
01355 }
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365 void
01366 EmitErrorReport(void)
01367 {
01368 ErrorData *edata = &errordata[errordata_stack_depth];
01369 MemoryContext oldcontext;
01370
01371 recursion_depth++;
01372 CHECK_STACK_DEPTH();
01373 oldcontext = MemoryContextSwitchTo(ErrorContext);
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389 if (edata->output_to_server && emit_log_hook)
01390 (*emit_log_hook) (edata);
01391
01392
01393 if (edata->output_to_server)
01394 send_message_to_server_log(edata);
01395
01396
01397 if (edata->output_to_client)
01398 send_message_to_frontend(edata);
01399
01400 MemoryContextSwitchTo(oldcontext);
01401 recursion_depth--;
01402 }
01403
01404
01405
01406
01407
01408
01409
01410
01411 ErrorData *
01412 CopyErrorData(void)
01413 {
01414 ErrorData *edata = &errordata[errordata_stack_depth];
01415 ErrorData *newedata;
01416
01417
01418
01419
01420
01421 CHECK_STACK_DEPTH();
01422
01423 Assert(CurrentMemoryContext != ErrorContext);
01424
01425
01426 newedata = (ErrorData *) palloc(sizeof(ErrorData));
01427 memcpy(newedata, edata, sizeof(ErrorData));
01428
01429
01430 if (newedata->message)
01431 newedata->message = pstrdup(newedata->message);
01432 if (newedata->detail)
01433 newedata->detail = pstrdup(newedata->detail);
01434 if (newedata->detail_log)
01435 newedata->detail_log = pstrdup(newedata->detail_log);
01436 if (newedata->hint)
01437 newedata->hint = pstrdup(newedata->hint);
01438 if (newedata->context)
01439 newedata->context = pstrdup(newedata->context);
01440 if (newedata->schema_name)
01441 newedata->schema_name = pstrdup(newedata->schema_name);
01442 if (newedata->table_name)
01443 newedata->table_name = pstrdup(newedata->table_name);
01444 if (newedata->column_name)
01445 newedata->column_name = pstrdup(newedata->column_name);
01446 if (newedata->datatype_name)
01447 newedata->datatype_name = pstrdup(newedata->datatype_name);
01448 if (newedata->constraint_name)
01449 newedata->constraint_name = pstrdup(newedata->constraint_name);
01450 if (newedata->internalquery)
01451 newedata->internalquery = pstrdup(newedata->internalquery);
01452
01453 return newedata;
01454 }
01455
01456
01457
01458
01459
01460
01461
01462 void
01463 FreeErrorData(ErrorData *edata)
01464 {
01465 if (edata->message)
01466 pfree(edata->message);
01467 if (edata->detail)
01468 pfree(edata->detail);
01469 if (edata->detail_log)
01470 pfree(edata->detail_log);
01471 if (edata->hint)
01472 pfree(edata->hint);
01473 if (edata->context)
01474 pfree(edata->context);
01475 if (edata->schema_name)
01476 pfree(edata->schema_name);
01477 if (edata->table_name)
01478 pfree(edata->table_name);
01479 if (edata->column_name)
01480 pfree(edata->column_name);
01481 if (edata->datatype_name)
01482 pfree(edata->datatype_name);
01483 if (edata->constraint_name)
01484 pfree(edata->constraint_name);
01485 if (edata->internalquery)
01486 pfree(edata->internalquery);
01487 pfree(edata);
01488 }
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498 void
01499 FlushErrorState(void)
01500 {
01501
01502
01503
01504
01505
01506
01507 errordata_stack_depth = -1;
01508 recursion_depth = 0;
01509
01510 MemoryContextResetAndDeleteChildren(ErrorContext);
01511 }
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521 void
01522 ReThrowError(ErrorData *edata)
01523 {
01524 ErrorData *newedata;
01525
01526 Assert(edata->elevel == ERROR);
01527
01528
01529 recursion_depth++;
01530 MemoryContextSwitchTo(ErrorContext);
01531
01532 if (++errordata_stack_depth >= ERRORDATA_STACK_SIZE)
01533 {
01534
01535
01536
01537
01538
01539 errordata_stack_depth = -1;
01540 ereport(PANIC, (errmsg_internal("ERRORDATA_STACK_SIZE exceeded")));
01541 }
01542
01543 newedata = &errordata[errordata_stack_depth];
01544 memcpy(newedata, edata, sizeof(ErrorData));
01545
01546
01547 if (newedata->message)
01548 newedata->message = pstrdup(newedata->message);
01549 if (newedata->detail)
01550 newedata->detail = pstrdup(newedata->detail);
01551 if (newedata->detail_log)
01552 newedata->detail_log = pstrdup(newedata->detail_log);
01553 if (newedata->hint)
01554 newedata->hint = pstrdup(newedata->hint);
01555 if (newedata->context)
01556 newedata->context = pstrdup(newedata->context);
01557 if (newedata->schema_name)
01558 newedata->schema_name = pstrdup(newedata->schema_name);
01559 if (newedata->table_name)
01560 newedata->table_name = pstrdup(newedata->table_name);
01561 if (newedata->column_name)
01562 newedata->column_name = pstrdup(newedata->column_name);
01563 if (newedata->datatype_name)
01564 newedata->datatype_name = pstrdup(newedata->datatype_name);
01565 if (newedata->constraint_name)
01566 newedata->constraint_name = pstrdup(newedata->constraint_name);
01567 if (newedata->internalquery)
01568 newedata->internalquery = pstrdup(newedata->internalquery);
01569
01570 recursion_depth--;
01571 PG_RE_THROW();
01572 }
01573
01574
01575
01576
01577 void
01578 pg_re_throw(void)
01579 {
01580
01581 if (PG_exception_stack != NULL)
01582 siglongjmp(*PG_exception_stack, 1);
01583 else
01584 {
01585
01586
01587
01588
01589
01590
01591
01592
01593 ErrorData *edata = &errordata[errordata_stack_depth];
01594
01595 Assert(errordata_stack_depth >= 0);
01596 Assert(edata->elevel == ERROR);
01597 edata->elevel = FATAL;
01598
01599
01600
01601
01602
01603
01604 if (IsPostmasterEnvironment)
01605 edata->output_to_server = is_log_level_output(FATAL,
01606 log_min_messages);
01607 else
01608 edata->output_to_server = (FATAL >= log_min_messages);
01609 if (whereToSendOutput == DestRemote)
01610 {
01611 if (ClientAuthInProgress)
01612 edata->output_to_client = true;
01613 else
01614 edata->output_to_client = (FATAL >= client_min_messages);
01615 }
01616
01617
01618
01619
01620
01621
01622 error_context_stack = NULL;
01623
01624 errfinish(0);
01625 }
01626
01627
01628 ExceptionalCondition("pg_re_throw tried to return", "FailedAssertion",
01629 __FILE__, __LINE__);
01630 }
01631
01632
01633
01634
01635
01636 void
01637 DebugFileOpen(void)
01638 {
01639 int fd,
01640 istty;
01641
01642 if (OutputFileName[0])
01643 {
01644
01645
01646
01647
01648
01649 if ((fd = open(OutputFileName, O_CREAT | O_APPEND | O_WRONLY,
01650 0666)) < 0)
01651 ereport(FATAL,
01652 (errcode_for_file_access(),
01653 errmsg("could not open file \"%s\": %m", OutputFileName)));
01654 istty = isatty(fd);
01655 close(fd);
01656
01657
01658
01659
01660 if (!freopen(OutputFileName, "a", stderr))
01661 ereport(FATAL,
01662 (errcode_for_file_access(),
01663 errmsg("could not reopen file \"%s\" as stderr: %m",
01664 OutputFileName)));
01665
01666
01667
01668
01669
01670
01671
01672 if (istty && IsUnderPostmaster)
01673 if (!freopen(OutputFileName, "a", stdout))
01674 ereport(FATAL,
01675 (errcode_for_file_access(),
01676 errmsg("could not reopen file \"%s\" as stdout: %m",
01677 OutputFileName)));
01678 }
01679 }
01680
01681
01682 #ifdef HAVE_SYSLOG
01683
01684
01685
01686
01687 void
01688 set_syslog_parameters(const char *ident, int facility)
01689 {
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700 if (syslog_ident == NULL || strcmp(syslog_ident, ident) != 0 ||
01701 syslog_facility != facility)
01702 {
01703 if (openlog_done)
01704 {
01705 closelog();
01706 openlog_done = false;
01707 }
01708 if (syslog_ident)
01709 free(syslog_ident);
01710 syslog_ident = strdup(ident);
01711
01712 syslog_facility = facility;
01713 }
01714 }
01715
01716
01717
01718
01719
01720 static void
01721 write_syslog(int level, const char *line)
01722 {
01723 static unsigned long seq = 0;
01724
01725 int len;
01726 const char *nlpos;
01727
01728
01729 if (!openlog_done)
01730 {
01731 openlog(syslog_ident ? syslog_ident : "postgres",
01732 LOG_PID | LOG_NDELAY | LOG_NOWAIT,
01733 syslog_facility);
01734 openlog_done = true;
01735 }
01736
01737
01738
01739
01740
01741 seq++;
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751 len = strlen(line);
01752 nlpos = strchr(line, '\n');
01753 if (len > PG_SYSLOG_LIMIT || nlpos != NULL)
01754 {
01755 int chunk_nr = 0;
01756
01757 while (len > 0)
01758 {
01759 char buf[PG_SYSLOG_LIMIT + 1];
01760 int buflen;
01761 int i;
01762
01763
01764 if (line[0] == '\n')
01765 {
01766 line++;
01767 len--;
01768
01769 nlpos = strchr(line, '\n');
01770 continue;
01771 }
01772
01773
01774 if (nlpos != NULL)
01775 buflen = nlpos - line;
01776 else
01777 buflen = len;
01778 buflen = Min(buflen, PG_SYSLOG_LIMIT);
01779 memcpy(buf, line, buflen);
01780 buf[buflen] = '\0';
01781
01782
01783 buflen = pg_mbcliplen(buf, buflen, buflen);
01784 if (buflen <= 0)
01785 return;
01786 buf[buflen] = '\0';
01787
01788
01789 if (line[buflen] != '\0' &&
01790 !isspace((unsigned char) line[buflen]))
01791 {
01792
01793 i = buflen - 1;
01794 while (i > 0 && !isspace((unsigned char) buf[i]))
01795 i--;
01796
01797 if (i > 0)
01798 {
01799 buflen = i;
01800 buf[i] = '\0';
01801 }
01802 }
01803
01804 chunk_nr++;
01805
01806 syslog(level, "[%lu-%d] %s", seq, chunk_nr, buf);
01807 line += buflen;
01808 len -= buflen;
01809 }
01810 }
01811 else
01812 {
01813
01814 syslog(level, "[%lu] %s", seq, line);
01815 }
01816 }
01817 #endif
01818
01819 #ifdef WIN32
01820
01821
01822
01823 static void
01824 write_eventlog(int level, const char *line, int len)
01825 {
01826 WCHAR *utf16;
01827 int eventlevel = EVENTLOG_ERROR_TYPE;
01828 static HANDLE evtHandle = INVALID_HANDLE_VALUE;
01829
01830 if (evtHandle == INVALID_HANDLE_VALUE)
01831 {
01832 evtHandle = RegisterEventSource(NULL, event_source ? event_source : "PostgreSQL");
01833 if (evtHandle == NULL)
01834 {
01835 evtHandle = INVALID_HANDLE_VALUE;
01836 return;
01837 }
01838 }
01839
01840 switch (level)
01841 {
01842 case DEBUG5:
01843 case DEBUG4:
01844 case DEBUG3:
01845 case DEBUG2:
01846 case DEBUG1:
01847 case LOG:
01848 case COMMERROR:
01849 case INFO:
01850 case NOTICE:
01851 eventlevel = EVENTLOG_INFORMATION_TYPE;
01852 break;
01853 case WARNING:
01854 eventlevel = EVENTLOG_WARNING_TYPE;
01855 break;
01856 case ERROR:
01857 case FATAL:
01858 case PANIC:
01859 default:
01860 eventlevel = EVENTLOG_ERROR_TYPE;
01861 break;
01862 }
01863
01864
01865
01866
01867
01868
01869
01870
01871 if (GetDatabaseEncoding() != GetPlatformEncoding() &&
01872 !in_error_recursion_trouble())
01873 {
01874 utf16 = pgwin32_toUTF16(line, len, NULL);
01875 if (utf16)
01876 {
01877 ReportEventW(evtHandle,
01878 eventlevel,
01879 0,
01880 0,
01881 NULL,
01882 1,
01883 0,
01884 (LPCWSTR *) &utf16,
01885 NULL);
01886
01887 pfree(utf16);
01888 return;
01889 }
01890 }
01891 ReportEventA(evtHandle,
01892 eventlevel,
01893 0,
01894 0,
01895 NULL,
01896 1,
01897 0,
01898 &line,
01899 NULL);
01900 }
01901 #endif
01902
01903 static void
01904 write_console(const char *line, int len)
01905 {
01906 int rc;
01907
01908 #ifdef WIN32
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918 if (GetDatabaseEncoding() != GetPlatformEncoding() &&
01919 !in_error_recursion_trouble() &&
01920 !redirection_done &&
01921 CurrentMemoryContext != NULL)
01922 {
01923 WCHAR *utf16;
01924 int utf16len;
01925
01926 utf16 = pgwin32_toUTF16(line, len, &utf16len);
01927 if (utf16 != NULL)
01928 {
01929 HANDLE stdHandle;
01930 DWORD written;
01931
01932 stdHandle = GetStdHandle(STD_ERROR_HANDLE);
01933 if (WriteConsoleW(stdHandle, utf16, utf16len, &written, NULL))
01934 {
01935 pfree(utf16);
01936 return;
01937 }
01938
01939
01940
01941
01942
01943 pfree(utf16);
01944 }
01945 }
01946 #else
01947
01948
01949
01950
01951
01952
01953 #endif
01954
01955
01956
01957
01958
01959 rc = write(fileno(stderr), line, len);
01960 (void) rc;
01961 }
01962
01963
01964
01965
01966 static void
01967 setup_formatted_log_time(void)
01968 {
01969 struct timeval tv;
01970 pg_time_t stamp_time;
01971 char msbuf[8];
01972
01973 gettimeofday(&tv, NULL);
01974 stamp_time = (pg_time_t) tv.tv_sec;
01975
01976
01977
01978
01979
01980
01981 pg_strftime(formatted_log_time, FORMATTED_TS_LEN,
01982
01983 "%Y-%m-%d %H:%M:%S %Z",
01984 pg_localtime(&stamp_time, log_timezone));
01985
01986
01987 sprintf(msbuf, ".%03d", (int) (tv.tv_usec / 1000));
01988 strncpy(formatted_log_time + 19, msbuf, 4);
01989 }
01990
01991
01992
01993
01994 static void
01995 setup_formatted_start_time(void)
01996 {
01997 pg_time_t stamp_time = (pg_time_t) MyStartTime;
01998
01999
02000
02001
02002
02003
02004 pg_strftime(formatted_start_time, FORMATTED_TS_LEN,
02005 "%Y-%m-%d %H:%M:%S %Z",
02006 pg_localtime(&stamp_time, log_timezone));
02007 }
02008
02009
02010
02011
02012 static void
02013 log_line_prefix(StringInfo buf, ErrorData *edata)
02014 {
02015
02016 static long log_line_number = 0;
02017
02018
02019 static int log_my_pid = 0;
02020
02021 int format_len;
02022 int i;
02023
02024
02025
02026
02027
02028
02029
02030 if (log_my_pid != MyProcPid)
02031 {
02032 log_line_number = 0;
02033 log_my_pid = MyProcPid;
02034 formatted_start_time[0] = '\0';
02035 }
02036 log_line_number++;
02037
02038 if (Log_line_prefix == NULL)
02039 return;
02040
02041 format_len = strlen(Log_line_prefix);
02042
02043 for (i = 0; i < format_len; i++)
02044 {
02045 if (Log_line_prefix[i] != '%')
02046 {
02047
02048 appendStringInfoChar(buf, Log_line_prefix[i]);
02049 continue;
02050 }
02051
02052 i++;
02053 if (i >= format_len)
02054 break;
02055
02056
02057 switch (Log_line_prefix[i])
02058 {
02059 case 'a':
02060 if (MyProcPort)
02061 {
02062 const char *appname = application_name;
02063
02064 if (appname == NULL || *appname == '\0')
02065 appname = _("[unknown]");
02066 appendStringInfoString(buf, appname);
02067 }
02068 break;
02069 case 'u':
02070 if (MyProcPort)
02071 {
02072 const char *username = MyProcPort->user_name;
02073
02074 if (username == NULL || *username == '\0')
02075 username = _("[unknown]");
02076 appendStringInfoString(buf, username);
02077 }
02078 break;
02079 case 'd':
02080 if (MyProcPort)
02081 {
02082 const char *dbname = MyProcPort->database_name;
02083
02084 if (dbname == NULL || *dbname == '\0')
02085 dbname = _("[unknown]");
02086 appendStringInfoString(buf, dbname);
02087 }
02088 break;
02089 case 'c':
02090 appendStringInfo(buf, "%lx.%04x", (long) (MyStartTime), MyProcPid);
02091 break;
02092 case 'p':
02093 appendStringInfo(buf, "%d", MyProcPid);
02094 break;
02095 case 'l':
02096 appendStringInfo(buf, "%ld", log_line_number);
02097 break;
02098 case 'm':
02099 setup_formatted_log_time();
02100 appendStringInfoString(buf, formatted_log_time);
02101 break;
02102 case 't':
02103 {
02104 pg_time_t stamp_time = (pg_time_t) time(NULL);
02105 char strfbuf[128];
02106
02107 pg_strftime(strfbuf, sizeof(strfbuf),
02108 "%Y-%m-%d %H:%M:%S %Z",
02109 pg_localtime(&stamp_time, log_timezone));
02110 appendStringInfoString(buf, strfbuf);
02111 }
02112 break;
02113 case 's':
02114 if (formatted_start_time[0] == '\0')
02115 setup_formatted_start_time();
02116 appendStringInfoString(buf, formatted_start_time);
02117 break;
02118 case 'i':
02119 if (MyProcPort)
02120 {
02121 const char *psdisp;
02122 int displen;
02123
02124 psdisp = get_ps_display(&displen);
02125 appendBinaryStringInfo(buf, psdisp, displen);
02126 }
02127 break;
02128 case 'r':
02129 if (MyProcPort && MyProcPort->remote_host)
02130 {
02131 appendStringInfoString(buf, MyProcPort->remote_host);
02132 if (MyProcPort->remote_port &&
02133 MyProcPort->remote_port[0] != '\0')
02134 appendStringInfo(buf, "(%s)",
02135 MyProcPort->remote_port);
02136 }
02137 break;
02138 case 'h':
02139 if (MyProcPort && MyProcPort->remote_host)
02140 appendStringInfoString(buf, MyProcPort->remote_host);
02141 break;
02142 case 'q':
02143
02144
02145 if (MyProcPort == NULL)
02146 i = format_len;
02147 break;
02148 case 'v':
02149
02150 if (MyProc != NULL && MyProc->backendId != InvalidBackendId)
02151 appendStringInfo(buf, "%d/%u",
02152 MyProc->backendId, MyProc->lxid);
02153 break;
02154 case 'x':
02155 appendStringInfo(buf, "%u", GetTopTransactionIdIfAny());
02156 break;
02157 case 'e':
02158 appendStringInfoString(buf, unpack_sql_state(edata->sqlerrcode));
02159 break;
02160 case '%':
02161 appendStringInfoChar(buf, '%');
02162 break;
02163 default:
02164
02165 break;
02166 }
02167 }
02168 }
02169
02170
02171
02172
02173
02174
02175 static inline void
02176 appendCSVLiteral(StringInfo buf, const char *data)
02177 {
02178 const char *p = data;
02179 char c;
02180
02181
02182 if (p == NULL)
02183 return;
02184
02185 appendStringInfoCharMacro(buf, '"');
02186 while ((c = *p++) != '\0')
02187 {
02188 if (c == '"')
02189 appendStringInfoCharMacro(buf, '"');
02190 appendStringInfoCharMacro(buf, c);
02191 }
02192 appendStringInfoCharMacro(buf, '"');
02193 }
02194
02195
02196
02197
02198
02199 static void
02200 write_csvlog(ErrorData *edata)
02201 {
02202 StringInfoData buf;
02203 bool print_stmt = false;
02204
02205
02206 static long log_line_number = 0;
02207
02208
02209 static int log_my_pid = 0;
02210
02211
02212
02213
02214
02215
02216 if (log_my_pid != MyProcPid)
02217 {
02218 log_line_number = 0;
02219 log_my_pid = MyProcPid;
02220 formatted_start_time[0] = '\0';
02221 }
02222 log_line_number++;
02223
02224 initStringInfo(&buf);
02225
02226
02227
02228
02229
02230
02231
02232
02233 if (formatted_log_time[0] == '\0')
02234 setup_formatted_log_time();
02235
02236 appendStringInfoString(&buf, formatted_log_time);
02237 appendStringInfoChar(&buf, ',');
02238
02239
02240 if (MyProcPort)
02241 appendCSVLiteral(&buf, MyProcPort->user_name);
02242 appendStringInfoChar(&buf, ',');
02243
02244
02245 if (MyProcPort)
02246 appendCSVLiteral(&buf, MyProcPort->database_name);
02247 appendStringInfoChar(&buf, ',');
02248
02249
02250 if (MyProcPid != 0)
02251 appendStringInfo(&buf, "%d", MyProcPid);
02252 appendStringInfoChar(&buf, ',');
02253
02254
02255 if (MyProcPort && MyProcPort->remote_host)
02256 {
02257 appendStringInfoChar(&buf, '"');
02258 appendStringInfoString(&buf, MyProcPort->remote_host);
02259 if (MyProcPort->remote_port && MyProcPort->remote_port[0] != '\0')
02260 {
02261 appendStringInfoChar(&buf, ':');
02262 appendStringInfoString(&buf, MyProcPort->remote_port);
02263 }
02264 appendStringInfoChar(&buf, '"');
02265 }
02266 appendStringInfoChar(&buf, ',');
02267
02268
02269 appendStringInfo(&buf, "%lx.%04x", (long) MyStartTime, MyProcPid);
02270 appendStringInfoChar(&buf, ',');
02271
02272
02273 appendStringInfo(&buf, "%ld", log_line_number);
02274 appendStringInfoChar(&buf, ',');
02275
02276
02277 if (MyProcPort)
02278 {
02279 StringInfoData msgbuf;
02280 const char *psdisp;
02281 int displen;
02282
02283 initStringInfo(&msgbuf);
02284
02285 psdisp = get_ps_display(&displen);
02286 appendBinaryStringInfo(&msgbuf, psdisp, displen);
02287 appendCSVLiteral(&buf, msgbuf.data);
02288
02289 pfree(msgbuf.data);
02290 }
02291 appendStringInfoChar(&buf, ',');
02292
02293
02294 if (formatted_start_time[0] == '\0')
02295 setup_formatted_start_time();
02296 appendStringInfoString(&buf, formatted_start_time);
02297 appendStringInfoChar(&buf, ',');
02298
02299
02300
02301 if (MyProc != NULL && MyProc->backendId != InvalidBackendId)
02302 appendStringInfo(&buf, "%d/%u", MyProc->backendId, MyProc->lxid);
02303 appendStringInfoChar(&buf, ',');
02304
02305
02306 appendStringInfo(&buf, "%u", GetTopTransactionIdIfAny());
02307 appendStringInfoChar(&buf, ',');
02308
02309
02310 appendStringInfoString(&buf, error_severity(edata->elevel));
02311 appendStringInfoChar(&buf, ',');
02312
02313
02314 appendStringInfoString(&buf, unpack_sql_state(edata->sqlerrcode));
02315 appendStringInfoChar(&buf, ',');
02316
02317
02318 appendCSVLiteral(&buf, edata->message);
02319 appendStringInfoChar(&buf, ',');
02320
02321
02322 if (edata->detail_log)
02323 appendCSVLiteral(&buf, edata->detail_log);
02324 else
02325 appendCSVLiteral(&buf, edata->detail);
02326 appendStringInfoChar(&buf, ',');
02327
02328
02329 appendCSVLiteral(&buf, edata->hint);
02330 appendStringInfoChar(&buf, ',');
02331
02332
02333 appendCSVLiteral(&buf, edata->internalquery);
02334 appendStringInfoChar(&buf, ',');
02335
02336
02337 if (edata->internalpos > 0 && edata->internalquery != NULL)
02338 appendStringInfo(&buf, "%d", edata->internalpos);
02339 appendStringInfoChar(&buf, ',');
02340
02341
02342 appendCSVLiteral(&buf, edata->context);
02343 appendStringInfoChar(&buf, ',');
02344
02345
02346 if (is_log_level_output(edata->elevel, log_min_error_statement) &&
02347 debug_query_string != NULL &&
02348 !edata->hide_stmt)
02349 print_stmt = true;
02350 if (print_stmt)
02351 appendCSVLiteral(&buf, debug_query_string);
02352 appendStringInfoChar(&buf, ',');
02353 if (print_stmt && edata->cursorpos > 0)
02354 appendStringInfo(&buf, "%d", edata->cursorpos);
02355 appendStringInfoChar(&buf, ',');
02356
02357
02358 if (Log_error_verbosity >= PGERROR_VERBOSE)
02359 {
02360 StringInfoData msgbuf;
02361
02362 initStringInfo(&msgbuf);
02363
02364 if (edata->funcname && edata->filename)
02365 appendStringInfo(&msgbuf, "%s, %s:%d",
02366 edata->funcname, edata->filename,
02367 edata->lineno);
02368 else if (edata->filename)
02369 appendStringInfo(&msgbuf, "%s:%d",
02370 edata->filename, edata->lineno);
02371 appendCSVLiteral(&buf, msgbuf.data);
02372 pfree(msgbuf.data);
02373 }
02374 appendStringInfoChar(&buf, ',');
02375
02376
02377 if (application_name)
02378 appendCSVLiteral(&buf, application_name);
02379
02380 appendStringInfoChar(&buf, '\n');
02381
02382
02383 if (am_syslogger)
02384 write_syslogger_file(buf.data, buf.len, LOG_DESTINATION_CSVLOG);
02385 else
02386 write_pipe_chunks(buf.data, buf.len, LOG_DESTINATION_CSVLOG);
02387
02388 pfree(buf.data);
02389 }
02390
02391
02392
02393
02394
02395 char *
02396 unpack_sql_state(int sql_state)
02397 {
02398 static char buf[12];
02399 int i;
02400
02401 for (i = 0; i < 5; i++)
02402 {
02403 buf[i] = PGUNSIXBIT(sql_state);
02404 sql_state >>= 6;
02405 }
02406
02407 buf[i] = '\0';
02408 return buf;
02409 }
02410
02411
02412
02413
02414
02415 static void
02416 send_message_to_server_log(ErrorData *edata)
02417 {
02418 StringInfoData buf;
02419
02420 initStringInfo(&buf);
02421
02422 formatted_log_time[0] = '\0';
02423
02424 log_line_prefix(&buf, edata);
02425 appendStringInfo(&buf, "%s: ", error_severity(edata->elevel));
02426
02427 if (Log_error_verbosity >= PGERROR_VERBOSE)
02428 appendStringInfo(&buf, "%s: ", unpack_sql_state(edata->sqlerrcode));
02429
02430 if (edata->message)
02431 append_with_tabs(&buf, edata->message);
02432 else
02433 append_with_tabs(&buf, _("missing error text"));
02434
02435 if (edata->cursorpos > 0)
02436 appendStringInfo(&buf, _(" at character %d"),
02437 edata->cursorpos);
02438 else if (edata->internalpos > 0)
02439 appendStringInfo(&buf, _(" at character %d"),
02440 edata->internalpos);
02441
02442 appendStringInfoChar(&buf, '\n');
02443
02444 if (Log_error_verbosity >= PGERROR_DEFAULT)
02445 {
02446 if (edata->detail_log)
02447 {
02448 log_line_prefix(&buf, edata);
02449 appendStringInfoString(&buf, _("DETAIL: "));
02450 append_with_tabs(&buf, edata->detail_log);
02451 appendStringInfoChar(&buf, '\n');
02452 }
02453 else if (edata->detail)
02454 {
02455 log_line_prefix(&buf, edata);
02456 appendStringInfoString(&buf, _("DETAIL: "));
02457 append_with_tabs(&buf, edata->detail);
02458 appendStringInfoChar(&buf, '\n');
02459 }
02460 if (edata->hint)
02461 {
02462 log_line_prefix(&buf, edata);
02463 appendStringInfoString(&buf, _("HINT: "));
02464 append_with_tabs(&buf, edata->hint);
02465 appendStringInfoChar(&buf, '\n');
02466 }
02467 if (edata->internalquery)
02468 {
02469 log_line_prefix(&buf, edata);
02470 appendStringInfoString(&buf, _("QUERY: "));
02471 append_with_tabs(&buf, edata->internalquery);
02472 appendStringInfoChar(&buf, '\n');
02473 }
02474 if (edata->context)
02475 {
02476 log_line_prefix(&buf, edata);
02477 appendStringInfoString(&buf, _("CONTEXT: "));
02478 append_with_tabs(&buf, edata->context);
02479 appendStringInfoChar(&buf, '\n');
02480 }
02481 if (Log_error_verbosity >= PGERROR_VERBOSE)
02482 {
02483
02484 if (edata->funcname && edata->filename)
02485 {
02486 log_line_prefix(&buf, edata);
02487 appendStringInfo(&buf, _("LOCATION: %s, %s:%d\n"),
02488 edata->funcname, edata->filename,
02489 edata->lineno);
02490 }
02491 else if (edata->filename)
02492 {
02493 log_line_prefix(&buf, edata);
02494 appendStringInfo(&buf, _("LOCATION: %s:%d\n"),
02495 edata->filename, edata->lineno);
02496 }
02497 }
02498 }
02499
02500
02501
02502
02503 if (is_log_level_output(edata->elevel, log_min_error_statement) &&
02504 debug_query_string != NULL &&
02505 !edata->hide_stmt)
02506 {
02507 log_line_prefix(&buf, edata);
02508 appendStringInfoString(&buf, _("STATEMENT: "));
02509 append_with_tabs(&buf, debug_query_string);
02510 appendStringInfoChar(&buf, '\n');
02511 }
02512
02513 #ifdef HAVE_SYSLOG
02514
02515 if (Log_destination & LOG_DESTINATION_SYSLOG)
02516 {
02517 int syslog_level;
02518
02519 switch (edata->elevel)
02520 {
02521 case DEBUG5:
02522 case DEBUG4:
02523 case DEBUG3:
02524 case DEBUG2:
02525 case DEBUG1:
02526 syslog_level = LOG_DEBUG;
02527 break;
02528 case LOG:
02529 case COMMERROR:
02530 case INFO:
02531 syslog_level = LOG_INFO;
02532 break;
02533 case NOTICE:
02534 case WARNING:
02535 syslog_level = LOG_NOTICE;
02536 break;
02537 case ERROR:
02538 syslog_level = LOG_WARNING;
02539 break;
02540 case FATAL:
02541 syslog_level = LOG_ERR;
02542 break;
02543 case PANIC:
02544 default:
02545 syslog_level = LOG_CRIT;
02546 break;
02547 }
02548
02549 write_syslog(syslog_level, buf.data);
02550 }
02551 #endif
02552
02553 #ifdef WIN32
02554
02555 if (Log_destination & LOG_DESTINATION_EVENTLOG)
02556 {
02557 write_eventlog(edata->elevel, buf.data, buf.len);
02558 }
02559 #endif
02560
02561
02562 if ((Log_destination & LOG_DESTINATION_STDERR) || whereToSendOutput == DestDebug)
02563 {
02564
02565
02566
02567
02568
02569 if (redirection_done && !am_syslogger)
02570 write_pipe_chunks(buf.data, buf.len, LOG_DESTINATION_STDERR);
02571 #ifdef WIN32
02572
02573
02574
02575
02576
02577
02578
02579
02580 else if (pgwin32_is_service())
02581 write_eventlog(edata->elevel, buf.data, buf.len);
02582 #endif
02583 else
02584 write_console(buf.data, buf.len);
02585 }
02586
02587
02588 if (am_syslogger)
02589 write_syslogger_file(buf.data, buf.len, LOG_DESTINATION_STDERR);
02590
02591
02592 if (Log_destination & LOG_DESTINATION_CSVLOG)
02593 {
02594 if (redirection_done || am_syslogger)
02595 {
02596
02597
02598
02599
02600 pfree(buf.data);
02601 write_csvlog(edata);
02602 }
02603 else
02604 {
02605
02606
02607
02608
02609 if (!(Log_destination & LOG_DESTINATION_STDERR) &&
02610 whereToSendOutput != DestDebug)
02611 write_console(buf.data, buf.len);
02612 pfree(buf.data);
02613 }
02614 }
02615 else
02616 {
02617 pfree(buf.data);
02618 }
02619 }
02620
02621
02622
02623
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637
02638
02639
02640
02641 static void
02642 write_pipe_chunks(char *data, int len, int dest)
02643 {
02644 PipeProtoChunk p;
02645 int fd = fileno(stderr);
02646 int rc;
02647
02648 Assert(len > 0);
02649
02650 p.proto.nuls[0] = p.proto.nuls[1] = '\0';
02651 p.proto.pid = MyProcPid;
02652
02653
02654 while (len > PIPE_MAX_PAYLOAD)
02655 {
02656 p.proto.is_last = (dest == LOG_DESTINATION_CSVLOG ? 'F' : 'f');
02657 p.proto.len = PIPE_MAX_PAYLOAD;
02658 memcpy(p.proto.data, data, PIPE_MAX_PAYLOAD);
02659 rc = write(fd, &p, PIPE_HEADER_SIZE + PIPE_MAX_PAYLOAD);
02660 (void) rc;
02661 data += PIPE_MAX_PAYLOAD;
02662 len -= PIPE_MAX_PAYLOAD;
02663 }
02664
02665
02666 p.proto.is_last = (dest == LOG_DESTINATION_CSVLOG ? 'T' : 't');
02667 p.proto.len = len;
02668 memcpy(p.proto.data, data, len);
02669 rc = write(fd, &p, PIPE_HEADER_SIZE + len);
02670 (void) rc;
02671 }
02672
02673
02674
02675
02676
02677
02678
02679
02680
02681
02682
02683
02684
02685 static void
02686 err_sendstring(StringInfo buf, const char *str)
02687 {
02688 if (in_error_recursion_trouble())
02689 pq_send_ascii_string(buf, str);
02690 else
02691 pq_sendstring(buf, str);
02692 }
02693
02694
02695
02696
02697 static void
02698 send_message_to_frontend(ErrorData *edata)
02699 {
02700 StringInfoData msgbuf;
02701
02702
02703 pq_beginmessage(&msgbuf, (edata->elevel < ERROR) ? 'N' : 'E');
02704
02705 if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3)
02706 {
02707
02708 char tbuf[12];
02709 int ssval;
02710 int i;
02711
02712 pq_sendbyte(&msgbuf, PG_DIAG_SEVERITY);
02713 err_sendstring(&msgbuf, error_severity(edata->elevel));
02714
02715
02716 ssval = edata->sqlerrcode;
02717 for (i = 0; i < 5; i++)
02718 {
02719 tbuf[i] = PGUNSIXBIT(ssval);
02720 ssval >>= 6;
02721 }
02722 tbuf[i] = '\0';
02723
02724 pq_sendbyte(&msgbuf, PG_DIAG_SQLSTATE);
02725 err_sendstring(&msgbuf, tbuf);
02726
02727
02728 pq_sendbyte(&msgbuf, PG_DIAG_MESSAGE_PRIMARY);
02729 if (edata->message)
02730 err_sendstring(&msgbuf, edata->message);
02731 else
02732 err_sendstring(&msgbuf, _("missing error text"));
02733
02734 if (edata->detail)
02735 {
02736 pq_sendbyte(&msgbuf, PG_DIAG_MESSAGE_DETAIL);
02737 err_sendstring(&msgbuf, edata->detail);
02738 }
02739
02740
02741
02742 if (edata->hint)
02743 {
02744 pq_sendbyte(&msgbuf, PG_DIAG_MESSAGE_HINT);
02745 err_sendstring(&msgbuf, edata->hint);
02746 }
02747
02748 if (edata->context)
02749 {
02750 pq_sendbyte(&msgbuf, PG_DIAG_CONTEXT);
02751 err_sendstring(&msgbuf, edata->context);
02752 }
02753
02754 if (edata->schema_name)
02755 {
02756 pq_sendbyte(&msgbuf, PG_DIAG_SCHEMA_NAME);
02757 err_sendstring(&msgbuf, edata->schema_name);
02758 }
02759
02760 if (edata->table_name)
02761 {
02762 pq_sendbyte(&msgbuf, PG_DIAG_TABLE_NAME);
02763 err_sendstring(&msgbuf, edata->table_name);
02764 }
02765
02766 if (edata->column_name)
02767 {
02768 pq_sendbyte(&msgbuf, PG_DIAG_COLUMN_NAME);
02769 err_sendstring(&msgbuf, edata->column_name);
02770 }
02771
02772 if (edata->datatype_name)
02773 {
02774 pq_sendbyte(&msgbuf, PG_DIAG_DATATYPE_NAME);
02775 err_sendstring(&msgbuf, edata->datatype_name);
02776 }
02777
02778 if (edata->constraint_name)
02779 {
02780 pq_sendbyte(&msgbuf, PG_DIAG_CONSTRAINT_NAME);
02781 err_sendstring(&msgbuf, edata->constraint_name);
02782 }
02783
02784 if (edata->cursorpos > 0)
02785 {
02786 snprintf(tbuf, sizeof(tbuf), "%d", edata->cursorpos);
02787 pq_sendbyte(&msgbuf, PG_DIAG_STATEMENT_POSITION);
02788 err_sendstring(&msgbuf, tbuf);
02789 }
02790
02791 if (edata->internalpos > 0)
02792 {
02793 snprintf(tbuf, sizeof(tbuf), "%d", edata->internalpos);
02794 pq_sendbyte(&msgbuf, PG_DIAG_INTERNAL_POSITION);
02795 err_sendstring(&msgbuf, tbuf);
02796 }
02797
02798 if (edata->internalquery)
02799 {
02800 pq_sendbyte(&msgbuf, PG_DIAG_INTERNAL_QUERY);
02801 err_sendstring(&msgbuf, edata->internalquery);
02802 }
02803
02804 if (edata->filename)
02805 {
02806 pq_sendbyte(&msgbuf, PG_DIAG_SOURCE_FILE);
02807 err_sendstring(&msgbuf, edata->filename);
02808 }
02809
02810 if (edata->lineno > 0)
02811 {
02812 snprintf(tbuf, sizeof(tbuf), "%d", edata->lineno);
02813 pq_sendbyte(&msgbuf, PG_DIAG_SOURCE_LINE);
02814 err_sendstring(&msgbuf, tbuf);
02815 }
02816
02817 if (edata->funcname)
02818 {
02819 pq_sendbyte(&msgbuf, PG_DIAG_SOURCE_FUNCTION);
02820 err_sendstring(&msgbuf, edata->funcname);
02821 }
02822
02823 pq_sendbyte(&msgbuf, '\0');
02824 }
02825 else
02826 {
02827
02828 StringInfoData buf;
02829
02830 initStringInfo(&buf);
02831
02832 appendStringInfo(&buf, "%s: ", error_severity(edata->elevel));
02833
02834 if (edata->show_funcname && edata->funcname)
02835 appendStringInfo(&buf, "%s: ", edata->funcname);
02836
02837 if (edata->message)
02838 appendStringInfoString(&buf, edata->message);
02839 else
02840 appendStringInfoString(&buf, _("missing error text"));
02841
02842 if (edata->cursorpos > 0)
02843 appendStringInfo(&buf, _(" at character %d"),
02844 edata->cursorpos);
02845 else if (edata->internalpos > 0)
02846 appendStringInfo(&buf, _(" at character %d"),
02847 edata->internalpos);
02848
02849 appendStringInfoChar(&buf, '\n');
02850
02851 err_sendstring(&msgbuf, buf.data);
02852
02853 pfree(buf.data);
02854 }
02855
02856 pq_endmessage(&msgbuf);
02857
02858
02859
02860
02861
02862
02863
02864
02865
02866 pq_flush();
02867 }
02868
02869
02870
02871
02872
02873
02874
02875
02876
02877
02878
02879
02880
02881
02882
02883 static char *
02884 expand_fmt_string(const char *fmt, ErrorData *edata)
02885 {
02886 StringInfoData buf;
02887 const char *cp;
02888
02889 initStringInfo(&buf);
02890
02891 for (cp = fmt; *cp; cp++)
02892 {
02893 if (cp[0] == '%' && cp[1] != '\0')
02894 {
02895 cp++;
02896 if (*cp == 'm')
02897 {
02898
02899
02900
02901
02902
02903 const char *cp2;
02904
02905 cp2 = useful_strerror(edata->saved_errno);
02906 for (; *cp2; cp2++)
02907 {
02908 if (*cp2 == '%')
02909 appendStringInfoCharMacro(&buf, '%');
02910 appendStringInfoCharMacro(&buf, *cp2);
02911 }
02912 }
02913 else
02914 {
02915
02916 appendStringInfoCharMacro(&buf, '%');
02917 appendStringInfoCharMacro(&buf, *cp);
02918 }
02919 }
02920 else
02921 appendStringInfoCharMacro(&buf, *cp);
02922 }
02923
02924 return buf.data;
02925 }
02926
02927
02928
02929
02930
02931 static const char *
02932 useful_strerror(int errnum)
02933 {
02934
02935 static char errorstr_buf[48];
02936 const char *str;
02937
02938 #ifdef WIN32
02939
02940 if (errnum >= 10000 && errnum <= 11999)
02941 return pgwin32_socket_strerror(errnum);
02942 #endif
02943 str = strerror(errnum);
02944
02945
02946
02947
02948
02949 if (str == NULL || *str == '\0')
02950 {
02951 snprintf(errorstr_buf, sizeof(errorstr_buf),
02952
02953
02954
02955 _("operating system error %d"), errnum);
02956 str = errorstr_buf;
02957 }
02958
02959 return str;
02960 }
02961
02962
02963
02964
02965
02966 static const char *
02967 error_severity(int elevel)
02968 {
02969 const char *prefix;
02970
02971 switch (elevel)
02972 {
02973 case DEBUG1:
02974 case DEBUG2:
02975 case DEBUG3:
02976 case DEBUG4:
02977 case DEBUG5:
02978 prefix = _("DEBUG");
02979 break;
02980 case LOG:
02981 case COMMERROR:
02982 prefix = _("LOG");
02983 break;
02984 case INFO:
02985 prefix = _("INFO");
02986 break;
02987 case NOTICE:
02988 prefix = _("NOTICE");
02989 break;
02990 case WARNING:
02991 prefix = _("WARNING");
02992 break;
02993 case ERROR:
02994 prefix = _("ERROR");
02995 break;
02996 case FATAL:
02997 prefix = _("FATAL");
02998 break;
02999 case PANIC:
03000 prefix = _("PANIC");
03001 break;
03002 default:
03003 prefix = "???";
03004 break;
03005 }
03006
03007 return prefix;
03008 }
03009
03010
03011
03012
03013
03014
03015
03016
03017 static void
03018 append_with_tabs(StringInfo buf, const char *str)
03019 {
03020 char ch;
03021
03022 while ((ch = *str++) != '\0')
03023 {
03024 appendStringInfoCharMacro(buf, ch);
03025 if (ch == '\n')
03026 appendStringInfoCharMacro(buf, '\t');
03027 }
03028 }
03029
03030
03031
03032
03033
03034
03035
03036 void
03037 write_stderr(const char *fmt,...)
03038 {
03039 va_list ap;
03040
03041 #ifdef WIN32
03042 char errbuf[2048];
03043 #endif
03044
03045 fmt = _(fmt);
03046
03047 va_start(ap, fmt);
03048 #ifndef WIN32
03049
03050 vfprintf(stderr, fmt, ap);
03051 fflush(stderr);
03052 #else
03053 vsnprintf(errbuf, sizeof(errbuf), fmt, ap);
03054
03055
03056
03057
03058
03059 if (pgwin32_is_service())
03060 {
03061 write_eventlog(ERROR, errbuf, strlen(errbuf));
03062 }
03063 else
03064 {
03065
03066 write_console(errbuf, strlen(errbuf));
03067 fflush(stderr);
03068 }
03069 #endif
03070 va_end(ap);
03071 }
03072
03073
03074
03075
03076
03077
03078
03079
03080
03081
03082 static bool
03083 is_log_level_output(int elevel, int log_min_level)
03084 {
03085 if (elevel == LOG || elevel == COMMERROR)
03086 {
03087 if (log_min_level == LOG || log_min_level <= ERROR)
03088 return true;
03089 }
03090 else if (log_min_level == LOG)
03091 {
03092
03093 if (elevel >= FATAL)
03094 return true;
03095 }
03096
03097 else if (elevel >= log_min_level)
03098 return true;
03099
03100 return false;
03101 }
03102
03103
03104
03105
03106
03107
03108
03109
03110
03111
03112
03113
03114
03115
03116
03117
03118 int
03119 trace_recovery(int trace_level)
03120 {
03121 if (trace_level < LOG &&
03122 trace_level >= trace_recovery_messages)
03123 return LOG;
03124
03125 return trace_level;
03126 }