From a482ab2c4e5b307df8f6246e7e5f91ddfc5cb0aa Mon Sep 17 00:00:00 2001 From: Ildus Kurbangaliev Date: Fri, 27 Nov 2020 09:47:40 +0500 Subject: [PATCH] add support of IPv4 and IPv6, fix #56 --- src/binary.cc | 16 ++++++++- src/pglink.c | 4 ++- tests/expected/import_schema.out | 60 +++++++++++++++++++++++++++++++- tests/sql/import_schema.sql | 16 +++++++++ 4 files changed, 93 insertions(+), 3 deletions(-) diff --git a/src/binary.cc b/src/binary.cc index 704a434..5f427f6 100644 --- a/src/binary.cc +++ b/src/binary.cc @@ -3,6 +3,7 @@ #include #include "clickhouse/columns/date.h" +#include "clickhouse/columns/ip4.h" #include "clickhouse/columns/lowcardinality.h" #include "clickhouse/columns/nullable.h" #include "clickhouse/columns/factory.h" @@ -18,6 +19,7 @@ extern "C" { #include "postgres.h" #include "pgtime.h" #include "funcapi.h" +#include "fmgr.h" #include "access/htup_details.h" #include "access/tupdesc.h" #include "catalog/pg_type_d.h" @@ -922,8 +924,20 @@ static Datum make_datum(clickhouse::ColumnRef col, size_t row, Oid * valtype, bo *valtype = TEXTOID; } break; + case Type::Code::IPv4: { + auto item = col->As()->AsString(row); + ret = DirectFunctionCall1(inet_in, CStringGetDatum(item.c_str())); + *valtype = INETOID; + } + break; + case Type::Code::IPv6: { + auto item = col->As()->AsString(row); + ret = DirectFunctionCall1(inet_in, CStringGetDatum(item.c_str())); + *valtype = INETOID; + } + break; default: - throw std::runtime_error("clickhouse_fdw: unsupported type"); + throw std::runtime_error("unsupported type in binary protocol"); } return ret; diff --git a/src/pglink.c b/src/pglink.c index 70ccf6d..66bc8b4 100644 --- a/src/pglink.c +++ b/src/pglink.c @@ -748,6 +748,8 @@ static char *str_types_map[][2] = { {"DateTime", "TIMESTAMP"}, {"Date", "DATE"}, // important that this one is after other Date types {"UUID", "UUID"}, + {"IPv4", "inet"}, + {"IPv6", "inet"}, {NULL, NULL}, }; @@ -835,7 +837,7 @@ parse_type(char *colname, char *typepart, bool *is_nullable, List **options) } size_t i = 0; - while (str_types_map[i] != NULL) + while (str_types_map[i][0] != NULL) { if (strncmp(str_types_map[i][0], typepart, strlen(str_types_map[i][0])) == 0) { diff --git a/tests/expected/import_schema.out b/tests/expected/import_schema.out index 271f2c8..43da376 100644 --- a/tests/expected/import_schema.out +++ b/tests/expected/import_schema.out @@ -102,6 +102,27 @@ SELECT clickhousedb_raw_query('INSERT INTO regression.types2 SELECT (1 row) +SELECT clickhousedb_raw_query('CREATE TABLE regression.ip ( + c1 IPv4, + c2 IPv6 +) ENGINE = MergeTree PARTITION BY c1 ORDER BY (c1); +'); + clickhousedb_raw_query +------------------------ + +(1 row) + +SELECT clickhousedb_raw_query($$ + INSERT INTO regression.ip VALUES + ('116.106.34.242', '2001:44c8:129:2632:33:0:252:2'), + ('116.106.34.243', '2a02:e980:1e::1'), + ('116.106.34.244', '::1'); +$$); + clickhousedb_raw_query +------------------------ + +(1 row) + -- array types SELECT clickhousedb_raw_query('CREATE TABLE regression.arrays ( c1 Array(Int), c2 Array(String) @@ -254,6 +275,15 @@ FDW options: (database 'regression', table_name 'tuples', engine 'MergeTree') Server: loopback FDW options: (database 'regression', table_name 'timezones', engine 'MergeTree') +\d+ clickhouse.ip; + Foreign table "clickhouse.ip" + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description +--------+------+-----------+----------+---------+-------------+---------+--------------+------------- + c1 | inet | | not null | | | main | | + c2 | inet | | not null | | | main | | +Server: loopback +FDW options: (database 'regression', table_name 'ip', engine 'MergeTree') + SELECT * FROM clickhouse.ints ORDER BY c1 DESC LIMIT 4; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c9 | c10 ----+----+----+----+----+----+----+----+------+------ @@ -298,6 +328,14 @@ SELECT * FROM clickhouse.timezones ORDER BY t1 LIMIT 2; 2020-01-01 12:00:00 | 2020-01-01 12:00:00 | 2020-01-01 12:00:00 | 2020-01-01 12:00:00 (2 rows) +SELECT * FROM clickhouse.ip ORDER BY c1; + c1 | c2 +----------------+------------------------------- + 116.106.34.242 | 2001:44c8:129:2632:33:0:252:2 + 116.106.34.243 | 2a02:e980:1e::1 + 116.106.34.244 | ::1 +(3 rows) + IMPORT FOREIGN SCHEMA "regression" FROM SERVER loopback_bin INTO clickhouse_bin; NOTICE: clickhouse_fdw: ClickHouse type was translated to type for column "c5", change it to BOOLEAN if needed NOTICE: clickhouse_fdw: ClickHouse type was translated to type for column "c2", please create composite type and alter the column if needed @@ -374,6 +412,15 @@ FDW options: (database 'regression', table_name 'tuples', engine 'MergeTree') Server: loopback_bin FDW options: (database 'regression', table_name 'timezones', engine 'MergeTree') +\d+ clickhouse_bin.ip; + Foreign table "clickhouse_bin.ip" + Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description +--------+------+-----------+----------+---------+-------------+---------+--------------+------------- + c1 | inet | | not null | | | main | | + c2 | inet | | not null | | | main | | +Server: loopback_bin +FDW options: (database 'regression', table_name 'ip', engine 'MergeTree') + SELECT * FROM clickhouse_bin.ints ORDER BY c1 DESC LIMIT 4; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c9 | c10 ----+----+----+----+----+----+----+----+------+------ @@ -413,6 +460,14 @@ SELECT * FROM clickhouse_bin.timezones ORDER BY t1 LIMIT 2; 2020-01-01 12:00:00 | 2020-01-01 11:00:00 | 2020-01-01 11:00:00 | 2020-01-01 12:00:00 (2 rows) +SELECT * FROM clickhouse.ip ORDER BY c1; + c1 | c2 +----------------+------------------------------- + 116.106.34.242 | 2001:44c8:129:2632:33:0:252:2 + 116.106.34.243 | 2a02:e980:1e::1 + 116.106.34.244 | ::1 +(3 rows) + IMPORT FOREIGN SCHEMA "regression" LIMIT TO (ints, types) FROM SERVER loopback INTO clickhouse_limit; NOTICE: clickhouse_fdw: ClickHouse type was translated to type for column "c5", change it to BOOLEAN if needed \d+ clickhouse_limit.ints; @@ -515,10 +570,11 @@ SELECT clickhousedb_raw_query('DROP DATABASE regression_2'); (1 row) DROP EXTENSION clickhouse_fdw CASCADE; -NOTICE: drop cascades to 21 other objects +NOTICE: drop cascades to 24 other objects DETAIL: drop cascades to server loopback drop cascades to foreign table clickhouse.arrays drop cascades to foreign table clickhouse.ints +drop cascades to foreign table clickhouse.ip drop cascades to foreign table clickhouse.timezones drop cascades to foreign table clickhouse.tuples drop cascades to foreign table clickhouse.types @@ -526,6 +582,7 @@ drop cascades to foreign table clickhouse.types2 drop cascades to foreign table clickhouse_limit.ints drop cascades to foreign table clickhouse_limit.types drop cascades to foreign table clickhouse_except.arrays +drop cascades to foreign table clickhouse_except.ip drop cascades to foreign table clickhouse_except.timezones drop cascades to foreign table clickhouse_except.tuples drop cascades to foreign table clickhouse_except.types2 @@ -533,6 +590,7 @@ drop cascades to foreign table clickhouse.custom_option drop cascades to server loopback_bin drop cascades to foreign table clickhouse_bin.arrays drop cascades to foreign table clickhouse_bin.ints +drop cascades to foreign table clickhouse_bin.ip drop cascades to foreign table clickhouse_bin.timezones drop cascades to foreign table clickhouse_bin.tuples drop cascades to foreign table clickhouse_bin.types diff --git a/tests/sql/import_schema.sql b/tests/sql/import_schema.sql index 244c19d..a833b12 100644 --- a/tests/sql/import_schema.sql +++ b/tests/sql/import_schema.sql @@ -57,6 +57,18 @@ SELECT clickhousedb_raw_query('INSERT INTO regression.types2 SELECT format(''cardinal {0}'', toString(number + 1)) FROM numbers(10);'); +SELECT clickhousedb_raw_query('CREATE TABLE regression.ip ( + c1 IPv4, + c2 IPv6 +) ENGINE = MergeTree PARTITION BY c1 ORDER BY (c1); +'); +SELECT clickhousedb_raw_query($$ + INSERT INTO regression.ip VALUES + ('116.106.34.242', '2001:44c8:129:2632:33:0:252:2'), + ('116.106.34.243', '2a02:e980:1e::1'), + ('116.106.34.244', '::1'); +$$); + -- array types SELECT clickhousedb_raw_query('CREATE TABLE regression.arrays ( c1 Array(Int), c2 Array(String) @@ -111,6 +123,7 @@ IMPORT FOREIGN SCHEMA "regression" FROM SERVER loopback INTO clickhouse; \d+ clickhouse.arrays; \d+ clickhouse.tuples; \d+ clickhouse.timezones; +\d+ clickhouse.ip; SELECT * FROM clickhouse.ints ORDER BY c1 DESC LIMIT 4; SELECT * FROM clickhouse.types ORDER BY c1 LIMIT 2; @@ -118,6 +131,7 @@ SELECT * FROM clickhouse.types2 ORDER BY c1 LIMIT 2; SELECT * FROM clickhouse.arrays ORDER BY c1 LIMIT 2; SELECT * FROM clickhouse.tuples ORDER BY c1 LIMIT 2; SELECT * FROM clickhouse.timezones ORDER BY t1 LIMIT 2; +SELECT * FROM clickhouse.ip ORDER BY c1; IMPORT FOREIGN SCHEMA "regression" FROM SERVER loopback_bin INTO clickhouse_bin; @@ -127,6 +141,7 @@ IMPORT FOREIGN SCHEMA "regression" FROM SERVER loopback_bin INTO clickhouse_bin; \d+ clickhouse_bin.arrays; \d+ clickhouse_bin.tuples; \d+ clickhouse_bin.timezones; +\d+ clickhouse_bin.ip; SELECT * FROM clickhouse_bin.ints ORDER BY c1 DESC LIMIT 4; SELECT * FROM clickhouse_bin.types ORDER BY c1 LIMIT 2; @@ -134,6 +149,7 @@ SELECT * FROM clickhouse_bin.types2 ORDER BY c1 LIMIT 2; SELECT * FROM clickhouse_bin.arrays ORDER BY c1 LIMIT 2; SELECT * FROM clickhouse_bin.tuples ORDER BY c1 LIMIT 2; SELECT * FROM clickhouse_bin.timezones ORDER BY t1 LIMIT 2; +SELECT * FROM clickhouse.ip ORDER BY c1; IMPORT FOREIGN SCHEMA "regression" LIMIT TO (ints, types) FROM SERVER loopback INTO clickhouse_limit;