X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FStorage%2FDBI%2FODBC%2FACCESS.pm;h=3a630cc59b5f5f0f59a18519e4c9eb7fe1a6e3ca;hb=94f9fbefc7e247e2319b2472787e974fcf8cbb97;hp=087f0c2f8990dd67687bd9f422bc59a567ffd669;hpb=2b8cc2f27d0dc881059e55dd6462bb28b7b8e414;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/Storage/DBI/ODBC/ACCESS.pm b/lib/DBIx/Class/Storage/DBI/ODBC/ACCESS.pm index 087f0c2..3a630cc 100644 --- a/lib/DBIx/Class/Storage/DBI/ODBC/ACCESS.pm +++ b/lib/DBIx/Class/Storage/DBI/ODBC/ACCESS.pm @@ -1,132 +1,157 @@ package DBIx::Class::Storage::DBI::ODBC::ACCESS; + use strict; use warnings; - -use base qw/DBIx::Class::Storage::DBI/; +use base qw/ + DBIx::Class::Storage::DBI::ODBC + DBIx::Class::Storage::DBI::ACCESS +/; use mro 'c3'; -use DBI; - -my $ERR_MSG_START = __PACKAGE__ . ' failed: '; +__PACKAGE__->mk_group_accessors(inherited => + 'disable_sth_caching_for_image_insert_or_update' +); -__PACKAGE__->sql_limit_dialect ('Top'); -__PACKAGE__->sql_quote_char ([qw/[ ]/]); - -sub insert { - my $self = shift; - my ( $source, $to_insert ) = @_; +__PACKAGE__->disable_sth_caching_for_image_insert_or_update(1); - my $bind_attributes = $self->source_bind_attributes( $source ); - my ( undef, $sth ) = $self->_execute( 'insert' => [], $source, $bind_attributes, $to_insert ); - - #store the identity here since @@IDENTITY is connection global and this prevents - #possibility that another insert to a different table overwrites it for this resultsource - my $identity = 'SELECT @@IDENTITY'; - my $max_sth = $self->{ _dbh }->prepare( $identity ) - or $self->throw_exception( $ERR_MSG_START . $self->{ _dbh }->errstr() ); - $max_sth->execute() or $self->throw_exception( $ERR_MSG_START . $max_sth->errstr ); +=head1 NAME - my $row = $max_sth->fetchrow_arrayref() - or $self->throw_exception( $ERR_MSG_START . "$identity did not return any result." ); +DBIx::Class::Storage::DBI::ODBC::ACCESS - Support specific to MS Access over ODBC - $self->{ last_pk }->{ $source->name() } = $row; +=head1 DESCRIPTION - return $to_insert; -} +This class implements support specific to Microsoft Access over ODBC. -sub last_insert_id { - my $self = shift; - my ( $result_source ) = @_; +It is a subclass of L and +L, see those classes for more +information. - return @{ $self->{ last_pk }->{ $result_source->name() } }; -} +It is loaded automatically by by L when it +detects a MS Access back-end. -sub bind_attribute_by_data_type { - my $self = shift; +This driver implements workarounds for C and C columns, and +L support for C columns. - my ( $data_type ) = @_; +=head1 EXAMPLE DSN - return { TYPE => $data_type } if $data_type == DBI::SQL_LONGVARCHAR; + dbi:ODBC:driver={Microsoft Access Driver (*.mdb, *.accdb)};dbq=C:\Users\rkitover\Documents\access_sample.accdb - return; -} +=head1 TEXT/IMAGE/MEMO COLUMNS -sub sqlt_type { 'ACCESS' } +Avoid using C columns as they will be truncated to 255 bytes. Some other +drivers (like L) will automatically +convert C columns to C, but the ODBC driver does not. -1; +C columns work correctly, but the statements for inserting or updating an +C column will not be L, due to a bug in the +Access ODBC driver. -=head1 NAME +C columns work correctly as well, but you must take care to set +L to C<$max_memo_size * 2 + 1>. This is done for +you automatically if you pass L in your +L; but if you set this +attribute directly on the C<$dbh>, keep this limitation in mind. -DBIx::Class::Storage::DBI::ODBC::ACCESS - Support specific to MS Access over ODBC - -=head1 WARNING +=cut -I am not a DBI, DBIx::Class or MS Access guru. Use this module with that in -mind. +# set LongReadLen = LongReadLen * 2 + 1 (see docs on MEMO) +sub _run_connection_actions { + my $self = shift; -This module is currently considered alpha software and can change without notice. + my $long_read_len = $self->_dbh->{LongReadLen}; -=head1 DESCRIPTION + # 80 is another default (just like 0) on some drivers + if ($long_read_len != 0 && $long_read_len != 80) { + $self->_dbh->{LongReadLen} = $long_read_len * 2 + 1; + } -This class implements support specific to Microsoft Access over ODBC. + # batch operations do not work + $self->_disable_odbc_array_ops; -It is loaded automatically by by DBIx::Class::Storage::DBI::ODBC when it -detects a MS Access back-end. + return $self->next::method(@_); +} -=head1 SUPPORTED VERSIONS +sub insert { + my $self = shift; + my ($source, $to_insert) = @_; -This module have currently only been tested on MS Access 2003 using the Jet 4.0 engine. + my $columns_info = $source->columns_info; -As far as my knowledge it should work on MS Access 2000 or later, but that have not been tested. -Information about support for different version of MS Access is welcome. + my $is_image_insert = 0; -=head1 IMPLEMENTATION NOTES + for my $col (keys %$to_insert) { + if ($self->_is_binary_lob_type($columns_info->{$col}{data_type})) { + $is_image_insert = 1; + last; + } + } -MS Access supports the @@IDENTITY function for retrieving the id of the latest inserted row. -@@IDENTITY is global to the connection, so to support the possibility of getting the last inserted -id for different tables, the insert() function stores the inserted id on a per table basis. -last_insert_id() then just returns the stored value. + local $self->{disable_sth_caching} = 1 if $is_image_insert + && $self->disable_sth_caching_for_image_insert_or_update; -=head1 KNOWN ACCESS PROBLEMS + return $self->next::method(@_); +} -=over +sub update { + my $self = shift; + my ($source, $fields) = @_; -=item Invalid precision value + my $columns_info = $source->columns_info; -This error message is received when trying to store more than 255 characters in a MEMO field. -The problem is (to my knowledge) an error in the MS Access ODBC driver. The problem is fixed -by setting the C of the column to C in C. -C is a constant in the C module. + my $is_image_insert = 0; -=back + for my $col (keys %$fields) { + if ($self->_is_binary_lob_type($columns_info->{$col}{data_type})) { + $is_image_insert = 1; + last; + } + } -=head1 IMPLEMENTED FUNCTIONS + local $self->{disable_sth_caching} = 1 if $is_image_insert + && $self->disable_sth_caching_for_image_insert_or_update; -=head2 bind_attribute_by_data_type + return $self->next::method(@_); +} -This function currently supports the SQL_LONGVARCHAR column type. +sub datetime_parser_type { + 'DBIx::Class::Storage::DBI::ODBC::ACCESS::DateTime::Format' +} -=head2 insert +package # hide from PAUSE + DBIx::Class::Storage::DBI::ODBC::ACCESS::DateTime::Format; -=head2 last_insert_id +my $datetime_format = '%Y-%m-%d %H:%M:%S'; # %F %T, no fractional part +my $datetime_parser; -=head2 sqlt_type +sub parse_datetime { + shift; + require DateTime::Format::Strptime; + $datetime_parser ||= DateTime::Format::Strptime->new( + pattern => $datetime_format, + on_error => 'croak', + ); + return $datetime_parser->parse_datetime(shift); +} -=head1 BUGS +sub format_datetime { + shift; + require DateTime::Format::Strptime; + $datetime_parser ||= DateTime::Format::Strptime->new( + pattern => $datetime_format, + on_error => 'croak', + ); + return $datetime_parser->format_datetime(shift); +} -Most likely. Bug reports are welcome. +1; -=head1 AUTHORS +=head1 AUTHOR -Øystein Torget C<< >> +See L and L. -=head1 COPYRIGHT +=head1 LICENSE You may distribute this code under the same terms as Perl itself. -Det Norske Veritas AS (DNV) - -http://www.dnv.com - =cut - +# vim:sts=2 sw=2: