default collist for storage _resolve_column_info
[dbsrgits/DBIx-Class.git] / t / 746mssql.t
CommitLineData
c1cac633 1use strict;
b9a2c3a5 2use warnings;
c1cac633 3
4use Test::More;
893403c8 5use Test::Exception;
c1cac633 6use lib qw(t/lib);
7use DBICTest;
b2d16f1f 8use DBIC::SqlMakerTest;
c1cac633 9
10my ($dsn, $user, $pass) = @ENV{map { "DBICTEST_MSSQL_ODBC_${_}" } qw/DSN USER PASS/};
11
12plan skip_all => 'Set $ENV{DBICTEST_MSSQL_ODBC_DSN}, _USER and _PASS to run this test'
13 unless ($dsn && $user);
14
ca791b95 15plan tests => 39;
c1cac633 16
ca791b95 17DBICTest::Schema->load_classes('ArtistGUID');
42e5b103 18my $schema = DBICTest::Schema->connect($dsn, $user, $pass);
c1cac633 19
8c0104fe 20{
21 no warnings 'redefine';
22 my $connect_count = 0;
23 my $orig_connect = \&DBI::connect;
24 local *DBI::connect = sub { $connect_count++; goto &$orig_connect };
25
26 $schema->storage->ensure_connected;
27
28 is( $connect_count, 1, 'only one connection made');
29}
9b3e916d 30
c1cac633 31isa_ok( $schema->storage, 'DBIx::Class::Storage::DBI::ODBC::Microsoft_SQL_Server' );
32
c5f77f6c 33$schema->storage->dbh_do (sub {
34 my ($storage, $dbh) = @_;
35 eval { $dbh->do("DROP TABLE artist") };
36 $dbh->do(<<'SQL');
c1cac633 37CREATE TABLE artist (
38 artistid INT IDENTITY NOT NULL,
a0dd8679 39 name VARCHAR(100),
39da2a2b 40 rank INT NOT NULL DEFAULT '13',
2eebd801 41 charfield CHAR(10) NULL,
c1cac633 42 primary key(artistid)
43)
c5f77f6c 44SQL
c5f77f6c 45});
46
c1cac633 47my %seen_id;
48
7b1b2582 49my @opts = (
50 { on_connect_call => 'use_dynamic_cursors' },
51 {},
52);
53my $new;
2eebd801 54
7b1b2582 55# test Auto-PK with different options
56for my $opts (@opts) {
57 $schema = DBICTest::Schema->clone;
58 $schema->connection($dsn, $user, $pass, $opts);
59
60 $schema->resultset('Artist')->search({ name => 'foo' })->delete;
61
62 $new = $schema->resultset('Artist')->create({ name => 'foo' });
63 ok($new->artistid > 0, "Auto-PK worked");
64}
c1cac633 65
66$seen_id{$new->artistid}++;
67
68# test LIMIT support
69for (1..6) {
70 $new = $schema->resultset('Artist')->create({ name => 'Artist ' . $_ });
71 is ( $seen_id{$new->artistid}, undef, "id for Artist $_ is unique" );
72 $seen_id{$new->artistid}++;
73}
74
75my $it = $schema->resultset('Artist')->search( {}, {
76 rows => 3,
77 order_by => 'artistid',
78});
79
80is( $it->count, 3, "LIMIT count ok" );
81is( $it->next->name, "foo", "iterator->next ok" );
82$it->next;
83is( $it->next->name, "Artist 2", "iterator->next ok" );
84is( $it->next, undef, "next past end of resultset ok" );
85
ca791b95 86# test GUID columns
87
88$schema->storage->dbh_do (sub {
89 my ($storage, $dbh) = @_;
90 eval { $dbh->do("DROP TABLE artist") };
91 $dbh->do(<<'SQL');
92CREATE TABLE artist (
93 artistid UNIQUEIDENTIFIER NOT NULL,
94 name VARCHAR(100),
95 rank INT NOT NULL DEFAULT '13',
96 charfield CHAR(10) NULL,
97 a_guid UNIQUEIDENTIFIER,
98 primary key(artistid)
99)
100SQL
101});
102
e34bae3a 103# start disconnected to make sure insert works on an un-reblessed storage
104$schema = DBICTest::Schema->connect($dsn, $user, $pass);
105
ca791b95 106my $row;
107lives_ok {
108 $row = $schema->resultset('ArtistGUID')->create({ name => 'mtfnpy' })
109} 'created a row with a GUID';
110
111ok(
112 eval { $row->artistid },
113 'row has GUID PK col populated',
114);
115diag $@ if $@;
116
117ok(
118 eval { $row->a_guid },
119 'row has a GUID col with auto_nextval populated',
120);
121diag $@ if $@;
122
123my $row_from_db = $schema->resultset('ArtistGUID')
124 ->search({ name => 'mtfnpy' })->first;
125
126is $row_from_db->artistid, $row->artistid,
127 'PK GUID round trip';
128
129is $row_from_db->a_guid, $row->a_guid,
130 'NON-PK GUID round trip';
131
818ec409 132# test MONEY type
133$schema->storage->dbh_do (sub {
134 my ($storage, $dbh) = @_;
135 eval { $dbh->do("DROP TABLE money_test") };
136 $dbh->do(<<'SQL');
137
138CREATE TABLE money_test (
139 id INT IDENTITY PRIMARY KEY,
5064f5c3 140 amount MONEY NULL
818ec409 141)
142
143SQL
144
145});
146
147my $rs = $schema->resultset('Money');
148
818ec409 149lives_ok {
d68f21ee 150 $row = $rs->create({ amount => 100 });
818ec409 151} 'inserted a money value';
152
153is $rs->find($row->id)->amount, '100.00', 'money value round-trip';
154
d68f21ee 155lives_ok {
156 $row->update({ amount => 200 });
157} 'updated a money value';
158
159is $rs->find($row->id)->amount, '200.00', 'updated money value round-trip';
160
f6b185e1 161lives_ok {
162 $row->update({ amount => undef });
163} 'updated a money value to NULL';
164
165is $rs->find($row->id)->amount, undef,'updated money value to NULL round-trip';
166
b9a2c3a5 167$schema->storage->dbh_do (sub {
168 my ($storage, $dbh) = @_;
169 eval { $dbh->do("DROP TABLE Owners") };
170 eval { $dbh->do("DROP TABLE Books") };
171 $dbh->do(<<'SQL');
b9a2c3a5 172CREATE TABLE Books (
173 id INT IDENTITY (1, 1) NOT NULL,
174 source VARCHAR(100),
175 owner INT,
176 title VARCHAR(10),
177 price INT NULL
178)
179
180CREATE TABLE Owners (
181 id INT IDENTITY (1, 1) NOT NULL,
42e5b103 182 name VARCHAR(100),
b9a2c3a5 183)
b9a2c3a5 184SQL
185
186});
893403c8 187
188lives_ok ( sub {
189 $schema->populate ('Owners', [
190 [qw/id name /],
191 [qw/1 wiggle/],
192 [qw/2 woggle/],
193 [qw/3 boggle/],
194 [qw/4 fREW/],
195 [qw/5 fRIOUX/],
196 [qw/6 fROOH/],
197 [qw/7 fRUE/],
198 [qw/8 fISMBoC/],
199 [qw/9 station/],
200 [qw/10 mirror/],
201 [qw/11 dimly/],
202 [qw/12 face_to_face/],
203 [qw/13 icarus/],
204 [qw/14 dream/],
205 [qw/15 dyrstyggyr/],
206 ]);
207}, 'populate with PKs supplied ok' );
208
209lives_ok ( sub {
210 $schema->populate ('BooksInLibrary', [
211 [qw/source owner title /],
212 [qw/Library 1 secrets0/],
213 [qw/Library 1 secrets1/],
214 [qw/Eatery 1 secrets2/],
215 [qw/Library 2 secrets3/],
216 [qw/Library 3 secrets4/],
217 [qw/Eatery 3 secrets5/],
218 [qw/Library 4 secrets6/],
219 [qw/Library 5 secrets7/],
220 [qw/Eatery 5 secrets8/],
221 [qw/Library 6 secrets9/],
222 [qw/Library 7 secrets10/],
223 [qw/Eatery 7 secrets11/],
224 [qw/Library 8 secrets12/],
225 ]);
226}, 'populate without PKs supplied ok' );
b9a2c3a5 227
228#
02d133f0 229# try a prefetch on tables with identically named columns
b9a2c3a5 230#
231
02d133f0 232# set quote char - make sure things work while quoted
233$schema->storage->_sql_maker->{quote_char} = [qw/[ ]/];
234$schema->storage->_sql_maker->{name_sep} = '.';
235
b9a2c3a5 236{
893403c8 237 # try a ->has_many direction
fc85215b 238 my $owners = $schema->resultset ('Owners')->search ({
239 'books.id' => { '!=', undef }
240 }, {
241 prefetch => 'books',
ff1ef65b 242 order_by => 'name',
56d2561e 243 rows => 3, # 8 results total
fc85215b 244 });
245
56d2561e 246 is ($owners->page(1)->all, 3, 'has_many prefetch returns correct number of rows');
247 is ($owners->page(1)->count, 3, 'has-many prefetch returns correct count');
248
618a0fe3 249 TODO: {
250 local $TODO = 'limit past end of resultset problem';
56d2561e 251 is ($owners->page(3)->all, 2, 'has_many prefetch returns correct number of rows');
252 is ($owners->page(3)->count, 2, 'has-many prefetch returns correct count');
64c7c000 253 is ($owners->page(3)->count_rs->next, 2, 'has-many prefetch returns correct count_rs');
254
255 # make sure count does not become overly complex FIXME
256 is_same_sql_bind (
257 $owners->page(3)->count_rs->as_query,
258 '(
259 SELECT COUNT( * )
260 FROM (
02d133f0 261 SELECT TOP 3 [me].[id]
262 FROM [owners] [me]
263 LEFT JOIN [books] [books] ON [books].[owner] = [me].[id]
264 WHERE ( [books].[id] IS NOT NULL )
265 GROUP BY [me].[id]
266 ORDER BY [me].[id] DESC
267 ) [count_subq]
64c7c000 268 )',
269 [],
270 );
618a0fe3 271 }
b9a2c3a5 272
42e5b103 273 # try a ->belongs_to direction (no select collapse, group_by should work)
fc85215b 274 my $books = $schema->resultset ('BooksInLibrary')->search ({
56d2561e 275 'owner.name' => [qw/wiggle woggle/],
fc85215b 276 }, {
fc85215b 277 distinct => 1,
42e5b103 278 prefetch => 'owner',
56d2561e 279 rows => 2, # 3 results total
ac93965c 280 order_by => { -desc => 'owner' },
281 # there is no sane way to order by the right side of a grouped prefetch currently :(
282 #order_by => { -desc => 'owner.name' },
fc85215b 283 });
284
b1e1d073 285
56d2561e 286 is ($books->page(1)->all, 2, 'Prefetched grouped search returns correct number of rows');
287 is ($books->page(1)->count, 2, 'Prefetched grouped search returns correct count');
b1e1d073 288
618a0fe3 289 TODO: {
290 local $TODO = 'limit past end of resultset problem';
56d2561e 291 is ($books->page(2)->all, 1, 'Prefetched grouped search returns correct number of rows');
292 is ($books->page(2)->count, 1, 'Prefetched grouped search returns correct count');
64c7c000 293 is ($books->page(2)->count_rs->next, 1, 'Prefetched grouped search returns correct count_rs');
294
295 # make sure count does not become overly complex FIXME
296 is_same_sql_bind (
297 $books->page(2)->count_rs->as_query,
298 '(
299 SELECT COUNT( * )
300 FROM (
02d133f0 301 SELECT TOP 2 [me].[id]
302 FROM [books] [me]
303 JOIN [owners] [owner] ON [owner].[id] = [me].[owner]
304 WHERE ( ( ( [owner].[name] = ? OR [owner].[name] = ? ) AND [source] = ? ) )
305 GROUP BY [me].[id], [me].[source], [me].[owner], [me].[title], [me].[price], [owner].[id], [owner].[name]
306 ORDER BY [me].[id] DESC
307 ) [count_subq]
64c7c000 308 )',
309 [
310 [ 'owner.name' => 'wiggle' ],
311 [ 'owner.name' => 'woggle' ],
312 [ 'source' => 'Library' ],
313 ],
314 );
618a0fe3 315 }
b2d16f1f 316
b9a2c3a5 317}
c1cac633 318
319# clean up our mess
320END {
ca791b95 321 if (my $dbh = eval { $schema->storage->_dbh }) {
322 eval { $dbh->do("DROP TABLE $_") }
323 for qw/artist money_test Books Owners/;
324 }
c1cac633 325}
fc85215b 326# vim:sw=2 sts=2