File Coverage

blib/lib/TablesRole/Source/DBI.pm
Criterion Covered Total %
statement 66 70 94.2
branch 11 24 45.8
condition 5 11 45.4
subroutine 11 11 100.0
pod 1 8 12.5
total 94 124 75.8


line stmt bran cond sub pod time code
1             package TablesRole::Source::DBI;
2              
3             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
4             our $DATE = '2020-06-01'; # DATE
5             our $DIST = 'TablesRoles-Standard'; # DIST
6             our $VERSION = '0.003'; # VERSION
7              
8 1     1   565 use 5.010001;
  1         4  
9 1     1   5 use Role::Tiny;
  1         2  
  1         6  
10 1     1   167 use Role::Tiny::With;
  1         2  
  1         902  
11             with 'TablesRole::Spec::Basic';
12              
13             sub new {
14 1     1 1 78460 my ($class, %args) = @_;
15              
16 1         6 my $dsn = delete $args{dsn};
17 1         3 my $user = delete $args{user};
18 1         3 my $password = delete $args{password};
19 1         5 my $dbh = delete $args{dbh};
20 1 50       22 if (defined $dbh) {
    0          
21             } elsif (defined $dsn) {
22 0         0 require DBI;
23 0         0 $dbh = DBI->connect($dsn, $user, $password, {RaiseError=>1});
24             }
25              
26 1         27 my $sth = delete $args{sth};
27 1         27 my $sth_bind_params = delete $args{sth_bind_params};
28 1         7 my $query = delete $args{query};
29 1         4 my $table = delete $args{table};
30 1 50       7 if (defined $sth) {
31             } else {
32 1 50       7 die "You specify 'query' or 'table', but you don't specify ".
33             "dbh/dsn+user+password, so I cannot create a statement handle"
34             unless $dbh;
35 1 50       7 if (defined $query) {
    50          
36             } elsif (defined $table) {
37 1         6 $query = "SELECT * FROM $table";
38             } else {
39 0         0 die "Please specify 'sth', 'query', or 'table' argument";
40             }
41 1         33 $sth = $dbh->prepare($query);
42 1   50     175 $sth->execute(@{ $sth_bind_params // [] }); # to check query syntax
  1         133  
43             }
44              
45 1         6 my $row_count_sth = delete $args{row_count_sth};
46 1         3 my $row_count_sth_bind_params = delete $args{row_count_sth_bind_params};
47 1         3 my $row_count_query = delete $args{row_count_query};
48 1 50       4 if (defined $row_count_sth) {
49             } else {
50 1 50       4 die "You specify 'row_count_query' or 'table', but you don't specify ".
51             "dbh/dsn+user+password, so I cannot create a statement handle"
52             unless $dbh;
53 1 50       6 if (defined $row_count_query) {
    50          
54             } elsif (defined $table) {
55 1         4 $row_count_query = "SELECT COUNT(*) FROM $table";
56             } else {
57 0         0 die "For getting row count, please specify 'row_count_sth', ".
58             "'row_count_query', or 'table' argument";
59             }
60 1         27 $row_count_sth = $dbh->prepare($row_count_query);
61 1   50     164 $sth->execute(@{ $row_count_sth_bind_params // [] }); # to check query syntax
  1         136  
62             }
63              
64 1 50       24 die "Unknown argument(s): ". join(", ", sort keys %args)
65             if keys %args;
66              
67 1         18 bless {
68             #dbh => $dbh,
69             sth => $sth,
70             sth_bind_params => $sth_bind_params,
71             row_count_sth => $row_count_sth,
72             row_count_sth_bind_params => $row_count_sth_bind_params,
73             }, $class;
74             }
75              
76             sub as_csv {
77 1     1 0 1867 require Text::CSV_XS;
78 1         16300 my $self = shift;
79              
80 1   33     16 $self->{csv_parser} //= Text::CSV_XS->new({binary=>1});
81 1         147 my $csv = $self->{csv_parser};
82              
83 1         4 my $res = "";
84 1         6 $csv->combine($self->get_column_names);
85 1         31 $res .= $csv->string . "\n";
86 1         15 $self->reset_iterator;
87 1         8 while (my $row = $self->get_row_arrayref) {
88 3         14 $csv->combine(@$row);
89 3         45 $res .= $csv->string . "\n";
90             }
91 1         8 $res;
92             }
93              
94             sub get_column_count {
95 1     1 0 3 my $self = shift;
96 1         12 $self->{sth}{NUM_OF_FIELDS};
97             }
98              
99             sub get_column_names {
100 2     2 0 4 my $self = shift;
101 2 50       10 wantarray ? @{ $self->{sth}{NAME_lc} } : $self->{sth}{NAME_lc};
  2         68  
102             }
103              
104             sub get_row_arrayref {
105 5     5 0 29 my $self = shift;
106 5         55 $self->{sth}->fetchrow_arrayref;
107             }
108              
109             sub get_row_count {
110 1     1 0 3 my $self = shift;
111 1   50     3 $self->{row_count_sth}->execute(@{ $self->{row_count_sth_bind_params} // [] });
  1         20  
112 1         10 my ($row_count) = $self->{row_count_sth}->fetchrow_array;
113 1         5 $row_count;
114             }
115              
116             sub get_row_hashref {
117 2     2 0 4 my $self = shift;
118 2         63 $self->{sth}->fetchrow_hashref;
119             }
120              
121             sub reset_iterator {
122 3     3 0 7 my $self = shift;
123 3   50     7 $self->{sth}->execute(@{ $self->{sth_bind_params} // [] });
  3         200  
124             }
125              
126             1;
127             # ABSTRACT: Role to access table data from DBI
128              
129             __END__