Deduplicate (and stabilize) the result of _collapse_cond
[dbsrgits/DBIx-Class.git] / t / search / stack_cond.t
diff --git a/t/search/stack_cond.t b/t/search/stack_cond.t
new file mode 100644 (file)
index 0000000..a68f692
--- /dev/null
@@ -0,0 +1,79 @@
+use strict;
+use warnings;
+
+use Test::More;
+use lib qw(t/lib);
+use DBICTest ':DiffSQL';
+use SQL::Abstract qw(is_plain_value is_literal_value);
+use List::Util 'shuffle';
+use Data::Dumper;
+$Data::Dumper::Terse = 1;
+$Data::Dumper::Useqq = 1;
+$Data::Dumper::Indent = 0;
+
+my $schema = DBICTest->init_schema();
+
+for my $c (
+  { cond => undef, sql => 'IS NULL' },
+  { cond => { -value => undef }, sql => 'IS NULL' },
+  { cond => \'foo', sql => '= foo' },
+  { cond => 'foo', sql => '= ?', bind => [
+    [ { dbic_colname => "title", sqlt_datatype => "varchar", sqlt_size => 100 } => 'foo' ],
+    [ { dbic_colname => "year", sqlt_datatype => "varchar", sqlt_size => 100 } => 'foo' ],
+  ]},
+  { cond => { -value => 'foo' }, sql => '= ?', bind => [
+    [ { dbic_colname => "title", sqlt_datatype => "varchar", sqlt_size => 100 } => 'foo' ],
+    [ { dbic_colname => "year", sqlt_datatype => "varchar", sqlt_size => 100 } => 'foo' ],
+  ]},
+  { cond => \[ '?', "foo" ], sql => '= ?', bind => [
+    [ {} => 'foo' ],
+    [ {} => 'foo' ],
+  ]},
+) {
+  my $rs = $schema->resultset('CD')->search({}, { columns => 'title' });
+
+  my $bare_cond = is_literal_value($c->{cond}) ? { '=', $c->{cond} } : $c->{cond};
+
+  my @query_steps = (
+    # this is a monkey-wrench, always there
+    { title => { '!=', [ -and => \'bar' ] }, year => { '!=', [ -and => 'bar' ] } },
+
+    { title => $bare_cond, year => { '=', $c->{cond} } },
+    { -and => [ year => $bare_cond, { title => { '=', $c->{cond} } } ] },
+    [ year => $bare_cond ],
+    [ title => $bare_cond ],
+    { -and => [ { year => { '=', $c->{cond} } }, { title => { '=', $c->{cond} } } ] },
+    { -and => { -or => { year => { '=', $c->{cond} } } }, -or => { title => $bare_cond } },
+  );
+
+  if (my $v = is_plain_value($c->{cond})) {
+    push @query_steps,
+      { year => $v->[0] },
+      { title => $v->[0] },
+      { -and => [ year => $v->[0], title => $v->[0] ] },
+    ;
+  }
+
+  @query_steps = shuffle @query_steps;
+
+  $rs = $rs->search($_) for @query_steps;
+
+  my @bind = @{$c->{bind} || []};
+  {
+    no warnings 'misc';
+    splice @bind, 1, 0, [ { dbic_colname => "year", sqlt_datatype => "varchar", sqlt_size => 100 } => 'bar' ];
+  }
+
+  is_same_sql_bind (
+    $rs->as_query,
+    "(
+      SELECT me.title
+        FROM cd me
+      WHERE title != bar AND title $c->{sql} AND year != ? AND year $c->{sql}
+    )",
+    \@bind,
+    'Double condition correctly collapsed for steps' . Dumper \@query_steps,
+  );
+}
+
+done_testing;