Part one of the sybase work by Caelum (mostly reviewed)
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / DBI / Sybase / NoBindVars.pm
CommitLineData
d867eeda 1package DBIx::Class::Storage::DBI::Sybase::NoBindVars;
2
3use base qw/
4 DBIx::Class::Storage::DBI::NoBindVars
5 DBIx::Class::Storage::DBI::Sybase
6/;
7use mro 'c3';
8use List::Util ();
9use Scalar::Util ();
10
11sub _init {
12 my $self = shift;
13 $self->disable_sth_caching(1);
14 $self->_identity_method('@@IDENTITY');
15 $self->next::method (@_);
16}
17
18sub _fetch_identity_sql { 'SELECT ' . $_[0]->_identity_method }
19
20my $number = sub { Scalar::Util::looks_like_number($_[0]) };
21
22my $decimal = sub { $_[0] =~ /^ [-+]? \d+ (?:\.\d*)? \z/x };
23
24my %noquote = (
25 int => sub { $_[0] =~ /^ [-+]? \d+ \z/x },
26 bit => => sub { $_[0] =~ /^[01]\z/ },
27 money => sub { $_[0] =~ /^\$ \d+ (?:\.\d*)? \z/x },
28 float => $number,
29 real => $number,
30 double => $number,
31 decimal => $decimal,
32 numeric => $decimal,
33);
34
35sub interpolate_unquoted {
36 my $self = shift;
37 my ($type, $value) = @_;
38
39 return $self->next::method(@_) if not defined $value or not defined $type;
40
41 if (my $key = List::Util::first { $type =~ /$_/i } keys %noquote) {
42 return 1 if $noquote{$key}->($value);
43 }
44 elsif ($self->is_datatype_numeric($type) && $number->($value)) {
45 return 1;
46 }
47
48 return $self->next::method(@_);
49}
50
51sub _prep_interpolated_value {
52 my ($self, $type, $value) = @_;
53
54 if ($type =~ /money/i && defined $value) {
55 # change a ^ not followed by \$ to a \$
56 $value =~ s/^ (?! \$) /\$/x;
57 }
58
59 return $value;
60}
61
621;
63
64=head1 NAME
65
66DBIx::Class::Storage::DBI::Sybase::NoBindVars - Storage::DBI subclass for Sybase
67without placeholder support
68
69=head1 DESCRIPTION
70
71If you're using this driver than your version of Sybase, or the libraries you
72use to connect to it, do not support placeholders.
73
74You can also enable this driver explicitly using:
75
76 my $schema = SchemaClass->clone;
77 $schema->storage_type('::DBI::Sybase::NoBindVars');
78 $schema->connect($dsn, $user, $pass, \%opts);
79
80See the discussion in L<< DBD::Sybase/Using ? Placeholders & bind parameters to
81$sth->execute >> for details on the pros and cons of using placeholders.
82
83One advantage of not using placeholders is that C<select @@identity> will work
84for obtainging the last insert id of an C<IDENTITY> column, instead of having to
85do C<select max(col)> in a transaction as the base Sybase driver does.
86
87When using this driver, bind variables will be interpolated (properly quoted of
88course) into the SQL query itself, without using placeholders.
89
90The caching of prepared statements is also explicitly disabled, as the
91interpolation renders it useless.
92
93=head1 AUTHORS
94
95See L<DBIx::Class/CONTRIBUTORS>.
96
97=head1 LICENSE
98
99You may distribute this code under the same terms as Perl itself.
100
101=cut
102# vim:sts=2 sw=2: