User tests: Successful: Unsuccessful:
Since Pdo driver has process limit in setQuery()
, we don't need to process it twice.
See https://github.com/joomla/joomla-cms/blob/staging/libraries/joomla/database/driver/pdo.php#L714
Open any Joomla page with pagination or rows limit in debug mode. You will see double LIMIT in SQL debug console if driver is pdomysql
, after this patch, the LIMIT keyword will only appear one.
Status | New | ⇒ | Pending |
Labels |
Added:
?
|
Category | ⇒ | SQL |
There is a case will make LIMIT appear 3 times. If someone try to override limit by setQuery()
with a query (object or string) which has set limit value. However this issue has exists a long time before this PR. see:
try
{
$db->setQuery($db->getQuery(true)->select('*')->from('#__content')->setLimit(20, 10), 100, 50)->execute();
}
catch (\Exception $e)
{
echo @end($db->getLog());
}
SELECT *
FROM fan_content LIMIT 10, 20 LIMIT 100, 50 LIMIT 100, 50
This PR can only remove the last 2 LIMIT which set by setQuery()
, but the first one which set from query object is still not overridable.
Here is a simple test of this PR:
$db = JFactory::getDbo();
// set string by setQuery()
$db->setQuery('SELECT * FROM #__content', 10, 20)->execute();
echo @end($db->getLog());
echo '<br>';
// set query object by setQuery()
$db->setQuery($db->getQuery(true)->select('*')->from('#__content'), 10, 20)->execute();
echo @end($db->getLog());
echo '<br>';
// set query object with limit
$db->setQuery($db->getQuery(true)->select('*')->from('#__content')->setLimit(20, 10))->execute();
echo @end($db->getLog());
echo '<br>';
// set query object and setQuery() both with limit
try
{
$db->setQuery($db->getQuery(true)->select('*')->from('#__content')->setLimit(20, 10), 100, 50)->execute();
}
catch (\Exception $e)
{
echo @end($db->getLog());
echo '<br>';
}
Before patch
SELECT * FROM fan_content LIMIT 10, 20 LIMIT 10, 20
SELECT * FROM fan_content LIMIT 10, 20 LIMIT 10, 20
SELECT * FROM fan_content LIMIT 10, 20
SELECT * FROM fan_content LIMIT 10, 20 LIMIT 100, 50 LIMIT 100, 50
After patch
SELECT * FROM fan_content LIMIT 10, 20
SELECT * FROM fan_content LIMIT 10, 20
SELECT * FROM fan_content LIMIT 10, 20
SELECT * FROM fan_content LIMIT 10, 20 LIMIT 100, 50
This is still an improvement but something in my gut tells me there's still something being handled incorrectly. I just can't figure out a way to deal with it.
I also think so, maybe we need unittest to make sure everything works correctly, this PR just a begining.
But I need more suggestion about how to continue work for this fix.
I have tested this item
I have tested it and patch removes the double LIMIT keyword from the SQL when using MySQL PDO driver.
Before Patch:
After Patch:
Category | SQL | ⇒ | SQL Unit Tests |
I have tested this item
Status | Pending | ⇒ | Ready to Commit |
Labels |
Added:
?
|
Category | SQL Unit Tests | ⇒ | Libraries |
Status | Ready to Commit | ⇒ | Fixed in Code Base |
Closed_Date | 0000-00-00 00:00:00 | ⇒ | 2016-09-05 18:14:20 |
Closed_By | ⇒ | rdeutz |
Labels |
Removed:
?
|
Something about this feels like a major code smell to me.
JDatabaseDriverPdo::setQuery()
ignores the limit and offset values that can be set in both the database driver and the query object and relies on values passed when you callsetQuery()
. Plus, this change doesn't account for the fact that casting a query object to string would still runproessLimit()
if values are set in the query object.Something definitely needs to be fixed, but at a first glance, this doesn't feel like the "right" fix.