fix uninitialized warning
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / DBI / ODBC / Microsoft_SQL_Server.pm
CommitLineData
c1cac633 1package DBIx::Class::Storage::DBI::ODBC::Microsoft_SQL_Server;
2use strict;
3use warnings;
4
eb0323df 5use base qw/DBIx::Class::Storage::DBI::MSSQL/;
2ad62d97 6use mro 'c3';
7
7b1b2582 8use List::Util();
9use Scalar::Util ();
ed7ab0f4 10use Try::Tiny;
fd323bf1 11use namespace::clean;
c1cac633 12
7b1b2582 13__PACKAGE__->mk_group_accessors(simple => qw/
14 _using_dynamic_cursors
15/);
c1cac633 16
17=head1 NAME
18
a89c6fc0 19DBIx::Class::Storage::DBI::ODBC::Microsoft_SQL_Server - Support specific
20to Microsoft SQL Server over ODBC
c1cac633 21
22=head1 DESCRIPTION
23
5a77aa8b 24This class implements support specific to Microsoft SQL Server over ODBC. It is
25loaded automatically by by DBIx::Class::Storage::DBI::ODBC when it detects a
26MSSQL back-end.
c1cac633 27
5a77aa8b 28Most of the functionality is provided from the superclass
29L<DBIx::Class::Storage::DBI::MSSQL>.
c1cac633 30
7b1b2582 31=head1 MULTIPLE ACTIVE STATEMENTS
32
33The following options are alternative ways to enable concurrent executing
34statement support. Each has its own advantages and drawbacks.
35
36=head2 connect_call_use_dynamic_cursors
37
38Use as:
39
40 on_connect_call => 'use_dynamic_cursors'
41
8384a713 42in your L<connect_info|DBIx::Class::Storage::DBI/connect_info> as one way to enable multiple
7b1b2582 43concurrent statements.
44
45Will add C<< odbc_cursortype => 2 >> to your DBI connection attributes. See
46L<DBD::ODBC/odbc_cursortype> for more information.
47
41dd5d30 48Alternatively, you can add it yourself and dynamic cursor support will be
49automatically enabled.
7b1b2582 50
41dd5d30 51If you're using FreeTDS, C<tds_version> must be set to at least C<8.0>.
52
53This will not work with CODE ref connect_info's.
7b1b2582 54
55B<WARNING:> this will break C<SCOPE_IDENTITY()>, and C<SELECT @@IDENTITY> will
56be used instead, which on SQL Server 2005 and later will return erroneous
57results on tables which have an on insert trigger that inserts into another
58table with an C<IDENTITY> column.
59
60=cut
61
62sub connect_call_use_dynamic_cursors {
63 my $self = shift;
64
65 if (ref($self->_dbi_connect_info->[0]) eq 'CODE') {
0a9a9955 66 $self->throw_exception ('Cannot set DBI attributes on a CODE ref connect_info');
7b1b2582 67 }
68
69 my $dbi_attrs = $self->_dbi_connect_info->[-1];
70
71 unless (ref($dbi_attrs) && Scalar::Util::reftype($dbi_attrs) eq 'HASH') {
72 $dbi_attrs = {};
73 push @{ $self->_dbi_connect_info }, $dbi_attrs;
74 }
75
76 if (not exists $dbi_attrs->{odbc_cursortype}) {
77 # turn on support for multiple concurrent statements, unless overridden
78 $dbi_attrs->{odbc_cursortype} = 2;
75517ea9 79 $self->disconnect; # resetting dbi attrs, so have to reconnect
80 $self->ensure_connected;
7b1b2582 81 $self->_set_dynamic_cursors;
82 }
83}
84
85sub _set_dynamic_cursors {
86 my $self = shift;
cbc0e07a 87 my $dbh = $self->_get_dbh;
41dd5d30 88
ed7ab0f4 89 try {
41dd5d30 90 local $dbh->{RaiseError} = 1;
91 local $dbh->{PrintError} = 0;
92 $dbh->do('SELECT @@IDENTITY');
ed7ab0f4 93 } catch {
1a58752c 94 $self->throw_exception (<<'EOF');
41dd5d30 95
96Your drivers do not seem to support dynamic cursors (odbc_cursortype => 2),
97if you're using FreeTDS, make sure to set tds_version to 8.0 or greater.
98EOF
1b300062 99 };
41dd5d30 100
7b1b2582 101 $self->_using_dynamic_cursors(1);
102 $self->_identity_method('@@identity');
103}
104
37b17a93 105sub _init {
7b1b2582 106 my $self = shift;
107
1a58752c 108 no warnings qw/uninitialized/;
109
110 if (
111 ref($self->_dbi_connect_info->[0]) ne 'CODE'
112 &&
113 ref ($self->_dbi_connect_info->[-1]) eq 'HASH'
114 &&
115 $self->_dbi_connect_info->[-1]{odbc_cursortype} == 2
116 ) {
7b1b2582 117 $self->_set_dynamic_cursors;
118 return;
119 }
120
121 $self->_using_dynamic_cursors(0);
122}
123
124=head2 connect_call_use_server_cursors
125
126Use as:
127
128 on_connect_call => 'use_server_cursors'
129
130May allow multiple active select statements. See
131L<DBD::ODBC/odbc_SQL_ROWSET_SIZE> for more information.
132
133Takes an optional parameter for the value to set the attribute to, default is
134C<2>.
135
136B<WARNING>: this does not work on all versions of SQL Server, and may lock up
137your database!
138
139=cut
140
141sub connect_call_use_server_cursors {
142 my $self = shift;
143 my $sql_rowset_size = shift || 2;
144
9ae966b9 145 $self->_get_dbh->{odbc_SQL_ROWSET_SIZE} = $sql_rowset_size;
7b1b2582 146}
147
445e08ff 148=head2 connect_call_use_MARS
7b1b2582 149
150Use as:
151
445e08ff 152 on_connect_call => 'use_MARS'
7b1b2582 153
154Use to enable a feature of SQL Server 2005 and later, "Multiple Active Result
155Sets". See L<DBD::ODBC::FAQ/Does DBD::ODBC support Multiple Active Statements?>
156for more information.
157
158B<WARNING>: This has implications for the way transactions are handled.
159
160=cut
161
445e08ff 162sub connect_call_use_MARS {
7b1b2582 163 my $self = shift;
164
165 my $dsn = $self->_dbi_connect_info->[0];
166
167 if (ref($dsn) eq 'CODE') {
1a58752c 168 $self->throw_exception('cannot change the DBI DSN on a CODE ref connect_info');
7b1b2582 169 }
170
171 if ($dsn !~ /MARS_Connection=/) {
172 $self->_dbi_connect_info->[0] = "$dsn;MARS_Connection=Yes";
9ae966b9 173 my $was_connected = defined $self->_dbh;
7b1b2582 174 $self->disconnect;
9ae966b9 175 $self->ensure_connected if $was_connected;
7b1b2582 176 }
177}
178
1791;
180
5a77aa8b 181=head1 AUTHOR
c1cac633 182
5a77aa8b 183See L<DBIx::Class/CONTRIBUTORS>.
c1cac633 184
185=head1 LICENSE
186
187You may distribute this code under the same terms as Perl itself.
188
189=cut
259c0e40 190# vim: sw=2 sts=2