2341bd876a
If you had a report query that had a subquery in the fields list, and that subquery had a LIMIT specifier, then it would be removed which could break your query. This patch prevents this case from breaking by ensuring that only a LIMIT that follows the last WHERE in the query is removed. If you don't have a WHERE, then it will behave like it always did, removing all the cases of LIMIT (which would still break a subquery but this is a) more rare, and b) would require more intelligent parsing to deal with. Also adds test cases and function documentation. Signed-off-by: Nicole C. Engard <nengard@bywatersolutions.com> Tested with this report: select biblionumber, (select itemnumber from items where items.biblionumber=biblio.biblionumber LIMIT 1) from biblio where biblionumber<1000; and it worked like a charm Signed-off-by: Paul Poulain <paul.poulain@biblibre.com>
92 lines
3.7 KiB
Perl
92 lines
3.7 KiB
Perl
# Copyright 2012 Catalyst IT Ltd.
|
|
#
|
|
# This file is part of Koha.
|
|
#
|
|
# Koha is free software; you can redistribute it and/or modify it under the
|
|
# terms of the GNU General Public License as published by the Free Software
|
|
# Foundation; either version 2 of the License, or (at your option) any later
|
|
# version.
|
|
#
|
|
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License along
|
|
# with Koha; if not, write to the Free Software Foundation, Inc.,
|
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
use Test::More tests => 19; # last test to print
|
|
|
|
use_ok('C4::Reports::Guided');
|
|
|
|
# This is the query I found that triggered bug 8594.
|
|
my $sql = "SELECT aqorders.ordernumber, biblio.title, biblio.biblionumber, items.homebranch,
|
|
aqorders.entrydate, aqorders.datereceived,
|
|
(SELECT DATE(datetime) FROM statistics
|
|
WHERE itemnumber=items.itemnumber AND
|
|
(type='return' OR type='issue') LIMIT 1)
|
|
AS shelvedate,
|
|
DATEDIFF(COALESCE(
|
|
(SELECT DATE(datetime) FROM statistics
|
|
WHERE itemnumber=items.itemnumber AND
|
|
(type='return' OR type='issue') LIMIT 1),
|
|
aqorders.datereceived), aqorders.entrydate) AS totaldays
|
|
FROM aqorders
|
|
LEFT JOIN biblio USING (biblionumber)
|
|
LEFT JOIN items ON (items.biblionumber = biblio.biblionumber
|
|
AND dateaccessioned=aqorders.datereceived)
|
|
WHERE (entrydate >= '2011-01-01' AND (datereceived < '2011-02-01' OR datereceived IS NULL))
|
|
AND items.homebranch LIKE 'INFO'
|
|
ORDER BY title";
|
|
|
|
my ($res_sql, $res_lim1, $res_lim2) = C4::Reports::Guided::strip_limit($sql);
|
|
is($res_sql, $sql, "Not breaking subqueries");
|
|
is($res_lim1, 0, "Returns correct default offset");
|
|
is($res_lim2, undef, "Returns correct default LIMIT");
|
|
|
|
# Now the same thing, but we want it to remove the LIMIT from the end
|
|
|
|
my $test_sql = $res_sql . " LIMIT 242";
|
|
($res_sql, $res_lim1, $res_lim2) = C4::Reports::Guided::strip_limit($test_sql);
|
|
# The replacement drops a ' ' where the limit was
|
|
is(trim($res_sql), $sql, "Correctly removes only final LIMIT");
|
|
is($res_lim1, 0, "Returns correct default offset");
|
|
is($res_lim2, 242, "Returns correct extracted LIMIT");
|
|
|
|
$test_sql = $res_sql . " LIMIT 13,242";
|
|
($res_sql, $res_lim1, $res_lim2) = C4::Reports::Guided::strip_limit($test_sql);
|
|
# The replacement drops a ' ' where the limit was
|
|
is(trim($res_sql), $sql, "Correctly removes only final LIMIT (with offset)");
|
|
is($res_lim1, 13, "Returns correct extracted offset");
|
|
is($res_lim2, 242, "Returns correct extracted LIMIT");
|
|
|
|
# After here is the simpler case, where there isn't a WHERE clause to worry
|
|
# about.
|
|
|
|
# First case with nothing to change
|
|
$sql = "SELECT * FROM items";
|
|
($res_sql, $res_lim1, $res_lim2) = C4::Reports::Guided::strip_limit($sql);
|
|
is($res_sql, $sql, "Not breaking simple queries");
|
|
is($res_lim1, 0, "Returns correct default offset");
|
|
is($res_lim2, undef, "Returns correct default LIMIT");
|
|
|
|
$test_sql = $sql . " LIMIT 242";
|
|
($res_sql, $res_lim1, $res_lim2) = C4::Reports::Guided::strip_limit($test_sql);
|
|
is(trim($res_sql), $sql, "Correctly removes LIMIT in simple case");
|
|
is($res_lim1, 0, "Returns correct default offset");
|
|
is($res_lim2, 242, "Returns correct extracted LIMIT");
|
|
|
|
$test_sql = $sql . " LIMIT 13,242";
|
|
($res_sql, $res_lim1, $res_lim2) = C4::Reports::Guided::strip_limit($test_sql);
|
|
is(trim($res_sql), $sql, "Correctly removes LIMIT in simple case (with offset)");
|
|
is($res_lim1, 13, "Returns correct extracted offset");
|
|
is($res_lim2, 242, "Returns correct extracted LIMIT");
|
|
|
|
sub trim {
|
|
my ($s) = @_;
|
|
$s =~ s/^\s*(.*?)\s*$/$1/s;
|
|
return $s;
|
|
}
|