diff --git a/src/pgduckdb_types.cpp b/src/pgduckdb_types.cpp index db2ad8d0..c71f0a37 100644 --- a/src/pgduckdb_types.cpp +++ b/src/pgduckdb_types.cpp @@ -220,8 +220,28 @@ ConvertDateDatum(const duckdb::Value &value) { inline Datum ConvertTimestampDatum(const duckdb::Value &value) { - duckdb::timestamp_t timestamp = value.GetValue(); - return timestamp.value - pgduckdb::PGDUCKDB_DUCK_TIMESTAMP_OFFSET; + // Extract raw int64_t value of timestamp + int64_t rawValue = value.GetValue(); + + // Handle specific Timestamp unit(sec, ms, ns) types + switch (value.type().id()) { + case duckdb::LogicalType::TIMESTAMP_MS: + // 1 ms = 10^3 micro-sec + rawValue *= 1000; + break; + case duckdb::LogicalType::TIMESTAMP_NS: + // 1 ns = 10^-3 micro-sec + rawValue /= 1000; + break; + case duckdb::LogicalType::TIMESTAMP_S: + // 1 s = 10^6 micro-sec + rawValue *= 1000000; + break; + default: + // Since we don't want to handle anything here + rawValue = rawValue; + } + return rawValue - pgduckdb::PGDUCKDB_DUCK_TIMESTAMP_OFFSET; } inline Datum @@ -1001,6 +1021,9 @@ GetPostgresDuckDBType(const duckdb::LogicalType &type) { case duckdb::LogicalTypeId::DATE: return DATEOID; case duckdb::LogicalTypeId::TIMESTAMP: + case duckdb::LogicalTypeId::TIMESTAMP_SEC: + case duckdb::LogicalTypeId::TIMESTAMP_MS: + case duckdb::LogicalTypeId::TIMESTAMP_NS: return TIMESTAMPOID; case duckdb::LogicalTypeId::TIMESTAMP_TZ: return TIMESTAMPTZOID; @@ -1222,6 +1245,10 @@ ConvertPostgresToDuckValue(Oid attr_type, Datum value, duckdb::Vector &result, i case duckdb::LogicalTypeId::DATE: Append(result, duckdb::date_t(static_cast(value + PGDUCKDB_DUCK_DATE_OFFSET)), offset); break; + + case duckdb::LogicalTypeId::TIMESTAMP_SEC: + case duckdb::LogicalTypeId::TIMESTAMP_MS: + case duckdb::LogicalTypeId::TIMESTAMP_NS: case duckdb::LogicalTypeId::TIMESTAMP: Append( result, duckdb::timestamp_t(static_cast(value + PGDUCKDB_DUCK_TIMESTAMP_OFFSET)), offset); diff --git a/test/regression/expected/type_support.out b/test/regression/expected/type_support.out index c4a42c26..f260395c 100644 --- a/test/regression/expected/type_support.out +++ b/test/regression/expected/type_support.out @@ -171,6 +171,27 @@ SELECT * FROM timestamptz_tbl WHERE a >= '2024-10-14 13:00:00 Europe/London'; Mon Oct 14 07:00:00 2024 PDT (3 rows) +-- TIMESTAMP_NS Conversion from DuckDB to PostgreSQL +SELECT * FROM duckdb.query($$ SELECT '1992-12-12 12:12:12.123456789'::TIMESTAMP_NS as ts $$); + ts +--------------------------------- + Sat Dec 12 12:12:12.123456 1992 +(1 row) + +-- TIMESTAMP_MS Conversion from DuckDB to PostgreSQL +SELECT * FROM duckdb.query($$ SELECT '1992-12-12 12:12:12.123'::TIMESTAMP_MS as ts $$); + ts +------------------------------ + Sat Dec 12 12:12:12.123 1992 +(1 row) + +-- TIMESTAMP_S Conversion from DuckDB to PostgreSQL +SELECT * FROM duckdb.query($$ SELECT '1992-12-12 12:12:12'::TIMESTAMP_S as ts $$); + ts +-------------------------- + Sat Dec 12 12:12:12 1992 +(1 row) + -- FLOAT4 CREATE TABLE float4_tbl(a FLOAT4); INSERT INTO float4_tbl SELECT CAST(a AS FLOAT4) FROM (VALUES diff --git a/test/regression/sql/type_support.sql b/test/regression/sql/type_support.sql index 64f1e20c..1fcaefbe 100644 --- a/test/regression/sql/type_support.sql +++ b/test/regression/sql/type_support.sql @@ -72,6 +72,15 @@ SELECT * FROM timestamptz_tbl; SELECT * FROM timestamptz_tbl WHERE a >= '2024-10-14 13:00:00+1'; SELECT * FROM timestamptz_tbl WHERE a >= '2024-10-14 13:00:00 Europe/London'; +-- TIMESTAMP_NS Conversion from DuckDB to PostgreSQL +SELECT * FROM duckdb.query($$ SELECT '1992-12-12 12:12:12.123456789'::TIMESTAMP_NS as ts $$); + +-- TIMESTAMP_MS Conversion from DuckDB to PostgreSQL +SELECT * FROM duckdb.query($$ SELECT '1992-12-12 12:12:12.123'::TIMESTAMP_MS as ts $$); + +-- TIMESTAMP_S Conversion from DuckDB to PostgreSQL +SELECT * FROM duckdb.query($$ SELECT '1992-12-12 12:12:12'::TIMESTAMP_S as ts $$); + -- FLOAT4 CREATE TABLE float4_tbl(a FLOAT4); INSERT INTO float4_tbl SELECT CAST(a AS FLOAT4) FROM (VALUES