From 3a55ee2f5e08dda91ae37ac72769abd629ae80a1 Mon Sep 17 00:00:00 2001 From: Eloy Lafuente Date: Wed, 17 Nov 2010 10:39:56 +0000 Subject: [PATCH] MDL-25268 dml - improved limitnum/limitfrom regexp in ms drivers + tests --- lib/dml/mssql_native_moodle_database.php | 4 ++-- lib/dml/simpletest/testdml.php | 19 +++++++++++++++++++ lib/dml/sqlsrv_native_moodle_database.php | 4 ++-- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/lib/dml/mssql_native_moodle_database.php b/lib/dml/mssql_native_moodle_database.php index d8123119631..884b3682317 100644 --- a/lib/dml/mssql_native_moodle_database.php +++ b/lib/dml/mssql_native_moodle_database.php @@ -686,8 +686,8 @@ class mssql_native_moodle_database extends moodle_database { if ($limitfrom or $limitnum) { if ($limitnum >= 1) { // Only apply TOP clause if we have any limitnum (limitfrom offset is handled later) $fetch = $limitfrom + $limitnum; - $sql = preg_replace('/^([\s(])*SELECT( DISTINCT)?(?!\s*TOP\s*\()/i', - "\\1SELECT\\2 TOP $fetch", $sql); + $sql = preg_replace('/^([\s(])*SELECT([\s]+)(DISTINCT|ALL)?(?!\s*TOP\s*\()/i', + "\\1SELECT\\2\\3 TOP $fetch", $sql); } } diff --git a/lib/dml/simpletest/testdml.php b/lib/dml/simpletest/testdml.php index 7514938da78..259f81a8354 100755 --- a/lib/dml/simpletest/testdml.php +++ b/lib/dml/simpletest/testdml.php @@ -3047,6 +3047,25 @@ class dml_test extends UnitTestCase { $DB->insert_record($tablename, array('course' => 5, 'content' => 'hello', 'name'=>'def')); $DB->insert_record($tablename, array('course' => 2, 'content' => 'universe', 'name'=>'abc')); + // test limits in queries with DISTINCT/ALL clauses and multiple whitespace. MDL-25268 + $sql = "SELECT DISTINCT course + FROM {{$tablename}} + ORDER BY course"; + // only limitfrom + $records = $DB->get_records_sql($sql, null, 1); + $this->assertEqual(2, count($records)); + $this->assertEqual(3, reset($records)->course); + $this->assertEqual(5, next($records)->course); + // only limitnum + $records = $DB->get_records_sql($sql, null, 0, 2); + $this->assertEqual(2, count($records)); + $this->assertEqual(2, reset($records)->course); + $this->assertEqual(3, next($records)->course); + // both limitfrom and limitnum + $records = $DB->get_records_sql($sql, null, 2, 2); + $this->assertEqual(1, count($records)); + $this->assertEqual(5, reset($records)->course); + // we have sql like this in moodle, this syntax breaks on older versions of sqlite for example.. $sql = "SELECT a.id AS id, a.course AS course FROM {{$tablename}} a diff --git a/lib/dml/sqlsrv_native_moodle_database.php b/lib/dml/sqlsrv_native_moodle_database.php index 60a2d1753e4..673bc0dcea6 100644 --- a/lib/dml/sqlsrv_native_moodle_database.php +++ b/lib/dml/sqlsrv_native_moodle_database.php @@ -778,8 +778,8 @@ class sqlsrv_native_moodle_database extends moodle_database { $offset = max(0, $offset); if ($limit > 0 && $offset == 0) { - $sql1 = preg_replace('/^([\s(])*SELECT( DISTINCT | ALL)?(?!\s*TOP\s*\()/i', - "\\1SELECT\\2 TOP $limit", $sql); + $sql1 = preg_replace('/^([\s(])*SELECT([\s]+)(DISTINCT|ALL)?(?!\s*TOP\s*\()/i', + "\\1SELECT\\2\\3 TOP $limit", $sql); } else { // Only apply TOP clause if we have any limitnum (limitfrom offset is handled later) if ($limit < 1) {