#
# test range scan bounds
# output to mysql-test/t/ndb_range_bounds.test
#
# give option --all to generate all cases
#

use strict;
use integer;
use Getopt::Long;

my $opt_all = 0;
my $opt_cnt = 5;
GetOptions("all" => \$opt_all, "cnt=i" => \$opt_cnt)
  or die "options are:  --all --cnt=N";

my $table = 't';

print <<EOF;
--source include/have_ndb.inc

--disable_warnings
drop table if exists $table;
--enable_warnings

# test range scan bounds
# generated by mysql-test/ndb/ndb_range_bounds.pl
# all selects must return 0

EOF

sub cut ($$@) {
  my($op, $key, @v) = @_;
  $op = '==' if $op eq '=';
  my(@w);
  eval "\@w = grep(\$_ $op $key, \@v)";
  $@ and die $@;
  return @w;
}

sub mkdummy (\@) {
  my ($val) = @_;
  return {
    'dummy' => 1,
    'exp' => '9 = 9',
    'cnt' => scalar @$val,
  };
}

sub mkone ($$$\@) {
  my($col, $op, $key, $val) = @_;
  my $cnt = scalar cut($op, $key, @$val);
  return {
    'exp' => "$col $op $key",
    'cnt' => $cnt,
  };
}

sub mktwo ($$$$$\@) {
  my($col, $op1, $key1, $op2, $key2, $val) = @_;
  my $cnt = scalar cut($op2, $key2, cut($op1, $key1, @$val));
  return {
    'exp' => "$col $op1 $key1 and $col $op2 $key2",
    'cnt' => $cnt,
  };
}

sub mkall ($$$\@) {
  my($col, $key1, $key2, $val) = @_;
  my @a = ();
  my $p = mkdummy(@$val);
  push(@a, $p) if $opt_all;
  my @ops = qw(< <= = >= >);
  for my $op (@ops) {
    my $p = mkone($col, $op, $key1, @$val);
    push(@a, $p) if $opt_all || $p->{cnt} != 0;
  }
  my @ops1 = $opt_all ? @ops : qw(= >= >);
  my @ops2 = $opt_all ? @ops : qw(<= <);
  for my $op1 (@ops1) {
    for my $op2 (@ops2) {
      my $p = mktwo($col, $op1, $key1, $op2, $key2, @$val);
      push(@a, $p) if $opt_all || $p->{cnt} != 0;
    }
  }
  return \@a;
}

for my $nn ("bcd", "") {
  my %nn;
  for my $x (qw(b c d)) {
    $nn{$x} = $nn =~ /$x/ ? "not null" : "null";
  }
  print <<EOF;
create table $table (
  a int primary key,
  b int $nn{b},
  c int $nn{c},
  d int $nn{d},
  index (b, c, d)
) engine=ndb;
EOF
  my @val = (0..($opt_cnt-1));
  my $v0 = 0;
  for my $v1 (@val) {
    for my $v2 (@val) {
      for my $v3 (@val) {
	print "insert into $table values($v0, $v1, $v2, $v3);\n";
	$v0++;
      }
    }
  }
  my $key1 = 1;
  my $key2 = 3;
  my $a1 = mkall('b', $key1, $key2, @val);
  my $a2 = mkall('c', $key1, $key2, @val);
  my $a3 = mkall('d', $key1, $key2, @val);
  for my $p1 (@$a1) {
    my $cnt1 = $p1->{cnt} * @val * @val;
    print "select count(*) - $cnt1 from $table";
    print " where $p1->{exp};\n";
    for my $p2 (@$a2) {
      my $cnt2 = $p1->{cnt} * $p2->{cnt} * @val;
      print "select count(*) - $cnt2 from $table";
      print " where $p1->{exp} and $p2->{exp};\n";
      for my $p3 (@$a3) {
	my $cnt3 = $p1->{cnt} * $p2->{cnt} * $p3->{cnt};
	print "select count(*) - $cnt3 from $table";
	print " where $p1->{exp} and $p2->{exp} and $p3->{exp};\n";
      }
    }
  }
  print <<EOF;
drop table $table;
EOF
}

# vim: set sw=2:
