line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# The contents of this file are Copyright (c) 2010 Daniel Norman |
2
|
|
|
|
|
|
|
# This program is free software; you can redistribute it and/or |
3
|
|
|
|
|
|
|
# modify it under the terms of the GNU General Public License as |
4
|
|
|
|
|
|
|
# published by the Free Software Foundation. |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
########################################### |
7
|
|
|
|
|
|
|
package DBR::Query::Select; |
8
|
|
|
|
|
|
|
|
9
|
18
|
|
|
18
|
|
123
|
use strict; |
|
18
|
|
|
|
|
34
|
|
|
18
|
|
|
|
|
689
|
|
10
|
18
|
|
|
18
|
|
123
|
use base 'DBR::Query'; |
|
18
|
|
|
|
|
37
|
|
|
18
|
|
|
|
|
1764
|
|
11
|
18
|
|
|
18
|
|
103
|
use Carp; |
|
18
|
|
|
|
|
34
|
|
|
18
|
|
|
|
|
1212
|
|
12
|
18
|
|
|
18
|
|
10299
|
use DBR::Record::Maker; |
|
18
|
|
|
|
|
64
|
|
|
18
|
|
|
|
|
27300
|
|
13
|
|
|
|
|
|
|
|
14
|
590
|
|
|
590
|
|
4053
|
sub _params { qw (fields tables where builder limit lock quiet_error) } |
15
|
574
|
|
|
574
|
|
2498
|
sub _reqparams { qw (fields tables) } |
16
|
574
|
|
|
574
|
|
2217
|
sub _validate_self{ 1 } # If I exist, I'm valid |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
sub fields{ |
19
|
603
|
|
|
603
|
0
|
1126
|
my $self = shift; |
20
|
603
|
50
|
50
|
|
|
2096
|
exists( $_[0] ) or return wantarray?( @{$self->{fields}||[]} ) : $self->{fields} || undef; |
|
27
|
100
|
|
|
|
232
|
|
|
|
100
|
|
|
|
|
|
21
|
|
|
|
|
|
|
|
22
|
574
|
|
|
|
|
3055
|
my @fields = $self->_arrayify(@_); |
23
|
574
|
50
|
|
|
|
2662
|
scalar(@fields) || croak('must provide at least one field'); |
24
|
|
|
|
|
|
|
|
25
|
574
|
|
|
|
|
1259
|
my $lastidx = -1; |
26
|
574
|
|
|
|
|
1546
|
for (@fields){ |
27
|
2455
|
50
|
|
|
|
14136
|
ref($_) =~ /^DBR::Config::Field/ || croak('must specify field as a DBR::Config::Field object'); # Could also be ::Anon |
28
|
2455
|
|
|
|
|
10009
|
$_->index( ++$lastidx ); |
29
|
|
|
|
|
|
|
} |
30
|
574
|
|
|
|
|
2604
|
$self->{last_idx} = $lastidx; |
31
|
574
|
|
|
|
|
1361
|
$self->{fields} = \@fields; |
32
|
|
|
|
|
|
|
|
33
|
574
|
|
|
|
|
2111
|
return 1; |
34
|
|
|
|
|
|
|
} |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
sub sql{ |
38
|
564
|
|
|
564
|
0
|
2144
|
my $self = shift; |
39
|
564
|
50
|
|
|
|
2511
|
my $conn = $self->instance->connect('conn') or return $self->_error('failed to connect'); |
40
|
564
|
|
|
|
|
1087
|
my $sql; |
41
|
|
|
|
|
|
|
|
42
|
564
|
|
|
|
|
1929
|
my $tables = join(',', map { $_->sql( $conn ) } @{$self->{tables}} ); |
|
566
|
|
|
|
|
2668
|
|
|
564
|
|
|
|
|
3633
|
|
43
|
564
|
|
|
|
|
2518
|
my $fields = join(',', map { $_->sql( $conn ) } @{$self->{fields}} ); |
|
2445
|
|
|
|
|
10630
|
|
|
564
|
|
|
|
|
1538
|
|
44
|
|
|
|
|
|
|
|
45
|
564
|
|
|
|
|
2744
|
$sql = "SELECT $fields FROM $tables"; |
46
|
564
|
100
|
|
|
|
4707
|
$sql .= ' WHERE ' . $self->{where}->sql($conn) if $self->{where}; |
47
|
564
|
50
|
|
|
|
3474
|
$sql .= ' FOR UPDATE' if $self->{lock}; |
48
|
564
|
50
|
|
|
|
2099
|
$sql .= ' LIMIT ' . $self->{limit} if $self->{limit}; |
49
|
|
|
|
|
|
|
|
50
|
564
|
|
|
|
|
2429
|
$self->_logDebug2( $sql ); |
51
|
564
|
|
|
|
|
4222
|
return $sql; |
52
|
|
|
|
|
|
|
} |
53
|
|
|
|
|
|
|
|
54
|
27
|
|
|
27
|
0
|
333
|
sub lastidx { $_[0]{last_idx} } |
55
|
1
|
50
|
|
1
|
0
|
4
|
sub can_be_subquery { scalar( @{ $_[0]->fields || [] } ) == 1 }; # Must have exactly one field |
|
1
|
|
|
|
|
6
|
|
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
sub run { |
58
|
567
|
|
|
567
|
0
|
1117
|
my $self = shift; |
59
|
567
|
|
33
|
|
|
4624
|
return $self->{sth} ||= $self->instance->getconn->prepare( $self->sql ) || confess "Failed to prepare"; # only run once |
|
|
|
66
|
|
|
|
|
60
|
|
|
|
|
|
|
} |
61
|
|
|
|
|
|
|
sub reset { |
62
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
63
|
0
|
|
0
|
|
|
0
|
return $self->{sth} && $self->{sth}->finish; |
64
|
|
|
|
|
|
|
} |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
# HERE - it's a little funky that we are handling split queries here, |
67
|
|
|
|
|
|
|
# but non-split queries in ResultSet. Not horrible... just funky. |
68
|
|
|
|
|
|
|
sub fetch_segment{ |
69
|
10
|
|
|
10
|
0
|
16
|
my $self = shift; |
70
|
10
|
|
|
|
|
24
|
my $value = shift; |
71
|
|
|
|
|
|
|
|
72
|
10
|
|
50
|
|
|
82
|
return ( $self->{spvals} ||= $self->_do_split )->{ $value } || []; |
73
|
|
|
|
|
|
|
} |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
sub _do_split{ |
76
|
4
|
|
|
4
|
|
9
|
my $self = shift; |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
# Should have a splitfield if we're getting here. Don't check for it. speeed. |
79
|
4
|
50
|
|
|
|
23
|
defined( my $idx = $self->{splitfield}->index ) or croak 'field object must provide an index'; |
80
|
|
|
|
|
|
|
|
81
|
4
|
|
|
|
|
17
|
my $sth = $self->run; |
82
|
|
|
|
|
|
|
|
83
|
4
|
50
|
|
|
|
571
|
defined( $sth->execute ) or croak 'failed to execute statement (' . $sth->errstr. ')'; |
84
|
|
|
|
|
|
|
|
85
|
4
|
|
|
|
|
11
|
my $row; |
86
|
4
|
|
|
|
|
22
|
my $code = 'while($row = $sth->fetch){ push @{$groupby{ $row->[' . $idx . '] }}, [@$row] }'; |
87
|
4
|
|
|
|
|
39
|
$self->_logDebug3($code); |
88
|
|
|
|
|
|
|
|
89
|
4
|
|
|
|
|
8
|
my %groupby; |
90
|
4
|
|
|
|
|
1647
|
eval $code; |
91
|
4
|
50
|
|
|
|
25
|
$@ && confess $@; |
92
|
|
|
|
|
|
|
|
93
|
4
|
|
|
|
|
20
|
$sth->finish; |
94
|
4
|
|
|
|
|
281
|
return \%groupby; |
95
|
|
|
|
|
|
|
} |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
sub get_record_obj{ |
99
|
39
|
|
|
39
|
0
|
92
|
my $self = shift; |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
# Only make the record-maker object once per query. Even split queries should be able to share the same one. |
102
|
39
|
0
|
66
|
|
|
757
|
return $self->{recordobj} ||= DBR::Record::Maker->new( |
103
|
|
|
|
|
|
|
session => $self->{session}, |
104
|
|
|
|
|
|
|
query => $self, # This value is not preserved by the record maker, thus no memory leak |
105
|
|
|
|
|
|
|
) or confess ('failed to create record class'); |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
sub DESTROY{ |
109
|
580
|
|
|
580
|
|
69523
|
my $self = shift; |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
# Can't finish the sth when going out of scope, it might live longer than this object. |
112
|
|
|
|
|
|
|
|
113
|
580
|
|
|
|
|
30714
|
return 1; |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
1; |