Adjust expected sql to match the new 'Track' table definition
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / DBI / MSSQL.pm
index 5bf3c10..d322d46 100644 (file)
@@ -41,6 +41,42 @@ sub insert_bulk {
   }
 }
 
+# support MSSQL GUID column types
+
+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) = @_;
@@ -93,9 +129,10 @@ sub _fetch_identity {
   my ($identity) = $sth->fetchrow_array;
   $sth->finish;
 
-  if ((not defined $identity) && $self->_identity_method &&
-        $self->_identity_method eq '@@identity') {
-    ($identity) = $self->_dbh->selectrow_array('select @@identity');
+  if ((not defined $identity) && $self->_identity_method) {
+    ($identity) = $self->_dbh->selectrow_array(
+      'select ' . $self->_identity_method
+    );
   }
 
   return $identity;
@@ -103,6 +140,23 @@ sub _fetch_identity {
 
 sub last_insert_id { shift->_identity }
 
+# savepoint syntax is the same as in Sybase ASE
+
+sub _svp_begin {
+  my ($self, $name) = @_;
+
+  $self->dbh->do("SAVE TRANSACTION $name");
+}
+
+# A new SAVE TRANSACTION with the same name releases the previous one.
+sub _svp_release { 1 }
+
+sub _svp_rollback {
+  my ($self, $name) = @_;
+
+  $self->dbh->do("ROLLBACK TRANSACTION $name");
+}
+
 sub build_datetime_parser {
   my $self = shift;
   my $type = "DateTime::Format::Strptime";
@@ -150,8 +204,11 @@ C<SELECT @@IDENTITY> can also be used by issuing:
 
   $self->_identity_method('@@identity');
 
-this is more dangerous, as inserting into a table with an on insert trigger that
-inserts into another table with an identity will give erroneous results.
+it will only be used if SCOPE_IDENTITY() fails.
+
+This is more dangerous, as inserting into a table with an on insert trigger that
+inserts into another table with an identity will give erroneous results on
+recent versions of SQL Server.
 
 =head1 AUTHOR