microsoft / msphpsql

Microsoft Drivers for PHP for SQL Server
MIT License
1.78k stars 371 forks source link

Fixed error when using PDO::ATTR_STRINGIFY_FETCHES #1468

Closed SakiTakamachi closed 10 months ago

SakiTakamachi commented 11 months ago

This fixes the issue reported here.

https://github.com/laravel/framework/issues/47937

Fixes for errors caused by PDO changes in php8.1.22 and 8.2.9.

test code

<?php

// my env
$pdo = new PDO('sqlsrv:server=mssql-server;database=test;', 'test_user', 'p@ssw0rd');
$pdo->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);
GrahamCampbell commented 11 months ago

Why does this PR change nothing?

SakiTakamachi commented 11 months ago

A test was crashing unexpectedly, so I'm temporarily running it without any changes. Revert when the current test is finished.

SakiTakamachi commented 11 months ago

The tests seem to fail even without any changes, and there seems to be some unstable tests.

SakiTakamachi commented 11 months ago

@v-makouz If you don't mind, could you please review it?

SakiTakamachi commented 11 months ago

This test will fail even if I didn't make any changes.

I don't understand why this is the case, just by looking at it lightly.

absci commented 11 months ago

Thanks for your contribution, there're some tests may fail intermittently due to connection. I'll rerun it.

SakiTakamachi commented 11 months ago

@absci

Thank you for confirmation.

Am I correct in thinking that I have to rerun the connection test many times until it succeeds?

youkidearitai commented 10 months ago

@absci

Hi, I heard PHP 8.1.22 and 8.2.8 throws Exception when PDO::ATTR_STRINGIFY_FETCHES. I would appreciate it if you could pass this pull request.

Regards.

absci commented 10 months ago

I have merged this PR, it'll be included in the next release.

SakiTakamachi commented 10 months ago

Thank you for confirming and merging!

jarkko-hautakorpi commented 10 months ago

Are there perhaps some undocumented changes coming, or was it a bug and no changes intended? https://learn.microsoft.com/en-us/sql/connect/php/pdo-setattribute?view=sql-server-ver16 This documentation is still valid?

SakiTakamachi commented 10 months ago

This documentation is still valid?

Yes, it is.

This is a fix that removes the error caused by changes in PDO core.

AbrahamBrookes commented 10 months ago

I also got hit with this issue, thanks for the PR and the merge!

pirex360 commented 10 months ago

Hi, I have also : SQLSTATE[IMSSP]: An invalid attribute was designated on the PDO object error.

I tried everything, removing all PDO::ATTR or PDO::SQLSRV, and the result is the same! Here is a sample of the connection data:

array(
                'driver'        => 'sqlsrv',
                'host'          => 'xxx.xxx.xxx.xxx',
                'port'          => 999999,
                'database'      => 'testdb',
                'username'      => 'johndoe',
                'password'      => 'test',
                'charset'       => 'utf8',
                'prefix'        => '',
                'prefix_indexes' => true,
                'options'       => array(
                    PDO::ATTR_EMULATE_PREPARES => true,
                    PDO::ATTR_STRINGIFY_FETCHES => false,
                    PDO::ATTR_CASE => PDO::CASE_LOWER,
                    PDO::SQLSRV_ATTR_FETCHES_NUMERIC_TYPE => true,
                    PDO::SQLSRV_ATTR_FORMAT_DECIMALS => true,
                ),
                'encrypt' => 'yes',     // added for MSSQL 18 to work
                'trust_server_certificate' => true, // added for MSSQL 18 to work
 )

I also tried upgrading to PHP 8.2.8 and the result is the same. I have pdo_sqlsrv and sqldrv extensions on 5.10.1.

The only way it worked, was downgrading to PHP 7.4 and I make a simple PHP script to test db connection and works, but this is not a solution for me, because I have a lot of composer dependencies for PHP 8.1 and I can't downgrade it! will be a messy job and some app features will be broken.

Can anybody help/guide me to the solution to this problem?

SakiTakamachi commented 10 months ago

@pirex360

I also tried upgrading to PHP 8.2.8 and the result is the same.

Is it really php8.2.8? This issue occurs on 8.2.9 and later.

