Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions src/pgduckdb_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,16 @@ ConvertDateDatum(const duckdb::Value &value) {
return date.days - pgduckdb::PGDUCKDB_DUCK_DATE_OFFSET;
}

static Datum
ConvertIntervalDatum(const duckdb::Value &value) {
duckdb::interval_t duckdb_interval = value.GetValue<duckdb::interval_t>();
Interval *pg_interval = static_cast<Interval *>(palloc(sizeof(Interval)));
pg_interval->month = duckdb_interval.months;
pg_interval->day = duckdb_interval.days;
pg_interval->time = duckdb_interval.micros;
return IntervalPGetDatum(pg_interval);
}

inline Datum
ConvertTimestampDatum(const duckdb::Value &value) {
// Extract raw int64_t value of timestamp
Expand Down Expand Up @@ -381,6 +391,16 @@ ConvertUUIDDatum(const duckdb::Value &value) {
return UUIDPGetDatum(postgres_uuid);
}

static duckdb::interval_t
DatumGetInterval(Datum value) {
Interval *pg_interval = DatumGetIntervalP(value);
duckdb::interval_t duck_interval;
duck_interval.months = pg_interval->month;
duck_interval.days = pg_interval->day;
duck_interval.micros = pg_interval->time;
return duck_interval;
}

template <int32_t OID>
struct PostgresTypeTraits;

Expand Down Expand Up @@ -489,6 +509,19 @@ struct PostgresTypeTraits<TIMESTAMPOID> {
}
};

// INTERVAL type
template <>
struct PostgresTypeTraits<INTERVALOID> {
static constexpr int16_t typlen = 16;
static constexpr bool typbyval = false;
static constexpr char typalign = 'c';

static inline Datum
ToDatum(const duckdb::Value &val) {
return ConvertIntervalDatum(val);
}
};

// DATE type
template <>
struct PostgresTypeTraits<DATEOID> {
Expand Down Expand Up @@ -591,6 +624,7 @@ using Float4Array = PODArray<PostgresOIDMapping<FLOAT4OID>>;
using Float8Array = PODArray<PostgresOIDMapping<FLOAT8OID>>;
using DateArray = PODArray<PostgresOIDMapping<DATEOID>>;
using TimestampArray = PODArray<PostgresOIDMapping<TIMESTAMPOID>>;
using IntervalArray = PODArray<PostgresOIDMapping<INTERVALOID>>;
using UUIDArray = PODArray<PostgresOIDMapping<UUIDOID>>;
using VarCharArray = PODArray<PostgresOIDMapping<VARCHAROID>>;
using NumericArray = PODArray<PostgresOIDMapping<NUMERICOID>>;
Expand Down Expand Up @@ -767,6 +801,10 @@ ConvertDuckToPostgresValue(TupleTableSlot *slot, duckdb::Value &value, idx_t col
slot->tts_values[col] = timestamp.value - pgduckdb::PGDUCKDB_DUCK_TIMESTAMP_OFFSET;
break;
}
case INTERVALOID: {
slot->tts_values[col] = ConvertIntervalDatum(value);
break;
}
case FLOAT4OID: {
slot->tts_values[col] = ConvertFloatDatum(value);
break;
Expand Down Expand Up @@ -822,6 +860,10 @@ ConvertDuckToPostgresValue(TupleTableSlot *slot, duckdb::Value &value, idx_t col
ConvertDuckToPostgresArray<TimestampArray>(slot, value, col);
break;
}
case INTERVALARRAYOID: {
ConvertDuckToPostgresArray<IntervalArray>(slot, value, col);
break;
}
case FLOAT4ARRAYOID: {
ConvertDuckToPostgresArray<Float4Array>(slot, value, col);
break;
Expand Down Expand Up @@ -897,6 +939,9 @@ ConvertPostgresToBaseDuckColumnType(Form_pg_attribute &attribute) {
return duckdb::LogicalTypeId::TIMESTAMP;
case TIMESTAMPTZOID:
return duckdb::LogicalTypeId::TIMESTAMP_TZ;
case INTERVALOID:
case INTERVALARRAYOID:
return duckdb::LogicalTypeId::INTERVAL;
case FLOAT4OID:
case FLOAT4ARRAYOID:
return duckdb::LogicalTypeId::FLOAT;
Expand Down Expand Up @@ -975,6 +1020,8 @@ GetPostgresArrayDuckDBType(const duckdb::LogicalType &type) {
return DATEARRAYOID;
case duckdb::LogicalTypeId::TIMESTAMP:
return TIMESTAMPARRAYOID;
case duckdb::LogicalTypeId::INTERVAL:
return INTERVALARRAYOID;
case duckdb::LogicalTypeId::FLOAT:
return FLOAT4ARRAYOID;
case duckdb::LogicalTypeId::DOUBLE:
Expand Down Expand Up @@ -1027,6 +1074,8 @@ GetPostgresDuckDBType(const duckdb::LogicalType &type) {
return TIMESTAMPOID;
case duckdb::LogicalTypeId::TIMESTAMP_TZ:
return TIMESTAMPTZOID;
case duckdb::LogicalTypeId::INTERVAL:
return INTERVALOID;
case duckdb::LogicalTypeId::FLOAT:
return FLOAT4OID;
case duckdb::LogicalTypeId::DOUBLE:
Expand Down Expand Up @@ -1188,6 +1237,8 @@ ConvertPostgresParameterToDuckValue(Datum value, Oid postgres_type) {
case TIMESTAMPTZOID:
return duckdb::Value::TIMESTAMPTZ(
duckdb::timestamp_t(DatumGetTimestampTz(value) + PGDUCKDB_DUCK_TIMESTAMP_OFFSET));
case INTERVALOID:
return duckdb::Value::INTERVAL(DatumGetInterval(value));
case FLOAT4OID:
return duckdb::Value::FLOAT(DatumGetFloat4(value));
case FLOAT8OID:
Expand Down Expand Up @@ -1257,6 +1308,9 @@ ConvertPostgresToDuckValue(Oid attr_type, Datum value, duckdb::Vector &result, i
Append<duckdb::timestamp_t>(
result, duckdb::timestamp_t(static_cast<int64_t>(value + PGDUCKDB_DUCK_TIMESTAMP_OFFSET)), offset);
break;
case duckdb::LogicalTypeId::INTERVAL:
Append<duckdb::interval_t>(result, DatumGetInterval(value), offset);
break;
case duckdb::LogicalTypeId::FLOAT:
Append<float>(result, DatumGetFloat4(value), offset);
break;
Expand Down
24 changes: 24 additions & 0 deletions test/regression/expected/array_type_support.out
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,19 @@ SELECT * FROM varchar_array_1d;
{}
(4 rows)

-- INTERVAL (single dimension)
CREATE TABLE interval_array_1d(a INTERVAL[]);
INSERT INTO interval_array_1d (a) VALUES (ARRAY['2 years 5 months 1 day 3 hours 30 minutes 5 seconds', '5 days 5 hours']::INTERVAL[]);
INSERT INTO interval_array_1d (a) VALUES (ARRAY['3 seconds']::INTERVAL[]);
INSERT INTO interval_array_1d (a) VALUES (ARRAY[NULL]::INTERVAL[]);
SELECT * FROM interval_array_1d;
a
----------------------------------------------------------------------
{"@ 2 years 5 mons 1 day 3 hours 30 mins 5 secs","@ 5 days 5 hours"}
{"@ 3 secs"}
{NULL}
(3 rows)

-- TIMESTAMP (single dimension)
CREATE TABLE timestamp_array_1d(a TIMESTAMP[]);
INSERT INTO timestamp_array_1d SELECT CAST(a as TIMESTAMP[]) FROM (VALUES
Expand Down Expand Up @@ -352,6 +365,15 @@ SELECT * FROM bytea_array_1d;
{"\\x11223344","\\x55667788"}
(2 rows)

-- INTERVAL (two dimensions)
CREATE TABLE interval_array_2d(a INTERVAL[][]);
INSERT INTO interval_array_2d (a) VALUES (ARRAY[ARRAY['3 seconds', '5 minutes'], ARRAY['1 day', '2 hours']]::INTERVAL[][]);
SELECT * FROM interval_array_2d;
a
---------------------------------------------------
{{"@ 3 secs","@ 5 mins"},{"@ 1 day","@ 2 hours"}}
(1 row)

-- TIMESTAMP (two dimensions)
CREATE TABLE timestamp_array_2d(a TIMESTAMP[][]);
INSERT INTO timestamp_array_2d VALUES
Expand Down Expand Up @@ -469,6 +491,7 @@ DROP TABLE bool_array_1d;
DROP TABLE char_array_1d;
DROP TABLE smallint_array_1d;
DROP TABLE varchar_array_1d;
DROP TABLE interval_array_1d;
DROP TABLE timestamp_array_1d;
DROP TABLE float4_array_1d;
DROP TABLE float8_array_1d;
Expand All @@ -480,6 +503,7 @@ DROP TABLE regclass_array_1d;
DROP TABLE char_array_2d;
DROP TABLE smallint_array_2d;
DROP TABLE varchar_array_2d;
DROP TABLE interval_array_2d;
DROP TABLE timestamp_array_2d;
DROP TABLE float4_array_2d;
DROP TABLE float8_array_2d;
Expand Down
18 changes: 18 additions & 0 deletions test/regression/expected/type_support.out
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,23 @@ SELECT * FROM date_tbl;
05-15-2023
(3 rows)

-- INTERVAL
CREATE TABLE interval_tbl(a INTERVAL);
INSERT INTO interval_tbl SELECT CAST(a AS INTERVAL) FROM (VALUES ('2 years 5 months 1 day 3 hours 30 minutes 5 seconds'::INTERVAL), ('5 day 5 hours'::INTERVAL), (NULL)) t(a);
SELECT * FROM interval_tbl;
a
-----------------------------------------------
@ 2 years 5 mons 1 day 3 hours 30 mins 5 secs
@ 5 days 5 hours

(3 rows)

SELECT * FROM interval_tbl WHERE a = '5 day 5 hours'::INTERVAL;
a
------------------
@ 5 days 5 hours
(1 row)

-- TIMESTAMP
CREATE TABLE timestamp_tbl(a TIMESTAMP);
INSERT INTO timestamp_tbl SELECT CAST(a AS TIMESTAMP) FROM (VALUES
Expand Down Expand Up @@ -394,6 +411,7 @@ DROP TABLE bpchar_tbl;
DROP TABLE varchar_tbl;
DROP TABLE text_tbl;
DROP TABLE date_tbl;
DROP TABLE interval_tbl;
DROP TABLE timestamp_tbl;
DROP TABLE timestamptz_tbl;
DROP TABLE float4_tbl;
Expand Down
14 changes: 14 additions & 0 deletions test/regression/sql/array_type_support.sql
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,13 @@ INSERT INTO varchar_array_1d SELECT CAST(a as VARCHAR[]) FROM (VALUES
) t(a);
SELECT * FROM varchar_array_1d;

-- INTERVAL (single dimension)
CREATE TABLE interval_array_1d(a INTERVAL[]);
INSERT INTO interval_array_1d (a) VALUES (ARRAY['2 years 5 months 1 day 3 hours 30 minutes 5 seconds', '5 days 5 hours']::INTERVAL[]);
INSERT INTO interval_array_1d (a) VALUES (ARRAY['3 seconds']::INTERVAL[]);
INSERT INTO interval_array_1d (a) VALUES (ARRAY[NULL]::INTERVAL[]);
SELECT * FROM interval_array_1d;

-- TIMESTAMP (single dimension)
CREATE TABLE timestamp_array_1d(a TIMESTAMP[]);
INSERT INTO timestamp_array_1d SELECT CAST(a as TIMESTAMP[]) FROM (VALUES
Expand Down Expand Up @@ -218,6 +225,11 @@ VALUES
(ARRAY[decode('11223344', 'hex'), decode('55667788', 'hex')]);
SELECT * FROM bytea_array_1d;

-- INTERVAL (two dimensions)
CREATE TABLE interval_array_2d(a INTERVAL[][]);
INSERT INTO interval_array_2d (a) VALUES (ARRAY[ARRAY['3 seconds', '5 minutes'], ARRAY['1 day', '2 hours']]::INTERVAL[][]);
SELECT * FROM interval_array_2d;

-- TIMESTAMP (two dimensions)
CREATE TABLE timestamp_array_2d(a TIMESTAMP[][]);
INSERT INTO timestamp_array_2d VALUES
Expand Down Expand Up @@ -287,6 +299,7 @@ DROP TABLE bool_array_1d;
DROP TABLE char_array_1d;
DROP TABLE smallint_array_1d;
DROP TABLE varchar_array_1d;
DROP TABLE interval_array_1d;
DROP TABLE timestamp_array_1d;
DROP TABLE float4_array_1d;
DROP TABLE float8_array_1d;
Expand All @@ -298,6 +311,7 @@ DROP TABLE regclass_array_1d;
DROP TABLE char_array_2d;
DROP TABLE smallint_array_2d;
DROP TABLE varchar_array_2d;
DROP TABLE interval_array_2d;
DROP TABLE timestamp_array_2d;
DROP TABLE float4_array_2d;
DROP TABLE float8_array_2d;
Expand Down
7 changes: 7 additions & 0 deletions test/regression/sql/type_support.sql
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ CREATE TABLE date_tbl(a DATE);
INSERT INTO date_tbl SELECT CAST(a AS DATE) FROM (VALUES ('2022-04-29'::DATE), (NULL), ('2023-05-15'::DATE)) t(a);
SELECT * FROM date_tbl;

-- INTERVAL
CREATE TABLE interval_tbl(a INTERVAL);
INSERT INTO interval_tbl SELECT CAST(a AS INTERVAL) FROM (VALUES ('2 years 5 months 1 day 3 hours 30 minutes 5 seconds'::INTERVAL), ('5 day 5 hours'::INTERVAL), (NULL)) t(a);
SELECT * FROM interval_tbl;
SELECT * FROM interval_tbl WHERE a = '5 day 5 hours'::INTERVAL;

-- TIMESTAMP
CREATE TABLE timestamp_tbl(a TIMESTAMP);
INSERT INTO timestamp_tbl SELECT CAST(a AS TIMESTAMP) FROM (VALUES
Expand Down Expand Up @@ -200,6 +206,7 @@ DROP TABLE bpchar_tbl;
DROP TABLE varchar_tbl;
DROP TABLE text_tbl;
DROP TABLE date_tbl;
DROP TABLE interval_tbl;
DROP TABLE timestamp_tbl;
DROP TABLE timestamptz_tbl;
DROP TABLE float4_tbl;
Expand Down