2d33352fe7a2836dea105c6281b876a719c7cabc
[dbsrgits/DBIx-Class.git] / t / sqlmaker / bind_transport.t
1 use strict;
2 use warnings;
3
4 use Test::More;
5 use Test::Exception;
6 use Math::BigInt;
7
8 use lib qw(t/lib);
9 use DBICTest ':DiffSQL';
10 use DBIx::Class::SQLMaker::LimitDialects;
11
12 my ($ROWS, $OFFSET) = (
13    DBIx::Class::SQLMaker::LimitDialects->__rows_bindtype,
14    DBIx::Class::SQLMaker::LimitDialects->__offset_bindtype,
15 );
16
17 my $schema = DBICTest->init_schema();
18
19 my $rs = $schema->resultset('CD')->search({ -and => [
20   'me.artist' => { '!=', '666' },
21   'me.artist' => { '!=', \[ '?', [ _ne => 'bar' ] ] },
22 ]});
23
24 # bogus sql query to make sure bind composition happens properly
25 my $complex_rs = $rs->search({}, {
26   '+columns' => { cnt => $rs->count_rs->as_query },
27   '+select' => \[ 'me.artist + ?', [ _add => 1 ] ], # free select
28   group_by => ['me.cdid', \[ 'me.artist - ?', [ _sub => 2 ] ] ],
29   having => \[ 'me.artist < ?', [ _lt => 3 ] ],
30   order_by => \[ 'me.artist * ? ', [ _mu => 4 ] ],
31   rows => 1,
32   page => 3,
33 });
34
35 for (1,2) {
36   is_same_sql_bind (
37     $complex_rs->as_query,
38     '(
39       SELECT  me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track,
40               (SELECT COUNT( * ) FROM cd me WHERE me.artist != ? AND me.artist != ?),
41               me.artist + ?
42         FROM cd me
43       WHERE me.artist != ? AND me.artist != ?
44       GROUP BY me.cdid, me.artist - ?
45       HAVING me.artist < ?
46       ORDER BY me.artist * ?
47       LIMIT ? OFFSET ?
48     )',
49     [
50       [ { sqlt_datatype => 'integer', dbic_colname => 'me.artist' } => 666 ],
51       [ { dbic_colname => '_ne' } => 'bar' ],
52       [ { dbic_colname => '_add' } => 1 ],
53       [ { sqlt_datatype => 'integer', dbic_colname => 'me.artist' } => 666 ],
54       [ { dbic_colname => '_ne' } => 'bar' ],
55       [ { dbic_colname => '_sub' } => 2 ],
56       [ { dbic_colname => '_lt' } => 3 ],
57       [ { dbic_colname => '_mu' } => 4 ],
58       [ $ROWS => 1 ],
59       [ $OFFSET => 2 ],
60     ],
61     'Correct crazy sql',
62   );
63 }
64
65 # see if we get anything back at all
66 isa_ok ($complex_rs->next, 'DBIx::Class::Row');
67
68 # Make sure that the bind shorthand syntax translation is accurate (and doesn't error)
69 shorthand_check(
70   [ _sub => 2 ],
71   [ { dbic_colname => '_sub' } => 2 ],
72   '[ $name => $val ] === [ { dbic_colname => $name }, $val ]',
73 );
74 shorthand_check(
75   [ artist => 2 ],
76   [ { dbic_colname => 'artist', sqlt_datatype => 'integer' } => 2 ],
77   'resolution of known column during [ $name => $val ] === [ { dbic_colname => $name }, $val ]',
78 );
79 shorthand_check(
80   [ \ 'number' => 2 ],
81   [ { sqlt_datatype => 'number' } => 2 ],
82   '[ \$dt => $val ] === [ { sqlt_datatype => $dt }, $val ]',
83 );
84 shorthand_check(
85   [ {} => 2 ],
86   [ {} => 2 ],
87   '[ {} => $val ] === [ {}, $val ]',
88 );
89 shorthand_check(
90   [ undef, 2 ],
91   [ {} => 2 ],
92   '[ undef, $val ] === [ {}, $val ]',
93 );
94 shorthand_check(
95   2,
96   [ {} => 2 ],
97   '$val === [ {}, $val ]',
98 );
99
100 shorthand_check(
101   Math::BigInt->new(42),
102   [ {} => Math::BigInt->new(42) ],
103   'stringifyable $object === [ {}, $object ]',
104 );
105
106 throws_ok {
107   shorthand_check(
108     [ 2 ],
109     [],
110   )
111 } qr !You must supply a datatype/bindtype .+ for non-scalar value  \Q[ 2 ]!,
112   'exception on bare array bindvalue';
113
114 throws_ok {
115   shorthand_check(
116     [ {} => [ 2 ] ],
117     [],
118   )
119 } qr !You must supply a datatype/bindtype .+ for non-scalar value  \Q[ 2 ]!,
120   'exception on untyped array bindvalue';
121
122 throws_ok {
123   shorthand_check(
124     [ {}, 2, 3 ],
125     [],
126   )
127 } qr !You must supply a datatype/bindtype .+ for non-scalar value  \[ 'HASH\(\w+\)', 2, 3 \]!,
128   'exception on bare multielement array bindvalue';
129
130 throws_ok {
131   shorthand_check(
132     bless( {}, 'Foo'),
133     [],
134   )
135 } qr !You must supply a datatype/bindtype .+ for non-scalar value  \Qbless( {}, 'Foo' )!,
136   'exception on bare object';
137
138 throws_ok {
139   shorthand_check(
140     [ {}, bless( {}, 'Foo') ],
141     [],
142   )
143 } qr !You must supply a datatype/bindtype .+ for non-scalar value  \Qbless( {}, 'Foo' )!,
144   'exception on untyped object';
145
146
147 sub shorthand_check {
148   my ($bind_shorthand, $bind_expected, $testname) = @_;
149
150   local $Test::Builder::Level = $Test::Builder::Level + 1;
151
152   is_same_sql_bind (
153     $schema->resultset('CD')->search({}, {
154       columns => [qw(cdid artist)],
155       group_by => ['cdid', \[ 'artist - ?', $bind_shorthand ] ],
156     })->as_query,
157     '(
158       SELECT me.cdid, me.artist
159         FROM cd me
160       GROUP BY cdid, artist - ?
161     )',
162     [ $bind_expected ],
163     $testname||(),
164   );
165 }
166
167 undef $schema;
168
169 done_testing;