mirror of
https://github.com/Icinga/icinga2.git
synced 2025-04-08 17:05:25 +02:00
Merge pull request #10300 from Icinga/error-timestamp-out-of-range-53323-214
IDO: timestamp out of range errors
This commit is contained in:
commit
ebac52b830
@ -891,9 +891,13 @@ bool IdoMysqlConnection::FieldToEscapedString(const String& key, const Value& va
|
||||
|
||||
*result = static_cast<long>(dbrefcol);
|
||||
} else if (DbValue::IsTimestamp(value)) {
|
||||
long ts = rawvalue;
|
||||
// MySQL TIMESTAMP columns have the year-2038 problem, hence the upper limit below.
|
||||
// Also, they don't accept FROM_UNIXTIME(0): ERROR 1292 (22007): Incorrect datetime value: '1970-01-01 00:00:00'
|
||||
|
||||
double ts = rawvalue;
|
||||
std::ostringstream msgbuf;
|
||||
msgbuf << "FROM_UNIXTIME(" << ts << ")";
|
||||
msgbuf << "FROM_UNIXTIME(" << std::fixed << std::setprecision(0)
|
||||
<< std::fmin(std::fmax(ts, 1.0), 2147483647.0) << ")";
|
||||
*result = Value(msgbuf.str());
|
||||
} else if (DbValue::IsObjectInsertID(value)) {
|
||||
auto id = static_cast<long>(rawvalue);
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "base/context.hpp"
|
||||
#include "base/statsfunction.hpp"
|
||||
#include "base/defer.hpp"
|
||||
#include <cmath>
|
||||
#include <utility>
|
||||
|
||||
using namespace icinga;
|
||||
@ -700,9 +701,49 @@ bool IdoPgsqlConnection::FieldToEscapedString(const String& key, const Value& va
|
||||
|
||||
*result = static_cast<long>(dbrefcol);
|
||||
} else if (DbValue::IsTimestamp(value)) {
|
||||
long ts = rawvalue;
|
||||
// In addition to the limits of PostgreSQL itself (4713BC - 294276AD),
|
||||
// years not fitting in YYYY may cause problems, see e.g. https://github.com/golang/go/issues/4556.
|
||||
// RFC 3339: "All dates and times are assumed to be (...) somewhere between 0000AD and 9999AD."
|
||||
// The below limits include safety buffers to make sure the timestamps are within 0-9999 AD in all time zones:
|
||||
//
|
||||
// postgres=# \x
|
||||
// Expanded display is on.
|
||||
// postgres=# SELECT TO_TIMESTAMP(-62135510400) AT TIME ZONE 'UTC' AS utc,
|
||||
// postgres-# TO_TIMESTAMP(-62135510400) AT TIME ZONE 'Asia/Vladivostok' AS east,
|
||||
// postgres-# TO_TIMESTAMP(-62135510400) AT TIME ZONE 'America/Juneau' AS west,
|
||||
// postgres-# TO_TIMESTAMP(-62135510400) AT TIME ZONE 'America/Nuuk' AS north;
|
||||
// -[ RECORD 1 ]--------------
|
||||
// utc | 0001-01-02 00:00:00
|
||||
// east | 0001-01-02 08:47:31
|
||||
// west | 0001-01-02 15:02:19
|
||||
// north | 0001-01-01 20:33:04
|
||||
//
|
||||
// postgres=# SELECT TO_TIMESTAMP(-62135510400-86400) AT TIME ZONE 'UTC' AS utc,
|
||||
// postgres-# TO_TIMESTAMP(-62135510400-86400) AT TIME ZONE 'Asia/Vladivostok' AS east,
|
||||
// postgres-# TO_TIMESTAMP(-62135510400-86400) AT TIME ZONE 'America/Juneau' AS west,
|
||||
// postgres-# TO_TIMESTAMP(-62135510400-86400) AT TIME ZONE 'America/Nuuk' AS north;
|
||||
// -[ RECORD 1 ]-----------------
|
||||
// utc | 0001-01-01 00:00:00
|
||||
// east | 0001-01-01 08:47:31
|
||||
// west | 0001-01-01 15:02:19
|
||||
// north | 0001-12-31 20:33:04 BC
|
||||
//
|
||||
// postgres=# SELECT TO_TIMESTAMP(253402214400) AT TIME ZONE 'UTC' AS utc,
|
||||
// postgres-# TO_TIMESTAMP(253402214400) AT TIME ZONE 'Asia/Vladivostok' AS east,
|
||||
// postgres-# TO_TIMESTAMP(253402214400) AT TIME ZONE 'America/Juneau' AS west,
|
||||
// postgres-# TO_TIMESTAMP(253402214400) AT TIME ZONE 'America/Nuuk' AS north;
|
||||
// -[ RECORD 1 ]-------------
|
||||
// utc | 9999-12-31 00:00:00
|
||||
// east | 9999-12-31 10:00:00
|
||||
// west | 9999-12-30 15:00:00
|
||||
// north | 9999-12-30 22:00:00
|
||||
//
|
||||
// postgres=#
|
||||
|
||||
double ts = rawvalue;
|
||||
std::ostringstream msgbuf;
|
||||
msgbuf << "TO_TIMESTAMP(" << ts << ") AT TIME ZONE 'UTC'";
|
||||
msgbuf << "TO_TIMESTAMP(" << std::fixed << std::setprecision(0)
|
||||
<< std::fmin(std::fmax(ts, -62135510400.0), 253402214400.0) << ") AT TIME ZONE 'UTC'";
|
||||
*result = Value(msgbuf.str());
|
||||
} else if (DbValue::IsObjectInsertID(value)) {
|
||||
auto id = static_cast<long>(rawvalue);
|
||||
|
Loading…
x
Reference in New Issue
Block a user