| line | stmt | bran | cond | sub | pod | time | code | 
| 1 | 2 |  |  | 2 |  | 44 | use 5.008003; | 
|  | 2 |  |  |  |  | 7 |  | 
| 2 | 2 |  |  | 2 |  | 13 | use strict; | 
|  | 2 |  |  |  |  | 27 |  | 
|  | 2 |  |  |  |  | 73 |  | 
| 3 | 2 |  |  | 2 |  | 11 | use warnings; | 
|  | 2 |  |  |  |  | 4 |  | 
|  | 2 |  |  |  |  | 161 |  | 
| 4 |  |  |  |  |  |  |  | 
| 5 |  |  |  |  |  |  |  | 
| 6 |  |  |  |  |  |  | our $AUTHORITY = 'cpan:TOBYINK'; | 
| 7 |  |  |  |  |  |  | our $VERSION   = '0.001'; | 
| 8 |  |  |  |  |  |  |  | 
| 9 |  |  |  |  |  |  | use Class::Tiny qw( database name sql_select sql_where sql_alias _join_info ); | 
| 10 | 2 |  |  | 2 |  | 12 |  | 
|  | 2 |  |  |  |  | 12 |  | 
|  | 2 |  |  |  |  | 17 |  | 
| 11 |  |  |  |  |  |  | use LINQ (); | 
| 12 | 2 |  |  | 2 |  | 1831 | use LINQ::Util::Internal (); | 
|  | 2 |  |  |  |  | 15 |  | 
|  | 2 |  |  |  |  | 43 |  | 
| 13 | 2 |  |  | 2 |  | 895 | use LINQ::Database::Util (); | 
|  | 2 |  |  |  |  | 936 |  | 
|  | 2 |  |  |  |  | 45 |  | 
| 14 | 2 |  |  | 2 |  | 840 | use Object::Adhoc (); | 
|  | 2 |  |  |  |  | 4 |  | 
|  | 2 |  |  |  |  | 45 |  | 
| 15 | 2 |  |  | 2 |  | 905 | use Scalar::Util (); | 
|  | 2 |  |  |  |  | 15138 |  | 
|  | 2 |  |  |  |  | 44 |  | 
| 16 | 2 |  |  | 2 |  | 14 |  | 
|  | 2 |  |  |  |  | 4 |  | 
|  | 2 |  |  |  |  | 29 |  | 
| 17 |  |  |  |  |  |  | use Role::Tiny::With (); | 
| 18 | 2 |  |  | 2 |  | 921 | Role::Tiny::With::with 'LINQ::Collection'; | 
|  | 2 |  |  |  |  | 10368 |  | 
|  | 2 |  |  |  |  | 2146 |  | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | my ( $self ) = ( shift ); | 
| 21 |  |  |  |  |  |  |  | 
| 22 | 6 |  |  | 6 |  | 118 | my %args = ( %$self, @_ ); | 
| 23 |  |  |  |  |  |  | delete $args{'_linq_iterator'}; | 
| 24 | 6 |  |  |  |  | 28 | ref( $self )->new( %args ); | 
| 25 | 6 |  |  |  |  | 15 | } | 
| 26 | 6 |  |  |  |  | 33 |  | 
| 27 |  |  |  |  |  |  | my ( $self ) = ( shift ); | 
| 28 |  |  |  |  |  |  | my $selection = LINQ::Util::Internal::assert_code( @_ ); | 
| 29 |  |  |  |  |  |  |  | 
| 30 | 3 |  |  | 3 | 0 | 5150 | if ( ! defined($self->sql_select) ) { | 
| 31 | 3 |  |  |  |  | 11 | my $columns = LINQ::Database::Util::selection_to_sql( $selection ); | 
| 32 |  |  |  |  |  |  | return $self->_clone( sql_select => $selection ) if $columns; | 
| 33 | 3 | 50 |  |  |  | 309 | } | 
| 34 | 3 |  |  |  |  | 28 |  | 
| 35 | 3 | 50 |  |  |  | 21 | $self->LINQ::Collection::select( $selection ); | 
| 36 |  |  |  |  |  |  | } | 
| 37 |  |  |  |  |  |  |  | 
| 38 | 0 |  |  |  |  | 0 | my ( $self ) = ( shift ); | 
| 39 |  |  |  |  |  |  | my $assertion = LINQ::Util::Internal::assert_code( @_ ); | 
| 40 |  |  |  |  |  |  |  | 
| 41 |  |  |  |  |  |  | if ( ! defined($self->sql_where) and ! defined($self->sql_select) ) { | 
| 42 | 4 |  |  | 4 | 0 | 7779 | my $filter = LINQ::Database::Util::assertion_to_sql( $assertion ); | 
| 43 | 4 |  |  |  |  | 12 | return $self->_clone( sql_where => $assertion ) if $filter; | 
| 44 |  |  |  |  |  |  | } | 
| 45 | 4 | 100 | 66 |  |  | 342 |  | 
| 46 | 3 |  |  |  |  | 83 | $self->LINQ::Collection::where( $assertion ); | 
| 47 | 3 | 100 |  |  |  | 19 | } | 
| 48 |  |  |  |  |  |  |  | 
| 49 |  |  |  |  |  |  | my ( $self ) = ( shift ); | 
| 50 | 2 |  |  |  |  | 43 | $self->_linq_iterator->to_iterator; | 
| 51 |  |  |  |  |  |  | } | 
| 52 |  |  |  |  |  |  |  | 
| 53 |  |  |  |  |  |  | my ( $self ) = ( shift ); | 
| 54 | 2 |  |  | 2 | 0 | 137 | $self->_linq_iterator->to_list; | 
| 55 | 2 |  |  |  |  | 23 | } | 
| 56 |  |  |  |  |  |  |  | 
| 57 |  |  |  |  |  |  | my ( $self ) = ( shift ); | 
| 58 |  |  |  |  |  |  | $self->_linq_iterator->to_array; | 
| 59 | 7 |  |  | 7 | 0 | 474 | } | 
| 60 | 7 |  |  |  |  | 16 |  | 
| 61 |  |  |  |  |  |  | my ( $self ) = ( shift ); | 
| 62 |  |  |  |  |  |  | $self->{_linq_iterator} ||= $self->_build_linq_iterator; | 
| 63 |  |  |  |  |  |  | } | 
| 64 | 0 |  |  | 0 | 0 | 0 |  | 
| 65 | 0 |  |  |  |  | 0 | my ( $self ) = ( shift ); | 
| 66 |  |  |  |  |  |  |  | 
| 67 |  |  |  |  |  |  | my $sth = $self->_build_sth; | 
| 68 |  |  |  |  |  |  | my $map = defined( $self->sql_select ) | 
| 69 | 9 |  |  | 9 |  | 16 | ? $self->sql_select | 
| 70 | 9 |  | 66 |  |  | 35 | : sub { Object::Adhoc::object( $_ ) }; | 
| 71 |  |  |  |  |  |  | my $started = 0; | 
| 72 |  |  |  |  |  |  |  | 
| 73 |  |  |  |  |  |  | LINQ::LINQ( sub { | 
| 74 | 7 |  |  | 7 |  | 11 | if ( not $started ) { | 
| 75 |  |  |  |  |  |  | $sth->execute; | 
| 76 | 7 |  |  |  |  | 15 | ++$started; | 
| 77 |  |  |  |  |  |  | } | 
| 78 |  |  |  |  |  |  | local $_ = $sth->fetchrow_hashref or return LINQ::END; | 
| 79 | 7 | 100 |  | 19 |  | 1442 | return $map->( $_ ); | 
|  | 19 |  |  |  |  | 62 |  | 
| 80 | 7 |  |  |  |  | 118 | } ); | 
| 81 |  |  |  |  |  |  | } | 
| 82 |  |  |  |  |  |  |  | 
| 83 | 39 | 100 |  | 39 |  | 14877 | my ( $self ) = ( shift ); | 
| 84 | 7 |  |  |  |  | 472 |  | 
| 85 | 7 |  |  |  |  | 29 | my $sql_select = defined($self->sql_select) ? $self->sql_select : '*'; | 
| 86 |  |  |  |  |  |  | if ( ref( $sql_select ) ) { | 
| 87 | 39 | 100 |  |  |  | 788 | $sql_select = LINQ::Database::Util::selection_to_sql( | 
| 88 | 32 |  |  |  |  | 160 | $sql_select, | 
| 89 | 7 |  |  |  |  | 46 | sub { $self->database->quote_identifier( @_ ) }, | 
| 90 |  |  |  |  |  |  | ) || '*'; | 
| 91 |  |  |  |  |  |  | } | 
| 92 |  |  |  |  |  |  |  | 
| 93 | 7 |  |  | 7 |  | 12 | my $sql_where = defined($self->sql_where) ? $self->sql_where : ''; | 
| 94 |  |  |  |  |  |  | if ( ref( $sql_where ) ) { | 
| 95 | 7 | 100 |  |  |  | 157 | $sql_where = LINQ::Database::Util::assertion_to_sql( | 
| 96 | 7 | 100 |  |  |  | 103 | $sql_where, | 
| 97 |  |  |  |  |  |  | sub { $self->database->quote_identifier( @_ ) }, | 
| 98 |  |  |  |  |  |  | sub { $self->database->quote( @_ ) }, | 
| 99 | 4 |  |  | 4 |  | 66 | ) || ''; | 
| 100 | 3 |  | 50 |  |  | 29 | } | 
| 101 |  |  |  |  |  |  |  | 
| 102 |  |  |  |  |  |  | if ( $self->_join_info ) { | 
| 103 | 7 | 100 |  |  |  | 130 | my $sql = sprintf( | 
| 104 | 7 | 100 |  |  |  | 82 | 'SELECT %s FROM %s t1 %s JOIN %s t2 ON t1.%s=t2.%s%s', | 
| 105 |  |  |  |  |  |  | $sql_select, | 
| 106 |  |  |  |  |  |  | $self->name, | 
| 107 | 2 |  |  | 2 |  | 37 | ( $self->_join_info->[0] =~ /^-(?:left|right|inner)$/ ) | 
| 108 | 2 |  |  | 2 |  | 40 | ? uc(substr($self->_join_info->[0], 1)) | 
| 109 | 2 |  | 50 |  |  | 40 | : '', | 
| 110 |  |  |  |  |  |  | $self->database->quote_identifier( $self->_join_info->[1] ), | 
| 111 |  |  |  |  |  |  | $self->database->quote_identifier( $self->_join_info->[2] ), | 
| 112 | 7 | 100 |  |  |  | 115 | $self->database->quote_identifier( $self->_join_info->[3] ), | 
| 113 | 1 | 50 |  |  |  | 36 | ( $sql_where ? " WHERE $sql_where" : $sql_where ), | 
|  |  | 50 |  |  |  |  |  | 
| 114 |  |  |  |  |  |  | ); | 
| 115 |  |  |  |  |  |  | return $self->database->prepare($sql); | 
| 116 |  |  |  |  |  |  | } | 
| 117 |  |  |  |  |  |  |  | 
| 118 |  |  |  |  |  |  | $self->database->prepare( sprintf( | 
| 119 |  |  |  |  |  |  | 'SELECT %s FROM %s%s', | 
| 120 |  |  |  |  |  |  | $sql_select, | 
| 121 |  |  |  |  |  |  | $self->name, | 
| 122 |  |  |  |  |  |  | ( $sql_where ? " WHERE $sql_where" : $sql_where ), | 
| 123 |  |  |  |  |  |  | ) ); | 
| 124 |  |  |  |  |  |  | } | 
| 125 | 1 |  |  |  |  | 56 |  | 
| 126 |  |  |  |  |  |  | my ( $self, $other, $hint, $field1, $field2, $joiner ); | 
| 127 |  |  |  |  |  |  |  | 
| 128 | 6 | 100 |  |  |  | 114 | if ( @_ == 6 ) { | 
| 129 |  |  |  |  |  |  | ( $self, $other, $hint, $field1, $field2, $joiner ) = @_; | 
| 130 |  |  |  |  |  |  | } | 
| 131 |  |  |  |  |  |  | else { | 
| 132 |  |  |  |  |  |  | ( $self, $other ) = ( shift, shift ); | 
| 133 |  |  |  |  |  |  | ( $field1, $field2, $joiner ) = @_; | 
| 134 |  |  |  |  |  |  | $hint = '-outer'; | 
| 135 |  |  |  |  |  |  | } | 
| 136 |  |  |  |  |  |  |  | 
| 137 | 1 |  |  | 1 | 0 | 4738 | if ( Scalar::Util::blessed($self)   and $self->isa(__PACKAGE__) | 
| 138 |  |  |  |  |  |  | and  Scalar::Util::blessed($other)  and $other->isa(__PACKAGE__) | 
| 139 | 1 | 50 |  |  |  | 5 | and  Scalar::Util::blessed($field1) and $field1->isa('LINQ::FieldSet::Single') | 
| 140 | 0 |  |  |  |  | 0 | and  Scalar::Util::blessed($field2) and $field2->isa('LINQ::FieldSet::Single') | 
| 141 |  |  |  |  |  |  | and  $joiner eq '-auto' | 
| 142 |  |  |  |  |  |  | and  $self->database == $other->database | 
| 143 | 1 |  |  |  |  | 3 | and  !$self->_join_info | 
| 144 | 1 |  |  |  |  | 2 | and  !$other->_join_info and !$other->sql_where and !$other->sql_select | 
| 145 | 1 |  |  |  |  | 2 | ) { | 
| 146 |  |  |  |  |  |  | return $self->_clone( | 
| 147 |  |  |  |  |  |  | _join_info => [ $hint, $other->name, $field1->fields->[0]->name, $field2->fields->[0]->name ] | 
| 148 | 1 | 50 | 33 |  |  | 61 | ); | 
|  |  |  | 33 |  |  |  |  | 
|  |  |  | 33 |  |  |  |  | 
|  |  |  | 33 |  |  |  |  | 
|  |  |  | 33 |  |  |  |  | 
|  |  |  | 33 |  |  |  |  | 
|  |  |  | 33 |  |  |  |  | 
|  |  |  | 33 |  |  |  |  | 
|  |  |  | 33 |  |  |  |  | 
|  |  |  | 33 |  |  |  |  | 
|  |  |  | 33 |  |  |  |  | 
|  |  |  | 33 |  |  |  |  | 
|  |  |  | 33 |  |  |  |  | 
| 149 |  |  |  |  |  |  | } | 
| 150 |  |  |  |  |  |  |  | 
| 151 |  |  |  |  |  |  | if ( $joiner eq -auto ) { | 
| 152 |  |  |  |  |  |  | require LINQ::DSL; | 
| 153 |  |  |  |  |  |  | $joiner = LINQ::DSL::HashSmush(); | 
| 154 |  |  |  |  |  |  | } | 
| 155 |  |  |  |  |  |  |  | 
| 156 |  |  |  |  |  |  | return $self->LINQ::Collection::join( $hint, $other, $field1, $field2, $joiner ); | 
| 157 | 1 |  |  |  |  | 110 | } | 
| 158 |  |  |  |  |  |  |  | 
| 159 |  |  |  |  |  |  |  | 
| 160 |  |  |  |  |  |  |  | 
| 161 |  |  |  |  |  |  | 1; |