File Coverage

blib/lib/ArrayDataRole/Source/DBI.pm
Criterion Covered Total %
statement 76 83 91.5
branch 28 42 66.6
condition 5 11 45.4
subroutine 11 12 91.6
pod 1 8 12.5
total 121 156 77.5


line stmt bran cond sub pod time code
1             package ArrayDataRole::Source::DBI;
2              
3 4     4   358334 use strict;
  4         9  
  4         131  
4 4     4   63 use 5.010001;
  4         13  
5 4     4   413 use Role::Tiny;
  4         5036  
  4         23  
6 4     4   1320 use Role::Tiny::With;
  4         220  
  4         3564  
7             with 'ArrayDataRole::Spec::Basic';
8              
9             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
10             our $DATE = '2024-05-06'; # DATE
11             our $DIST = 'ArrayDataRoles-Standard'; # DIST
12             our $VERSION = '0.010'; # VERSION
13              
14             sub new {
15 1     1 1 608087 my ($class, %args) = @_;
16              
17 1         5 my $dsn = delete $args{dsn};
18 1         3 my $user = delete $args{user};
19 1         3 my $password = delete $args{password};
20 1         3 my $dbh = delete $args{dbh};
21 1 50       7 if (defined $dbh) {
    0          
22             } elsif (defined $dsn) {
23 0         0 require DBI;
24 0         0 $dbh = DBI->connect($dsn, $user, $password, {RaiseError=>1});
25             }
26              
27 1         21 my $sth = delete $args{sth};
28 1         4 my $sth_bind_params = delete $args{sth_bind_params};
29 1         3 my $query = delete $args{query};
30 1         2 my $table = delete $args{table}; # XXX quote
31 1         10 my $column = delete $args{column}; # XXX quote
32 1 50       4 if (defined $sth) {
33             } else {
34 1 50       5 die "You specify 'query' or 'table' & 'column', but you don't specify ".
35             "dbh/dsn+user+password, so I cannot create a statement handle"
36             unless $dbh;
37 1 50 33     44 if (defined $query) {
    50          
38             } elsif (defined $table && defined $column) {
39 1         18 $query = "SELECT $column FROM $table";
40             } else {
41 0         0 die "Please specify 'sth', 'query', or 'table' & 'column' arguments";
42             }
43 1         49 $sth = $dbh->prepare($query);
44 1   50     188 $sth->execute(@{ $sth_bind_params // [] }); # to check query syntax
  1         129  
45             }
46              
47 1         8 my $row_count_sth = delete $args{row_count_sth};
48 1         2 my $row_count_sth_bind_params = delete $args{row_count_sth_bind_params};
49 1         2 my $row_count_query = delete $args{row_count_query};
50 1 50       5 if (defined $row_count_sth) {
51             } else {
52 1 50       6 die "You specify 'row_count_query' or 'table', but you don't specify ".
53             "dbh/dsn+user+password, so I cannot create a statement handle"
54             unless $dbh;
55 1 50       5 if (defined $row_count_query) {
    50          
56             } elsif (defined $table) {
57 1         3 $row_count_query = "SELECT COUNT(*) FROM $table";
58             } else {
59 0         0 die "For getting row count, please specify 'row_count_sth', ".
60             "'row_count_query', or 'table' argument";
61             }
62 1         34 $row_count_sth = $dbh->prepare($row_count_query);
63 1   50     121 $sth->execute(@{ $row_count_sth_bind_params // [] }); # to check query syntax
  1         69  
64             }
65              
66 1 50       7 die "Unknown argument(s): ". join(", ", sort keys %args)
67             if keys %args;
68              
69 1         14 bless {
70             #dbh => $dbh,
71             sth => $sth,
72             sth_bind_params => $sth_bind_params,
73             row_count_sth => $row_count_sth,
74             row_count_sth_bind_params => $row_count_sth_bind_params,
75             pos => 0, # iterator pos
76             #buf => '', # exists when there is a buffer
77             }, $class;
78             }
79              
80             sub get_next_item {
81 9     9 0 25 my $self = shift;
82 9 100       25 if (exists $self->{buf}) {
83 6         13 $self->{pos}++;
84 6         16 return delete $self->{buf};
85             } else {
86 3         56 my $row = $self->{sth}->fetchrow_arrayref;
87 3 50       14 die "StopIteration" unless $row;
88 3         17 $self->{pos}++;
89 3         22 $row->[0];
90             }
91             }
92              
93             sub has_next_item {
94 8     8 0 14 my $self = shift;
95 8 50       35 if (exists $self->{buf}) {
96 0         0 return 1;
97             }
98 8         104 my $row = $self->{sth}->fetchrow_arrayref;
99 8 100       41 return 0 unless $row;
100 6         33 $self->{buf} = $row->[0];
101 6         22 1;
102             }
103              
104             sub get_item_count {
105 1     1 0 3 my $self = shift;
106 1   50     3 $self->{row_count_sth}->execute(@{ $self->{row_count_sth_bind_params} // [] });
  1         26  
107 1         13 my ($row_count) = $self->{row_count_sth}->fetchrow_array;
108 1         7 $row_count;
109             }
110              
111             sub reset_iterator {
112 4     4 0 83 my $self = shift;
113 4   50     48 $self->{sth}->execute(@{ $self->{sth_bind_params} // [] });
  4         280  
114 4         19 $self->{pos} = 0;
115             }
116              
117             sub get_iterator_pos {
118 0     0 0 0 my $self = shift;
119 0         0 $self->{pos};
120             }
121              
122             sub get_item_at_pos {
123 3     3 0 59 my ($self, $pos) = @_;
124 3 100       16 $self->reset_iterator if $self->{pos} > $pos;
125 3         19 while (1) {
126 5 100       42 die "Out of range" unless $self->has_next_item;
127 4         11 my $item = $self->get_next_item;
128 4 100       26 return $item if $self->{pos} > $pos;
129             }
130             }
131              
132             sub has_item_at_pos {
133 3     3 0 9 my ($self, $pos) = @_;
134 3 100       17 return 1 if $self->{pos} > $pos;
135 2         4 while (1) {
136 3 100       11 return 0 unless $self->has_next_item;
137 2         6 $self->get_next_item;
138 2 100       12 return 1 if $self->{pos} > $pos;
139             }
140             }
141              
142             1;
143             # ABSTRACT: Role to access elements from DBI
144              
145             __END__