Skip to content

Commit 17b1d1a

Browse files
committed
new json
1 parent e70a3d3 commit 17b1d1a

File tree

3 files changed

+91
-6
lines changed

3 files changed

+91
-6
lines changed

lib/ch/row_binary.ex

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,7 @@ defmodule Ch.RowBinary do
516516
:uuid,
517517
:date,
518518
:date32,
519+
:json,
519520
:ipv4,
520521
:ipv6,
521522
:point,
@@ -697,6 +698,20 @@ defmodule Ch.RowBinary do
697698
defp utf8_size(codepoint) when codepoint <= 0xFFFF, do: 3
698699
defp utf8_size(codepoint) when codepoint <= 0x10FFFF, do: 4
699700

701+
@compile inline: [decode_json_decode_rows: 5]
702+
703+
for {pattern, size} <- varints do
704+
defp decode_json_decode_rows(
705+
<<unquote(pattern), s::size(unquote(size))-bytes, bin::bytes>>,
706+
types_rest,
707+
row,
708+
rows,
709+
types
710+
) do
711+
decode_rows(types_rest, bin, [Jason.decode!(s) | row], rows, types)
712+
end
713+
end
714+
700715
@compile inline: [decode_binary_decode_rows: 5]
701716

702717
for {pattern, size} <- varints do
@@ -865,6 +880,9 @@ defmodule Ch.RowBinary do
865880
<<d::32-little-signed, bin::bytes>> = bin
866881
decode_rows(types_rest, bin, [Date.add(@epoch_date, d) | row], rows, types)
867882

883+
:json ->
884+
decode_json_decode_rows(bin, types_rest, row, rows, types)
885+
868886
{:datetime, timezone} ->
869887
<<s::32-little, bin::bytes>> = bin
870888

lib/ch/types.ex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ defmodule Ch.Types do
2626
# {"DateTime", :datetime, []},
2727
{"Date32", :date32, []},
2828
{"Date", :date, []},
29+
{"JSON", :json, []},
2930
{"LowCardinality", :low_cardinality, [:type]},
3031
for size <- [32, 64, 128, 256] do
3132
{"Decimal#{size}", :"decimal#{size}", [:int]}

test/ch/connection_test.exs

Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -568,20 +568,86 @@ defmodule Ch.ConnectionTest do
568568
}} = Ch.query(conn, "SELECT * FROM t_uuid ORDER BY y")
569569
end
570570

571+
# TODO non utf8
572+
test "read json as string", %{conn: conn} do
573+
assert Ch.query!(conn, ~s|select '{"a":42}'::JSON|, [],
574+
settings: [
575+
enable_json_type: 1,
576+
output_format_binary_write_json_as_string: 1
577+
]
578+
).rows == [[%{"a" => "42"}]]
579+
end
580+
581+
test "write->read json as string", %{conn: conn} do
582+
Ch.query!(conn, "CREATE TABLE test_write_json(json JSON) ENGINE = Memory", [],
583+
settings: [
584+
enable_json_type: 1
585+
]
586+
)
587+
588+
rowbinary =
589+
Ch.RowBinary.encode_rows(
590+
[
591+
[Jason.encode_to_iodata!(%{"a" => 42})],
592+
[Jason.encode_to_iodata!(%{"b" => 10})]
593+
],
594+
_types = [:string]
595+
)
596+
597+
Ch.query!(conn, ["insert into test_write_json(json) format RowBinary\n" | rowbinary], [],
598+
settings: [
599+
enable_json_type: 1,
600+
input_format_binary_read_json_as_string: 1
601+
]
602+
)
603+
604+
assert Ch.query!(conn, "select json from test_write_json", [],
605+
settings: [
606+
enable_json_type: 1,
607+
output_format_binary_write_json_as_string: 1
608+
]
609+
).rows ==
610+
[[%{"a" => "42"}], [%{"b" => "10"}]]
611+
end
612+
613+
# https://clickhouse.com/docs/en/sql-reference/data-types/newjson
614+
# https://clickhouse.com/docs/en/integrations/data-formats/json/overview
615+
# https://clickhouse.com/blog/a-new-powerful-json-data-type-for-clickhouse
616+
# https://clickhouse.com/blog/json-bench-clickhouse-vs-mongodb-elasticsearch-duckdb-postgresql
617+
# https://github.com/ClickHouse/ClickHouse/pull/70288
618+
# https://github.com/ClickHouse/ClickHouse/blob/master/src/Core/TypeId.h
571619
@tag :skip
572620
test "json", %{conn: conn} do
573-
settings = [allow_experimental_object_type: 1]
621+
settings = [enable_json_type: 1]
574622

575-
Ch.query!(conn, "CREATE TABLE json(o JSON) ENGINE = Memory", [], settings: settings)
623+
assert Ch.query!(
624+
conn,
625+
~s|select '{"a":42,"b":10}'::JSON|,
626+
[],
627+
settings: settings,
628+
decode: false,
629+
format: "RowBinary"
630+
).rows == [
631+
<<2, 1, 97, 10, 42, 0, 0, 0, 0, 0, 0, 0, 1, 98, 10, 10, 0, 0, 0, 0, 0, 0, 0>>
632+
]
576633

577-
Ch.query!(conn, ~s|INSERT INTO json VALUES ('{"a": 1, "b": { "c": 2, "d": [1, 2, 3] }}')|)
634+
# Ch.query!(conn, "CREATE TABLE test_json(json JSON) ENGINE = Memory", [], settings: settings)
578635

579-
assert Ch.query!(conn, "SELECT o.a, o.b.c, o.b.d[3] FROM json").rows == [[1, 2, 3]]
636+
# Ch.query!(
637+
# conn,
638+
# ~s|INSERT INTO test_json VALUES ('{"a" : {"b" : 42}, "c" : [1, 2, 3]}'), ('{"f" : "Hello, World!"}'), ('{"a" : {"b" : 43, "e" : 10}, "c" : [4, 5, 6]}')|
639+
# )
580640

581-
# named tuples are not supported yet
582-
assert_raise ArgumentError, fn -> Ch.query!(conn, "SELECT o FROM json") end
641+
# assert Ch.query!(conn, "SELECT json FROM test_json") == :asdf
642+
643+
# assert Ch.query!(conn, "SELECT json.a, json.b.c, json.b.d[3] FROM test_json").rows == [
644+
# [1, 2, 3]
645+
# ]
583646
end
584647

648+
# TODO variant (is there?)
649+
# TODO dynamic
650+
585651
# TODO enum16
586652

587653
test "enum8", %{conn: conn} do

0 commit comments

Comments
 (0)