|
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