Files
percona-toolkit/t/lib/TableNibbler.t
svetasmirnova 59b80afe93 PT-2156 - Fix tests for lib
- Impoved the fix for PT-2016, so it does not files with keys with USING keyword
- Added brackets to expression in lib/TableNibbler.pm, so it does not crap query wit many indexes with OR keyword
- Adjusted test t/lib/TableNibbler.t, so it reflects above chages
- Modified lib/Cxn.pm, so it has workaround for https://github.com/perl5-dbi/DBD-mysql/issues/306 , introduced in DBD::mysql 4.0.50
- Updated tests: added debugging code and cleanups
- Updated modules for tools
2023-03-17 19:50:50 +03:00

736 lines
29 KiB
Perl

#!/usr/bin/perl
BEGIN {
die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n"
unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH};
unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib";
};
use strict;
use warnings FATAL => 'all';
use English qw(-no_match_vars);
use Test::More tests => 26;
use TableParser;
use TableNibbler;
use Quoter;
use PerconaTest;
my $q = new Quoter();
my $tp = new TableParser(Quoter => $q);
my $n = new TableNibbler(
TableParser => $tp,
Quoter => $q,
);
my $t;
$t = $tp->parse( load_file('t/lib/samples/sakila.film.sql') );
is_deeply(
$n->generate_asc_stmt (
tbl_struct => $t,
cols => $t->{cols},
index => 'PRIMARY',
),
{
cols => [qw(film_id title description release_year language_id
original_language_id rental_duration rental_rate
length replacement_cost rating special_features
last_update)],
index => 'PRIMARY',
where => '((`film_id` >= ?))',
slice => [0],
scols => [qw(film_id)],
boundaries => {
'>=' => '((`film_id` >= ?))',
'>' => '((`film_id` > ?))',
'<=' => '((`film_id` <= ?))',
'<' => '((`film_id` < ?))',
},
},
'asc stmt on sakila.film',
);
is_deeply(
$n->generate_del_stmt (
tbl_struct => $t,
),
{
cols => [qw(film_id)],
index => 'PRIMARY',
where => '(`film_id` = ?)',
slice => [0],
scols => [qw(film_id)],
},
'del stmt on sakila.film',
);
is_deeply(
$n->generate_asc_stmt (
tbl_struct => $t,
index => 'PRIMARY',
),
{
cols => [qw(film_id title description release_year language_id
original_language_id rental_duration rental_rate
length replacement_cost rating special_features
last_update)],
index => 'PRIMARY',
where => '((`film_id` >= ?))',
slice => [0],
scols => [qw(film_id)],
boundaries => {
'>=' => '((`film_id` >= ?))',
'>' => '((`film_id` > ?))',
'<=' => '((`film_id` <= ?))',
'<' => '((`film_id` < ?))',
},
},
'defaults to all columns',
);
throws_ok(
sub {
$n->generate_asc_stmt (
tbl_struct => $t,
cols => $t->{cols},
index => 'title',
)
},
qr/Index 'title' does not exist in table/,
'Error on nonexistent index',
);
is_deeply(
$n->generate_asc_stmt (
tbl_struct => $t,
cols => $t->{cols},
index => 'idx_title',
),
{
cols => [qw(film_id title description release_year language_id
original_language_id rental_duration rental_rate
length replacement_cost rating special_features
last_update)],
index => 'idx_title',
where => '((`title` >= ?))',
slice => [1],
scols => [qw(title)],
boundaries => {
'>=' => '((`title` >= ?))',
'>' => '((`title` > ?))',
'<=' => '((`title` <= ?))',
'<' => '((`title` < ?))',
},
},
'asc stmt on sakila.film with different index',
);
is_deeply(
$n->generate_del_stmt (
tbl_struct => $t,
index => 'idx_title',
cols => [qw(film_id)],
),
{
cols => [qw(film_id title description release_year language_id original_language_id rental_duration rental_rate length replacement_cost rating special_features last_update)],
index => 'idx_title',
where => '(`film_id` = ? AND `title` = ? AND ((? IS NULL AND `description` IS NULL) OR (`description` = ?)) AND ((? IS NULL AND `release_year` IS NULL) OR (`release_year` = ?)) AND `language_id` = ? AND ((? IS NULL AND `original_language_id` IS NULL) OR (`original_language_id` = ?)) AND `rental_duration` = ? AND `rental_rate` = ? AND ((? IS NULL AND `length` IS NULL) OR (`length` = ?)) AND `replacement_cost` = ? AND ((? IS NULL AND `rating` IS NULL) OR (`rating` = ?)) AND ((? IS NULL AND `special_features` IS NULL) OR (`special_features` = ?)) AND `last_update` = ?)',
slice => [ 0, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 8, 8, 9, 10, 10, 11, 11, 12 ],
scols => [qw( film_id title description description release_year release_year language_id original_language_id original_language_id
rental_duration rental_rate length length replacement_cost rating rating special_features special_features last_update)],
},
'del stmt on sakila.film with different index and extra column',
);
# TableParser::find_best_index() is case-insensitive, returning the
# correct case even if the wrong case is given. But generate_asc_stmt()
# no longer calls find_best_index() so this test is a moot point.
is_deeply(
$n->generate_asc_stmt (
tbl_struct => $t,
cols => $t->{cols},
index => 'idx_title',
),
{
cols => [qw(film_id title description release_year language_id
original_language_id rental_duration rental_rate
length replacement_cost rating special_features
last_update)],
index => 'idx_title',
where => '((`title` >= ?))',
slice => [1],
scols => [qw(title)],
boundaries => {
'>=' => '((`title` >= ?))',
'>' => '((`title` > ?))',
'<=' => '((`title` <= ?))',
'<' => '((`title` < ?))',
},
},
'Index returned in correct lettercase',
);
is_deeply(
$n->generate_asc_stmt (
tbl_struct => $t,
cols => [qw(title)],
index => 'PRIMARY',
),
{
cols => [qw(title film_id)],
index => 'PRIMARY',
where => '((`film_id` >= ?))',
slice => [1],
scols => [qw(film_id)],
boundaries => {
'>=' => '((`film_id` >= ?))',
'>' => '((`film_id` > ?))',
'<=' => '((`film_id` <= ?))',
'<' => '((`film_id` < ?))',
},
},
'Required columns added to SELECT list',
);
# ##########################################################################
# Switch to the rental table
# ##########################################################################
$t = $tp->parse( load_file('t/lib/samples/sakila.rental.sql') );
is_deeply(
$n->generate_asc_stmt(
tbl_struct => $t,
cols => $t->{cols},
index => 'rental_date',
),
{
cols => [qw(rental_id rental_date inventory_id customer_id
return_date staff_id last_update)],
index => 'rental_date',
where => '((`rental_date` > ?) OR (`rental_date` = ? AND `inventory_id` > ?)'
. ' OR (`rental_date` = ? AND `inventory_id` = ? AND `customer_id` >= ?))',
slice => [1, 1, 2, 1, 2, 3],
scols => [qw(rental_date rental_date inventory_id rental_date inventory_id customer_id)],
boundaries => {
'>=' => '((`rental_date` > ?) OR (`rental_date` = ? AND '
. '`inventory_id` > ?) OR (`rental_date` = ? AND `inventory_id` '
. '= ? AND `customer_id` >= ?))',
'>' => '((`rental_date` > ?) OR (`rental_date` = ? AND '
. '`inventory_id` > ?) OR (`rental_date` = ? AND `inventory_id` '
. '= ? AND `customer_id` > ?))',
'<=' => '((`rental_date` < ?) OR (`rental_date` = ? AND '
. '`inventory_id` < ?) OR (`rental_date` = ? AND `inventory_id` '
. '= ? AND `customer_id` <= ?))',
'<' => '((`rental_date` < ?) OR (`rental_date` = ? AND '
. '`inventory_id` < ?) OR (`rental_date` = ? AND `inventory_id` '
. '= ? AND `customer_id` < ?))',
},
},
'Alternate index on sakila.rental',
);
is_deeply(
$n->generate_del_stmt (
tbl_struct => $t,
index => 'rental_date',
),
{
cols => [qw(rental_date inventory_id customer_id)],
index => 'rental_date',
where => '(`rental_date` = ? AND `inventory_id` = ? AND `customer_id` = ?)',
slice => [0, 1, 2],
scols => [qw(rental_date inventory_id customer_id)],
},
'Alternate index on sakila.rental delete statement',
);
# Check that I can select from one table and insert into another OK
my $f = $tp->parse( load_file('t/lib/samples/sakila.film.sql') );
is_deeply(
$n->generate_ins_stmt(
ins_tbl => $f,
sel_cols => $t->{cols},
),
{
cols => [qw(last_update)],
slice => [6],
},
'Generated an INSERT statement from film into rental',
);
my $sel_tbl = $tp->parse( load_file('t/lib/samples/issue_131_sel.sql') );
my $ins_tbl = $tp->parse( load_file('t/lib/samples/issue_131_ins.sql') );
is_deeply(
$n->generate_ins_stmt(
ins_tbl => $ins_tbl,
sel_cols => $sel_tbl->{cols},
),
{
cols => [qw(id name)],
slice => [0, 2],
},
'INSERT stmt with different col order and a missing ins col'
);
is_deeply(
$n->generate_asc_stmt(
tbl_struct => $t,
cols => $t->{cols},
index => 'rental_date',
asc_first => 1,
),
{
cols => [qw(rental_id rental_date inventory_id customer_id
return_date staff_id last_update)],
index => 'rental_date',
where => '((`rental_date` >= ?))',
slice => [1],
scols => [qw(rental_date)],
boundaries => {
'>=' => '((`rental_date` >= ?))',
'>' => '((`rental_date` > ?))',
'<=' => '((`rental_date` <= ?))',
'<' => '((`rental_date` < ?))',
},
},
'Alternate index with asc_first on sakila.rental',
);
is_deeply(
$n->generate_asc_stmt(
tbl_struct => $t,
cols => $t->{cols},
index => 'rental_date',
n_index_cols => 2,
),
{
cols => [qw(rental_id rental_date inventory_id customer_id
return_date staff_id last_update)],
index => 'rental_date',
where => '((`rental_date` > ?) OR (`rental_date` = ? AND `inventory_id` >= ?))',
slice => [qw(1 1 2)],
scols => [qw(rental_date rental_date inventory_id)],
boundaries => {
'<' =>
'((`rental_date` < ?) OR (`rental_date` = ? AND `inventory_id` < ?))',
'<=' =>
'((`rental_date` < ?) OR (`rental_date` = ? AND `inventory_id` <= ?))',
'>' =>
'((`rental_date` > ?) OR (`rental_date` = ? AND `inventory_id` > ?))',
'>=' =>
'((`rental_date` > ?) OR (`rental_date` = ? AND `inventory_id` >= ?))'
},
},
'Use only N left-most columns of the index',
);
is_deeply(
$n->generate_asc_stmt(
tbl_struct => $t,
cols => $t->{cols},
index => 'rental_date',
n_index_cols => 5,
),
{
cols => [qw(rental_id rental_date inventory_id customer_id
return_date staff_id last_update)],
index => 'rental_date',
where => '((`rental_date` > ?) OR (`rental_date` = ? AND `inventory_id` > ?)'
. ' OR (`rental_date` = ? AND `inventory_id` = ? AND `customer_id` >= ?))',
slice => [1, 1, 2, 1, 2, 3],
scols => [qw(rental_date rental_date inventory_id rental_date inventory_id customer_id)],
boundaries => {
'>=' => '((`rental_date` > ?) OR (`rental_date` = ? AND '
. '`inventory_id` > ?) OR (`rental_date` = ? AND `inventory_id` '
. '= ? AND `customer_id` >= ?))',
'>' => '((`rental_date` > ?) OR (`rental_date` = ? AND '
. '`inventory_id` > ?) OR (`rental_date` = ? AND `inventory_id` '
. '= ? AND `customer_id` > ?))',
'<=' => '((`rental_date` < ?) OR (`rental_date` = ? AND '
. '`inventory_id` < ?) OR (`rental_date` = ? AND `inventory_id` '
. '= ? AND `customer_id` <= ?))',
'<' => '((`rental_date` < ?) OR (`rental_date` = ? AND '
. '`inventory_id` < ?) OR (`rental_date` = ? AND `inventory_id` '
. '= ? AND `customer_id` < ?))',
},
},
"Don't crash if N > number of index columns"
);
is_deeply(
$n->generate_asc_stmt(
tbl_struct => $t,
cols => $t->{cols},
index => 'rental_date',
asc_only => 1,
),
{
cols => [qw(rental_id rental_date inventory_id customer_id
return_date staff_id last_update)],
index => 'rental_date',
where => '((`rental_date` > ?) OR (`rental_date` = ? AND `inventory_id` > ?)'
. ' OR (`rental_date` = ? AND `inventory_id` = ? AND `customer_id` > ?))',
slice => [1, 1, 2, 1, 2, 3],
scols => [qw(rental_date rental_date inventory_id rental_date inventory_id customer_id)],
boundaries => {
'>=' => '((`rental_date` > ?) OR (`rental_date` = ? AND '
. '`inventory_id` > ?) OR (`rental_date` = ? AND `inventory_id` '
. '= ? AND `customer_id` >= ?))',
'>' => '((`rental_date` > ?) OR (`rental_date` = ? AND '
. '`inventory_id` > ?) OR (`rental_date` = ? AND `inventory_id` '
. '= ? AND `customer_id` > ?))',
'<=' => '((`rental_date` < ?) OR (`rental_date` = ? AND '
. '`inventory_id` < ?) OR (`rental_date` = ? AND `inventory_id` '
. '= ? AND `customer_id` <= ?))',
'<' => '((`rental_date` < ?) OR (`rental_date` = ? AND '
. '`inventory_id` < ?) OR (`rental_date` = ? AND `inventory_id` '
. '= ? AND `customer_id` < ?))',
},
},
'Alternate index on sakila.rental with strict ascending',
);
# ##########################################################################
# Switch to the rental table with customer_id nullable
# ##########################################################################
$t = $tp->parse( load_file('t/lib/samples/sakila.rental.null.sql') );
is_deeply(
$n->generate_asc_stmt(
tbl_struct => $t,
cols => $t->{cols},
index => 'rental_date',
),
{
cols => [qw(rental_id rental_date inventory_id customer_id
return_date staff_id last_update)],
index => 'rental_date',
where => '((`rental_date` > ?) OR (`rental_date` = ? AND `inventory_id` > ?)'
. ' OR (`rental_date` = ? AND `inventory_id` = ? AND '
. '(? IS NULL OR `customer_id` >= ?)))',
slice => [1, 1, 2, 1, 2, 3, 3],
scols => [qw(rental_date rental_date inventory_id rental_date inventory_id customer_id customer_id)],
boundaries => {
'>=' => '((`rental_date` > ?) OR (`rental_date` = ? AND '
. '`inventory_id` > ?) OR (`rental_date` = ? AND `inventory_id` '
. '= ? AND (? IS NULL OR `customer_id` >= ?)))',
'>' => '((`rental_date` > ?) OR (`rental_date` = ? AND `inventory_id` > ?) OR '
. '(`rental_date` = ? AND `inventory_id` = ? AND ((? IS NULL AND `customer_id` IS NOT NULL) '
. 'OR (`customer_id` > ?))))',
# '((`rental_date` > ?) OR (`rental_date` = ? AND '
#. '`inventory_id` > ?) OR (`rental_date` = ? AND `inventory_id` '
# . '= ? AND ((? IS NULL AND `customer_id` IS NOT NULL) '
# . 'OR (`customer_id` > ?))))',
'<=' => '((`rental_date` < ?) OR (`rental_date` = ? AND '
. '`inventory_id` < ?) OR (`rental_date` = ? AND `inventory_id` '
. '= ? AND (? IS NULL OR `customer_id` <= ?)))',
'<' => '((`rental_date` < ?) OR (`rental_date` = ? AND `inventory_id` < ?) OR '
. '((? IS NOT NULL AND `customer_id` IS NULL) OR (`customer_id` < ?)) OR '
. '(`rental_date` = ? AND `inventory_id` = ?))',
# '((`rental_date` < ?) OR (`rental_date` = ? AND '
#. '`inventory_id` < ?) OR (`rental_date` = ? AND `inventory_id` '
#. '= ? AND ((? IS NOT NULL AND `customer_id` IS NULL) '
#. 'OR (`customer_id` < ?))))',
},
},
'Alternate index on sakila.rental with nullable customer_id',
);
is_deeply(
$n->generate_del_stmt (
tbl_struct => $t,
index => 'rental_date',
),
{
cols => [qw(rental_date inventory_id customer_id)],
index => 'rental_date',
where => '(`rental_date` = ? AND `inventory_id` = ? AND '
. '((? IS NULL AND `customer_id` IS NULL) OR (`customer_id` = ?)))',
slice => [0, 1, 2, 2],
scols => [qw(rental_date inventory_id customer_id customer_id)],
},
'Alternate index on sakila.rental delete statement with nullable customer_id',
);
is_deeply(
$n->generate_asc_stmt(
tbl_struct => $t,
cols => $t->{cols},
index => 'rental_date',
asc_only => 1,
),
{
cols => [qw(rental_id rental_date inventory_id customer_id
return_date staff_id last_update)],
index => 'rental_date',
where => '((`rental_date` > ?) OR (`rental_date` = ? AND `inventory_id` > ?) OR '
. '(`rental_date` = ? AND `inventory_id` = ? AND ((? IS NULL AND `customer_id` IS NOT NULL) '
. 'OR (`customer_id` > ?))))',
# '((`rental_date` > ?) OR (`rental_date` = ? AND `inventory_id` > ?)'
#. ' OR (`rental_date` = ? AND `inventory_id` = ? AND '
#. '((? IS NULL AND `customer_id` IS NOT NULL) OR (`customer_id` > ?))))',
slice => [1, 1, 2, 1, 2, 3, 3],
scols => [qw(rental_date rental_date inventory_id rental_date inventory_id customer_id customer_id)],
boundaries => {
'>=' => '((`rental_date` > ?) OR (`rental_date` = ? AND '
. '`inventory_id` > ?) OR (`rental_date` = ? AND `inventory_id` '
. '= ? AND (? IS NULL OR `customer_id` >= ?)))',
'>' => '((`rental_date` > ?) OR (`rental_date` = ? AND `inventory_id` > ?) OR '
. '(`rental_date` = ? AND `inventory_id` = ? AND ((? IS NULL AND `customer_id` IS NOT NULL) OR '
. '(`customer_id` > ?))))',
# '((`rental_date` > ?) OR (`rental_date` = ? AND '
#. '`inventory_id` > ?) OR (`rental_date` = ? AND `inventory_id` '
#. '= ? AND ((? IS NULL AND `customer_id` IS NOT NULL) '
#. 'OR (`customer_id` > ?))))',
'<=' => '((`rental_date` < ?) OR (`rental_date` = ? AND '
. '`inventory_id` < ?) OR (`rental_date` = ? AND `inventory_id` '
. '= ? AND (? IS NULL OR `customer_id` <= ?)))',
'<' => '((`rental_date` < ?) OR (`rental_date` = ? AND `inventory_id` < ?) OR '
. '((? IS NOT NULL AND `customer_id` IS NULL) OR (`customer_id` < ?)) OR '
. '(`rental_date` = ? AND `inventory_id` = ?))',
# '((`rental_date` < ?) OR (`rental_date` = ? AND '
#. '`inventory_id` < ?) OR (`rental_date` = ? AND `inventory_id` '
#. '= ? AND ((? IS NOT NULL AND `customer_id` IS NULL) '
#. 'OR (`customer_id` < ?))))',
},
},
'Alternate index on sakila.rental with nullable customer_id and strict ascending',
);
# ##########################################################################
# Switch to the rental table with inventory_id nullable
# ##########################################################################
$t = $tp->parse( load_file('t/lib/samples/sakila.rental.null2.sql') );
is_deeply(
$n->generate_asc_stmt(
tbl_struct => $t,
cols => $t->{cols},
index => 'rental_date',
),
{
cols => [qw(rental_id rental_date inventory_id customer_id
return_date staff_id last_update)],
index => 'rental_date',
where => '((`rental_date` > ?) OR (`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NOT NULL)'
. ' OR (`inventory_id` > ?))) OR (`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NULL) OR '
. '(`inventory_id` = ?)) AND `customer_id` >= ?))',
# '((`rental_date` > ?) OR '
#. '(`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NOT NULL) OR (`inventory_id` > ?)))'
#. ' OR (`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NULL) '
#. 'OR (`inventory_id` = ?)) AND `customer_id` >= ?))',
slice => [1, 1, 2, 2, 1, 2, 2, 3],
scols => [qw(rental_date rental_date inventory_id inventory_id
rental_date inventory_id inventory_id customer_id)],
boundaries => {
'>=' => '((`rental_date` > ?) OR (`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NOT NULL) OR '
. '(`inventory_id` > ?))) OR (`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NULL) OR '
. '(`inventory_id` = ?)) AND `customer_id` >= ?))',
# '((`rental_date` > ?) OR (`rental_date` = ? AND '
#. '((? IS NULL AND `inventory_id` IS NOT NULL) OR (`inventory_id` '
#. '> ?))) OR (`rental_date` = ? AND ((? IS NULL AND `inventory_id` '
#. 'IS NULL) OR (`inventory_id` = ?)) AND `customer_id` >= ?))',
'>' => '((`rental_date` > ?) OR (`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NOT NULL) OR '
. '(`inventory_id` > ?))) OR (`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NULL) OR '
. '(`inventory_id` = ?)) AND `customer_id` > ?))',
# '((`rental_date` > ?) OR (`rental_date` = ? AND ((? IS NULL '
#. 'AND `inventory_id` IS NOT NULL) OR (`inventory_id` > ?))) OR '
#. '(`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NULL) '
#. 'OR (`inventory_id` = ?)) AND `customer_id` > ?))',
'<=' => '((`rental_date` < ?) OR ((? IS NOT NULL AND `inventory_id` IS NULL) OR (`inventory_id` < ?)) '
. 'OR (`rental_date` = ?) OR (`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NULL) OR '
. '(`inventory_id` = ?)) AND `customer_id` <= ?))',
# '((`rental_date` < ?) OR (`rental_date` = ? AND ((? IS NOT '
#. 'NULL AND `inventory_id` IS NULL) OR (`inventory_id` < ?))) OR '
#. '(`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NULL) '
#. 'OR (`inventory_id` = ?)) AND `customer_id` <= ?))',
'<' => '((`rental_date` < ?) OR ((? IS NOT NULL AND `inventory_id` IS NULL) OR (`inventory_id` < ?)) '
. 'OR (`rental_date` = ?) OR (`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NULL) OR '
. '(`inventory_id` = ?)) AND `customer_id` < ?))',
# '((`rental_date` < ?) OR (`rental_date` = ? AND ((? IS NOT '
#. 'NULL AND `inventory_id` IS NULL) OR (`inventory_id` < ?))) '
#. 'OR (`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS '
#. 'NULL) OR (`inventory_id` = ?)) AND `customer_id` < ?))',
},
},
'Alternate index on sakila.rental with nullable inventory_id',
);
is_deeply(
$n->generate_asc_stmt(
tbl_struct => $t,
cols => $t->{cols},
index => 'rental_date',
asc_only => 1,
),
{
cols => [qw(rental_id rental_date inventory_id customer_id
return_date staff_id last_update)],
index => 'rental_date',
where => '((`rental_date` > ?) OR (`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NOT NULL) OR '
. '(`inventory_id` > ?))) OR (`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NULL) OR '
. '(`inventory_id` = ?)) AND `customer_id` > ?))',
# '((`rental_date` > ?) OR '
#. '(`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NOT NULL) OR (`inventory_id` > ?)))'
#. ' OR (`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NULL) '
#. 'OR (`inventory_id` = ?)) AND `customer_id` > ?))',
slice => [1, 1, 2, 2, 1, 2, 2, 3],
scols => [qw(rental_date rental_date inventory_id inventory_id
rental_date inventory_id inventory_id customer_id)],
boundaries => {
'>=' => '((`rental_date` > ?) OR (`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NOT NULL) OR '
. '(`inventory_id` > ?))) OR (`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NULL) OR '
. '(`inventory_id` = ?)) AND `customer_id` >= ?))',
# '((`rental_date` > ?) OR (`rental_date` = ? AND '
#. '((? IS NULL AND `inventory_id` IS NOT NULL) OR (`inventory_id` '
#. '> ?))) OR (`rental_date` = ? AND ((? IS NULL AND `inventory_id` '
#. 'IS NULL) OR (`inventory_id` = ?)) AND `customer_id` >= ?))',
'>' => '((`rental_date` > ?) OR (`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NOT NULL) OR '
. '(`inventory_id` > ?))) OR (`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NULL) OR '
. '(`inventory_id` = ?)) AND `customer_id` > ?))',
# '((`rental_date` > ?) OR (`rental_date` = ? AND ((? IS NULL '
#. 'AND `inventory_id` IS NOT NULL) OR (`inventory_id` > ?))) OR '
#. '(`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NULL) '
#. 'OR (`inventory_id` = ?)) AND `customer_id` > ?))',
'<=' => '((`rental_date` < ?) OR ((? IS NOT NULL AND `inventory_id` IS NULL) OR (`inventory_id` < ?)) OR '
. '(`rental_date` = ?) OR (`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NULL) OR '
. '(`inventory_id` = ?)) AND `customer_id` <= ?))',
# '((`rental_date` < ?) OR (`rental_date` = ? AND ((? IS NOT '
#. 'NULL AND `inventory_id` IS NULL) OR (`inventory_id` < ?))) OR '
#. '(`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NULL) '
#. 'OR (`inventory_id` = ?)) AND `customer_id` <= ?))',
'<' => '((`rental_date` < ?) OR ((? IS NOT NULL AND `inventory_id` IS NULL) OR (`inventory_id` < ?)) OR '
. '(`rental_date` = ?) OR (`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NULL) OR '
. '(`inventory_id` = ?)) AND `customer_id` < ?))',
#'((`rental_date` < ?) OR (`rental_date` = ? AND ((? IS NOT '
#. 'NULL AND `inventory_id` IS NULL) OR (`inventory_id` < ?))) '
#. 'OR (`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS '
#. 'NULL) OR (`inventory_id` = ?)) AND `customer_id` < ?))',
},
},
'Alternate index on sakila.rental with nullable inventory_id and strict ascending',
);
# ##########################################################################
# Switch to the rental table with cols in a different order.
# ##########################################################################
$t = $tp->parse( load_file('t/lib/samples/sakila.rental.remix.sql') );
is_deeply(
$n->generate_asc_stmt(
tbl_struct => $t,
index => 'rental_date',
),
{
cols => [qw(rental_id rental_date customer_id inventory_id
return_date staff_id last_update)],
index => 'rental_date',
where => '((`rental_date` > ?) OR (`rental_date` = ? AND `inventory_id` > ?)'
. ' OR (`rental_date` = ? AND `inventory_id` = ? AND `customer_id` >= ?))',
slice => [1, 1, 3, 1, 3, 2],
scols => [qw(rental_date rental_date inventory_id rental_date inventory_id customer_id)],
boundaries => {
'>=' => '((`rental_date` > ?) OR (`rental_date` = ? AND '
. '`inventory_id` > ?) OR (`rental_date` = ? AND `inventory_id` '
. '= ? AND `customer_id` >= ?))',
'>' => '((`rental_date` > ?) OR (`rental_date` = ? AND '
. '`inventory_id` > ?) OR (`rental_date` = ? AND `inventory_id` '
. '= ? AND `customer_id` > ?))',
'<=' => '((`rental_date` < ?) OR (`rental_date` = ? AND '
. '`inventory_id` < ?) OR (`rental_date` = ? AND `inventory_id` '
. '= ? AND `customer_id` <= ?))',
'<' => '((`rental_date` < ?) OR (`rental_date` = ? AND '
. '`inventory_id` < ?) OR (`rental_date` = ? AND `inventory_id` '
. '= ? AND `customer_id` < ?))',
},
},
'Out-of-order index on sakila.rental',
);
# ##########################################################################
# Switch to table without any indexes
# ##########################################################################
$t = $tp->parse( load_file('t/lib/samples/t1.sql') );
# This test is no longer needed because TableSyncNibble shouldn't
# ask TableNibbler to asc an indexless table.
# throws_ok(
# sub {
# $n->generate_asc_stmt (
# tbl_struct => $t,
# )
# },
# qr/Cannot find an ascendable index in table/,
# 'Error when no good index',
# );
is_deeply(
$n->generate_cmp_where(
cols => [qw(a b c d)],
slice => [0, 3],
is_nullable => {},
type => '>=',
),
{
scols => [qw(a a d)],
slice => [0, 0, 3],
where => '((`a` > ?) OR (`a` = ? AND `d` >= ?))',
},
'WHERE for >=',
);
is_deeply(
$n->generate_cmp_where(
cols => [qw(a b c d)],
slice => [0, 3],
is_nullable => {},
type => '>',
),
{
scols => [qw(a a d)],
slice => [0, 0, 3],
where => '((`a` > ?) OR (`a` = ? AND `d` > ?))',
},
'WHERE for >',
);
is_deeply(
$n->generate_cmp_where(
cols => [qw(a b c d)],
slice => [0, 3],
is_nullable => {},
type => '<=',
),
{
scols => [qw(a a d)],
slice => [0, 0, 3],
where => '((`a` < ?) OR (`a` = ? AND `d` <= ?))',
},
'WHERE for <=',
);
is_deeply(
$n->generate_cmp_where(
cols => [qw(a b c d)],
slice => [0, 3],
is_nullable => {},
type => '<',
),
{
scols => [qw(a a d)],
slice => [0, 0, 3],
where => '((`a` < ?) OR (`a` = ? AND `d` < ?))',
},
'WHERE for <',
);
# #############################################################################
# Done.
# #############################################################################
exit;