Ensured parametrised queries respect data types#39
Ensured parametrised queries respect data types#39Mr-Kaos wants to merge 1 commit intoelvanto:masterfrom
Conversation
|
Just realised that if a numeric string is given, it will always ascertain as is_numeric, which will likely cause issues for string-based parameters that could take a numeric string. This will need to be corrected. |
Did some tests, and it seems MySQL does not have a problem with numeric values being passed as strings into a procedure. However, I am not sure how this will fare in other database languages. At the very least, this ensures that bit-typed parameters work: foreach ($this->positionalParams as $value) {
switch (true) {
case is_bool($value):
$pdoStatement->bindValue($i, $value, PDO::PARAM_BOOL);
break;
default:
$pdoStatement->bindValue($i, $value, PDO::PARAM_STR);
}
$i++;
}
foreach ($this->namedParams as $name => $value) {
switch (true) {
case is_bool($value):
$pdoStatement->bindValue($name, $value, PDO::PARAM_BOOL);
break;
default:
$pdoStatement->bindValue($name, $value, PDO::PARAM_STR);
}
} |
joshmcrae
left a comment
There was a problem hiding this comment.
Looks good if we make a slight modification.
I'm thinking this will need to be a breaking change.
| foreach ($this->positionalParams as $value) { | ||
| $pdoStatement->bindValue($i, $value, PDO::PARAM_STR); | ||
| switch (true) { | ||
| case is_numeric($value): |
There was a problem hiding this comment.
is_numeric will return true if:
- Value is a string containing a numeric value
- Value is an int
- Value is a float
Since PDO only has a param type for ints specifically and we want to allow int-only values in actual strings, is_int should be used here instead. This means floats and strings containing numeric values are still bound as strings.
If using
Database::execute()with an array of values of varying types, particularly booleans or ints, they are encased in quotes, causing them to be interpreted as strings.This would result in the following error:
SQL Error: SQLSTATE[22001]: String data, right truncated: 1406 Data too long for column 'BoolVal' at row 1 (0)This was found by attempting to call a stored procedure that took a
bitas a parameter, in which the boolean in PHP was passed as a string, violating the max length of the parameter.Below is some sample code I used to replicate the issue before the fix:
MySQL Stored Procedure:
PHP Code:
Note: I could not test for the same erroneous behaviour using named parameters, as I believe MySQL does not support them in stored procedures. I included the fix in that
foreachloop anyway as it looks like it would encounter the same issue if used.