add mysql bit_as_unsigned on_connect_call option, and tests for bit type
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / DBI / mysql.pm
CommitLineData
843f8ecd 1package DBIx::Class::Storage::DBI::mysql;
2
3use strict;
4use warnings;
5
698775ed 6use base qw/
7 DBIx::Class::Storage::DBI::MultiColumnIn
698775ed 8 DBIx::Class::Storage::DBI
9/;
2ad62d97 10use mro 'c3';
5c160298 11use DBI ':sql_types';
12use namespace::clean;
843f8ecd 13
87aa29e2 14__PACKAGE__->sql_maker_class('DBIx::Class::SQLAHacks::MySQL');
843f8ecd 15
5c160298 16__PACKAGE__->mk_group_accessors(simple => qw/_bit_as/);
17
e96a93df 18sub with_deferred_fk_checks {
19 my ($self, $sub) = @_;
20
5cf7285e 21 $self->_do_query('SET FOREIGN_KEY_CHECKS = 0');
e96a93df 22 $sub->();
5cf7285e 23 $self->_do_query('SET FOREIGN_KEY_CHECKS = 1');
e96a93df 24}
25
97a0a148 26sub connect_call_set_strict_mode {
0fde80d9 27 my $self = shift;
97a0a148 28
29 # the @@sql_mode puts back what was previously set on the session handle
30 $self->_do_query(q|SET SQL_MODE = CONCAT('ANSI,TRADITIONAL,ONLY_FULL_GROUP_BY,', @@sql_mode)|);
0fde80d9 31 $self->_do_query(q|SET SQL_AUTO_IS_NULL = 0|);
32}
33
d4f16b21 34sub _dbh_last_insert_id {
35 my ($self, $dbh, $source, $col) = @_;
36 $dbh->{mysql_insertid};
843f8ecd 37}
38
d3944540 39# we need to figure out what mysql version we're running
40sub sql_maker {
41 my $self = shift;
42
43 unless ($self->_sql_maker) {
44 my $maker = $self->next::method (@_);
45
46 # mysql 3 does not understand a bare JOIN
47 my $mysql_ver = $self->_get_dbh->get_info(18);
48 $maker->{_default_jointype} = 'INNER' if $mysql_ver =~ /^3/;
49 }
50
51 return $self->_sql_maker;
52}
53
e8d293df 54sub sqlt_type {
55 return 'MySQL';
56}
57
96736321 58sub deployment_statements {
59 my $self = shift;
60 my ($schema, $type, $version, $dir, $sqltargs, @rest) = @_;
61
62 $sqltargs ||= {};
63
64 if (
65 ! exists $sqltargs->{producer_args}{mysql_version}
66 and
67 my $dver = $self->_server_info->{normalized_dbms_version}
68 ) {
69 $sqltargs->{producer_args}{mysql_version} = $dver;
70 }
71
72 $self->next::method($schema, $type, $version, $dir, $sqltargs, @rest);
73}
74
adb3554a 75sub _svp_begin {
eeb8cfeb 76 my ($self, $name) = @_;
adb3554a 77
9ae966b9 78 $self->_get_dbh->do("SAVEPOINT $name");
adb3554a 79}
80
81sub _svp_release {
eeb8cfeb 82 my ($self, $name) = @_;
adb3554a 83
9ae966b9 84 $self->_get_dbh->do("RELEASE SAVEPOINT $name");
adb3554a 85}
86
87sub _svp_rollback {
eeb8cfeb 88 my ($self, $name) = @_;
adb3554a 89
9ae966b9 90 $self->_get_dbh->do("ROLLBACK TO SAVEPOINT $name")
adb3554a 91}
48fe9087 92
106d5f3b 93sub is_replicating {
9ae966b9 94 my $status = shift->_get_dbh->selectrow_hashref('show slave status');
f797e89e 95 return ($status->{Slave_IO_Running} eq 'Yes') && ($status->{Slave_SQL_Running} eq 'Yes');
106d5f3b 96}
97
98sub lag_behind_master {
9ae966b9 99 return shift->_get_dbh->selectrow_hashref('show slave status')->{Seconds_Behind_Master};
106d5f3b 100}
101
613f65e5 102# MySql can not do subquery update/deletes, only way is slow per-row operations.
ab807c12 103# This assumes you have set proper transaction isolation and use innodb.
b5963465 104sub _subq_update_delete {
613f65e5 105 return shift->_per_row_update_delete (@_);
106}
107
5c160298 108# handle bit fields properly
109
110=head2 connect_call_bit_as_unsigned
111
112Used as:
113
114 on_connect_call => 'bit_as_unsigned'
115
116in your L<connect_info|DBIx::Class::Storage::DBI/connect_info>.
117
118Beginning in MySQL 5.0.3 C<BIT> columns are stored as binary data, where before
119they were an alias for C<TINYINT>.
120
121See L<http://dev.mysql.com/doc/refman/5.0/en/numeric-types.html> for details.
122
123This option allows you to use C<BIT> columns as C<UNSIGNED> integers in all
124versions of MySQL.
125
126B<NOTE:> do not insert negative values when using this option, they will not be
127inserted correctly.
128
129=cut
130
131sub connect_call_bit_as_unsigned {
132 my $self = shift;
133
134 $self->_bit_as('UNSIGNED');
135}
136
137sub bind_attribute_by_data_type {
138 my $self = shift;
139 my ($data_type) = @_;
140
141 my $res = $self->next::method(@_) || {};
142
143 if ($data_type && $self->_bit_as && lc($data_type) eq 'bit') {
144 $res->{TYPE} = SQL_INTEGER;
145 }
146
147 return $res;
148}
149
150sub _select_args {
151 my $self = shift;
152 my ($ident, $select) = @_;
153
154 return $self->next::method(@_) unless $self->_bit_as;
155
156 my $col_info = $self->_resolve_column_info($ident);
157
158 for my $select_idx (0..$#$select) {
159 my $selected = $select->[$select_idx];
160
161 next if ref $selected;
162
163 my $data_type = $col_info->{$selected}{data_type};
164
165 if ($data_type && lc($data_type) eq 'bit') {
166 $selected = $self->sql_maker->_quote($selected);
167
168 $select->[$select_idx] = \("CAST($selected AS " . $self->_bit_as . ")");
169 }
170 }
171
172 return $self->next::method(@_);
173}
174
843f8ecd 1751;
176
75d07914 177=head1 NAME
843f8ecd 178
c9d438ff 179DBIx::Class::Storage::DBI::mysql - Storage::DBI class implementing MySQL specifics
843f8ecd 180
181=head1 SYNOPSIS
182
c9d438ff 183Storage::DBI autodetects the underlying MySQL database, and re-blesses the
184C<$storage> object into this class.
185
3ce9dd08 186 my $schema = MyDb::Schema->connect( $dsn, $user, $pass, { on_connect_call => 'set_strict_mode' } );
843f8ecd 187
188=head1 DESCRIPTION
189
b8391c87 190This class implements MySQL specific bits of L<DBIx::Class::Storage::DBI>,
191like AutoIncrement column support and savepoints. Also it augments the
192SQL maker to support the MySQL-specific C<STRAIGHT_JOIN> join type, which
193you can use by specifying C<< join_type => 'straight' >> in the
194L<relationship attributes|DBIx::Class::Relationship::Base/join_type>
195
c9d438ff 196
97a0a148 197It also provides a one-stop on-connect macro C<set_strict_mode> which sets
198session variables such that MySQL behaves more predictably as far as the
199SQL standard is concerned.
0fde80d9 200
3c01add8 201=head1 STORAGE OPTIONS
202
203=head2 set_strict_mode
204
205Enables session-wide strict options upon connecting. Equivalent to:
206
207 ->connect ( ... , {
208 on_connect_do => [
209 q|SET SQL_MODE = CONCAT('ANSI,TRADITIONAL,ONLY_FULL_GROUP_BY,', @@sql_mode)|,
210 q|SET SQL_AUTO_IS_NULL = 0|,
211 ]
212 });
213
843f8ecd 214=head1 AUTHORS
215
c9d438ff 216See L<DBIx::Class/CONTRIBUTORS>
843f8ecd 217
218=head1 LICENSE
219
220You may distribute this code under the same terms as Perl itself.
221
222=cut