-
Notifications
You must be signed in to change notification settings - Fork 89
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add boundary check for converting duckdb date/timestamps to PG dates/timestamps #653
base: main
Are you sure you want to change the base?
Changes from all commits
0eb5436
70ebc69
0178cf9
62dafa0
beb1f0b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -156,6 +156,25 @@ struct DecimalConversionDouble { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
static inline bool | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ValidDate(duckdb::date_t dt) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if ((dt < pgduckdb::PGDUCKDB_PG_MIN_DATE_VALUE || dt > pgduckdb::PGDUCKDB_PG_MAX_DATE_VALUE) && | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
!(dt == duckdb::date_t::infinity() || dt == duckdb::date_t::ninfinity())) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
static inline bool | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ValidTimestampOrTimestampTz(int64_t timestamp) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// PG TIMESTAMP RANGE = 4714-11-24 00:00:00 (BC) <-> 294276-12-31 23:59:59 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// DUCK TIMESTAMP RANGE = 290308-12-22 00:00:00 (BC) <-> 294247-01-10 04:00:54 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Taking Intersection of the ranges | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// MIN TIMESTAMP = 4714-11-24 00:00:00 (BC) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// MAX TIMESTAMP = 294246-12-31 23:59:59 , To keep it capped to a specific year.. also coincidently this is EXACTLY | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// 30 years less than PG max value. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return timestamp >= pgduckdb::PGDUCKDB_MIN_TIMESTAMP_VALUE && timestamp < pgduckdb::PGDUCKDB_MAX_TIMESTAMP_VALUE; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
static inline Datum | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ConvertBoolDatum(const duckdb::Value &value) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return value.GetValue<bool>(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -216,6 +235,20 @@ ConvertBinaryDatum(const duckdb::Value &value) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
inline Datum | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ConvertDateDatum(const duckdb::Value &value) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
duckdb::date_t date = value.GetValue<duckdb::date_t>(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!ValidDate(date)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
throw duckdb::OutOfRangeException("The value should be between min and max value (%s <-> %s)", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
duckdb::Date::ToString(pgduckdb::PGDUCKDB_PG_MIN_DATE_VALUE), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
duckdb::Date::ToString(pgduckdb::PGDUCKDB_PG_MAX_DATE_VALUE)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Special Handling for +/-infinity date values | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!duckdb::Date::IsFinite(date)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// -infinity value is different for PG date | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (date == duckdb::date_t::ninfinity()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return date.days - 1; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return date.days; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+244
to
+250
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of doing this
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return date.days - pgduckdb::PGDUCKDB_DUCK_DATE_OFFSET; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -255,6 +288,14 @@ ConvertTimestampDatum(const duckdb::Value &value) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Extract raw int64_t value of timestamp | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
int64_t rawValue = value.GetValue<int64_t>(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Early Return for +/-Inf | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!duckdb::Timestamp::IsFinite(static_cast<duckdb::timestamp_t>(rawValue))) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (rawValue == static_cast<int64_t>(duckdb::timestamp_t::ninfinity())) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return Int64GetDatum(rawValue - 1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return Int64GetDatum(rawValue); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Handle specific Timestamp unit(sec, ms, ns) types | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
switch (value.type().id()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case duckdb::LogicalType::TIMESTAMP_MS: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -273,7 +314,36 @@ ConvertTimestampDatum(const duckdb::Value &value) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Since we don't want to handle anything here | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
break; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return rawValue - pgduckdb::PGDUCKDB_DUCK_TIMESTAMP_OFFSET; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!ValidTimestampOrTimestampTz(rawValue)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
throw duckdb::OutOfRangeException( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"The Timestamp value should be between min and max value (%s <-> %s)", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
duckdb::Timestamp::ToString(static_cast<duckdb::timestamp_t>(PGDUCKDB_MIN_TIMESTAMP_VALUE)), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
duckdb::Timestamp::ToString(static_cast<duckdb::timestamp_t>(PGDUCKDB_MAX_TIMESTAMP_VALUE))); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return Int64GetDatum(rawValue - pgduckdb::PGDUCKDB_DUCK_TIMESTAMP_OFFSET); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
inline Datum | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ConvertTimestampTzDatum(const duckdb::Value &value) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
duckdb::timestamp_tz_t timestamp = value.GetValue<duckdb::timestamp_tz_t>(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
int64_t rawValue = timestamp.value; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Early Return for +/-Inf | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!duckdb::Timestamp::IsFinite(static_cast<duckdb::timestamp_t>(rawValue))) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (rawValue == static_cast<int64_t>(duckdb::timestamp_t::ninfinity())) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return Int64GetDatum(rawValue - 1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return Int64GetDatum(rawValue); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!ValidTimestampOrTimestampTz(rawValue)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
throw duckdb::OutOfRangeException( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"The TimestampTz value should be between min and max value (%s <-> %s)", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
duckdb::Timestamp::ToString(static_cast<duckdb::timestamp_t>(PGDUCKDB_MIN_TIMESTAMP_VALUE)), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
duckdb::Timestamp::ToString(static_cast<duckdb::timestamp_t>(PGDUCKDB_MAX_TIMESTAMP_VALUE))); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return Int64GetDatum(rawValue - pgduckdb::PGDUCKDB_DUCK_TIMESTAMP_OFFSET); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
inline Datum | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -876,8 +946,7 @@ ConvertDuckToPostgresValue(TupleTableSlot *slot, duckdb::Value &value, idx_t col | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
break; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case TIMESTAMPTZOID: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
duckdb::timestamp_tz_t timestamp = value.GetValue<duckdb::timestamp_tz_t>(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
slot->tts_values[col] = timestamp.value - pgduckdb::PGDUCKDB_DUCK_TIMESTAMP_OFFSET; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
slot->tts_values[col] = ConvertTimestampTzDatum(value); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
break; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case INTERVALOID: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -1278,6 +1347,75 @@ AppendJsonb(duckdb::Vector &result, Datum value, idx_t offset) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
data[offset] = duckdb::StringVector::AddString(result, str); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
static void | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
AppendDate(duckdb::Vector &result, Datum value, idx_t offset) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
auto date = DatumGetDateADT(value); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bool is_inf_val = false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (date == DATEVAL_NOBEGIN) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
is_inf_val = true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// -infinity value is different between PG and duck | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
date += 1; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (date == DATEVAL_NOEND) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
is_inf_val = true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (is_inf_val) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Append<duckdb::date_t>(result, duckdb::date_t(static_cast<int32_t>(date)), offset); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Append<duckdb::date_t>(result, duckdb::date_t(static_cast<int32_t>(date + PGDUCKDB_DUCK_DATE_OFFSET)), offset); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+1352
to
+1365
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this function becomes a lot easier to follow if there are some early returns in there. Same for the two other functions below (
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
static void | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
AppendTimestamp(duckdb::Vector &result, Datum value, idx_t offset) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
int64_t timestamp = static_cast<int64_t>(DatumGetTimestamp(value)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bool is_inf_val = false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (timestamp == TIMESTAMP_MINUS_INFINITY) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
is_inf_val = true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// -infinity value is different between PG and duck | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
timestamp += 1; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (timestamp == TIMESTAMP_INFINITY) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
is_inf_val = true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Bounds Check | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!is_inf_val && !ValidTimestampOrTimestampTz(timestamp + PGDUCKDB_DUCK_TIMESTAMP_OFFSET)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
throw duckdb::OutOfRangeException( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"The Timestamp value should be between min and max value (%s <-> %s)", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
duckdb::Timestamp::ToString(static_cast<duckdb::timestamp_t>(PGDUCKDB_MIN_TIMESTAMP_VALUE)), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
duckdb::Timestamp::ToString(static_cast<duckdb::timestamp_t>(PGDUCKDB_MAX_TIMESTAMP_VALUE))); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (is_inf_val) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Append<duckdb::timestamp_t>(result, duckdb::timestamp_t(timestamp), offset); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Append<duckdb::timestamp_t>(result, duckdb::timestamp_t(timestamp + PGDUCKDB_DUCK_TIMESTAMP_OFFSET), offset); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
static void | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
AppendTimestampTz(duckdb::Vector &result, Datum value, idx_t offset) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
int64_t timestamp = static_cast<int64_t>(DatumGetTimestamp(value)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bool is_inf_val = false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (timestamp == TIMESTAMP_MINUS_INFINITY) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
is_inf_val = true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// -infinity value is different between PG and duck | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
timestamp += 1; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (timestamp == TIMESTAMP_INFINITY) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
is_inf_val = true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Bounds Check | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!is_inf_val && !ValidTimestampOrTimestampTz(timestamp + PGDUCKDB_DUCK_TIMESTAMP_OFFSET)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
throw duckdb::OutOfRangeException( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"The TimestampTz value should be between min and max value (%s <-> %s)", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
duckdb::Timestamp::ToString(static_cast<duckdb::timestamp_tz_t>(PGDUCKDB_MIN_TIMESTAMP_VALUE)), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
duckdb::Timestamp::ToString(static_cast<duckdb::timestamp_tz_t>(PGDUCKDB_MAX_TIMESTAMP_VALUE))); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (is_inf_val) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Append<duckdb::timestamp_tz_t>(result, duckdb::timestamp_tz_t(timestamp), offset); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Append<duckdb::timestamp_tz_t>(result, duckdb::timestamp_tz_t(timestamp + PGDUCKDB_DUCK_TIMESTAMP_OFFSET), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
offset); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
template <class T, class OP = DecimalConversionInteger> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
T | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ConvertDecimal(const NumericVar &numeric) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -1434,19 +1572,17 @@ ConvertPostgresToDuckValue(Oid attr_type, Datum value, duckdb::Vector &result, i | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
break; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case duckdb::LogicalTypeId::DATE: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Append<duckdb::date_t>(result, duckdb::date_t(static_cast<int32_t>(value + PGDUCKDB_DUCK_DATE_OFFSET)), offset); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
AppendDate(result, value, offset); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
break; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case duckdb::LogicalTypeId::TIMESTAMP_SEC: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case duckdb::LogicalTypeId::TIMESTAMP_MS: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case duckdb::LogicalTypeId::TIMESTAMP_NS: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case duckdb::LogicalTypeId::TIMESTAMP: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Append<duckdb::timestamp_t>( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
result, duckdb::timestamp_t(static_cast<int64_t>(value + PGDUCKDB_DUCK_TIMESTAMP_OFFSET)), offset); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
AppendTimestamp(result, value, offset); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
break; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case duckdb::LogicalTypeId::TIMESTAMP_TZ: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Append<duckdb::timestamp_tz_t>( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
result, duckdb::timestamp_tz_t(static_cast<int64_t>(value + PGDUCKDB_DUCK_TIMESTAMP_OFFSET)), offset); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
AppendTimestampTz(result, value, offset); // Timestamp and Timestamptz are basically same in PG | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
break; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case duckdb::LogicalTypeId::INTERVAL: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Append<duckdb::interval_t>(result, DatumGetInterval(value), offset); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -1645,5 +1781,4 @@ FromNumeric(Numeric num) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
dest.buf = NULL; /* digits array is not palloc'd */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return dest; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} // namespace pgduckdb |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
-- Test +/- inf values | ||
CREATE TABLE t(a DATE); | ||
INSERT INTO t VALUES('Infinity'), ('-Infinity'); | ||
-- PG Execution | ||
SELECT * from t; | ||
a | ||
----------- | ||
infinity | ||
-infinity | ||
(2 rows) | ||
|
||
SELECT isfinite(a) FROM t; | ||
isfinite | ||
---------- | ||
f | ||
f | ||
(2 rows) | ||
|
||
set duckdb.force_execution = true; | ||
-- DuckDB execution | ||
SELECT * from t; | ||
a | ||
----------- | ||
infinity | ||
-infinity | ||
(2 rows) | ||
|
||
SELECT isfinite(a) FROM t; | ||
isfinite | ||
---------- | ||
f | ||
f | ||
(2 rows) | ||
|
||
-- Cleanup | ||
set duckdb.force_execution = false; | ||
DROP TABLE t; | ||
-- Check upper and lower limits of date range | ||
SELECT * FROM duckdb.query($$ SELECT '4714-11-24 (BC)'::date as date $$); | ||
date | ||
--------------- | ||
11-24-4714 BC | ||
(1 row) | ||
|
||
SELECT * FROM duckdb.query($$ SELECT '4714-11-23 (BC)'::date as date $$); -- out of range | ||
ERROR: (PGDuckDB/Duckdb_ExecCustomScan_Cpp) Out of Range Error: The value should be between min and max value (4714-11-24 (BC) <-> 5874897-12-31) | ||
SELECT * FROM duckdb.query($$ SELECT '5874897-12-31'::date as date $$); | ||
date | ||
--------------- | ||
12-31-5874897 | ||
(1 row) | ||
|
||
SELECT * FROM duckdb.query($$ SELECT '5874898-01-01'::date as date $$); -- out of range | ||
ERROR: (PGDuckDB/Duckdb_ExecCustomScan_Cpp) Out of Range Error: The value should be between min and max value (4714-11-24 (BC) <-> 5874897-12-31) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of making this a huge condition lets split them up: