From: Rafael Kitover Date: Thu, 30 Jul 2009 11:29:19 +0000 (+0000) Subject: MSSQL GUID support X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=ca791b95e618ab76bddbaf58441e3d6873336850;p=dbsrgits%2FDBIx-Class-Historic.git MSSQL GUID support --- diff --git a/lib/DBIx/Class/ResultSource.pm b/lib/DBIx/Class/ResultSource.pm index 89b8eda..8a61a40 100644 --- a/lib/DBIx/Class/ResultSource.pm +++ b/lib/DBIx/Class/ResultSource.pm @@ -153,9 +153,15 @@ automatically. =item auto_nextval -Set this to a true value for a column whose value is retrieved -automatically from an oracle sequence. If you do not use an Oracle -trigger to get the nextval, you have to set sequence as well. +Set this to a true value for a column whose value is retrieved automatically +from a sequence or function (if supported by your Storage driver.) For a +sequence, if you do not use a trigger to get the nextval, you have to set the +L value as well. + +Also set this for MSSQL columns with the 'uniqueidentifier' +L whose values you want to automatically +generate using C, unless they are a primary key in which case this will +be done anyway. =item extra diff --git a/lib/DBIx/Class/Storage/DBI/MSSQL.pm b/lib/DBIx/Class/Storage/DBI/MSSQL.pm index d9cd2ee..37733f6 100644 --- a/lib/DBIx/Class/Storage/DBI/MSSQL.pm +++ b/lib/DBIx/Class/Storage/DBI/MSSQL.pm @@ -41,6 +41,40 @@ sub insert_bulk { } } +sub insert { + my $self = shift; + my ($source, $to_insert) = @_; + + my $updated_cols = {}; + + my %guid_cols; + my @pk_cols = $source->primary_columns; + my %pk_cols; + @pk_cols{@pk_cols} = (); + + my @pk_guids = grep { + $source->column_info($_)->{data_type} =~ /^uniqueidentifier/i + } @pk_cols; + + my @auto_guids = grep { + $source->column_info($_)->{data_type} =~ /^uniqueidentifier/i + && + $source->column_info($_)->{auto_nextval} + } grep { not exists $pk_cols{$_} } $source->columns; + + my @get_guids_for = + grep { not exists $to_insert->{$_} } (@pk_guids, @auto_guids); + + for my $guid_col (@get_guids_for) { + my ($new_guid) = $self->dbh->selectrow_array('SELECT NEWID()'); + $updated_cols->{$guid_col} = $to_insert->{$guid_col} = $new_guid; + } + + $updated_cols = { %$updated_cols, %{ $self->next::method(@_) } }; + + return $updated_cols; +} + sub _prep_for_execute { my $self = shift; my ($op, $extra_bind, $ident, $args) = @_; diff --git a/t/746mssql.t b/t/746mssql.t index e5be28a..f9cbf85 100644 --- a/t/746mssql.t +++ b/t/746mssql.t @@ -12,8 +12,9 @@ my ($dsn, $user, $pass) = @ENV{map { "DBICTEST_MSSQL_ODBC_${_}" } qw/DSN USER PA plan skip_all => 'Set $ENV{DBICTEST_MSSQL_ODBC_DSN}, _USER and _PASS to run this test' unless ($dsn && $user); -plan tests => 34; +plan tests => 39; +DBICTest::Schema->load_classes('ArtistGUID'); my $schema = DBICTest::Schema->connect($dsn, $user, $pass); { @@ -33,7 +34,6 @@ $schema->storage->dbh_do (sub { my ($storage, $dbh) = @_; eval { $dbh->do("DROP TABLE artist") }; $dbh->do(<<'SQL'); - CREATE TABLE artist ( artistid INT IDENTITY NOT NULL, name VARCHAR(100), @@ -41,9 +41,7 @@ CREATE TABLE artist ( charfield CHAR(10) NULL, primary key(artistid) ) - SQL - }); my %seen_id; @@ -85,6 +83,49 @@ $it->next; is( $it->next->name, "Artist 2", "iterator->next ok" ); is( $it->next, undef, "next past end of resultset ok" ); +# test GUID columns + +$schema->storage->dbh_do (sub { + my ($storage, $dbh) = @_; + eval { $dbh->do("DROP TABLE artist") }; + $dbh->do(<<'SQL'); +CREATE TABLE artist ( + artistid UNIQUEIDENTIFIER NOT NULL, + name VARCHAR(100), + rank INT NOT NULL DEFAULT '13', + charfield CHAR(10) NULL, + a_guid UNIQUEIDENTIFIER, + primary key(artistid) +) +SQL +}); + +my $row; +lives_ok { + $row = $schema->resultset('ArtistGUID')->create({ name => 'mtfnpy' }) +} 'created a row with a GUID'; + +ok( + eval { $row->artistid }, + 'row has GUID PK col populated', +); +diag $@ if $@; + +ok( + eval { $row->a_guid }, + 'row has a GUID col with auto_nextval populated', +); +diag $@ if $@; + +my $row_from_db = $schema->resultset('ArtistGUID') + ->search({ name => 'mtfnpy' })->first; + +is $row_from_db->artistid, $row->artistid, + 'PK GUID round trip'; + +is $row_from_db->a_guid, $row->a_guid, + 'NON-PK GUID round trip'; + # test MONEY type $schema->storage->dbh_do (sub { my ($storage, $dbh) = @_; @@ -102,7 +143,6 @@ SQL my $rs = $schema->resultset('Money'); -my $row; lives_ok { $row = $rs->create({ amount => 100 }); } 'inserted a money value'; @@ -126,8 +166,6 @@ $schema->storage->dbh_do (sub { eval { $dbh->do("DROP TABLE Owners") }; eval { $dbh->do("DROP TABLE Books") }; $dbh->do(<<'SQL'); - - CREATE TABLE Books ( id INT IDENTITY (1, 1) NOT NULL, source VARCHAR(100), @@ -140,7 +178,6 @@ CREATE TABLE Owners ( id INT IDENTITY (1, 1) NOT NULL, name VARCHAR(100), ) - SQL }); @@ -278,11 +315,9 @@ $schema->storage->_sql_maker->{name_sep} = '.'; # clean up our mess END { - if (my $dbh = eval { $schema->storage->_dbh }) { - $dbh->do('DROP TABLE artist'); - $dbh->do('DROP TABLE money_test'); - $dbh->do('DROP TABLE Books'); - $dbh->do('DROP TABLE Owners'); - } + if (my $dbh = eval { $schema->storage->_dbh }) { + eval { $dbh->do("DROP TABLE $_") } + for qw/artist money_test Books Owners/; + } } # vim:sw=2 sts=2