File Coverage

blib/lib/SQL/Bind.pm
Criterion Covered Total %
statement 50 51 98.0
branch 17 18 94.4
condition n/a
subroutine 5 5 100.0
pod 0 1 0.0
total 72 75 96.0


line stmt bran cond sub pod time code
1             package SQL::Bind;
2 2     2   72072 use strict;
  2         14  
  2         58  
3 2     2   11 use warnings;
  2         3  
  2         52  
4 2     2   9 use base 'Exporter';
  2         4  
  2         1326  
5             our @EXPORT_OK = qw(sql);
6              
7             our $VERSION = '1.03';
8              
9             our $PlaceholderPrefix = ':';
10             our $PlaceholderRegex = qr/(?i)([a-z_][a-z0-9_]*)/;
11              
12             sub sql {
13 13     13 0 34839 my ($sql, %params) = @_;
14              
15 13         19 my @bind;
16              
17 13         17 my $exceptions = '';
18              
19 13 100       30 if ($PlaceholderPrefix eq ':') {
20 12         22 $exceptions = '(?
21             }
22              
23 13         281 $sql =~ s{$exceptions${PlaceholderPrefix}${PlaceholderRegex}(!|\*)?}{
24             my $options = $2
25             ? {
26             {
27             '!' => 'raw',
28             '*' => 'recursive'
29 17 100       65 }->{$2} => 1
30             }
31             : {};
32 17         53 my ($replacement, @subbind) = _replace($1, $options, %params);
33              
34 17         27 push @bind, @subbind;
35              
36 17         56 $replacement;
37             }ge;
38              
39 13         60 return ($sql, @bind);
40             }
41              
42             sub _replace {
43 17     17   45 my ($placeholder, $options, %params) = @_;
44              
45 17         19 my @bind;
46              
47 17         17 my $replacement = '';
48              
49 17 50       37 if (!exists $params{$placeholder}) {
50 0         0 die sprintf 'unknown placeholder: %s', $placeholder;
51             }
52              
53 17 100       45 if (ref $params{$placeholder} eq 'HASH') {
    100          
54 2 100       5 if ($options->{raw}) {
55 1         19 $replacement = join ', ', map { $_ . '=' . $params{$placeholder}->{$_} }
56 1         4 keys %{$params{$placeholder}};
  1         4  
57             }
58             else {
59 1         2 $replacement = join ', ', map { $_ . '=?' } keys %{$params{$placeholder}};
  1         4  
  1         4  
60 1         3 push @bind, values %{$params{$placeholder}};
  1         3  
61             }
62             }
63             elsif (ref $params{$placeholder} eq 'ARRAY') {
64 4 100       11 if ($options->{raw}) {
65 2         3 $replacement = join ', ', @{$params{$placeholder}};
  2         6  
66             }
67             else {
68 2         14 $replacement = join ', ', map { '?' } 1 .. @{$params{$placeholder}};
  4         11  
  2         10  
69 2         4 push @bind, @{$params{$placeholder}};
  2         4  
70             }
71             }
72             else {
73 11 100       24 if ($options->{raw}) {
    100          
74 1         3 $replacement = $params{$placeholder};
75             }
76             elsif ($options->{recursive}) {
77 1         5 my ($subsql, @subbind) = sql($params{$placeholder}, %params);
78              
79 1         2 $replacement = $subsql;
80 1         3 push @bind, @subbind;
81             }
82             else {
83 9         12 $replacement = '?';
84 9         13 push @bind, $params{$placeholder};
85             }
86             }
87              
88 17         47 return ($replacement, @bind);
89             }
90              
91             1;
92             __END__