Comprehensive MSAccess support over both DBD::ODBC and DBD::ADO
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / DBI / ADO / MS_Jet.pm
CommitLineData
726c8f65 1package DBIx::Class::Storage::DBI::ADO::MS_Jet;
2
3use strict;
4use warnings;
5use base qw/
6 DBIx::Class::Storage::DBI::ADO
7 DBIx::Class::Storage::DBI::ACCESS
8/;
9use mro 'c3';
10use DBIx::Class::Storage::DBI::ADO::MS_Jet::Cursor ();
11
12__PACKAGE__->cursor_class('DBIx::Class::Storage::DBI::ADO::MS_Jet::Cursor');
13
14=head1 NAME
15
16DBIx::Class::Storage::DBI::ADO::MS_Jet - Support for MS Access over ADO
17
18=head1 DESCRIPTION
19
20This driver is a subclass of L<DBIx::Class::Storage::DBI::ADO> and
21L<DBIx::Class::Storage::DBI::ACCESS> for connecting to MS Access via
22L<DBD::ADO>.
23
24See the documentation for L<DBIx::Class::Storage::DBI::ACCESS> for
25information on the MS Access driver for L<DBIx::Class>.
26
27This driver implements workarounds for C<TEXT/IMAGE/MEMO> columns, sets the
28L<cursor_class|DBIx::Class::Storage::DBI/cursor_class> to
29L<DBIx::Class::Storage::DBI::ADO::MS_Jet::Cursor> to normalize returned
30C<GUID> values and provides L<DBIx::Class::InflateColumn::DateTime> support
31for C<DATETIME> columns.
32
33=head1 EXAMPLE DSNs
34
35 # older Access versions:
36 dbi:ADO:Microsoft.Jet.OLEDB.4.0;Data Source=C:\Users\rkitover\Documents\access_sample.accdb
37
38 # newer Access versions:
39 dbi:ADO:Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\rkitover\Documents\access_sample.accdb;Persist Security Info=False'
40
41=head1 TEXT/IMAGE/MEMO COLUMNS
42
43The ADO driver does not suffer from the
44L<problems|DBIx::Class::Storage::DBI::ODBC::ACCESS/"TEXT/IMAGE/MEMO COLUMNS">
45the L<ODBC|DBIx::Class::Storage::DBI::ODBC::ACCESS> driver has with these types
46of columns. You can use them safely.
47
48When you execute a C<CREATE TABLE> statement over this driver with a C<TEXT>
49column, it will be converted to C<MEMO>, while in the
50L<ODBC|DBIx::Class::Storage::DBI::ODBC::ACCESS> driver it is converted to
51C<VARCHAR(255)>.
52
53However, the caveat about L<LongReadLen|DBI/LongReadLen> having to be twice the
54max size of your largest C<MEMO/TEXT> column C<+1> still applies. L<DBD::ADO>
55sets L<LongReadLen|DBI/LongReadLen> to a large value by default, so it should be
56safe to just leave it unset. If you do pass a L<LongReadLen|DBI/LongReadLen> in
57your L<connect_info|DBIx::Class::Storage::DBI/connect_info>, it will be
58multiplied by two and C<1> added, just as for the
59L<ODBC|DBIx::Class::Storage::DBI::ODBC::ACCESS> driver.
60
61=cut
62
63# set LongReadLen = LongReadLen * 2 + 1 (see docs on MEMO)
64sub _run_connection_actions {
65 my $self = shift;
66
67 my $long_read_len = $self->_dbh->{LongReadLen};
68
69# This is the DBD::ADO default.
70 if ($long_read_len != 2147483647) {
71 $self->_dbh->{LongReadLen} = $long_read_len * 2 + 1;
72 }
73
74 return $self->next::method(@_);
75}
76
77# AutoCommit does not get reset properly after transactions for some reason
78# (probably because of my nested transaction hacks in ACCESS.pm) fix it up
79# here.
80
81sub _dbh_commit {
82 my $self = shift;
83 $self->next::method(@_);
84 $self->_dbh->{AutoCommit} = $self->_dbh_autocommit
85 if $self->{transaction_depth} == 1;
86}
87
88sub _dbh_rollback {
89 my $self = shift;
90 $self->next::method(@_);
91 $self->_dbh->{AutoCommit} = $self->_dbh_autocommit
92 if $self->{transaction_depth} == 1;
93}
94
95# Fix up GUIDs for ->find, for cursors see the cursor_class above.
96
97sub select_single {
98 my $self = shift;
99 my ($ident, $select) = @_;
100
101 my @row = $self->next::method(@_);
102
103 return @row unless
104 $self->cursor_class->isa('DBIx::Class::Storage::DBI::ADO::MS_Jet::Cursor');
105
106 my $col_info = $self->_resolve_column_info($ident);
107
108 for my $select_idx (0..$#$select) {
109 my $selected = $select->[$select_idx];
110
111 next if ref $selected;
112
113 my $data_type = $col_info->{$selected}{data_type};
114
115 if ($self->_is_guid_type($data_type)) {
116 my $returned = $row[$select_idx];
117
118 $row[$select_idx] = substr($returned, 1, 36)
119 if substr($returned, 0, 1) eq '{';
120 }
121 }
122
123 return @row;
124}
125
126sub datetime_parser_type {
127 'DBIx::Class::Storage::DBI::ADO::MS_Jet::DateTime::Format'
128}
129
130package # hide from PAUSE
131 DBIx::Class::Storage::DBI::ADO::MS_Jet::DateTime::Format;
132
133my $datetime_format = '%m/%d/%Y %I:%M:%S %p';
134my $datetime_parser;
135
136sub parse_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->parse_datetime(shift);
144}
145
146sub format_datetime {
147 shift;
148 require DateTime::Format::Strptime;
149 $datetime_parser ||= DateTime::Format::Strptime->new(
150 pattern => $datetime_format,
151 on_error => 'croak',
152 );
153 return $datetime_parser->format_datetime(shift);
154}
155
1561;
157
158=head1 AUTHOR
159
160See L<DBIx::Class/AUTHOR> and L<DBIx::Class/CONTRIBUTORS>.
161
162=head1 LICENSE
163
164You may distribute this code under the same terms as Perl itself.
165
166=cut
167# vim:sts=2 sw=2: