Skip to content

Commit

Permalink
JSONB support (#513)
Browse files Browse the repository at this point in the history
Adding support for JSONB and JSONB[]
  • Loading branch information
ritwizsinha authored Jan 13, 2025
1 parent 9e5a5df commit cf6e6c4
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 5 deletions.
19 changes: 18 additions & 1 deletion src/pgduckdb_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ extern "C" {
#include "utils/syscache.h"
#include "utils/date.h"
#include "utils/timestamp.h"
#include "utils/jsonb.h"
}

#include "pgduckdb/pgduckdb_filter.hpp"
Expand Down Expand Up @@ -900,6 +901,8 @@ ConvertPostgresToBaseDuckColumnType(Form_pg_attribute &attribute) {
return duckdb::LogicalTypeId::UUID;
case JSONOID:
case JSONARRAYOID:
case JSONBOID:
case JSONBARRAYOID:
return duckdb::LogicalType::JSON();
case REGCLASSOID:
case REGCLASSARRAYOID:
Expand Down Expand Up @@ -1059,6 +1062,15 @@ AppendString(duckdb::Vector &result, Datum value, idx_t offset, bool is_bpchar)
data[offset] = duckdb::StringVector::AddString(result, str);
}

static void
AppendJsonb(duckdb::Vector &result, Datum value, idx_t offset) {
auto jsonb = DatumGetJsonbP(value);
auto jsonb_str = JsonbToCString(NULL, &jsonb->root, VARSIZE(jsonb));
duckdb::string_t str(jsonb_str);
auto data = duckdb::FlatVector::GetData<duckdb::string_t>(result);
data[offset] = duckdb::StringVector::AddString(result, str);
}

template <class T, class OP = DecimalConversionInteger>
T
ConvertDecimal(const NumericVar &numeric) {
Expand Down Expand Up @@ -1200,7 +1212,12 @@ ConvertPostgresToDuckValue(Oid attr_type, Datum value, duckdb::Vector &result, i
break;
case duckdb::LogicalTypeId::VARCHAR: {
// NOTE: This also handles JSON
AppendString(result, value, offset, attr_type == BPCHAROID);
if (attr_type == JSONBOID) {
AppendJsonb(result, value, offset);
break;
} else {
AppendString(result, value, offset, attr_type == BPCHAROID);
}
break;
}
case duckdb::LogicalTypeId::DATE:
Expand Down
26 changes: 24 additions & 2 deletions test/regression/expected/array_type_support.out
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,27 @@ SELECT * FROM json_array_1d;
{}
(4 rows)

-- JSONB (single dimension)
CREATE TABLE jsonb_array_1d(a JSONB[]);
INSERT INTO jsonb_array_1d VALUES
(ARRAY['{"key": "value"}', '{"array": [1, 2, 3]}']::JSONB[]),
(ARRAY[
'{"key1": "value1"}'::jsonb,
'{"key2": "value2"}'::jsonb
]),
(NULL),
(ARRAY['{"object": {"nested": "value"}}', NULL, '{"number": 42}']::JSONB[]),
(ARRAY[]::JSONB[]);
SELECT * FROM jsonb_array_1d;
a
-------------------------------------------------------------------
{"{\"key\": \"value\"}","{\"array\": [1, 2, 3]}"}
{"{\"key1\": \"value1\"}","{\"key2\": \"value2\"}"}

{"{\"object\": {\"nested\": \"value\"}}",NULL,"{\"number\": 42}"}
{}
(5 rows)

-- REGCLASS (single dimension)
CREATE TABLE regclass_array_1d(a REGCLASS[]);
INSERT INTO regclass_array_1d VALUES
Expand Down Expand Up @@ -320,8 +341,8 @@ SELECT * FROM varchar_array_2d;

-- BYTEA (single dimension)
CREATE TABLE bytea_array_1d (a bytea[]);
INSERT INTO bytea_array_1d (a)
VALUES
INSERT INTO bytea_array_1d (a)
VALUES
(ARRAY[decode('01020304', 'hex'), decode('aabbccdd', 'hex')]),
(ARRAY[decode('11223344', 'hex'), decode('55667788', 'hex')]);
SELECT * FROM bytea_array_1d;
Expand Down Expand Up @@ -454,6 +475,7 @@ DROP TABLE float8_array_1d;
DROP TABLE numeric_array_1d;
DROP TABLE uuid_array_1d;
DROP TABLE json_array_1d;
DROP TABLE jsonb_array_1d;
DROP TABLE regclass_array_1d;
DROP TABLE char_array_2d;
DROP TABLE smallint_array_2d;
Expand Down
21 changes: 21 additions & 0 deletions test/regression/expected/type_support.out
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,26 @@ SELECT * FROM json_tbl;
{}
(4 rows)

-- JSONB
CREATE TABLE jsonb_tbl(a JSONB);
INSERT INTO jsonb_tbl (a) VALUES
('{"a": 1, "b": {"c": 2, "d": [3, 4]}, "e": "hello"}'),
('{"f": 10, "g": {"h": 20, "i": 30}, "j": [40, 50, 60]}'),
('{"k": true, "l": null, "m": {"n": "world", "o": [7, 8, 9]}}'),
('[1, 2, 3]'),
('["a", "b", "c"]'),
('[{"key": "value"}, {"key": "another"}]');
SELECT * FROM jsonb_tbl;
a
-------------------------------------------------------------
{"a": 1, "b": {"c": 2, "d": [3, 4]}, "e": "hello"}
{"f": 10, "g": {"h": 20, "i": 30}, "j": [40, 50, 60]}
{"k": true, "l": null, "m": {"n": "world", "o": [7, 8, 9]}}
[1, 2, 3]
["a", "b", "c"]
[{"key": "value"}, {"key": "another"}]
(6 rows)

-- BLOB
CREATE TABLE blob_tbl(a bytea);
INSERT INTO blob_tbl SELECT CAST(a as bytea) FROM (VALUES
Expand Down Expand Up @@ -364,5 +384,6 @@ DROP TABLE bigint_numeric;
DROP TABLE hugeint_numeric;
DROP TABLE uuid_tbl;
DROP TABLE json_tbl;
DROP TABLE jsonb_tbl;
DROP TABLE blob_tbl;
DROP TABLE regclass_tbl;
19 changes: 17 additions & 2 deletions test/regression/sql/array_type_support.sql
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,20 @@ INSERT INTO json_array_1d VALUES
(ARRAY[]::JSON[]);
SELECT * FROM json_array_1d;


-- JSONB (single dimension)
CREATE TABLE jsonb_array_1d(a JSONB[]);
INSERT INTO jsonb_array_1d VALUES
(ARRAY['{"key": "value"}', '{"array": [1, 2, 3]}']::JSONB[]),
(ARRAY[
'{"key1": "value1"}'::jsonb,
'{"key2": "value2"}'::jsonb
]),
(NULL),
(ARRAY['{"object": {"nested": "value"}}', NULL, '{"number": 42}']::JSONB[]),
(ARRAY[]::JSONB[]);
SELECT * FROM jsonb_array_1d;

-- REGCLASS (single dimension)
CREATE TABLE regclass_array_1d(a REGCLASS[]);
INSERT INTO regclass_array_1d VALUES
Expand Down Expand Up @@ -198,8 +212,8 @@ SELECT * FROM varchar_array_2d;
-- BYTEA (single dimension)
CREATE TABLE bytea_array_1d (a bytea[]);

INSERT INTO bytea_array_1d (a)
VALUES
INSERT INTO bytea_array_1d (a)
VALUES
(ARRAY[decode('01020304', 'hex'), decode('aabbccdd', 'hex')]),
(ARRAY[decode('11223344', 'hex'), decode('55667788', 'hex')]);
SELECT * FROM bytea_array_1d;
Expand Down Expand Up @@ -279,6 +293,7 @@ DROP TABLE float8_array_1d;
DROP TABLE numeric_array_1d;
DROP TABLE uuid_array_1d;
DROP TABLE json_array_1d;
DROP TABLE jsonb_array_1d;
DROP TABLE regclass_array_1d;
DROP TABLE char_array_2d;
DROP TABLE smallint_array_2d;
Expand Down
12 changes: 12 additions & 0 deletions test/regression/sql/type_support.sql
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,17 @@ INSERT INTO json_tbl SELECT CAST(a as JSON) FROM (VALUES
) t(a);
SELECT * FROM json_tbl;

-- JSONB
CREATE TABLE jsonb_tbl(a JSONB);
INSERT INTO jsonb_tbl (a) VALUES
('{"a": 1, "b": {"c": 2, "d": [3, 4]}, "e": "hello"}'),
('{"f": 10, "g": {"h": 20, "i": 30}, "j": [40, 50, 60]}'),
('{"k": true, "l": null, "m": {"n": "world", "o": [7, 8, 9]}}'),
('[1, 2, 3]'),
('["a", "b", "c"]'),
('[{"key": "value"}, {"key": "another"}]');
SELECT * FROM jsonb_tbl;

-- BLOB
CREATE TABLE blob_tbl(a bytea);
INSERT INTO blob_tbl SELECT CAST(a as bytea) FROM (VALUES
Expand Down Expand Up @@ -191,5 +202,6 @@ DROP TABLE bigint_numeric;
DROP TABLE hugeint_numeric;
DROP TABLE uuid_tbl;
DROP TABLE json_tbl;
DROP TABLE jsonb_tbl;
DROP TABLE blob_tbl;
DROP TABLE regclass_tbl;

0 comments on commit cf6e6c4

Please sign in to comment.