if ($identity_insert) {
my $table = $source->from;
- $self->dbh->do("SET IDENTITY_INSERT $table ON");
+ $self->_get_dbh->do("SET IDENTITY_INSERT $table ON");
}
$self->next::method(@_);
if ($identity_insert) {
my $table = $source->from;
- $self->dbh->do("SET IDENTITY_INSERT $table OFF");
+ $self->_get_dbh->do("SET IDENTITY_INSERT $table OFF");
}
}
@pk_cols{@pk_cols} = ();
my @pk_guids = grep {
+ $source->column_info($_)->{data_type}
+ &&
$source->column_info($_)->{data_type} =~ /^uniqueidentifier/i
} @pk_cols;
my @auto_guids = grep {
+ $source->column_info($_)->{data_type}
+ &&
$source->column_info($_)->{data_type} =~ /^uniqueidentifier/i
&&
$source->column_info($_)->{auto_nextval}
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()');
+ my ($new_guid) = $self->_get_dbh->selectrow_array('SELECT NEWID()');
$updated_cols->{$guid_col} = $to_insert->{$guid_col} = $new_guid;
}
# cast MONEY values properly
if ($op eq 'insert' || $op eq 'update') {
my $fields = $args->[0];
- my $col_info = $self->_resolve_column_info($ident, [keys %$fields]);
for my $col (keys %$fields) {
- if ($col_info->{$col}{data_type} =~ /^money\z/i) {
+ # $ident is a result source object with INSERT/UPDATE ops
+ if ($ident->column_info ($col)->{data_type}
+ &&
+ $ident->column_info ($col)->{data_type} =~ /^money\z/i) {
my $val = $fields->{$col};
$fields->{$col} = \['CAST(? AS MONEY)', [ $col => $val ]];
}
my ($op) = @_;
my ($rv, $sth, @bind) = $self->dbh_do($self->can('_dbh_execute'), @_);
+
if ($op eq 'insert') {
- $self->_identity($self->_fetch_identity($sth));
- }
- return wantarray ? ($rv, $sth, @bind) : $rv;
-}
+ # this should bring back the result of SELECT SCOPE_IDENTITY() we tacked
+ # on in _prep_for_execute above
+ my ($identity) = $sth->fetchrow_array;
-sub _fetch_identity {
- my ($self, $sth) = @_;
- my ($identity) = $sth->fetchrow_array;
- $sth->finish;
+ # SCOPE_IDENTITY failed, but we can do something else
+ if ( (! $identity) && $self->_identity_method) {
+ ($identity) = $self->_dbh->selectrow_array(
+ 'select ' . $self->_identity_method
+ );
+ }
- if ((not defined $identity) && $self->_identity_method)
- ($identity) = $self->_dbh->selectrow_array(
- 'select ' . $self->_identity_method
- );
+ $self->_identity($identity);
+ $sth->finish;
}
- return $identity;
+ return wantarray ? ($rv, $sth, @bind) : $rv;
}
sub last_insert_id { shift->_identity }
sub _svp_begin {
my ($self, $name) = @_;
- $self->dbh->do("SAVE TRANSACTION $name");
+ $self->_get_dbh->do("SAVE TRANSACTION $name");
}
# A new SAVE TRANSACTION with the same name releases the previous one.
sub _svp_rollback {
my ($self, $name) = @_;
- $self->dbh->do("ROLLBACK TRANSACTION $name");
+ $self->_get_dbh->do("ROLLBACK TRANSACTION $name");
}
sub build_datetime_parser {
=head1 IMPLEMENTATION NOTES
+=head2 IDENTITY information
+
Microsoft SQL Server supports three methods of retrieving the IDENTITY
value for inserted row: IDENT_CURRENT, @@IDENTITY, and SCOPE_IDENTITY().
SCOPE_IDENTITY is used here because it is the safest. However, it must
inserts into another table with an identity will give erroneous results on
recent versions of SQL Server.
+=head2 bulk_insert
+
+Be aware that we have tried to make things as simple as possible for our users.
+For MSSQL that means that when a user tries to do a populate/bulk_insert which
+includes an autoincrementing column, we will try to tell the database to allow
+the insertion of the autoinc column. But the user must have the db_ddladmin
+role membership, otherwise you will get a fairly opaque error message.
+
=head1 AUTHOR
See L<DBIx::Class/CONTRIBUTORS>.