mirror of
https://github.com/postgrespro/pg_probackup.git
synced 2025-01-20 11:34:51 +02:00
PGPRO-1026: Store timestamps with timezone, parse timezone from timestamp
from config and command line parameters
This commit is contained in:
parent
9813471e7b
commit
be71f4a8f9
@ -1546,13 +1546,13 @@ pg_stop_backup(pgBackup *backup)
|
||||
*/
|
||||
sent = pgut_send(conn,
|
||||
"SELECT *, txid_snapshot_xmax(txid_current_snapshot()),"
|
||||
" current_timestamp(0)::timestamp"
|
||||
" current_timestamp(0)::timestamptz"
|
||||
" FROM pg_stop_backup(false)",
|
||||
0, NULL, WARNING);
|
||||
else
|
||||
sent = pgut_send(conn,
|
||||
"SELECT *, txid_snapshot_xmax(txid_current_snapshot()),"
|
||||
" current_timestamp(0)::timestamp"
|
||||
" current_timestamp(0)::timestamptz"
|
||||
" FROM pg_stop_backup()",
|
||||
0, NULL, WARNING);
|
||||
|
||||
|
@ -381,7 +381,7 @@ pgBackupCreateDir(pgBackup *backup)
|
||||
void
|
||||
pgBackupWriteControl(FILE *out, pgBackup *backup)
|
||||
{
|
||||
char timestamp[20];
|
||||
char timestamp[100];
|
||||
|
||||
fprintf(out, "#Configuration\n");
|
||||
fprintf(out, "backup-mode = %s\n", pgBackupGetBackupMode(backup));
|
||||
|
@ -223,7 +223,7 @@ pgBackupDeleteFiles(pgBackup *backup)
|
||||
size_t i;
|
||||
char *backup_id;
|
||||
char path[MAXPGPATH];
|
||||
char timestamp[20];
|
||||
char timestamp[100];
|
||||
parray *files;
|
||||
|
||||
/*
|
||||
@ -428,4 +428,4 @@ do_delete_instance(void)
|
||||
|
||||
elog(INFO, "Instance '%s' successfully deleted", instance_name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -720,6 +720,7 @@ create_recovery_conf(time_t backup_id,
|
||||
PROGRAM_VERSION);
|
||||
fprintf(fp, "restore_command = 'pg_probackup archive-get -B %s --instance %s --wal-file-path %%p --wal-file-name %%f'\n",
|
||||
backup_path, instance_name);
|
||||
fprintf(fp, "recovery_target_action = 'promote'\n");
|
||||
|
||||
if (target_time)
|
||||
fprintf(fp, "recovery_target_time = '%s'\n", target_time);
|
||||
@ -736,7 +737,6 @@ create_recovery_conf(time_t backup_id,
|
||||
* replayed.
|
||||
*/
|
||||
fprintf(fp, "recovery_target = 'immediate'\n");
|
||||
fprintf(fp, "recovery_target_action = 'promote'\n");
|
||||
}
|
||||
|
||||
if (target_inclusive)
|
||||
|
@ -235,7 +235,7 @@ show_backup_list(FILE *out, parray *backup_list)
|
||||
pgBackup *backup = parray_get(backup_list, i);
|
||||
TimeLineID parent_tli;
|
||||
char *backup_id;
|
||||
char timestamp[20] = "----";
|
||||
char timestamp[100] = "----";
|
||||
char duration[20] = "----";
|
||||
char data_bytes_str[10] = "----";
|
||||
|
||||
|
24
src/util.c
24
src/util.c
@ -144,9 +144,29 @@ get_data_checksum_version(bool safe)
|
||||
void
|
||||
time2iso(char *buf, size_t len, time_t time)
|
||||
{
|
||||
struct tm *tm = localtime(&time);
|
||||
struct tm *ptm = gmtime(&time);
|
||||
time_t gmt = mktime(ptm);
|
||||
time_t offset;
|
||||
|
||||
strftime(buf, len, "%Y-%m-%d %H:%M:%S", tm);
|
||||
ptm = localtime(&time);
|
||||
offset = time - gmt + (ptm->tm_isdst ? 3600 : 0);
|
||||
|
||||
strftime(buf, len, "%Y-%m-%d %H:%M:%S", ptm);
|
||||
|
||||
if (offset != 0)
|
||||
{
|
||||
buf += strlen(buf);
|
||||
sprintf(buf, "%c%02d",
|
||||
(offset >= 0) ? '+' : '-',
|
||||
abs((int) offset) / SECS_PER_HOUR);
|
||||
|
||||
if (abs((int) offset) % SECS_PER_HOUR != 0)
|
||||
{
|
||||
buf += strlen(buf);
|
||||
sprintf(buf, ":%02d",
|
||||
abs((int) offset % SECS_PER_HOUR) / SECS_PER_MINUTE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* copied from timestamp.c */
|
||||
|
@ -2,7 +2,7 @@
|
||||
*
|
||||
* logger.h: - prototypes of logger functions.
|
||||
*
|
||||
* Portions Copyright (c) 2017-2017, Postgres Professional
|
||||
* Copyright (c) 2017-2017, Postgres Professional
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
104
src/utils/pgut.c
104
src/utils/pgut.c
@ -28,6 +28,10 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define MAX_TZDISP_HOUR 15 /* maximum allowed hour part */
|
||||
#define SECS_PER_MINUTE 60
|
||||
#define MINS_PER_HOUR 60
|
||||
|
||||
const char *PROGRAM_NAME = NULL;
|
||||
|
||||
const char *pgut_dbname = NULL;
|
||||
@ -496,19 +500,91 @@ parse_uint64(const char *value, uint64 *result)
|
||||
* Convert ISO-8601 format string to time_t value.
|
||||
*/
|
||||
bool
|
||||
parse_time(const char *value, time_t *time)
|
||||
parse_time(const char *value, time_t *result)
|
||||
{
|
||||
size_t len;
|
||||
int fields_num,
|
||||
tz = 0,
|
||||
i;
|
||||
char *tmp;
|
||||
int i;
|
||||
struct tm tm;
|
||||
char junk[2];
|
||||
|
||||
/* tmp = replace( value, !isalnum, ' ' ) */
|
||||
tmp = pgut_malloc(strlen(value) + + 1);
|
||||
len = 0;
|
||||
for (i = 0; value[i]; i++)
|
||||
tmp[len++] = (IsAlnum(value[i]) ? value[i] : ' ');
|
||||
fields_num = 1;
|
||||
|
||||
while (*value)
|
||||
{
|
||||
if (IsAlnum(*value))
|
||||
{
|
||||
tmp[len++] = *value;
|
||||
value++;
|
||||
}
|
||||
else if (fields_num < 6)
|
||||
{
|
||||
fields_num++;
|
||||
tmp[len++] = ' ';
|
||||
value++;
|
||||
}
|
||||
/* timezone field is 7th */
|
||||
else if ((*value == '-' || *value == '+') && fields_num == 6)
|
||||
{
|
||||
int hr,
|
||||
min,
|
||||
sec = 0;
|
||||
char *cp;
|
||||
|
||||
errno = 0;
|
||||
hr = strtol(value + 1, &cp, 10);
|
||||
if ((value + 1) == cp || errno == ERANGE)
|
||||
return false;
|
||||
|
||||
/* explicit delimiter? */
|
||||
if (*cp == ':')
|
||||
{
|
||||
errno = 0;
|
||||
min = strtol(cp + 1, &cp, 10);
|
||||
if (errno == ERANGE)
|
||||
return false;
|
||||
if (*cp == ':')
|
||||
{
|
||||
errno = 0;
|
||||
sec = strtol(cp + 1, &cp, 10);
|
||||
if (errno == ERANGE)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/* otherwise, might have run things together... */
|
||||
else if (*cp == '\0' && strlen(value) > 3)
|
||||
{
|
||||
min = hr % 100;
|
||||
hr = hr / 100;
|
||||
/* we could, but don't, support a run-together hhmmss format */
|
||||
}
|
||||
else
|
||||
min = 0;
|
||||
|
||||
/* Range-check the values; see notes in datatype/timestamp.h */
|
||||
if (hr < 0 || hr > MAX_TZDISP_HOUR)
|
||||
return false;
|
||||
if (min < 0 || min >= MINS_PER_HOUR)
|
||||
return false;
|
||||
if (sec < 0 || sec >= SECS_PER_MINUTE)
|
||||
return false;
|
||||
|
||||
tz = (hr * MINS_PER_HOUR + min) * SECS_PER_MINUTE + sec;
|
||||
if (*value == '-')
|
||||
tz = -tz;
|
||||
|
||||
fields_num++;
|
||||
value = cp;
|
||||
}
|
||||
/* wrong format */
|
||||
else if (!IsSpace(*value))
|
||||
return false;
|
||||
}
|
||||
tmp[len] = '\0';
|
||||
|
||||
/* parse for "YYYY-MM-DD HH:MI:SS" */
|
||||
@ -540,7 +616,25 @@ parse_time(const char *value, time_t *time)
|
||||
/* determine whether Daylight Saving Time is in effect */
|
||||
tm.tm_isdst = -1;
|
||||
|
||||
*time = mktime(&tm);
|
||||
*result = mktime(&tm);
|
||||
|
||||
/* adjust time zone */
|
||||
if (tz != 0)
|
||||
{
|
||||
time_t ltime = time(NULL);
|
||||
struct tm *ptm = gmtime(<ime);
|
||||
time_t gmt = mktime(ptm);
|
||||
time_t offset;
|
||||
|
||||
/* UTC time */
|
||||
*result -= tz;
|
||||
|
||||
/* Get local time */
|
||||
ptm = localtime(<ime);
|
||||
offset = ltime - gmt + (ptm->tm_isdst ? 3600 : 0);
|
||||
|
||||
*result += offset;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -195,7 +195,7 @@ extern bool parse_int32(const char *value, int32 *result);
|
||||
extern bool parse_uint32(const char *value, uint32 *result);
|
||||
extern bool parse_int64(const char *value, int64 *result);
|
||||
extern bool parse_uint64(const char *value, uint64 *result);
|
||||
extern bool parse_time(const char *value, time_t *time);
|
||||
extern bool parse_time(const char *value, time_t *result);
|
||||
extern bool parse_int(const char *value, int *result, int flags,
|
||||
const char **hintmsg);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user