Replace \D with [^0-9] in sensitive spots
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / DBI / NoBindVars.pm
CommitLineData
3885cff6 1package DBIx::Class::Storage::DBI::NoBindVars;
2
3use strict;
4use warnings;
5
6use base 'DBIx::Class::Storage::DBI';
2ad62d97 7use mro 'c3';
3885cff6 8
fcb7fcbb 9use DBIx::Class::SQLMaker::LimitDialects;
10use List::Util qw/first/;
11
12use namespace::clean;
13
14=head1 NAME
b43345f2 15
16DBIx::Class::Storage::DBI::NoBindVars - Sometime DBDs have poor to no support for bind variables
17
18=head1 DESCRIPTION
19
20This class allows queries to work when the DBD or underlying library does not
21support the usual C<?> placeholders, or at least doesn't support them very
22well, as is the case with L<DBD::Sybase>
23
24=head1 METHODS
25
b33697ef 26=head2 connect_info
b43345f2 27
b33697ef 28We can't cache very effectively without bind variables, so force the C<disable_sth_caching> setting to be turned on when the connect info is set.
b43345f2 29
30=cut
31
b33697ef 32sub connect_info {
33 my $self = shift;
d944c5ae 34 my $retval = $self->next::method(@_);
b33697ef 35 $self->disable_sth_caching(1);
36 $retval;
b43345f2 37}
38
d5130dd2 39=head2 _prep_for_execute
b43345f2 40
d5130dd2 41Manually subs in the values for the usual C<?> placeholders.
b43345f2 42
43=cut
44
d5130dd2 45sub _prep_for_execute {
46 my $self = shift;
b50a5275 47
d944c5ae 48 my ($sql, $bind) = $self->next::method(@_);
49
7c63f828 50 # stringify bind args, quote via $dbh, and manually insert
0e773352 51 #my ($op, $ident, $args) = @_;
52 my $ident = $_[1];
d944c5ae 53
b4474f31 54 my @sql_part = split /\?/, $sql;
55 my $new_sql;
56
0e773352 57 for (@$bind) {
abe9977d 58 my $data = (ref $_->[1]) ? "$_->[1]" : $_->[1]; # always stringify, array types are currently not supported
b55e97a7 59
abe9977d 60 my $datatype = $_->[0]{sqlt_datatype};
b55e97a7 61
0e773352 62 $data = $self->_prep_interpolated_value($datatype, $data)
63 if $datatype;
6636ad53 64
0e773352 65 $data = $self->_get_dbh->quote($data)
abe9977d 66 unless ($datatype and $self->interpolate_unquoted($datatype, $data) );
e06ad5d5 67
0e773352 68 $new_sql .= shift(@sql_part) . $data;
d944c5ae 69 }
0e773352 70
b4474f31 71 $new_sql .= join '', @sql_part;
d5130dd2 72
01c04b1b 73 return ($new_sql, []);
3885cff6 74}
75
80007f97 76=head2 interpolate_unquoted
e06ad5d5 77
148e3b50 78This method is called by L</_prep_for_execute> for every column in
79order to determine if its value should be quoted or not. The arguments
80are the current column data type and the actual bind value. The return
80007f97 81value is interpreted as: true - do not quote, false - do quote. You should
148e3b50 82override this in you Storage::DBI::<database> subclass, if your RDBMS
83does not like quotes around certain datatypes (e.g. Sybase and integer
fcb7fcbb 84columns). The default method returns false, except for integer datatypes
85paired with values containing nothing but digits.
e06ad5d5 86
0ac07712 87 WARNING!!!
e06ad5d5 88
148e3b50 89 Always validate that the bind-value is valid for the current datatype.
90 Otherwise you may very well open the door to SQL injection attacks.
e06ad5d5 91
0ac07712 92=cut
e06ad5d5 93
80007f97 94sub interpolate_unquoted {
0ac07712 95 #my ($self, $datatype, $value) = @_;
fcb7fcbb 96
97 return 1 if (
98 defined $_[2]
99 and
100 $_[1]
101 and
f033dcbe 102 $_[2] !~ /[^0-9]/
fcb7fcbb 103 and
104 $_[1] =~ /int(?:eger)? | (?:tiny|small|medium|big)int/ix
105 );
106
80007f97 107 return 0;
0ac07712 108}
148e3b50 109
166c6561 110=head2 _prep_interpolated_value
e06ad5d5 111
112Given a datatype and the value to be inserted directly into a SQL query, returns
0ac07712 113the necessary string to represent that value (by e.g. adding a '$' sign)
e06ad5d5 114
115=cut
116
166c6561 117sub _prep_interpolated_value {
0ac07712 118 #my ($self, $datatype, $value) = @_;
119 return $_[2];
120}
e06ad5d5 121
a2bd3796 122=head1 FURTHER QUESTIONS?
3885cff6 123
a2bd3796 124Check the list of L<additional DBIC resources|DBIx::Class/GETTING HELP/SUPPORT>.
3885cff6 125
a2bd3796 126=head1 COPYRIGHT AND LICENSE
3885cff6 127
a2bd3796 128This module is free software L<copyright|DBIx::Class/COPYRIGHT AND LICENSE>
129by the L<DBIx::Class (DBIC) authors|DBIx::Class/AUTHORS>. You can
130redistribute it and/or modify it under the same terms as the
131L<DBIx::Class library|DBIx::Class/COPYRIGHT AND LICENSE>.
3885cff6 132
133=cut
b43345f2 134
1351;