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