File Coverage

blib/lib/SQL/Bind.pm
Criterion Covered Total %
statement 47 48 97.9
branch 15 16 93.7
condition n/a
subroutine 5 5 100.0
pod 0 1 0.0
total 67 70 95.7


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