414c3914c3f62d3d62d0afedd254b4dbd402302d
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / DBI / Informix.pm
1 package DBIx::Class::Storage::DBI::Informix;
2 use strict;
3 use warnings;
4
5 use base qw/DBIx::Class::Storage::DBI/;
6 use mro 'c3';
7
8 use Scope::Guard ();
9 use Context::Preserve 'preserve_context';
10 use namespace::clean;
11
12 __PACKAGE__->mk_group_accessors('simple' => '__last_insert_id');
13
14 =head1 NAME
15
16 DBIx::Class::Storage::DBI::Informix - Base Storage Class for Informix Support
17
18 =head1 DESCRIPTION
19
20 This class implements storage-specific support for the Informix RDBMS
21
22 =head1 METHODS
23
24 =cut
25
26 sub _execute {
27   my $self = shift;
28   my ($op) = @_;
29   my ($rv, $sth, @rest) = $self->next::method(@_);
30   if ($op eq 'insert') {
31     $self->__last_insert_id($sth->{ix_sqlerrd}[1]);
32   }
33   return (wantarray ? ($rv, $sth, @rest) : $rv);
34 }
35
36 sub last_insert_id {
37   shift->__last_insert_id;
38 }
39
40 sub _sql_maker_opts {
41   my ( $self, $opts ) = @_;
42
43   if ( $opts ) {
44     $self->{_sql_maker_opts} = { %$opts };
45   }
46
47   return { limit_dialect => 'SkipFirst', %{$self->{_sql_maker_opts}||{}} };
48 }
49
50 sub _svp_begin {
51     my ($self, $name) = @_;
52
53     $self->_get_dbh->do("SAVEPOINT $name");
54 }
55
56 # can't release savepoints
57 sub _svp_release { 1 }
58
59 sub _svp_rollback {
60     my ($self, $name) = @_;
61
62     $self->_get_dbh->do("ROLLBACK TO SAVEPOINT $name")
63 }
64
65 sub with_deferred_fk_checks {
66   my ($self, $sub) = @_;
67
68   my $txn_scope_guard = $self->txn_scope_guard;
69
70   $self->_do_query('SET CONSTRAINTS ALL DEFERRED');
71
72   my $sg = Scope::Guard->new(sub {
73     $self->_do_query('SET CONSTRAINTS ALL IMMEDIATE');
74   });
75
76   return preserve_context { $sub->() } after => sub { $txn_scope_guard->commit };
77 }
78
79 =head2 connect_call_datetime_setup
80
81 Used as:
82
83   on_connect_call => 'datetime_setup'
84
85 In L<connect_info|DBIx::Class::Storage::DBI/connect_info> to set the C<DATE> and
86 C<DATETIME> formats.
87
88 Sets the following environment variables:
89
90     GL_DATE="%m/%d/%Y"
91     GL_DATETIME="%Y-%m-%d %H:%M:%S%F5"
92
93 The C<DBDATE> and C<DBCENTURY> environment variables are cleared.
94
95 B<NOTE:> setting the C<GL_DATE> environment variable seems to have no effect
96 after the process has started, so the default format is used. The C<GL_DATETIME>
97 setting does take effect however.
98
99 The C<DATETIME> data type supports up to 5 digits after the decimal point for
100 second precision, depending on how you have declared your column. The full
101 possible precision is used.
102
103 The column declaration for a C<DATETIME> with maximum precision is:
104
105   column_name DATETIME YEAR TO FRACTION(5)
106
107 The C<DATE> data type stores the date portion only, and it B<MUST> be declared
108 with:
109
110   data_type => 'date'
111
112 in your Result class.
113
114 You will need the L<DateTime::Format::Strptime> module for inflation to work.
115
116 =cut
117
118 sub connect_call_datetime_setup {
119   my $self = shift;
120
121   delete @ENV{qw/DBDATE DBCENTURY/};
122
123   $ENV{GL_DATE}     = "%m/%d/%Y";
124   $ENV{GL_DATETIME} = "%Y-%m-%d %H:%M:%S%F5";
125 }
126
127 sub datetime_parser_type {
128   'DBIx::Class::Storage::DBI::Informix::DateTime::Format'
129 }
130
131 package # hide from PAUSE
132   DBIx::Class::Storage::DBI::Informix::DateTime::Format;
133
134 my $timestamp_format = '%Y-%m-%d %H:%M:%S.%5N'; # %F %T
135 my $date_format      = '%m/%d/%Y';
136
137 my ($timestamp_parser, $date_parser);
138
139 sub parse_datetime {
140   shift;
141   require DateTime::Format::Strptime;
142   $timestamp_parser ||= DateTime::Format::Strptime->new(
143     pattern  => $timestamp_format,
144     on_error => 'croak',
145   );
146   return $timestamp_parser->parse_datetime(shift);
147 }
148
149 sub format_datetime {
150   shift;
151   require DateTime::Format::Strptime;
152   $timestamp_parser ||= DateTime::Format::Strptime->new(
153     pattern  => $timestamp_format,
154     on_error => 'croak',
155   );
156   return $timestamp_parser->format_datetime(shift);
157 }
158
159 sub parse_date {
160   shift;
161   require DateTime::Format::Strptime;
162   $date_parser ||= DateTime::Format::Strptime->new(
163     pattern  => $date_format,
164     on_error => 'croak',
165   );
166   return $date_parser->parse_datetime(shift);
167 }
168
169 sub format_date {
170   shift;
171   require DateTime::Format::Strptime;
172   $date_parser ||= DateTime::Format::Strptime->new(
173     pattern  => $date_format,
174     on_error => 'croak',
175   );
176   return $date_parser->format_datetime(shift);
177 }
178
179 1;
180
181 =head1 AUTHOR
182
183 See L<DBIx::Class/AUTHOR> and L<DBIx::Class/CONTRIBUTORS>.
184
185 =head1 LICENSE
186
187 You may distribute this code under the same terms as Perl itself.
188
189 =cut