line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package SQL::Statement; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
######################################################################### |
4
|
|
|
|
|
|
|
# |
5
|
|
|
|
|
|
|
# This module is copyright (c), 2001,2005 by Jeff Zucker. |
6
|
|
|
|
|
|
|
# This module is copyright (c), 2007-2020 by Jens Rehsack. |
7
|
|
|
|
|
|
|
# All rights reserved. |
8
|
|
|
|
|
|
|
# |
9
|
|
|
|
|
|
|
# It may be freely distributed under the same terms as Perl itself. |
10
|
|
|
|
|
|
|
# |
11
|
|
|
|
|
|
|
# See below for help (search for SYNOPSIS) |
12
|
|
|
|
|
|
|
######################################################################### |
13
|
|
|
|
|
|
|
|
14
|
16
|
|
|
16
|
|
555119
|
use strict; |
|
16
|
|
|
|
|
102
|
|
|
16
|
|
|
|
|
537
|
|
15
|
16
|
|
|
16
|
|
88
|
use warnings FATAL => "all"; |
|
16
|
|
|
|
|
40
|
|
|
16
|
|
|
|
|
582
|
|
16
|
|
|
|
|
|
|
|
17
|
16
|
|
|
16
|
|
355
|
use 5.008; |
|
16
|
|
|
|
|
56
|
|
18
|
16
|
|
|
16
|
|
89
|
use vars qw($VERSION $DEBUG); |
|
16
|
|
|
|
|
30
|
|
|
16
|
|
|
|
|
1051
|
|
19
|
|
|
|
|
|
|
|
20
|
16
|
|
|
16
|
|
12997
|
use SQL::Parser (); |
|
16
|
|
|
|
|
88
|
|
|
16
|
|
|
|
|
807
|
|
21
|
16
|
|
|
16
|
|
9211
|
use SQL::Eval (); |
|
16
|
|
|
|
|
48
|
|
|
16
|
|
|
|
|
366
|
|
22
|
16
|
|
|
16
|
|
7649
|
use SQL::Statement::RAM (); |
|
16
|
|
|
|
|
44
|
|
|
16
|
|
|
|
|
418
|
|
23
|
16
|
|
|
16
|
|
7604
|
use SQL::Statement::TermFactory (); |
|
16
|
|
|
|
|
64
|
|
|
16
|
|
|
|
|
521
|
|
24
|
16
|
|
|
16
|
|
8662
|
use SQL::Statement::Util (); |
|
16
|
|
|
|
|
45
|
|
|
16
|
|
|
|
|
463
|
|
25
|
|
|
|
|
|
|
|
26
|
16
|
|
|
16
|
|
105
|
use Carp qw(carp croak); |
|
16
|
|
|
|
|
36
|
|
|
16
|
|
|
|
|
1249
|
|
27
|
16
|
|
|
16
|
|
6609
|
use Clone qw(clone); |
|
16
|
|
|
|
|
37815
|
|
|
16
|
|
|
|
|
978
|
|
28
|
16
|
|
|
16
|
|
3283
|
use Errno; |
|
16
|
|
|
|
|
9615
|
|
|
16
|
|
|
|
|
829
|
|
29
|
16
|
|
|
16
|
|
109
|
use Scalar::Util qw(blessed looks_like_number); |
|
16
|
|
|
|
|
34
|
|
|
16
|
|
|
|
|
825
|
|
30
|
16
|
|
|
16
|
|
101
|
use List::Util qw(first); |
|
16
|
|
|
|
|
36
|
|
|
16
|
|
|
|
|
975
|
|
31
|
16
|
|
|
16
|
|
93
|
use Params::Util qw(_INSTANCE _STRING _ARRAY _ARRAY0 _HASH0 _HASH); |
|
16
|
|
|
|
|
30
|
|
|
16
|
|
|
|
|
107788
|
|
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
#use locale; |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
$VERSION = '1.413_001'; |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
sub new |
38
|
|
|
|
|
|
|
{ |
39
|
872
|
|
|
872
|
1
|
368937
|
my ( $class, $sql, $flags ) = @_; |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
# IF USER DEFINED extend_csv IN SCRIPT |
42
|
|
|
|
|
|
|
# USE THE ANYDATA DIALECT RATHER THAN THE CSV DIALECT |
43
|
|
|
|
|
|
|
# WITH DBD::CSV |
44
|
|
|
|
|
|
|
|
45
|
872
|
0
|
33
|
|
|
4110
|
if ( ( defined($main::extend_csv) && $main::extend_csv ) |
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
46
|
|
|
|
|
|
|
|| ( defined($main::extend_sql) && $main::extend_sql ) ) |
47
|
|
|
|
|
|
|
{ |
48
|
0
|
|
|
|
|
0
|
$flags = SQL::Parser->new('AnyData'); |
49
|
|
|
|
|
|
|
} |
50
|
872
|
|
|
|
|
1480
|
my $parser = $flags; |
51
|
872
|
|
|
|
|
1838
|
my $self = bless( {}, $class ); |
52
|
872
|
50
|
|
|
|
2194
|
$flags->{PrintError} = 1 unless defined $flags->{PrintError}; |
53
|
872
|
100
|
|
|
|
1976
|
$flags->{text_numbers} = 1 unless defined $flags->{text_numbers}; |
54
|
872
|
100
|
|
|
|
1875
|
$flags->{alpha_compare} = 1 unless defined $flags->{alpha_compare}; |
55
|
|
|
|
|
|
|
|
56
|
872
|
50
|
|
|
|
3455
|
unless ( blessed($flags) ) # avoid copying stale data from earlier parsing sessions |
57
|
|
|
|
|
|
|
{ |
58
|
0
|
|
|
|
|
0
|
%$self = ( %$self, %{ clone($flags) } ); |
|
0
|
|
|
|
|
0
|
|
59
|
|
|
|
|
|
|
} |
60
|
|
|
|
|
|
|
else |
61
|
|
|
|
|
|
|
{ |
62
|
872
|
|
|
|
|
4703
|
$self->{$_} = $flags->{$_} for qw(RaiseError PrintError opts); |
63
|
|
|
|
|
|
|
} |
64
|
|
|
|
|
|
|
|
65
|
872
|
|
|
|
|
2002
|
$self->{dlm} = '~'; |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
# Dean Arnold improvement to allow better subclassing |
68
|
|
|
|
|
|
|
# if (!ref($parser) or (ref($parser) and ref($parser) !~ /^SQL::Parser/)) { |
69
|
872
|
50
|
|
|
|
5859
|
unless ( _INSTANCE( $parser, 'SQL::Parser' ) ) |
70
|
|
|
|
|
|
|
{ |
71
|
0
|
|
0
|
|
|
0
|
my $parser_dialect = $flags->{dialect} || 'AnyData'; |
72
|
0
|
0
|
|
|
|
0
|
$parser_dialect = 'AnyData' if ( $parser_dialect =~ m/^(?:CSV|Excel)$/ ); |
73
|
|
|
|
|
|
|
|
74
|
0
|
|
|
|
|
0
|
$parser = SQL::Parser->new( $parser_dialect, $flags ); |
75
|
|
|
|
|
|
|
} |
76
|
872
|
|
|
|
|
3479
|
$self->{termFactory} = SQL::Statement::TermFactory->new($self); |
77
|
872
|
|
|
|
|
1849
|
$self->{capabilities} = {}; |
78
|
872
|
|
|
|
|
2366
|
$self->prepare( $sql, $parser ); |
79
|
865
|
|
|
|
|
2658
|
return $self; |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
sub prepare |
83
|
|
|
|
|
|
|
{ |
84
|
872
|
|
|
872
|
1
|
1718
|
my ( $self, $sql, $parser ) = @_; |
85
|
|
|
|
|
|
|
|
86
|
872
|
50
|
|
|
|
2347
|
$self->{already_prepared}->{$sql} and return; |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
# delete earlier preparations, they're overwritten after this prepare run |
89
|
872
|
|
|
|
|
1762
|
$self->{already_prepared} = {}; |
90
|
872
|
|
|
|
|
2891
|
my $rv = $parser->parse($sql); |
91
|
865
|
100
|
|
|
|
1885
|
if ($rv) |
92
|
|
|
|
|
|
|
{ |
93
|
855
|
|
|
|
|
2912
|
undef $self->{errstr}; |
94
|
855
|
|
|
|
|
43836
|
my $parser_struct = clone( $parser->{struct} ); |
95
|
855
|
|
|
|
|
2925
|
while ( my ( $k, $v ) = each( %{$parser_struct} ) ) |
|
9564
|
|
|
|
|
22052
|
|
96
|
|
|
|
|
|
|
{ |
97
|
8709
|
|
|
|
|
16945
|
$self->{$k} = $v; |
98
|
|
|
|
|
|
|
} |
99
|
855
|
|
|
|
|
1659
|
undef $self->{where_terms}; # force rebuild when needed |
100
|
855
|
|
|
|
|
1499
|
undef $self->{columns}; |
101
|
855
|
|
|
|
|
1370
|
undef $self->{splitted_all_cols}; |
102
|
855
|
|
|
|
|
1459
|
$self->{argnum} = 0; |
103
|
|
|
|
|
|
|
|
104
|
855
|
|
|
|
|
1426
|
my $values = $self->{values}; |
105
|
855
|
|
|
|
|
1268
|
my $param_num = -1; |
106
|
855
|
100
|
|
|
|
2087
|
if ( $self->{limit_clause} ) |
107
|
|
|
|
|
|
|
{ |
108
|
9
|
|
|
|
|
58
|
$self->{limit_clause} = SQL::Statement::Limit->new( $self->{limit_clause} ); |
109
|
|
|
|
|
|
|
} |
110
|
|
|
|
|
|
|
|
111
|
855
|
100
|
|
|
|
1860
|
if ( defined( $self->{num_placeholders} ) ) |
112
|
|
|
|
|
|
|
{ |
113
|
17
|
|
|
|
|
69
|
for my $i ( 0 .. $self->{num_placeholders} - 1 ) |
114
|
|
|
|
|
|
|
{ |
115
|
36
|
|
|
|
|
111
|
$self->{params}->[$i] = SQL::Statement::Param->new($i); |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
|
119
|
855
|
|
|
|
|
1274
|
$self->{tables} = [ map { SQL::Statement::Table->new($_) } @{ $self->{table_names} } ]; |
|
704
|
|
|
|
|
1929
|
|
|
855
|
|
|
|
|
2050
|
|
120
|
|
|
|
|
|
|
|
121
|
855
|
100
|
66
|
|
|
2889
|
if ( $self->{where_clause} && !defined( $self->{where_terms} ) ) |
122
|
|
|
|
|
|
|
{ |
123
|
229
|
|
|
|
|
948
|
$self->{where_terms} = $self->{termFactory}->buildCondition( $self->{where_clause} ); |
124
|
|
|
|
|
|
|
#if ( $self->{where_clause}->{combiners} ) |
125
|
|
|
|
|
|
|
#{ |
126
|
|
|
|
|
|
|
# $self->{has_OR} = 1 |
127
|
|
|
|
|
|
|
# if ( first { -1 != index( $_, 'OR' ) } @{ $self->{where_clause}->{combiners} } ); |
128
|
|
|
|
|
|
|
#} |
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
|
131
|
855
|
|
|
|
|
2672
|
++$self->{already_prepared}->{$sql}; |
132
|
855
|
|
|
|
|
3377
|
return $self; |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
else |
135
|
|
|
|
|
|
|
{ |
136
|
10
|
|
|
|
|
49
|
$self->{errstr} = $parser->errstr; |
137
|
10
|
|
|
|
|
31
|
++$self->{already_prepared}->{$sql}; |
138
|
10
|
|
|
|
|
22
|
return; |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
} |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
sub execute |
143
|
|
|
|
|
|
|
{ |
144
|
4654
|
|
|
4654
|
1
|
194375
|
my ( $self, $data, $params ) = @_; |
145
|
|
|
|
|
|
|
( $self->{NUM_OF_ROWS}, $self->{NUM_OF_FIELDS}, $self->{data} ) = ( 0, 0, [] ) and return 'OEO' |
146
|
4654
|
100
|
50
|
|
|
10915
|
if ( $self->{no_execute} ); |
147
|
4649
|
100
|
|
|
|
9794
|
$self->{procedure}->{data} = $data if ( $self->{procedure} ); |
148
|
4649
|
|
|
|
|
9029
|
$self->{params} = $params; |
149
|
|
|
|
|
|
|
|
150
|
4649
|
|
|
|
|
11821
|
my ($command) = $self->command(); |
151
|
4649
|
50
|
|
|
|
9200
|
return $self->do_err('No command found!') unless ($command); |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
$self->{where_clause} |
154
|
|
|
|
|
|
|
and !defined( $self->{where_terms} ) |
155
|
4649
|
100
|
100
|
|
|
10796
|
and $self->{where_terms} = $self->{termFactory}->buildCondition( $self->{where_clause} ); |
156
|
|
|
|
|
|
|
|
157
|
4649
|
|
|
|
|
12393
|
( $self->{NUM_OF_ROWS}, $self->{NUM_OF_FIELDS}, $self->{data} ) = $self->$command( $data, $params ); |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
$self->{NAME} = |
160
|
4648
|
100
|
|
|
|
12836
|
_ARRAY0( $self->{columns} ) ? [ map { delete $_->{term}->{fastpath}; $_->display_name() } @{ $self->{columns} } ] : []; |
|
13395
|
|
|
|
|
21228
|
|
|
13395
|
|
|
|
|
25387
|
|
|
4642
|
|
|
|
|
8943
|
|
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
# Force closing the tables |
163
|
4648
|
|
|
|
|
8780
|
$self->{tables} = [ map { SQL::Statement::Table->new($_->{name}) } @{ delete $self->{tables} } ]; # create keen defs |
|
4518
|
|
|
|
|
11796
|
|
|
4648
|
|
|
|
|
9126
|
|
164
|
|
|
|
|
|
|
|
165
|
4648
|
|
|
|
|
11217
|
undef $self->{where_terms}; # force rebuild when needed |
166
|
|
|
|
|
|
|
|
167
|
4648
|
100
|
|
|
|
10145
|
return unless ( defined( $self->{NUM_OF_ROWS} ) ); |
168
|
4644
|
|
100
|
|
|
17236
|
return $self->{NUM_OF_ROWS} || '0E0'; |
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
sub CREATE ($$$) |
172
|
|
|
|
|
|
|
{ |
173
|
35
|
|
|
35
|
0
|
94
|
my ( $self, $data, $params ) = @_; |
174
|
35
|
|
|
|
|
53
|
my $names; |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
# CREATE TABLE AS ... |
177
|
35
|
|
|
|
|
71
|
my $subquery = $self->{subquery}; |
178
|
35
|
50
|
|
|
|
85
|
if ($subquery) |
179
|
|
|
|
|
|
|
{ |
180
|
0
|
|
|
|
|
0
|
my $sth; |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
# AS IMPORT |
183
|
0
|
0
|
|
|
|
0
|
if ( $subquery =~ m/^IMPORT/i ) |
184
|
|
|
|
|
|
|
{ |
185
|
|
|
|
|
|
|
$sth = $data->{Database}->prepare("SELECT * FROM $subquery") |
186
|
0
|
0
|
|
|
|
0
|
or return $self->do_err( $data->{Database}->errstr() ); |
187
|
0
|
0
|
|
|
|
0
|
$sth->execute(@$params) or return $self->do_err( $sth->errstr() ); |
188
|
0
|
|
|
|
|
0
|
$names = $sth->{NAME}; |
189
|
|
|
|
|
|
|
} |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
# AS SELECT |
192
|
|
|
|
|
|
|
else |
193
|
|
|
|
|
|
|
{ |
194
|
|
|
|
|
|
|
$sth = $data->{Database}->prepare($subquery) |
195
|
0
|
0
|
|
|
|
0
|
or return $self->do_err( $data->{Database}->errstr() ); |
196
|
0
|
0
|
|
|
|
0
|
$sth->execute() or return $self->do_err( $sth->errstr() ); |
197
|
0
|
|
|
|
|
0
|
$names = $sth->{NAME}; |
198
|
|
|
|
|
|
|
} |
199
|
0
|
0
|
|
|
|
0
|
$names = $sth->{NAME} unless defined $names; |
200
|
0
|
|
|
|
|
0
|
my $tbl_data = $sth->{sql_stmt}->{data}; |
201
|
0
|
|
0
|
|
|
0
|
my $tbl_name = $self->{org_table_names}->[0] || $self->tables(0)->name; |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
# my @tbl_cols = map {$_->name} $sth->{sql_stmt}->columns; |
204
|
|
|
|
|
|
|
#my @tbl_cols=map{$_->name} $sth->{sql_stmt}->columns if $sth->{sql_stmt}; |
205
|
0
|
|
|
|
|
0
|
my @tbl_cols; |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
# @tbl_cols=@{ $sth->{NAME} } unless @tbl_cols; |
208
|
0
|
0
|
|
|
|
0
|
@tbl_cols = @{$names} unless (@tbl_cols); |
|
0
|
|
|
|
|
0
|
|
209
|
0
|
|
|
|
|
0
|
my $create_sql = "CREATE TABLE $tbl_name"; |
210
|
0
|
0
|
|
|
|
0
|
$create_sql = "CREATE TEMP TABLE $tbl_name" if ( $self->{is_ram_table} ); |
211
|
0
|
|
|
|
|
0
|
my @coldefs = map { "'$_' TEXT" } @tbl_cols; |
|
0
|
|
|
|
|
0
|
|
212
|
0
|
|
|
|
|
0
|
$create_sql .= '(' . join( ',', @coldefs ) . ')'; |
213
|
0
|
0
|
|
|
|
0
|
$data->{Database}->do($create_sql) or die "Can't do <$create_sql>: " . $data->{Database}->errstr; |
214
|
0
|
|
|
|
|
0
|
my $colstr = ('?,') x @tbl_cols; |
215
|
0
|
|
|
|
|
0
|
my $insert_sql = "INSERT INTO $tbl_name VALUES($colstr)"; |
216
|
0
|
|
|
|
|
0
|
my $local_sth = $data->{Database}->prepare($insert_sql); |
217
|
0
|
|
|
|
|
0
|
$local_sth->execute(@$_) for @$tbl_data; |
218
|
0
|
|
|
|
|
0
|
return ( 0, 0 ); |
219
|
|
|
|
|
|
|
} |
220
|
35
|
|
|
|
|
128
|
my ( $eval, $foo ) = $self->open_tables( $data, 1, 1 ); |
221
|
35
|
50
|
|
|
|
187
|
return unless ($eval); |
222
|
35
|
|
|
|
|
156
|
$eval->params($params); |
223
|
35
|
|
|
|
|
118
|
my ( $row, $table, $col ) = ( [], $eval->table( $self->tables(0)->name() ) ); |
224
|
35
|
50
|
|
|
|
119
|
if ( _ARRAY( $table->col_names() ) ) |
225
|
|
|
|
|
|
|
{ |
226
|
0
|
|
|
|
|
0
|
return $self->do_err( "Table '" . $self->tables(0)->name() . "' already exists." ); |
227
|
|
|
|
|
|
|
} |
228
|
35
|
|
|
|
|
109
|
foreach $col ( $self->columns() ) |
229
|
|
|
|
|
|
|
{ |
230
|
97
|
|
|
|
|
146
|
push( @{$row}, $col->name() ); |
|
97
|
|
|
|
|
225
|
|
231
|
|
|
|
|
|
|
} |
232
|
35
|
|
|
|
|
182
|
$table->push_names( $data, $row ); |
233
|
|
|
|
|
|
|
|
234
|
35
|
|
|
|
|
214
|
return ( 0, 0 ); |
235
|
|
|
|
|
|
|
} |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
sub CALL |
238
|
|
|
|
|
|
|
{ |
239
|
0
|
|
|
0
|
0
|
0
|
my ( $self, $data, $params ) = @_; |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
# my $dbh = $data->{Database}; |
242
|
|
|
|
|
|
|
# $self->{procedure}->{data} = $data; |
243
|
|
|
|
|
|
|
|
244
|
0
|
|
|
|
|
0
|
my $procTerm = $self->{termFactory}->buildCondition( $self->{procedure} ); |
245
|
|
|
|
|
|
|
|
246
|
0
|
|
|
|
|
0
|
( $self->{NUM_OF_ROWS}, $self->{NUM_OF_FIELDS}, $self->{data} ) = $procTerm->value($data); |
247
|
|
|
|
|
|
|
} |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
my $enoentstr = "Cannot open .*\(" . Errno::ENOENT . "\)"; |
250
|
|
|
|
|
|
|
my $eabstrstr = "Abstract method .*::open_table called"; |
251
|
|
|
|
|
|
|
my $notblrx = qr/(?:$enoentstr|$eabstrstr)/; |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
sub DROP ($$$) |
254
|
|
|
|
|
|
|
{ |
255
|
12
|
|
|
12
|
0
|
31
|
my ( $self, $data, $params ) = @_; |
256
|
12
|
|
|
|
|
25
|
my $eval; |
257
|
|
|
|
|
|
|
my @err; |
258
|
12
|
|
|
|
|
26
|
eval { |
259
|
12
|
|
|
0
|
|
102
|
local $SIG{__WARN__} = sub { push @err, @_ }; |
|
0
|
|
|
|
|
0
|
|
260
|
12
|
|
|
|
|
50
|
($eval) = $self->open_tables( $data, 0, 1 ); |
261
|
|
|
|
|
|
|
}; |
262
|
12
|
100
|
66
|
|
|
115
|
if ( $self->{ignore_missing_table} |
|
|
|
100
|
|
|
|
|
|
|
|
66
|
|
|
|
|
263
|
|
|
|
|
|
|
and ( $@ or @err or $self->{errstr} ) |
264
|
10
|
|
|
|
|
95
|
and grep { $_ =~ $notblrx } ( @err, $@, $self->{errstr} ) ) |
265
|
|
|
|
|
|
|
{ |
266
|
5
|
|
|
|
|
28
|
return ( -1, 0 ); |
267
|
|
|
|
|
|
|
} |
268
|
|
|
|
|
|
|
|
269
|
7
|
50
|
|
|
|
27
|
return if $self->{errstr}; |
270
|
7
|
50
|
0
|
|
|
39
|
return $self->do_err( $@ || $err[0] ) if ( $@ || @err ); |
|
|
|
33
|
|
|
|
|
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
# return undef unless $eval; |
273
|
7
|
50
|
|
|
|
21
|
return ( -1, 0 ) unless $eval; |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
# $eval->params($params); |
276
|
7
|
|
|
|
|
22
|
my ($table) = $eval->table( $self->tables(0)->name() ); |
277
|
7
|
|
|
|
|
39
|
$table->drop($data); |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
#use mylibs; zwarn $self->{sql_stmt}; |
280
|
7
|
|
|
|
|
77
|
return ( -1, 0 ); |
281
|
|
|
|
|
|
|
} |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
sub INSERT ($$$) |
284
|
|
|
|
|
|
|
{ |
285
|
4275
|
|
|
4275
|
0
|
7511
|
my ( $self, $data, $params ) = @_; |
286
|
|
|
|
|
|
|
|
287
|
4275
|
|
|
|
|
11049
|
my ( $eval, $all_cols ) = $self->open_tables( $data, 0, 1 ); |
288
|
4275
|
50
|
|
|
|
12587
|
return unless ($eval); |
289
|
|
|
|
|
|
|
|
290
|
4275
|
100
|
|
|
|
14622
|
$params and $eval->params($params); |
291
|
4275
|
50
|
|
|
|
8937
|
$self->verify_columns( $data, $eval, $all_cols ) if ( scalar( $self->columns() ) ); |
292
|
4275
|
50
|
|
|
|
9113
|
return if ( $self->{errstr} ); |
293
|
|
|
|
|
|
|
|
294
|
4275
|
|
|
|
|
9246
|
my ($table) = $eval->table( $self->tables(0)->name() ); |
295
|
4275
|
50
|
|
|
|
11953
|
$table->seek( $data, 0, 2 ) unless ( $table->capability('insert_new_row') ); |
296
|
|
|
|
|
|
|
|
297
|
4275
|
|
|
|
|
7110
|
my ( $val, $col, $i, $k ); |
298
|
4275
|
|
|
|
|
8831
|
my ($cNum) = scalar( $self->columns() ); |
299
|
4275
|
|
|
|
|
6282
|
my $param_num = 0; |
300
|
|
|
|
|
|
|
|
301
|
4275
|
50
|
|
|
|
8201
|
$cNum |
302
|
|
|
|
|
|
|
or return $self->do_err("Bad col names in INSERT"); |
303
|
|
|
|
|
|
|
|
304
|
4275
|
|
|
|
|
6682
|
my $maxCol = $#$all_cols; |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
# INSERT INTO $table (row, ...) VALUES (value, ...), (...) |
307
|
4275
|
|
|
|
|
7237
|
for ( $k = 0; $k < scalar( @{ $self->{values} } ); ++$k ) |
|
8555
|
|
|
|
|
19708
|
|
308
|
|
|
|
|
|
|
{ |
309
|
4280
|
|
|
|
|
7526
|
my ($array) = []; |
310
|
4280
|
|
|
|
|
9114
|
for ( $i = 0; $i < $cNum; $i++ ) |
311
|
|
|
|
|
|
|
{ |
312
|
12791
|
|
|
|
|
23064
|
$col = $self->columns($i); |
313
|
12791
|
|
|
|
|
25348
|
$val = $self->row_values( $k, $i ); |
314
|
12791
|
50
|
66
|
|
|
60067
|
if ( defined( _INSTANCE( $val, 'SQL::Statement::Param' ) ) ) |
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
315
|
|
|
|
|
|
|
{ |
316
|
0
|
|
|
|
|
0
|
$val = $eval->param( $val->idx() ); |
317
|
|
|
|
|
|
|
} |
318
|
|
|
|
|
|
|
elsif ( defined( _INSTANCE( $val, 'SQL::Statement::Term' ) ) ) |
319
|
|
|
|
|
|
|
{ |
320
|
0
|
|
|
|
|
0
|
$val = $val->value($eval); |
321
|
|
|
|
|
|
|
} |
322
|
|
|
|
|
|
|
elsif ( $val and $val->{type} eq 'placeholder' ) |
323
|
|
|
|
|
|
|
{ |
324
|
12242
|
|
|
|
|
31132
|
$val = $eval->param( $param_num++ ); |
325
|
|
|
|
|
|
|
} |
326
|
|
|
|
|
|
|
elsif ( defined( _HASH($val) ) ) |
327
|
|
|
|
|
|
|
{ |
328
|
549
|
|
|
|
|
1577
|
$val = $self->{termFactory}->buildCondition($val); |
329
|
549
|
|
|
|
|
1215
|
$val = $val->value($eval); |
330
|
|
|
|
|
|
|
} |
331
|
|
|
|
|
|
|
else |
332
|
|
|
|
|
|
|
{ |
333
|
0
|
|
|
|
|
0
|
return $self->do_err('Internal error: Unexpected column type'); |
334
|
|
|
|
|
|
|
} |
335
|
12791
|
|
|
|
|
30947
|
$array->[ $table->column_num( $col->name() ) ] = $val; |
336
|
|
|
|
|
|
|
} |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
# Extend row to put values in ALL fields |
339
|
4280
|
50
|
|
|
|
9132
|
$#$array < $maxCol and $array->[$maxCol] = undef; |
340
|
|
|
|
|
|
|
|
341
|
4280
|
50
|
|
|
|
9369
|
$table->capability('insert_new_row') |
342
|
|
|
|
|
|
|
? $table->insert_new_row( $data, $array ) |
343
|
|
|
|
|
|
|
: $table->push_row( $data, $array ); |
344
|
|
|
|
|
|
|
} |
345
|
|
|
|
|
|
|
|
346
|
4275
|
|
|
|
|
18108
|
return ( $k, 0 ); |
347
|
|
|
|
|
|
|
} |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
sub DELETE ($$$) |
350
|
|
|
|
|
|
|
{ |
351
|
6
|
|
|
6
|
|
17
|
my ( $self, $data, $params ) = @_; |
352
|
6
|
|
|
|
|
19
|
my ( $eval, $all_cols ) = $self->open_tables( $data, 0, 1 ); |
353
|
6
|
50
|
|
|
|
36
|
return unless $eval; |
354
|
6
|
|
|
|
|
35
|
$eval->params($params); |
355
|
6
|
|
|
|
|
26
|
$self->verify_columns( $data, $eval, $all_cols ); |
356
|
6
|
50
|
|
|
|
25
|
return if ( $self->{errstr} ); |
357
|
6
|
|
|
|
|
17
|
my $tname = $self->tables(0)->name(); |
358
|
6
|
|
|
|
|
24
|
my ($table) = $eval->table($tname); |
359
|
6
|
|
|
|
|
9
|
my $affected = 0; |
360
|
6
|
|
|
|
|
12
|
my ( @rows, $array ); |
361
|
|
|
|
|
|
|
|
362
|
6
|
|
|
|
|
26
|
while ( $array = $table->fetch_row($data) ) |
363
|
|
|
|
|
|
|
{ |
364
|
29
|
100
|
|
|
|
72
|
if ( $self->eval_where( $eval, $tname, $array ) ) |
365
|
|
|
|
|
|
|
{ |
366
|
10
|
|
|
|
|
16
|
++$affected; |
367
|
10
|
50
|
33
|
|
|
48
|
if ( $table->capability('rowwise_delete') and $table->capability('inplace_delete') ) |
|
|
0
|
|
|
|
|
|
368
|
|
|
|
|
|
|
{ |
369
|
10
|
50
|
|
|
|
26
|
if ( $table->capability('delete_one_row') ) |
|
|
50
|
|
|
|
|
|
370
|
|
|
|
|
|
|
{ |
371
|
0
|
|
|
|
|
0
|
$table->delete_one_row( $data, $array ); |
372
|
|
|
|
|
|
|
} |
373
|
|
|
|
|
|
|
elsif ( $table->capability('delete_current_row') ) |
374
|
|
|
|
|
|
|
{ |
375
|
10
|
|
|
|
|
29
|
$table->delete_current_row( $data, $array ); |
376
|
|
|
|
|
|
|
} |
377
|
|
|
|
|
|
|
} |
378
|
|
|
|
|
|
|
elsif ( $table->capability('rowwise_delete') ) |
379
|
|
|
|
|
|
|
{ |
380
|
0
|
|
|
|
|
0
|
push( @rows, $array ); |
381
|
|
|
|
|
|
|
} |
382
|
|
|
|
|
|
|
|
383
|
10
|
|
|
|
|
32
|
next; |
384
|
|
|
|
|
|
|
} |
385
|
|
|
|
|
|
|
|
386
|
19
|
50
|
|
|
|
49
|
push( @rows, $array ) unless ( $table->capability('rowwise_delete') ); |
387
|
|
|
|
|
|
|
} |
388
|
|
|
|
|
|
|
|
389
|
6
|
50
|
|
|
|
19
|
if ($affected) |
390
|
|
|
|
|
|
|
{ |
391
|
6
|
50
|
|
|
|
16
|
if ( $table->capability('rowwise_delete') ) |
392
|
|
|
|
|
|
|
{ # @rows is empty in case of inplace_delete capability |
393
|
6
|
|
|
|
|
18
|
foreach my $array (@rows) |
394
|
|
|
|
|
|
|
{ |
395
|
0
|
|
|
|
|
0
|
$table->delete_one_row( $data, $array ); |
396
|
|
|
|
|
|
|
} |
397
|
|
|
|
|
|
|
} |
398
|
|
|
|
|
|
|
else |
399
|
|
|
|
|
|
|
{ |
400
|
|
|
|
|
|
|
# rewrite table without deleted elements |
401
|
0
|
|
|
|
|
0
|
$table->seek( $data, 0, 0 ); |
402
|
0
|
|
|
|
|
0
|
foreach my $array (@rows) |
403
|
|
|
|
|
|
|
{ |
404
|
0
|
|
|
|
|
0
|
$table->push_row( $data, $array ); |
405
|
|
|
|
|
|
|
} |
406
|
0
|
|
|
|
|
0
|
$table->truncate($data); |
407
|
|
|
|
|
|
|
} |
408
|
|
|
|
|
|
|
} |
409
|
|
|
|
|
|
|
|
410
|
6
|
|
|
|
|
44
|
return ( $affected, 0 ); |
411
|
|
|
|
|
|
|
} |
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
sub UPDATE ($$$) |
414
|
|
|
|
|
|
|
{ |
415
|
5
|
|
|
5
|
0
|
15
|
my ( $self, $data, $params ) = @_; |
416
|
|
|
|
|
|
|
|
417
|
5
|
|
|
|
|
19
|
my ( $eval, $all_cols ) = $self->open_tables( $data, 0, 1 ); |
418
|
5
|
50
|
|
|
|
23
|
return unless $eval; |
419
|
|
|
|
|
|
|
|
420
|
5
|
|
|
|
|
15
|
my $valnum = $self->{num_val_placeholders}; |
421
|
5
|
100
|
|
|
|
17
|
my @val_params = splice( @{$params}, 0, $valnum ) if ($valnum); |
|
3
|
|
|
|
|
8
|
|
422
|
5
|
|
33
|
|
|
27
|
$self->{params} ||= $params; |
423
|
5
|
|
|
|
|
25
|
$eval->params($params); |
424
|
5
|
|
|
|
|
19
|
$self->verify_columns( $data, $eval, $all_cols ); |
425
|
5
|
50
|
|
|
|
19
|
return if ( $self->{errstr} ); |
426
|
|
|
|
|
|
|
|
427
|
5
|
|
|
|
|
18
|
my $tname = $self->tables(0)->name(); |
428
|
5
|
|
|
|
|
20
|
my ($table) = $eval->table($tname); |
429
|
5
|
|
|
|
|
8
|
my $affected = 0; |
430
|
5
|
|
|
|
|
12
|
my @rows; |
431
|
|
|
|
|
|
|
|
432
|
5
|
|
|
|
|
23
|
while ( my $array = $table->fetch_row($data) ) |
433
|
|
|
|
|
|
|
{ |
434
|
21
|
|
|
|
|
38
|
my $originalValues; |
435
|
21
|
100
|
|
|
|
54
|
if ( $self->eval_where( $eval, $tname, $array ) ) |
436
|
|
|
|
|
|
|
{ |
437
|
7
|
|
|
|
|
15
|
my $valpos = 0; |
438
|
7
|
50
|
|
|
|
22
|
if ( $table->capability('update_specific_row') ) |
439
|
|
|
|
|
|
|
{ |
440
|
0
|
|
|
|
|
0
|
$originalValues = clone($array); |
441
|
|
|
|
|
|
|
} |
442
|
|
|
|
|
|
|
|
443
|
7
|
|
|
|
|
27
|
for ( my $i = 0; $i < $self->columns(); $i++ ) |
444
|
|
|
|
|
|
|
{ |
445
|
9
|
|
|
|
|
27
|
my $val = $self->row_values( 0, $i ); |
446
|
9
|
50
|
66
|
|
|
101
|
if ( defined( _INSTANCE( $val, 'SQL::Statement::Param' ) ) ) |
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
447
|
|
|
|
|
|
|
{ |
448
|
0
|
|
|
|
|
0
|
$val = $val_params[ $valpos++ ]; |
449
|
|
|
|
|
|
|
} |
450
|
|
|
|
|
|
|
elsif ( defined( _INSTANCE( $val, 'SQL::Statement::Term' ) ) ) |
451
|
|
|
|
|
|
|
{ |
452
|
0
|
|
|
|
|
0
|
$val = $val->value($eval); |
453
|
|
|
|
|
|
|
} |
454
|
|
|
|
|
|
|
elsif ( $val and $val->{type} eq 'placeholder' ) |
455
|
|
|
|
|
|
|
{ |
456
|
6
|
|
|
|
|
18
|
$val = $val_params[ $valpos++ ]; |
457
|
|
|
|
|
|
|
} |
458
|
|
|
|
|
|
|
elsif ( defined( _HASH($val) ) ) |
459
|
|
|
|
|
|
|
{ |
460
|
3
|
|
|
|
|
14
|
$val = $self->{termFactory}->buildCondition($val); |
461
|
3
|
|
|
|
|
24
|
$val = $val->value($eval); |
462
|
|
|
|
|
|
|
} |
463
|
|
|
|
|
|
|
else |
464
|
|
|
|
|
|
|
{ |
465
|
0
|
|
|
|
|
0
|
return $self->do_err('Internal error: Unexpected column type'); |
466
|
|
|
|
|
|
|
} |
467
|
|
|
|
|
|
|
|
468
|
9
|
|
|
|
|
21
|
my $col = $self->columns($i); |
469
|
9
|
|
|
|
|
36
|
$array->[ $table->column_num( $col->name() ) ] = $val; |
470
|
|
|
|
|
|
|
} |
471
|
|
|
|
|
|
|
|
472
|
7
|
|
|
|
|
14
|
++$affected; |
473
|
7
|
50
|
33
|
|
|
23
|
if ( $table->capability('rowwise_update') and $table->capability('inplace_update') ) |
|
|
0
|
|
|
|
|
|
474
|
|
|
|
|
|
|
{ |
475
|
|
|
|
|
|
|
# Martin Fabiani : |
476
|
|
|
|
|
|
|
# the following block is the most important enhancement to SQL::Statement::UPDATE |
477
|
7
|
50
|
|
|
|
34
|
if ( $table->capability('update_specific_row') ) |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
478
|
|
|
|
|
|
|
{ |
479
|
0
|
|
|
|
|
0
|
$table->update_specific_row( $data, $array, $originalValues ); |
480
|
|
|
|
|
|
|
} |
481
|
|
|
|
|
|
|
elsif ( $table->capability('update_one_row') ) |
482
|
|
|
|
|
|
|
{ |
483
|
|
|
|
|
|
|
# NOTE: this prevents from updating index keys |
484
|
0
|
|
|
|
|
0
|
$table->update_one_row( $data, $array ); |
485
|
|
|
|
|
|
|
} |
486
|
|
|
|
|
|
|
elsif ( $table->capability('update_current_row') ) |
487
|
|
|
|
|
|
|
{ |
488
|
7
|
|
|
|
|
27
|
$table->update_current_row( $data, $array ); |
489
|
|
|
|
|
|
|
} |
490
|
|
|
|
|
|
|
} |
491
|
|
|
|
|
|
|
elsif ( $table->capability('rowwise_update') ) |
492
|
|
|
|
|
|
|
{ |
493
|
0
|
0
|
|
|
|
0
|
push( @rows, $array ) unless ( $table->capability('update_specific_row') ); |
494
|
0
|
0
|
|
|
|
0
|
push( @rows, [ $array, $originalValues ] ) |
495
|
|
|
|
|
|
|
if ( $table->capability('update_specific_row') ); |
496
|
|
|
|
|
|
|
} |
497
|
|
|
|
|
|
|
} |
498
|
|
|
|
|
|
|
|
499
|
21
|
50
|
|
|
|
56
|
push( @rows, $array ) unless ( $table->capability('rowwise_update') ); |
500
|
|
|
|
|
|
|
} |
501
|
|
|
|
|
|
|
|
502
|
5
|
50
|
|
|
|
22
|
if ($affected) |
503
|
|
|
|
|
|
|
{ |
504
|
5
|
50
|
|
|
|
15
|
if ( $table->capability('rowwise_update') ) |
505
|
|
|
|
|
|
|
{ # @rows is empty in case of inplace_update capability |
506
|
5
|
|
|
|
|
17
|
foreach my $array (@rows) |
507
|
|
|
|
|
|
|
{ |
508
|
0
|
0
|
|
|
|
0
|
if ( $table->capability('update_specific_row') ) |
|
|
0
|
|
|
|
|
|
509
|
|
|
|
|
|
|
{ |
510
|
0
|
|
|
|
|
0
|
$table->update_specific_row( $data, $array->[0], $array->[1] ); |
511
|
|
|
|
|
|
|
} |
512
|
|
|
|
|
|
|
elsif ( $table->capability('update_one_row') ) |
513
|
|
|
|
|
|
|
{ |
514
|
0
|
|
|
|
|
0
|
$table->update_one_row( $data, $array ); |
515
|
|
|
|
|
|
|
} |
516
|
|
|
|
|
|
|
} |
517
|
|
|
|
|
|
|
} |
518
|
|
|
|
|
|
|
else |
519
|
|
|
|
|
|
|
{ |
520
|
|
|
|
|
|
|
# rewrite table with updated elements |
521
|
0
|
|
|
|
|
0
|
$table->seek( $data, 0, 0 ); |
522
|
0
|
|
|
|
|
0
|
foreach my $array (@rows) |
523
|
|
|
|
|
|
|
{ |
524
|
0
|
|
|
|
|
0
|
$table->push_row( $data, $array ); |
525
|
|
|
|
|
|
|
} |
526
|
0
|
|
|
|
|
0
|
$table->truncate($data); |
527
|
|
|
|
|
|
|
} |
528
|
|
|
|
|
|
|
} |
529
|
|
|
|
|
|
|
|
530
|
5
|
|
|
|
|
34
|
return ( $affected, 0 ); |
531
|
|
|
|
|
|
|
} |
532
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
sub find_join_columns |
534
|
|
|
|
|
|
|
{ |
535
|
32
|
|
|
32
|
1
|
93
|
my ( $self, @all_cols ) = @_; |
536
|
32
|
|
|
|
|
60
|
my $display_combine = 'NAMED'; |
537
|
32
|
100
|
|
|
|
99
|
$display_combine = 'NATURAL' if ( -1 != index( $self->{join}->{type}, 'NATURAL' ) ); |
538
|
32
|
100
|
|
|
|
88
|
$display_combine = 'USING' if ( -1 != index( $self->{join}->{clause}, 'USING' ) ); |
539
|
32
|
|
|
|
|
46
|
my @display_cols; |
540
|
32
|
|
|
|
|
58
|
my @keycols = (); |
541
|
25
|
|
|
|
|
64
|
@keycols = @{ $self->{join}->{keycols} } |
542
|
32
|
100
|
|
|
|
82
|
if $self->{join}->{keycols}; |
543
|
32
|
|
|
|
|
68
|
foreach (@keycols) { $_ =~ s/\./$self->{dlm}/ } |
|
57
|
|
|
|
|
205
|
|
544
|
32
|
|
|
|
|
51
|
my %is_key_col; |
545
|
32
|
|
|
|
|
66
|
%is_key_col = map { $_ => 1 } @keycols; |
|
57
|
|
|
|
|
308
|
|
546
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
# IF NAMED COLUMNS, USE NAMED COLUMNS |
548
|
|
|
|
|
|
|
# |
549
|
32
|
100
|
|
|
|
103
|
if ( $display_combine eq 'NAMED' ) |
|
|
50
|
|
|
|
|
|
550
|
|
|
|
|
|
|
{ |
551
|
16
|
|
|
|
|
45
|
@display_cols = $self->columns(); |
552
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
# |
554
|
|
|
|
|
|
|
# DAA |
555
|
|
|
|
|
|
|
# need to get to $self's table objects to get the name |
556
|
|
|
|
|
|
|
# |
557
|
|
|
|
|
|
|
# @display_cols = map {$_->table . $self->{dlm} . $_->name} @display_cols; |
558
|
|
|
|
|
|
|
# @display_cols = map {$_->table->{NAME} . $self->{dlm} . $_->name} @display_cols; |
559
|
|
|
|
|
|
|
|
560
|
16
|
|
|
|
|
42
|
my @tbls = $self->tables(); |
561
|
16
|
|
|
|
|
38
|
my %tables = (); |
562
|
|
|
|
|
|
|
|
563
|
16
|
|
|
|
|
53
|
$tables{ $_->name() } = $_ foreach (@tbls); |
564
|
|
|
|
|
|
|
|
565
|
16
|
|
|
|
|
178
|
foreach ( 0 .. $#display_cols ) |
566
|
|
|
|
|
|
|
{ |
567
|
|
|
|
|
|
|
$display_cols[$_] = ( |
568
|
|
|
|
|
|
|
$display_cols[$_]->table() |
569
|
|
|
|
|
|
|
? $tables{ $display_cols[$_]->table() }->name() |
570
|
|
|
|
|
|
|
: '' |
571
|
|
|
|
|
|
|
) |
572
|
|
|
|
|
|
|
. $self->{dlm} |
573
|
72
|
100
|
|
|
|
167
|
. $display_cols[$_]->name(); |
574
|
|
|
|
|
|
|
} |
575
|
|
|
|
|
|
|
} |
576
|
|
|
|
|
|
|
|
577
|
|
|
|
|
|
|
# IF ASTERISKED COLUMNS AND NOT NATURAL OR USING |
578
|
|
|
|
|
|
|
# USE ALL COLUMNS, IN ORDER OF NAMING OF TABLES |
579
|
|
|
|
|
|
|
# |
580
|
|
|
|
|
|
|
elsif ( $display_combine eq 'NONE' ) |
581
|
|
|
|
|
|
|
{ |
582
|
0
|
|
|
|
|
0
|
@display_cols = @all_cols; |
583
|
|
|
|
|
|
|
} |
584
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
# IF NATURAL, COMBINE ALL SHARED COLUMNS |
586
|
|
|
|
|
|
|
# IF USING, COMBINE ALL KEY COLUMNS |
587
|
|
|
|
|
|
|
# |
588
|
|
|
|
|
|
|
else |
589
|
|
|
|
|
|
|
{ |
590
|
16
|
|
|
|
|
24
|
my %is_natural; |
591
|
16
|
|
|
|
|
26
|
for my $full_col (@all_cols) |
592
|
|
|
|
|
|
|
{ |
593
|
64
|
|
|
|
|
422
|
my ( $table, $col ) = $full_col =~ m/^([^$self->{dlm}]+)$self->{dlm}(.+)$/; |
594
|
64
|
100
|
100
|
|
|
196
|
next if ( ( $display_combine eq 'NATURAL' ) and $is_natural{$col} ); |
595
|
58
|
50
|
100
|
|
|
195
|
next if ( ( $display_combine eq 'USING' ) && $is_natural{$col} && $is_key_col{$col} ); |
|
|
|
66
|
|
|
|
|
596
|
48
|
|
|
|
|
74
|
push( @display_cols, $full_col ); |
597
|
48
|
|
|
|
|
97
|
$is_natural{$col}++; |
598
|
|
|
|
|
|
|
} |
599
|
|
|
|
|
|
|
} |
600
|
32
|
|
|
|
|
67
|
my @shared = (); |
601
|
32
|
|
|
|
|
50
|
my %is_shared; |
602
|
32
|
100
|
|
|
|
115
|
if ( $self->{join}->{type} =~ m/NATURAL/ ) |
603
|
|
|
|
|
|
|
{ |
604
|
6
|
|
|
|
|
14
|
for my $full_col (@all_cols) |
605
|
|
|
|
|
|
|
{ |
606
|
24
|
|
|
|
|
123
|
my ( $table, $col ) = $full_col =~ m/^([^$self->{dlm}]+)$self->{dlm}(.+)$/; |
607
|
24
|
100
|
|
|
|
78
|
push( @shared, $col ) if ( $is_shared{$col}++ ); # using side-effect of post-inc |
608
|
|
|
|
|
|
|
} |
609
|
|
|
|
|
|
|
} |
610
|
|
|
|
|
|
|
else |
611
|
|
|
|
|
|
|
{ |
612
|
26
|
|
|
|
|
68
|
@shared = @keycols; |
613
|
|
|
|
|
|
|
} |
614
|
32
|
|
|
|
|
79
|
$self->{join}->{shared_cols} = \@shared; |
615
|
32
|
|
|
|
|
114
|
$self->{join}->{display_cols} = \@display_cols; |
616
|
|
|
|
|
|
|
} |
617
|
|
|
|
|
|
|
|
618
|
|
|
|
|
|
|
sub JOIN |
619
|
|
|
|
|
|
|
{ |
620
|
34
|
|
|
34
|
0
|
63
|
my ( $self, $data, $params ) = @_; |
621
|
|
|
|
|
|
|
|
622
|
34
|
|
|
|
|
97
|
my ( $eval, $all_cols ) = $self->open_tables( $data, 0, 0 ); |
623
|
34
|
50
|
|
|
|
122
|
return undef unless $eval; |
624
|
34
|
|
|
|
|
135
|
$eval->params($params); |
625
|
34
|
|
|
|
|
123
|
$self->verify_columns( $data, $eval, $all_cols ); |
626
|
34
|
100
|
|
|
|
108
|
return if ( $self->{errstr} ); |
627
|
32
|
100
|
100
|
|
|
149
|
if ( $self->{join}->{keycols} |
|
|
|
100
|
|
|
|
|
628
|
|
|
|
|
|
|
and $self->{join}->{table_order} |
629
|
15
|
|
|
|
|
59
|
and ( scalar( @{ $self->{join}->{table_order} } ) == 0 ) ) |
630
|
|
|
|
|
|
|
{ |
631
|
7
|
|
|
|
|
24
|
$self->{join}->{table_order} = $self->order_joins( $self->{join}->{keycols} ); |
632
|
|
|
|
|
|
|
$self->{join}->{table_order} = $self->{table_names} |
633
|
7
|
50
|
|
|
|
26
|
unless ( defined( $self->{join}->{table_order} ) ); |
634
|
|
|
|
|
|
|
} |
635
|
32
|
|
|
|
|
80
|
my @tables = $self->tables; |
636
|
|
|
|
|
|
|
|
637
|
|
|
|
|
|
|
# GET THE LIST OF QUALIFIED COLUMN NAMES FOR DISPLAY |
638
|
|
|
|
|
|
|
# *IN ORDER BY NAMING OF TABLES* |
639
|
|
|
|
|
|
|
# |
640
|
32
|
|
|
|
|
51
|
my @all_cols; |
641
|
32
|
|
|
|
|
61
|
for my $table (@tables) |
642
|
|
|
|
|
|
|
{ |
643
|
76
|
|
|
|
|
104
|
my @cols = @{ $eval->table( $table->{name} )->col_names }; |
|
76
|
|
|
|
|
203
|
|
644
|
76
|
|
|
|
|
129
|
for my $col (@cols) |
645
|
|
|
|
|
|
|
{ |
646
|
204
|
|
|
|
|
487
|
push( @all_cols, $table->{name} . $self->{dlm} . $col ); |
647
|
|
|
|
|
|
|
} |
648
|
|
|
|
|
|
|
} |
649
|
32
|
|
|
|
|
121
|
$self->find_join_columns(@all_cols); |
650
|
|
|
|
|
|
|
|
651
|
|
|
|
|
|
|
# JOIN THE TABLES |
652
|
|
|
|
|
|
|
# *IN ORDER *BY JOINS* |
653
|
|
|
|
|
|
|
# |
654
|
32
|
100
|
|
|
|
86
|
@tables = @{ $self->{join}->{table_order} } if ( $self->{join}->{table_order} ); |
|
15
|
|
|
|
|
51
|
|
655
|
32
|
|
|
|
|
90
|
my ( $tableA, $tableB ) = splice( @tables, 0, 2 ); |
656
|
32
|
100
|
|
|
|
93
|
$tableA = $tableA->{name} if ( ref($tableA) ); |
657
|
32
|
100
|
|
|
|
76
|
$tableB = $tableB->{name} if ( ref($tableB) ); |
658
|
32
|
|
|
|
|
91
|
my ( $tableAobj, $tableBobj ) = ( $eval->table($tableA), $eval->table($tableB) ); |
659
|
32
|
|
33
|
|
|
84
|
$tableAobj->{NAME} ||= $tableA; |
660
|
32
|
|
33
|
|
|
86
|
$tableBobj->{NAME} ||= $tableB; |
661
|
32
|
|
|
|
|
100
|
$self->join_2_tables( $data, $params, $tableAobj, $tableBobj ); |
662
|
|
|
|
|
|
|
|
663
|
32
|
|
|
|
|
81
|
for my $next_table (@tables) |
664
|
|
|
|
|
|
|
{ |
665
|
12
|
|
|
|
|
118
|
$tableAobj = $self->{join}->{table}; |
666
|
12
|
|
|
|
|
39
|
$tableBobj = $eval->table($next_table); |
667
|
12
|
|
33
|
|
|
40
|
$tableBobj->{NAME} ||= $next_table; |
668
|
12
|
|
|
|
|
37
|
$self->join_2_tables( $data, $params, $tableAobj, $tableBobj ); |
669
|
12
|
|
|
|
|
41
|
$self->{cur_table} = $next_table; |
670
|
|
|
|
|
|
|
} |
671
|
32
|
|
|
|
|
154
|
return $self->SELECT( $data, $params ); |
672
|
|
|
|
|
|
|
} |
673
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
sub join_2_tables |
675
|
|
|
|
|
|
|
{ |
676
|
44
|
|
|
44
|
1
|
97
|
my ( $self, $data, $params, $tableAobj, $tableBobj ) = @_; |
677
|
44
|
|
|
|
|
72
|
my $share_type = 'IMPLICIT'; |
678
|
44
|
100
|
|
|
|
123
|
$share_type = 'NATURAL' if ( -1 != index( $self->{join}->{type}, 'NATURAL' ) ); |
679
|
44
|
100
|
|
|
|
107
|
$share_type = 'USING' if ( -1 != index( $self->{join}->{clause}, 'USING' ) ); |
680
|
44
|
100
|
|
|
|
111
|
$share_type = 'ON' if ( -1 != index( $self->{join}->{clause}, 'ON' ) ); |
681
|
|
|
|
|
|
|
$share_type = 'USING' |
682
|
44
|
100
|
66
|
|
|
112
|
if ( ( $share_type eq 'ON' ) && ( scalar( @{ $self->{join}->{keycols} } ) == 1 ) ); |
|
7
|
|
|
|
|
26
|
|
683
|
44
|
|
|
|
|
63
|
my $join_type = 'INNER'; |
684
|
44
|
100
|
|
|
|
105
|
$join_type = 'LEFT' if ( -1 != index( $self->{join}->{type}, 'LEFT' ) ); |
685
|
44
|
100
|
|
|
|
100
|
$join_type = 'RIGHT' if ( -1 != index( $self->{join}->{type}, 'RIGHT' ) ); |
686
|
44
|
100
|
|
|
|
95
|
$join_type = 'FULL' if ( -1 != index( $self->{join}->{type}, 'FULL' ) ); |
687
|
|
|
|
|
|
|
|
688
|
44
|
|
|
|
|
71
|
my $right_join = $join_type eq 'RIGHT'; |
689
|
44
|
100
|
|
|
|
82
|
if ($right_join) |
690
|
|
|
|
|
|
|
{ |
691
|
3
|
|
|
|
|
7
|
my $tmpTbl = $tableAobj; |
692
|
3
|
|
|
|
|
7
|
$tableAobj = $tableBobj; |
693
|
3
|
|
|
|
|
5
|
$tableBobj = $tmpTbl; |
694
|
|
|
|
|
|
|
} |
695
|
|
|
|
|
|
|
|
696
|
44
|
|
|
|
|
99
|
my $tableA = $tableAobj->{NAME}; |
697
|
44
|
50
|
|
|
|
115
|
( 0 != index( $tableA, '"' ) ) and $tableA = lc $tableA; |
698
|
44
|
|
|
|
|
65
|
my $tableB = $tableBobj->{NAME}; |
699
|
44
|
50
|
|
|
|
101
|
( 0 != index( $tableB, '"' ) ) and $tableB = lc $tableB; |
700
|
44
|
|
|
|
|
68
|
my @colsA = @{ $tableAobj->col_names() }; |
|
44
|
|
|
|
|
132
|
|
701
|
44
|
|
|
|
|
71
|
my @colsB = @{ $tableBobj->col_names() }; |
|
44
|
|
|
|
|
87
|
|
702
|
44
|
|
|
|
|
86
|
my ( %isunqualA, %isunqualB, @shared_cols ); |
703
|
44
|
|
|
|
|
197
|
$isunqualB{ $colsB[$_] } = 1 for ( 0 .. $#colsB ); |
704
|
44
|
|
|
|
|
77
|
my @tmpshared = @{ $self->{join}->{shared_cols} }; |
|
44
|
|
|
|
|
115
|
|
705
|
|
|
|
|
|
|
|
706
|
44
|
50
|
|
|
|
147
|
if ( $share_type eq 'ON' ) |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
707
|
|
|
|
|
|
|
{ |
708
|
0
|
0
|
|
|
|
0
|
$right_join and @tmpshared = reverse @tmpshared; |
709
|
|
|
|
|
|
|
} |
710
|
|
|
|
|
|
|
elsif ( $share_type eq 'USING' ) |
711
|
|
|
|
|
|
|
{ |
712
|
17
|
|
|
|
|
34
|
foreach my $c (@tmpshared) |
713
|
|
|
|
|
|
|
{ |
714
|
17
|
|
|
|
|
49
|
substr( $c, 0, index( $c, $self->{dlm} ) + 1 ) = ''; |
715
|
17
|
|
|
|
|
43
|
push( @shared_cols, $tableA . $self->{dlm} . $c ); |
716
|
17
|
|
|
|
|
38
|
push( @shared_cols, $tableB . $self->{dlm} . $c ); |
717
|
|
|
|
|
|
|
} |
718
|
|
|
|
|
|
|
} |
719
|
|
|
|
|
|
|
elsif ( $share_type eq 'NATURAL' ) |
720
|
|
|
|
|
|
|
{ |
721
|
6
|
|
|
|
|
13
|
for my $c (@colsA) |
722
|
|
|
|
|
|
|
{ |
723
|
12
|
50
|
|
|
|
33
|
if ( $tableA eq $self->{dlm} . 'tmp' ) |
724
|
|
|
|
|
|
|
{ |
725
|
0
|
|
|
|
|
0
|
substr( $c, 0, index( $c, $self->{dlm} ) + 1 ) = ''; |
726
|
|
|
|
|
|
|
} |
727
|
12
|
100
|
|
|
|
25
|
if ( $isunqualB{$c} ) |
728
|
|
|
|
|
|
|
{ |
729
|
6
|
|
|
|
|
16
|
push( @shared_cols, $tableA . $self->{dlm} . $c ); |
730
|
6
|
|
|
|
|
19
|
push( @shared_cols, $tableB . $self->{dlm} . $c ); |
731
|
|
|
|
|
|
|
} |
732
|
|
|
|
|
|
|
} |
733
|
|
|
|
|
|
|
} |
734
|
|
|
|
|
|
|
|
735
|
44
|
|
|
|
|
72
|
my %whichqual; |
736
|
44
|
100
|
66
|
|
|
183
|
if ( $share_type eq 'ON' || $share_type eq 'IMPLICIT' ) |
737
|
|
|
|
|
|
|
{ |
738
|
21
|
|
|
|
|
40
|
foreach my $colb (@colsB) |
739
|
|
|
|
|
|
|
{ |
740
|
77
|
|
|
|
|
198
|
$colb = $whichqual{$colb} = $tableB . $self->{dlm} . $colb; |
741
|
|
|
|
|
|
|
} |
742
|
|
|
|
|
|
|
} |
743
|
|
|
|
|
|
|
else |
744
|
|
|
|
|
|
|
{ |
745
|
23
|
|
|
|
|
50
|
@colsB = map { $tableB . $self->{dlm} . $_ } @colsB; |
|
46
|
|
|
|
|
132
|
|
746
|
|
|
|
|
|
|
} |
747
|
|
|
|
|
|
|
|
748
|
44
|
|
|
|
|
88
|
my @all_cols = map { $tableA . $self->{dlm} . $_ } @colsA; |
|
220
|
|
|
|
|
433
|
|
749
|
44
|
100
|
|
|
|
165
|
@all_cols = $right_join ? ( @colsB, @all_cols ) : ( @all_cols, @colsB ); |
750
|
|
|
|
|
|
|
{ |
751
|
44
|
|
|
|
|
62
|
my $str = $self->{dlm} . "tmp" . $self->{dlm}; |
|
44
|
|
|
|
|
96
|
|
752
|
44
|
|
|
|
|
78
|
foreach (@all_cols) |
753
|
|
|
|
|
|
|
{ |
754
|
343
|
|
|
|
|
505
|
my $pos = index( $_, $str ); |
755
|
343
|
100
|
|
|
|
656
|
$pos >= 0 and substr( $_, $pos, length($str) ) = ''; |
756
|
|
|
|
|
|
|
} |
757
|
|
|
|
|
|
|
} |
758
|
44
|
100
|
|
|
|
109
|
if ( $tableA eq $self->{dlm} . 'tmp' ) |
759
|
|
|
|
|
|
|
{ |
760
|
12
|
|
|
|
|
23
|
foreach my $colA (@colsA) |
761
|
|
|
|
|
|
|
{ |
762
|
139
|
|
|
|
|
250
|
my $c = substr( $colA, index( $colA, $self->{dlm} ) + 1 ); |
763
|
139
|
|
|
|
|
222
|
$isunqualA{$c} = $colA; |
764
|
|
|
|
|
|
|
} |
765
|
|
|
|
|
|
|
#%isunqualA = |
766
|
|
|
|
|
|
|
# map { my ($c) = $_ =~ m/^(?:[^$self->{dlm}]+)$self->{dlm}(.+)$/; $c => $_ } @colsA; |
767
|
|
|
|
|
|
|
} |
768
|
|
|
|
|
|
|
else |
769
|
|
|
|
|
|
|
{ |
770
|
32
|
|
|
|
|
60
|
foreach my $cola (@colsA) |
771
|
|
|
|
|
|
|
{ |
772
|
81
|
|
|
|
|
194
|
$cola = $isunqualA{$cola} = $tableA . $self->{dlm} . $cola; |
773
|
|
|
|
|
|
|
} |
774
|
|
|
|
|
|
|
} |
775
|
|
|
|
|
|
|
|
776
|
44
|
|
|
|
|
73
|
my ( %col_numsA, %col_numsB ); |
777
|
44
|
|
|
|
|
233
|
$col_numsA{ $colsA[$_] } = $_ for ( 0 .. $#colsA ); |
778
|
44
|
|
|
|
|
174
|
$col_numsB{ $colsB[$_] } = $_ for ( 0 .. $#colsB ); |
779
|
|
|
|
|
|
|
|
780
|
44
|
100
|
66
|
|
|
170
|
if ( $share_type eq 'ON' || $share_type eq 'IMPLICIT' ) |
781
|
|
|
|
|
|
|
{ |
782
|
21
|
|
|
|
|
148
|
%whichqual = ( %whichqual, %isunqualA ); |
783
|
|
|
|
|
|
|
|
784
|
21
|
|
|
|
|
112
|
while (@tmpshared) |
785
|
|
|
|
|
|
|
{ |
786
|
62
|
|
|
|
|
139
|
my ( $k1, $k2 ) = splice( @tmpshared, 0, 2 ); |
787
|
|
|
|
|
|
|
|
788
|
|
|
|
|
|
|
# if both keys are in one table, bail out - FIXME: errmsg? |
789
|
62
|
0
|
33
|
|
|
131
|
next if ( $isunqualA{$k1} && $isunqualA{$k2} ); |
790
|
62
|
0
|
33
|
|
|
131
|
next if ( $isunqualB{$k1} && $isunqualB{$k2} ); |
791
|
|
|
|
|
|
|
|
792
|
62
|
50
|
|
|
|
114
|
defined( $whichqual{$k1} ) and $k1 = $whichqual{$k1}; |
793
|
62
|
50
|
|
|
|
119
|
defined( $whichqual{$k2} ) and $k2 = $whichqual{$k2}; |
794
|
|
|
|
|
|
|
|
795
|
62
|
100
|
100
|
|
|
304
|
if ( defined( $col_numsA{$k1} ) && defined( $col_numsB{$k2} ) ) |
|
|
100
|
100
|
|
|
|
|
796
|
|
|
|
|
|
|
{ |
797
|
17
|
|
|
|
|
47
|
push( @shared_cols, $k1, $k2 ); |
798
|
|
|
|
|
|
|
} |
799
|
|
|
|
|
|
|
elsif ( defined( $col_numsA{$k2} ) && defined( $col_numsB{$k1} ) ) |
800
|
|
|
|
|
|
|
{ |
801
|
3
|
|
|
|
|
10
|
push( @shared_cols, $k2, $k1 ); |
802
|
|
|
|
|
|
|
} |
803
|
|
|
|
|
|
|
} |
804
|
|
|
|
|
|
|
} |
805
|
|
|
|
|
|
|
|
806
|
44
|
|
|
|
|
67
|
my %is_shared; |
807
|
44
|
|
|
|
|
73
|
for my $c (@shared_cols) |
808
|
|
|
|
|
|
|
{ |
809
|
86
|
|
|
|
|
147
|
$is_shared{$c} = 1; |
810
|
|
|
|
|
|
|
defined( $col_numsA{$c} ) |
811
|
86
|
50
|
66
|
|
|
328
|
or defined( $col_numsB{$c} ) |
812
|
|
|
|
|
|
|
or return $self->do_err("Can't find shared columns!"); |
813
|
|
|
|
|
|
|
} |
814
|
44
|
|
|
|
|
101
|
my ( $posA, $posB ) = ( [], [] ); |
815
|
44
|
|
|
|
|
85
|
for my $f (@shared_cols) |
816
|
|
|
|
|
|
|
{ |
817
|
86
|
100
|
|
|
|
172
|
defined( $col_numsA{$f} ) and push( @{$posA}, $col_numsA{$f} ); |
|
43
|
|
|
|
|
93
|
|
818
|
86
|
100
|
|
|
|
178
|
defined( $col_numsB{$f} ) and push( @{$posB}, $col_numsB{$f} ); |
|
43
|
|
|
|
|
94
|
|
819
|
|
|
|
|
|
|
} |
820
|
|
|
|
|
|
|
|
821
|
44
|
|
|
|
|
79
|
my $is_inner_join = $join_type eq "INNER"; |
822
|
|
|
|
|
|
|
#use mylibs; zwarn $self->{join}; |
823
|
|
|
|
|
|
|
# CYCLE THROUGH TABLE B, CREATING A HASH OF ITS VALUES |
824
|
|
|
|
|
|
|
# |
825
|
44
|
|
|
|
|
76
|
my $hashB = {}; |
826
|
44
|
|
|
|
|
152
|
TBLBFETCH: while ( my $array = $tableBobj->fetch_row($data) ) |
827
|
|
|
|
|
|
|
{ |
828
|
294
|
|
|
|
|
610
|
my @key_vals = @$array[@$posB]; |
829
|
294
|
100
|
|
|
|
472
|
if ($is_inner_join) |
830
|
|
|
|
|
|
|
{ |
831
|
247
|
|
50
|
|
|
550
|
defined($_) or next TBLBFETCH for (@key_vals); |
832
|
|
|
|
|
|
|
} |
833
|
294
|
|
|
|
|
508
|
my $hashkey = join( ' ', @key_vals ); |
834
|
294
|
|
|
|
|
372
|
push( @{ $hashB->{$hashkey} }, $array ); |
|
294
|
|
|
|
|
971
|
|
835
|
|
|
|
|
|
|
} |
836
|
|
|
|
|
|
|
|
837
|
|
|
|
|
|
|
# CYCLE THROUGH TABLE A |
838
|
|
|
|
|
|
|
# |
839
|
44
|
|
|
|
|
81
|
my $blankRow; |
840
|
44
|
|
|
|
|
74
|
my $joined_table = []; |
841
|
44
|
|
|
|
|
63
|
my %visited; |
842
|
44
|
|
|
|
|
108
|
TBLAFETCH: while ( my $arrayA = $tableAobj->fetch_row($data) ) # use tbl1st & tbl2nd |
843
|
|
|
|
|
|
|
{ |
844
|
355
|
|
|
|
|
710
|
my @key_vals = @$arrayA[@$posA]; |
845
|
355
|
100
|
|
|
|
593
|
if ($is_inner_join) |
846
|
|
|
|
|
|
|
{ |
847
|
311
|
|
50
|
|
|
656
|
defined($_) or next TBLAFETCH for (@key_vals); |
848
|
|
|
|
|
|
|
} |
849
|
355
|
|
|
|
|
536
|
my $hashkey = join( ' ', @key_vals ); |
850
|
355
|
|
|
|
|
539
|
my $rowsB = $hashB->{$hashkey}; |
851
|
355
|
100
|
100
|
|
|
740
|
if ( !defined($rowsB) && ( $join_type ne 'INNER' ) ) |
852
|
|
|
|
|
|
|
{ |
853
|
14
|
50
|
|
|
|
53
|
defined($blankRow) or $blankRow = [ (undef) x scalar(@colsB) ]; |
854
|
14
|
|
|
|
|
31
|
$rowsB = [$blankRow]; |
855
|
|
|
|
|
|
|
} |
856
|
|
|
|
|
|
|
|
857
|
355
|
50
|
|
|
|
640
|
if ( $join_type ne 'UNION' ) |
858
|
|
|
|
|
|
|
{ |
859
|
355
|
|
|
|
|
472
|
for my $arrayB ( @{$rowsB} ) |
|
355
|
|
|
|
|
557
|
|
860
|
|
|
|
|
|
|
{ |
861
|
404
|
100
|
|
|
|
607
|
my $newRow = $right_join ? [ @{$arrayB}, @{$arrayA} ] : [ @{$arrayA}, @{$arrayB} ]; |
|
11
|
|
|
|
|
13
|
|
|
11
|
|
|
|
|
25
|
|
|
393
|
|
|
|
|
540
|
|
|
393
|
|
|
|
|
1476
|
|
862
|
|
|
|
|
|
|
|
863
|
404
|
|
|
|
|
848
|
push( @$joined_table, $newRow ); |
864
|
|
|
|
|
|
|
} |
865
|
|
|
|
|
|
|
} |
866
|
|
|
|
|
|
|
|
867
|
355
|
|
|
|
|
996
|
++$visited{$hashkey}; |
868
|
|
|
|
|
|
|
} |
869
|
|
|
|
|
|
|
|
870
|
|
|
|
|
|
|
# ADD THE LEFTOVER B ROWS IF NEEDED |
871
|
|
|
|
|
|
|
# |
872
|
44
|
100
|
66
|
|
|
185
|
if ( $join_type eq 'FULL' || $join_type eq 'UNION' ) |
873
|
|
|
|
|
|
|
{ |
874
|
|
|
|
|
|
|
my $st_is_NaturalOrUsing = ( -1 != index( $self->{join}->{type}, 'NATURAL' ) ) |
875
|
2
|
|
66
|
|
|
15
|
|| ( -1 != index( $self->{join}->{clause}, 'USING' ) ); |
876
|
2
|
|
|
|
|
7
|
while ( my ( $k, $v ) = each %{$hashB} ) |
|
8
|
|
|
|
|
26
|
|
877
|
|
|
|
|
|
|
{ |
878
|
6
|
100
|
|
|
|
19
|
next if ( $visited{$k} ); |
879
|
2
|
|
|
|
|
6
|
for my $rowB (@$v) |
880
|
|
|
|
|
|
|
{ |
881
|
2
|
|
|
|
|
6
|
my ( @arrayA, @tmpB, $rowhash ); |
882
|
2
|
|
|
|
|
3
|
@{$rowhash}{@colsB} = @{$rowB}; |
|
2
|
|
|
|
|
8
|
|
|
2
|
|
|
|
|
6
|
|
883
|
2
|
|
|
|
|
8
|
for my $c (@all_cols) |
884
|
|
|
|
|
|
|
{ |
885
|
8
|
|
|
|
|
71
|
my ( $table, $col ) = split( $self->{dlm}, $c, 2 ); |
886
|
8
|
100
|
|
|
|
23
|
push( @arrayA, undef ) if ( $table eq $tableA ); |
887
|
8
|
100
|
|
|
|
24
|
push( @tmpB, $rowhash->{$c} ) if ( $table eq $tableB ); |
888
|
|
|
|
|
|
|
} |
889
|
2
|
100
|
|
|
|
8
|
@arrayA[@$posA] = @tmpB[@$posB] if ($st_is_NaturalOrUsing); |
890
|
2
|
|
|
|
|
4
|
my $newRow = [ @arrayA, @tmpB ]; |
891
|
2
|
|
|
|
|
4
|
push( @{$joined_table}, $newRow ); |
|
2
|
|
|
|
|
11
|
|
892
|
|
|
|
|
|
|
} |
893
|
|
|
|
|
|
|
} |
894
|
|
|
|
|
|
|
} |
895
|
|
|
|
|
|
|
|
896
|
44
|
|
|
|
|
209
|
undef $hashB; |
897
|
44
|
|
|
|
|
126
|
undef $tableAobj; |
898
|
44
|
|
|
|
|
63
|
undef $tableBobj; |
899
|
|
|
|
|
|
|
|
900
|
|
|
|
|
|
|
$self->{join}->{table} = |
901
|
44
|
|
|
|
|
215
|
SQL::Statement::TempTable->new( $self->{dlm} . 'tmp', \@all_cols, $self->{join}->{display_cols}, $joined_table ); |
902
|
|
|
|
|
|
|
|
903
|
44
|
|
|
|
|
351
|
return; |
904
|
|
|
|
|
|
|
} |
905
|
|
|
|
|
|
|
|
906
|
|
|
|
|
|
|
sub run_functions |
907
|
|
|
|
|
|
|
{ |
908
|
176
|
|
|
176
|
1
|
347
|
my ( $self, $data, $params ) = @_; |
909
|
176
|
|
|
|
|
426
|
my ( $eval, $all_cols ) = $self->open_tables( $data, 0, 0 ); |
910
|
176
|
|
|
|
|
467
|
my @row = (); |
911
|
176
|
|
|
|
|
434
|
for my $col ( $self->columns() ) |
912
|
|
|
|
|
|
|
{ |
913
|
176
|
|
|
|
|
504
|
my $val = $col->value($eval); # FIXME approve |
914
|
176
|
|
|
|
|
9418
|
push( @row, $val ); |
915
|
|
|
|
|
|
|
} |
916
|
176
|
|
|
|
|
1140
|
return ( 1, scalar @row, [ \@row ] ); |
917
|
|
|
|
|
|
|
} |
918
|
|
|
|
|
|
|
|
919
|
|
|
|
|
|
|
sub SELECT($$) |
920
|
|
|
|
|
|
|
{ |
921
|
348
|
|
|
348
|
0
|
736
|
my ( $self, $data, $params ) = @_; |
922
|
|
|
|
|
|
|
|
923
|
348
|
|
66
|
|
|
943
|
$self->{params} ||= $params; |
924
|
348
|
100
|
|
|
|
1326
|
defined( _ARRAY( $self->{table_names} ) ) or return $self->run_functions( $data, $params ); |
925
|
|
|
|
|
|
|
|
926
|
172
|
|
|
|
|
343
|
my ( $eval, $all_cols, $tableName, $table ); |
927
|
172
|
100
|
|
|
|
456
|
if ( defined( $self->{join} ) ) |
928
|
|
|
|
|
|
|
{ |
929
|
66
|
100
|
|
|
|
216
|
defined $self->{join}->{table} or return $self->JOIN( $data, $params ); |
930
|
32
|
|
|
|
|
63
|
$tableName = $self->{dlm} . 'tmp'; |
931
|
32
|
|
|
|
|
74
|
$table = $self->{join}->{table}; |
932
|
|
|
|
|
|
|
} |
933
|
|
|
|
|
|
|
else |
934
|
|
|
|
|
|
|
{ |
935
|
106
|
|
|
|
|
313
|
( $eval, $all_cols ) = $self->open_tables( $data, 0, 0 ); |
936
|
105
|
100
|
|
|
|
375
|
return unless $eval; |
937
|
104
|
|
|
|
|
429
|
$eval->params($params); |
938
|
104
|
|
|
|
|
380
|
$self->verify_columns( $data, $eval, $all_cols ); |
939
|
104
|
100
|
|
|
|
300
|
return if ( $self->{errstr} ); |
940
|
103
|
|
|
|
|
260
|
$tableName = $self->tables(0)->name(); |
941
|
103
|
|
|
|
|
411
|
$table = $eval->table($tableName); |
942
|
|
|
|
|
|
|
} |
943
|
|
|
|
|
|
|
|
944
|
135
|
|
|
|
|
261
|
my $rows = []; |
945
|
|
|
|
|
|
|
|
946
|
|
|
|
|
|
|
# In a loop, build the list of columns to retrieve; this will be |
947
|
|
|
|
|
|
|
# used both for fetching data and ordering. |
948
|
135
|
|
|
|
|
273
|
my ( $cList, $col, $tbl, $ar, $i, $c ); |
949
|
135
|
|
|
|
|
216
|
my $numFields = 0; |
950
|
135
|
|
|
|
|
223
|
my %columns; |
951
|
|
|
|
|
|
|
my @names; |
952
|
135
|
|
|
|
|
233
|
my %funcs = (); |
953
|
|
|
|
|
|
|
|
954
|
|
|
|
|
|
|
# |
955
|
|
|
|
|
|
|
# DAA |
956
|
|
|
|
|
|
|
# |
957
|
|
|
|
|
|
|
# lets just disable this and see where it leads... |
958
|
|
|
|
|
|
|
# |
959
|
|
|
|
|
|
|
# if ($self->{join}) { |
960
|
|
|
|
|
|
|
# @names = @{ $table->col_names }; |
961
|
|
|
|
|
|
|
# for my $col(@names) { |
962
|
|
|
|
|
|
|
# $columns{$tableName}->{"$col"} = $numFields++; |
963
|
|
|
|
|
|
|
# push(@$cList, $table->column_num($col)); |
964
|
|
|
|
|
|
|
# } |
965
|
|
|
|
|
|
|
# } |
966
|
|
|
|
|
|
|
# else { |
967
|
135
|
|
|
|
|
299
|
foreach my $column ( $self->columns() ) |
968
|
|
|
|
|
|
|
{ |
969
|
313
|
50
|
|
|
|
1792
|
if ( _INSTANCE( $column, 'SQL::Statement::Param' ) ) |
970
|
|
|
|
|
|
|
{ |
971
|
0
|
|
|
|
|
0
|
my $val = $eval->param( $column->idx() ); |
972
|
0
|
0
|
|
|
|
0
|
if ( -1 != ( my $idx = index( $val, '.' ) ) ) |
973
|
|
|
|
|
|
|
{ |
974
|
0
|
|
|
|
|
0
|
$col = substr( $val, 0, $idx ); |
975
|
0
|
|
|
|
|
0
|
$tbl = substr( $val, $idx + 1 ); |
976
|
|
|
|
|
|
|
} |
977
|
|
|
|
|
|
|
else |
978
|
|
|
|
|
|
|
{ |
979
|
0
|
|
|
|
|
0
|
$col = $val; |
980
|
0
|
|
|
|
|
0
|
$tbl = $tableName; |
981
|
|
|
|
|
|
|
} |
982
|
0
|
|
0
|
|
|
0
|
$tbl ||= ''; |
983
|
0
|
|
|
|
|
0
|
$columns{$tbl}->{$col} = $numFields++; |
984
|
|
|
|
|
|
|
} |
985
|
|
|
|
|
|
|
else |
986
|
|
|
|
|
|
|
{ |
987
|
313
|
|
|
|
|
871
|
( $col, $tbl ) = ( $column->name(), $column->table() ); |
988
|
313
|
|
100
|
|
|
754
|
$tbl ||= ''; |
989
|
313
|
|
|
|
|
1046
|
$columns{$tbl}->{ $column->display_name() } = $columns{$tbl}->{$col} = $numFields++; |
990
|
|
|
|
|
|
|
} |
991
|
|
|
|
|
|
|
|
992
|
|
|
|
|
|
|
# |
993
|
|
|
|
|
|
|
# handle functions in select list |
994
|
|
|
|
|
|
|
# |
995
|
|
|
|
|
|
|
# DAA |
996
|
|
|
|
|
|
|
# |
997
|
|
|
|
|
|
|
# check for a join temp table; if so, check if we can locate |
998
|
|
|
|
|
|
|
# the column in its delimited set |
999
|
|
|
|
|
|
|
# |
1000
|
|
|
|
|
|
|
my $cnum = |
1001
|
|
|
|
|
|
|
( ( $tableName eq ( $self->{dlm} . 'tmp' ) ) && ( $tbl ne '' ) ) |
1002
|
313
|
100
|
100
|
|
|
1465
|
? $table->column_num( $tbl . $self->{dlm} . $col ) |
1003
|
|
|
|
|
|
|
: $table->column_num($col); |
1004
|
|
|
|
|
|
|
|
1005
|
313
|
100
|
66
|
|
|
1121
|
if ( !defined $cnum || $column->{function} ) |
1006
|
|
|
|
|
|
|
{ |
1007
|
33
|
|
|
|
|
74
|
$funcs{$col} = $column->{function}; |
1008
|
33
|
|
|
|
|
62
|
$cnum = $col; |
1009
|
|
|
|
|
|
|
} |
1010
|
313
|
|
|
|
|
616
|
push( @$cList, $cnum ); |
1011
|
|
|
|
|
|
|
|
1012
|
|
|
|
|
|
|
# push(@$cList, $table->column_num($col)); |
1013
|
313
|
|
|
|
|
687
|
push( @names, $col ); |
1014
|
|
|
|
|
|
|
} |
1015
|
|
|
|
|
|
|
|
1016
|
|
|
|
|
|
|
# } |
1017
|
135
|
50
|
|
|
|
342
|
$cList = [] unless ( defined($cList) ); |
1018
|
135
|
100
|
|
|
|
342
|
if ( $self->{join} ) |
1019
|
|
|
|
|
|
|
{ |
1020
|
32
|
|
|
|
|
70
|
foreach (@names) { $_ =~ s/^[^$self->{dlm}]+$self->{dlm}//; } |
|
122
|
|
|
|
|
395
|
|
1021
|
|
|
|
|
|
|
} |
1022
|
135
|
|
|
|
|
363
|
$self->{NAME} = \@names; |
1023
|
|
|
|
|
|
|
# $self->verify_order_cols($table); |
1024
|
135
|
|
|
|
|
418
|
my @order_by = $self->order(); |
1025
|
135
|
|
|
|
|
229
|
my @extraSortCols = (); |
1026
|
|
|
|
|
|
|
|
1027
|
135
|
100
|
|
|
|
302
|
if (@order_by) |
1028
|
|
|
|
|
|
|
{ |
1029
|
17
|
|
|
|
|
33
|
my $nFields = $numFields; |
1030
|
|
|
|
|
|
|
|
1031
|
|
|
|
|
|
|
# It is possible that the user gave an ORDER BY clause with columns |
1032
|
|
|
|
|
|
|
# that are not part of $cList yet. These columns will need to be |
1033
|
|
|
|
|
|
|
# present in the array of arrays for sorting, but will be stripped |
1034
|
|
|
|
|
|
|
# off later. |
1035
|
17
|
|
|
|
|
37
|
my $i = -1; |
1036
|
17
|
|
|
|
|
38
|
foreach my $column (@order_by) |
1037
|
|
|
|
|
|
|
{ |
1038
|
20
|
|
|
|
|
31
|
++$i; |
1039
|
20
|
|
|
|
|
63
|
( $col, $tbl ) = ( $column->column(), $column->table() ); |
1040
|
20
|
|
|
|
|
42
|
my $pos; |
1041
|
20
|
|
66
|
|
|
67
|
$tbl ||= $self->colname2table($col); |
1042
|
20
|
|
100
|
|
|
55
|
$tbl ||= ''; |
1043
|
20
|
100
|
|
|
|
57
|
if ( $self->{join} ) |
1044
|
|
|
|
|
|
|
{ |
1045
|
6
|
|
|
|
|
19
|
$pos = $table->column_num( $tbl . $self->{dlm} . $col ); |
1046
|
6
|
100
|
|
|
|
18
|
defined($pos) |
1047
|
|
|
|
|
|
|
or $pos = $table->column_num( $tbl . '_' . $col ); |
1048
|
|
|
|
|
|
|
} |
1049
|
20
|
100
|
|
|
|
75
|
next if ( exists( $columns{$tbl}->{$col} ) ); |
1050
|
1
|
50
|
|
|
|
6
|
$pos = $table->column_num($col) unless ( defined($pos) ); |
1051
|
1
|
|
|
|
|
3
|
push( @extraSortCols, $pos ); |
1052
|
1
|
|
|
|
|
3
|
$columns{$tbl}->{$col} = $nFields++; |
1053
|
|
|
|
|
|
|
} |
1054
|
|
|
|
|
|
|
} |
1055
|
|
|
|
|
|
|
|
1056
|
135
|
100
|
|
|
|
410
|
my $e = $self->{join} ? $table : $eval; |
1057
|
|
|
|
|
|
|
|
1058
|
|
|
|
|
|
|
# begin count for limiting if there's a limit clause and no order clause |
1059
|
|
|
|
|
|
|
# |
1060
|
135
|
100
|
100
|
|
|
332
|
my $limit_count = 0 if ( $self->limit() and !$self->order() ); |
1061
|
135
|
|
|
|
|
295
|
my $limit = $self->limit(); |
1062
|
135
|
|
|
|
|
213
|
my $row_count = 0; |
1063
|
135
|
|
100
|
|
|
283
|
my $offset = $self->offset() || 0; |
1064
|
135
|
|
|
|
|
450
|
while ( my $array = $table->fetch_row($data) ) |
1065
|
|
|
|
|
|
|
{ |
1066
|
8673
|
100
|
|
|
|
18821
|
if ( $self->eval_where( $e, $tableName, $array, \%funcs ) ) |
1067
|
|
|
|
|
|
|
{ |
1068
|
8432
|
100
|
100
|
|
|
16668
|
next if ( defined($limit_count) and ( $row_count++ < $offset ) ); |
1069
|
|
|
|
|
|
|
|
1070
|
8427
|
|
|
|
|
14763
|
my @row = map { $_->value($e) } $self->columns(); |
|
21086
|
|
|
|
|
41805
|
|
1071
|
8427
|
|
|
|
|
13247
|
push( @{$rows}, \@row ); |
|
8427
|
|
|
|
|
14882
|
|
1072
|
|
|
|
|
|
|
|
1073
|
|
|
|
|
|
|
# We quit here if there's a limit clause without order clause |
1074
|
|
|
|
|
|
|
# and the limit has been reached |
1075
|
8427
|
100
|
100
|
|
|
27148
|
defined($limit_count) |
1076
|
|
|
|
|
|
|
and ( ++$limit_count >= $limit ) |
1077
|
|
|
|
|
|
|
and return ( $limit, $numFields, $rows ); |
1078
|
|
|
|
|
|
|
} |
1079
|
|
|
|
|
|
|
} |
1080
|
|
|
|
|
|
|
|
1081
|
134
|
100
|
|
|
|
424
|
if ( $self->distinct() ) |
1082
|
|
|
|
|
|
|
{ |
1083
|
5
|
|
|
|
|
9
|
my %seen; |
1084
|
5
|
|
|
|
|
24
|
@{$rows} = map { |
1085
|
33
|
50
|
|
|
|
50
|
$seen{ join( "\0", ( map { defined($_) ? $_ : '' } @{$_} ) ) }++ |
|
89
|
100
|
|
|
|
218
|
|
|
33
|
|
|
|
|
48
|
|
1086
|
|
|
|
|
|
|
? () |
1087
|
|
|
|
|
|
|
: $_ |
1088
|
5
|
|
|
|
|
9
|
} @{$rows}; |
|
5
|
|
|
|
|
13
|
|
1089
|
|
|
|
|
|
|
} |
1090
|
|
|
|
|
|
|
|
1091
|
134
|
100
|
|
|
|
393
|
if ( $self->{has_set_functions} ) |
1092
|
|
|
|
|
|
|
{ |
1093
|
19
|
|
|
|
|
44
|
my $aggreg; |
1094
|
19
|
100
|
|
|
|
65
|
if ( $self->{group_by} ) |
1095
|
|
|
|
|
|
|
{ |
1096
|
7
|
|
|
|
|
13
|
my @keycols = @{ $self->{colpos} }{ @{ $self->{group_by} } }; |
|
7
|
|
|
|
|
27
|
|
|
7
|
|
|
|
|
15
|
|
1097
|
7
|
|
|
|
|
41
|
$aggreg = SQL::Statement::Group->new( $self, $rows, \@keycols ); |
1098
|
|
|
|
|
|
|
} |
1099
|
|
|
|
|
|
|
else |
1100
|
|
|
|
|
|
|
{ |
1101
|
12
|
|
|
|
|
114
|
$aggreg = SQL::Statement::Aggregate->new( $self, $rows ); |
1102
|
|
|
|
|
|
|
} |
1103
|
19
|
|
|
|
|
71
|
$rows = $aggreg->calc(); |
1104
|
|
|
|
|
|
|
# FIXME re-order if order_by |
1105
|
|
|
|
|
|
|
} |
1106
|
|
|
|
|
|
|
|
1107
|
134
|
100
|
|
|
|
349
|
if (@order_by) |
1108
|
0
|
|
|
|
|
0
|
{ |
1109
|
16
|
|
|
16
|
|
8739
|
use sort 'stable'; |
|
16
|
|
|
|
|
9566
|
|
|
16
|
|
|
|
|
104
|
|
1110
|
|
|
|
|
|
|
my @sortCols = map { |
1111
|
17
|
|
|
|
|
61
|
my ( $col, $tbl ) = ( $_->column(), $_->table() ); |
|
20
|
|
|
|
|
60
|
|
1112
|
20
|
50
|
66
|
|
|
100
|
$self->{join} and $table->is_shared($col) and $tbl = 'shared'; |
1113
|
20
|
|
50
|
|
|
73
|
$tbl ||= $self->colname2table($col) || ''; |
|
|
|
66
|
|
|
|
|
1114
|
20
|
|
|
|
|
83
|
( $columns{$tbl}->{$col}, $_->desc() ) |
1115
|
|
|
|
|
|
|
} @order_by; |
1116
|
|
|
|
|
|
|
|
1117
|
17
|
|
|
|
|
49
|
$i = scalar(@sortCols); |
1118
|
|
|
|
|
|
|
do |
1119
|
17
|
|
|
|
|
31
|
{ |
1120
|
20
|
|
|
|
|
58
|
my $desc = $sortCols[ --$i ]; |
1121
|
20
|
|
|
|
|
34
|
my $colNum = $sortCols[ --$i ]; |
1122
|
20
|
|
|
|
|
101
|
@{$rows} = sort { |
1123
|
132
|
|
|
|
|
166
|
my $result; |
1124
|
132
|
|
|
|
|
246
|
$result = _anycmp( $a->[$colNum], $b->[$colNum] ); |
1125
|
132
|
100
|
|
|
|
255
|
$desc and $result = -$result; |
1126
|
|
|
|
|
|
|
$result; |
1127
|
20
|
|
|
|
|
40
|
} @{$rows}; |
|
20
|
|
|
|
|
99
|
|
1128
|
|
|
|
|
|
|
} while ( $i > 0 ); |
1129
|
16
|
|
|
16
|
|
3296
|
use sort 'defaults'; # for perl < 5.10.0 |
|
16
|
|
|
|
|
42
|
|
|
16
|
|
|
|
|
69
|
|
1130
|
|
|
|
|
|
|
} |
1131
|
|
|
|
|
|
|
|
1132
|
134
|
100
|
|
|
|
363
|
if ( defined( $self->limit() ) ) |
1133
|
|
|
|
|
|
|
{ |
1134
|
1
|
|
50
|
|
|
4
|
my $offset = $self->offset() || 0; |
1135
|
1
|
|
50
|
|
|
8
|
my $limit = $self->limit() || 0; |
1136
|
1
|
|
|
|
|
3
|
@{$rows} = splice( @{$rows}, $offset, $limit ); |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
4
|
|
1137
|
|
|
|
|
|
|
} |
1138
|
|
|
|
|
|
|
|
1139
|
|
|
|
|
|
|
# Rip off columns that have been added for @extraSortCols only |
1140
|
134
|
100
|
|
|
|
305
|
if (@extraSortCols) |
1141
|
|
|
|
|
|
|
{ |
1142
|
1
|
|
|
|
|
3
|
foreach my $row ( @{$rows} ) |
|
1
|
|
|
|
|
3
|
|
1143
|
|
|
|
|
|
|
{ |
1144
|
4
|
|
|
|
|
6
|
splice( @{$row}, $numFields, scalar(@extraSortCols) ); |
|
4
|
|
|
|
|
8
|
|
1145
|
|
|
|
|
|
|
} |
1146
|
|
|
|
|
|
|
} |
1147
|
|
|
|
|
|
|
|
1148
|
134
|
|
|
|
|
226
|
( scalar( @{$rows} ), $numFields, $rows ); |
|
134
|
|
|
|
|
1505
|
|
1149
|
|
|
|
|
|
|
} |
1150
|
|
|
|
|
|
|
|
1151
|
|
|
|
|
|
|
sub _anycmp($$;$) |
1152
|
|
|
|
|
|
|
{ |
1153
|
32226
|
|
|
32226
|
|
51521
|
my ( $a, $b, $case_fold ) = @_; |
1154
|
|
|
|
|
|
|
|
1155
|
32226
|
100
|
66
|
|
|
134747
|
if ( !defined($a) || !defined($b) ) |
|
|
100
|
66
|
|
|
|
|
1156
|
|
|
|
|
|
|
{ |
1157
|
4
|
|
|
|
|
9
|
return defined($a) - defined($b); |
1158
|
|
|
|
|
|
|
} |
1159
|
|
|
|
|
|
|
elsif ( looks_like_number($a) && looks_like_number($b) ) |
1160
|
|
|
|
|
|
|
{ |
1161
|
24164
|
|
|
|
|
64540
|
return $a <=> $b; |
1162
|
|
|
|
|
|
|
} |
1163
|
|
|
|
|
|
|
else |
1164
|
|
|
|
|
|
|
{ |
1165
|
8058
|
50
|
0
|
|
|
24074
|
return $case_fold ? lc($a) cmp lc($b) || $a cmp $b : $a cmp $b; |
1166
|
|
|
|
|
|
|
} |
1167
|
|
|
|
|
|
|
} |
1168
|
|
|
|
|
|
|
|
1169
|
|
|
|
|
|
|
sub eval_where |
1170
|
|
|
|
|
|
|
{ |
1171
|
8723
|
|
|
8723
|
1
|
14853
|
my ( $self, $eval, $tname, $rowary ) = @_; |
1172
|
8723
|
100
|
|
|
|
21879
|
return 1 unless ( defined( $self->{where_terms} ) ); |
1173
|
458
|
|
|
|
|
686
|
$self->{argnum} = 0; |
1174
|
|
|
|
|
|
|
|
1175
|
458
|
|
|
|
|
1195
|
return $self->{where_terms}->value($eval); |
1176
|
|
|
|
|
|
|
} |
1177
|
|
|
|
|
|
|
|
1178
|
|
|
|
|
|
|
sub fetch_row |
1179
|
|
|
|
|
|
|
{ |
1180
|
123
|
|
|
123
|
1
|
10623
|
my ($self) = @_; |
1181
|
123
|
|
50
|
|
|
282
|
$self->{data} ||= []; |
1182
|
123
|
|
|
|
|
162
|
my $row = shift @{ $self->{data} }; |
|
123
|
|
|
|
|
219
|
|
1183
|
123
|
100
|
100
|
|
|
427
|
return unless $row and scalar @$row; |
1184
|
93
|
|
|
|
|
188
|
return $row; |
1185
|
|
|
|
|
|
|
} |
1186
|
|
|
|
|
|
|
|
1187
|
16
|
|
|
16
|
|
8429
|
no warnings 'once'; |
|
16
|
|
|
|
|
44
|
|
|
16
|
|
|
|
|
1134
|
|
1188
|
|
|
|
|
|
|
*fetch = \&fetch_row; |
1189
|
|
|
|
|
|
|
|
1190
|
16
|
|
|
16
|
|
121
|
use warnings; |
|
16
|
|
|
|
|
67
|
|
|
16
|
|
|
|
|
87119
|
|
1191
|
|
|
|
|
|
|
|
1192
|
|
|
|
|
|
|
sub fetch_rows |
1193
|
|
|
|
|
|
|
{ |
1194
|
250
|
|
|
250
|
1
|
22330
|
my $self = $_[0]; |
1195
|
250
|
|
50
|
|
|
753
|
my $rows = $self->{data} || []; |
1196
|
250
|
|
|
|
|
522
|
$self->{data} = []; |
1197
|
250
|
|
|
|
|
606
|
return $rows; |
1198
|
|
|
|
|
|
|
} |
1199
|
|
|
|
|
|
|
|
1200
|
7
|
|
|
7
|
1
|
1138
|
sub open_table ($$$$$) { croak "Abstract method " . ref( $_[0] ) . "::open_table called" } |
1201
|
|
|
|
|
|
|
|
1202
|
|
|
|
|
|
|
sub open_tables |
1203
|
|
|
|
|
|
|
{ |
1204
|
4649
|
|
|
4649
|
1
|
9079
|
my ( $self, $data, $createMode, $lockMode ) = @_; |
1205
|
4649
|
|
|
|
|
6287
|
my @c; |
1206
|
4649
|
|
|
|
|
7360
|
my $t = {}; |
1207
|
4649
|
|
|
|
|
9834
|
my @tables = $self->tables(); |
1208
|
4649
|
|
|
|
|
7458
|
my $count = -1; |
1209
|
4649
|
|
|
|
|
8199
|
for my $tbl (@tables) |
1210
|
|
|
|
|
|
|
{ |
1211
|
4519
|
|
|
|
|
6116
|
++$count; |
1212
|
4519
|
|
|
|
|
8480
|
my $name = $tbl->name(); |
1213
|
4519
|
50
|
|
|
|
11984
|
if ( $name =~ m/^(.+)\.([^\.]+)$/ ) |
1214
|
|
|
|
|
|
|
{ |
1215
|
0
|
|
|
|
|
0
|
my $schema = $1; # ignored |
1216
|
0
|
|
|
|
|
0
|
$name = $tbl->{name} = $2; |
1217
|
|
|
|
|
|
|
} |
1218
|
|
|
|
|
|
|
|
1219
|
4519
|
100
|
66
|
|
|
28644
|
if ( defined( $self->{table_func} ) && defined( $self->{table_func}->{ uc $name } ) ) |
|
|
100
|
100
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
1220
|
|
|
|
|
|
|
{ |
1221
|
2
|
|
|
|
|
4
|
my $u_func = $self->{table_func}->{ uc $name }; |
1222
|
2
|
|
|
|
|
7
|
$t->{$name} = $self->get_user_func_table( $name, $u_func ); |
1223
|
|
|
|
|
|
|
} |
1224
|
|
|
|
|
|
|
elsif (defined( $data->{Database}->{sql_ram_tables} ) |
1225
|
|
|
|
|
|
|
&& defined( $data->{Database}->{sql_ram_tables}->{$name} ) |
1226
|
|
|
|
|
|
|
&& $data->{Database}->{sql_ram_tables}->{$name} ) |
1227
|
|
|
|
|
|
|
{ |
1228
|
4475
|
|
|
|
|
9830
|
$t->{$name} = $data->{Database}->{sql_ram_tables}->{$name}; |
1229
|
4475
|
|
|
|
|
16514
|
$t->{$name}->seek( $data, 0, 0 ); |
1230
|
|
|
|
|
|
|
$t->{$name}->init_table( $data, $name, $createMode, $lockMode ) |
1231
|
4475
|
50
|
|
|
|
13859
|
if ( $t->{$name}->can('init_table') ); |
1232
|
|
|
|
|
|
|
} |
1233
|
|
|
|
|
|
|
elsif ( $self->{is_ram_table} ) |
1234
|
|
|
|
|
|
|
{ |
1235
|
35
|
|
|
|
|
230
|
$t->{$name} = $data->{Database}->{sql_ram_tables}->{$name} = |
1236
|
|
|
|
|
|
|
SQL::Statement::RAM::Table->new( $name, [], [] ); |
1237
|
|
|
|
|
|
|
} |
1238
|
|
|
|
|
|
|
else |
1239
|
|
|
|
|
|
|
{ |
1240
|
7
|
|
|
|
|
16
|
undef $@; |
1241
|
7
|
|
|
|
|
15
|
eval { |
1242
|
7
|
|
|
|
|
16
|
my $open_name = $self->{org_table_names}->[$count]; |
1243
|
7
|
|
|
|
|
27
|
$t->{$name} = $self->open_table( $data, $open_name, $createMode, $lockMode ); |
1244
|
|
|
|
|
|
|
}; |
1245
|
7
|
|
|
|
|
562
|
my $err = $t->{$name}->{errstr}; |
1246
|
7
|
50
|
|
|
|
26
|
return $self->do_err($err) if ($err); |
1247
|
7
|
50
|
|
|
|
45
|
return $self->do_err($@) if ($@); |
1248
|
|
|
|
|
|
|
} |
1249
|
|
|
|
|
|
|
|
1250
|
4512
|
|
|
|
|
7201
|
my @cnames; |
1251
|
4512
|
|
|
|
|
7736
|
my $table_cols = $t->{$name}->{org_col_names}; |
1252
|
4512
|
100
|
|
|
|
8335
|
$table_cols = $t->{$name}->{col_names} unless $table_cols; |
1253
|
4512
|
|
|
|
|
8107
|
for my $c (@$table_cols) |
1254
|
|
|
|
|
|
|
{ |
1255
|
13311
|
100
|
|
|
|
26040
|
my $newc = $c =~ m/^"/ ? $c : lc($c); |
1256
|
13311
|
|
|
|
|
22270
|
push( @cnames, $newc ); |
1257
|
13311
|
|
|
|
|
24043
|
$self->{ORG_NAME}->{$newc} = $c; |
1258
|
|
|
|
|
|
|
} |
1259
|
|
|
|
|
|
|
|
1260
|
|
|
|
|
|
|
# |
1261
|
|
|
|
|
|
|
# set the col_num => col_obj hash for the table |
1262
|
|
|
|
|
|
|
# |
1263
|
4512
|
|
|
|
|
6500
|
my $col_nums; |
1264
|
4512
|
|
|
|
|
6254
|
my $i = 0; |
1265
|
4512
|
|
|
|
|
7818
|
for (@cnames) |
1266
|
|
|
|
|
|
|
{ |
1267
|
13311
|
|
|
|
|
23006
|
$col_nums->{$_} = $i++; |
1268
|
|
|
|
|
|
|
} |
1269
|
4512
|
|
|
|
|
10547
|
$t->{$name}->{col_nums} = $col_nums; |
1270
|
4512
|
|
|
|
|
10246
|
$t->{$name}->{col_names} = \@cnames; |
1271
|
|
|
|
|
|
|
|
1272
|
4512
|
|
|
|
|
13549
|
my $tcols = $t->{$name}->col_names(); |
1273
|
4512
|
|
|
|
|
6816
|
my @newcols; |
1274
|
4512
|
|
|
|
|
7831
|
for (@$tcols) |
1275
|
|
|
|
|
|
|
{ |
1276
|
13311
|
50
|
|
|
|
23003
|
next unless ( defined($_) ); |
1277
|
13311
|
|
|
|
|
19777
|
my $ncol = $_; |
1278
|
13311
|
50
|
|
|
|
32982
|
$ncol = $name . '.' . $ncol unless ( $ncol =~ m/\./ ); |
1279
|
13311
|
|
|
|
|
23843
|
push( @newcols, $ncol ); |
1280
|
|
|
|
|
|
|
} |
1281
|
4512
|
|
|
|
|
12833
|
@c = ( @c, @newcols ); |
1282
|
|
|
|
|
|
|
} |
1283
|
|
|
|
|
|
|
|
1284
|
4642
|
|
|
|
|
14481
|
$self->buildColumnObjects( $t, \@tables ); |
1285
|
4642
|
50
|
|
|
|
10631
|
return $self->do_err( $self->{errstr} ) if ( $self->{errstr} ); |
1286
|
|
|
|
|
|
|
|
1287
|
|
|
|
|
|
|
################################################## |
1288
|
|
|
|
|
|
|
# Patch from Cosimo Streppone |
1289
|
|
|
|
|
|
|
|
1290
|
|
|
|
|
|
|
# my $all_cols = $self->{all_cols} |
1291
|
|
|
|
|
|
|
# || [ map {$_->{name} }@{$self->{columns}} ] |
1292
|
|
|
|
|
|
|
# || []; |
1293
|
|
|
|
|
|
|
# @$all_cols = (@$all_cols,@c); |
1294
|
|
|
|
|
|
|
# $self->{all_cols} = $all_cols; |
1295
|
4642
|
100
|
|
|
|
9109
|
if ( !$self->{all_cols} ) |
1296
|
|
|
|
|
|
|
{ |
1297
|
502
|
|
|
|
|
872
|
my $all_cols = []; |
1298
|
502
|
|
|
|
|
770
|
$all_cols = [ map { $_->{name} } @{ $self->{columns} } ]; |
|
1113
|
|
|
|
|
2616
|
|
|
502
|
|
|
|
|
1000
|
|
1299
|
502
|
|
50
|
|
|
1268
|
$all_cols ||= []; # ? |
1300
|
502
|
|
|
|
|
1551
|
@$all_cols = ( @$all_cols, @c ); |
1301
|
502
|
|
|
|
|
1081
|
$self->{all_cols} = $all_cols; |
1302
|
|
|
|
|
|
|
} |
1303
|
|
|
|
|
|
|
################################################## |
1304
|
|
|
|
|
|
|
|
1305
|
4642
|
|
|
|
|
15772
|
return SQL::Eval->new( { 'tables' => $t } ), \@c; |
1306
|
|
|
|
|
|
|
} |
1307
|
|
|
|
|
|
|
|
1308
|
|
|
|
|
|
|
sub getColumnObject($) |
1309
|
|
|
|
|
|
|
{ |
1310
|
686
|
|
|
686
|
1
|
1289
|
my ( $self, $newcol, $t, $tables ) = @_; |
1311
|
686
|
|
|
|
|
1324
|
my @columns; |
1312
|
|
|
|
|
|
|
|
1313
|
686
|
100
|
100
|
|
|
3107
|
if ( ( $newcol->{type} eq 'column' ) && ( -1 != index( $newcol->{value}, '*' ) ) ) |
|
|
100
|
66
|
|
|
|
|
1314
|
|
|
|
|
|
|
{ |
1315
|
199
|
|
|
|
|
374
|
my $tbl; |
1316
|
|
|
|
|
|
|
my @tables; |
1317
|
199
|
50
|
|
|
|
436
|
if ( $newcol->{value} =~ m/^(.+)\.\*$/ ) |
1318
|
|
|
|
|
|
|
{ |
1319
|
0
|
|
|
|
|
0
|
$tbl = $1; |
1320
|
0
|
0
|
|
|
|
0
|
return $self->do_err("No table name given in '$newcol->{value}'") |
1321
|
|
|
|
|
|
|
unless ( defined( _STRING($tbl) ) ); |
1322
|
0
|
|
|
|
|
0
|
@tables = ($tbl); |
1323
|
|
|
|
|
|
|
} |
1324
|
|
|
|
|
|
|
else |
1325
|
|
|
|
|
|
|
{ |
1326
|
199
|
|
|
|
|
305
|
@tables = map { $_->name() } @{$tables}; |
|
212
|
|
|
|
|
408
|
|
|
199
|
|
|
|
|
401
|
|
1327
|
|
|
|
|
|
|
} |
1328
|
|
|
|
|
|
|
|
1329
|
|
|
|
|
|
|
my $join = defined( _HASH( $self->{join} ) ) |
1330
|
|
|
|
|
|
|
&& ( ( -1 != index( $self->{join}->{type}, 'NATURAL' ) ) |
1331
|
199
|
|
100
|
|
|
834
|
|| ( -1 != index( $self->{join}->{clause}, 'USING' ) ) ); |
1332
|
199
|
|
|
|
|
353
|
my %shared_cols; |
1333
|
|
|
|
|
|
|
|
1334
|
199
|
|
|
|
|
371
|
foreach my $table (@tables) |
1335
|
|
|
|
|
|
|
{ |
1336
|
212
|
50
|
|
|
|
489
|
return $self->do_err("Can't find table '$table'") unless ( defined( $t->{$table} ) ); |
1337
|
212
|
|
|
|
|
358
|
my $tcols = $t->{$table}->{col_names}; |
1338
|
212
|
50
|
|
|
|
529
|
return $self->do_err("Couldn't find column names for table '$table'!") |
1339
|
|
|
|
|
|
|
unless ( _ARRAY($tcols) ); |
1340
|
212
|
|
|
|
|
337
|
foreach my $colName ( @{$tcols} ) |
|
212
|
|
|
|
|
366
|
|
1341
|
|
|
|
|
|
|
{ |
1342
|
652
|
100
|
100
|
|
|
1378
|
next if ( $join && $shared_cols{$colName}++ ); |
1343
|
644
|
|
|
|
|
2087
|
my $expcol = [ |
1344
|
|
|
|
|
|
|
$colName, # column name |
1345
|
|
|
|
|
|
|
$table, # table name |
1346
|
|
|
|
|
|
|
SQL::Statement::ColumnValue->new( $self, $table . '.' . $colName ), # term |
1347
|
|
|
|
|
|
|
$colName, # display name |
1348
|
|
|
|
|
|
|
$colName, |
1349
|
|
|
|
|
|
|
$newcol, |
1350
|
|
|
|
|
|
|
]; |
1351
|
644
|
|
|
|
|
1564
|
push( @columns, $expcol ); |
1352
|
|
|
|
|
|
|
} |
1353
|
|
|
|
|
|
|
} |
1354
|
|
|
|
|
|
|
} |
1355
|
|
|
|
|
|
|
elsif ( ( 'CREATE' eq $self->command() ) || ( 'DROP' eq $self->command() ) ) |
1356
|
|
|
|
|
|
|
{ |
1357
|
|
|
|
|
|
|
return $self->do_err("Invalid column type '$newcol->{type}'") |
1358
|
97
|
50
|
|
|
|
421
|
unless ( 'column' eq $newcol->{type} ); |
1359
|
|
|
|
|
|
|
my $expcol = [ |
1360
|
|
|
|
|
|
|
$newcol->{value}, # column name |
1361
|
|
|
|
|
|
|
undef, # table name |
1362
|
|
|
|
|
|
|
undef, # term |
1363
|
|
|
|
|
|
|
$newcol->{value}, # display name |
1364
|
|
|
|
|
|
|
$newcol->{value}, # original name |
1365
|
97
|
|
|
|
|
274
|
$newcol, # coldef |
1366
|
|
|
|
|
|
|
]; |
1367
|
97
|
|
|
|
|
184
|
push( @columns, $expcol ); |
1368
|
|
|
|
|
|
|
} |
1369
|
|
|
|
|
|
|
else |
1370
|
|
|
|
|
|
|
{ |
1371
|
390
|
|
|
|
|
597
|
my $col; |
1372
|
390
|
100
|
|
|
|
848
|
if ( $newcol->{type} eq 'setfunc' ) |
1373
|
|
|
|
|
|
|
{ |
1374
|
24
|
|
|
|
|
106
|
my @cols = $self->getColumnObject( $newcol->{arg}, $t ); |
1375
|
24
|
100
|
|
|
|
68
|
if ( 1 == scalar(@cols) ) |
1376
|
|
|
|
|
|
|
{ |
1377
|
18
|
|
|
|
|
48
|
$col = $cols[0]->[2]; |
1378
|
|
|
|
|
|
|
} |
1379
|
|
|
|
|
|
|
else |
1380
|
|
|
|
|
|
|
{ |
1381
|
|
|
|
|
|
|
# FIXME add '\0' constants between items? |
1382
|
|
|
|
|
|
|
my $colSep = $self->{termFactory}->buildCondition( |
1383
|
|
|
|
|
|
|
{ |
1384
|
6
|
|
|
|
|
43
|
type => 'string', |
1385
|
|
|
|
|
|
|
value => "\0", |
1386
|
|
|
|
|
|
|
} |
1387
|
|
|
|
|
|
|
); |
1388
|
6
|
|
|
|
|
23
|
@cols = map { $_->[2], $colSep } @cols; |
|
0
|
|
|
|
|
0
|
|
1389
|
6
|
|
|
|
|
15
|
pop(@cols); |
1390
|
|
|
|
|
|
|
$col = $self->{termFactory}->buildCondition( |
1391
|
|
|
|
|
|
|
{ |
1392
|
6
|
|
|
|
|
44
|
type => 'function', |
1393
|
|
|
|
|
|
|
name => 'str_concat', |
1394
|
|
|
|
|
|
|
value => \@cols, |
1395
|
|
|
|
|
|
|
} |
1396
|
|
|
|
|
|
|
); |
1397
|
|
|
|
|
|
|
} |
1398
|
|
|
|
|
|
|
} |
1399
|
|
|
|
|
|
|
else |
1400
|
|
|
|
|
|
|
{ |
1401
|
366
|
|
|
|
|
1263
|
$col = $self->{termFactory}->buildCondition($newcol); |
1402
|
|
|
|
|
|
|
} |
1403
|
|
|
|
|
|
|
|
1404
|
|
|
|
|
|
|
my $expcol = [ |
1405
|
|
|
|
|
|
|
$newcol->{name} || $newcol->{value}, # column name |
1406
|
|
|
|
|
|
|
undef, # table name |
1407
|
|
|
|
|
|
|
$col, # term |
1408
|
|
|
|
|
|
|
$newcol->{alias} || $newcol->{fullorg}, # display name |
1409
|
|
|
|
|
|
|
$newcol->{fullorg}, # original name |
1410
|
390
|
|
66
|
|
|
2181
|
$newcol, # coldef |
|
|
|
66
|
|
|
|
|
1411
|
|
|
|
|
|
|
]; |
1412
|
390
|
|
|
|
|
843
|
push( @columns, $expcol ); |
1413
|
|
|
|
|
|
|
} |
1414
|
|
|
|
|
|
|
|
1415
|
686
|
|
|
|
|
1706
|
return @columns; |
1416
|
|
|
|
|
|
|
} |
1417
|
|
|
|
|
|
|
|
1418
|
|
|
|
|
|
|
sub buildColumnObjects($) |
1419
|
|
|
|
|
|
|
{ |
1420
|
4642
|
|
|
4642
|
1
|
8072
|
my ( $self, $t, $tables ) = @_; |
1421
|
|
|
|
|
|
|
|
1422
|
4642
|
100
|
|
|
|
14299
|
defined( _ARRAY0( $self->{column_defs} ) ) or return; |
1423
|
4635
|
100
|
|
|
|
12375
|
defined( _ARRAY0( $self->{columns} ) ) and return; |
1424
|
|
|
|
|
|
|
|
1425
|
495
|
|
|
|
|
924
|
$self->{columns} = []; |
1426
|
|
|
|
|
|
|
|
1427
|
495
|
|
|
|
|
867
|
my $coldefs = $self->{column_defs}; |
1428
|
|
|
|
|
|
|
|
1429
|
495
|
|
|
|
|
871
|
for ( my $i = 0; $i < scalar( @{$coldefs} ); ++$i ) |
|
1157
|
|
|
|
|
2814
|
|
1430
|
|
|
|
|
|
|
{ |
1431
|
662
|
|
|
|
|
1046
|
my $colentry = $coldefs->[$i]; |
1432
|
|
|
|
|
|
|
|
1433
|
662
|
|
|
|
|
1626
|
my @columns = $self->getColumnObject( $colentry, $t, $tables ); |
1434
|
662
|
50
|
|
|
|
1566
|
return if ( $self->{errstr} ); |
1435
|
|
|
|
|
|
|
|
1436
|
662
|
|
|
|
|
1143
|
foreach my $col (@columns) |
1437
|
|
|
|
|
|
|
{ |
1438
|
1113
|
|
|
|
|
1542
|
my $expcol = SQL::Statement::Util::Column->new( @{$col} ); |
|
1113
|
|
|
|
|
3315
|
|
1439
|
1113
|
|
|
|
|
1649
|
push( @{ $self->{columns} }, $expcol ); |
|
1113
|
|
|
|
|
2138
|
|
1440
|
1113
|
|
66
|
|
|
4925
|
$self->{column_aliases}->{ $col->[4] } ||= $col->[3]; |
1441
|
1113
|
|
|
|
|
1443
|
$self->{colpos}->{ $col->[3] } = scalar( @{ $self->{columns} } ) - 1; |
|
1113
|
|
|
|
|
4103
|
|
1442
|
|
|
|
|
|
|
} |
1443
|
|
|
|
|
|
|
} |
1444
|
|
|
|
|
|
|
|
1445
|
495
|
|
|
|
|
1374
|
return; |
1446
|
|
|
|
|
|
|
} |
1447
|
|
|
|
|
|
|
|
1448
|
|
|
|
|
|
|
sub verify_expand_column |
1449
|
|
|
|
|
|
|
{ |
1450
|
13143
|
|
|
13143
|
1
|
26761
|
my ( $self, $c, $i, $usr_cols, $is_duplicate, $col_exists ) = @_; |
1451
|
|
|
|
|
|
|
|
1452
|
|
|
|
|
|
|
# XXX |
1453
|
13143
|
100
|
|
|
|
25848
|
defined $self->{ALIASES}->{$c} and $c = $self->{ALIASES}->{$c}; |
1454
|
|
|
|
|
|
|
|
1455
|
13143
|
|
|
|
|
19145
|
my ( $table, $col, $col_obj ); |
1456
|
13143
|
100
|
|
|
|
27971
|
if ( $c =~ m/(\S+)\.(\S+)/ ) |
|
|
100
|
|
|
|
|
|
1457
|
|
|
|
|
|
|
{ |
1458
|
1
|
|
|
|
|
3
|
$table = $1; |
1459
|
1
|
|
|
|
|
2
|
$col = $2; |
1460
|
|
|
|
|
|
|
} |
1461
|
13142
|
|
|
|
|
25434
|
elsif ( ++${$i} >= 0 ) |
1462
|
|
|
|
|
|
|
{ |
1463
|
13122
|
|
|
|
|
17844
|
$col_obj = $usr_cols->[ ${$i} ]; |
|
13122
|
|
|
|
|
19689
|
|
1464
|
13122
|
|
|
|
|
27752
|
( $table, $col ) = ( $col_obj->{table}, $col_obj->{name} ); |
1465
|
|
|
|
|
|
|
} |
1466
|
|
|
|
|
|
|
else |
1467
|
|
|
|
|
|
|
{ |
1468
|
20
|
|
|
|
|
57
|
( $table, $col ) = $self->full_qualified_column_name($c); |
1469
|
|
|
|
|
|
|
} |
1470
|
13143
|
50
|
|
|
|
24290
|
return unless ($col); |
1471
|
|
|
|
|
|
|
|
1472
|
|
|
|
|
|
|
my $is_column = |
1473
|
13143
|
100
|
100
|
|
|
83918
|
( defined( _INSTANCE( $col_obj, 'SQL::Statement::Util::Column' ) ) and ( $col_obj->{coldef}->{type} eq 'column' ) ) |
1474
|
|
|
|
|
|
|
? 1 |
1475
|
|
|
|
|
|
|
: 0; |
1476
|
|
|
|
|
|
|
|
1477
|
13143
|
100
|
100
|
|
|
39429
|
unless ( $is_column and defined($table) ) |
1478
|
|
|
|
|
|
|
{ |
1479
|
210
|
|
|
|
|
550
|
( $table, undef ) = $self->full_qualified_column_name($col); |
1480
|
|
|
|
|
|
|
} |
1481
|
|
|
|
|
|
|
|
1482
|
13143
|
50
|
|
|
|
27387
|
if ( defined( _INSTANCE( $table, 'SQL::Statement::Table' ) ) ) |
1483
|
|
|
|
|
|
|
{ |
1484
|
0
|
|
|
|
|
0
|
$table = $table->name(); |
1485
|
|
|
|
|
|
|
} |
1486
|
|
|
|
|
|
|
|
1487
|
13143
|
100
|
100
|
|
|
39534
|
if ( $is_column and !$table ) |
|
|
100
|
|
|
|
|
|
1488
|
|
|
|
|
|
|
{ |
1489
|
2
|
50
|
|
|
|
8
|
return $self->do_err("Ambiguous column name '$c'") if ( $is_duplicate->{$c} ); |
1490
|
2
|
|
|
|
|
10
|
return $self->do_err("No such column '$col'"); |
1491
|
0
|
|
|
|
|
0
|
$col = $c; |
1492
|
|
|
|
|
|
|
} |
1493
|
|
|
|
|
|
|
elsif ($is_column) |
1494
|
|
|
|
|
|
|
{ |
1495
|
13086
|
50
|
|
|
|
26440
|
my $is_user_def = 1 if ( $self->{opts}->{function_defs}->{$col} ); |
1496
|
|
|
|
|
|
|
return $self->do_err("No such column '$table.$col'") |
1497
|
|
|
|
|
|
|
unless ( $col_exists->{"$table.$col"} |
1498
|
13086
|
0
|
33
|
|
|
34295
|
or $col_exists->{ "\L$table." . $col } |
|
|
|
33
|
|
|
|
|
1499
|
|
|
|
|
|
|
or $is_user_def ); |
1500
|
|
|
|
|
|
|
} |
1501
|
|
|
|
|
|
|
|
1502
|
13141
|
100
|
100
|
|
|
47917
|
return ( $table, $col ) if ( $is_column or ${$i} < 0 ); |
|
55
|
|
|
|
|
205
|
|
1503
|
34
|
|
|
|
|
90
|
return; |
1504
|
|
|
|
|
|
|
} |
1505
|
|
|
|
|
|
|
|
1506
|
|
|
|
|
|
|
sub verify_columns |
1507
|
|
|
|
|
|
|
{ |
1508
|
4424
|
|
|
4424
|
1
|
8155
|
my ( $self, $data, $eval, $all_cols ) = @_; |
1509
|
|
|
|
|
|
|
|
1510
|
|
|
|
|
|
|
# |
1511
|
|
|
|
|
|
|
# NOTE FOR LATER: |
1512
|
|
|
|
|
|
|
# perhaps cache column names and skip this after first table open |
1513
|
|
|
|
|
|
|
# |
1514
|
4424
|
|
50
|
|
|
8290
|
$all_cols ||= []; |
1515
|
4424
|
|
|
|
|
5866
|
my @tmp_cols = @{$all_cols}; |
|
4424
|
|
|
|
|
9209
|
|
1516
|
4424
|
|
|
|
|
9014
|
my @usr_cols = $self->columns(); |
1517
|
4424
|
50
|
|
|
|
9348
|
return $self->do_err('No fetchable columns') if ( 0 == scalar(@usr_cols) ); |
1518
|
|
|
|
|
|
|
|
1519
|
4424
|
|
|
|
|
8314
|
my ( $cnum, $fully_qualified_cols ) = ( 0, [] ); |
1520
|
4424
|
|
|
|
|
7827
|
my @tmpcols = map { $_->{name} } @usr_cols; |
|
13122
|
|
|
|
|
28082
|
|
1521
|
4424
|
|
|
|
|
7866
|
my %col_exists = map { $_ => 1 } @tmp_cols; |
|
13296
|
|
|
|
|
29576
|
|
1522
|
|
|
|
|
|
|
|
1523
|
4424
|
|
|
|
|
8338
|
my ( %is_member, @duplicates, %is_duplicate ); |
1524
|
|
|
|
|
|
|
# $_ =~ s/[^.]*\.(.*)/$1/; |
1525
|
4424
|
|
|
|
|
8471
|
foreach (@$all_cols) |
1526
|
|
|
|
|
|
|
{ |
1527
|
13296
|
|
|
|
|
29295
|
substr( $_, 0, index( $_, '.' ) + 1 ) = ''; |
1528
|
|
|
|
|
|
|
} # XXX we're modifying $all_cols from caller! |
1529
|
4424
|
|
|
|
|
14723
|
@duplicates = grep( $is_member{$_}++, @$all_cols ); |
1530
|
4424
|
|
|
|
|
7290
|
%is_duplicate = map { $_ => 1 } @duplicates; |
|
54
|
|
|
|
|
126
|
|
1531
|
4424
|
100
|
100
|
|
|
19555
|
if ( exists( $self->{join} ) && defined( _HASH( $self->{join} ) ) ) |
1532
|
|
|
|
|
|
|
{ |
1533
|
34
|
|
|
|
|
71
|
my $join = $self->{join}; |
1534
|
34
|
100
|
|
|
|
169
|
if ( -1 != index( uc $join->{type}, 'NATURAL' ) ) |
|
|
100
|
|
|
|
|
|
1535
|
|
|
|
|
|
|
{ |
1536
|
6
|
|
|
|
|
14
|
%is_duplicate = (); |
1537
|
|
|
|
|
|
|
} |
1538
|
|
|
|
|
|
|
|
1539
|
|
|
|
|
|
|
# the following should be probably conditioned on an option, |
1540
|
|
|
|
|
|
|
# but I do not know which --BW |
1541
|
|
|
|
|
|
|
elsif ( 'USING' eq $join->{clause} ) |
1542
|
|
|
|
|
|
|
{ |
1543
|
10
|
|
|
|
|
21
|
my @keys = @{ $join->{keycols} }; |
|
10
|
|
|
|
|
27
|
|
1544
|
10
|
|
|
|
|
31
|
delete @is_duplicate{@keys}; |
1545
|
|
|
|
|
|
|
} |
1546
|
|
|
|
|
|
|
} |
1547
|
|
|
|
|
|
|
|
1548
|
4424
|
|
|
|
|
6329
|
my %set_func_nofunc; |
1549
|
4424
|
100
|
|
|
|
8335
|
if ( defined( $self->{has_set_functions} ) ) |
1550
|
|
|
|
|
|
|
{ |
1551
|
20
|
|
|
|
|
40
|
my @set_func_nofunc = grep { ( $_->{type} ne 'setfunc' ) } @{ $self->{column_defs} }; |
|
34
|
|
|
|
|
96
|
|
|
20
|
|
|
|
|
55
|
|
1552
|
20
|
|
66
|
|
|
50
|
%set_func_nofunc = map { ( $_->{alias} || $_->{fullorg} ) => 1 } @set_func_nofunc; |
|
9
|
|
|
|
|
64
|
|
1553
|
|
|
|
|
|
|
} |
1554
|
4424
|
|
|
|
|
10344
|
my ( $is_fully, $set_fully ) = ( {}, {} ); |
1555
|
4424
|
|
|
|
|
7019
|
my $i = -1; |
1556
|
4424
|
|
|
|
|
9630
|
my $num_tables = $self->tables(); |
1557
|
4424
|
|
|
|
|
7520
|
for my $c (@tmpcols) |
1558
|
|
|
|
|
|
|
{ |
1559
|
13122
|
|
|
|
|
33691
|
my ( $table, $col ) = $self->verify_expand_column( $c, \$i, \@usr_cols, \%is_duplicate, \%col_exists ); |
1560
|
13122
|
100
|
|
|
|
29311
|
return if ( $self->{errstr} ); |
1561
|
13120
|
100
|
66
|
|
|
36249
|
next unless ( $table && $col ); |
1562
|
|
|
|
|
|
|
|
1563
|
13086
|
|
|
|
|
24401
|
my $ftc = "$table.$col"; |
1564
|
13086
|
50
|
33
|
|
|
49982
|
next if ( $table and $col and $is_fully->{$ftc} ); |
|
|
|
33
|
|
|
|
|
1565
|
|
|
|
|
|
|
|
1566
|
13086
|
|
|
|
|
23282
|
$self->{columns}->[$i]->{name} = $col; |
1567
|
13086
|
|
|
|
|
20299
|
$self->{columns}->[$i]->{table} = $table; |
1568
|
|
|
|
|
|
|
|
1569
|
13086
|
50
|
33
|
|
|
34537
|
if ( $table and $col ) |
1570
|
|
|
|
|
|
|
{ |
1571
|
13086
|
|
|
|
|
21324
|
push( @$fully_qualified_cols, $ftc ); |
1572
|
13086
|
|
|
|
|
23418
|
++$is_fully->{$ftc}; |
1573
|
13086
|
100
|
|
|
|
30683
|
++$set_fully->{$ftc} if ( $set_func_nofunc{$c} ); |
1574
|
|
|
|
|
|
|
} |
1575
|
|
|
|
|
|
|
} |
1576
|
|
|
|
|
|
|
|
1577
|
4422
|
100
|
|
|
|
8717
|
if ( defined( $self->{has_set_functions} ) ) |
1578
|
|
|
|
|
|
|
{ |
1579
|
20
|
100
|
|
|
|
93
|
if ( defined( _ARRAY( $self->{group_by} ) ) ) |
1580
|
|
|
|
|
|
|
{ |
1581
|
7
|
|
|
|
|
10
|
foreach my $grpby ( @{ $self->{group_by} } ) |
|
7
|
|
|
|
|
18
|
|
1582
|
|
|
|
|
|
|
{ |
1583
|
8
|
|
|
|
|
15
|
$i = -2; |
1584
|
8
|
|
|
|
|
23
|
my ( $table, $col ) = $self->verify_expand_column( $grpby, \$i, \@usr_cols, \%is_duplicate, \%col_exists ); |
1585
|
8
|
50
|
|
|
|
24
|
return if ( $self->{errstr} ); |
1586
|
8
|
|
33
|
|
|
18
|
$col ||= $grpby; |
1587
|
8
|
50
|
33
|
|
|
32
|
( $table, $col ) = $self->full_qualified_column_name($col) |
1588
|
|
|
|
|
|
|
if ( defined($col) && !defined($table) ); |
1589
|
8
|
50
|
33
|
|
|
36
|
next unless ( defined($table) && defined($col) ); |
1590
|
8
|
|
|
|
|
31
|
delete $set_fully->{"$table.$col"}; |
1591
|
|
|
|
|
|
|
} |
1592
|
|
|
|
|
|
|
} |
1593
|
|
|
|
|
|
|
|
1594
|
20
|
100
|
|
|
|
75
|
if ( defined( _HASH($set_fully) ) ) |
1595
|
|
|
|
|
|
|
{ |
1596
|
|
|
|
|
|
|
return $self->do_err( |
1597
|
|
|
|
|
|
|
sprintf( |
1598
|
|
|
|
|
|
|
"Column%s '%s' must appear in the GROUP BY clause or be used in an aggregate function", |
1599
|
1
|
|
|
|
|
7
|
scalar( keys( %{$set_fully} ) ) > 1 ? 's' : '', |
1600
|
1
|
50
|
|
|
|
3
|
join( "', '", keys( %{$set_fully} ) ) |
|
1
|
|
|
|
|
10
|
|
1601
|
|
|
|
|
|
|
) |
1602
|
|
|
|
|
|
|
); |
1603
|
|
|
|
|
|
|
} |
1604
|
|
|
|
|
|
|
} |
1605
|
|
|
|
|
|
|
|
1606
|
4421
|
100
|
|
|
|
9170
|
if ( $self->{sort_spec_list} ) |
1607
|
|
|
|
|
|
|
{ |
1608
|
17
|
|
|
|
|
70
|
for my $n ( 0 .. scalar @{ $self->{sort_spec_list} } - 1 ) |
|
17
|
|
|
|
|
67
|
|
1609
|
|
|
|
|
|
|
{ |
1610
|
20
|
100
|
|
|
|
124
|
defined( _INSTANCE( $self->{sort_spec_list}->[$n], 'SQL::Statement::Order' ) ) and next; |
1611
|
13
|
|
|
|
|
25
|
my ( $newcol, $direction ) = each %{ $self->{sort_spec_list}->[$n] }; |
|
13
|
|
|
|
|
63
|
|
1612
|
13
|
|
66
|
|
|
68
|
my $desc = $direction && ( $direction eq "DESC" ); # ($direction || "ASC") eq "DESC"; |
1613
|
|
|
|
|
|
|
|
1614
|
|
|
|
|
|
|
# XXX parse order by like group by and select list |
1615
|
13
|
|
|
|
|
26
|
$i = -2; |
1616
|
13
|
|
|
|
|
61
|
my ( $table, $col ) = $self->verify_expand_column( $newcol, \$i, \@usr_cols, \%is_duplicate, \%col_exists ); |
1617
|
13
|
50
|
|
|
|
53
|
$self->{errstr} and return; |
1618
|
13
|
100
|
66
|
|
|
80
|
( $table, $col ) = $self->full_qualified_column_name($newcol) |
1619
|
|
|
|
|
|
|
if ( defined($col) && !defined($table) ); |
1620
|
13
|
100
|
|
|
|
68
|
defined($table) and $col = $table . "." . $col; |
1621
|
13
|
|
|
|
|
68
|
$self->{sort_spec_list}->[$n] = SQL::Statement::Order->new( |
1622
|
|
|
|
|
|
|
col => SQL::Statement::Util::Column->new( |
1623
|
|
|
|
|
|
|
$col, # column name |
1624
|
|
|
|
|
|
|
$table, # table name |
1625
|
|
|
|
|
|
|
SQL::Statement::ColumnValue->new( $self, $col ), # term |
1626
|
|
|
|
|
|
|
$newcol # display name |
1627
|
|
|
|
|
|
|
), |
1628
|
|
|
|
|
|
|
direction => $direction, |
1629
|
|
|
|
|
|
|
desc => $desc, |
1630
|
|
|
|
|
|
|
); |
1631
|
|
|
|
|
|
|
} |
1632
|
|
|
|
|
|
|
} |
1633
|
|
|
|
|
|
|
|
1634
|
4421
|
|
|
|
|
19751
|
return $fully_qualified_cols; |
1635
|
|
|
|
|
|
|
} |
1636
|
|
|
|
|
|
|
|
1637
|
|
|
|
|
|
|
sub distinct() |
1638
|
|
|
|
|
|
|
{ |
1639
|
134
|
|
|
134
|
1
|
695
|
my $q = _STRING( $_[0]->{set_quantifier} ); |
1640
|
134
|
|
66
|
|
|
597
|
return defined($q) && ( 'DISTINCT' eq $q ); |
1641
|
|
|
|
|
|
|
} |
1642
|
|
|
|
|
|
|
|
1643
|
|
|
|
|
|
|
sub column_names() |
1644
|
|
|
|
|
|
|
{ |
1645
|
0
|
|
|
0
|
1
|
0
|
my @cols = map { $_->name() } $_[0]->columns(); |
|
0
|
|
|
|
|
0
|
|
1646
|
0
|
|
|
|
|
0
|
return @cols; |
1647
|
|
|
|
|
|
|
} |
1648
|
|
|
|
|
|
|
|
1649
|
5823
|
|
|
5823
|
1
|
107712
|
sub command() { return $_[0]->{command} } |
1650
|
|
|
|
|
|
|
|
1651
|
|
|
|
|
|
|
sub params(;$) |
1652
|
|
|
|
|
|
|
{ |
1653
|
2
|
50
|
|
2
|
1
|
20
|
if ( !$_[0]->{params} ) |
1654
|
|
|
|
|
|
|
{ |
1655
|
0
|
0
|
|
|
|
0
|
return wantarray ? () : 0; |
1656
|
|
|
|
|
|
|
} |
1657
|
2
|
50
|
|
|
|
8
|
return $_[0]->{params}->[ $_[1] ] if ( defined $_[1] ); |
1658
|
|
|
|
|
|
|
|
1659
|
2
|
50
|
|
|
|
15
|
return wantarray ? @{ $_[0]->{params} } : scalar @{ $_[0]->{params} }; |
|
0
|
|
|
|
|
0
|
|
|
2
|
|
|
|
|
14
|
|
1660
|
|
|
|
|
|
|
} |
1661
|
|
|
|
|
|
|
|
1662
|
|
|
|
|
|
|
sub row_values(;$$) |
1663
|
|
|
|
|
|
|
{ |
1664
|
12803
|
50
|
|
12803
|
1
|
30688
|
unless ( defined( _ARRAY( $_[0]->{values} ) ) ) |
1665
|
|
|
|
|
|
|
{ |
1666
|
0
|
0
|
|
|
|
0
|
return wantarray ? () : 0; |
1667
|
|
|
|
|
|
|
} |
1668
|
12803
|
100
|
|
|
|
20699
|
if ( defined( $_[1] ) ) |
1669
|
|
|
|
|
|
|
{ |
1670
|
12802
|
50
|
|
|
|
24441
|
return 0 unless ( defined( $_[0]->{values}->[ $_[1] ] ) ); |
1671
|
12802
|
100
|
|
|
|
31127
|
return $_[0]->{values}->[ $_[1] ]->[ $_[2] ] if ( defined $_[2] ); |
1672
|
|
|
|
|
|
|
|
1673
|
|
|
|
|
|
|
return wantarray |
1674
|
0
|
|
|
|
|
0
|
? map { $_->{value} } @{ $_[0]->{values}->[ $_[1] ] } |
|
0
|
|
|
|
|
0
|
|
1675
|
1
|
50
|
|
|
|
3
|
: scalar @{ $_[0]->{values}->[ $_[1] ] }; |
|
1
|
|
|
|
|
7
|
|
1676
|
|
|
|
|
|
|
} |
1677
|
|
|
|
|
|
|
else |
1678
|
|
|
|
|
|
|
{ |
1679
|
|
|
|
|
|
|
return wantarray |
1680
|
|
|
|
|
|
|
? map { |
1681
|
0
|
|
|
|
|
0
|
[ map { $_->{value} } @{$_} ] |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
1682
|
0
|
|
|
|
|
0
|
} @{ $_[0]->{values} } |
1683
|
1
|
50
|
|
|
|
4
|
: scalar( @{ $_[0]->{values} } ); |
|
1
|
|
|
|
|
7
|
|
1684
|
|
|
|
|
|
|
} |
1685
|
|
|
|
|
|
|
} |
1686
|
|
|
|
|
|
|
|
1687
|
|
|
|
|
|
|
# |
1688
|
|
|
|
|
|
|
# $num_of_cols = $stmt->columns() # number of columns |
1689
|
|
|
|
|
|
|
# @cols = $stmt->columns() # array of S::S::Column objects |
1690
|
|
|
|
|
|
|
# $col = $stmt->columns($cnum) # S::S::Column obj for col number $cnum |
1691
|
|
|
|
|
|
|
# $col = $stmt->columns($cname) # S::S::Column obj for col named $cname |
1692
|
|
|
|
|
|
|
# |
1693
|
|
|
|
|
|
|
sub columns |
1694
|
|
|
|
|
|
|
{ |
1695
|
34581
|
|
|
34581
|
1
|
55086
|
my ( $self, $col ) = @_; |
1696
|
34581
|
100
|
|
|
|
62236
|
if ( !$self->{columns} ) |
1697
|
|
|
|
|
|
|
{ |
1698
|
1
|
50
|
|
|
|
9
|
return wantarray ? () : 0; |
1699
|
|
|
|
|
|
|
} |
1700
|
|
|
|
|
|
|
|
1701
|
34580
|
100
|
66
|
|
|
116641
|
if ( defined $col and $col =~ m/^\d+$/ ) |
|
|
50
|
|
|
|
|
|
1702
|
|
|
|
|
|
|
{ # arg1 = a number |
1703
|
12801
|
|
|
|
|
28420
|
return $self->{columns}->[$col]; |
1704
|
|
|
|
|
|
|
} |
1705
|
|
|
|
|
|
|
elsif ( defined $col ) |
1706
|
|
|
|
|
|
|
{ # arg1 = string |
1707
|
0
|
|
|
|
|
0
|
for my $c ( @{ $self->{columns} } ) |
|
0
|
|
|
|
|
0
|
|
1708
|
|
|
|
|
|
|
{ |
1709
|
0
|
0
|
|
|
|
0
|
return $c if ( $c->name() eq $col ); |
1710
|
|
|
|
|
|
|
} |
1711
|
|
|
|
|
|
|
} |
1712
|
|
|
|
|
|
|
|
1713
|
21779
|
100
|
|
|
|
33172
|
return wantarray ? @{ $self->{columns} } : scalar @{ $self->{columns} }; |
|
13213
|
|
|
|
|
26188
|
|
|
8566
|
|
|
|
|
24958
|
|
1714
|
|
|
|
|
|
|
} |
1715
|
|
|
|
|
|
|
|
1716
|
|
|
|
|
|
|
sub colname2colnum |
1717
|
|
|
|
|
|
|
{ |
1718
|
0
|
0
|
|
0
|
1
|
0
|
if ( !$_[0]->{columns} ) { return undef; } |
|
0
|
|
|
|
|
0
|
|
1719
|
0
|
|
|
|
|
0
|
for my $i ( 0 .. $#{ $_[0]->{columns} } ) |
|
0
|
|
|
|
|
0
|
|
1720
|
|
|
|
|
|
|
{ |
1721
|
0
|
0
|
|
|
|
0
|
return $i if ( $_[0]->{columns}->[$i]->name() eq $_[1] ); |
1722
|
|
|
|
|
|
|
} |
1723
|
0
|
|
|
|
|
0
|
return undef; |
1724
|
|
|
|
|
|
|
} |
1725
|
|
|
|
|
|
|
|
1726
|
|
|
|
|
|
|
sub colname2table($) |
1727
|
|
|
|
|
|
|
{ |
1728
|
2
|
|
|
2
|
1
|
5
|
my ( $self, $col_name ) = @_; |
1729
|
2
|
50
|
|
|
|
7
|
return undef unless defined $col_name; |
1730
|
|
|
|
|
|
|
|
1731
|
2
|
|
|
|
|
4
|
my ( $tbl, $col ); |
1732
|
2
|
50
|
|
|
|
7
|
if ( $col_name =~ /^(.+)\.(.+)$/ ) |
1733
|
|
|
|
|
|
|
{ |
1734
|
0
|
|
|
|
|
0
|
( $tbl, $col ) = ( $1, $2 ); |
1735
|
|
|
|
|
|
|
} |
1736
|
|
|
|
|
|
|
else |
1737
|
|
|
|
|
|
|
{ |
1738
|
2
|
|
|
|
|
5
|
$col = $col_name; |
1739
|
|
|
|
|
|
|
} |
1740
|
|
|
|
|
|
|
|
1741
|
2
|
|
|
|
|
3
|
my $found_table; |
1742
|
2
|
|
|
|
|
4
|
for my $full_col ( @{ $self->{all_cols} } ) |
|
2
|
|
|
|
|
5
|
|
1743
|
|
|
|
|
|
|
{ |
1744
|
10
|
|
|
|
|
32
|
my ( $stbl, $scol ) = $full_col =~ /^(.+)\.(.+)$/; |
1745
|
10
|
50
|
100
|
|
|
36
|
next unless ( $scol || '' ) eq $col; |
1746
|
0
|
0
|
0
|
|
|
0
|
next if ( defined($tbl) && ( $tbl ne $stbl ) ); |
1747
|
0
|
|
|
|
|
0
|
$found_table = $stbl; |
1748
|
0
|
|
|
|
|
0
|
last; |
1749
|
|
|
|
|
|
|
} |
1750
|
2
|
|
|
|
|
11
|
return $found_table; |
1751
|
|
|
|
|
|
|
} |
1752
|
|
|
|
|
|
|
|
1753
|
|
|
|
|
|
|
sub full_qualified_column_name($) |
1754
|
|
|
|
|
|
|
{ |
1755
|
574
|
|
|
574
|
1
|
1091
|
my ( $self, $col_name ) = @_; |
1756
|
574
|
50
|
|
|
|
1110
|
return unless ( defined($col_name) ); |
1757
|
|
|
|
|
|
|
|
1758
|
|
|
|
|
|
|
# XXX |
1759
|
574
|
100
|
|
|
|
1237
|
defined $self->{ALIASES}->{$col_name} and $col_name = $self->{ALIASES}->{$col_name}; |
1760
|
|
|
|
|
|
|
|
1761
|
574
|
|
|
|
|
837
|
my ( $tbl, $col ); |
1762
|
574
|
100
|
|
|
|
1987
|
unless ( ( $tbl, $col ) = $col_name =~ m/^((?:"[^"]+")|(?:[^.]+))\.(.*)$/ ) |
1763
|
|
|
|
|
|
|
{ |
1764
|
449
|
|
|
|
|
743
|
$col = $col_name; |
1765
|
|
|
|
|
|
|
} |
1766
|
|
|
|
|
|
|
|
1767
|
574
|
100
|
|
|
|
1199
|
unless ( defined( $self->{splitted_all_cols} ) ) |
1768
|
|
|
|
|
|
|
{ |
1769
|
118
|
|
|
|
|
187
|
my @rc; |
1770
|
118
|
|
|
|
|
188
|
for my $full_col ( @{ $self->{all_cols} } ) |
|
118
|
|
|
|
|
277
|
|
1771
|
|
|
|
|
|
|
{ |
1772
|
722
|
100
|
|
|
|
2849
|
if ( my ( $stbl, $scol ) = $full_col =~ m/^((?:"[^"]+")|(?:[^.]+))\.(.*)$/ ) |
1773
|
|
|
|
|
|
|
{ |
1774
|
440
|
|
|
|
|
646
|
push( @{ $self->{splitted_all_cols} }, [ $stbl, $scol ] ); |
|
440
|
|
|
|
|
1144
|
|
1775
|
440
|
100
|
100
|
|
|
1076
|
defined($tbl) and ( $tbl ne $stbl ) and next; |
1776
|
416
|
100
|
|
|
|
1088
|
( $scol eq $col ) and @rc = ( $stbl, $scol ); |
1777
|
|
|
|
|
|
|
} |
1778
|
|
|
|
|
|
|
} |
1779
|
118
|
100
|
|
|
|
569
|
@rc and return @rc; |
1780
|
|
|
|
|
|
|
} |
1781
|
|
|
|
|
|
|
else |
1782
|
|
|
|
|
|
|
{ |
1783
|
456
|
|
|
|
|
636
|
for my $splitted_col ( @{ $self->{splitted_all_cols} } ) |
|
456
|
|
|
|
|
944
|
|
1784
|
|
|
|
|
|
|
{ |
1785
|
1576
|
100
|
100
|
|
|
3503
|
defined($tbl) and ( $tbl ne $splitted_col->[0] ) and next; |
1786
|
1228
|
100
|
|
|
|
3411
|
( $splitted_col->[1] eq $col ) and return @$splitted_col; |
1787
|
|
|
|
|
|
|
} |
1788
|
|
|
|
|
|
|
} |
1789
|
|
|
|
|
|
|
|
1790
|
39
|
|
|
|
|
117
|
return ( $tbl, $col ); |
1791
|
|
|
|
|
|
|
} |
1792
|
|
|
|
|
|
|
|
1793
|
|
|
|
|
|
|
#sub verify_order_cols |
1794
|
|
|
|
|
|
|
#{ |
1795
|
|
|
|
|
|
|
# my ( $self, $table ) = @_; |
1796
|
|
|
|
|
|
|
# return unless $self->{sort_spec_list}; |
1797
|
|
|
|
|
|
|
# my @ocols = $self->order(); |
1798
|
|
|
|
|
|
|
# my @tcols = @{ $table->col_names() }; |
1799
|
|
|
|
|
|
|
# my @n_ocols; |
1800
|
|
|
|
|
|
|
# |
1801
|
|
|
|
|
|
|
# for my $colnum ( 0 .. $#ocols ) |
1802
|
|
|
|
|
|
|
# { |
1803
|
|
|
|
|
|
|
# my $col = $self->order($colnum); |
1804
|
|
|
|
|
|
|
# |
1805
|
|
|
|
|
|
|
# if ( !defined( $col->table() ) ) |
1806
|
|
|
|
|
|
|
# { |
1807
|
|
|
|
|
|
|
# my $cname = $ocols[$colnum]->{col}->name(); |
1808
|
|
|
|
|
|
|
# my $tname = $self->colname2table($cname); |
1809
|
|
|
|
|
|
|
# return $self->do_err("No such column '$cname'.") unless ($tname); |
1810
|
|
|
|
|
|
|
# $self->{sort_spec_list}->[$colnum]->{col}->{table} = $tname; |
1811
|
|
|
|
|
|
|
# push( @n_ocols, $tname ); |
1812
|
|
|
|
|
|
|
# } |
1813
|
|
|
|
|
|
|
# } |
1814
|
|
|
|
|
|
|
# |
1815
|
|
|
|
|
|
|
# return 1; |
1816
|
|
|
|
|
|
|
#} |
1817
|
|
|
|
|
|
|
|
1818
|
407
|
|
|
407
|
1
|
1186
|
sub limit ($) { $_[0]->{limit_clause}->{limit}; } |
1819
|
138
|
|
|
138
|
1
|
479
|
sub offset ($) { $_[0]->{limit_clause}->{offset}; } |
1820
|
|
|
|
|
|
|
|
1821
|
|
|
|
|
|
|
sub order |
1822
|
|
|
|
|
|
|
{ |
1823
|
139
|
100
|
|
139
|
1
|
952
|
return unless ( defined $_[0]->{sort_spec_list} ); |
1824
|
|
|
|
|
|
|
|
1825
|
|
|
|
|
|
|
return |
1826
|
|
|
|
|
|
|
defined( $_[1] ) && looks_like_number( $_[1] ) ? $_[0]->{sort_spec_list}->[ $_[1] ] |
1827
|
18
|
|
|
|
|
62
|
: wantarray ? @{ $_[0]->{sort_spec_list} } |
1828
|
20
|
100
|
66
|
|
|
109
|
: scalar @{ $_[0]->{sort_spec_list} }; |
|
1
|
100
|
|
|
|
5
|
|
1829
|
|
|
|
|
|
|
} |
1830
|
|
|
|
|
|
|
|
1831
|
|
|
|
|
|
|
sub tables |
1832
|
|
|
|
|
|
|
{ |
1833
|
|
|
|
|
|
|
return |
1834
|
|
|
|
|
|
|
defined( $_[1] ) && looks_like_number( $_[1] ) ? $_[0]->{tables}->[ $_[1] ] |
1835
|
4701
|
|
|
|
|
10684
|
: wantarray ? @{ $_[0]->{tables} } |
1836
|
13557
|
100
|
66
|
13557
|
1
|
54229
|
: scalar @{ $_[0]->{tables} }; |
|
4424
|
100
|
|
|
|
9169
|
|
1837
|
|
|
|
|
|
|
} |
1838
|
|
|
|
|
|
|
|
1839
|
|
|
|
|
|
|
sub order_joins |
1840
|
|
|
|
|
|
|
{ |
1841
|
7
|
|
|
7
|
1
|
18
|
my ( $self, $links ) = @_; |
1842
|
7
|
|
|
|
|
12
|
my ( @new_keycols, @new_links ); |
1843
|
7
|
|
|
|
|
16
|
for (@$links) |
1844
|
|
|
|
|
|
|
{ |
1845
|
7
|
|
|
|
|
17
|
my ( $tbl, $col ) = $self->full_qualified_column_name($_); |
1846
|
7
|
|
|
|
|
26
|
push( @new_keycols, $tbl . $self->{dlm} . $col ); |
1847
|
7
|
|
|
|
|
18
|
push( @new_links, $tbl ); |
1848
|
|
|
|
|
|
|
} |
1849
|
7
|
|
|
|
|
19
|
$self->{join}->{keycols} = $links = \@new_keycols; |
1850
|
|
|
|
|
|
|
# my @tmp = @new_keycols; |
1851
|
|
|
|
|
|
|
# foreach (@tmp) { $_ =~ s/\./$self->{dlm}/g; } |
1852
|
|
|
|
|
|
|
# $self->{join}->{keycols} = \@tmp; |
1853
|
|
|
|
|
|
|
# @$links = \@new_keycols; |
1854
|
7
|
|
|
|
|
19
|
my @all_tables; |
1855
|
|
|
|
|
|
|
my %relations; |
1856
|
7
|
|
|
|
|
0
|
my %is_table; |
1857
|
|
|
|
|
|
|
|
1858
|
7
|
|
|
|
|
20
|
while (@new_links) |
1859
|
|
|
|
|
|
|
{ |
1860
|
7
|
|
|
|
|
15
|
my $t1 = shift(@new_links); |
1861
|
7
|
|
|
|
|
11
|
my $t2 = shift(@new_links); |
1862
|
7
|
50
|
33
|
|
|
40
|
return undef unless ( defined($t1) and defined($t2) ); |
1863
|
0
|
0
|
|
|
|
0
|
push @all_tables, $t1 unless ( $is_table{$t1}++ ); |
1864
|
0
|
0
|
|
|
|
0
|
push @all_tables, $t2 unless ( $is_table{$t2}++ ); |
1865
|
0
|
|
|
|
|
0
|
$relations{$t1}{$t2}++; |
1866
|
0
|
|
|
|
|
0
|
$relations{$t2}{$t1}++; |
1867
|
|
|
|
|
|
|
} |
1868
|
0
|
|
|
|
|
0
|
my @tables = @all_tables; |
1869
|
0
|
|
|
|
|
0
|
my @order = shift @tables; |
1870
|
0
|
|
|
|
|
0
|
my %is_ordered = ( $order[0] => 1 ); |
1871
|
0
|
|
|
|
|
0
|
my %visited; |
1872
|
0
|
|
|
|
|
0
|
while (@tables) |
1873
|
|
|
|
|
|
|
{ |
1874
|
0
|
|
|
|
|
0
|
my $t = shift @tables; |
1875
|
0
|
|
|
|
|
0
|
my @rels = keys %{ $relations{$t} }; |
|
0
|
|
|
|
|
0
|
|
1876
|
0
|
|
|
|
|
0
|
for my $t2 (@rels) |
1877
|
|
|
|
|
|
|
{ |
1878
|
0
|
0
|
|
|
|
0
|
next unless $is_ordered{$t2}; |
1879
|
0
|
|
|
|
|
0
|
push @order, $t; |
1880
|
0
|
|
|
|
|
0
|
$is_ordered{$t}++; |
1881
|
0
|
|
|
|
|
0
|
last; |
1882
|
|
|
|
|
|
|
} |
1883
|
0
|
0
|
|
|
|
0
|
if ( !$is_ordered{$t} ) |
1884
|
|
|
|
|
|
|
{ |
1885
|
0
|
0
|
|
|
|
0
|
push( @tables, $t ) if ( $visited{$t}++ < @all_tables ); |
1886
|
|
|
|
|
|
|
} |
1887
|
|
|
|
|
|
|
} |
1888
|
0
|
0
|
|
|
|
0
|
if ( @order < @all_tables ) |
1889
|
|
|
|
|
|
|
{ |
1890
|
0
|
|
|
|
|
0
|
my @missing; |
1891
|
0
|
|
|
|
|
0
|
my %in_order = map { $_ => 1 } @order; |
|
0
|
|
|
|
|
0
|
|
1892
|
0
|
|
|
|
|
0
|
foreach my $tbl (@all_tables) |
1893
|
|
|
|
|
|
|
{ |
1894
|
0
|
0
|
|
|
|
0
|
next if ( $in_order{$tbl} ); |
1895
|
0
|
|
|
|
|
0
|
push( @missing, $tbl ); |
1896
|
|
|
|
|
|
|
} |
1897
|
0
|
|
|
|
|
0
|
return $self->do_err( sprintf( 'Unconnected tables (%s) in equijoin statement!', join( ', ', @missing ) ) ); |
1898
|
|
|
|
|
|
|
} |
1899
|
0
|
|
|
|
|
0
|
$self->{join}->{table_order} = \@order; |
1900
|
0
|
|
|
|
|
0
|
return \@order; |
1901
|
|
|
|
|
|
|
} |
1902
|
|
|
|
|
|
|
|
1903
|
|
|
|
|
|
|
sub do_err |
1904
|
|
|
|
|
|
|
{ |
1905
|
12
|
|
|
12
|
1
|
168
|
my $self = shift; |
1906
|
12
|
|
|
|
|
27
|
my $err = shift; |
1907
|
12
|
|
|
|
|
23
|
my $errtype = shift; |
1908
|
12
|
|
|
|
|
90
|
my @c = caller 6; |
1909
|
|
|
|
|
|
|
|
1910
|
|
|
|
|
|
|
#$err = "[" . $self->{original_string} . "]\n$err\n\n"; |
1911
|
|
|
|
|
|
|
# $err = "$err\n\n"; |
1912
|
12
|
|
|
|
|
31
|
my $prog = $c[1]; |
1913
|
12
|
|
|
|
|
23
|
my $line = $c[2]; |
1914
|
12
|
100
|
|
|
|
47
|
$prog = defined($prog) ? " called from $prog" : ''; |
1915
|
12
|
100
|
|
|
|
42
|
$prog .= defined($line) ? " at $line" : ''; |
1916
|
12
|
|
|
|
|
41
|
$err = "\nExecution ERROR: $err$prog.\n\n"; |
1917
|
|
|
|
|
|
|
|
1918
|
12
|
|
|
|
|
24
|
$self->{errstr} = $err; |
1919
|
12
|
50
|
|
|
|
47
|
carp $err if $self->{PrintError}; |
1920
|
12
|
100
|
|
|
|
173
|
croak "$err" if $self->{RaiseError}; |
1921
|
11
|
|
|
|
|
79
|
return; |
1922
|
|
|
|
|
|
|
} |
1923
|
|
|
|
|
|
|
|
1924
|
14
|
|
|
14
|
1
|
11756
|
sub errstr() { return $_[0]->{errstr}; } |
1925
|
|
|
|
|
|
|
|
1926
|
1
|
|
|
1
|
1
|
18
|
sub where_hash() { return $_[0]->{where_clause}; } |
1927
|
|
|
|
|
|
|
|
1928
|
0
|
|
|
0
|
1
|
0
|
sub column_defs() { return $_[0]->{column_defs}; } |
1929
|
|
|
|
|
|
|
|
1930
|
|
|
|
|
|
|
sub where() |
1931
|
|
|
|
|
|
|
{ |
1932
|
5
|
50
|
|
5
|
1
|
39
|
return undef unless $_[0]->{where_terms}; |
1933
|
5
|
|
|
|
|
87
|
return $_[0]->{where_terms}; |
1934
|
|
|
|
|
|
|
} |
1935
|
|
|
|
|
|
|
|
1936
|
|
|
|
|
|
|
sub get_user_func_table |
1937
|
|
|
|
|
|
|
{ |
1938
|
2
|
|
|
2
|
1
|
5
|
my ( $self, $name, $u_func ) = @_; |
1939
|
2
|
|
|
|
|
24
|
my $term = $self->{termFactory}->buildCondition($u_func); |
1940
|
|
|
|
|
|
|
|
1941
|
2
|
|
|
|
|
6
|
my @data_aryref = @{ $term->value(undef) }; |
|
2
|
|
|
|
|
16
|
|
1942
|
2
|
|
|
|
|
5
|
my $col_names = shift @data_aryref; |
1943
|
|
|
|
|
|
|
|
1944
|
|
|
|
|
|
|
# my $tempTable = SQL::Statement::TempTable->new( |
1945
|
|
|
|
|
|
|
# $name, $col_names, $col_names, $data_aryref |
1946
|
|
|
|
|
|
|
# ); |
1947
|
2
|
|
|
|
|
16
|
my $tempTable = SQL::Statement::RAM::Table->new( $name, $col_names, \@data_aryref ); |
1948
|
2
|
|
33
|
|
|
25
|
$tempTable->{all_cols} ||= $col_names; |
1949
|
2
|
|
|
|
|
10
|
return $tempTable; |
1950
|
|
|
|
|
|
|
} |
1951
|
|
|
|
|
|
|
|
1952
|
|
|
|
|
|
|
sub capability($) |
1953
|
|
|
|
|
|
|
{ |
1954
|
0
|
|
|
0
|
1
|
0
|
my ( $self, $capname ) = @_; |
1955
|
0
|
0
|
|
|
|
0
|
return $self->{capabilities}->{$capname} if ( defined( $self->{capabilities}->{$capname} ) ); |
1956
|
|
|
|
|
|
|
|
1957
|
0
|
|
|
|
|
0
|
return; |
1958
|
|
|
|
|
|
|
} |
1959
|
|
|
|
|
|
|
|
1960
|
|
|
|
|
|
|
sub DESTROY |
1961
|
|
|
|
|
|
|
{ |
1962
|
870
|
|
|
870
|
|
95286
|
my $self = $_[0]; |
1963
|
|
|
|
|
|
|
|
1964
|
870
|
|
|
|
|
1987
|
undef $self->{NAME}; |
1965
|
870
|
|
|
|
|
1881
|
undef $self->{ORG_NAME}; |
1966
|
870
|
|
|
|
|
1698
|
undef $self->{all_cols}; |
1967
|
870
|
|
|
|
|
1812
|
undef $self->{already_prepared}; |
1968
|
870
|
|
|
|
|
1375
|
undef $self->{argnum}; |
1969
|
870
|
|
|
|
|
2014
|
undef $self->{col_obj}; |
1970
|
870
|
|
|
|
|
1486
|
undef $self->{column_names}; |
1971
|
870
|
|
|
|
|
3237
|
undef $self->{columns}; |
1972
|
870
|
|
|
|
|
1452
|
undef $self->{cur_table}; |
1973
|
870
|
|
|
|
|
1744
|
undef $self->{data}; |
1974
|
870
|
|
|
|
|
1535
|
undef $self->{group_by}; |
1975
|
|
|
|
|
|
|
#undef $self->{has_OR}; |
1976
|
870
|
|
|
|
|
1936
|
undef $self->{join}; |
1977
|
870
|
|
|
|
|
1465
|
undef $self->{limit_clause}; |
1978
|
870
|
|
|
|
|
1495
|
undef $self->{num_placeholders}; |
1979
|
870
|
|
|
|
|
1349
|
undef $self->{num_val_placeholders}; |
1980
|
870
|
|
|
|
|
1513
|
undef $self->{org_table_names}; |
1981
|
870
|
|
|
|
|
1367
|
undef $self->{params}; |
1982
|
870
|
|
|
|
|
2255
|
undef $self->{opts}; |
1983
|
870
|
|
|
|
|
1484
|
undef $self->{procedure}; |
1984
|
870
|
|
|
|
|
1282
|
undef $self->{set_function}; |
1985
|
870
|
|
|
|
|
1488
|
undef $self->{sort_spec_list}; |
1986
|
870
|
|
|
|
|
1341
|
undef $self->{subquery}; |
1987
|
870
|
|
|
|
|
1879
|
undef $self->{tables}; |
1988
|
870
|
|
|
|
|
1451
|
undef $self->{table_names}; |
1989
|
870
|
|
|
|
|
1321
|
undef $self->{table_func}; |
1990
|
870
|
|
|
|
|
1999
|
undef $self->{where_clause}; |
1991
|
870
|
|
|
|
|
1663
|
undef $self->{where_terms}; |
1992
|
870
|
|
|
|
|
7738
|
undef $self->{values}; |
1993
|
|
|
|
|
|
|
} |
1994
|
|
|
|
|
|
|
|
1995
|
|
|
|
|
|
|
package SQL::Statement::Aggregate; |
1996
|
|
|
|
|
|
|
|
1997
|
16
|
|
|
16
|
|
165
|
use Scalar::Util qw(looks_like_number); |
|
16
|
|
|
|
|
46
|
|
|
16
|
|
|
|
|
1080
|
|
1998
|
16
|
|
|
16
|
|
128
|
use Params::Util qw(_HASH); |
|
16
|
|
|
|
|
52
|
|
|
16
|
|
|
|
|
841
|
|
1999
|
16
|
|
|
16
|
|
119
|
use Clone qw(clone); |
|
16
|
|
|
|
|
35
|
|
|
16
|
|
|
|
|
13906
|
|
2000
|
|
|
|
|
|
|
|
2001
|
|
|
|
|
|
|
sub new |
2002
|
|
|
|
|
|
|
{ |
2003
|
19
|
|
|
19
|
|
53
|
my ( $class, $owner, $rows ) = @_; |
2004
|
19
|
|
|
|
|
68
|
my $self = { |
2005
|
|
|
|
|
|
|
owner => $owner, |
2006
|
|
|
|
|
|
|
records => $rows, |
2007
|
|
|
|
|
|
|
}; |
2008
|
19
|
|
|
|
|
61
|
return bless( $self, $class ); |
2009
|
|
|
|
|
|
|
} |
2010
|
|
|
|
|
|
|
|
2011
|
|
|
|
|
|
|
my $empty_agg = { |
2012
|
|
|
|
|
|
|
uniq => [], |
2013
|
|
|
|
|
|
|
count => 0, |
2014
|
|
|
|
|
|
|
sum => undef, |
2015
|
|
|
|
|
|
|
min => undef, |
2016
|
|
|
|
|
|
|
max => undef, |
2017
|
|
|
|
|
|
|
}; |
2018
|
|
|
|
|
|
|
|
2019
|
|
|
|
|
|
|
sub do_calc() |
2020
|
|
|
|
|
|
|
{ |
2021
|
19
|
|
|
19
|
|
39
|
my $self = $_[0]; |
2022
|
|
|
|
|
|
|
|
2023
|
19
|
|
|
|
|
30
|
foreach my $line ( 0 .. ( scalar( @{ $self->{records} } ) - 1 ) ) |
|
19
|
|
|
|
|
88
|
|
2024
|
|
|
|
|
|
|
{ |
2025
|
8073
|
|
|
|
|
13989
|
my $row = $self->{records}->[$line]; |
2026
|
8073
|
|
|
|
|
12925
|
my $result = $self->getAffectedResult($row); |
2027
|
|
|
|
|
|
|
|
2028
|
8073
|
|
|
|
|
10505
|
foreach my $colidx ( 0 .. ( scalar( @{ $self->{owner}->{columns} } ) - 1 ) ) |
|
8073
|
|
|
|
|
15539
|
|
2029
|
|
|
|
|
|
|
{ |
2030
|
20115
|
|
|
|
|
31525
|
my $coldef = $self->{owner}->{columns}->[$colidx]->{coldef}; |
2031
|
20115
|
|
|
|
|
29214
|
my $colval = $row->[$colidx]; |
2032
|
|
|
|
|
|
|
|
2033
|
20115
|
100
|
|
|
|
31470
|
if ( $coldef->{type} eq 'setfunc' ) |
2034
|
|
|
|
|
|
|
{ |
2035
|
16086
|
100
|
|
|
|
27428
|
if ( $coldef->{distinct} eq 'DISTINCT' ) |
2036
|
|
|
|
|
|
|
{ |
2037
|
9
|
100
|
|
|
|
30
|
next if defined( $result->{uniq}->[$colidx]->{$colval} ); |
2038
|
6
|
|
|
|
|
14
|
$result->{uniq}->[$colidx]->{$colval} = 1; |
2039
|
|
|
|
|
|
|
} |
2040
|
|
|
|
|
|
|
|
2041
|
|
|
|
|
|
|
$result->{agg}->[$colidx] = clone($empty_agg) |
2042
|
16083
|
100
|
|
|
|
32523
|
unless ( defined( _HASH( $result->{agg}->[$colidx] ) ) ); |
2043
|
16083
|
|
|
|
|
21525
|
my $agg = $result->{agg}->[$colidx]; |
2044
|
|
|
|
|
|
|
|
2045
|
16083
|
|
|
|
|
20645
|
++$agg->{count}; |
2046
|
16083
|
100
|
100
|
|
|
33699
|
unless ( defined( $agg->{max} ) |
2047
|
|
|
|
|
|
|
&& ( SQL::Statement::_anycmp( $colval, $agg->{max} ) < 0 ) ) |
2048
|
|
|
|
|
|
|
{ |
2049
|
16038
|
|
|
|
|
22977
|
$agg->{max} = $colval; |
2050
|
|
|
|
|
|
|
} |
2051
|
16083
|
100
|
100
|
|
|
36358
|
unless ( defined( $agg->{min} ) |
2052
|
|
|
|
|
|
|
&& ( SQL::Statement::_anycmp( $colval, $agg->{min} ) > 0 ) ) |
2053
|
|
|
|
|
|
|
{ |
2054
|
4069
|
|
|
|
|
6073
|
$agg->{min} = $colval; |
2055
|
|
|
|
|
|
|
} |
2056
|
16083
|
100
|
|
|
|
41601
|
$agg->{sum} += $colval if ( looks_like_number($colval) ); |
2057
|
|
|
|
|
|
|
} |
2058
|
|
|
|
|
|
|
else |
2059
|
|
|
|
|
|
|
{ |
2060
|
|
|
|
|
|
|
$result->{pure}->[$colidx] = $colval |
2061
|
4029
|
100
|
|
|
|
8130
|
unless ( defined( $result->{pure}->[$colidx] ) ); |
2062
|
|
|
|
|
|
|
} |
2063
|
|
|
|
|
|
|
} |
2064
|
|
|
|
|
|
|
} |
2065
|
|
|
|
|
|
|
} |
2066
|
|
|
|
|
|
|
|
2067
|
|
|
|
|
|
|
sub build_row # (\%) |
2068
|
|
|
|
|
|
|
{ |
2069
|
32
|
|
|
32
|
|
58
|
my ( $self, $result ) = @_; |
2070
|
32
|
|
|
|
|
60
|
my @row; |
2071
|
|
|
|
|
|
|
|
2072
|
32
|
|
|
|
|
55
|
foreach my $colidx ( 0 .. ( scalar( @{ $self->{owner}->{columns} } ) - 1 ) ) |
|
32
|
|
|
|
|
83
|
|
2073
|
|
|
|
|
|
|
{ |
2074
|
65
|
|
|
|
|
308
|
my $coldef = $self->{owner}->{columns}->[$colidx]->{coldef}; |
2075
|
|
|
|
|
|
|
|
2076
|
65
|
100
|
|
|
|
127
|
if ( $coldef->{type} eq 'setfunc' ) |
2077
|
|
|
|
|
|
|
{ |
2078
|
41
|
100
|
|
|
|
130
|
if ( $coldef->{name} eq 'COUNT' ) |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
2079
|
|
|
|
|
|
|
{ |
2080
|
20
|
|
100
|
|
|
96
|
push( @row, $result->{agg}->[$colidx]->{count} || 0 ); |
2081
|
|
|
|
|
|
|
} |
2082
|
|
|
|
|
|
|
elsif ( $coldef->{name} eq 'MAX' ) |
2083
|
|
|
|
|
|
|
{ |
2084
|
11
|
|
|
|
|
39
|
push( @row, $result->{agg}->[$colidx]->{max} ); |
2085
|
|
|
|
|
|
|
} |
2086
|
|
|
|
|
|
|
elsif ( $coldef->{name} eq 'MIN' ) |
2087
|
|
|
|
|
|
|
{ |
2088
|
1
|
|
|
|
|
9
|
push( @row, $result->{agg}->[$colidx]->{min} ); |
2089
|
|
|
|
|
|
|
} |
2090
|
|
|
|
|
|
|
elsif ( $coldef->{name} eq 'SUM' ) |
2091
|
|
|
|
|
|
|
{ |
2092
|
8
|
|
|
|
|
26
|
push( @row, $result->{agg}->[$colidx]->{sum} ); |
2093
|
|
|
|
|
|
|
} |
2094
|
|
|
|
|
|
|
elsif ( $coldef->{name} eq 'AVG' ) |
2095
|
|
|
|
|
|
|
{ |
2096
|
1
|
|
|
|
|
3
|
my $count = $result->{agg}->[$colidx]->{count}; |
2097
|
1
|
|
|
|
|
4
|
my $sum = $result->{agg}->[$colidx]->{sum}; |
2098
|
1
|
50
|
33
|
|
|
9
|
my $avg = $sum / $count if ( $count && $sum ); |
2099
|
1
|
|
|
|
|
5
|
push( @row, $avg ); |
2100
|
|
|
|
|
|
|
} |
2101
|
|
|
|
|
|
|
else |
2102
|
|
|
|
|
|
|
{ |
2103
|
0
|
|
|
|
|
0
|
return $self->{owner}->do_err("Invalid SET FUNCTION '$coldef->{name}'"); |
2104
|
|
|
|
|
|
|
} |
2105
|
|
|
|
|
|
|
} |
2106
|
|
|
|
|
|
|
else |
2107
|
|
|
|
|
|
|
{ |
2108
|
24
|
|
|
|
|
59
|
push( @row, $result->{pure}->[$colidx] ); |
2109
|
|
|
|
|
|
|
} |
2110
|
|
|
|
|
|
|
} |
2111
|
|
|
|
|
|
|
|
2112
|
32
|
|
|
|
|
67
|
return \@row; |
2113
|
|
|
|
|
|
|
} |
2114
|
|
|
|
|
|
|
|
2115
|
|
|
|
|
|
|
sub calc() |
2116
|
|
|
|
|
|
|
{ |
2117
|
12
|
|
|
12
|
|
27
|
my $self = $_[0]; |
2118
|
|
|
|
|
|
|
|
2119
|
12
|
|
|
|
|
39
|
$self->{final_row} = {}; |
2120
|
|
|
|
|
|
|
|
2121
|
12
|
|
|
|
|
41
|
$self->do_calc(); |
2122
|
|
|
|
|
|
|
|
2123
|
12
|
|
|
|
|
50
|
my $final_row = $self->build_row( $self->{final_row} ); |
2124
|
|
|
|
|
|
|
|
2125
|
12
|
|
|
|
|
769
|
return [$final_row]; |
2126
|
|
|
|
|
|
|
} |
2127
|
|
|
|
|
|
|
|
2128
|
|
|
|
|
|
|
sub getAffectedResult # (\@) |
2129
|
|
|
|
|
|
|
{ |
2130
|
4049
|
|
|
4049
|
|
6098
|
return $_[0]->{final_row}; |
2131
|
|
|
|
|
|
|
} |
2132
|
|
|
|
|
|
|
|
2133
|
|
|
|
|
|
|
package SQL::Statement::Group; |
2134
|
|
|
|
|
|
|
|
2135
|
16
|
|
|
16
|
|
158
|
use vars qw(@ISA); |
|
16
|
|
|
|
|
59
|
|
|
16
|
|
|
|
|
1002
|
|
2136
|
|
|
|
|
|
|
|
2137
|
16
|
|
|
16
|
|
135
|
use Params::Util qw(_HASH); |
|
16
|
|
|
|
|
45
|
|
|
16
|
|
|
|
|
5854
|
|
2138
|
|
|
|
|
|
|
|
2139
|
|
|
|
|
|
|
@ISA = qw(SQL::Statement::Aggregate); |
2140
|
|
|
|
|
|
|
|
2141
|
|
|
|
|
|
|
sub new |
2142
|
|
|
|
|
|
|
{ |
2143
|
7
|
|
|
7
|
|
17
|
my ( $class, $owner, $rows, $keycols ) = @_; |
2144
|
|
|
|
|
|
|
|
2145
|
7
|
|
|
|
|
46
|
my $self = $class->SUPER::new( $owner, $rows ); |
2146
|
7
|
|
|
|
|
26
|
$self->{keycols} = $keycols; |
2147
|
|
|
|
|
|
|
|
2148
|
7
|
|
|
|
|
17
|
return $self; |
2149
|
|
|
|
|
|
|
} |
2150
|
|
|
|
|
|
|
|
2151
|
|
|
|
|
|
|
sub calc() |
2152
|
|
|
|
|
|
|
{ |
2153
|
7
|
|
|
7
|
|
12
|
my $self = $_[0]; |
2154
|
7
|
|
|
|
|
10
|
my @final_table; |
2155
|
|
|
|
|
|
|
|
2156
|
7
|
|
|
|
|
32
|
$self->do_calc(); |
2157
|
|
|
|
|
|
|
|
2158
|
7
|
100
|
|
|
|
16
|
if ( scalar( keys( %{ $self->{final_rows} } ) ) ) |
|
7
|
|
|
|
|
29
|
|
2159
|
|
|
|
|
|
|
{ |
2160
|
6
|
|
|
|
|
12
|
foreach my $key ( keys( %{ $self->{final_rows} } ) ) |
|
6
|
|
|
|
|
18
|
|
2161
|
|
|
|
|
|
|
{ |
2162
|
19
|
|
|
|
|
67
|
my $final_row = $self->build_row( $self->{final_rows}->{$key} ); |
2163
|
19
|
|
|
|
|
38
|
push( @final_table, $final_row ); |
2164
|
|
|
|
|
|
|
} |
2165
|
|
|
|
|
|
|
} |
2166
|
|
|
|
|
|
|
else |
2167
|
|
|
|
|
|
|
{ |
2168
|
1
|
|
|
|
|
7
|
my $final_row = $self->build_row( {} ); |
2169
|
1
|
|
|
|
|
5
|
push( @final_table, $final_row ); |
2170
|
|
|
|
|
|
|
} |
2171
|
|
|
|
|
|
|
|
2172
|
7
|
|
|
|
|
744
|
return \@final_table; |
2173
|
|
|
|
|
|
|
} |
2174
|
|
|
|
|
|
|
|
2175
|
|
|
|
|
|
|
sub getAffectedResult # (\@) |
2176
|
|
|
|
|
|
|
{ |
2177
|
4024
|
|
|
4024
|
|
5857
|
my ( $self, $row ) = @_; |
2178
|
|
|
|
|
|
|
|
2179
|
4024
|
|
|
|
|
5472
|
my $rowkey = join( "\0", @$row[ @{ $self->{keycols} } ] ); |
|
4024
|
|
|
|
|
10249
|
|
2180
|
|
|
|
|
|
|
|
2181
|
|
|
|
|
|
|
$self->{final_rows}->{$rowkey} = {} |
2182
|
4024
|
100
|
|
|
|
9353
|
unless ( defined( _HASH( $self->{final_rows}->{$rowkey} ) ) ); |
2183
|
|
|
|
|
|
|
|
2184
|
4024
|
|
|
|
|
6745
|
return $self->{final_rows}->{$rowkey}; |
2185
|
|
|
|
|
|
|
} |
2186
|
|
|
|
|
|
|
|
2187
|
|
|
|
|
|
|
package SQL::Statement::TempTable; |
2188
|
|
|
|
|
|
|
|
2189
|
16
|
|
|
16
|
|
140
|
use vars qw(@ISA); |
|
16
|
|
|
|
|
56
|
|
|
16
|
|
|
|
|
1043
|
|
2190
|
|
|
|
|
|
|
|
2191
|
|
|
|
|
|
|
BEGIN |
2192
|
|
|
|
|
|
|
{ |
2193
|
16
|
|
|
16
|
|
122
|
require SQL::Eval; |
2194
|
|
|
|
|
|
|
|
2195
|
16
|
|
|
|
|
14283
|
@SQL::Statement::TempTable::ISA = qw(SQL::Eval::Table); |
2196
|
|
|
|
|
|
|
} |
2197
|
|
|
|
|
|
|
|
2198
|
|
|
|
|
|
|
sub new |
2199
|
|
|
|
|
|
|
{ |
2200
|
44
|
|
|
44
|
|
123
|
my ( $class, $name, $col_names, $table_cols, $table ) = @_; |
2201
|
44
|
|
|
|
|
68
|
my %col_nums; |
2202
|
44
|
|
|
|
|
315
|
$col_nums{ $col_names->[$_] } = $_ for ( 0 .. scalar @$col_names - 1 ); |
2203
|
44
|
|
|
|
|
158
|
my @display_order = @col_nums{@$table_cols}; |
2204
|
44
|
|
|
|
|
239
|
my $self = { |
2205
|
|
|
|
|
|
|
col_names => $col_names, |
2206
|
|
|
|
|
|
|
table_cols => \@display_order, |
2207
|
|
|
|
|
|
|
col_nums => \%col_nums, |
2208
|
|
|
|
|
|
|
table => $table, |
2209
|
|
|
|
|
|
|
NAME => $name, |
2210
|
|
|
|
|
|
|
rowpos => 0, |
2211
|
|
|
|
|
|
|
maxrow => scalar @$table |
2212
|
|
|
|
|
|
|
}; |
2213
|
44
|
|
|
|
|
174
|
return $class->SUPER::new($self); |
2214
|
|
|
|
|
|
|
} |
2215
|
|
|
|
|
|
|
|
2216
|
6
|
|
|
6
|
|
26
|
sub is_shared($) { $_[0]->{is_shared}->{ $_[1] }; } |
2217
|
0
|
|
|
0
|
|
0
|
sub get_pos() { $_[0]->{rowpos} } |
2218
|
|
|
|
|
|
|
|
2219
|
|
|
|
|
|
|
sub column_num($) |
2220
|
|
|
|
|
|
|
{ |
2221
|
129
|
|
|
129
|
|
239
|
my ( $s, $col ) = @_; |
2222
|
129
|
|
|
|
|
230
|
my $new_col = $s->{col_nums}->{$col}; |
2223
|
129
|
100
|
|
|
|
290
|
unless ( defined($new_col) ) |
2224
|
|
|
|
|
|
|
{ |
2225
|
6
|
|
|
|
|
22
|
my @tmp = split( '~', $col ); |
2226
|
6
|
100
|
|
|
|
22
|
return unless ( 2 == scalar(@tmp) ); |
2227
|
1
|
|
|
|
|
4
|
$new_col = lc( $tmp[0] ) . '~' . $tmp[1]; |
2228
|
1
|
|
|
|
|
3
|
$new_col = $s->{col_nums}->{$new_col}; |
2229
|
|
|
|
|
|
|
} |
2230
|
124
|
|
|
|
|
207
|
return $new_col; |
2231
|
|
|
|
|
|
|
} |
2232
|
|
|
|
|
|
|
|
2233
|
|
|
|
|
|
|
sub fetch_row() |
2234
|
|
|
|
|
|
|
{ |
2235
|
|
|
|
|
|
|
return $_[0]->{row} = |
2236
|
|
|
|
|
|
|
( $_[0]->{rowpos} >= $_[0]->{maxrow} ) |
2237
|
|
|
|
|
|
|
? undef |
2238
|
450
|
100
|
|
450
|
|
1412
|
: $_[0]->{table}->[ $_[0]->{rowpos}++ ]; |
2239
|
|
|
|
|
|
|
} |
2240
|
|
|
|
|
|
|
|
2241
|
1189
|
|
|
1189
|
|
3671
|
sub column($) { return $_[0]->{row}->[ $_[0]->{col_nums}->{ $_[1] } ]; } |
2242
|
|
|
|
|
|
|
|
2243
|
|
|
|
|
|
|
package SQL::Statement::Order; |
2244
|
|
|
|
|
|
|
|
2245
|
|
|
|
|
|
|
sub new ($$) |
2246
|
|
|
|
|
|
|
{ |
2247
|
13
|
|
|
13
|
|
31
|
my $proto = shift; |
2248
|
13
|
|
|
|
|
62
|
my $self = {@_}; |
2249
|
13
|
|
33
|
|
|
109
|
bless( $self, ( ref($proto) || $proto ) ); |
2250
|
|
|
|
|
|
|
} |
2251
|
40
|
|
|
40
|
|
94
|
sub table ($) { $_[0]->{col}->table(); } |
2252
|
40
|
|
|
40
|
|
149
|
sub column ($) { $_[0]->{col}->display_name(); } |
2253
|
20
|
|
|
20
|
|
80
|
sub desc ($) { $_[0]->{desc}; } |
2254
|
0
|
|
|
0
|
|
0
|
sub direction ($) { $_[0]->{direction}; } |
2255
|
|
|
|
|
|
|
|
2256
|
|
|
|
|
|
|
package SQL::Statement::Limit; |
2257
|
|
|
|
|
|
|
|
2258
|
|
|
|
|
|
|
sub new ($$) |
2259
|
|
|
|
|
|
|
{ |
2260
|
9
|
|
|
9
|
|
23
|
my ( $proto, $self ) = @_; |
2261
|
9
|
|
33
|
|
|
60
|
bless( $self, ( ref($proto) || $proto ) ); |
2262
|
|
|
|
|
|
|
} |
2263
|
|
|
|
|
|
|
|
2264
|
|
|
|
|
|
|
#sub limit ($) { shift->{limit}; } |
2265
|
|
|
|
|
|
|
#sub offset ($) { shift->{offset}; } |
2266
|
|
|
|
|
|
|
|
2267
|
|
|
|
|
|
|
package SQL::Statement::Param; |
2268
|
|
|
|
|
|
|
|
2269
|
|
|
|
|
|
|
sub new |
2270
|
|
|
|
|
|
|
{ |
2271
|
36
|
|
|
36
|
|
69
|
my ( $class, $idx ) = @_; |
2272
|
36
|
|
|
|
|
82
|
my $self = { 'idx' => $idx }; |
2273
|
36
|
|
|
|
|
115
|
return bless( $self, $class ); |
2274
|
|
|
|
|
|
|
} |
2275
|
|
|
|
|
|
|
|
2276
|
0
|
|
|
0
|
|
0
|
sub idx ($) { $_[0]->{idx}; } |
2277
|
|
|
|
|
|
|
|
2278
|
|
|
|
|
|
|
package SQL::Statement::Table; |
2279
|
|
|
|
|
|
|
|
2280
|
|
|
|
|
|
|
sub new |
2281
|
|
|
|
|
|
|
{ |
2282
|
5222
|
|
|
5222
|
|
10073
|
my ( $class, $table_name ) = @_; |
2283
|
|
|
|
|
|
|
|
2284
|
5222
|
100
|
|
|
|
14302
|
if ( $table_name !~ m/"/ ) |
2285
|
|
|
|
|
|
|
{ |
2286
|
5194
|
|
|
|
|
10941
|
$table_name = lc $table_name; |
2287
|
|
|
|
|
|
|
} |
2288
|
|
|
|
|
|
|
|
2289
|
5222
|
|
|
|
|
12357
|
my $self = { |
2290
|
|
|
|
|
|
|
name => $table_name, |
2291
|
|
|
|
|
|
|
}; |
2292
|
|
|
|
|
|
|
|
2293
|
5222
|
|
|
|
|
16432
|
return bless( $self, $class ); |
2294
|
|
|
|
|
|
|
} |
2295
|
|
|
|
|
|
|
|
2296
|
9281
|
|
|
9281
|
|
24272
|
sub name { $_[0]->{name} } |
2297
|
|
|
|
|
|
|
|
2298
|
|
|
|
|
|
|
1; |
2299
|
|
|
|
|
|
|
__END__ |