non-destructive hashref handling for connect_info options
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / DBI.pm
index 7d1ced1..336ab1f 100644 (file)
@@ -115,7 +115,7 @@ sub _emulate_limit {
 }
 
 sub _recurse_fields {
-  my ($self, $fields) = @_;
+  my ($self, $fields, $params) = @_;
   my $ref = ref $fields;
   return $self->_quote($fields) unless $ref;
   return $$fields if $ref eq 'SCALAR';
@@ -123,10 +123,10 @@ sub _recurse_fields {
   if ($ref eq 'ARRAY') {
     return join(', ', map {
       $self->_recurse_fields($_)
-      .(exists $self->{rownum_hack_count}
-         ? ' AS col'.$self->{rownum_hack_count}++
-         : '')
-     } @$fields);
+        .(exists $self->{rownum_hack_count} && !($params && $params->{no_rownum_hack})
+          ? ' AS col'.$self->{rownum_hack_count}++
+          : '')
+      } @$fields);
   } elsif ($ref eq 'HASH') {
     foreach my $func (keys %$fields) {
       return $self->_sqlcase($func)
@@ -142,7 +142,7 @@ sub _order_by {
   if (ref $_[0] eq 'HASH') {
     if (defined $_[0]->{group_by}) {
       $ret = $self->_sqlcase(' group by ')
-               .$self->_recurse_fields($_[0]->{group_by});
+        .$self->_recurse_fields($_[0]->{group_by}, { no_rownum_hack => 1 });
     }
     if (defined $_[0]->{having}) {
       my $frag;
@@ -382,15 +382,14 @@ each other. In most cases this is simply a C<.>.
 =item unsafe
 
 This Storage driver normally installs its own C<HandleError>, sets
-C<RaiseError> on, and sets C<PrintError> off on all database handles,
-including those supplied by a coderef.  It does this so that it can
-have consistent and useful error behavior.
+C<RaiseError> and C<ShowErrorStatement> on, and sets C<PrintError> off on
+all database handles, including those supplied by a coderef.  It does this
+so that it can have consistent and useful error behavior.
 
 If you set this option to a true value, Storage will not do its usual
-modifications to the database handle's C<RaiseError>, C<PrintError>, and
-C<HandleError> attributes, and instead relies on the settings in your
-connect_info DBI options (or the values you set in your connection
-coderef, in the case that you are connecting via coderef).
+modifications to the database handle's attributes, and instead relies on
+the settings in your connect_info DBI options (or the values you set in
+your connection coderef, in the case that you are connecting via coderef).
 
 Note that your custom settings can cause Storage to malfunction,
 especially if you set a C<HandleError> handler that suppresses exceptions
@@ -480,6 +479,7 @@ sub connect_info {
 
   my $last_info = $dbi_info->[-1];
   if(ref $last_info eq 'HASH') {
+    $last_info = { %$last_info }; # so delete is non-destructive
     for my $storage_opt (qw/on_connect_do disable_sth_caching unsafe/) {
       if(my $value = delete $last_info->{$storage_opt}) {
         $self->$storage_opt($value);
@@ -490,6 +490,8 @@ sub connect_info {
         $self->_sql_maker_opts->{$sql_maker_opt} = $opt_val;
       }
     }
+    # re-insert modified hashref
+    $dbi_info->[-1] = $last_info;
 
     # Get rid of any trailing empty hashref
     pop(@$dbi_info) if !keys %$last_info;
@@ -772,6 +774,7 @@ sub _connect {
       $dbh->{HandleError} = sub {
           $weak_self->throw_exception("DBI Exception: $_[0]")
       };
+      $dbh->{ShowErrorStatement} = 1;
       $dbh->{RaiseError} = 1;
       $dbh->{PrintError} = 0;
     }
@@ -788,6 +791,7 @@ sub _connect {
 
 sub txn_begin {
   my $self = shift;
+  $self->ensure_connected();
   if($self->{transaction_depth}++ == 0) {
     $self->debugobj->txn_begin()
       if $self->debug;
@@ -1199,7 +1203,7 @@ sub bind_attribute_by_data_type {
     return;
 }
 
-=head2 create_ddl_dir (EXPERIMENTAL)
+=head2 create_ddl_dir
 
 =over 4
 
@@ -1210,9 +1214,6 @@ sub bind_attribute_by_data_type {
 Creates a SQL file based on the Schema, for each of the specified
 database types, in the given directory.
 
-Note that this feature is currently EXPERIMENTAL and may not work correctly
-across all databases, or fully handle complex relationships.
-
 =cut
 
 sub create_ddl_dir
@@ -1430,7 +1431,10 @@ Returns the datetime parser class
 
 sub datetime_parser {
   my $self = shift;
-  return $self->{datetime_parser} ||= $self->build_datetime_parser(@_);
+  return $self->{datetime_parser} ||= do {
+    $self->ensure_connected;
+    $self->build_datetime_parser(@_);
+  };
 }
 
 =head2 datetime_parser_type