-
Notifications
You must be signed in to change notification settings - Fork 11.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tuples Insertion with float & double values lose the decimal portion #23850
Comments
Please add the definition of the Do you have any casts, accessors or mutators in your |
No, I don't have any cast, accessors nor mutations in my model. About the definition of the |
It works for me. Does it work if you use a |
And try using the
When you use a |
Even if you use string how does this condition make sense? Its basically saying, if its a float then pass on the type as INT when, clearly its not the same data type. |
It's specific to MySQL: #16069 |
I just tried on your recommendations and got the following results:
The problem is that our application is accounting oriented so setting a monetary destined field to
|
I just tested on two different database engines and found out that this issues only occurs with MariaDB engines, the one we are currently using is MariaDB 10.1.31 |
Laravel doesn't officially support MariaDB. For monetary values you should definitely use |
Or as integer. |
What I think it was missed in this issue is the PDO option ATTR_EMULATE_PREPARES. When this option is set to On php 7.0 seems to work fine. Indeed, the below "if" located in
|
@ionutantohi: Why should it be removed? |
Why would you set Until now, that check was harmful, I don't know yet what is causing this, but something changed from php7.0 to 7.2 or PDO But now, with php7.2 it's causing issues in some conditions. An one of them is having PDO::ATTR_EMULATE_PREPARES = true Steps to reproduce:
Output:
If |
There's a reason for using |
@ionutantohi: Cool, feel free to submit a PR with good test cases to avoid this change causing havoc. |
@staudenmeir I understand this, but a workaround it needed for both cases. Here is what happened to me in real life. I have a project started on Laravel 5.5 and php7.0. In config/databases.php I had ATTR_EMULATE_PREPARES = true Inside the projected is a script which saves currency exchange rates multiple times a day. We upgraded to laravel 5.6 and php7.2. All went ok until we spotted that the exchange_rates were not saved correctly. Imagine what can happen to a billing project. |
Hi @themsaid @taylorotwell, I don't want to bother to much, but I would like to hear your opinion on this before continuing. In the initial issue, the user compained that the decimals are lost when saved in database. I experienced the same issue and it seems to be related to On my project, I can't switch that to false because the database is on a remote server and having Ie: Also, is seems to relate how a value is bound in MysqlConnection.php. A float value is bound as If that check will be removed, I don't know yet the impact on this issue: #16063 Here are some tests with current codebase of how a value is bound, including PARAM_INT for floats php7.2.4 tested on both mysql 5.5/5.7 Thank you! |
thanks @ionutantohi, i encounter this issue too because add ATTR_EMULATES_PREPARE. it is needed for 000webhost to work properly and then i move to another hosting without deleting the options. after deleting that, float saved without losing decimal. although i do not measure performance as it is not my focus (for now) |
any news on this? Or recommendation how to proceed? @themsaid Or second option - can I modify the line in MySqlConnection.php to instead of |
It looks like this is a 7.2 Issue. In my Custom system I always used PARAM_INT with decimal. Suddenly on Upgrade now I have to go through my whole system and find the Decimal fields and update them to PARAM_STR or it wont save. Gotta love this unanounced change. |
For those who monitor this. I made a pull request (#26817) containing a failing test to demonstrate the issue, but it was closed with the reason that we shouldn't use emulate prepares anymore. In my opinion this is wrong. Emulate prepares is an option in PDO which laravel doesn't handle it correctly on php 7.2 I tried to fix this but with no luck. The pull request which introduced this (#16069) has no tests and to be honest, I was afraid to not break something else. |
Laravel will miss-behave in multiple ways with MySQL and PgSQL as documented in various issues and even PRs, because people try to get a fix in but _the_ recommendation right now is to *not* use it. I figured it might save everyones time if ppl fill this out upfront because it's often takes some forth and back until users mention this. See: - laravel#29023 - laravel#23850 - laravel#25818 - laravel#27951 - laravel#28149
Change If the application use some "mysql view", it enables an "MySQL Bug" like: Please. remove this "is_float" from "MySQLConnection" class |
In PHP 7.2, the behavior of emulated queries was fixed, so it makes sense to remove the is_float check for MySQL https://bugs.php.net/bug.php?id=73234 https://bugs.php.net/bug.php?id=77954 @vitordm @driesvints @taylorotwell |
I have the same issue: Eloquent saves float as int. |
Description:
On insertions or updates, like when you use the save method from Eloquent model, float and double variables are losing their decimal part
Steps To Reproduce:
Starting by supposing that you have an accounting table in your database as it follows
Table Criation code:
And that your Eloquent model and Controller have the following code:
Eloquent Model code:
Controller code:
When sending a request to the viewAccounts operation from the Accounting controller, the expected output would be:
But current output is:
Notice that the current output shows how the decimal part is lost when the tuple is inserted into the table, and you can confirm it by checking directly into the database.
We found out that the issue might be related to the validation applied on the bindValues method, from illuminate\database\MySqlConnection.php file, where the data type bound to the value is defined on a ternary if as it follows:
so, by changing the validation to:
we get the expected output for the given example, just by basically removing the "is_float" portion from the validation
The text was updated successfully, but these errors were encountered: