1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
|
use strict;
use warnings;
use Test::More;
use lib qw(t/lib);
use DBICTest ':DiffSQL';
my $schema = DBICTest::Schema->connect (DBICTest->_database, { quote_char => '`' });
# cheat
require DBIx::Class::Storage::DBI::mysql;
*DBIx::Class::Storage::DBI::mysql::_get_server_version = sub { 5 };
bless ( $schema->storage, 'DBIx::Class::Storage::DBI::mysql' );
# check that double-subqueries are properly wrapped
{
# the expected SQL may seem wastefully nonsensical - this is due to
# CD's tablename being \'cd', which triggers the "this can be anything"
# mode, and forces a subquery. This in turn forces *another* subquery
# because mysql is being mysql
# Also we know it will fail - never deployed. All we care about is the
# SQL to compare, hence the eval
$schema->is_executed_sql_bind( sub {
eval { $schema->resultset ('CD')->update({ genreid => undef }) }
},[[
'UPDATE cd SET `genreid` = ? WHERE `cdid` IN ( SELECT * FROM ( SELECT `me`.`cdid` FROM cd `me` ) `_forced_double_subquery` )',
[ { dbic_colname => "genreid", sqlt_datatype => "integer" } => undef ],
]], 'Correct update-SQL with double-wrapped subquery' );
# same comment as above
$schema->is_executed_sql_bind( sub {
eval { $schema->resultset ('CD')->delete }
}, [[
'DELETE FROM cd WHERE `cdid` IN ( SELECT * FROM ( SELECT `me`.`cdid` FROM cd `me` ) `_forced_double_subquery` )',
]], 'Correct delete-SQL with double-wrapped subquery' );
# and a couple of really contrived examples (we test them live in t/71mysql.t)
my $rs = $schema->resultset('Artist')->search({ name => { -like => 'baby_%' } });
my ($count_sql, @count_bind) = @${$rs->count_rs->as_query};
$schema->is_executed_sql_bind( sub {
eval {
$schema->resultset('Artist')->search(
{ artistid => {
-in => $rs->get_column('artistid')
->as_query
} },
)->update({ name => \[ "CONCAT( `name`, '_bell_out_of_', $count_sql )", @count_bind ] });
}
}, [[
q(
UPDATE `artist`
SET `name` = CONCAT(`name`, '_bell_out_of_', (
SELECT *
FROM (
SELECT COUNT( * )
FROM `artist` `me`
WHERE `name` LIKE ?
) `_forced_double_subquery`
))
WHERE
`artistid` IN (
SELECT *
FROM (
SELECT `me`.`artistid`
FROM `artist` `me`
WHERE `name` LIKE ?
) `_forced_double_subquery` )
),
( [ { dbic_colname => "name", sqlt_datatype => "varchar", sqlt_size => 100 }
=> 'baby_%' ]
) x 2
]]);
$schema->is_executed_sql_bind( sub {
eval {
$schema->resultset('CD')->search_related('artist',
{ 'artist.name' => { -like => 'baby_with_%' } }
)->delete
}
}, [[
q(
DELETE FROM `artist`
WHERE `artistid` IN (
SELECT *
FROM (
SELECT `artist`.`artistid`
FROM cd `me`
JOIN `artist` `artist`
ON `artist`.`artistid` = `me`.`artist`
WHERE `artist`.`name` LIKE ?
) `_forced_double_subquery`
)
),
[ { dbic_colname => "artist.name", sqlt_datatype => "varchar", sqlt_size => 100 }
=> 'baby_with_%' ],
]] );
}
# Test support for straight joins
{
my $cdsrc = $schema->source('CD');
my $artrel_info = $cdsrc->relationship_info ('artist');
$cdsrc->add_relationship(
'straight_artist',
$artrel_info->{class},
$artrel_info->{cond},
{ %{$artrel_info->{attrs}}, join_type => 'straight' },
);
is_same_sql_bind (
$cdsrc->resultset->search({}, { prefetch => 'straight_artist' })->as_query,
'(
SELECT `me`.`cdid`, `me`.`artist`, `me`.`title`, `me`.`year`, `me`.`genreid`, `me`.`single_track`,
`straight_artist`.`artistid`, `straight_artist`.`name`, `straight_artist`.`rank`, `straight_artist`.`charfield`
FROM cd `me`
STRAIGHT_JOIN `artist` `straight_artist` ON `straight_artist`.`artistid` = `me`.`artist`
)',
[],
'straight joins correctly supported for mysql'
);
}
# Test support for inner joins on mysql v3
for (
[ 3 => 'INNER JOIN' ],
[ 4 => 'JOIN' ],
) {
my ($ver, $join_op) = @$_;
# we do not care at this point if data is available, just do a reconnect cycle
# to clear the server version cache and then get a new maker
{
$schema->storage->disconnect;
$schema->storage->_sql_maker(undef);
no warnings 'redefine';
local *DBIx::Class::Storage::DBI::mysql::_get_server_version = sub { $ver };
$schema->storage->ensure_connected;
$schema->storage->sql_maker;
}
is_same_sql_bind (
$schema->resultset('CD')->search ({}, { prefetch => 'artist' })->as_query,
"(
SELECT `me`.`cdid`, `me`.`artist`, `me`.`title`, `me`.`year`, `me`.`genreid`, `me`.`single_track`,
`artist`.`artistid`, `artist`.`name`, `artist`.`rank`, `artist`.`charfield`
FROM cd `me`
$join_op `artist` `artist` ON `artist`.`artistid` = `me`.`artist`
)",
[],
"default join type works for version $ver",
);
}
done_testing;
|