diff --git a/.gitignore b/.gitignore index 043eaf271..d1cf53e71 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,7 @@ phpdoc.xml docs/api docs/cache + +# PHPUnit +/.phpunit.cache +.phpunit.result.cache diff --git a/adodb-lib.inc.php b/adodb-lib.inc.php index 92e02df56..4c2668b26 100644 --- a/adodb-lib.inc.php +++ b/adodb-lib.inc.php @@ -27,34 +27,26 @@ global $ADODB_INCLUDED_LIB; $ADODB_INCLUDED_LIB = 1; +/** + * Strip the ORDER BY clause from the outer SELECT. + * + * @param string $sql + * + * @return string + */ function adodb_strip_order_by($sql) { - preg_match_all('/(\sORDER\s+BY\s(?:[^)](?!LIMIT))*)/is', $sql, $arr); - if ($arr) - { - $tmp = array_pop($arr); - $arr = [1=>array_pop($tmp)]; - } - if ($arr) - if (strpos($arr[1], '(') !== false) { - $at = strpos($sql, $arr[1]); - $cntin = 0; - for ($i=$at, $max=strlen($sql); $i < $max; $i++) { - $ch = $sql[$i]; - if ($ch == '(') { - $cntin += 1; - } elseif($ch == ')') { - $cntin -= 1; - if ($cntin < 0) { - break; - } - } - } - $sql = substr($sql,0,$at).substr($sql,$i); - } else { - $sql = str_replace($arr[1], '', $sql); + $num = preg_match_all('/(\sORDER\s+BY\s(?:[^)](?!LIMIT))*)/is', $sql, $matches, PREG_OFFSET_CAPTURE); + if ($num) { + // Get the last match + list($last_order_by, $offset) = array_pop($matches[1]); + + // If we find a ')' after the last order by, then it belongs to a + // sub-query, not the outer SQL statement and should not be stripped + if (strpos($sql, ')', $offset) === false) { + $sql = str_replace($last_order_by, '', $sql); } - + } return $sql; } diff --git a/adodb.inc.php b/adodb.inc.php index 718b7f096..cafef6751 100644 --- a/adodb.inc.php +++ b/adodb.inc.php @@ -3980,9 +3980,7 @@ function __construct($queryID,$mode=false) { } function __destruct() { - if($this->_queryID != -1) { - $this->Close(); - } + $this->Close(); } #[\ReturnTypeWillChange] diff --git a/docs/changelog.md b/docs/changelog.md index 516afb0be..605aeb789 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -28,11 +28,24 @@ Older changelogs: [#814](https://github.com/ADOdb/ADOdb/issues/814) +## [5.22.4] - Unreleased + +### Fixed + +- adodb_strip_order_by() throws deprecated warnings on PHP 8.1 + [#869](https://github.com/ADOdb/ADOdb/issues/869) +- adodb_strip_order_by() shouldn't strip clause from subqueries + [#870](https://github.com/ADOdb/ADOdb/issues/870) +- mysqli: Fix mysqli_result could not be converted to int + [#867](https://github.com/ADOdb/ADOdb/issues/867) + + ## [5.22.3] - 2022-09-06 ### Fixed - alterColumnSql() and changeTableSQL() produce different SQL + [#124](https://github.com/ADOdb/ADOdb/issues/124) [#383](https://github.com/ADOdb/ADOdb/issues/383) [#865](https://github.com/ADOdb/ADOdb/issues/865) - Fix PHP 8.1 deprecated warning in GetUpdateSQL() @@ -1328,6 +1341,7 @@ Released together with [v4.95](changelog_v4.x.md#495---17-may-2007) [5.23.0]: https://github.com/adodb/adodb/compare/v5.22.3...master +[5.22.4]: https://github.com/adodb/adodb/compare/v5.22.3...v5.22.4 [5.22.3]: https://github.com/adodb/adodb/compare/v5.22.2...v5.22.3 [5.22.2]: https://github.com/adodb/adodb/compare/v5.22.1...v5.22.2 [5.22.1]: https://github.com/adodb/adodb/compare/v5.22.0...v5.22.1 diff --git a/tests/LibTest.php b/tests/LibTest.php index 2f02e00e0..971dc6e62 100644 --- a/tests/LibTest.php +++ b/tests/LibTest.php @@ -39,6 +39,51 @@ public function setUp(): void $this->db = ADONewConnection('mysqli'); } + /** + * Test for {@see adodb_strip_order_by()} + * + * @dataProvider providerStripOrderBy + */ + public function testStripOrderBy($sql, $stripped): void + { + $this->assertSame($stripped, adodb_strip_order_by($sql)); + } + + /** + * Data provider for {@see testStripOrderBy()} + * + * @return array [SQL statement, SQL with ORDER BY clause stripped] + */ + public function providerStripOrderBy(): array + { + return [ + 'No order by clause' => [ + "SELECT name FROM table", + "SELECT name FROM table" + ], + 'Simple order by clause' => [ + "SELECT name FROM table ORDER BY name", + "SELECT name FROM table" + ], + 'Order by clause descending' => [ + "SELECT name FROM table ORDER BY name DESC", + "SELECT name FROM table" + ], + 'Order by clause with limit' => [ + "SELECT name FROM table ORDER BY name LIMIT 5", + "SELECT name FROM table LIMIT 5" + ], + 'Ordered Subquery with outer order by' => [ + "SELECT * FROM table WHERE name IN (SELECT TOP 5 name FROM table_b ORDER by name) ORDER BY name DESC", + "SELECT * FROM table WHERE name IN (SELECT TOP 5 name FROM table_b ORDER by name)" + ], + 'Ordered Subquery without outer order by' => [ + "SELECT * FROM table WHERE name IN (SELECT TOP 5 name FROM table_b ORDER by name)", + "SELECT * FROM table WHERE name IN (SELECT TOP 5 name FROM table_b ORDER by name)" + ], + ]; + } + /** * Test for {@see _adodb_quote_fieldname()} *