Massive rewrite of bind handling, and overall simplification of ::Storage::DBI
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / DBI / AutoCast.pm
index e405d02..b7f28a6 100644 (file)
@@ -10,7 +10,7 @@ __PACKAGE__->mk_group_accessors('simple' => 'auto_cast' );
 
 =head1 NAME
 
-DBIx::Class::Storage::DBI::AutoCast
+DBIx::Class::Storage::DBI::AutoCast - Storage component for RDBMS requiring explicit placeholder typing
 
 =head1 SYNOPSIS
 
@@ -18,22 +18,26 @@ DBIx::Class::Storage::DBI::AutoCast
 
 =head1 DESCRIPTION
 
-Some combinations of RDBMS and DBD drivers (e.g. FreeTDS and Sybase)
-statements with values bound to columns or conditions that are not strings
-will throw implicit type conversion errors.
+In some combinations of RDBMS and DBD drivers (e.g. FreeTDS and Sybase)
+statements with values bound to columns or conditions that are not strings will
+throw implicit type conversion errors.
 
 As long as a column L<data_type|DBIx::Class::ResultSource/add_columns> is
-defined, and it resolves to a L<DBI> C<$dbi_type> via C<_dbi_data_type()>
-as defined in your Storage driver, the placeholder for this column will
-be converted to:
+defined and resolves to a base RDBMS native type via L</_native_data_type> as
+defined in your Storage driver, the placeholder for this column will be
+converted to:
 
-  CAST(? as $dbi_type)
+  CAST(? as $mapped_type)
+
+This option can also be enabled in
+L<connect_info|DBIx::Class::Storage::DBI/connect_info> as:
+
+  on_connect_call => ['set_auto_cast']
 
 =cut
 
 sub _prep_for_execute {
   my $self = shift;
-  my ($op, $extra_bind, $ident, $args) = @_;
 
   my ($sql, $bind) = $self->next::method (@_);
 
@@ -41,27 +45,39 @@ sub _prep_for_execute {
 # gets skippeed.
   if ($self->auto_cast && @$bind) {
     my $new_sql;
-    my @sql_part = split /\?/, $sql;
-    my $col_info = $self->_resolve_column_info($ident,[ map $_->[0], @$bind ]);
-
-    foreach my $bound (@$bind) {
-      my $col = $bound->[0];
-      my $dbi_type = $self->_dbi_data_type($col_info->{$col}{data_type});
-
-      foreach my $data (@{$bound}[1..$#$bound]) {   # <--- this will multiply the amount of ?'s no...?
-        $new_sql .= shift(@sql_part) .
-          ($dbi_type ? "CAST(? AS $dbi_type)" : '?');
-      }
+    my @sql_part = split /\?/, $sql, scalar @$bind + 1;
+    for (@$bind) {
+      my $cast_type = $self->_native_data_type($_->[0]{sqlt_datatype});
+      $new_sql .= shift(@sql_part) . ($cast_type ? "CAST(? AS $cast_type)" : '?');
     }
-    $new_sql .= join '', @sql_part;
-    $sql = $new_sql;
+    $sql = $new_sql . shift @sql_part;
   }
 
   return ($sql, $bind);
 }
 
+=head2 connect_call_set_auto_cast
+
+Executes:
+
+  $schema->storage->auto_cast(1);
+
+on connection.
+
+Used as:
+
+    on_connect_call => ['set_auto_cast']
+
+in L<connect_info|DBIx::Class::Storage::DBI/connect_info>.
+
+=cut
+
+sub connect_call_set_auto_cast {
+  my $self = shift;
+  $self->auto_cast(1);
+}
 
-=head1 AUTHORS
+=head1 AUTHOR
 
 See L<DBIx::Class/CONTRIBUTORS>