1 package DBIx::Class::Storage::DBI::InterBase;
5 use base qw/DBIx::Class::Storage::DBI/;
7 use List::Util 'first';
13 DBIx::Class::Storage::DBI::InterBase - Driver for the Firebird RDBMS
17 This class implements autoincrements for Firebird using C<RETURNING> as well as
18 L<auto_nextval|DBIx::Class::ResultSource/auto_nextval> sets the limit dialect to
19 C<FIRST X SKIP X> and provides L<DBIx::Class::InflateColumn::DateTime> support.
21 You need to use either the
22 L<disable_sth_caching|DBIx::Class::Storage::DBI/disable_sth_caching> option or
23 L</connect_call_use_softcommit> (see L</CAVEATS>) for your code to function
24 correctly with this driver. Otherwise you will likely get bizarre error messages
25 such as C<no statement executing>. The alternative is to use the
26 L<ODBC|DBIx::Class::Storage::DBI::ODBC::Firebird> driver, which is more suitable
27 for long running processes such as under L<Catalyst>.
29 To turn on L<DBIx::Class::InflateColumn::DateTime> support, see
30 L</connect_call_datetime_setup>.
34 sub _supports_insert_returning { 1 }
37 my ($self, $nextval, $sequence) = @_;
39 if ($nextval ne 'nextval') {
40 $self->throw_exception("Can only fetch 'nextval' for a sequence");
43 $self->throw_exception('No sequence to fetch') unless $sequence;
45 my ($val) = $self->_get_dbh->selectrow_array(
46 'SELECT GEN_ID(' . $self->sql_maker->_quote($sequence) .
47 ', 1) FROM rdb$database');
52 sub _dbh_get_autoinc_seq {
53 my ($self, $dbh, $source, $col) = @_;
55 my $table_name = $source->from;
56 $table_name = $$table_name if ref $table_name;
57 $table_name = $self->sql_maker->quote_char ? $table_name : uc($table_name);
59 local $dbh->{LongReadLen} = 100000;
60 local $dbh->{LongTruncOk} = 1;
62 my $sth = $dbh->prepare(<<'EOF');
63 SELECT t.rdb$trigger_source
65 WHERE t.rdb$relation_name = ?
66 AND t.rdb$system_flag = 0 -- user defined
67 AND t.rdb$trigger_type = 1 -- BEFORE INSERT
69 $sth->execute($table_name);
71 while (my ($trigger) = $sth->fetchrow_array) {
73 /^"([^"]+)/ ? $1 : uc($1)
74 } $trigger =~ /new\.("?\w+"?)/ig;
76 my ($quoted, $generator) = $trigger =~
77 /(?:gen_id\s* \( \s* |next \s* value \s* for \s*)(")?(\w+)/ix;
80 $generator = uc $generator unless $quoted;
84 $self->sql_maker->quote_char ? ($_ eq $col) : (uc($_) eq uc($col))
92 # this sub stolen from DB2
95 my ( $self, $opts ) = @_;
98 $self->{_sql_maker_opts} = { %$opts };
101 return { limit_dialect => 'FirstSkip', %{$self->{_sql_maker_opts}||{}} };
105 my ($self, $name) = @_;
107 $self->_get_dbh->do("SAVEPOINT $name");
111 my ($self, $name) = @_;
113 $self->_get_dbh->do("RELEASE SAVEPOINT $name");
117 my ($self, $name) = @_;
119 $self->_get_dbh->do("ROLLBACK TO SAVEPOINT $name")
125 my $dbh = $self->_dbh or return 0;
127 local $dbh->{RaiseError} = 1;
128 local $dbh->{PrintError} = 0;
131 $dbh->do('select 1 from rdb$database');
138 # We want dialect 3 for new features and quoting to work, DBD::InterBase uses
139 # dialect 1 (interbase compat) by default.
142 $self->_set_sql_dialect(3);
145 sub _set_sql_dialect {
147 my $val = shift || 3;
149 my $dsn = $self->_dbi_connect_info->[0];
151 return if ref($dsn) eq 'CODE';
153 if ($dsn !~ /ib_dialect=/) {
154 $self->_dbi_connect_info->[0] = "$dsn;ib_dialect=$val";
155 my $connected = defined $self->_dbh;
157 $self->ensure_connected if $connected;
161 sub _get_server_version {
164 return $self->next::method(@_) if ref $self ne __PACKAGE__;
166 local $SIG{__WARN__} = sub {}; # silence warning due to bug in DBD::InterBase
168 return $self->next::method(@_);
171 =head2 connect_call_use_softcommit
175 on_connect_call => 'use_softcommit'
177 In L<connect_info|DBIx::Class::Storage::DBI/connect_info> to set the
178 L<DBD::InterBase> C<ib_softcommit> option.
180 You need either this option or C<< disable_sth_caching => 1 >> for
181 L<DBIx::Class> code to function correctly (otherwise you may get C<no statement
182 executing> errors.) Or use the L<ODBC|DBIx::Class::Storage::DBI::ODBC::Firebird>
185 The downside of using this option is that your process will B<NOT> see UPDATEs,
186 INSERTs and DELETEs from other processes for already open statements.
190 sub connect_call_use_softcommit {
193 $self->_dbh->{ib_softcommit} = 1;
196 =head2 connect_call_datetime_setup
200 on_connect_call => 'datetime_setup'
202 In L<connect_info|DBIx::Class::Storage::DBI/connect_info> to set the date and
203 timestamp formats using:
205 $dbh->{ib_time_all} = 'ISO';
207 See L<DBD::InterBase> for more details.
209 The C<TIMESTAMP> data type supports up to 4 digits after the decimal point for
210 second precision. The full precision is used.
212 The C<DATE> data type stores the date portion only, and it B<MUST> be declared
217 in your Result class.
219 Timestamp columns can be declared with either C<datetime> or C<timestamp>.
221 You will need the L<DateTime::Format::Strptime> module for inflation to work.
223 For L<DBIx::Class::Storage::DBI::ODBC::Firebird>, this is a noop and sub-second
224 precision is not currently available.
228 sub connect_call_datetime_setup {
231 $self->_get_dbh->{ib_time_all} = 'ISO';
234 sub datetime_parser_type {
235 'DBIx::Class::Storage::DBI::InterBase::DateTime::Format'
238 package # hide from PAUSE
239 DBIx::Class::Storage::DBI::InterBase::DateTime::Format;
241 my $timestamp_format = '%Y-%m-%d %H:%M:%S.%4N'; # %F %T
242 my $date_format = '%Y-%m-%d';
244 my ($timestamp_parser, $date_parser);
248 require DateTime::Format::Strptime;
249 $timestamp_parser ||= DateTime::Format::Strptime->new(
250 pattern => $timestamp_format,
253 return $timestamp_parser->parse_datetime(shift);
256 sub format_datetime {
258 require DateTime::Format::Strptime;
259 $timestamp_parser ||= DateTime::Format::Strptime->new(
260 pattern => $timestamp_format,
263 return $timestamp_parser->format_datetime(shift);
268 require DateTime::Format::Strptime;
269 $date_parser ||= DateTime::Format::Strptime->new(
270 pattern => $date_format,
273 return $date_parser->parse_datetime(shift);
278 require DateTime::Format::Strptime;
279 $date_parser ||= DateTime::Format::Strptime->new(
280 pattern => $date_format,
283 return $date_parser->format_datetime(shift);
294 with L</connect_call_use_softcommit>, you will not be able to see changes made
295 to data in other processes. If this is an issue, use
296 L<disable_sth_caching|DBIx::Class::Storage::DBI/disable_sth_caching> as a
297 workaround for the C<no statement executing> errors, this of course adversely
300 Alternately, use the L<ODBC|DBIx::Class::Storage::DBI::ODBC::Firebird> driver.
304 C<last_insert_id> support by default only works for Firebird versions 2 or
305 greater, L<auto_nextval|DBIx::Class::ResultSource/auto_nextval> however should
306 work with earlier versions.
310 Sub-second precision for TIMESTAMPs is not currently available when using the
311 L<ODBC|DBIx::Class::Storage::DBI::ODBC::Firebird> driver.
317 See L<DBIx::Class/AUTHOR> and L<DBIx::Class/CONTRIBUTORS>.
321 You may distribute this code under the same terms as Perl itself.