20
20
21
21
#include < clickhouse/base/socket.h> // for ipv4-ipv6 platform-specific stuff
22
22
23
- bool operator ==(const in_addr & left, const in_addr & right)
24
- {
23
+ // only compare PODs of equal size this way
24
+ template <typename L, typename R, typename
25
+ = std::enable_if_t <sizeof (L) == sizeof (R) && std::conjunction_v<std::is_pod<L>, std::is_pod<R>>>>
26
+ bool operator ==(const L & left, const R& right) {
25
27
return memcmp (&left, &right, sizeof (left)) == 0 ;
26
28
}
27
29
28
- bool operator ==(const in6_addr & left, const in6_addr & right)
29
- {
30
- return memcmp (&left, &right, sizeof (left)) == 0 ;
30
+ bool operator ==(const in6_addr & left, const std::string_view & right) {
31
+ return right.size () == sizeof (left) && memcmp (&left, right.data (), sizeof (left)) == 0 ;
31
32
}
32
33
33
- in_addr make_IPv4 (uint32_t ip)
34
- {
34
+ bool operator ==(const std::string_view & left, const in6_addr & right) {
35
+ return left.size () == sizeof (right) && memcmp (left.data (), &right, sizeof (right)) == 0 ;
36
+ }
37
+
38
+ namespace {
39
+
40
+ using namespace clickhouse ;
41
+ using namespace std ::literals::string_view_literals;
42
+
43
+ in_addr MakeIPv4 (uint32_t ip) {
35
44
static_assert (sizeof (in_addr) == sizeof (ip));
36
45
in_addr result;
37
46
memcpy (&result, &ip, sizeof (ip));
38
47
39
48
return result;
40
49
}
41
50
42
- std::ostream& operator <<(std::ostream& ostr, const in6_addr & addr)
43
- {
44
- char buf[INET6_ADDRSTRLEN];
45
- const char * ip_str = inet_ntop (AF_INET6, &addr, buf, INET6_ADDRSTRLEN);
46
-
47
- if (!ip_str)
48
- return ostr << " <!INVALID IPv6 VALUE!>" ;
49
-
50
- return ostr << ip_str;
51
+ in6_addr MakeIPv6 (uint8_t v0, uint8_t v1, uint8_t v2, uint8_t v3,
52
+ uint8_t v4, uint8_t v5, uint8_t v6, uint8_t v7,
53
+ uint8_t v8, uint8_t v9, uint8_t v10, uint8_t v11,
54
+ uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15) {
55
+ return in6_addr{{{v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15}}};
51
56
}
52
57
53
- namespace {
54
-
55
- using namespace clickhouse ;
56
- using namespace std ::literals::string_view_literals;
58
+ in6_addr MakeIPv6 (uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15) {
59
+ return in6_addr{{{0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , v10, v11, v12, v13, v14, v15}}};
60
+ }
57
61
58
62
static std::vector<uint32_t > MakeNumbers () {
59
63
return std::vector<uint32_t >
@@ -91,7 +95,7 @@ static const auto LOWCARDINALITY_STRING_FOOBAR_10_ITEMS_BINARY =
91
95
92
96
template <typename Generator>
93
97
auto GenerateVector (size_t items, Generator && gen) {
94
- std::vector<std:: result_of_t <Generator (size_t )>> result;
98
+ std::vector<my_result_of_t <Generator (size_t )>> result;
95
99
result.reserve (items);
96
100
for (size_t i = 0 ; i < items; ++i) {
97
101
result.push_back (std::move (gen (i)));
@@ -130,8 +134,7 @@ auto AlternateGenerators(Generator1 && gen1, Generator2 && gen2) {
130
134
}
131
135
132
136
template <typename T>
133
- std::vector<T> ConcatSequences (std::vector<T> && vec1, std::vector<T> && vec2)
134
- {
137
+ std::vector<T> ConcatSequences (std::vector<T> && vec1, std::vector<T> && vec2) {
135
138
std::vector<T> result (vec1);
136
139
137
140
result.reserve (vec1.size () + vec2.size ());
@@ -548,14 +551,14 @@ TEST(ColumnsCase, ColumnIPv4)
548
551
col.Append (" 127.0.0.1" );
549
552
col.Append (3585395774 );
550
553
col.Append (0 );
551
- const in_addr ip = make_IPv4 (0x12345678 );
554
+ const in_addr ip = MakeIPv4 (0x12345678 );
552
555
col.Append (ip);
553
556
554
557
ASSERT_EQ (5u , col.Size ());
555
- EXPECT_EQ (make_IPv4 (0xffffffff ), col.At (0 ));
556
- EXPECT_EQ (make_IPv4 (0x0100007f ), col.At (1 ));
557
- EXPECT_EQ (make_IPv4 (3585395774 ), col.At (2 ));
558
- EXPECT_EQ (make_IPv4 (0 ), col.At (3 ));
558
+ EXPECT_EQ (MakeIPv4 (0xffffffff ), col.At (0 ));
559
+ EXPECT_EQ (MakeIPv4 (0x0100007f ), col.At (1 ));
560
+ EXPECT_EQ (MakeIPv4 (3585395774 ), col.At (2 ));
561
+ EXPECT_EQ (MakeIPv4 (0 ), col.At (3 ));
559
562
EXPECT_EQ (ip, col.At (4 ));
560
563
561
564
EXPECT_EQ (" 255.255.255.255" , col.AsString (0 ));
@@ -568,6 +571,63 @@ TEST(ColumnsCase, ColumnIPv4)
568
571
EXPECT_EQ (0u , col.Size ());
569
572
}
570
573
574
+ TEST (ColumnsCase, ColumnIPv4_construct_from_data)
575
+ {
576
+ const auto vals = {
577
+ MakeIPv4 (0x12345678 ),
578
+ MakeIPv4 (0x0 ),
579
+ MakeIPv4 (0x0100007f )
580
+ };
581
+
582
+ {
583
+ // Column is usable after being initialized with empty data column
584
+ auto col = ColumnIPv4 (std::make_shared<ColumnUInt32>());
585
+ EXPECT_EQ (0u , col.Size ());
586
+
587
+ // Make sure that `Append` and `At`/`[]` work properly
588
+ size_t i = 0 ;
589
+ for (const auto & v : vals) {
590
+ col.Append (v);
591
+ EXPECT_EQ (v, col[col.Size () - 1 ]) << " At pos " << i;
592
+ EXPECT_EQ (v, col.At (col.Size () - 1 )) << " At pos " << i;
593
+ ++i;
594
+ }
595
+
596
+ EXPECT_EQ (vals.size (), col.Size ());
597
+ }
598
+
599
+ {
600
+ // Column reports values from data column exactly, and also can be modified afterwards.
601
+ const auto values = std::vector<uint32_t >{std::numeric_limits<uint32_t >::min (), 123 , 456 , 789101112 , std::numeric_limits<uint32_t >::max ()};
602
+ auto col = ColumnIPv4 (std::make_shared<ColumnUInt32>(values));
603
+
604
+ EXPECT_EQ (values.size (), col.Size ());
605
+ for (size_t i = 0 ; i < values.size (); ++i) {
606
+ EXPECT_EQ (ntohl (values[i]), col[i]) << " At pos: " << i;
607
+ }
608
+
609
+ // Make sure that `Append` and `At`/`[]` work properly
610
+ size_t i = 0 ;
611
+ for (const auto & v : vals) {
612
+ col.Append (v);
613
+ EXPECT_EQ (v, col[col.Size () - 1 ]) << " At pos " << i;
614
+ EXPECT_EQ (v, col.At (col.Size () - 1 )) << " At pos " << i;
615
+ ++i;
616
+ }
617
+
618
+ EXPECT_EQ (values.size () + vals.size (), col.Size ());
619
+ }
620
+
621
+ EXPECT_ANY_THROW (ColumnIPv4 (nullptr ));
622
+ EXPECT_ANY_THROW (ColumnIPv4 (ColumnRef (std::make_shared<ColumnInt8>())));
623
+ EXPECT_ANY_THROW (ColumnIPv4 (ColumnRef (std::make_shared<ColumnInt32>())));
624
+
625
+ EXPECT_ANY_THROW (ColumnIPv4 (ColumnRef (std::make_shared<ColumnUInt8>())));
626
+
627
+ EXPECT_ANY_THROW (ColumnIPv4 (ColumnRef (std::make_shared<ColumnInt128>())));
628
+ EXPECT_ANY_THROW (ColumnIPv4 (ColumnRef (std::make_shared<ColumnString>())));
629
+ }
630
+
571
631
TEST (ColumnsCase, ColumnIPv6)
572
632
{
573
633
// TODO: split into proper method-level unit-tests
@@ -576,22 +636,16 @@ TEST(ColumnsCase, ColumnIPv6)
576
636
col.Append (" ::" );
577
637
col.Append (" ::FFFF:204.152.189.116" );
578
638
579
- const auto ipv6 = in6_addr{{{ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 }}} ;
639
+ const auto ipv6 = MakeIPv6 ( 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 ) ;
580
640
col.Append (ipv6);
581
641
582
642
ASSERT_EQ (4u , col.Size ());
583
- const auto first_val = in6_addr{{{0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 }}};
584
- EXPECT_EQ (first_val, col.At (0 ));
585
-
586
- const auto second_val = in6_addr{{{0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }}};
587
- EXPECT_EQ (second_val, col.At (1 ));
588
-
589
- const auto third_val = in6_addr{{{0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0xff , 0xff , 204 , 152 , 189 , 116 }}};
590
- EXPECT_EQ (third_val, col.At (2 ));
643
+ EXPECT_EQ (MakeIPv6 (0 , 0 , 0 , 0 , 0 , 1 ), col.At (0 ));
644
+ EXPECT_EQ (MakeIPv6 (0 , 0 , 0 , 0 , 0 , 0 ), col.At (1 ));
645
+ EXPECT_EQ (MakeIPv6 (0xff , 0xff , 204 , 152 , 189 , 116 ), col.At (2 ));
591
646
592
647
EXPECT_EQ (ipv6, col.At (3 ));
593
648
594
-
595
649
EXPECT_EQ (" ::1" , col.AsString (0 ));
596
650
EXPECT_EQ (" ::" , col.AsString (1 ));
597
651
EXPECT_EQ (" ::ffff:204.152.189.116" , col.AsString (2 ));
@@ -601,6 +655,70 @@ TEST(ColumnsCase, ColumnIPv6)
601
655
EXPECT_EQ (0u , col.Size ());
602
656
}
603
657
658
+ TEST (ColumnsCase, ColumnIPv6_construct_from_data)
659
+ {
660
+ const auto vals = {
661
+ MakeIPv6 (0xff , 0xff , 204 , 152 , 189 , 116 ),
662
+ MakeIPv6 (0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 ),
663
+ };
664
+
665
+ {
666
+ // Column is usable after being initialized with empty data column
667
+ auto col = ColumnIPv6 (std::make_shared<ColumnFixedString>(16 ));
668
+ EXPECT_EQ (0u , col.Size ());
669
+
670
+ // Make sure that `Append` and `At`/`[]` work properly
671
+ size_t i = 0 ;
672
+ for (const auto & v : vals) {
673
+ col.Append (v);
674
+ EXPECT_EQ (v, col[col.Size () - 1 ]) << " At pos " << i;
675
+ EXPECT_EQ (v, col.At (col.Size () - 1 )) << " At pos " << i;
676
+ ++i;
677
+ }
678
+
679
+ EXPECT_EQ (vals.size (), col.Size ());
680
+ }
681
+
682
+ {
683
+ // Column reports values from data column exactly, and also can be modified afterwards.
684
+ using namespace std ::literals;
685
+ const auto values = std::vector<std::string_view>{
686
+ " \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F " sv,
687
+ " \x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F " sv,
688
+ " \xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF " sv};
689
+ auto col = ColumnIPv6 (std::make_shared<ColumnFixedString>(16 , values));
690
+
691
+ EXPECT_EQ (values.size (), col.Size ());
692
+ for (size_t i = 0 ; i < values.size (); ++i) {
693
+ EXPECT_EQ (values[i], col[i]) << " At pos: " << i;
694
+ }
695
+
696
+ // Make sure that `Append` and `At`/`[]` work properly
697
+ size_t i = 0 ;
698
+ for (const auto & v : vals) {
699
+ col.Append (v);
700
+ EXPECT_EQ (v, col[col.Size () - 1 ]) << " At pos " << i;
701
+ EXPECT_EQ (v, col.At (col.Size () - 1 )) << " At pos " << i;
702
+ ++i;
703
+ }
704
+
705
+ EXPECT_EQ (values.size () + vals.size (), col.Size ());
706
+ }
707
+
708
+ // Make sure that column can't be constructed with wrong data columns (wrong size/wrong type or null)
709
+ EXPECT_ANY_THROW (ColumnIPv4 (nullptr ));
710
+ EXPECT_ANY_THROW (ColumnIPv6 (ColumnRef (std::make_shared<ColumnFixedString>(15 ))));
711
+ EXPECT_ANY_THROW (ColumnIPv6 (ColumnRef (std::make_shared<ColumnFixedString>(17 ))));
712
+
713
+ EXPECT_ANY_THROW (ColumnIPv6 (ColumnRef (std::make_shared<ColumnInt8>())));
714
+ EXPECT_ANY_THROW (ColumnIPv6 (ColumnRef (std::make_shared<ColumnInt32>())));
715
+
716
+ EXPECT_ANY_THROW (ColumnIPv6 (ColumnRef (std::make_shared<ColumnUInt8>())));
717
+
718
+ EXPECT_ANY_THROW (ColumnIPv6 (ColumnRef (std::make_shared<ColumnInt128>())));
719
+ EXPECT_ANY_THROW (ColumnIPv6 (ColumnRef (std::make_shared<ColumnString>())));
720
+ }
721
+
604
722
TEST (ColumnsCase, ColumnDecimal128_from_string) {
605
723
auto col = std::make_shared<ColumnDecimal>(38 , 0 );
606
724
0 commit comments