1package Rose::DB::MySQL;
2
3use strict;
4
5use Carp();
6
7use DateTime::Format::MySQL;
8use SQL::ReservedWords::MySQL();
9
10TRY:
11{
12  local $@;
13  eval { require DBD::mysql }; # Ignore errors
14}
15
16use Rose::DB;
17
18our $VERSION = '0.774';
19
20our $Debug = 0;
21
22use Rose::Class::MakeMethods::Generic
23(
24  inheritable_scalar =>
25  [
26    'supports_schema',
27    'coerce_autoincrement_to_serial',
28  ]
29);
30
31__PACKAGE__->supports_schema(1);
32__PACKAGE__->coerce_autoincrement_to_serial(1);
33
34#
35# Object methods
36#
37
38sub registration_schema { shift->database }
39
40sub build_dsn
41{
42  my($self_or_class, %args) = @_;
43
44  my %info;
45
46  $info{'database'} = $args{'db'} || $args{'database'};
47  $info{'host'}     = $args{'host'};
48  $info{'port'}     = $args{'port'};
49
50  return
51    "dbi:mysql:" .
52    join(';', map { "$_=$info{$_}" } grep { defined $info{$_} }
53              qw(database host port));
54}
55
56sub dbi_driver { 'mysql' }
57
58sub mysql_auto_reconnect     { shift->dbh_attribute_boolean('mysql_auto_reconnect', @_) }
59sub mysql_client_found_rows  { shift->dbh_attribute_boolean('mysql_client_found_rows', @_) }
60sub mysql_compression        { shift->dbh_attribute_boolean('mysql_compression', @_) }
61sub mysql_connect_timeout    { shift->dbh_attribute_boolean('mysql_connect_timeout', @_) }
62sub mysql_embedded_groups    { shift->dbh_attribute('mysql_embedded_groups', @_) }
63sub mysql_embedded_options   { shift->dbh_attribute('mysql_embedded_options', @_) }
64sub mysql_local_infile       { shift->dbh_attribute('mysql_local_infile', @_) }
65sub mysql_multi_statements   { shift->dbh_attribute_boolean('mysql_multi_statements', @_) }
66sub mysql_read_default_file  { shift->dbh_attribute('mysql_read_default_file', @_) }
67sub mysql_read_default_group { shift->dbh_attribute('mysql_read_default_group', @_) }
68sub mysql_socket             { shift->dbh_attribute('mysql_socket', @_) }
69sub mysql_ssl                { shift->dbh_attribute_boolean('mysql_ssl', @_) }
70sub mysql_ssl_ca_file        { shift->dbh_attribute('mysql_ssl_ca_file', @_) }
71sub mysql_ssl_ca_path        { shift->dbh_attribute('mysql_ssl_ca_path', @_) }
72sub mysql_ssl_cipher         { shift->dbh_attribute('mysql_ssl_cipher', @_) }
73sub mysql_ssl_client_cert    { shift->dbh_attribute('mysql_ssl_client_cert', @_) }
74sub mysql_ssl_client_key     { shift->dbh_attribute('mysql_ssl_client_key', @_) }
75sub mysql_use_result         { shift->dbh_attribute_boolean('mysql_use_result', @_) }
76sub mysql_bind_type_guessing { shift->dbh_attribute_boolean('mysql_bind_type_guessing', @_) }
77
78sub mysql_enable_utf8
79{
80  my($self) = shift;
81  $self->dbh->do('SET NAMES utf8')  if(@_ && $self->has_dbh);
82  $self->dbh_attribute_boolean('mysql_enable_utf8', @_)
83}
84
85sub mysql_enable_utf8mb4
86{
87  my($self) = shift;
88  $self->dbh->do('SET NAMES utf8mb4')  if(@_ && $self->has_dbh);
89  $self->dbh_attribute_boolean('mysql_enable_utf8mb4', @_)
90}
91
92sub database_version
93{
94  my($self) = shift;
95  return $self->{'database_version'}  if(defined $self->{'database_version'});
96
97  my $vers = $self->dbh->get_info(18); # SQL_DBMS_VER
98
99  # Convert to an integer, e.g., 5.1.13 -> 5001013
100  if($vers =~ /^(\d+)\.(\d+)(?:\.(\d+))?/)
101  {
102    $vers = sprintf('%d%03d%03d', $1, $2, $3 || 0);
103  }
104
105  return $self->{'database_version'} = $vers;
106}
107
108sub init_dbh
109{
110  my($self) = shift;
111
112  $self->{'supports_on_duplicate_key_update'} = undef;
113
114  my $method = ref($self)->parent_class . '::init_dbh';
115
116  no strict 'refs';
117  return $self->$method(@_);
118}
119
120sub max_column_name_length { 64 }
121sub max_column_alias_length { 255 }
122
123sub quote_column_name
124{
125  my $name = $_[1];
126  $name =~ s/`/``/g;
127  return qq(`$name`);
128}
129
130sub quote_table_name
131{
132  my $name = $_[1];
133  $name =~ s/`/``/g;
134  return qq(`$name`);
135}
136
137sub list_tables
138{
139  my($self, %args) = @_;
140
141  my $types = $args{'include_views'} ? "'TABLE','VIEW'" : 'TABLE';
142  my @tables;
143
144  my $schema = $self->schema;
145
146  $schema = $self->database  unless(defined $schema);
147
148  my $error;
149
150  TRY:
151  {
152    local $@;
153
154    eval
155    {
156      my $dbh = $self->dbh or die $self->error;
157
158      local $dbh->{'RaiseError'} = 1;
159      local $dbh->{'FetchHashKeyName'} = 'NAME';
160
161      my $sth = $dbh->table_info($self->catalog, $schema, '%', $types);
162
163      $sth->execute;
164
165      while(my $table_info = $sth->fetchrow_hashref)
166      {
167        push(@tables, $self->unquote_table_name($table_info->{'TABLE_NAME'}));
168      }
169    };
170
171    $error = $@;
172  }
173
174  if($error)
175  {
176    Carp::croak "Could not list tables from ", $self->dsn, " - $error";
177  }
178
179  return wantarray ? @tables : \@tables;
180}
181
182sub init_date_handler { DateTime::Format::MySQL->new }
183
184sub insertid_param { 'mysql_insertid' }
185
186sub last_insertid_from_sth { $_[1]->{'mysql_insertid'} }
187
188sub format_table_with_alias
189{
190  my($self, $table, $alias, $hints) = @_;
191
192  my $version = $self->database_version;
193
194  if($hints && $version >= 3_023_012)
195  {
196    my $sql = "$table $alias ";
197
198    # "ignore index()" and "use index()" were added in 3.23.12 (07 March 2000)
199    # "force index()" was added in 4.0.9 (09 January 2003)
200    my @types = (($version >= 4_000_009 ? 'force' : ()), qw(use ignore));
201
202    foreach my $index_hint_type (@types)
203    {
204      my $key = "${index_hint_type}_index";
205
206      if($hints->{$key})
207      {
208        $sql .= uc($index_hint_type) . ' INDEX (';
209
210        if(ref $hints->{$key} eq 'ARRAY')
211        {
212          $sql .= join(', ', @{$hints->{$key}});
213        }
214        else { $sql .= $hints->{$key} }
215
216        $sql .= ')';
217
218        # Only one of these hints is allowed
219        last;
220      }
221    }
222
223    return $sql;
224  }
225
226  return "$table $alias";
227}
228
229sub format_select_start_sql
230{
231  my($self, $hints) = @_;
232
233  return 'SELECT'  unless($hints);
234
235  return 'SELECT ' . ($hints->{'comment'} ? "/* $hints->{'comment'} */" : '') .
236    join(' ', (map { $hints->{$_} ? uc("sql_$_") : () }
237      qw(small_result big_result buffer_result cache no_cache calc_found_rows)),
238      (map { $hints->{$_} ? uc($_) : () } qw(high_priority straight_join)));
239}
240
241sub format_select_lock
242{
243  my($self, $class, $lock, $tables_list) = @_;
244
245  $lock = { type => $lock }  unless(ref $lock);
246
247  $lock->{'type'} ||= 'for update'  if($lock->{'for_update'});
248
249  my %types =
250  (
251    'for update' => 'FOR UPDATE',
252    'shared'     => 'LOCK IN SHARE MODE',
253  );
254
255  my $sql = $types{$lock->{'type'}}
256    or Carp::croak "Invalid lock type: $lock->{'type'}";
257
258  return $sql;
259}
260
261sub validate_date_keyword
262{
263  no warnings;
264  !ref $_[1] && ($_[1] =~ /^(?:(?:now|cur(?:date|time)|sysdate)\(\)|
265    current_(?:time|date|timestamp)(?:\(\))?|0000-00-00)$/xi ||
266    ($_[0]->keyword_function_calls && $_[1] =~ /^\w+\(.*\)$/));
267}
268
269sub validate_datetime_keyword
270{
271  no warnings;
272  !ref $_[1] && ($_[1]  =~ /^(?:(?:now|cur(?:date|time)|sysdate)\(\)|
273    current_(?:time|date|timestamp)(?:\(\))?|0000-00-00[ ]00:00:00)$/xi ||
274    ($_[0]->keyword_function_calls && $_[1] =~ /^\w+\(.*\)$/));
275}
276
277sub validate_timestamp_keyword
278{
279  no warnings;
280  !ref $_[1] && ($_[1] =~ /^(?:(?:now|cur(?:date|time)|sysdate)\(\)|
281    current_(?:time|date|timestamp)(?:\(\))?|0000-00-00[ ]00:00:00|00000000000000)$/xi ||
282    ($_[0]->keyword_function_calls && $_[1] =~ /^\w+\(.*\)$/));
283}
284
285*format_timestamp = \&Rose::DB::format_datetime;
286
287sub parse_bitfield
288{
289  my($self, $val, $size, $from_db) = @_;
290
291  if(ref $val)
292  {
293    if($size && $val->Size != $size)
294    {
295      return Bit::Vector->new_Bin($size, $val->to_Bin);
296    }
297
298    return $val;
299  }
300
301  no warnings 'uninitialized';
302  if($from_db && $val =~ /^\d+$/)
303  {
304    return Bit::Vector->new_Dec($size || (length($val) * 4), $val);
305  }
306  elsif($val =~ /^[10]+$/)
307  {
308    return Bit::Vector->new_Bin($size || length $val, $val);
309  }
310  elsif($val =~ /^\d*[2-9]\d*$/)
311  {
312    return Bit::Vector->new_Dec($size || (length($val) * 4), $val);
313  }
314  elsif($val =~ s/^0x// || $val =~ s/^X'(.*)'$/$1/ || $val =~ /^[0-9a-f]+$/i)
315  {
316    return Bit::Vector->new_Hex($size || (length($val) * 4), $val);
317  }
318  elsif($val =~ s/^B'([10]+)'$/$1/i)
319  {
320    return Bit::Vector->new_Bin($size || length $val, $val);
321  }
322  else
323  {
324    return undef;
325    #return Bit::Vector->new_Bin($size || length($val), $val);
326  }
327}
328
329sub format_bitfield
330{
331  my($self, $vec, $size) = @_;
332
333  $vec = Bit::Vector->new_Bin($size, $vec->to_Bin)  if($size);
334
335  # MySQL 5.0.3 or later requires this crap...
336  if($self->database_version >= 5_000_003)
337  {
338    return q(b') . $vec->to_Bin . q('); # 'CAST(' . $vec->to_Dec . ' AS UNSIGNED)';
339  }
340
341  return hex($vec->to_Hex);
342}
343
344sub validate_bitfield_keyword { defined $_[1] ? 1 : 0 }
345
346sub should_inline_bitfield_value
347{
348  # MySQL 5.0.3 or later requires this crap...
349  return $_[0]->{'should_inline_bitfield_value'} ||=
350    (shift->database_version >= 5_000_003) ? 1 : 0;
351}
352
353sub select_bitfield_column_sql
354{
355  my($self, $column, $table) = @_;
356
357  # MySQL 5.0.3 or later requires this crap...
358  if($self->database_version >= 5_000_003)
359  {
360    return q{CONCAT("b'", BIN(} .
361           $self->auto_quote_column_with_table($column, $table) .
362           q{ + 0), "'")};
363  }
364  else
365  {
366    return $self->auto_quote_column_with_table($column, $table) . q{ + 0};
367  }
368}
369
370sub parse_set
371{
372  my($self) = shift;
373
374  return $_[0]  if(ref $_[0] eq 'ARRAY');
375
376  if(@_ > 1 && !ref $_[1])
377  {
378    pop(@_);
379    return [ @_ ];
380  }
381
382  my $val = $_[0];
383
384  return undef  unless(defined $val);
385
386  my @set = split(/,/, $val);
387
388  return \@set;
389}
390
391sub format_set
392{
393  my($self) = shift;
394
395  my @set = (ref $_[0]) ? @{$_[0]} : @_;
396
397  return undef  unless(@set && defined $set[0]);
398
399  return join(',', map
400  {
401    if(!defined $_)
402    {
403      Carp::croak 'Undefined value found in array or list passed to ',
404                  __PACKAGE__, '::format_set()';
405    }
406    else { $_ }
407  }
408  @set);
409}
410
411sub refine_dbi_column_info
412{
413  my($self, $col_info) = @_;
414
415  my $method = ref($self)->parent_class . '::refine_dbi_column_info';
416
417  no strict 'refs';
418  $self->$method($col_info);
419
420  if($col_info->{'TYPE_NAME'} eq 'timestamp' && defined $col_info->{'COLUMN_DEF'})
421  {
422    if($col_info->{'COLUMN_DEF'} eq '0000-00-00 00:00:00' ||
423       $col_info->{'COLUMN_DEF'} eq '00000000000000')
424    {
425      # MySQL uses strange "all zeros" default values for timestamp fields.
426      # We'll just ignore them, since MySQL will use them internally no
427      # matter what we do.
428      $col_info->{'COLUMN_DEF'} = undef;
429    }
430    elsif($col_info->{'COLUMN_DEF'} eq 'CURRENT_TIMESTAMP')
431    {
432      # Translate "current time" value into something that our date parser
433      # will understand.
434      #$col_info->{'COLUMN_DEF'} = 'now';
435
436      # Actually, let the database handle this.
437      $col_info->{'COLUMN_DEF'} = undef;
438    }
439  }
440
441  # Put valid SET and ENUM values in standard keys
442  if($col_info->{'TYPE_NAME'} eq 'set')
443  {
444
445    $col_info->{'RDBO_SET_VALUES'} = $col_info->{'mysql_values'};
446  }
447  elsif($col_info->{'TYPE_NAME'} eq 'enum')
448  {
449    $col_info->{'RDBO_ENUM_VALUES'} = $col_info->{'mysql_values'};
450  }
451
452  # Consider (big)int autoincrement to be (big)serial
453  if($col_info->{'mysql_is_auto_increment'} &&
454     ref($self)->coerce_autoincrement_to_serial)
455  {
456    if($col_info->{'TYPE_NAME'} eq 'int')
457    {
458      $col_info->{'TYPE_NAME'} = 'serial';
459    }
460    elsif($col_info->{'TYPE_NAME'} eq 'bigint')
461    {
462      $col_info->{'TYPE_NAME'} = 'bigserial';
463    }
464  }
465
466  return;
467}
468
469sub supports_arbitrary_defaults_on_insert { 1 }
470sub likes_redundant_join_conditions       { 1 }
471
472sub supports_on_duplicate_key_update
473{
474  my($self) = shift;
475
476  if(defined $self->{'supports_on_duplicate_key_update'})
477  {
478    return $self->{'supports_on_duplicate_key_update'};
479  }
480
481  if($self->database_version >= 4_001_000)
482  {
483    return $self->{'supports_on_duplicate_key_update'} = 1;
484  }
485
486  return $self->{'supports_on_duplicate_key_update'} = 0;
487}
488
489sub supports_select_from_subselect
490{
491  my($self) = shift;
492
493  if(defined $self->{'supports_select_from_subselect'})
494  {
495    return $self->{'supports_select_from_subselect'};
496  }
497
498  if($self->database_version >= 5_000_045)
499  {
500    return $self->{'supports_select_from_subselect'} = 1;
501  }
502
503  return $self->{'supports_select_from_subselect'} = 0;
504}
505
506#our %Reserved_Words = map { $_ => 1 } qw(read for case);
507#sub is_reserved_word { $Reserved_Words{lc $_[1]} }
508
509*is_reserved_word = \&SQL::ReservedWords::MySQL::is_reserved;
510
511#
512# Introspection
513#
514
515sub _get_primary_key_column_names
516{
517  my($self, $catalog, $schema, $table) = @_;
518
519  my $dbh = $self->dbh or die $self->error;
520
521  local $dbh->{'FetchHashKeyName'} = 'NAME';
522
523  my $fq_table =
524    join('.', grep { defined } ($catalog, $schema,
525                                $self->quote_table_name($table)));
526
527  my $sth = $dbh->prepare("SHOW INDEX FROM $fq_table");
528  $sth->execute;
529
530  my @columns;
531
532  while(my $row = $sth->fetchrow_hashref)
533  {
534    next  unless($row->{'Key_name'} eq 'PRIMARY');
535    push(@columns, $row->{'Column_name'});
536  }
537
538  return \@columns;
539}
540
541# Bury warning down here to make nice with version extractors
542if(defined $DBD::mysql::VERSION && $DBD::mysql::VERSION <= 2.9)
543{
544  warn "WARNING: Rose::DB may not work correctly with DBD::mysql ",
545       "version 2.9 or earlier.  You have version $DBD::mysql::VERSION";
546}
547
5481;
549
550__END__
551
552=head1 NAME
553
554Rose::DB::MySQL - MySQL driver class for Rose::DB.
555
556=head1 SYNOPSIS
557
558  use Rose::DB;
559
560  Rose::DB->register_db(
561    domain   => 'development',
562    type     => 'main',
563    driver   => 'mysql',
564    database => 'dev_db',
565    host     => 'localhost',
566    username => 'devuser',
567    password => 'mysecret',
568  );
569
570
571  Rose::DB->default_domain('development');
572  Rose::DB->default_type('main');
573  ...
574
575  # Set max length of varchar columns used to emulate the array data type
576  Rose::DB::MySQL->max_array_characters(128);
577
578  $db = Rose::DB->new; # $db is really a Rose::DB::MySQL-derived object
579  ...
580
581=head1 DESCRIPTION
582
583L<Rose::DB> blesses objects into a class derived from L<Rose::DB::MySQL> when the L<driver|Rose::DB/driver> is "mysql".  This mapping of driver names to class names is configurable.  See the documentation for L<Rose::DB>'s L<new()|Rose::DB/new> and L<driver_class()|Rose::DB/driver_class> methods for more information.
584
585This class cannot be used directly.  You must use L<Rose::DB> and let its L<new()|Rose::DB/new> method return an object blessed into the appropriate class for you, according to its L<driver_class()|Rose::DB/driver_class> mappings.
586
587Only the methods that are new or have different behaviors than those in L<Rose::DB> are documented here.  See the L<Rose::DB> documentation for the full list of methods.
588
589=head1 CLASS METHODS
590
591=over 4
592
593=item B<coerce_autoincrement_to_serial [BOOL]>
594
595Get or set a boolean value that indicates whether or not "auto-increment" columns will be considered to have the column type  "serial."  If true, "integer" columns are coerced to the "serial" column type, and "bigint" columns use the "bigserial" column type.  The default value is true.
596
597This setting comes into play when L<Rose::DB::Object::Loader> is used to auto-create column metadata based on an existing database schema.
598
599=item B<max_array_characters [INT]>
600
601Get or set the maximum length of varchar columns used to emulate the array data type.  The default value is 255.
602
603MySQL does not have a native "ARRAY" data type, but this data type can be emulated using a "VARCHAR" column and a specially formatted string.  The formatting and parsing of this string is handled by the L<format_array|/format_array> and L<parse_array|/parse_array> object methods.  The maximum length limit is honored by the L<format_array|/format_array> object method.
604
605=item B<max_interval_characters [INT]>
606
607Get or set the maximum length of varchar columns used to emulate the interval data type.  The default value is 255.
608
609MySQL does not have a native "interval" data type, but this data type can be emulated using a "VARCHAR" column and a specially formatted string.  The formatting and parsing of this string is handled by the L<format_interval|/format_interval> and L<parse_interval|/parse_interval> object methods.  The maximum length limit is honored by the L<format_interval|/format_interval> object method.
610
611=back
612
613=head1 OBJECT METHODS
614
615=over 4
616
617=item B<mysql_auto_reconnect [BOOL]>
618
619Get or set the L<mysql_auto_reconnect|DBD::mysql/mysql_auto_reconnect> database handle attribute.  This is set directly on the L<dbh|Rose::DB/dbh>, if one exists.  Otherwise, it will be set when the L<dbh|Rose::DB/dbh> is created.  If no value for this attribute is defined (the default) then it will not be set when the L<dbh|Rose::DB/dbh> is created, deferring instead to whatever default value L<DBD::mysql> chooses.
620
621Returns the value of this attribute in the L<dbh|Rose::DB/dbh>, if one exists, or the value that will be set when the L<dbh|Rose::DB/dbh> is next created.
622
623See the L<DBD::mysql|DBD::mysql/mysql_auto_reconnect> documentation to learn more about this attribute.
624
625=item B<mysql_bind_type_guessing [BOOL]>
626
627Get or set the L<mysql_bind_type_guessing|DBD::mysql/mysql_bind_type_guessing> database handle attribute.  This is set directly on the L<dbh|Rose::DB/dbh>, if one exists.  Otherwise, it will be set when the L<dbh|Rose::DB/dbh> is created.  If no value for this attribute is defined (the default) then it will not be set when the L<dbh|Rose::DB/dbh> is created, deferring instead to whatever default value L<DBD::mysql> chooses.
628
629Returns the value of this attribute in the L<dbh|Rose::DB/dbh>, if one exists, or the value that will be set when the L<dbh|Rose::DB/dbh> is next created.
630
631See the L<DBD::mysql|DBD::mysql/mysql_bind_type_guessing> documentation to learn more about this attribute.
632
633=item B<mysql_client_found_rows [BOOL]>
634
635Get or set the L<mysql_client_found_rows|DBD::mysql/mysql_client_found_rows> database handle attribute.  This is set directly on the L<dbh|Rose::DB/dbh>, if one exists.  Otherwise, it will be set when the L<dbh|Rose::DB/dbh> is created.  If no value for this attribute is defined (the default) then it will not be set when the L<dbh|Rose::DB/dbh> is created, deferring instead to whatever default value L<DBD::mysql> chooses.
636
637Returns the value of this attribute in the L<dbh|Rose::DB/dbh>, if one exists, or the value that will be set when the L<dbh|Rose::DB/dbh> is next created.
638
639See the L<DBD::mysql|DBD::mysql/mysql_client_found_rows> documentation to learn more about this attribute.
640
641=item B<mysql_compression [BOOL]>
642
643Get or set the L<mysql_compression|DBD::mysql/mysql_compression> database handle attribute.  This is set directly on the L<dbh|Rose::DB/dbh>, if one exists.  Otherwise, it will be set when the L<dbh|Rose::DB/dbh> is created.  If no value for this attribute is defined (the default) then it will not be set when the L<dbh|Rose::DB/dbh> is created, deferring instead to whatever default value L<DBD::mysql> chooses.
644
645Returns the value of this attribute in the L<dbh|Rose::DB/dbh>, if one exists, or the value that will be set when the L<dbh|Rose::DB/dbh> is next created.
646
647See the L<DBD::mysql|DBD::mysql/mysql_compression> documentation to learn more about this attribute.
648
649=item B<mysql_connect_timeout [BOOL]>
650
651Get or set the L<mysql_connect_timeout|DBD::mysql/mysql_connect_timeout> database handle attribute.  This is set directly on the L<dbh|Rose::DB/dbh>, if one exists.  Otherwise, it will be set when the L<dbh|Rose::DB/dbh> is created.  If no value for this attribute is defined (the default) then it will not be set when the L<dbh|Rose::DB/dbh> is created, deferring instead to whatever default value L<DBD::mysql> chooses.
652
653Returns the value of this attribute in the L<dbh|Rose::DB/dbh>, if one exists, or the value that will be set when the L<dbh|Rose::DB/dbh> is next created.
654
655See the L<DBD::mysql|DBD::mysql/mysql_connect_timeout> documentation to learn more about this attribute.
656
657=item B<mysql_embedded_groups [STRING]>
658
659Get or set the L<mysql_embedded_groups|DBD::mysql/mysql_embedded_groups> database handle attribute.  This is set directly on the L<dbh|Rose::DB/dbh>, if one exists.  Otherwise, it will be set when the L<dbh|Rose::DB/dbh> is created.  If no value for this attribute is defined (the default) then it will not be set when the L<dbh|Rose::DB/dbh> is created, deferring instead to whatever default value L<DBD::mysql> chooses.
660
661Returns the value of this attribute in the L<dbh|Rose::DB/dbh>, if one exists, or the value that will be set when the L<dbh|Rose::DB/dbh> is next created.
662
663See the L<DBD::mysql|DBD::mysql/mysql_embedded_groups> documentation to learn more about this attribute.
664
665=item B<mysql_embedded_options [STRING]>
666
667Get or set the L<mysql_embedded_options|DBD::mysql/mysql_embedded_options> database handle attribute.  This is set directly on the L<dbh|Rose::DB/dbh>, if one exists.  Otherwise, it will be set when the L<dbh|Rose::DB/dbh> is created.  If no value for this attribute is defined (the default) then it will not be set when the L<dbh|Rose::DB/dbh> is created, deferring instead to whatever default value L<DBD::mysql> chooses.
668
669Returns the value of this attribute in the L<dbh|Rose::DB/dbh>, if one exists, or the value that will be set when the L<dbh|Rose::DB/dbh> is next created.
670
671See the L<DBD::mysql|DBD::mysql/mysql_embedded_options> documentation to learn more about this attribute.
672
673=item B<mysql_enable_utf8 [BOOL]>
674
675Get or set the L<mysql_enable_utf8|DBD::mysql/mysql_enable_utf8> database handle attribute.  This is set directly on the L<dbh|Rose::DB/dbh>, if one exists, by executing the SQL C<SET NAMES utf8>.  Otherwise, it will be set when the L<dbh|Rose::DB/dbh> is created.  If no value for this attribute is defined (the default) then it will not be set when the L<dbh|Rose::DB/dbh> is created, deferring instead to whatever default value L<DBD::mysql> chooses.
676
677Returns the value of this attribute in the L<dbh|Rose::DB/dbh>, if one exists, or the value that will be set when the L<dbh|Rose::DB/dbh> is next created.
678
679See the L<DBD::mysql|DBD::mysql/mysql_enable_utf8> documentation to learn more about this attribute.
680
681=item B<mysql_enable_utf8mb4 [BOOL]>
682
683Get or set the L<mysql_enable_utf8mb4|DBD::mysql/mysql_enable_utf8mb4> database handle attribute.  This is set directly on the L<dbh|Rose::DB/dbh>, if one exists, by executing the SQL C<SET NAMES utf8mb4>.  Otherwise, it will be set when the L<dbh|Rose::DB/dbh> is created.  If no value for this attribute is defined (the default) then it will not be set when the L<dbh|Rose::DB/dbh> is created, deferring instead to whatever default value L<DBD::mysql> chooses.
684
685Returns the value of this attribute in the L<dbh|Rose::DB/dbh>, if one exists, or the value that will be set when the L<dbh|Rose::DB/dbh> is next created.
686
687See the L<DBD::mysql|DBD::mysql/mysql_enable_utf8mb4> documentation to learn more about this attribute.
688
689=item B<mysql_local_infile [STRING]>
690
691Get or set the L<mysql_local_infile|DBD::mysql/mysql_local_infile> database handle attribute.  This is set directly on the L<dbh|Rose::DB/dbh>, if one exists.  Otherwise, it will be set when the L<dbh|Rose::DB/dbh> is created.  If no value for this attribute is defined (the default) then it will not be set when the L<dbh|Rose::DB/dbh> is created, deferring instead to whatever default value L<DBD::mysql> chooses.
692
693Returns the value of this attribute in the L<dbh|Rose::DB/dbh>, if one exists, or the value that will be set when the L<dbh|Rose::DB/dbh> is next created.
694
695See the L<DBD::mysql|DBD::mysql/mysql_local_infile> documentation to learn more about this attribute.
696
697=item B<mysql_multi_statements [BOOL]>
698
699Get or set the L<mysql_multi_statements|DBD::mysql/mysql_multi_statements> database handle attribute.  This is set directly on the L<dbh|Rose::DB/dbh>, if one exists.  Otherwise, it will be set when the L<dbh|Rose::DB/dbh> is created.  If no value for this attribute is defined (the default) then it will not be set when the L<dbh|Rose::DB/dbh> is created, deferring instead to whatever default value L<DBD::mysql> chooses.
700
701Returns the value of this attribute in the L<dbh|Rose::DB/dbh>, if one exists, or the value that will be set when the L<dbh|Rose::DB/dbh> is next created.
702
703See the L<DBD::mysql|DBD::mysql/mysql_multi_statements> documentation to learn more about this attribute.
704
705=item B<mysql_read_default_file [STRING]>
706
707Get or set the L<mysql_read_default_file|DBD::mysql/mysql_read_default_file> database handle attribute.  This is set directly on the L<dbh|Rose::DB/dbh>, if one exists.  Otherwise, it will be set when the L<dbh|Rose::DB/dbh> is created.  If no value for this attribute is defined (the default) then it will not be set when the L<dbh|Rose::DB/dbh> is created, deferring instead to whatever default value L<DBD::mysql> chooses.
708
709Returns the value of this attribute in the L<dbh|Rose::DB/dbh>, if one exists, or the value that will be set when the L<dbh|Rose::DB/dbh> is next created.
710
711See the L<DBD::mysql|DBD::mysql/mysql_read_default_file> documentation to learn more about this attribute.
712
713=item B<mysql_read_default_group [STRING]>
714
715Get or set the L<mysql_read_default_group|DBD::mysql/mysql_read_default_group> database handle attribute.  This is set directly on the L<dbh|Rose::DB/dbh>, if one exists.  Otherwise, it will be set when the L<dbh|Rose::DB/dbh> is created.  If no value for this attribute is defined (the default) then it will not be set when the L<dbh|Rose::DB/dbh> is created, deferring instead to whatever default value L<DBD::mysql> chooses.
716
717Returns the value of this attribute in the L<dbh|Rose::DB/dbh>, if one exists, or the value that will be set when the L<dbh|Rose::DB/dbh> is next created.
718
719See the L<DBD::mysql|DBD::mysql/mysql_read_default_group> documentation to learn more about this attribute.
720
721=item B<mysql_socket [STRING]>
722
723Get or set the L<mysql_socket|DBD::mysql/mysql_socket> database handle attribute.  This is set directly on the L<dbh|Rose::DB/dbh>, if one exists.  Otherwise, it will be set when the L<dbh|Rose::DB/dbh> is created.  If no value for this attribute is defined (the default) then it will not be set when the L<dbh|Rose::DB/dbh> is created, deferring instead to whatever default value L<DBD::mysql> chooses.
724
725Returns the value of this attribute in the L<dbh|Rose::DB/dbh>, if one exists, or the value that will be set when the L<dbh|Rose::DB/dbh> is next created.
726
727See the L<DBD::mysql|DBD::mysql/mysql_socket> documentation to learn more about this attribute.
728
729=item B<mysql_ssl [BOOL]>
730
731Get or set the L<mysql_ssl|DBD::mysql/mysql_ssl> database handle attribute.  This is set directly on the L<dbh|Rose::DB/dbh>, if one exists.  Otherwise, it will be set when the L<dbh|Rose::DB/dbh> is created.  If no value for this attribute is defined (the default) then it will not be set when the L<dbh|Rose::DB/dbh> is created, deferring instead to whatever default value L<DBD::mysql> chooses.
732
733Returns the value of this attribute in the L<dbh|Rose::DB/dbh>, if one exists, or the value that will be set when the L<dbh|Rose::DB/dbh> is next created.
734
735See the L<DBD::mysql|DBD::mysql/mysql_ssl> documentation to learn more about this attribute.
736
737=item B<mysql_ssl_ca_file [STRING]>
738
739Get or set the L<mysql_ssl_ca_file|DBD::mysql/mysql_ssl_ca_file> database handle attribute.  This is set directly on the L<dbh|Rose::DB/dbh>, if one exists.  Otherwise, it will be set when the L<dbh|Rose::DB/dbh> is created.  If no value for this attribute is defined (the default) then it will not be set when the L<dbh|Rose::DB/dbh> is created, deferring instead to whatever default value L<DBD::mysql> chooses.
740
741Returns the value of this attribute in the L<dbh|Rose::DB/dbh>, if one exists, or the value that will be set when the L<dbh|Rose::DB/dbh> is next created.
742
743See the L<DBD::mysql|DBD::mysql/mysql_ssl_ca_file> documentation to learn more about this attribute.
744
745=item B<mysql_ssl_ca_path [STRING]>
746
747Get or set the L<mysql_ssl_ca_path|DBD::mysql/mysql_ssl_ca_path> database handle attribute.  This is set directly on the L<dbh|Rose::DB/dbh>, if one exists.  Otherwise, it will be set when the L<dbh|Rose::DB/dbh> is created.  If no value for this attribute is defined (the default) then it will not be set when the L<dbh|Rose::DB/dbh> is created, deferring instead to whatever default value L<DBD::mysql> chooses.
748
749Returns the value of this attribute in the L<dbh|Rose::DB/dbh>, if one exists, or the value that will be set when the L<dbh|Rose::DB/dbh> is next created.
750
751See the L<DBD::mysql|DBD::mysql/mysql_ssl_ca_path> documentation to learn more about this attribute.
752
753=item B<mysql_ssl_cipher [STRING]>
754
755Get or set the L<mysql_ssl_cipher|DBD::mysql/mysql_ssl_cipher> database handle attribute.  This is set directly on the L<dbh|Rose::DB/dbh>, if one exists.  Otherwise, it will be set when the L<dbh|Rose::DB/dbh> is created.  If no value for this attribute is defined (the default) then it will not be set when the L<dbh|Rose::DB/dbh> is created, deferring instead to whatever default value L<DBD::mysql> chooses.
756
757Returns the value of this attribute in the L<dbh|Rose::DB/dbh>, if one exists, or the value that will be set when the L<dbh|Rose::DB/dbh> is next created.
758
759See the L<DBD::mysql|DBD::mysql/mysql_ssl_cipher> documentation to learn more about this attribute.
760
761=item B<mysql_ssl_client_cert [STRING]>
762
763Get or set the L<mysql_ssl_client_cert|DBD::mysql/mysql_ssl_client_cert> database handle attribute.  This is set directly on the L<dbh|Rose::DB/dbh>, if one exists.  Otherwise, it will be set when the L<dbh|Rose::DB/dbh> is created.  If no value for this attribute is defined (the default) then it will not be set when the L<dbh|Rose::DB/dbh> is created, deferring instead to whatever default value L<DBD::mysql> chooses.
764
765Returns the value of this attribute in the L<dbh|Rose::DB/dbh>, if one exists, or the value that will be set when the L<dbh|Rose::DB/dbh> is next created.
766
767See the L<DBD::mysql|DBD::mysql/mysql_ssl_client_cert> documentation to learn more about this attribute.
768
769=item B<mysql_ssl_client_key [STRING]>
770
771Get or set the L<mysql_ssl_client_key|DBD::mysql/mysql_ssl_client_key> database handle attribute.  This is set directly on the L<dbh|Rose::DB/dbh>, if one exists.  Otherwise, it will be set when the L<dbh|Rose::DB/dbh> is created.  If no value for this attribute is defined (the default) then it will not be set when the L<dbh|Rose::DB/dbh> is created, deferring instead to whatever default value L<DBD::mysql> chooses.
772
773Returns the value of this attribute in the L<dbh|Rose::DB/dbh>, if one exists, or the value that will be set when the L<dbh|Rose::DB/dbh> is next created.
774
775See the L<DBD::mysql|DBD::mysql/mysql_ssl_client_key> documentation to learn more about this attribute.
776
777=item B<mysql_use_result [BOOL]>
778
779Get or set the L<mysql_use_result|DBD::mysql/mysql_use_result> database handle attribute.  This is set directly on the L<dbh|Rose::DB/dbh>, if one exists.  Otherwise, it will be set when the L<dbh|Rose::DB/dbh> is created.  If no value for this attribute is defined (the default) then it will not be set when the L<dbh|Rose::DB/dbh> is created, deferring instead to whatever default value L<DBD::mysql> chooses.
780
781Returns the value of this attribute in the L<dbh|Rose::DB/dbh>, if one exists, or the value that will be set when the L<dbh|Rose::DB/dbh> is next created.
782
783See the L<DBD::mysql|DBD::mysql/mysql_use_result> documentation to learn more about this attribute.
784
785=back
786
787=head2 Value Parsing and Formatting
788
789=over 4
790
791=item B<format_array ARRAYREF | LIST>
792
793Given a reference to an array or a list of values, return a specially formatted string.  Undef is returned if ARRAYREF points to an empty array or if LIST is not passed.  The array or list must not contain undefined values.
794
795If the resulting string is longer than L<max_array_characters|/max_array_characters>, a fatal error will occur.
796
797=item B<format_interval DURATION>
798
799Given a L<DateTime::Duration> object, return a string formatted according to the rules of PostgreSQL's "INTERVAL" column type.  If DURATION is undefined, a L<DateTime::Duration> object, a valid interval keyword (according to L<validate_interval_keyword|Rose::DB/validate_interval_keyword>), or if it looks like a function call (matches C</^\w+\(.*\)$/>) and L<keyword_function_calls|Rose::DB/keyword_function_calls> is true, then it is returned unmodified.
800
801If the resulting string is longer than L<max_interval_characters|/max_interval_characters>, a fatal error will occur.
802
803=item B<format_set ARRAYREF | LIST>
804
805Given a reference to an array or a list of values, return a string formatted according to the rules of MySQL's "SET" data type.  Undef is returned if ARRAYREF points to an empty array or if LIST is not passed.  If the array or list contains undefined values, a fatal error will occur.
806
807=item B<parse_array STRING | LIST | ARRAYREF>
808
809Parse STRING and return a reference to an array.  STRING should be formatted according to the MySQL array data type emulation format returned by L<format_array()|/format_array>.  Undef is returned if STRING is undefined.
810
811If a LIST of more than one item is passed, a reference to an array containing the values in LIST is returned.
812
813If a an ARRAYREF is passed, it is returned as-is.
814
815=item B<parse_interval STRING>
816
817Parse STRING and return a L<DateTime::Duration> object.  STRING should be formatted according to the PostgreSQL native "interval" (years, months, days, hours, minutes, seconds) data type.
818
819If STRING is a L<DateTime::Duration> object, a valid interval keyword (according to L<validate_interval_keyword|Rose::DB/validate_interval_keyword>), or if it looks like a function call (matches C</^\w+\(.*\)$/>) and L<keyword_function_calls|Rose::DB/keyword_function_calls> is true, then it is returned unmodified.  Otherwise, undef is returned if STRING could not be parsed as a valid "interval" value.
820
821=item B<parse_set STRING | LIST | ARRAYREF>
822
823Parse STRING and return a reference to an array.  STRING should be formatted according to MySQL's "SET" data type.  Undef is returned if STRING is undefined.
824
825If a LIST of more than one item is passed, a reference to an array containing the values in LIST is returned.
826
827If a an ARRAYREF is passed, it is returned as-is.
828
829=item B<validate_date_keyword STRING>
830
831Returns true if STRING is a valid keyword for the MySQL "date" data type.  Valid (case-insensitive) date keywords are:
832
833    curdate()
834    current_date
835    current_date()
836    now()
837    sysdate()
838    00000-00-00
839
840Any string that looks like a function call (matches /^\w+\(.*\)$/) is also considered a valid date keyword if L<keyword_function_calls|Rose::DB/keyword_function_calls> is true.
841
842=item B<validate_datetime_keyword STRING>
843
844Returns true if STRING is a valid keyword for the MySQL "datetime" data type, false otherwise.  Valid (case-insensitive) datetime keywords are:
845
846    curdate()
847    current_date
848    current_date()
849    current_time
850    current_time()
851    current_timestamp
852    current_timestamp()
853    curtime()
854    now()
855    sysdate()
856    0000-00-00 00:00:00
857
858Any string that looks like a function call (matches /^\w+\(.*\)$/) is also considered a valid datetime keyword if L<keyword_function_calls|Rose::DB/keyword_function_calls> is true.
859
860=item B<validate_timestamp_keyword STRING>
861
862Returns true if STRING is a valid keyword for the MySQL "timestamp" data type, false otherwise.  Valid (case-insensitive) timestamp keywords are:
863
864    curdate()
865    current_date
866    current_date()
867    current_time
868    current_time()
869    current_timestamp
870    current_timestamp()
871    curtime()
872    now()
873    sysdate()
874    0000-00-00 00:00:00
875    00000000000000
876
877Any string that looks like a function call (matches /^\w+\(.*\)$/) is also considered a valid timestamp keyword if L<keyword_function_calls|Rose::DB/keyword_function_calls> is true.
878
879=back
880
881=head1 AUTHOR
882
883John C. Siracusa (siracusa@gmail.com)
884
885=head1 LICENSE
886
887Copyright (c) 2010 by John C. Siracusa.  All rights reserved.  This program is
888free software; you can redistribute it and/or modify it under the same terms
889as Perl itself.
890