File Coverage

blib/lib/Class/ReluctantORM/SQL/Parser.pm
Criterion Covered Total %
statement 29 81 35.8
branch 0 24 0.0
condition 0 24 0.0
subroutine 8 13 61.5
pod 1 2 50.0
total 38 144 26.3


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;