Commit | Line | Data |
843f8ecd |
1 | package DBIx::Class::Storage::DBI::mysql; |
2 | |
3 | use strict; |
4 | use warnings; |
5 | |
698775ed |
6 | use base qw/ |
7 | DBIx::Class::Storage::DBI::MultiColumnIn |
698775ed |
8 | DBIx::Class::Storage::DBI |
9 | /; |
2ad62d97 |
10 | use mro 'c3'; |
5c160298 |
11 | use DBI ':sql_types'; |
12 | use 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 |
18 | sub 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 |
26 | sub 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 |
34 | sub _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 |
40 | sub 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 |
54 | sub sqlt_type { |
55 | return 'MySQL'; |
56 | } |
57 | |
96736321 |
58 | sub 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 |
75 | sub _svp_begin { |
eeb8cfeb |
76 | my ($self, $name) = @_; |
adb3554a |
77 | |
9ae966b9 |
78 | $self->_get_dbh->do("SAVEPOINT $name"); |
adb3554a |
79 | } |
80 | |
81 | sub _svp_release { |
eeb8cfeb |
82 | my ($self, $name) = @_; |
adb3554a |
83 | |
9ae966b9 |
84 | $self->_get_dbh->do("RELEASE SAVEPOINT $name"); |
adb3554a |
85 | } |
86 | |
87 | sub _svp_rollback { |
eeb8cfeb |
88 | my ($self, $name) = @_; |
adb3554a |
89 | |
9ae966b9 |
90 | $self->_get_dbh->do("ROLLBACK TO SAVEPOINT $name") |
adb3554a |
91 | } |
48fe9087 |
92 | |
106d5f3b |
93 | sub 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 | |
98 | sub 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 |
104 | sub _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 | |
112 | Used as: |
113 | |
114 | on_connect_call => 'bit_as_unsigned' |
115 | |
116 | in your L<connect_info|DBIx::Class::Storage::DBI/connect_info>. |
117 | |
118 | Beginning in MySQL 5.0.3 C<BIT> columns are stored as binary data, where before |
119 | they were an alias for C<TINYINT>. |
120 | |
121 | See L<http://dev.mysql.com/doc/refman/5.0/en/numeric-types.html> for details. |
122 | |
123 | This option allows you to use C<BIT> columns as C<UNSIGNED> integers in all |
124 | versions of MySQL. |
125 | |
126 | B<NOTE:> do not insert negative values when using this option, they will not be |
127 | inserted correctly. |
128 | |
129 | =cut |
130 | |
131 | sub connect_call_bit_as_unsigned { |
132 | my $self = shift; |
133 | |
134 | $self->_bit_as('UNSIGNED'); |
135 | } |
136 | |
137 | sub 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 | |
150 | sub _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 |
175 | 1; |
176 | |
75d07914 |
177 | =head1 NAME |
843f8ecd |
178 | |
c9d438ff |
179 | DBIx::Class::Storage::DBI::mysql - Storage::DBI class implementing MySQL specifics |
843f8ecd |
180 | |
181 | =head1 SYNOPSIS |
182 | |
c9d438ff |
183 | Storage::DBI autodetects the underlying MySQL database, and re-blesses the |
184 | C<$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 |
190 | This class implements MySQL specific bits of L<DBIx::Class::Storage::DBI>, |
191 | like AutoIncrement column support and savepoints. Also it augments the |
192 | SQL maker to support the MySQL-specific C<STRAIGHT_JOIN> join type, which |
193 | you can use by specifying C<< join_type => 'straight' >> in the |
194 | L<relationship attributes|DBIx::Class::Relationship::Base/join_type> |
195 | |
c9d438ff |
196 | |
97a0a148 |
197 | It also provides a one-stop on-connect macro C<set_strict_mode> which sets |
198 | session variables such that MySQL behaves more predictably as far as the |
199 | SQL standard is concerned. |
0fde80d9 |
200 | |
3c01add8 |
201 | =head1 STORAGE OPTIONS |
202 | |
203 | =head2 set_strict_mode |
204 | |
205 | Enables 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 |
216 | See L<DBIx::Class/CONTRIBUTORS> |
843f8ecd |
217 | |
218 | =head1 LICENSE |
219 | |
220 | You may distribute this code under the same terms as Perl itself. |
221 | |
222 | =cut |