Commit | Line | Data |
843f8ecd |
1 | package DBIx::Class::Storage::DBI::mysql; |
2 | |
3 | use strict; |
4 | use warnings; |
5 | |
be64931c |
6 | use base qw/DBIx::Class::Storage::DBI/; |
843f8ecd |
7 | |
26d54a1d |
8 | use Try::Tiny; |
9 | use namespace::clean; |
10 | |
d5dedbd6 |
11 | __PACKAGE__->sql_maker_class('DBIx::Class::SQLMaker::MySQL'); |
6a247f33 |
12 | __PACKAGE__->sql_limit_dialect ('LimitXY'); |
2b8cc2f2 |
13 | __PACKAGE__->sql_quote_char ('`'); |
843f8ecd |
14 | |
be64931c |
15 | __PACKAGE__->_use_multicolumn_in (1); |
16 | |
26d54a1d |
17 | # We turn FOREIGN_KEY_CHECKS off, do a transaction, then turn them back on right |
18 | # before the COMMIT so that they can be checked during the COMMIT. |
19 | |
c0992bf1 |
20 | # nothing tests this hypothesis, why? |
21 | |
e96a93df |
22 | sub with_deferred_fk_checks { |
23 | my ($self, $sub) = @_; |
24 | |
5cf7285e |
25 | $self->_do_query('SET FOREIGN_KEY_CHECKS = 0'); |
26d54a1d |
26 | |
27 | my $tried_fk_checks_reset = 0; |
28 | |
29 | return try { |
30 | my $guard = $self->txn_scope_guard; |
31 | preserve_context { $sub->() } after => sub { |
32 | $tried_fk_checks_reset = 1; |
33 | $self->_do_query('SET FOREIGN_KEY_CHECKS = 1'); |
34 | $guard->commit; |
35 | }; |
36 | } |
37 | catch { |
38 | my $e = $_; |
39 | if (not $tried_fk_checks_reset) { |
40 | eval { |
41 | $self->_do_query('SET FOREIGN_KEY_CHECKS = 1'); |
42 | }; |
43 | if ($@) { |
44 | $e .= " also 'SET FOREIGN_KEY_CHECKS = 1' failed: $@" |
45 | } |
46 | } |
47 | $self->throw_exception($e); |
48 | }; |
e96a93df |
49 | } |
50 | |
97a0a148 |
51 | sub connect_call_set_strict_mode { |
0fde80d9 |
52 | my $self = shift; |
97a0a148 |
53 | |
54 | # the @@sql_mode puts back what was previously set on the session handle |
55 | $self->_do_query(q|SET SQL_MODE = CONCAT('ANSI,TRADITIONAL,ONLY_FULL_GROUP_BY,', @@sql_mode)|); |
0fde80d9 |
56 | $self->_do_query(q|SET SQL_AUTO_IS_NULL = 0|); |
57 | } |
58 | |
d4f16b21 |
59 | sub _dbh_last_insert_id { |
60 | my ($self, $dbh, $source, $col) = @_; |
61 | $dbh->{mysql_insertid}; |
843f8ecd |
62 | } |
63 | |
f98120e4 |
64 | # here may seem like an odd place to override, but this is the first |
65 | # method called after we are connected *and* the driver is determined |
66 | # ($self is reblessed). See code flow in ::Storage::DBI::_populate_dbh |
67 | sub _run_connection_actions { |
68 | my $self = shift; |
69 | |
70 | # default mysql_auto_reconnect to off unless explicitly set |
71 | if ( |
72 | $self->_dbh->{mysql_auto_reconnect} |
73 | and |
74 | ! exists $self->_dbic_connect_attributes->{mysql_auto_reconnect} |
75 | ) { |
76 | $self->_dbh->{mysql_auto_reconnect} = 0; |
77 | } |
78 | |
79 | $self->next::method(@_); |
80 | } |
81 | |
d3944540 |
82 | # we need to figure out what mysql version we're running |
83 | sub sql_maker { |
84 | my $self = shift; |
85 | |
86 | unless ($self->_sql_maker) { |
87 | my $maker = $self->next::method (@_); |
88 | |
89 | # mysql 3 does not understand a bare JOIN |
af1f4f84 |
90 | my $mysql_ver = $self->_dbh_get_info('SQL_DBMS_VER'); |
d3944540 |
91 | $maker->{_default_jointype} = 'INNER' if $mysql_ver =~ /^3/; |
92 | } |
93 | |
94 | return $self->_sql_maker; |
95 | } |
96 | |
e8d293df |
97 | sub sqlt_type { |
98 | return 'MySQL'; |
99 | } |
100 | |
96736321 |
101 | sub deployment_statements { |
102 | my $self = shift; |
103 | my ($schema, $type, $version, $dir, $sqltargs, @rest) = @_; |
104 | |
105 | $sqltargs ||= {}; |
106 | |
107 | if ( |
108 | ! exists $sqltargs->{producer_args}{mysql_version} |
8273e845 |
109 | and |
96736321 |
110 | my $dver = $self->_server_info->{normalized_dbms_version} |
111 | ) { |
112 | $sqltargs->{producer_args}{mysql_version} = $dver; |
113 | } |
114 | |
115 | $self->next::method($schema, $type, $version, $dir, $sqltargs, @rest); |
116 | } |
117 | |
90d7422f |
118 | sub _exec_svp_begin { |
eeb8cfeb |
119 | my ($self, $name) = @_; |
adb3554a |
120 | |
90d7422f |
121 | $self->_dbh->do("SAVEPOINT $name"); |
adb3554a |
122 | } |
123 | |
90d7422f |
124 | sub _exec_svp_release { |
eeb8cfeb |
125 | my ($self, $name) = @_; |
adb3554a |
126 | |
90d7422f |
127 | $self->_dbh->do("RELEASE SAVEPOINT $name"); |
adb3554a |
128 | } |
129 | |
90d7422f |
130 | sub _exec_svp_rollback { |
eeb8cfeb |
131 | my ($self, $name) = @_; |
adb3554a |
132 | |
90d7422f |
133 | $self->_dbh->do("ROLLBACK TO SAVEPOINT $name") |
adb3554a |
134 | } |
48fe9087 |
135 | |
106d5f3b |
136 | sub is_replicating { |
9ae966b9 |
137 | my $status = shift->_get_dbh->selectrow_hashref('show slave status'); |
f797e89e |
138 | return ($status->{Slave_IO_Running} eq 'Yes') && ($status->{Slave_SQL_Running} eq 'Yes'); |
106d5f3b |
139 | } |
140 | |
141 | sub lag_behind_master { |
9ae966b9 |
142 | return shift->_get_dbh->selectrow_hashref('show slave status')->{Seconds_Behind_Master}; |
106d5f3b |
143 | } |
144 | |
843f8ecd |
145 | 1; |
146 | |
75d07914 |
147 | =head1 NAME |
843f8ecd |
148 | |
c9d438ff |
149 | DBIx::Class::Storage::DBI::mysql - Storage::DBI class implementing MySQL specifics |
843f8ecd |
150 | |
151 | =head1 SYNOPSIS |
152 | |
c9d438ff |
153 | Storage::DBI autodetects the underlying MySQL database, and re-blesses the |
154 | C<$storage> object into this class. |
155 | |
3ce9dd08 |
156 | my $schema = MyDb::Schema->connect( $dsn, $user, $pass, { on_connect_call => 'set_strict_mode' } ); |
843f8ecd |
157 | |
158 | =head1 DESCRIPTION |
159 | |
b8391c87 |
160 | This class implements MySQL specific bits of L<DBIx::Class::Storage::DBI>, |
161 | like AutoIncrement column support and savepoints. Also it augments the |
162 | SQL maker to support the MySQL-specific C<STRAIGHT_JOIN> join type, which |
163 | you can use by specifying C<< join_type => 'straight' >> in the |
164 | L<relationship attributes|DBIx::Class::Relationship::Base/join_type> |
165 | |
c9d438ff |
166 | |
97a0a148 |
167 | It also provides a one-stop on-connect macro C<set_strict_mode> which sets |
168 | session variables such that MySQL behaves more predictably as far as the |
169 | SQL standard is concerned. |
0fde80d9 |
170 | |
3c01add8 |
171 | =head1 STORAGE OPTIONS |
172 | |
173 | =head2 set_strict_mode |
174 | |
175 | Enables session-wide strict options upon connecting. Equivalent to: |
176 | |
177 | ->connect ( ... , { |
178 | on_connect_do => [ |
179 | q|SET SQL_MODE = CONCAT('ANSI,TRADITIONAL,ONLY_FULL_GROUP_BY,', @@sql_mode)|, |
180 | q|SET SQL_AUTO_IS_NULL = 0|, |
181 | ] |
182 | }); |
183 | |
843f8ecd |
184 | =head1 AUTHORS |
185 | |
c9d438ff |
186 | See L<DBIx::Class/CONTRIBUTORS> |
843f8ecd |
187 | |
188 | =head1 LICENSE |
189 | |
190 | You may distribute this code under the same terms as Perl itself. |
191 | |
192 | =cut |