line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Class::ReluctantORM::SQL::Parser; |
2
|
1
|
|
|
1
|
|
5
|
use strict; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
30
|
|
3
|
1
|
|
|
1
|
|
6
|
use warnings; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
24
|
|
4
|
|
|
|
|
|
|
|
5
|
1
|
|
|
1
|
|
5
|
use base 'SQL::Parser'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
1329
|
|
6
|
|
|
|
|
|
|
|
7
|
1
|
|
|
1
|
|
65368
|
use Scalar::Util qw(blessed); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
71
|
|
8
|
|
|
|
|
|
|
|
9
|
1
|
|
|
1
|
|
7
|
use Class::ReluctantORM::Utilities qw(install_method); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
47
|
|
10
|
|
|
|
|
|
|
|
11
|
1
|
|
|
1
|
|
7
|
use Class::ReluctantORM::SQL::Aliases; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
150
|
|
12
|
|
|
|
|
|
|
|
13
|
1
|
|
|
1
|
|
1028
|
use SQL::Statement::TermFactory; |
|
1
|
|
|
|
|
124998
|
|
|
1
|
|
|
|
|
1011
|
|
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
our $DEBUG ||= 0; |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
sub new { |
18
|
1
|
|
|
1
|
1
|
4
|
my $class = shift; |
19
|
1
|
|
|
|
|
11
|
my $self = $class->SUPER::new(@_); |
20
|
|
|
|
|
|
|
|
21
|
1
|
|
|
|
|
6143
|
$self->{RaiseError} = 1; |
22
|
1
|
|
|
|
|
3
|
$self->{PrintError} = 0; |
23
|
1
|
|
|
|
|
11
|
$self->feature('reserved_words', 'TRUE', 0); |
24
|
1
|
|
|
|
|
15
|
$self->feature('reserved_words', 'FALSE', 0); |
25
|
1
|
|
|
|
|
11
|
$self->feature('valid_data_types', 'BOOLEAN', 1); |
26
|
|
|
|
|
|
|
|
27
|
1
|
|
|
|
|
11
|
return $self; |
28
|
|
|
|
|
|
|
} |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
sub LITERAL { |
31
|
0
|
|
|
0
|
0
|
|
my ( $self, $str ) = @_; |
32
|
0
|
0
|
|
|
|
|
return 'BOOLEAN' if ($str =~ m/^(TRUE|FALSE)$/); |
33
|
0
|
|
|
|
|
|
return $self->SUPER::LITERAL($str); |
34
|
|
|
|
|
|
|
} |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
#==========================================================# |
38
|
|
|
|
|
|
|
# parse_where Support |
39
|
|
|
|
|
|
|
#==========================================================# |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
our %SS_LITERAL_TYPES = map { uc($_) => 1 } qw(string number null boolean); |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
sub __build_crit_from_parse_tree { |
46
|
0
|
|
|
0
|
|
|
my $parser = shift; |
47
|
0
|
|
|
|
|
|
my $stmt = shift; |
48
|
0
|
|
|
|
|
|
my $cro_where = shift; |
49
|
0
|
|
|
|
|
|
$parser->{__where_under_construction} = $cro_where; |
50
|
0
|
|
|
|
|
|
my $ss_where = $stmt->{where_clause}; # ENCAPSULATION VIOLATION into SQL::Parser v1.15 |
51
|
0
|
0
|
|
|
|
|
if ($DEBUG > 2) { print STDERR __PACKAGE__ . ':' . __LINE__ . "Have SQL::Statement parse tree as:\n" . Dumper($ss_where); } |
|
0
|
|
|
|
|
|
|
52
|
0
|
|
|
|
|
|
return $parser->__bcfpt_recursor($ss_where); |
53
|
|
|
|
|
|
|
} |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
sub __bcfpt_recursor { |
56
|
0
|
|
|
0
|
|
|
my $parser = shift; |
57
|
0
|
|
|
|
|
|
my $ss_node = shift; |
58
|
|
|
|
|
|
|
|
59
|
0
|
|
|
|
|
|
my $is_ref = ref($ss_node); |
60
|
0
|
|
0
|
|
|
|
my $is_hash = $is_ref && (ref($ss_node) eq 'HASH'); |
61
|
0
|
|
0
|
|
|
|
my $is_operation = ($is_hash && exists $ss_node->{op}); |
62
|
0
|
|
0
|
|
|
|
my $is_param = $is_hash && $ss_node->{type} && $ss_node->{type} eq 'placeholder'; |
63
|
0
|
|
0
|
|
|
|
my $is_column = $is_hash && $ss_node->{type} && $ss_node->{type} eq 'column'; |
64
|
0
|
|
0
|
|
|
|
my $is_function = $is_ref && blessed($ss_node) && $ss_node->isa('SQL::Statement::Util::Function'); |
65
|
0
|
|
0
|
|
|
|
my $is_literal = $is_hash && exists($SS_LITERAL_TYPES{uc($ss_node->{type} || '')}); |
66
|
0
|
|
0
|
|
|
|
my $is_null = $is_literal && $ss_node->{type} eq 'null'; |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
# Handle negations as a proper operation |
69
|
0
|
0
|
0
|
|
|
|
if ($is_hash && $ss_node->{neg}) { |
70
|
0
|
|
|
|
|
|
return Criterion->new('NOT', $parser->__bcfpt_recursor({%$ss_node, neg => 0})); |
71
|
|
|
|
|
|
|
} |
72
|
|
|
|
|
|
|
|
73
|
0
|
0
|
|
|
|
|
if ($is_operation) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
74
|
0
|
|
|
|
|
|
my @args = map { $parser->__bcfpt_recursor($ss_node->{$_}) } grep { /^arg/ } sort keys %$ss_node; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
75
|
0
|
|
|
|
|
|
return Criterion->new($ss_node->{op}, @args); |
76
|
|
|
|
|
|
|
} elsif ($is_function) { |
77
|
0
|
|
|
|
|
|
my @args = map { $parser->__bcfpt_recursor($_) } @{$ss_node->args}; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
78
|
0
|
|
|
|
|
|
my $func_name = $ss_node->{name}; |
79
|
0
|
|
|
|
|
|
Class::ReluctantORM::Exception::NotImplemented->throw('SQL functions not yet supported'); |
80
|
|
|
|
|
|
|
} elsif ($is_param) { |
81
|
0
|
|
|
|
|
|
return Param->new(); |
82
|
|
|
|
|
|
|
} elsif ($is_column) { |
83
|
0
|
|
|
|
|
|
return $parser->__bcfpt_boost_to_column($ss_node); |
84
|
|
|
|
|
|
|
} elsif ($is_literal) { |
85
|
0
|
0
|
|
|
|
|
return Literal->new(($is_null ? undef : $ss_node->{value}), uc($ss_node->{type})); |
86
|
|
|
|
|
|
|
} else { |
87
|
0
|
|
|
|
|
|
Class::ReluctantORM::Exception::Param::BadValue->croak(error => __PACKAGE__ . '::__boost cannot handle this arg: ' . ref($ss_node)); |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
sub __bcfpt_boost_to_column { |
92
|
0
|
|
|
0
|
|
|
my $parser = shift; |
93
|
0
|
|
|
|
|
|
my $ss_node = shift; |
94
|
|
|
|
|
|
|
|
95
|
0
|
|
|
|
|
|
my ($table_name, $col_name) = split /\./, $ss_node->{value}; # DRIVER DEPENDENCY - table/column name separator |
96
|
0
|
0
|
|
|
|
|
if (!$col_name) { ($col_name, $table_name) = ($table_name, $col_name); } |
|
0
|
|
|
|
|
|
|
97
|
0
|
|
|
|
|
|
my ($col, $table); |
98
|
0
|
0
|
|
|
|
|
if ($table_name) { |
99
|
0
|
|
|
|
|
|
$table = $parser->{__where_under_construction}->find_table($table_name); |
100
|
0
|
0
|
|
|
|
|
unless ($table) { |
101
|
|
|
|
|
|
|
# Must not be a previously referenced table |
102
|
0
|
|
|
|
|
|
$table = Table->new(table => $table_name); |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
} |
105
|
0
|
|
|
|
|
|
$col = Column->new( |
106
|
|
|
|
|
|
|
table => $table, |
107
|
|
|
|
|
|
|
column => lc(__trim_quotes($col_name)), |
108
|
|
|
|
|
|
|
); |
109
|
0
|
|
|
|
|
|
return $col; |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
sub __trim_quotes { |
114
|
0
|
|
|
0
|
|
|
my $t = shift; |
115
|
0
|
|
|
|
|
|
$t =~ tr/'"[]//d; |
116
|
0
|
|
|
|
|
|
return $t; |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
1; |