Current section
Files
Jump to
Current section
Files
native/clickhouse-cpp/tests/simple/main.cpp
#include <clickhouse/client.h>
#include <clickhouse/error_codes.h>
#include <clickhouse/types/type_parser.h>
#include <clickhouse/base/socket.h>
#include <ut/utils.h>
#include <stdexcept>
#include <iostream>
#include <cmath>
#include <thread>
#include <iostream>
#if defined(_MSC_VER)
# pragma warning(disable : 4996)
#endif
using namespace clickhouse;
using namespace std;
inline void PrintBlock(const Block& block) {
for (Block::Iterator bi(block); bi.IsValid(); bi.Next()) {
std::cout << bi.Name() << " ";
}
std::cout << std::endl << block;
}
inline void ArrayExample(Client& client) {
Block b;
/// Create a table.
client.Execute("CREATE TEMPORARY TABLE IF NOT EXISTS test_array (arr Array(UInt64))");
auto arr = std::make_shared<ColumnArray>(std::make_shared<ColumnUInt64>());
auto id = std::make_shared<ColumnUInt64>();
id->Append(1);
arr->AppendAsColumn(id);
id->Append(3);
arr->AppendAsColumn(id);
id->Append(7);
arr->AppendAsColumn(id);
id->Append(9);
arr->AppendAsColumn(id);
b.AppendColumn("arr", arr);
client.Insert("test_array", b);
client.Select("SELECT arr FROM test_array", [](const Block& block)
{
for (size_t c = 0; c < block.GetRowCount(); ++c) {
auto col = block[0]->As<ColumnArray>()->GetAsColumn(c);
for (size_t i = 0; i < col->Size(); ++i) {
std::cerr << (int)(*col->As<ColumnUInt64>())[i] << " ";
}
std::cerr << std::endl;
}
}
);
/// Delete table.
client.Execute("DROP TEMPORARY TABLE test_array");
}
inline void MultiArrayExample(Client& client) {
Block b;
/// Create a table.
client.Execute("CREATE TEMPORARY TABLE IF NOT EXISTS test_multiarray (arr Array(Array(UInt64)))");
auto arr = std::make_shared<ColumnArray>(std::make_shared<ColumnUInt64>());
auto id = std::make_shared<ColumnUInt64>();
id->Append(17);
arr->AppendAsColumn(id);
auto a2 = std::make_shared<ColumnArray>(std::make_shared<ColumnArray>(std::make_shared<ColumnUInt64>()));
a2->AppendAsColumn(arr);
b.AppendColumn("arr", a2);
client.Insert("test_multiarray", b);
client.Select("SELECT arr FROM test_multiarray", [](const Block& block)
{
for (size_t c = 0; c < block.GetRowCount(); ++c) {
auto col = block[0]->As<ColumnArray>()->GetAsColumn(c);
cout << "[";
for (size_t i = 0; i < col->Size(); ++i) {
auto col2 = col->As<ColumnArray>()->GetAsColumn(i);
for (size_t j = 0; j < col2->Size(); ++j) {
cout << (int)(*col2->As<ColumnUInt64>())[j];
if (j + 1 != col2->Size()) {
cout << " ";
}
}
}
std::cout << "]" << std::endl;
}
}
);
/// Delete table.
client.Execute("DROP TEMPORARY TABLE test_multiarray");
}
inline void DateExample(Client& client) {
Block b;
/// Create a table.
client.Execute("CREATE TEMPORARY TABLE IF NOT EXISTS test_date (d DateTime, dz DateTime('Europe/Moscow'))");
auto d = std::make_shared<ColumnDateTime>();
auto dz = std::make_shared<ColumnDateTime>();
d->Append(std::time(nullptr));
dz->Append(std::time(nullptr));
b.AppendColumn("d", d);
b.AppendColumn("dz", dz);
client.Insert("test_date", b);
client.Select("SELECT d, dz FROM test_date", [](const Block& block)
{
for (size_t c = 0; c < block.GetRowCount(); ++c) {
auto print_value = [&](const auto& col) {
std::time_t t = col->At(c);
std::cerr << std::asctime(std::localtime(&t));
std::cerr << col->Timezone() << std::endl;
};
print_value(block[0]->As<ColumnDateTime>());
print_value(block[1]->As<ColumnDateTime>());
}
}
);
/// Delete table.
client.Execute("DROP TEMPORARY TABLE test_date");
}
inline void DateTime64Example(Client& client) {
Block b;
/// Create a table.
client.Execute("CREATE TEMPORARY TABLE IF NOT EXISTS test_datetime64 (dt64 DateTime64(6))");
auto d = std::make_shared<ColumnDateTime64>(6);
d->Append(std::time(nullptr) * 1000000 + 123456);
b.AppendColumn("dt64", d);
client.Insert("test_datetime64", b);
client.Select("SELECT dt64 FROM test_datetime64", [](const Block& block)
{
for (size_t c = 0; c < block.GetRowCount(); ++c) {
auto col = block[0]->As<ColumnDateTime64>();
uint64_t t = col->As<ColumnDateTime64>()->At(c);
std::time_t ct = t / 1000000;
uint64_t us = t % 1000000;
std::cerr << "ctime: " << std::asctime(std::localtime(&ct));
std::cerr << "us: " << us << std::endl;
}
}
);
/// Delete table.
client.Execute("DROP TEMPORARY TABLE test_datetime64");
}
inline void DecimalExample(Client& client) {
Block b;
/// Create a table.
client.Execute("CREATE TEMPORARY TABLE IF NOT EXISTS test_decimal (d Decimal64(4))");
auto d = std::make_shared<ColumnDecimal>(18, 4);
d->Append(21111);
b.AppendColumn("d", d);
client.Insert("test_decimal", b);
client.Select("SELECT d FROM test_decimal", [](const Block& block)
{
for (size_t c = 0; c < block.GetRowCount(); ++c) {
auto col = block[0]->As<ColumnDecimal>();
cout << (int)col->At(c) << endl;
}
}
);
client.Select("SELECT toDecimal32(2, 4) AS x", [](const Block& block)
{
for (size_t c = 0; c < block.GetRowCount(); ++c) {
auto col = block[0]->As<ColumnDecimal>();
cout << (int)col->At(c) << endl;
}
}
);
/// Delete table.
client.Execute("DROP TEMPORARY TABLE test_decimal");
}
inline void GenericExample(Client& client) {
/// Create a table.
client.Execute("CREATE TEMPORARY TABLE IF NOT EXISTS test_client (id UInt64, name String)");
/// Insert some values.
{
Block block;
auto id = std::make_shared<ColumnUInt64>();
id->Append(1);
id->Append(7);
auto name = std::make_shared<ColumnString>();
name->Append("one");
name->Append("seven");
block.AppendColumn("id" , id);
block.AppendColumn("name", name);
client.Insert("test_client", block);
}
/// Select values inserted in the previous step.
client.Select("SELECT id, name FROM test_client", [](const Block& block)
{
std::cout << PrettyPrintBlock{block} << std::endl;
}
);
/// Delete table.
client.Execute("DROP TEMPORARY TABLE test_client");
}
inline void ParamExample(Client& client) {
/// Create a table.
client.Execute("CREATE TEMPORARY TABLE IF NOT EXISTS test_client (id UInt64, name String)");
{
Query query("insert into test_client values ({id: UInt64}, {name: String})");
query.SetParam("id", "1").SetParam("name", "NAME");
client.Execute(query);
query.SetParam("id", "123").SetParam("name", "FromParam");
client.Execute(query);
const char FirstPrintable = ' ';
char test_str1[FirstPrintable * 2 + 1];
for (unsigned int i = 0; i < FirstPrintable; i++) {
test_str1[i * 2] = 'A';
test_str1[i * 2 + 1] = i;
}
test_str1[int(FirstPrintable * 2)] = 'A';
query.SetParam("id", "333").SetParam("name", std::string(test_str1, FirstPrintable * 2 + 1));
client.Execute(query);
const char LastPrintable = 127;
unsigned char big_string[LastPrintable - FirstPrintable];
for (unsigned int i = 0; i < sizeof(big_string); i++) big_string[i] = i + FirstPrintable;
query.SetParam("id", "444").SetParam("name", std::string((char*)big_string, sizeof(big_string)));
client.Execute(query);
query.SetParam("id", "555")
.SetParam("name", "utf8Русский");
client.Execute(query);
}
/// Select values inserted in the previous step.
Query query ("SELECT id, name, length(name) FROM test_client where id > {a: Int32}");
query.SetParam("a", "4");
SelectCallback cb([](const Block& block)
{
std::cout << PrettyPrintBlock{block} << std::endl;
});
query.OnData(cb);
client.Select(query);
/// Delete table.
client.Execute("DROP TEMPORARY TABLE test_client");
}
inline void ParamNullExample(Client& client) {
client.Execute("CREATE TEMPORARY TABLE IF NOT EXISTS test_client (id UInt64, name Nullable(String))");
Query query("insert into test_client values ({id: UInt64}, {name: Nullable(String)})");
query.SetParam("id", "123").SetParam("name", QueryParamValue());
client.Execute(query);
query.SetParam("id", "456").SetParam("name", "String Value");
client.Execute(query);
client.Select("SELECT id, name FROM test_client", [](const Block& block) {
for (size_t c = 0; c < block.GetRowCount(); ++c) {
std::cerr << block[0]->As<ColumnUInt64>()->At(c) << " ";
auto col_string = block[1]->As<ColumnNullable>();
if (col_string->IsNull(c)) {
std::cerr << "\\N\n";
} else {
std::cerr << col_string->Nested()->As<ColumnString>()->At(c) << "\n";
}
}
});
client.Execute("DROP TEMPORARY TABLE test_client");
}
inline void NullableExample(Client& client) {
/// Create a table.
client.Execute("CREATE TEMPORARY TABLE IF NOT EXISTS test_client (id Nullable(UInt64), date Nullable(Date))");
/// Insert some values.
{
Block block;
{
auto id = std::make_shared<ColumnUInt64>();
id->Append(1);
id->Append(2);
auto nulls = std::make_shared<ColumnUInt8>();
nulls->Append(0);
nulls->Append(0);
block.AppendColumn("id", std::make_shared<ColumnNullable>(id, nulls));
}
{
auto date = std::make_shared<ColumnDate>();
date->Append(std::time(nullptr));
date->Append(std::time(nullptr));
auto nulls = std::make_shared<ColumnUInt8>();
nulls->Append(0);
nulls->Append(1);
block.AppendColumn("date", std::make_shared<ColumnNullable>(date, nulls));
}
client.Insert("test_client", block);
}
/// Select values inserted in the previous step.
client.Select("SELECT id, date FROM test_client", [](const Block& block)
{
for (size_t c = 0; c < block.GetRowCount(); ++c) {
auto col_id = block[0]->As<ColumnNullable>();
auto col_date = block[1]->As<ColumnNullable>();
if (col_id->IsNull(c)) {
std::cerr << "\\N ";
} else {
std::cerr << col_id->Nested()->As<ColumnUInt64>()->At(c)
<< " ";
}
if (col_date->IsNull(c)) {
std::cerr << "\\N\n";
} else {
std::time_t t = col_date->Nested()->As<ColumnDate>()->At(c);
std::cerr << std::asctime(std::localtime(&t))
<< "\n";
}
}
}
);
/// Delete table.
client.Execute("DROP TEMPORARY TABLE test_client");
}
inline void NumbersExample(Client& client) {
size_t num = 0;
client.Select("SELECT number, number FROM system.numbers LIMIT 100000", [&num](const Block& block)
{
if (Block::Iterator(block).IsValid()) {
auto col = block[0]->As<ColumnUInt64>();
for (size_t i = 0; i < col->Size(); ++i) {
if (col->At(i) < num) {
throw std::runtime_error("invalid sequence of numbers");
}
num = col->At(i);
}
}
}
);
}
inline void CancelableExample(Client& client) {
/// Create a table.
client.Execute("CREATE TEMPORARY TABLE IF NOT EXISTS test_client (x UInt64)");
/// Insert a few blocks.
for (unsigned j = 0; j < 10; j++) {
Block b;
auto x = std::make_shared<ColumnUInt64>();
for (uint64_t i = 0; i < 1000; i++) {
x->Append(i);
}
b.AppendColumn("x", x);
client.Insert("test_client", b);
}
/// Send a query which is canceled after receiving the first block (note:
/// due to the low number of rows in this test, this will not actually have
/// any effect, it just tests for errors)
client.SelectCancelable("SELECT * FROM test_client", [](const Block&)
{
return false;
}
);
/// Delete table.
client.Execute("DROP TEMPORARY TABLE test_client");
}
inline void ExecptionExample(Client& client) {
/// Create a table.
client.Execute("CREATE TEMPORARY TABLE IF NOT EXISTS test_exceptions (id UInt64, name String)");
/// Expect failing on table creation.
try {
client.Execute("CREATE TEMPORARY TABLE test_exceptions (id UInt64, name String)");
} catch (const ServerException& e) {
if (e.GetCode() == ErrorCodes::TABLE_ALREADY_EXISTS) {
// OK
} else {
throw;
}
}
/// Delete table.
client.Execute("DROP TEMPORARY TABLE test_exceptions");
}
inline void EnumExample(Client& client) {
/// Create a table.
client.Execute("CREATE TEMPORARY TABLE IF NOT EXISTS test_enums (id UInt64, e Enum8('One' = 1, 'Two' = 2))");
/// Insert some values.
{
Block block;
auto id = std::make_shared<ColumnUInt64>();
id->Append(1);
id->Append(2);
auto e = std::make_shared<ColumnEnum8>(Type::CreateEnum8({{"One", 1}, {"Two", 2}}));
e->Append(1);
e->Append("Two");
block.AppendColumn("id", id);
block.AppendColumn("e", e);
client.Insert("test_enums", block);
}
/// Select values inserted in the previous step.
client.Select("SELECT id, e FROM test_enums", [](const Block& block)
{
for (Block::Iterator bi(block); bi.IsValid(); bi.Next()) {
std::cout << bi.Name() << " ";
}
std::cout << std::endl;
for (size_t i = 0; i < block.GetRowCount(); ++i) {
std::cout << (*block[0]->As<ColumnUInt64>())[i] << " "
<< (*block[1]->As<ColumnEnum8>()).NameAt(i) << "\n";
}
}
);
/// Delete table.
client.Execute("DROP TEMPORARY TABLE test_enums");
}
inline void SelectNull(Client& client) {
client.Select("SELECT NULL", []([[maybe_unused]] const Block& block)
{
assert(block.GetRowCount() < 2);
(void)(block);
}
);
}
inline void ShowTables(Client& client) {
/// Select values inserted in the previous step.
client.Select("SHOW TABLES", [](const Block& block)
{
for (size_t i = 0; i < block.GetRowCount(); ++i) {
std::cout << (*block[0]->As<ColumnString>())[i] << "\n";
}
}
);
}
inline void IPExample(Client &client) {
/// Create a table.
client.Execute("CREATE TEMPORARY TABLE IF NOT EXISTS test_ips (id UInt64, v4 IPv4, v6 IPv6)");
/// Insert some values.
{
Block block;
auto id = std::make_shared<ColumnUInt64>();
id->Append(1);
id->Append(2);
id->Append(3);
auto v4 = std::make_shared<ColumnIPv4>();
v4->Append("127.0.0.1");
v4->Append(3585395774);
v4->Append(0);
auto v6 = std::make_shared<ColumnIPv6>();
v6->Append("::1");
v6->Append("aa::ff");
v6->Append("fe80::86ba:ef31:f2d8:7e8b");
block.AppendColumn("id", id);
block.AppendColumn("v4", v4);
block.AppendColumn("v6", v6);
client.Insert("test_ips", block);
}
/// Select values inserted in the previous step.
client.Select("SELECT id, v4, v6 FROM test_ips", [](const Block& block)
{
for (Block::Iterator bi(block); bi.IsValid(); bi.Next()) {
std::cout << bi.Name() << " ";
}
std::cout << std::endl;
for (size_t i = 0; i < block.GetRowCount(); ++i) {
std::cout << (*block[0]->As<ColumnUInt64>())[i] << " "
<< (*block[1]->As<ColumnIPv4>()).AsString(i) << " (" << (*block[1]->As<ColumnIPv4>())[i].s_addr << ") "
<< (*block[2]->As<ColumnIPv6>()).AsString(i) << "\n";
}
}
);
/// Delete table.
client.Execute("DROP TEMPORARY TABLE test_ips");
}
static void RunTests(Client& client) {
ParamExample(client);
ParamNullExample(client);
ArrayExample(client);
CancelableExample(client);
DateExample(client);
DateTime64Example(client);
DecimalExample(client);
EnumExample(client);
ExecptionExample(client);
GenericExample(client);
IPExample(client);
MultiArrayExample(client);
NullableExample(client);
NumbersExample(client);
SelectNull(client);
ShowTables(client);
}
int main() {
try {
const auto localHostEndpoint = ClientOptions()
.SetHost( getEnvOrDefault("CLICKHOUSE_HOST", "localhost"))
.SetPort( getEnvOrDefault<size_t>("CLICKHOUSE_PORT", "9000"))
.SetEndpoints({ {"asasdasd", 9000}
,{"localhost"}
,{"noalocalhost", 9000}
})
.SetUser( getEnvOrDefault("CLICKHOUSE_USER", "default"))
.SetPassword( getEnvOrDefault("CLICKHOUSE_PASSWORD", ""))
.SetDefaultDatabase(getEnvOrDefault("CLICKHOUSE_DB", "default"));
{
Client client(ClientOptions(localHostEndpoint)
.SetPingBeforeQuery(true));
RunTests(client);
std::cout << "current endpoint : " << client.GetCurrentEndpoint().value().host << "\n";
}
{
Client client(ClientOptions(localHostEndpoint)
.SetPingBeforeQuery(true)
.SetCompressionMethod(CompressionMethod::LZ4));
RunTests(client);
}
} catch (const std::exception& e) {
std::cerr << "exception : " << e.what() << std::endl;
}
return 0;
}