3a630cc59b5f5f0f59a18519e4c9eb7fe1a6e3ca
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / DBI / ODBC / ACCESS.pm
1 package DBIx::Class::Storage::DBI::ODBC::ACCESS;
2
3 use strict;
4 use warnings;
5 use base qw/
6   DBIx::Class::Storage::DBI::ODBC
7   DBIx::Class::Storage::DBI::ACCESS
8 /;
9 use mro 'c3';
10
11 __PACKAGE__->mk_group_accessors(inherited =>
12   'disable_sth_caching_for_image_insert_or_update'
13 );
14
15 __PACKAGE__->disable_sth_caching_for_image_insert_or_update(1);
16
17 =head1 NAME
18
19 DBIx::Class::Storage::DBI::ODBC::ACCESS - Support specific to MS Access over ODBC
20
21 =head1 DESCRIPTION
22
23 This class implements support specific to Microsoft Access over ODBC.
24
25 It is a subclass of L<DBIx::Class::Storage::DBI::ODBC> and
26 L<DBIx::Class::Storage::DBI::ACCESS>, see those classes for more
27 information.
28
29 It is loaded automatically by by L<DBIx::Class::Storage::DBI::ODBC> when it
30 detects a MS Access back-end.
31
32 This driver implements workarounds for C<IMAGE> and C<MEMO> columns, and
33 L<DBIx::Class::InflateColumn::DateTime> support for C<DATETIME> columns.
34
35 =head1 EXAMPLE DSN
36
37   dbi:ODBC:driver={Microsoft Access Driver (*.mdb, *.accdb)};dbq=C:\Users\rkitover\Documents\access_sample.accdb
38
39 =head1 TEXT/IMAGE/MEMO COLUMNS
40
41 Avoid using C<TEXT> columns as they will be truncated to 255 bytes. Some other
42 drivers (like L<ADO|DBIx::Class::Storage::DBI::ADO::MS_Jet>) will automatically
43 convert C<TEXT> columns to C<MEMO>, but the ODBC driver does not.
44
45 C<IMAGE> columns work correctly, but the statements for inserting or updating an
46 C<IMAGE> column will not be L<cached|DBI/prepare_cached>, due to a bug in the
47 Access ODBC driver.
48
49 C<MEMO> columns work correctly as well, but you must take care to set
50 L<LongReadLen|DBI/LongReadLen> to C<$max_memo_size * 2 + 1>. This is done for
51 you automatically if you pass L<LongReadLen|DBI/LongReadLen> in your
52 L<connect_info|DBIx::Class::Storage::DBI/connect_info>; but if you set this
53 attribute directly on the C<$dbh>, keep this limitation in mind.
54
55 =cut
56
57 # set LongReadLen = LongReadLen * 2 + 1 (see docs on MEMO)
58 sub _run_connection_actions {
59   my $self = shift;
60
61   my $long_read_len = $self->_dbh->{LongReadLen};
62
63   # 80 is another default (just like 0) on some drivers
64   if ($long_read_len != 0 && $long_read_len != 80) {
65     $self->_dbh->{LongReadLen} = $long_read_len * 2 + 1;
66   }
67
68   # batch operations do not work
69   $self->_disable_odbc_array_ops;
70
71   return $self->next::method(@_);
72 }
73
74 sub insert {
75   my $self = shift;
76   my ($source, $to_insert) = @_;
77
78   my $columns_info = $source->columns_info;
79
80   my $is_image_insert = 0;
81
82   for my $col (keys %$to_insert) {
83     if ($self->_is_binary_lob_type($columns_info->{$col}{data_type})) {
84       $is_image_insert = 1;
85       last;
86     }
87   }
88
89   local $self->{disable_sth_caching} = 1 if $is_image_insert
90     && $self->disable_sth_caching_for_image_insert_or_update;
91
92   return $self->next::method(@_);
93 }
94
95 sub update {
96   my $self = shift;
97   my ($source, $fields) = @_;
98
99   my $columns_info = $source->columns_info;
100
101   my $is_image_insert = 0;
102
103   for my $col (keys %$fields) {
104     if ($self->_is_binary_lob_type($columns_info->{$col}{data_type})) {
105       $is_image_insert = 1;
106       last;
107     }
108   }
109
110   local $self->{disable_sth_caching} = 1 if $is_image_insert
111     && $self->disable_sth_caching_for_image_insert_or_update;
112
113   return $self->next::method(@_);
114 }
115
116 sub datetime_parser_type {
117   'DBIx::Class::Storage::DBI::ODBC::ACCESS::DateTime::Format'
118 }
119
120 package # hide from PAUSE
121   DBIx::Class::Storage::DBI::ODBC::ACCESS::DateTime::Format;
122
123 my $datetime_format = '%Y-%m-%d %H:%M:%S'; # %F %T, no fractional part
124 my $datetime_parser;
125
126 sub parse_datetime {
127   shift;
128   require DateTime::Format::Strptime;
129   $datetime_parser ||= DateTime::Format::Strptime->new(
130     pattern  => $datetime_format,
131     on_error => 'croak',
132   );
133   return $datetime_parser->parse_datetime(shift);
134 }
135
136 sub format_datetime {
137   shift;
138   require DateTime::Format::Strptime;
139   $datetime_parser ||= DateTime::Format::Strptime->new(
140     pattern  => $datetime_format,
141     on_error => 'croak',
142   );
143   return $datetime_parser->format_datetime(shift);
144 }
145
146 1;
147
148 =head1 AUTHOR
149
150 See L<DBIx::Class/AUTHOR> and L<DBIx::Class/CONTRIBUTORS>.
151
152 =head1 LICENSE
153
154 You may distribute this code under the same terms as Perl itself.
155
156 =cut
157 # vim:sts=2 sw=2: