Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
19 changes: 17 additions & 2 deletions src/common/ducklake_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ string ToSQLString(DuckLakeMetadataManager &metadata_manager, const Value &value
case LogicalTypeId::VARIANT: {
Vector tmp(value, count_t(1));
RecursiveUnifiedVectorFormat format;
Vector::RecursiveToUnifiedFormat(tmp, 1, format);
Vector::RecursiveToUnifiedFormat(tmp, format);
UnifiedVariantVectorData vector_data(format);
auto val = VariantUtils::ConvertVariantToValue(vector_data, 0, 0);
if (!use_native_type) {
Expand Down Expand Up @@ -278,6 +278,13 @@ string DuckLakeUtil::ValueToSQL(DuckLakeMetadataManager &metadata_manager, Clien
auto str_val = val.CastAs(context, LogicalType::VARCHAR);
return ValueToSQL(metadata_manager, context, str_val);
}
const bool native_type = metadata_manager.TypeIsNativelySupported(val.type());
const bool nested_type = val.type().IsNested();
if (!native_type && nested_type) {
auto json_value = val.CastAs(context, LogicalType::JSON());
auto text = json_value.ToString();
return StringUtil::Format("%s", SQLString(text));
}
string result;
switch (val.type().id()) {
case LogicalTypeId::VARCHAR: {
Expand All @@ -287,6 +294,14 @@ string DuckLakeUtil::ValueToSQL(DuckLakeMetadataManager &metadata_manager, Clien
}
return EscapeVarcharForSQL(str_val);
}
case LogicalTypeId::BIT: {
auto bit_text = val.ToString();
if (!bit_text.empty() && (bit_text[0] == 'b' || bit_text[0] == 'B')) {
bit_text = bit_text.substr(1);
}
result = StringUtil::Format("%s", SQLString(bit_text));
break;
}
case LogicalTypeId::BLOB: {
if (!metadata_manager.TypeIsNativelySupported(LogicalType::BLOB)) {
return ToByteaHexLiteral(StringValue::Get(val));
Expand All @@ -297,7 +312,7 @@ string DuckLakeUtil::ValueToSQL(DuckLakeMetadataManager &metadata_manager, Clien
default:
result = ToSQLString(metadata_manager, val);
}
if (metadata_manager.TypeIsNativelySupported(val.type()) || !val.type().IsNested()) {
if (native_type || !val.type().IsNested()) {
return result;
}
return StringUtil::Format("%s", SQLString(result));
Expand Down
1 change: 1 addition & 0 deletions src/include/metadata_manager/postgres_metadata_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class PostgresMetadataManager : public DuckLakeMetadataManager {
}

string GetColumnTypeInternal(const LogicalType &type) override;
string CastColumnToTarget(const string &column, const LogicalType &type) override;
shared_ptr<DuckLakeInlinedData> TransformInlinedData(QueryResult &result,
const vector<LogicalType> &expected_types) override;

Expand Down
7 changes: 7 additions & 0 deletions src/metadata_manager/postgres_metadata_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,13 @@ string PostgresMetadataManager::GetColumnTypeInternal(const LogicalType &column_
}
}

string PostgresMetadataManager::CastColumnToTarget(const string &column, const LogicalType &type) {
if (type.IsNested()) {
return StringUtil::Format("CAST(CAST(%s AS JSON) AS %s)", column, type.ToString());
}
return DuckLakeMetadataManager::CastColumnToTarget(column, type);
}

unique_ptr<QueryResult> PostgresMetadataManager::ExecuteQuery(DuckLakeSnapshot snapshot, string &query,
string command) {
auto &commit_info = transaction.GetCommitInfo();
Expand Down
2 changes: 1 addition & 1 deletion test/configs/postgres.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"description": "Run DuckLake tests using Postgres as a catalog DBMS.",
"on_init": "ATTACH 'dbname=ducklakedb' AS pg (TYPE postgres); USE pg; DROP SCHEMA public CASCADE; DROP SCHEMA IF EXISTS metadata_s1 CASCADE; DROP SCHEMA IF EXISTS metadata_s2 CASCADE; CREATE SCHEMA public;USE memory; DETACH pg; SET pg_experimental_filter_pushdown=false;",
"on_init": "SET extension_directory='{TEST_DIR}/extensions'; INSTALL postgres FROM '__BUILD_DIRECTORY__/repository'; INSTALL json FROM '__BUILD_DIRECTORY__/repository'; LOAD postgres; LOAD json; ATTACH 'dbname=ducklakedb' AS pg (TYPE postgres); USE pg; DROP SCHEMA public CASCADE; DROP SCHEMA IF EXISTS metadata_s1 CASCADE; DROP SCHEMA IF EXISTS metadata_s2 CASCADE; CREATE SCHEMA public;USE memory; DETACH pg; SET pg_experimental_filter_pushdown=false;",
"autoloading": "none",
"statically_loaded_extensions": [
"core_functions",
Expand Down
66 changes: 66 additions & 0 deletions test/sql/data_inlining/postgres_inline_struct_timestamps.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# name: test/sql/data_inlining/postgres_inline_struct_timestamps.test
# description: check inline struct timestamp variants with postgres metadata
# group: [data_inlining]

require ducklake

require parquet

require json

require postgres_scanner

test-env DATA_PATH {TEST_DIR}

test-env DUCKLAKE_CONNECTION {DUCKLAKE_CONNECTION}

statement ok
SET TimeZone='UTC';

statement ok
ATTACH 'ducklake:{DUCKLAKE_CONNECTION}' AS ducklake (DATA_PATH '{DATA_PATH}/ducklake_postgres_inline_struct_timestamps', METADATA_SCHEMA 'inline_struct_timestamps_{UUID}', DATA_INLINING_ROW_LIMIT 10)

statement ok
CREATE TABLE ducklake.events (
id INTEGER,
event_struct STRUCT(
ts TIMESTAMP,
ts_ns TIMESTAMP_NS,
ts_tz TIMESTAMPTZ,
ts_tz_ns TIMESTAMPTZ_NS
)
);

statement ok
INSERT INTO ducklake.events VALUES (
1,
struct_pack(
ts := TIMESTAMP '2024-01-01 02:03:04',
ts_ns := CAST('2024-01-01 02:03:04' AS TIMESTAMP_NS),
ts_tz := CAST('2024-01-01 02:03:04+00' AS TIMESTAMPTZ),
ts_tz_ns := CAST('2024-01-01 02:03:04+00' AS TIMESTAMPTZ_NS)
)
);

statement ok
CALL ducklake_flush_inlined_data('ducklake');

query T
SELECT struct_extract(event_struct, 'ts')::VARCHAR FROM ducklake.events;
----
2024-01-01 02:03:04

query T
SELECT struct_extract(event_struct, 'ts_ns')::VARCHAR FROM ducklake.events;
----
2024-01-01 02:03:04

query T
SELECT struct_extract(event_struct, 'ts_tz')::VARCHAR FROM ducklake.events;
----
2024-01-01 02:03:04+00

query T
SELECT struct_extract(event_struct, 'ts_tz_ns')::VARCHAR FROM ducklake.events;
----
2024-01-01 02:03:04+00
Loading