-
-
Notifications
You must be signed in to change notification settings - Fork 212
[RTM] Quote reserved words in database queries #8813
Conversation
I have a semi-automated way (creating split branches and then rebasing), so you don't have to do it by hand. But are the code changes actually the same in Contao 3 and Contao 4?
|
Most of them are the same. The |
Sadly this is not how it works. I can only create the split branches after the PR has been merged into Contao 3.5 and a new version has been tagged. So I guess we have to do it manually. 😢 |
K, I do it :) |
Thank you very much. |
Description ----------- This is the port of contao/core#8813. Also see #1106 and contao/installation-bundle#70 Commits ------- 84c4746 Quote reserved words in database queries 7bf64b1 Use static instead of \Database as self-reference.
Before merging this we should check if this fix needs to be applied here as well (I think it does): |
Yes, I think so. Needs to be applied in both Mysql.php and Mysqli.php. |
And this one as well: contao/core-bundle@541a8ca |
Unfortunately, there are even more problems. Sometimes the identifier is not a column but an expression such as Of course we could add something like this: // Not an identifier
if (!preg_match('/^[a-z0-9_$.]+$/', $strName))
{
return $strName;
} However this would leave the column names inside the EDIT: The regex should be |
@contao/developers I don't think that quoting identifiers is the correct solution as it leads to unforeseen issues. We have to discuss this topic again. I am going to revert the changes in Contao 4.4.11 meanwhile. |
I still think quoting identifiers is the right solution and your fix with the regular expression is correct. Although we should allow uppercase letters too:
Which is correct IMO. If you as a developer pass such a string to the model you have to do the quoting yourself, because you are passing an SQL expression and not a column name. |
Apparently the dollar sign is a permitted character in an unquoted identifier: |
From release announce: 4.4.9 (2017/12/14) * Fixes several minor PHP 7.2 related issues. 4.4.10 (2017/12/27) * Fixes a few minor issues including a problem with the comments bundle. 4.4.11 (2017/12/28) * Reverts the identifier quoting changes. MySQL 8 and MariaDB 10.2 In MySQL 8.0.2 and MariaDB 10.2.7 rows has been added as reserved word. Since we are using a field named rows in the tl_layout table, Contao is no longer compatible with the mentioned database versions. To avoid renaming the field in Contao and potentially causing theme import issues, we have added identifier quoting in version 4.4.10(*1). Unfortunately this led to several unforeseen problems(*2), so we had to revert the changes in version 4.4.11. (*1) contao/core-bundle#1262 (*2) contao/core#8813 (comment) 4.4.12 (2018/1/3) * Optimizes adding pages to the search index and fixes a few minor issues.
@ausi the PR also needs (if get recontinued) to take the creation into account: creating a new layout will otherwise not works because of the There is also another issue regarding mariadb, will create an issue for it in core-bundle |
@DanielSchwiperich The set method is already handled, see https://github.com/contao/core/pull/8813/files#diff-a715adcad847fd730a703866083b4ae5R200 |
As discussed in Mumble on January 18th, 2018, we want to merge this with the changes from contao/core-bundle@4de1d20 and contao/core-bundle@541a8ca. |
And add the regex check |
I looked again and think we must not include the |
What if it is |
Same as with |
Ok. I wonder if the method should be called |
No, seems reasonable 👍 |
{ | ||
if (in_array(strtolower($strName), array('rows'), true)) | ||
if ($strName == 'rows') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@leofeyer why did you remove the strtolower()
?
This would make it no longer work for Rows
or ROWS
.
// The identifier is quoted already
if (strncmp($strName, '`', 1) === 0)
{
return $strName;
}
// Not an identifier
if (!preg_match('/^[A-Za-z0-9_$]+$/', $strName))
{
return $strName;
} This is actually only required in Contao 4.4 as we are only quoting |
@@ -95,7 +95,10 @@ protected function get_error() | |||
*/ | |||
protected function find_in_set($strKey, $varSet, $blnIsField=false) | |||
{ | |||
$strKey = \Database::quoteIdentifier($strKey); | |||
if (preg_match('/^[A-Za-z0-9_$]+$/', $strKey)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check is not necessary as it is handled by quoteIdentifier()
itself.
@@ -85,7 +85,10 @@ protected function get_error() | |||
*/ | |||
protected function find_in_set($strKey, $varSet, $blnIsField=false) | |||
{ | |||
$strKey = \Database::quoteIdentifier($strKey); | |||
if (preg_match('/^[A-Za-z0-9_$]+$/', $strKey)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
Thank you @ausi. |
@@ -95,6 +95,8 @@ protected function get_error() | |||
*/ | |||
protected function find_in_set($strKey, $varSet, $blnIsField=false) | |||
{ | |||
$strKey = static::quoteIdentifier($strKey); | |||
|
|||
if ($blnIsField) | |||
{ | |||
return "FIND_IN_SET(" . $strKey . ", " . $varSet . ")"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case we should probably use "FIND_IN_SET(" . $strKey . ", " . static::quoteIdentifier($varSet) . ")";
because $varSet
is then an identifier too.
@@ -85,6 +85,8 @@ protected function get_error() | |||
*/ | |||
protected function find_in_set($strKey, $varSet, $blnIsField=false) | |||
{ | |||
$strKey = static::quoteIdentifier($strKey); | |||
|
|||
if ($blnIsField) | |||
{ | |||
return "FIND_IN_SET(" . $strKey . ", " . $varSet . ")"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
As discussed in contao/core-bundle#1106 and the Contao Mumble call, we want to escape all column names that are reserved keywords.
In Contao 4 we will use
\System::getContainer()->get('connection')->getDatabasePlatform()->quoteSingleIdentifier($name);
. In Contao 3.5 (this pull request) we only quoterows
.There is no need to fix the install tool in 3.5, as it uses quoted column names already.
@leofeyer Do you have an automated workflow to port this pull request to Contao 4.4, or should I do it by hand?