11#include < clickhouse/client.h>
22#include < contrib/gtest/gtest.h>
33
4+ #include < cmath>
5+
46using namespace clickhouse ;
57
6- namespace clickhouse
7- {
8- std::ostream & operator <<(std::ostream & ostr, const ServerInfo & server_info)
9- {
8+ namespace clickhouse {
9+ std::ostream & operator <<(std::ostream & ostr, const ServerInfo & server_info) {
1010 return ostr << server_info.name << " /" << server_info.display_name
1111 << " ver "
1212 << server_info.version_major << " ."
@@ -16,6 +16,33 @@ std::ostream & operator<<(std::ostream & ostr, const ServerInfo & server_info)
1616}
1717}
1818
19+ namespace {
20+
21+ uint64_t versionNumber (
22+ uint64_t version_major,
23+ uint64_t version_minor,
24+ uint64_t version_patch = 0 ,
25+ uint64_t revision = 0 ) {
26+
27+ // in this case version_major can be up to 1000
28+ static auto revision_decimal_places = 8 ;
29+ static auto patch_decimal_places = 4 ;
30+ static auto minor_decimal_places = 4 ;
31+
32+ auto const result = version_major * static_cast <uint64_t >(std::pow (10 , minor_decimal_places + patch_decimal_places + revision_decimal_places))
33+ + version_minor * static_cast <uint64_t >(std::pow (10 , patch_decimal_places + revision_decimal_places))
34+ + version_patch * static_cast <uint64_t >(std::pow (10 , revision_decimal_places))
35+ + revision;
36+
37+ return result;
38+ }
39+
40+ uint64_t versionNumber (const ServerInfo & server_info) {
41+ return versionNumber (server_info.version_major , server_info.version_minor , server_info.version_patch , server_info.revision );
42+ }
43+
44+ }
45+
1946// Use value-parameterized tests to run same tests with different client
2047// options.
2148class ClientCase : public testing ::TestWithParam<ClientOptions> {
@@ -356,7 +383,7 @@ TEST_P(ClientCase, Numbers) {
356383
357384TEST_P (ClientCase, SimpleAggregateFunction) {
358385 const auto & server_info = client_->GetServerInfo ();
359- if (server_info. version_major <= 19 && server_info. version_minor < 9 ) {
386+ if (versionNumber ( server_info) < versionNumber ( 19 , 9 ) ) {
360387 std::cout << " Test is skipped since server '" << server_info << " ' does not support SimpleAggregateFunction" << std::endl;
361388 return ;
362389 }
@@ -688,6 +715,71 @@ TEST_P(ClientCase, Decimal) {
688715 });
689716}
690717
718+ // Test roundtrip of DateTime64 values
719+ TEST_P (ClientCase, DateTime64) {
720+ const auto & server_info = client_->GetServerInfo ();
721+ if (versionNumber (server_info) < versionNumber (20 , 1 )) {
722+ std::cout << " Test is skipped since server '" << server_info << " ' does not support DateTime64" << std::endl;
723+ return ;
724+ }
725+
726+ Block block;
727+ client_->Execute (" DROP TABLE IF EXISTS test_clickhouse_cpp.datetime64;" );
728+
729+ client_->Execute (" CREATE TABLE IF NOT EXISTS "
730+ " test_clickhouse_cpp.datetime64 (dt DateTime64(6)) "
731+ " ENGINE = Memory" );
732+
733+ auto col_dt64 = std::make_shared<ColumnDateTime64>(6 );
734+ block.AppendColumn (" dt" , col_dt64);
735+
736+ // Empty INSERT and SELECT
737+ client_->Insert (" test_clickhouse_cpp.datetime64" , block);
738+ client_->Select (" SELECT dt FROM test_clickhouse_cpp.datetime64" ,
739+ [](const Block& block) {
740+ ASSERT_EQ (0U , block.GetRowCount ());
741+ }
742+ );
743+
744+ const std::vector<Int64> data{
745+ -1'234'567'890'123'456'7ll , // approx year 1578
746+ -1'234'567'890'123ll , // 1969-12-17T17:03:52.890123
747+ -1'234'567ll , // 1969-12-31T23:59:58.234567
748+ 0 , // epoch
749+ 1'234'567ll , // 1970-01-01T00:00:01.234567
750+ 1'234'567'890'123ll , // 1970-01-15T06:56:07.890123
751+ 1'234'567'890'123'456'7ll // 2361-03-21T19:15:01.234567
752+ };
753+ for (const auto & d : data) {
754+ col_dt64->Append (d);
755+ }
756+
757+ block.RefreshRowCount ();
758+
759+ // Non-empty INSERT and SELECT
760+ client_->Insert (" test_clickhouse_cpp.datetime64" , block);
761+
762+ size_t total_rows = 0 ;
763+ client_->Select (" SELECT dt FROM test_clickhouse_cpp.datetime64" ,
764+ [&total_rows, &data](const Block& block) {
765+ total_rows += block.GetRowCount ();
766+ if (block.GetRowCount () == 0 ) {
767+ return ;
768+ }
769+
770+ ASSERT_EQ (1U , block.GetColumnCount ());
771+ if (auto col = block[0 ]->As <ColumnDateTime64>()) {
772+ ASSERT_EQ (data.size (), col->Size ());
773+ for (size_t i = 0 ; i < col->Size (); ++i) {
774+ EXPECT_EQ (data[i], col->At (i)) << " at index: " << i;
775+ }
776+ }
777+ }
778+ );
779+
780+ ASSERT_EQ (total_rows, data.size ());
781+ }
782+
691783INSTANTIATE_TEST_CASE_P (
692784 Client, ClientCase,
693785 ::testing::Values (
0 commit comments