use quoting in firebird tests
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / DBI / InterBase.pm
CommitLineData
88a8d0fa 1package DBIx::Class::Storage::DBI::InterBase;
2
145b2a3d 3# partly stolen from DBIx::Class::Storage::DBI::MSSQL
88a8d0fa 4
5use strict;
6use warnings;
637d2fae 7use base qw/DBIx::Class::Storage::DBI/;
88a8d0fa 8use mro 'c3';
88a8d0fa 9use List::Util();
10
11__PACKAGE__->mk_group_accessors(simple => qw/
2680ffe5 12 _auto_incs
88a8d0fa 13/);
14
90489c23 15=head1 NAME
16
17DBIx::Class::Storage::DBI::InterBase - Driver for the Firebird RDBMS
18
19=head1 DESCRIPTION
20
21This class implements autoincrements for Firebird using C<RETURNING>, sets the
22limit dialect to C<FIRST X SKIP X> and provides preliminary
23L<DBIx::Class::InflateColumn::DateTime> support.
24
25For ODBC support, see L<DBIx::Class::Storage::DBI::ODBC::Firebird>.
26
32323fc2 27To turn on L<DBIx::Class::InflateColumn::DateTime> support, add:
28
29 on_connect_call => 'datetime_setup'
30
31to your L<DBIx::Class::Storage::DBI/connect_info>.
32
90489c23 33=cut
34
88a8d0fa 35sub _prep_for_execute {
36 my $self = shift;
37 my ($op, $extra_bind, $ident, $args) = @_;
38
88a8d0fa 39 if ($op eq 'insert') {
6e8d182b 40 my @pk = $ident->primary_columns;
41 my %pk;
42 @pk{@pk} = ();
43
1ae0a36c 44 my @auto_inc_cols = grep {
45 my $inserting = $args->[0]{$_};
145b2a3d 46
6e8d182b 47 ($ident->column_info($_)->{is_auto_increment}
48 || exists $pk{$_})
49 && (
1ae0a36c 50 (not defined $inserting)
51 ||
2680ffe5 52 (ref $inserting eq 'SCALAR' && $$inserting =~ /^null\z/i)
1ae0a36c 53 )
54 } $ident->columns;
88a8d0fa 55
145b2a3d 56 if (@auto_inc_cols) {
1696e04f 57 $args->[1]{returning} = \@auto_inc_cols;
145b2a3d 58
2680ffe5 59 $self->_auto_incs([]);
60 $self->_auto_incs->[0] = \@auto_inc_cols;
145b2a3d 61 }
88a8d0fa 62 }
63
1696e04f 64 return $self->next::method(@_);
1ae0a36c 65}
66
88a8d0fa 67sub _execute {
68 my $self = shift;
69 my ($op) = @_;
70
71 my ($rv, $sth, @bind) = $self->dbh_do($self->can('_dbh_execute'), @_);
72
2680ffe5 73 if ($op eq 'insert' && $self->_auto_incs) {
88a8d0fa 74 local $@;
145b2a3d 75 my (@auto_incs) = eval {
76 local $SIG{__WARN__} = sub {};
77 $sth->fetchrow_array
78 };
2680ffe5 79 $self->_auto_incs->[1] = \@auto_incs;
88a8d0fa 80 $sth->finish;
81 }
82
83 return wantarray ? ($rv, $sth, @bind) : $rv;
84}
85
145b2a3d 86sub last_insert_id {
87 my ($self, $source, @cols) = @_;
88 my @result;
88a8d0fa 89
145b2a3d 90 my %auto_incs;
2680ffe5 91 @auto_incs{ @{ $self->_auto_incs->[0] } } =
92 @{ $self->_auto_incs->[1] };
145b2a3d 93
94 push @result, $auto_incs{$_} for @cols;
95
96 return @result;
97}
98
99# this sub stolen from DB2
88a8d0fa 100
145b2a3d 101sub _sql_maker_opts {
102 my ( $self, $opts ) = @_;
103
104 if ( $opts ) {
105 $self->{_sql_maker_opts} = { %$opts };
106 }
107
108 return { limit_dialect => 'FirstSkip', %{$self->{_sql_maker_opts}||{}} };
109}
110
32323fc2 111sub _svp_begin {
112 my ($self, $name) = @_;
113
114 $self->_get_dbh->do("SAVEPOINT $name");
115}
116
117sub _svp_release {
118 my ($self, $name) = @_;
119
120 $self->_get_dbh->do("RELEASE SAVEPOINT $name");
121}
122
123sub _svp_rollback {
124 my ($self, $name) = @_;
125
126 $self->_get_dbh->do("ROLLBACK TO SAVEPOINT $name")
127}
128
129sub _ping {
130 my $self = shift;
131
132 my $dbh = $self->_dbh or return 0;
133
134 local $dbh->{RaiseError} = 1;
135
136 eval {
137 $dbh->do('select 1 from rdb$database');
138 };
139
140 return $@ ? 0 : 1;
141}
142
143=head2 connect_call_datetime_setup
9cd0b325 144
32323fc2 145Used as:
9cd0b325 146
32323fc2 147 on_connect_call => 'datetime_setup'
148
149In L<DBIx::Class::Storage::DBI/connect_info> to set the date and timestamp
150formats using:
151
152 $dbh->{ib_time_all} = 'ISO';
153
154See L<DBD::InterBase> for more details.
155
156The C<TIMESTAMP> data type supports up to 4 digits after the decimal point for
157second precision. The full precision is used.
158
159You will need the L<DateTime::Format::Strptime> module for inflation to work.
160
161For L<DBIx::Class::Storage::DBI::ODBC::Firebird>, this is a noop and sub-second
162precision is not currently available.
163
164=cut
165
166sub connect_call_datetime_setup {
167 my $self = shift;
168
169 $self->_get_dbh->{ib_time_all} = 'ISO';
9cd0b325 170}
171
32323fc2 172
173# from MSSQL
174
175sub build_datetime_parser {
176 my $self = shift;
177 my $type = "DateTime::Format::Strptime";
178 eval "use ${type}";
179 $self->throw_exception("Couldn't load ${type}: $@") if $@;
180 return $type->new(
181 pattern => '%Y-%m-%d %H:%M:%S.%4N', # %F %T
182 on_error => 'croak',
183 );
9cd0b325 184}
185
145b2a3d 1861;
90489c23 187
188=head1 CAVEATS
189
190=over 4
191
192=item *
193
194C<last_insert_id> support only works for Firebird versions 2 or greater. To
195work with earlier versions, we'll need to figure out how to retrieve the bodies
196of C<BEFORE INSERT> triggers and parse them for the C<GENERATOR> name.
197
90489c23 198=back
199
200=head1 AUTHOR
201
202See L<DBIx::Class/AUTHOR> and L<DBIx::Class/CONTRIBUTORS>.
203
204=head1 LICENSE
205
206You may distribute this code under the same terms as Perl itself.
207
208=cut