pirex360 commented 10 months ago

@pirex360

I also tried upgrading to PHP 8.2.8 and the result is the same.

Is it really php8.2.8? This issue occurs on 8.2.9 and later.

Sorry, it was my mistake... I put in PHP 8.2.8 and re-install the driver and now it works !!! in PLESK if you change the PHP version you have to install again the driver, even if you have it in 8.2.0.

Now my question shifted...what will happen if PLESK auto updates and forces us to use PHP 8.2.9 or + ? Is this a temporary fix?

SakiTakamachi commented 10 months ago

@pirex360

This fix is ​​still in the process of being merged into the dev branch and has not been released.

It will be included in the next release.

If you update to php8.2.9 again before the release, of course the problem will reoccur.

Using the driver that is new version after release will permanently fix this issue.

ssswang commented 10 months ago

@pirex360 If you upgrade to php 8.2.9, you will get SQLSTATE[IMSSP]: An invalid attribute was designated on the PDO object because of PDO::ATTR_STRINGIFY_FETCHES => false,

In my own limited experiment and testing, it is safe to remove this line. Please correct me if I am wrong.

This is also a solution wrote by SakiTakamachi using a try catch block without removing PDO::ATTR_STRINGIFY_FETCHES => false, https://github.com/laravel/framework/issues/47937#issuecomment-1671772276

SakiTakamachi commented 10 months ago

@ssswang

Yes, you are right.

In the current php specification, the initial value of PDO::ATTR_STRINGIFY_FETCHES is false.

Therefore, it can be controlled by specifying SQLSRV_ATTR_FETCHES_NUMERIC_TYPE.

You can safely delete the PDO::ATTR_STRINGIFY_FETCHES line.

neclimdul commented 10 months ago

"after release" :disappointed:

ssswang commented 10 months ago

@SakiTakamachi Arigato, Sakichi. Thank you for confirming. It's 5 AM in Japan. Don't work too hard. ^^

pirex360 commented 10 months ago

@pirex360 If you upgrade to php 8.2.9, you will get SQLSTATE[IMSSP]: An invalid attribute was designated on the PDO object because of PDO::ATTR_STRINGIFY_FETCHES => false,

In my own limited experiment and testing, it is safe to remove this line. Please correct me if I am wrong.

This is also a solution wrote by SakiTakamachi using a try catch block without removing PDO::ATTR_STRINGIFY_FETCHES => false, laravel/framework#47937 (comment)

It's weird, In my testing... I remove all the options array from the connection :

 'options'       => array(
                    PDO::ATTR_EMULATE_PREPARES => true,
                    PDO::ATTR_STRINGIFY_FETCHES => false,
                    PDO::ATTR_CASE => PDO::CASE_LOWER,
                    PDO::SQLSRV_ATTR_FETCHES_NUMERIC_TYPE => true,
                    PDO::SQLSRV_ATTR_FORMAT_DECIMALS => true,
                ),

And still, the error appears...

SakiTakamachi commented 10 months ago

It doesn't make much sense to test it in Laravel. Because the initial value is set inside Laravel, it is not possible to completely remove the option specification.

https://github.com/laravel/framework/blob/10.x/src/Illuminate/Database/Connectors/SqlServerConnector.php#L19

SakiTakamachi commented 10 months ago

And removing an option doesn't mean setting it to false, it means not specifying anything.

pirex360 commented 10 months ago

And removing an option doesn't mean setting it to false, it means not specifying anything.

Sure, You are right... it fallback to the defaults... but doesn't the default supported by the driver? The key is your "Because the initial value is set inside Laravel, it is not possible to completely remove the option specification.", it points to the problem of Laravel defaults and not Driver Default.

Thanks for your time, it was enlightenment.

JGlueck-WIKA commented 10 months ago

@absci Any news on when the next release will take place?

absci commented 10 months ago

@absci Any news on when the next release will take place?

There's no exact time at the moment, possibly the end of 2023.

SakiTakamachi commented 10 months ago

@absci

Is it difficult to release a patch version that addresses this issue as 5.11.1 first?

absci commented 10 months ago

@absci

Is it difficult to release a patch version that addresses this issue as 5.11.1 first?

