File Coverage

blib/lib/EV/ClickHouse.pm
Criterion Covered Total %
statement 14 89 15.7
branch 0 70 0.0
condition 0 74 0.0
subroutine 5 8 62.5
pod 1 1 100.0
total 20 242 8.2


line stmt bran cond sub pod time code
1             package EV::ClickHouse;
2 24     24   2768395 use strict;
  24         41  
  24         826  
3 24     24   214 use warnings;
  24         38  
  24         1299  
4              
5 24     24   899 use EV;
  24         3420  
  24         956  
6              
7             BEGIN {
8 24     24   78 our $VERSION = '0.02';
9 24     24   118 use XSLoader;
  24         59  
  24         698  
10 24         123692 XSLoader::load __PACKAGE__, $VERSION;
11             }
12              
13             *q = \&query;
14             *reconnect = \&reset;
15             *disconnect = \&finish;
16              
17 0     0     sub _uri_unescape { my $s = $_[0]; $s =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/ge; $s }
  0            
  0            
  0            
18              
19             sub new {
20 0     0 1   my ($class, %args) = @_;
21              
22             # Connection URI: clickhouse://user:pass@host:port/database
23             # host accepts a bracketed IPv6 literal (e.g. clickhouse://[::1]:9000/db)
24 0 0         if (my $uri = delete $args{uri}) {
25 0 0         if ($uri =~ m{^clickhouse(?:\+(\w+))?://(?:([^:@]*?)(?::([^@]*))?\@)?(\[[^\]]+\]|[^/:?]+)(?::(\d+))?(?:/([^?]*))?(?:\?(.*))?$}) {
26 0           my ($proto, $u, $pw, $h, $p, $db, $qs) = ($1, $2, $3, $4, $5, $6, $7);
27 0           $h =~ s/^\[(.*)\]$/$1/;
28 0 0 0       $args{protocol} //= $proto if $proto;
29 0 0 0       $args{user} //= _uri_unescape($u) if defined $u && $u ne '';
      0        
30 0 0 0       $args{password} //= _uri_unescape($pw) if defined $pw;
31 0   0       $args{host} //= $h;
32 0 0 0       $args{port} //= $p if defined $p;
33 0 0 0       $args{database} //= _uri_unescape($db) if defined $db && $db ne '';
      0        
34 0 0         if (defined $qs) {
35 0           for my $pair (split /&/, $qs) {
36 0           my ($k, $v) = split /=/, $pair, 2;
37 0 0 0       $args{$k} //= _uri_unescape($v) if defined $k && defined $v;
      0        
38             }
39             }
40             } else {
41 0           die "EV::ClickHouse: invalid URI '$uri'\n";
42             }
43             }
44              
45 0   0       my $loop = delete $args{loop} || EV::default_loop;
46 0           my $self = $class->_new($loop);
47              
48 0 0   0     $self->on_error(exists $args{on_error} ? delete $args{on_error} : sub { die @_ });
  0            
49 0 0         $self->on_connect(delete $args{on_connect}) if exists $args{on_connect};
50 0 0         $self->on_progress(delete $args{on_progress}) if exists $args{on_progress};
51 0 0         $self->on_disconnect(delete $args{on_disconnect}) if exists $args{on_disconnect};
52 0 0         $self->on_trace(delete $args{on_trace}) if exists $args{on_trace};
53              
54 0   0       my $host = delete $args{host} // '127.0.0.1';
55 0           my $port = delete $args{port};
56 0   0       my $protocol = delete $args{protocol} // 'http';
57 0   0       my $user = delete $args{user} // 'default';
58 0   0       my $password = delete $args{password} // '';
59 0           my $db_alias = delete $args{db};
60 0   0       my $database = delete $args{database} // $db_alias // 'default';
      0        
61 0   0       my $tls = delete $args{tls} // 0;
62 0           my $tls_ca_file = delete $args{tls_ca_file};
63 0   0       my $tls_skip_verify = delete $args{tls_skip_verify} // 0;
64              
65             # options
66 0   0       my $compress = delete $args{compress} // 0;
67 0           my $session_id = delete $args{session_id};
68 0           my $connect_timeout = delete $args{connect_timeout};
69 0           my $query_timeout = delete $args{query_timeout};
70 0   0       my $auto_reconnect = delete $args{auto_reconnect} // 0;
71 0   0       my $keepalive = delete $args{keepalive} // 0;
72 0   0       my $reconnect_delay = delete $args{reconnect_delay} // 0;
73 0   0       my $reconnect_max_delay = delete $args{reconnect_max_delay} // 0;
74              
75             # decode options (native protocol)
76 0   0       my $decode_datetime = delete $args{decode_datetime} // 0;
77 0   0       my $decode_decimal = delete $args{decode_decimal} // 0;
78 0   0       my $decode_enum = delete $args{decode_enum} // 0;
79 0   0       my $named_rows = delete $args{named_rows} // 0;
80              
81 0 0 0       die "EV::ClickHouse: unknown protocol '$protocol' (expected 'http' or 'native')\n"
82             unless $protocol eq 'http' || $protocol eq 'native';
83              
84 0 0 0       $port //= ($protocol eq 'native') ? 9000 : 8123;
85              
86 0 0         $self->_set_protocol($protocol eq 'native' ? 1 : 0);
87 0 0         $self->_set_compress($compress) if $compress;
88 0 0         $self->_set_session_id($session_id) if defined $session_id;
89 0 0         $self->_set_connect_timeout($connect_timeout) if $connect_timeout;
90 0 0         $self->_set_query_timeout($query_timeout) if $query_timeout;
91 0 0         $self->_set_tls($tls) if $tls;
92 0 0         $self->_set_tls_ca_file($tls_ca_file) if defined $tls_ca_file;
93 0 0         $self->_set_tls_skip_verify($tls_skip_verify) if $tls_skip_verify;
94 0 0         $self->_set_auto_reconnect($auto_reconnect) if $auto_reconnect;
95 0 0         $self->_set_keepalive($keepalive) if $keepalive;
96 0 0         $self->_set_reconnect_delay($reconnect_delay) if $reconnect_delay;
97 0 0         $self->_set_reconnect_max_delay($reconnect_max_delay) if $reconnect_max_delay;
98              
99             # compute decode_flags bitmask
100 0           my $decode_flags = 0;
101 0 0         $decode_flags |= 1 if $decode_datetime; # DECODE_DT_STR
102 0 0         $decode_flags |= 2 if $decode_decimal; # DECODE_DEC_SCALE
103 0 0         $decode_flags |= 4 if $decode_enum; # DECODE_ENUM_STR
104 0 0         $decode_flags |= 8 if $named_rows; # DECODE_NAMED_ROWS
105 0 0         $self->_set_decode_flags($decode_flags) if $decode_flags;
106              
107 0           my $settings = delete $args{settings};
108 0 0         $self->_set_settings($settings) if $settings;
109              
110 0 0         warn "EV::ClickHouse->new: unknown parameter(s): " . join(', ', sort keys %args) . "\n"
111             if %args;
112              
113 0           $self->connect($host, $port, $user, $password, $database);
114              
115 0           $self;
116             }
117              
118             1;
119              
120             __END__