workaround for Moose bug affecting Replicated storage
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / DBI / SQLAnywhere.pm
1 package DBIx::Class::Storage::DBI::SQLAnywhere;
2
3 use strict;
4 use warnings;
5 use base qw/DBIx::Class::Storage::DBI/;
6 use mro 'c3';
7 use List::Util ();
8
9 __PACKAGE__->mk_group_accessors(simple => qw/
10   _identity
11 /);
12
13 =head1 NAME
14
15 DBIx::Class::Storage::DBI::SQLAnywhere - Driver for Sybase SQL Anywhere
16
17 =head1 DESCRIPTION
18
19 This class implements autoincrements for Sybase SQL Anywhere, selects the
20 RowNumberOver limit implementation and provides
21 L<DBIx::Class::InflateColumn::DateTime> support.
22
23 You need the C<DBD::SQLAnywhere> driver that comes with the SQL Anywhere
24 distribution, B<NOT> the one on CPAN. It is usually under a path such as:
25
26   /opt/sqlanywhere11/sdk/perl
27
28 Recommended L<DBIx::Class::Storage::DBI/connect_info> settings:
29
30   on_connect_call => 'datetime_setup'
31
32 =head1 METHODS
33
34 =cut
35
36 sub last_insert_id { shift->_identity }
37
38 sub insert {
39   my $self = shift;
40   my ($source, $to_insert) = @_;
41
42   my $identity_col = List::Util::first {
43       $source->column_info($_)->{is_auto_increment} 
44   } $source->columns;
45
46 # user might have an identity PK without is_auto_increment
47   if (not $identity_col) {
48     foreach my $pk_col ($source->primary_columns) {
49       if (not exists $to_insert->{$pk_col}) {
50         $identity_col = $pk_col;
51         last;
52       }
53     }
54   }
55
56   if ($identity_col && (not exists $to_insert->{$identity_col})) {
57     my $dbh = $self->_get_dbh;
58     my $table_name = $source->from;
59     $table_name    = $$table_name if ref $table_name;
60
61     my ($identity) = $dbh->selectrow_array("SELECT GET_IDENTITY('$table_name')");
62
63     $to_insert->{$identity_col} = $identity;
64
65     $self->_identity($identity);
66   }
67
68   return $self->next::method(@_);
69 }
70
71 # this sub stolen from DB2
72
73 sub _sql_maker_opts {
74   my ( $self, $opts ) = @_;
75
76   if ( $opts ) {
77     $self->{_sql_maker_opts} = { %$opts };
78   }
79
80   return { limit_dialect => 'RowNumberOver', %{$self->{_sql_maker_opts}||{}} };
81 }
82
83 # this sub stolen from MSSQL
84
85 sub build_datetime_parser {
86   my $self = shift;
87   my $type = "DateTime::Format::Strptime";
88   eval "use ${type}";
89   $self->throw_exception("Couldn't load ${type}: $@") if $@;
90   return $type->new( pattern => '%Y-%m-%d %H:%M:%S.%6N' );
91 }
92
93 =head2 connect_call_datetime_setup
94
95 Used as:
96
97     on_connect_call => 'datetime_setup'
98
99 In L<DBIx::Class::Storage::DBI/connect_info> to set the date and timestamp
100 formats (as temporary options for the session) for use with
101 L<DBIx::Class::InflateColumn::DateTime>.
102
103 The C<TIMESTAMP> data type supports up to 6 digits after the decimal point for
104 second precision. The full precision is used.
105
106 The C<DATE> data type supposedly stores hours and minutes too, according to the
107 documentation, but I could not get that to work. It seems to only store the
108 date.
109
110 You will need the L<DateTime::Format::Strptime> module for inflation to work.
111
112 =cut
113
114 sub connect_call_datetime_setup {
115   my $self = shift;
116
117   $self->_do_query(
118     "set temporary option timestamp_format = 'yyyy-mm-dd hh:mm:ss.ssssss'"
119   );
120   $self->_do_query(
121     "set temporary option date_format      = 'yyyy-mm-dd hh:mm:ss.ssssss'"
122   );
123 }
124
125 1;
126
127 =head1 AUTHOR
128
129 See L<DBIx::Class/AUTHOR> and L<DBIx::Class/CONTRIBUTORS>.
130
131 =head1 LICENSE
132
133 You may distribute this code under the same terms as Perl itself.
134
135 =cut