From 29941c6be75dd512e29296098c1ee02167652bf3 Mon Sep 17 00:00:00 2001 From: ruslandoga Date: Sun, 9 Feb 2025 12:17:38 +0300 Subject: [PATCH] eh? --- lib/ch/row_binary.ex | 16 +++++++++++++- test/ch/connection_test.exs | 43 +++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/lib/ch/row_binary.ex b/lib/ch/row_binary.ex index 3e7511d..6477875 100644 --- a/lib/ch/row_binary.ex +++ b/lib/ch/row_binary.ex @@ -698,6 +698,20 @@ defmodule Ch.RowBinary do defp utf8_size(codepoint) when codepoint <= 0xFFFF, do: 3 defp utf8_size(codepoint) when codepoint <= 0x10FFFF, do: 4 + @compile inline: [decode_json_decode_rows: 5] + + for {pattern, size} <- varints do + defp decode_json_decode_rows( + <>, + types_rest, + row, + rows, + types + ) do + decode_rows(types_rest, bin, [:json.decode(s) | row], rows, types) + end + end + @compile inline: [decode_binary_decode_rows: 5] for {pattern, size} <- varints do @@ -867,7 +881,7 @@ defmodule Ch.RowBinary do decode_rows(types_rest, bin, [Date.add(@epoch_date, d) | row], rows, types) :json -> - raise ArgumentError, "JSON type is not supported for decoding: #{inspect(bin)}" + decode_json_decode_rows(bin, types_rest, row, rows, types) {:datetime, timezone} -> <> = bin diff --git a/test/ch/connection_test.exs b/test/ch/connection_test.exs index 8894d6e..acf1785 100644 --- a/test/ch/connection_test.exs +++ b/test/ch/connection_test.exs @@ -568,12 +568,55 @@ defmodule Ch.ConnectionTest do }} = Ch.query(conn, "SELECT * FROM t_uuid ORDER BY y") end + # TODO non utf8 + test "read json as string", %{conn: conn} do + assert Ch.query!(conn, ~s|select '{"a":42}'::JSON|, [], + settings: [ + enable_json_type: 1, + output_format_binary_write_json_as_string: 1 + ] + ).rows == [[%{"a" => "42"}]] + end + + test "write->read json as string", %{conn: conn} do + Ch.query!(conn, "CREATE TABLE test_write_json(json JSON) ENGINE = Memory", [], + settings: [ + enable_json_type: 1 + ] + ) + + rowbinary = + Ch.RowBinary.encode_rows( + [ + [:json.encode(%{"a" => 42})], + [:json.encode(%{"b" => 10})] + ], + _types = [:string] + ) + + Ch.query!(conn, ["insert into test_write_json(json) format RowBinary\n" | rowbinary], [], + settings: [ + enable_json_type: 1, + input_format_binary_read_json_as_string: 1 + ] + ) + + assert Ch.query!(conn, "select json from test_write_json", [], + settings: [ + enable_json_type: 1, + output_format_binary_write_json_as_string: 1 + ] + ).rows == + [[%{"a" => "42"}], [%{"b" => "10"}]] + end + # https://clickhouse.com/docs/en/sql-reference/data-types/newjson # https://clickhouse.com/docs/en/integrations/data-formats/json/overview # https://clickhouse.com/blog/a-new-powerful-json-data-type-for-clickhouse # https://clickhouse.com/blog/json-bench-clickhouse-vs-mongodb-elasticsearch-duckdb-postgresql # https://github.com/ClickHouse/ClickHouse/pull/70288 # https://github.com/ClickHouse/ClickHouse/blob/master/src/Core/TypeId.h + @tag :skip test "json", %{conn: conn} do settings = [enable_json_type: 1]