I'll discuss it with management levels. Maybe we can do a hotfix release.

SakiTakamachi commented 10 months ago

I'll discuss it with management levels. Maybe we can do a hotfix release.

I apologize for the trouble. Thanks so much.

skylord123 commented 10 months ago

I'll discuss it with management levels. Maybe we can do a hotfix release.

This is currently breaking the build process for my company. Since we build our container off Ubuntu using Ondrej repo we are stuck on PHP 8.1.22 that has this problem. So a hotfix would be a godsend to getting this resolved.

Also thanks @SakiTakamachi for a good job finding and fixing this.

kokoshneta commented 10 months ago

@absci Is it difficult to release a patch version that addresses this issue as 5.11.1 first?

I'll discuss it with management levels. Maybe we can do a hotfix release.

Since this is currently breaking every single Laravel install where the developer is unable to control the minor version of PHP (e.g., Plesk-hosted – once you’re on 8.2.9, it seems you can’t downgrade back to 8.2.8 without Plesk auto-re-upgrading), a hotfix would be highly appreciated.

JGlueck-WIKA commented 10 months ago

For those of you with a Laravel installation also suffering from this problem at the moment - the workaround suggested here helped us to circumnavigate that issue for now.

Anyhow, a release of this fix would be highly appreciated.

wwwDESIGN-basti commented 10 months ago

Here is the easiest und final solution: https://github.com/SakiTakamachi/laravel-sqlsrv-err-avoid

install it and the problem is gone.

skylord123 commented 10 months ago

Here is the easiest und final solution: https://github.com/SakiTakamachi/laravel-sqlsrv-err-avoid

install it and the problem is gone.

Not a final solution, just a bandaid. Basically just ignores the problem this driver is currently causing. The final solution would be to get a patched version of msphpsql.

I have over 25+ services so manually installing this bandaid until this is fixed then removing it is quite a large effort.

David-Engel commented 10 months ago

Think this PR should not have been merged as-is. The fix should be made in PHP (the offending PR should be reverted), where the break happened. This change will be fine if it is needed for PHP 8.3. But don't make everyone else patch out-of-band for an upstream error.

Changes that break backwards compatibility should only be made on version changes where you might expect to have to test for version compatibility. Upgrading from PHP 8.2.8 to PHP 8.2.9 shouldn't break downstream apps.

SakiTakamachi commented 10 months ago

@David-Engel

All other pdo exts do not raise an error under the same conditions.

Only PDO SQLSRV raises an error.

So I personally don't think this is a BC break.

It takes a lot of effort to consider all downstream proprietary specifications in order to make upstream modifications.

I have checked all 16 pdo drivers present in pecl and only sqlsrv causes the error, even those not in php-src.

SakiTakamachi commented 10 months ago

Even if you look at the PDO documentation, it doesn't say that setAttribute throw an exception, and it states that it simply returns false on failure.

https://www.php.net/manual/en/pdo.setattribute.php#refsect1-pdo.setattribute-returnvalues

Therefore, I believe that the essence of this problem is that PDO SQLSRV does not conform to the PDO specification.

youkidearitai commented 10 months ago

@David-Engel No, I don't think PHP 8.2.9 is BC break. Because this is done for the convenience of throwing parameters other than the allowed list that msphpsql is doing arbitrarily. I think should fix to msphpsql.

youkidearitai commented 10 months ago

@David-Engel Or are you saying that you don't allow modifying ext/pdo/pdo_dbh.c in php-src?

youkidearitai commented 10 months ago

@David-Engel Or are you saying that you don't allow modifying ext/pdo/pdo_dbh.c in php-src?

I think one thing, If msphpsql isn't going to chase php-src, it should be proposed in an RFC to have it integrated into php-src.

SakiTakamachi commented 10 months ago

@David-Engel This is a problem that this repository should solve, as the proprietary error throwing spec is causing this issue. I really hope for an early hotfix release. If you want a fix at the underlying specification level rather than a monkey patch, I'm ready to help with that fix.

SakiTakamachi commented 10 months ago

I have created an issue because I can't keep talking forever in this PR. https://github.com/microsoft/msphpsql/issues/1474