Commit | Line | Data |
65c2b042 |
1 | package DBIx::Class::Storage::DBI::ODBC::ACCESS; |
726c8f65 |
2 | |
65c2b042 |
3 | use strict; |
4 | use warnings; |
726c8f65 |
5 | use base qw/ |
6 | DBIx::Class::Storage::DBI::ODBC |
7 | DBIx::Class::Storage::DBI::ACCESS |
8 | /; |
2ad62d97 |
9 | use mro 'c3'; |
10 | |
726c8f65 |
11 | __PACKAGE__->mk_group_accessors(inherited => |
12 | 'disable_sth_caching_for_image_insert_or_update' |
13 | ); |
65c2b042 |
14 | |
726c8f65 |
15 | __PACKAGE__->disable_sth_caching_for_image_insert_or_update(1); |
65c2b042 |
16 | |
726c8f65 |
17 | =head1 NAME |
65c2b042 |
18 | |
726c8f65 |
19 | DBIx::Class::Storage::DBI::ODBC::ACCESS - Support specific to MS Access over ODBC |
65c2b042 |
20 | |
726c8f65 |
21 | =head1 DESCRIPTION |
65c2b042 |
22 | |
726c8f65 |
23 | This class implements support specific to Microsoft Access over ODBC. |
65c2b042 |
24 | |
726c8f65 |
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. |
d4daee7b |
28 | |
726c8f65 |
29 | It is loaded automatically by by L<DBIx::Class::Storage::DBI::ODBC> when it |
30 | detects a MS Access back-end. |
d4daee7b |
31 | |
726c8f65 |
32 | This driver implements workarounds for C<IMAGE> and C<MEMO> columns, and |
33 | L<DBIx::Class::InflateColumn::DateTime> support for C<DATETIME> columns. |
d4daee7b |
34 | |
726c8f65 |
35 | =head1 EXAMPLE DSN |
65c2b042 |
36 | |
726c8f65 |
37 | dbi:ODBC:driver={Microsoft Access Driver (*.mdb, *.accdb)};dbq=C:\Users\rkitover\Documents\access_sample.accdb |
65c2b042 |
38 | |
726c8f65 |
39 | =head1 TEXT/IMAGE/MEMO COLUMNS |
65c2b042 |
40 | |
726c8f65 |
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. |
65c2b042 |
44 | |
726c8f65 |
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. |
65c2b042 |
48 | |
726c8f65 |
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. |
65c2b042 |
54 | |
726c8f65 |
55 | =cut |
65c2b042 |
56 | |
726c8f65 |
57 | # set LongReadLen = LongReadLen * 2 + 1 (see docs on MEMO) |
58 | sub _run_connection_actions { |
59 | my $self = shift; |
65c2b042 |
60 | |
726c8f65 |
61 | my $long_read_len = $self->_dbh->{LongReadLen}; |
65c2b042 |
62 | |
726c8f65 |
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 | } |
65c2b042 |
67 | |
1d8a370f |
68 | # batch operations do not work |
69 | $self->_get_dbh->{odbc_disable_array_operations} = 1; |
70 | |
726c8f65 |
71 | return $self->next::method(@_); |
72 | } |
65c2b042 |
73 | |
726c8f65 |
74 | sub insert { |
75 | my $self = shift; |
76 | my ($source, $to_insert) = @_; |
65c2b042 |
77 | |
726c8f65 |
78 | my $columns_info = $source->columns_info; |
65c2b042 |
79 | |
726c8f65 |
80 | my $is_image_insert = 0; |
65c2b042 |
81 | |
726c8f65 |
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 | } |
65c2b042 |
88 | |
726c8f65 |
89 | local $self->{disable_sth_caching} = 1 if $is_image_insert |
90 | && $self->disable_sth_caching_for_image_insert_or_update; |
65c2b042 |
91 | |
726c8f65 |
92 | return $self->next::method(@_); |
93 | } |
65c2b042 |
94 | |
726c8f65 |
95 | sub update { |
96 | my $self = shift; |
97 | my ($source, $fields) = @_; |
65c2b042 |
98 | |
726c8f65 |
99 | my $columns_info = $source->columns_info; |
65c2b042 |
100 | |
726c8f65 |
101 | my $is_image_insert = 0; |
65c2b042 |
102 | |
726c8f65 |
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 | } |
65c2b042 |
109 | |
726c8f65 |
110 | local $self->{disable_sth_caching} = 1 if $is_image_insert |
111 | && $self->disable_sth_caching_for_image_insert_or_update; |
65c2b042 |
112 | |
726c8f65 |
113 | return $self->next::method(@_); |
114 | } |
65c2b042 |
115 | |
726c8f65 |
116 | sub datetime_parser_type { |
117 | 'DBIx::Class::Storage::DBI::ODBC::ACCESS::DateTime::Format' |
118 | } |
65c2b042 |
119 | |
726c8f65 |
120 | package # hide from PAUSE |
121 | DBIx::Class::Storage::DBI::ODBC::ACCESS::DateTime::Format; |
65c2b042 |
122 | |
726c8f65 |
123 | my $datetime_format = '%Y-%m-%d %H:%M:%S'; # %F %T, no fractional part |
124 | my $datetime_parser; |
65c2b042 |
125 | |
726c8f65 |
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 | } |
65c2b042 |
135 | |
726c8f65 |
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 | } |
65c2b042 |
145 | |
726c8f65 |
146 | 1; |
65c2b042 |
147 | |
726c8f65 |
148 | =head1 AUTHOR |
65c2b042 |
149 | |
726c8f65 |
150 | See L<DBIx::Class/AUTHOR> and L<DBIx::Class/CONTRIBUTORS>. |
65c2b042 |
151 | |
726c8f65 |
152 | =head1 LICENSE |
65c2b042 |
153 | |
154 | You may distribute this code under the same terms as Perl itself. |
155 | |
65c2b042 |
156 | =cut |
726c8f65 |
157 | # vim:sts=2 sw=2: |