From dfdf7697a0b47f2823d68a253710fdf74c1afc9f Mon Sep 17 00:00:00 2001 From: Tishj Date: Wed, 22 May 2024 14:49:48 +0200 Subject: [PATCH] add JSON type support --- Makefile | 9 ++++++++- include/quack/quack_types.hpp | 2 +- sql/type_support.sql | 13 ++++++++++++- src/quack_planner.cpp | 2 +- src/quack_types.cpp | 24 ++++++++++++++++++------ 5 files changed, 40 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index fba5f04f..f6cc1ff0 100644 --- a/Makefile +++ b/Makefile @@ -66,7 +66,14 @@ third_party/duckdb/Makefile: git submodule update --init --recursive third_party/duckdb/build/$(QUACK_BUILD_DUCKDB)/src/$(DUCKDB_LIB): - $(MAKE) -C third_party/duckdb $(QUACK_BUILD_DUCKDB) DISABLE_SANITIZER=1 ENABLE_UBSAN=0 BUILD_UNITTESTS=OFF BUILD_HTTPFS=1 CMAKE_EXPORT_COMPILE_COMMANDS=1 + $(MAKE) -C third_party/duckdb \ + $(QUACK_BUILD_DUCKDB) \ + DISABLE_SANITIZER=1 \ + ENABLE_UBSAN=0 \ + BUILD_UNITTESTS=OFF \ + BUILD_HTTPFS=1 \ + BUILD_JSON=1 \ + CMAKE_EXPORT_COMPILE_COMMANDS=1 install_duckdb: $(install_bin) -m 755 third_party/duckdb/build/$(QUACK_BUILD_DUCKDB)/src/$(DUCKDB_LIB) $(DESTDIR)$(PG_LIB) diff --git a/include/quack/quack_types.hpp b/include/quack/quack_types.hpp index 82fdf428..d2ad9f0e 100644 --- a/include/quack/quack_types.hpp +++ b/include/quack/quack_types.hpp @@ -16,7 +16,7 @@ constexpr int32_t QUACK_DUCK_DATE_OFFSET = 10957; constexpr int64_t QUACK_DUCK_TIMESTAMP_OFFSET = INT64CONST(10957) * USECS_PER_DAY; duckdb::LogicalType ConvertPostgresToDuckColumnType(Oid type, int32_t typmod); -Oid GetPostgresDuckDBType(duckdb::LogicalTypeId type); +Oid GetPostgresDuckDBType(duckdb::LogicalType type); void ConvertPostgresToDuckValue(Datum value, duckdb::Vector &result, idx_t offset); void ConvertDuckToPostgresValue(TupleTableSlot *slot, duckdb::Value &value, idx_t col); void InsertTupleIntoChunk(duckdb::DataChunk &output, PostgresHeapSeqScanThreadInfo &threadScanInfo, diff --git a/sql/type_support.sql b/sql/type_support.sql index 4c6da769..fe24d491 100644 --- a/sql/type_support.sql +++ b/sql/type_support.sql @@ -117,6 +117,16 @@ INSERT INTO uuid_tbl SELECT CAST(a as UUID) FROM (VALUES ) t(a); SELECT * FROM uuid_tbl; +-- JSON +CREATE TABLE json_tbl(a JSON); +INSERT INTO json_tbl SELECT CAST(a as JSON) FROM (VALUES + ('{"key1": "value1", "key2": "value2"}'), + ('["item1", "item2", "item3"]'), + (NULL), + ('{}') +) t(a); +SELECT * FROM json_tbl; + DROP TABLE chr; DROP TABLE small; DROP TABLE intgr; @@ -131,4 +141,5 @@ DROP TABLE smallint_numeric; DROP TABLE integer_numeric; DROP TABLE bigint_numeric; DROP TABLE hugeint_numeric; -DROP TABLE uuid_tbl; \ No newline at end of file +DROP TABLE uuid_tbl; +DROP TABLE json_tbl; diff --git a/src/quack_planner.cpp b/src/quack_planner.cpp index e748ceca..d0e25e71 100644 --- a/src/quack_planner.cpp +++ b/src/quack_planner.cpp @@ -71,7 +71,7 @@ quack_create_plan(Query *parse, const char *query) { for (auto i = 0; i < preparedResultTypes.size(); i++) { auto &column = preparedResultTypes[i]; - Oid postgresColumnOid = quack::GetPostgresDuckDBType(column.id()); + Oid postgresColumnOid = quack::GetPostgresDuckDBType(column); if (OidIsValid(postgresColumnOid)) { HeapTuple tp; diff --git a/src/quack_types.cpp b/src/quack_types.cpp index 3831d3e2..1a0c4902 100644 --- a/src/quack_types.cpp +++ b/src/quack_types.cpp @@ -119,6 +119,7 @@ ConvertDuckToPostgresValue(TupleTableSlot *slot, duckdb::Value &value, idx_t col break; case BPCHAROID: case TEXTOID: + case JSONOID: case VARCHAROID: { auto str = value.GetValue(); auto varchar = str.c_str(); @@ -264,14 +265,17 @@ ConvertPostgresToDuckColumnType(Oid type, int32_t typmod) { } case UUIDOID: return duckdb::LogicalTypeId::UUID; + case JSONOID: + return duckdb::LogicalType::JSON(); default: elog(ERROR, "(DuckDB/ConvertPostgresToDuckColumnType) Unsupported quack type: %d", type); } } Oid -GetPostgresDuckDBType(duckdb::LogicalTypeId type) { - switch (type) { +GetPostgresDuckDBType(duckdb::LogicalType type) { + auto id = type.id(); + switch (id) { case duckdb::LogicalTypeId::BOOLEAN: return BOOLOID; case duckdb::LogicalTypeId::TINYINT: @@ -284,8 +288,12 @@ GetPostgresDuckDBType(duckdb::LogicalTypeId type) { return INT8OID; case duckdb::LogicalTypeId::HUGEINT: return NUMERICOID; - case duckdb::LogicalTypeId::VARCHAR: + case duckdb::LogicalTypeId::VARCHAR: { + if (type.IsJSONType()) { + return JSONOID; + } return VARCHAROID; + } case duckdb::LogicalTypeId::DATE: return DATEOID; case duckdb::LogicalTypeId::TIMESTAMP: @@ -299,8 +307,10 @@ GetPostgresDuckDBType(duckdb::LogicalTypeId type) { } case duckdb::LogicalTypeId::UUID: return UUIDOID; - default: - elog(ERROR, "(DuckDB/GetPostgresDuckDBType) Unsupported quack type: %d", static_cast(type)); + default: { + elog(ERROR, "(DuckDB/GetPostgresDuckDBType) Unsupported quack type: %s", type.ToString().c_str()); + break; + } } } @@ -405,9 +415,11 @@ ConvertPostgresToDuckValue(Datum value, duckdb::Vector &result, idx_t offset) { case duckdb::LogicalTypeId::BIGINT: Append(result, DatumGetInt64(value), offset); break; - case duckdb::LogicalTypeId::VARCHAR: + case duckdb::LogicalTypeId::VARCHAR: { + // NOTE: This also handles JSON AppendString(result, value, offset); break; + } case duckdb::LogicalTypeId::DATE: Append(result, duckdb::date_t(static_cast(value + QUACK_DUCK_DATE_OFFSET)), offset); break;