Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ CH_CPP_FLAGS = -D CMAKE_BUILD_TYPE=Release -D WITH_OPENSSL=ON

# Build static on Darwin by default.
ifndef ($(CH_BUILD))
ifeq ($(OS),Darwin)
# ifeq ($(OS),Darwin)
CH_BUILD = static
endif
# endif
endif

# Are we statically compiling clickhouse-cpp into the extension or no?
Expand Down
75 changes: 75 additions & 0 deletions src/binary.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <sstream>
#include <iostream>
#include <cassert>
#include <stdexcept>
Expand Down Expand Up @@ -250,6 +251,11 @@ static Oid get_corr_postgres_type(const TypeRef & type)
return FLOAT4OID;
case Type::Code::Float64:
return FLOAT8OID;
case Type::Code::Decimal128:
case Type::Code::Decimal64:
case Type::Code::Decimal32:
case Type::Code::Decimal:
return NUMERICOID;
case Type::Code::FixedString:
case Type::Code::Enum8:
case Type::Code::Enum16:
Expand Down Expand Up @@ -461,6 +467,26 @@ static void column_append(clickhouse::ColumnRef col, Datum val, Oid valtype, boo
}
break;
}
case NUMERICOID: {
// Convert numeric to string and let ColumnDecimal parse it.
char *s = DatumGetCString(DirectFunctionCall1(numeric_out, val));
switch (col->Type()->GetCode())
{
case Type::Code::Decimal128:
case Type::Code::Decimal64:
case Type::Code::Decimal32:
case Type::Code::Decimal:
col->As<ColumnDecimal>()->Append(std::string(s));
break;
default:
throw std::runtime_error(
"unexpected column "
"type for NUMERIC: "
+ col->Type()->GetName());
}
pfree(s);
break;
}
case TEXTOID: {
char * s = TextDatumGetCString(val);

Expand Down Expand Up @@ -745,6 +771,55 @@ static Datum make_datum(clickhouse::ColumnRef col, size_t row, Oid * valtype, bo
*valtype = FLOAT8OID;
}
break;
case Type::Code::Decimal128:
case Type::Code::Decimal64:
case Type::Code::Decimal32:
case Type::Code::Decimal:
{
auto decCol = col->As<ColumnDecimal>();
auto val = decCol->At(row);

// Convert the Int128 to a string.
std::stringstream ss;
ss << val;
std::string str = ss.str();

// Start a destination string.
std::stringstream res;
auto scale = decCol->GetScale();

// Output a dash for negative values
if (val < 0)
{
res << '-';
str.erase(0, 1);
}

if (str.length() <= scale)
{
// Append the entire value prepended with zeros after the decimal.
res << "0." << std::string(scale-1, '0') << str;
}
else
{
// There are digits before the decimal.
auto decAt = str.length() - scale;
res << str.substr(0, decAt);

// Append any digits after the decimal.
if (decAt < str.length())
{
res << '.' << str.substr(decAt);
}
}

ret = DirectFunctionCall3(numeric_in,
CStringGetDatum(res.str().c_str()),
ObjectIdGetDatum(0),
Int32GetDatum(-1));
*valtype = NUMERICOID;
}
break;
case Type::Code::FixedString: {
auto s = std::string(col->As<ColumnFixedString>()->At(row));
ret = CStringGetTextDatum(s.c_str());
Expand Down
9 changes: 3 additions & 6 deletions src/pglink.c
Original file line number Diff line number Diff line change
Expand Up @@ -377,12 +377,9 @@ extend_insert_query(ch_http_insert_state *state, TupleTableSlot *slot)
break;
case NUMERICOID:
{
Datum valueDatum;
float8 f;

valueDatum = DirectFunctionCall1(numeric_float8, value);
f = DatumGetFloat8(valueDatum);
appendStringInfo(&state->sql, "%f", f);
char *extval = DatumGetCString(DirectFunctionCall1(numeric_out, value));
appendStringInfoString(&state->sql, extval);
pfree(extval);
}
break;
case BPCHAROID:
Expand Down
104 changes: 104 additions & 0 deletions test/expected/decimal.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
SET datestyle = 'ISO';
CREATE SERVER binary_decimal_loopback FOREIGN DATA WRAPPER clickhouse_fdw OPTIONS(dbname 'decimal_test', driver 'binary');
CREATE SERVER http_decimal_loopback FOREIGN DATA WRAPPER clickhouse_fdw OPTIONS(dbname 'decimal_test', driver 'http');
CREATE USER MAPPING FOR CURRENT_USER SERVER binary_decimal_loopback;
CREATE USER MAPPING FOR CURRENT_USER SERVER http_decimal_loopback;
SELECT clickhouse_raw_query('DROP DATABASE IF EXISTS decimal_test');
clickhouse_raw_query
----------------------

(1 row)

SELECT clickhouse_raw_query('CREATE DATABASE decimal_test');
clickhouse_raw_query
----------------------

(1 row)

SELECT clickhouse_raw_query($$
CREATE TABLE decimal_test.decimals (
id Int32 NOT NULL,
dec Decimal(8, 0) NOT NULL,
dec32 Decimal32(4) NOT NULL,
dec64 Decimal64(6) NOT NULL,
dec128 Decimal128(8) NOT NULL
) ENGINE = MergeTree PARTITION BY id ORDER BY (id);
$$);
clickhouse_raw_query
----------------------

(1 row)

CREATE SCHEMA dec_bin;
CREATE SCHEMA dec_http;
IMPORT FOREIGN SCHEMA "decimal_test" FROM SERVER binary_decimal_loopback INTO dec_bin;
\d dec_bin.decimals
Foreign table "dec_bin.decimals"
Column | Type | Collation | Nullable | Default | FDW options
--------+---------------+-----------+----------+---------+-------------
id | integer | | not null | |
dec | numeric(8,0) | | not null | |
dec32 | numeric(9,4) | | not null | |
dec64 | numeric(18,6) | | not null | |
dec128 | numeric(38,8) | | not null | |
Server: binary_decimal_loopback
FDW options: (database 'decimal_test', table_name 'decimals', engine 'MergeTree')

IMPORT FOREIGN SCHEMA "decimal_test" FROM SERVER http_decimal_loopback INTO dec_http;
\d dec_http.decimals
Foreign table "dec_http.decimals"
Column | Type | Collation | Nullable | Default | FDW options
--------+---------------+-----------+----------+---------+-------------
id | integer | | not null | |
dec | numeric(8,0) | | not null | |
dec32 | numeric(9,4) | | not null | |
dec64 | numeric(18,6) | | not null | |
dec128 | numeric(38,8) | | not null | |
Server: http_decimal_loopback
FDW options: (database 'decimal_test', table_name 'decimals', engine 'MergeTree')

-- Fails pending https://github.com/ClickHouse/clickhouse-cpp/issues/422
INSERT INTO dec_bin.decimals (id, dec, dec32, dec64, dec128) VALUES
(1, 42::NUMERIC, 98.6::NUMERIC, 102.4::NUMERIC, 1024.003::NUMERIC),
(2, 9999, 9999.9999, 9999999.999999, 99999999999.99999999),
(3, -9999, -9999.9999, -9999999.999999, -99999999999.99999999)
;
INSERT INTO dec_http.decimals VALUES
(4, 1000000::NUMERIC, 10000::NUMERIC, 3000000000::NUMERIC, 400000000000::NUMERIC),
(5, -1, -0.0001, -0.000001, -0.00000001),
(6, 0, 0, 0, 0)
;
SELECT * FROM dec_bin.decimals ORDER BY id;
id | dec | dec32 | dec64 | dec128
----+---------+------------+-------------------+-----------------------
1 | 42 | 98.6000 | 102.400000 | 1024.00300000
2 | 9999 | 9999.9999 | 9999999.999999 | 99999999999.99999999
3 | -9999 | -9999.9999 | -9999999.999999 | -99999999999.99999999
4 | 1000000 | 10000.0000 | 3000000000.000000 | 400000000000.00000000
5 | -1 | -0.0001 | -0.000001 | -0.00000001
6 | 0 | 0.0000 | 0.000000 | 0.00000000
(6 rows)

SELECT * FROM dec_http.decimals ORDER BY id;
id | dec | dec32 | dec64 | dec128
----+---------+------------+-------------------+-----------------------
1 | 42 | 98.6000 | 102.400000 | 1024.00300000
2 | 9999 | 9999.9999 | 9999999.999999 | 99999999999.99999999
3 | -9999 | -9999.9999 | -9999999.999999 | -99999999999.99999999
4 | 1000000 | 10000.0000 | 3000000000.000000 | 400000000000.00000000
5 | -1 | -0.0001 | -0.000001 | -0.00000001
6 | 0 | 0.0000 | 0.000000 | 0.00000000
(6 rows)

SELECT clickhouse_raw_query('DROP DATABASE decimal_test');
clickhouse_raw_query
----------------------

(1 row)

DROP USER MAPPING FOR CURRENT_USER SERVER binary_decimal_loopback;
DROP USER MAPPING FOR CURRENT_USER SERVER http_decimal_loopback;
DROP SERVER binary_decimal_loopback CASCADE;
NOTICE: drop cascades to foreign table dec_bin.decimals
DROP SERVER http_decimal_loopback CASCADE;
NOTICE: drop cascades to foreign table dec_http.decimals
46 changes: 46 additions & 0 deletions test/sql/decimal.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
SET datestyle = 'ISO';
CREATE SERVER binary_decimal_loopback FOREIGN DATA WRAPPER clickhouse_fdw OPTIONS(dbname 'decimal_test', driver 'binary');
CREATE SERVER http_decimal_loopback FOREIGN DATA WRAPPER clickhouse_fdw OPTIONS(dbname 'decimal_test', driver 'http');
CREATE USER MAPPING FOR CURRENT_USER SERVER binary_decimal_loopback;
CREATE USER MAPPING FOR CURRENT_USER SERVER http_decimal_loopback;

SELECT clickhouse_raw_query('DROP DATABASE IF EXISTS decimal_test');
SELECT clickhouse_raw_query('CREATE DATABASE decimal_test');
SELECT clickhouse_raw_query($$
CREATE TABLE decimal_test.decimals (
id Int32 NOT NULL,
dec Decimal(8, 0) NOT NULL,
dec32 Decimal32(4) NOT NULL,
dec64 Decimal64(6) NOT NULL,
dec128 Decimal128(8) NOT NULL
) ENGINE = MergeTree PARTITION BY id ORDER BY (id);
$$);

CREATE SCHEMA dec_bin;
CREATE SCHEMA dec_http;
IMPORT FOREIGN SCHEMA "decimal_test" FROM SERVER binary_decimal_loopback INTO dec_bin;
\d dec_bin.decimals
IMPORT FOREIGN SCHEMA "decimal_test" FROM SERVER http_decimal_loopback INTO dec_http;
\d dec_http.decimals

-- Fails pending https://github.com/ClickHouse/clickhouse-cpp/issues/422
INSERT INTO dec_bin.decimals (id, dec, dec32, dec64, dec128) VALUES
(1, 42::NUMERIC, 98.6::NUMERIC, 102.4::NUMERIC, 1024.003::NUMERIC),
(2, 9999, 9999.9999, 9999999.999999, 99999999999.99999999),
(3, -9999, -9999.9999, -9999999.999999, -99999999999.99999999)
;

INSERT INTO dec_http.decimals VALUES
(4, 1000000::NUMERIC, 10000::NUMERIC, 3000000000::NUMERIC, 400000000000::NUMERIC),
(5, -1, -0.0001, -0.000001, -0.00000001),
(6, 0, 0, 0, 0)
;

SELECT * FROM dec_bin.decimals ORDER BY id;
SELECT * FROM dec_http.decimals ORDER BY id;

SELECT clickhouse_raw_query('DROP DATABASE decimal_test');
DROP USER MAPPING FOR CURRENT_USER SERVER binary_decimal_loopback;
DROP USER MAPPING FOR CURRENT_USER SERVER http_decimal_loopback;
DROP SERVER binary_decimal_loopback CASCADE;
DROP SERVER http_decimal_loopback CASCADE;
Loading