File Coverage

blib/lib/Mojo/DB/Results/Role/Struct.pm
Criterion Covered Total %
statement 22 22 100.0
branch 2 2 100.0
condition 2 2 100.0
subroutine 7 7 100.0
pod 2 2 100.0
total 35 35 100.0


line stmt bran cond sub pod time code
1             package Mojo::DB::Results::Role::Struct;
2              
3 1     1   915 use Mojo::Base -role;
  1         3  
  1         8  
4 1     1   545 use Mojo::Util qw(encode sha1_sum);
  1         3  
  1         132  
5 1     1   585 use Struct::Dumb 'readonly_struct';
  1         2346  
  1         7  
6              
7             our $VERSION = 'v0.1.1';
8              
9             requires qw(array arrays columns);
10              
11 7   100 7 1 10719 sub struct { my $r = $_[0]->array // return undef; $_[0]->_struct->(@$r) }
  4         55  
12              
13             sub structs {
14 4     4 1 519 my $self = shift;
15 4         14 my $struct = $self->_struct;
16 4     4   16 return $self->arrays->map(sub { $struct->(@$_) });
  4         109  
17             }
18              
19             sub _struct {
20 8     8   16 my $self = shift;
21 8         26 my $cols = $self->columns;
22 8         51 my $name = 'RowStruct_' . sha1_sum(join "\0", map { encode 'UTF-8', $_ } @$cols);
  24         411  
23 8 100       191 return $self->{_struct} if defined($self->{_struct} = __PACKAGE__->can($name));
24 2         11 readonly_struct $name => $cols;
25 2         438 return $self->{_struct} = __PACKAGE__->can($name);
26             }
27              
28             1;
29              
30             =head1 NAME
31              
32             Mojo::DB::Results::Role::Struct - Database query results as structs
33              
34             =head1 SYNOPSIS
35              
36             use Mojo::SQLite;
37             my $sqlite = Mojo::SQLite->new(...);
38             my $results = $sqlite->db->query('SELECT * FROM "table" WHERE "foo" = ?', 42);
39             my $struct = $results->with_roles('Mojo::DB::Results::Role::Struct')->structs->first;
40             my $bar = $struct->bar; # dies unless column "bar" exists
41              
42             use Mojo::Pg;
43             my $pg = Mojo::Pg->new(...)->with_roles('Mojo::DB::Role::ResultsRoles');
44             push @{$pg->results_roles}, 'Mojo::DB::Results::Role::Struct';
45             my $results = $pg->db->query('SELECT "foo", "bar" FROM "table"');
46             foreach my $row ($results->structs->each) {
47             my $foo = $row->foo;
48             my $bar = $row->baz; # dies
49             }
50              
51             =head1 DESCRIPTION
52              
53             This role can be applied to a results object for L or similar
54             database APIs. It provides L and L methods which return
55             L records, providing read-only accessors only for the expected
56             column names. Note that a column name that is not a valid identifier is
57             trickier to access in this manner.
58              
59             my $row = $results->struct;
60             my $col_name = 'foo.bar';
61             my $val = $row->$col_name;
62             # or
63             my $val = $row->${\'foo.bar'};
64              
65             You can apply the role to a results object using L,
66             or apply it to all results objects created by a database manager using
67             L as shown in the synopsis.
68              
69             =head1 METHODS
70              
71             L composes the following methods.
72              
73             =head2 struct
74              
75             my $struct = $results->struct;
76              
77             Fetch next row from the statement handle with the result object's C
78             method, and return it as a struct.
79              
80             =head2 structs
81              
82             my $collection = $results->structs;
83              
84             Fetch all rows from the statement handle with the result object's C
85             method, and return them as a L object containing structs.
86              
87             =head1 BUGS
88              
89             Report any issues on the public bugtracker.
90              
91             =head1 AUTHOR
92              
93             Dan Book
94              
95             =head1 COPYRIGHT AND LICENSE
96              
97             This software is Copyright (c) 2019 by Dan Book.
98              
99             This is free software, licensed under:
100              
101             The Artistic License 2.0 (GPL Compatible)
102              
103             =head1 SEE ALSO
104              
105             L, L, L, L