|
3 | 3 | * show.c: show backup information.
|
4 | 4 | *
|
5 | 5 | * Portions Copyright (c) 2009-2011, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
|
6 |
| - * Portions Copyright (c) 2015-2019, Postgres Professional |
| 6 | + * Portions Copyright (c) 2015-2022, Postgres Professional |
7 | 7 | *
|
8 | 8 | *-------------------------------------------------------------------------
|
9 | 9 | */
|
|
12 | 12 |
|
13 | 13 | #include <time.h>
|
14 | 14 | #include <dirent.h>
|
| 15 | +#include <locale.h> |
15 | 16 | #include <sys/stat.h>
|
16 | 17 |
|
17 | 18 | #include "utils/json.h"
|
@@ -71,6 +72,43 @@ static PQExpBufferData show_buf;
|
71 | 72 | static bool first_instance = true;
|
72 | 73 | static int32 json_level = 0;
|
73 | 74 |
|
| 75 | +static const char* lc_env_locale; |
| 76 | +typedef enum { |
| 77 | + LOCALE_C, // Used for formatting output to unify the dot-based floating point representation |
| 78 | + LOCALE_ENV // Default environment locale |
| 79 | +} output_numeric_locale; |
| 80 | + |
| 81 | +#ifdef HAVE_USELOCALE |
| 82 | +static locale_t env_locale, c_locale; |
| 83 | +#endif |
| 84 | +void memorize_environment_locale() { |
| 85 | + lc_env_locale = (const char *)getenv("LC_NUMERIC"); |
| 86 | + lc_env_locale = lc_env_locale != NULL ? lc_env_locale : "C"; |
| 87 | +#ifdef HAVE_USELOCALE |
| 88 | + env_locale = newlocale(LC_NUMERIC_MASK, lc_env_locale, (locale_t)0); |
| 89 | + c_locale = newlocale(LC_NUMERIC_MASK, "C", (locale_t)0); |
| 90 | +#else |
| 91 | +#ifdef HAVE__CONFIGTHREADLOCALE |
| 92 | + _configthreadlocale(_ENABLE_PER_THREAD_LOCALE); |
| 93 | +#endif |
| 94 | +#endif |
| 95 | +} |
| 96 | + |
| 97 | +void free_environment_locale() { |
| 98 | +#ifdef HAVE_USELOCALE |
| 99 | + freelocale(env_locale); |
| 100 | + freelocale(c_locale); |
| 101 | +#endif |
| 102 | +} |
| 103 | + |
| 104 | +static void set_output_numeric_locale(output_numeric_locale loc) { |
| 105 | +#ifdef HAVE_USELOCALE |
| 106 | + uselocale(loc == LOCALE_C ? c_locale : env_locale); |
| 107 | +#else |
| 108 | + setlocale(LC_NUMERIC, loc == LOCALE_C ? "C" : lc_env_locale); |
| 109 | +#endif |
| 110 | +} |
| 111 | + |
74 | 112 | /*
|
75 | 113 | * Entry point of pg_probackup SHOW subcommand.
|
76 | 114 | */
|
@@ -513,6 +551,9 @@ show_instance_plain(const char *instance_name, parray *backup_list, bool show_na
|
513 | 551 | ShowBackendRow *rows;
|
514 | 552 | TimeLineID parent_tli = 0;
|
515 | 553 |
|
| 554 | + // Since we've been printing a table, set LC_NUMERIC to its default environment value |
| 555 | + set_output_numeric_locale(LOCALE_ENV); |
| 556 | + |
516 | 557 | for (i = 0; i < SHOW_FIELDS_COUNT; i++)
|
517 | 558 | widths[i] = strlen(names[i]);
|
518 | 559 |
|
@@ -726,6 +767,8 @@ show_instance_plain(const char *instance_name, parray *backup_list, bool show_na
|
726 | 767 | }
|
727 | 768 |
|
728 | 769 | pfree(rows);
|
| 770 | + // Restore the C locale |
| 771 | + set_output_numeric_locale(LOCALE_C); |
729 | 772 | }
|
730 | 773 |
|
731 | 774 | /*
|
@@ -806,6 +849,9 @@ show_archive_plain(const char *instance_name, uint32 xlog_seg_size,
|
806 | 849 | uint32 widths_sum = 0;
|
807 | 850 | ShowArchiveRow *rows;
|
808 | 851 |
|
| 852 | + // Since we've been printing a table, set LC_NUMERIC to its default environment value |
| 853 | + set_output_numeric_locale(LOCALE_ENV); |
| 854 | + |
809 | 855 | for (i = 0; i < SHOW_ARCHIVE_FIELDS_COUNT; i++)
|
810 | 856 | widths[i] = strlen(names[i]);
|
811 | 857 |
|
@@ -973,6 +1019,8 @@ show_archive_plain(const char *instance_name, uint32 xlog_seg_size,
|
973 | 1019 | }
|
974 | 1020 |
|
975 | 1021 | pfree(rows);
|
| 1022 | + // Restore the C locale |
| 1023 | + set_output_numeric_locale(LOCALE_C); |
976 | 1024 | //TODO: free timelines
|
977 | 1025 | }
|
978 | 1026 |
|
@@ -1045,8 +1093,9 @@ show_archive_json(const char *instance_name, uint32 xlog_seg_size,
|
1045 | 1093 | appendPQExpBuffer(buf, "%lu", tlinfo->size);
|
1046 | 1094 |
|
1047 | 1095 | json_add_key(buf, "zratio", json_level);
|
| 1096 | + |
1048 | 1097 | if (tlinfo->size != 0)
|
1049 |
| - zratio = ((float)xlog_seg_size*tlinfo->n_xlog_files) / tlinfo->size; |
| 1098 | + zratio = ((float) xlog_seg_size * tlinfo->n_xlog_files) / tlinfo->size; |
1050 | 1099 | appendPQExpBuffer(buf, "%.2f", zratio);
|
1051 | 1100 |
|
1052 | 1101 | if (tlinfo->closest_backup != NULL)
|
|
0 commit comments