File Coverage

blib/lib/DBIx/Class/Storage/DBI/MariaDB.pm
Criterion Covered Total %
statement 15 59 25.4
branch 2 18 11.1
condition 0 17 0.0
subroutine 5 18 27.7
pod 7 8 87.5
total 29 120 24.1


line stmt bran cond sub pod time code
1             package DBIx::Class::Storage::DBI::MariaDB;
2              
3 4     4   1118499 use strict;
  4         9  
  4         169  
4 4     4   22 use warnings;
  4         7  
  4         243  
5              
6 4     4   4976 use DBI;
  4         68983  
  4         342  
7 4     4   35 use base qw/DBIx::Class::Storage::DBI/;
  4         8  
  4         7860  
8              
9             our $VERSION = '0.1.4';
10              
11             __PACKAGE__->sql_maker_class('DBIx::Class::SQLMaker::MySQL');
12             __PACKAGE__->sql_limit_dialect('LimitXY');
13             __PACKAGE__->sql_quote_char('`');
14              
15             __PACKAGE__->_use_multicolumn_in(1);
16              
17             sub with_deferred_fk_checks {
18 0     0 1 0 my ( $self, $sub ) = @_;
19              
20 0         0 $self->_do_query('SET FOREIGN_KEY_CHECKS = 0');
21 0         0 $sub->();
22 0         0 $self->_do_query('SET FOREIGN_KEY_CHECKS = 1');
23             }
24              
25             sub connect_call_set_strict_mode {
26 0     0 0 0 my $self = shift;
27              
28             # the @@sql_mode puts back what was previously set on the session handle
29 0         0 $self->_do_query(
30             q|SET SQL_MODE = CONCAT('ANSI,TRADITIONAL,ONLY_FULL_GROUP_BY,', @@sql_mode)|
31             );
32 0         0 $self->_do_query(q|SET SQL_AUTO_IS_NULL = 0|);
33             }
34              
35             sub _dbh_last_insert_id {
36 0     0   0 my ( $self, $dbh, $source, $col ) = @_;
37 0         0 $dbh->{mariadb_insertid};
38             }
39              
40             sub _prep_for_execute {
41 0     0   0 my $self = shift;
42              
43             # Only update and delete need special double-subquery treatment
44             # Insert referencing the same table (i.e. SELECT MAX(id) + 1) seems
45             # to work just fine on MariaDB
46 0 0 0     0 return $self->next::method(@_)
47             if ( $_[0] eq 'select' or $_[0] eq 'insert' );
48              
49             # FIXME FIXME FIXME - this is a terrible, gross, incomplete, MariaDB-specific
50             # hack but it works rather well for the limited amount of actual use cases
51             # which can not be done in any other way on MariaDB. This allows us to fix
52             # some bugs without breaking MariaDB support in the process and is also
53             # crucial for more complex things like Shadow to be usable
54             #
55             # This code is just a pre-analyzer, working in tandem with ::SQLMaker::MySQL,
56             # where the possibly-set value of {_modification_target_referenced_re} is
57             # used to demarcate which part of the final SQL to double-wrap in a subquery.
58             #
59             # This is covered extensively by "offline" tests, so that competing SQLMaker
60             # implementations could benefit from the existing tests just as well.
61              
62             # extract the source name, construct modification indicator re
63 0         0 my $sm = $self->sql_maker;
64              
65 0         0 my $target_name = $_[1]->from;
66              
67 0 0       0 if ( ref $target_name ) {
68 0 0 0     0 if (
69             ref $target_name eq 'SCALAR'
70             and $$target_name =~ /^ (?:
71             \` ( [^`]+ ) \` #`
72             | ( [\w\-]+ )
73             ) $/x
74             )
75             {
76             # this is just a plain-ish name, which has been literal-ed for
77             # whatever reason
78 0 0       0 $target_name = ( defined $1 ) ? $1 : $2;
79             } else {
80              
81             # this is something very complex, perhaps a custom result source or whatnot
82             # can't deal with it
83 0         0 undef $target_name;
84             }
85             }
86              
87             local $sm->{_modification_target_referenced_re} =
88 0 0       0 qr/ (?
89             if $target_name;
90              
91 0         0 $self->next::method(@_);
92             }
93              
94             # here may seem like an odd place to override, but this is the first
95             # method called after we are connected *and* the driver is determined
96             # ($self is reblessed). See code flow in ::Storage::DBI::_populate_dbh
97             sub _run_connection_actions {
98 0     0   0 my $self = shift;
99              
100             # default mariadb_auto_reconnect to off unless explicitly set
101 0 0 0     0 if ( $self->_dbh->{mariadb_auto_reconnect}
102             and !exists $self->_dbic_connect_attributes->{mariadb_auto_reconnect} )
103             {
104 0         0 $self->_dbh->{mariadb_auto_reconnect} = 0;
105             }
106              
107 0         0 $self->next::method(@_);
108             }
109              
110             # we need to figure out what mysql version we're running
111             sub sql_maker {
112 0     0 1 0 my $self = shift;
113              
114             # it is critical to get the version *before* calling next::method
115             # otherwise the potential connect will obliterate the sql_maker
116             # next::method will populate in the _sql_maker accessor
117 0         0 my $mariadb_ver = $self->_server_info->{normalized_dbms_version};
118              
119 0         0 my $sm = $self->next::method(@_);
120              
121             # mysql 3 does not understand a bare JOIN
122 0 0       0 $sm->{_default_jointype} = 'INNER' if $mariadb_ver < 4;
123              
124 0         0 $sm;
125             }
126              
127             sub sqlt_type {
128             # used by SQL::Translator
129 0     0 1 0 return 'MySQL';
130             }
131              
132             sub deployment_statements {
133 0     0 1 0 my $self = shift;
134 0         0 my ( $schema, $type, $version, $dir, $sqltargs, @rest ) = @_;
135              
136 0   0     0 $sqltargs ||= {};
137              
138 0 0 0     0 if ( !exists $sqltargs->{producer_args}{mysql_version}
139             and my $dver = $self->_server_info->{normalized_dbms_version} )
140             {
141 0         0 $sqltargs->{producer_args}{mysql_version} = $dver;
142             }
143              
144 0         0 $self->next::method( $schema, $type, $version, $dir, $sqltargs, @rest );
145             }
146              
147             sub _exec_svp_begin {
148 0     0   0 my ( $self, $name ) = @_;
149              
150 0         0 $self->_dbh->do("SAVEPOINT $name");
151             }
152              
153             sub _exec_svp_release {
154 0     0   0 my ( $self, $name ) = @_;
155              
156 0         0 $self->_dbh->do("RELEASE SAVEPOINT $name");
157             }
158              
159             sub _exec_svp_rollback {
160 0     0   0 my ( $self, $name ) = @_;
161              
162 0         0 $self->_dbh->do("ROLLBACK TO SAVEPOINT $name");
163             }
164              
165             sub is_replicating {
166 0     0 1 0 my $status = shift->_get_dbh->selectrow_hashref('show slave status');
167             return ( $status->{Slave_IO_Running} eq 'Yes' )
168 0   0     0 && ( $status->{Slave_SQL_Running} eq 'Yes' );
169             }
170              
171             sub lag_behind_master {
172             return
173             shift->_get_dbh->selectrow_hashref('show slave status')
174 0     0 1 0 ->{Seconds_Behind_Master};
175             }
176              
177             sub bind_attribute_by_data_type {
178 20 100   20 1 14838 if ( $_[1] =~ /^(?:(?:tiny|medium|long|)blob|(?:var|)binary)$/i ) {
179 12         80 return DBI::SQL_BINARY;
180             }
181 8         42 return;
182             }
183              
184             1;
185              
186             =head1 NAME
187              
188             DBIx::Class::Storage::DBI::MariaDB - Storage::DBI class implementing MariaDB specifics
189              
190             =head1 DESCRIPTION
191              
192             This module adds support for MariaDB in the DBIx::Class ORM. It supports
193             exactly the same parameters as the L
194             module, so check that for further documentation.
195              
196             =head1 USAGE
197              
198             Similar to other storage modules that are builtin to DBIx::Class, all you need
199             to do is ensure DBIx::Class::Storage::DBI::MariaDB is loaded and specify
200             MariaDB in the DSN. For example:
201              
202             package MyApp::Schema;
203             use base 'DBIx::Class::Schema';
204              
205             # register classes
206             # ...
207             # load mariadb storage
208             __PACKAGE__->ensure_class_loaded('DBIx::Class::Storage::DBI::MariaDB');
209              
210             package MyApp;
211             use MyApp::Schema;
212              
213             my $dsn = "dbi:MariaDB:database=mydb";
214             my $user = "noone";
215             my $pass = "topsecret";
216             my $schema = MyApp::Schema->connect($dsn, $user, $pass);
217              
218             =head1 COPYRIGHT AND LICENSE
219              
220             Copyright (C) 2023 Siemplexus
221              
222             This library is free software; you can redistribute it and/or modify
223             it under the same terms as Perl itself.
224              
225             =head1 AUTHORS
226              
227             Antonis Kalou Ea.kalou@shadowcat.co.ukE
228             Jess Robinson Ej.robinson@shadowcat.co.ukE