X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FStorage%2FDBI%2FSQLAnywhere.pm;h=3d054bb192d5ae8f6e17111684c309304cd2ba14;hb=d52fc26dd05b56a41494a5ec86cddecfe3587b96;hp=73a5df0d95d7e405ad3859238d2676e89bf22587;hpb=7df295ecab8ab961c2b3c88515006f18d9c7f4b4;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/Storage/DBI/SQLAnywhere.pm b/lib/DBIx/Class/Storage/DBI/SQLAnywhere.pm index 73a5df0..3d054bb 100644 --- a/lib/DBIx/Class/Storage/DBI/SQLAnywhere.pm +++ b/lib/DBIx/Class/Storage/DBI/SQLAnywhere.pm @@ -2,23 +2,32 @@ package DBIx::Class::Storage::DBI::SQLAnywhere; use strict; use warnings; -use base qw/DBIx::Class::Storage::DBI/; +use base qw/DBIx::Class::Storage::DBI::UniqueIdentifier/; use mro 'c3'; -use List::Util (); +use List::Util 'first'; +use DBIx::Class::_Util 'dbic_internal_try'; +use Try::Tiny; +use namespace::clean; -__PACKAGE__->mk_group_accessors(simple => qw/ - _identity -/); +__PACKAGE__->mk_group_accessors(simple => qw/_identity/); +__PACKAGE__->sql_limit_dialect ('RowNumberOver'); +__PACKAGE__->sql_quote_char ('"'); + +__PACKAGE__->new_guid('UUIDTOSTR(NEWID())'); + +# default to the UUID decoding cursor, overridable by the user +__PACKAGE__->cursor_class('DBIx::Class::Storage::DBI::SQLAnywhere::Cursor'); =head1 NAME -DBIx::Class::Storage::DBI::SQLAnywhere - Driver for Sybase SQL Anywhere +DBIx::Class::Storage::DBI::SQLAnywhere - Driver for SQL Anywhere =head1 DESCRIPTION -This class implements autoincrements for Sybase SQL Anywhere, selects the -RowNumberOver limit implementation and provides -L support. +This class implements autoincrements for SQL Anywhere and provides +L support and support for the +C type (via +L.) You need the C driver that comes with the SQL Anywhere distribution, B the one on CPAN. It is usually under a path such as: @@ -35,18 +44,28 @@ Recommended L settings: sub last_insert_id { shift->_identity } -sub insert { +sub _prefetch_autovalues { my $self = shift; - my ($source, $to_insert) = @_; + my ($source, $colinfo, $to_insert) = @_; + + my $values = $self->next::method(@_); - my $identity_col = List::Util::first { - $source->column_info($_)->{is_auto_increment} - } $source->columns; + my $identity_col = + first { $colinfo->{$_}{is_auto_increment} } keys %$colinfo; # user might have an identity PK without is_auto_increment +# +# FIXME we probably should not have supported the above, see what +# does it take to move away from it if (not $identity_col) { foreach my $pk_col ($source->primary_columns) { - if (not exists $to_insert->{$pk_col}) { + if ( + ! exists $to_insert->{$pk_col} + and + $colinfo->{$pk_col}{data_type} + and + $colinfo->{$pk_col}{data_type} !~ /^uniqueidentifier/i + ) { $identity_col = $pk_col; last; } @@ -58,36 +77,77 @@ sub insert { my $table_name = $source->from; $table_name = $$table_name if ref $table_name; - my ($identity) = $dbh->selectrow_array("SELECT GET_IDENTITY('$table_name')"); + my ($identity) = dbic_internal_try { + $dbh->selectrow_array("SELECT GET_IDENTITY('$table_name')") + }; + + if (defined $identity) { + $values->{$identity_col} = $identity; + $self->_identity($identity); + } + } + + return $values; +} + +sub _uuid_to_str { + my ($self, $data) = @_; - $to_insert->{$identity_col} = $identity; + $data = unpack 'H*', $data; - $self->_identity($identity); + for my $pos (8, 13, 18, 23) { + substr($data, $pos, 0) = '-'; } - return $self->next::method(@_); + return $data; } -# this sub stolen from DB2 +# select_single does not invoke a cursor object at all, hence UUID decoding happens +# here if the proper cursor class is set +sub select_single { + my $self = shift; + + my @row = $self->next::method(@_); + + return @row + unless $self->cursor_class->isa('DBIx::Class::Storage::DBI::SQLAnywhere::Cursor'); -sub _sql_maker_opts { - my ( $self, $opts ) = @_; + my ($ident, $select) = @_; - if ( $opts ) { - $self->{_sql_maker_opts} = { %$opts }; + my $col_info = $self->_resolve_column_info($ident); + + for my $select_idx (0..$#$select) { + my $selected = $select->[$select_idx]; + + next if ref $selected; + + my $data_type = $col_info->{$selected}{data_type} + or next; + + if ($self->_is_guid_type($data_type)) { + my $returned = $row[$select_idx]; + + if (length $returned == 16) { + $row[$select_idx] = $self->_uuid_to_str($returned); + } + } } - return { limit_dialect => 'RowNumberOver', %{$self->{_sql_maker_opts}||{}} }; + return @row; } # this sub stolen from MSSQL sub build_datetime_parser { my $self = shift; - my $type = "DateTime::Format::Strptime"; - eval "use ${type}"; - $self->throw_exception("Couldn't load ${type}: $@") if $@; - return $type->new( pattern => '%Y-%m-%d %H:%M:%S.%6N' ); + dbic_internal_try { + require DateTime::Format::Strptime; + } + catch { + $self->throw_exception("Couldn't load DateTime::Format::Strptime: $_"); + }; + + return DateTime::Format::Strptime->new( pattern => '%Y-%m-%d %H:%M:%S.%6N' ); } =head2 connect_call_datetime_setup @@ -122,19 +182,19 @@ sub connect_call_datetime_setup { ); } -sub _svp_begin { +sub _exec_svp_begin { my ($self, $name) = @_; - $self->_get_dbh->do("SAVEPOINT $name"); + $self->_dbh->do("SAVEPOINT $name"); } # can't release savepoints that have been rolled back -sub _svp_release { 1 } +sub _exec_svp_release { 1 } -sub _svp_rollback { +sub _exec_svp_rollback { my ($self, $name) = @_; - $self->_get_dbh->do("ROLLBACK TO SAVEPOINT $name") + $self->_dbh->do("ROLLBACK TO SAVEPOINT $name") } 1; @@ -152,12 +212,13 @@ be turned off (or increased) by the DBA by executing: Highly recommended. -=head1 AUTHOR +=head1 FURTHER QUESTIONS? -See L and L. +Check the list of L. -=head1 LICENSE +=head1 COPYRIGHT AND LICENSE -You may distribute this code under the same terms as Perl itself. - -=cut +This module is free software L +by the L. You can +redistribute it and/or modify it under the same terms as the +L.