Massive rewrite of bind handling, and overall simplification of ::Storage::DBI
[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
b43345f2 9=head1 NAME
10
11DBIx::Class::Storage::DBI::NoBindVars - Sometime DBDs have poor to no support for bind variables
12
13=head1 DESCRIPTION
14
15This class allows queries to work when the DBD or underlying library does not
16support the usual C<?> placeholders, or at least doesn't support them very
17well, as is the case with L<DBD::Sybase>
18
19=head1 METHODS
20
b33697ef 21=head2 connect_info
b43345f2 22
b33697ef 23We 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 24
25=cut
26
b33697ef 27sub connect_info {
28 my $self = shift;
d944c5ae 29 my $retval = $self->next::method(@_);
b33697ef 30 $self->disable_sth_caching(1);
31 $retval;
b43345f2 32}
33
d5130dd2 34=head2 _prep_for_execute
b43345f2 35
d5130dd2 36Manually subs in the values for the usual C<?> placeholders.
b43345f2 37
38=cut
39
d5130dd2 40sub _prep_for_execute {
41 my $self = shift;
b50a5275 42
d944c5ae 43 my ($sql, $bind) = $self->next::method(@_);
44
7c63f828 45 # stringify bind args, quote via $dbh, and manually insert
0e773352 46 #my ($op, $ident, $args) = @_;
47 my $ident = $_[1];
d944c5ae 48
b4474f31 49 my @sql_part = split /\?/, $sql;
50 my $new_sql;
51
0e773352 52 my $col_info = $self->_resolve_column_info(
53 $ident, [ map { $_->[0]{dbic_colname} || () } @$bind ]
54 );
a49fe312 55
0e773352 56 for (@$bind) {
57 my $datatype = $col_info->{ $_->[0]{dbic_colname}||'' }{data_type};
b55e97a7 58
0e773352 59 my $data = (ref $_->[1]) ? "$_->[1]" : $_->[1]; # always stringify
b55e97a7 60
0e773352 61 $data = $self->_prep_interpolated_value($datatype, $data)
62 if $datatype;
6636ad53 63
0e773352 64 $data = $self->_get_dbh->quote($data)
65 unless $self->interpolate_unquoted($datatype, $data);
e06ad5d5 66
0e773352 67 $new_sql .= shift(@sql_part) . $data;
d944c5ae 68 }
0e773352 69
b4474f31 70 $new_sql .= join '', @sql_part;
d5130dd2 71
01c04b1b 72 return ($new_sql, []);
3885cff6 73}
74
80007f97 75=head2 interpolate_unquoted
e06ad5d5 76
148e3b50 77This method is called by L</_prep_for_execute> for every column in
78order to determine if its value should be quoted or not. The arguments
79are the current column data type and the actual bind value. The return
80007f97 80value is interpreted as: true - do not quote, false - do quote. You should
148e3b50 81override this in you Storage::DBI::<database> subclass, if your RDBMS
82does not like quotes around certain datatypes (e.g. Sybase and integer
80007f97 83columns). The default method always returns false (do quote).
e06ad5d5 84
0ac07712 85 WARNING!!!
e06ad5d5 86
148e3b50 87 Always validate that the bind-value is valid for the current datatype.
88 Otherwise you may very well open the door to SQL injection attacks.
e06ad5d5 89
0ac07712 90=cut
e06ad5d5 91
80007f97 92sub interpolate_unquoted {
0ac07712 93 #my ($self, $datatype, $value) = @_;
80007f97 94 return 0;
0ac07712 95}
148e3b50 96
166c6561 97=head2 _prep_interpolated_value
e06ad5d5 98
99Given a datatype and the value to be inserted directly into a SQL query, returns
0ac07712 100the necessary string to represent that value (by e.g. adding a '$' sign)
e06ad5d5 101
102=cut
103
166c6561 104sub _prep_interpolated_value {
0ac07712 105 #my ($self, $datatype, $value) = @_;
106 return $_[2];
107}
e06ad5d5 108
3885cff6 109=head1 AUTHORS
110
0ac07712 111See L<DBIx::Class/CONTRIBUTORS>
3885cff6 112
113=head1 LICENSE
114
115You may distribute this code under the same terms as Perl itself.
116
117=cut
b43345f2 118
1191;