f3d240f821d7e5d45366a6c9ff149c73619cfd7c
[dbsrgits/DBIx-Class.git] / t / sqlmaker / dbihacks_internals.t
1 use strict;
2 use warnings;
3 use Test::More;
4 use Test::Warn;
5
6 use lib qw(t/lib);
7 use DBICTest;
8
9 use DBIC::SqlMakerTest;
10 use Data::Dumper;
11
12 my $schema = DBICTest->init_schema( no_deploy => 1);
13 my $sm = $schema->storage->sql_maker;
14
15 for my $t (
16   {
17     where => { artistid => 1, charfield => undef },
18     cc_result => { artistid => 1, charfield => undef },
19     sql => 'WHERE artistid = ? AND charfield IS NULL',
20     efcc_result => [qw( artistid )],
21   },
22   {
23     where => { -and => [ artistid => 1, charfield => undef, { rank => 13 } ] },
24     cc_result => { artistid => 1, charfield => undef, rank => 13 },
25     sql => 'WHERE artistid = ?  AND charfield IS NULL AND rank = ?',
26     efcc_result => [qw( artistid rank )],
27   },
28   {
29     where => { -and => [ { artistid => 1, charfield => undef}, { rank => 13 } ] },
30     cc_result => { artistid => 1, charfield => undef, rank => 13 },
31     sql => 'WHERE artistid = ?  AND charfield IS NULL AND rank = ?',
32     efcc_result => [qw( artistid rank )],
33   },
34   {
35     where => { -and => [ -or => { name => 'Caterwauler McCrae' }, 'rank' ] },
36     cc_result => { name => 'Caterwauler McCrae', rank => undef },
37     sql => 'WHERE name = ? AND rank IS NULL',
38     efcc_result => [qw( name )],
39   },
40   {
41     where => { -and => [ [ [ artist => {'=' => \'foo' } ] ], { name => \[ '= ?', 'bar' ] } ] },
42     cc_result => { artist => {'=' => \'foo' }, name => \[ '= ?', 'bar' ] },
43     sql => 'WHERE artist = foo AND name = ?',
44     efcc_result => [qw( artist )],
45   },
46   {
47     where => { -and => [ -or => { name => 'Caterwauler McCrae', artistid => 2 } ] },
48     cc_result => { -or => [ artistid => 2, name => 'Caterwauler McCrae' ] },
49     sql => 'WHERE artistid = ? OR name = ?',
50     efcc_result => [],
51   },
52   {
53     where => { -and => [ \'foo=bar',  [ { artistid => { '=', 3 } } ], { name => 'Caterwauler McCrae'} ] },
54     cc_result => { '' => \'foo=bar', name => 'Caterwauler McCrae', artistid => 3 },
55     sql => 'WHERE foo=bar AND artistid = ? AND name = ?',
56     efcc_result => [qw( artistid name )],
57   },
58   {
59     where => { artistid => [ 1 ], rank => [ 13, 2, 3 ], charfield => [ undef ] },
60     cc_result => { artistid => 1, charfield => undef, rank => [13, 2, 3] },
61     sql => 'WHERE artistid = ? AND charfield IS NULL AND ( rank = ? OR rank = ? OR rank = ? )',
62     efcc_result => [qw( artistid )],
63   },
64   {
65     where => { artistid => { '=' => 1 }, rank => { '>' => 12 }, charfield => { '=' => undef } },
66     cc_result => { artistid => 1, charfield => undef, rank => { '>' => 12 } },
67     sql => 'WHERE artistid = ? AND charfield IS NULL AND rank > ?',
68     efcc_result => [qw( artistid )],
69   },
70   {
71     where => { artistid => { '=' => [ 1 ], }, charfield => { '=' => [-and => \'1', \['?',2] ] }, rank => { '=' => [ 1, 2 ] } },
72     cc_result => { artistid => 1, charfield => [-and => { '=' => \'1' }, { '=' => \['?',2] } ], rank => { '=' => [1, 2] } },
73     sql => 'WHERE artistid = ? AND charfield = 1 AND charfield = ? AND ( rank = ? OR rank = ? )',
74     efcc_result => [qw( artistid charfield )],
75   },
76   {
77     where => { -and => [ artistid => 1, artistid => 2 ], name => [ -and => { '!=', 1 }, 2 ], charfield => [ -or => { '=', 2 } ], rank => [-and => undef, { '=', undef }, { '!=', 2 } ] },
78     cc_result => { artistid => [ -and => 1, 2 ], name => [ -and => { '!=', 1 }, 2 ], charfield => 2, rank => [ -and => undef, undef, { '!=', 2 } ] },
79     sql => 'WHERE artistid = ? AND artistid = ? AND charfield = ? AND name != ? AND name = ? AND rank IS NULL AND rank IS NULL AND rank != ?',
80     efcc_result => [qw( artistid charfield name )],
81   },
82   {
83     where => { -and => [
84       [ '_macro.to' => { -like => '%correct%' }, '_wc_macros.to' => { -like => '%correct%' } ],
85       { -and => [ { 'group.is_active' => 1 }, { 'me.is_active' => 1 } ] }
86     ] },
87     cc_result => {
88       'group.is_active' => 1,
89       'me.is_active' => 1,
90       -or => [
91         '_macro.to' => { -like => '%correct%' },
92         '_wc_macros.to' => { -like => '%correct%' },
93       ],
94     },
95     sql => 'WHERE ( _macro.to LIKE ? OR _wc_macros.to LIKE ? ) AND group.is_active = ? AND me.is_active = ?',
96     efcc_result => [qw( group.is_active me.is_active )],
97   },
98   {
99     where => { artistid => [] },
100     cc_result => { artistid => [] },
101     efcc_result => [],
102   },
103   (map {
104     {
105       where => { -and => $_ },
106       cc_result => undef,
107       efcc_result => [],
108       sql => '',
109     },
110     {
111       where => { -or => $_ },
112       cc_result => undef,
113       efcc_result => [],
114       sql => '',
115     },
116   } (
117     # bare
118     [], {},
119     # singles
120     [ {} ], [ [] ],
121     # doubles
122     [ [], [] ], [ {}, {} ], [ [], {} ], [ {}, [] ],
123     # tripples
124     [ {}, [], {} ], [ [], {}, [] ]
125   )),
126
127   # FIXME legacy compat crap, possibly worth undef/dieing in SQLMaker
128   { where => { artistid => {} }, sql => '', cc_result => undef, efcc_result => [] },
129
130   # batshit insanity, just to be thorough
131   {
132     where => { -and => [ [ 'artistid' ], [ -and => [ artistid => { '!=', 69 }, artistid => undef, artistid => { '=' => 200 } ]], artistid => [], { -or => [] }, { -and => [] }, [ 'charfield' ], { name => [] }, 'rank' ] },
133     cc_result => { artistid => [ -and => undef, { '!=', 69 }, undef, 200, [] ], charfield => undef, name => [], rank => undef },
134     sql => 'WHERE artistid IS NULL AND artistid != ? AND artistid IS NULL AND artistid = ? AND 0=1 AND charfield IS NULL AND 0=1 AND rank IS NULL',
135     efcc_result => [qw( artistid )],
136   },
137
138   # original test from RT#93244
139   {
140     where => {
141       -and => [
142         \[
143           "LOWER(me.title) LIKE ?",
144           '%spoon%',
145         ],
146         [ { 'me.title' => 'Spoonful of bees' } ],
147     ]},
148     cc_result => {
149       '' => \[
150         "LOWER(me.title) LIKE ?",
151         '%spoon%',
152       ],
153       'me.title' => 'Spoonful of bees',
154     },
155     sql => 'WHERE LOWER(me.title) LIKE ? AND me.title = ?',
156     efcc_result => [qw( me.title )],
157   }
158 ) {
159
160   for my $w (
161     $t->{where},
162     [ -and => $t->{where} ],
163     ( keys %{$t->{where}} <= 1 ) ? [ %{$t->{where}} ] : ()
164   ) {
165     my $name = do { local ($Data::Dumper::Indent, $Data::Dumper::Terse, $Data::Dumper::Sortkeys) = (0, 1, 1); Dumper $w };
166
167     my @orig_sql_bind = $sm->where($w);
168
169     is_same_sql ( $orig_sql_bind[0], $t->{sql}, "Expected SQL from $name" )
170       if exists $t->{sql};
171
172     my $collapsed_cond = $schema->storage->_collapse_cond($w);
173
174     is_same_sql_bind(
175       \[ $sm->where($collapsed_cond) ],
176       \\@orig_sql_bind,
177       "Collapse did not alter final SQL based on $name",
178     );
179
180     is_deeply(
181       $collapsed_cond,
182       $t->{cc_result},
183       "Expected collapsed condition produced on $name",
184     );
185
186     is_deeply(
187       $schema->storage->_extract_fixed_condition_columns($w),
188       $t->{efcc_result},
189       "Expected fixed_condition produced on $name",
190     );
191   }
192 }
193
194 done_testing;