Skip to content
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

Ignore DB2 warning when reaching end #5162

Closed
wants to merge 1 commit into from
Closed

Ignore DB2 warning when reaching end #5162

wants to merge 1 commit into from

Conversation

tdutrion
Copy link

@tdutrion tdutrion commented Jan 5, 2022

Q A
Type bug
BC Break no
Fixed issues

Summary

System OS400 NEPTUNE 4 7 00210009E53W
PHP Version 7.4.27
ibm_db2 2.1.5
error_reporting 32767 (E_ALL)

Ignore DB2 warning when reaching the end of a rowset.

Error in French:

Warning: db2_stmt_error(): La ligne n'a pas {t{ trouv{e pour C65399500002000003. SQLCODE=100"

I don't have an IBMi configured in English sorry, it says row not found for C65399500002000003).

When ignoring this warning, there is no more execution problem. The error is checked in the condition just below, and there should always be a db2_error when an actual error is raised.

@derrabus
Copy link
Member

derrabus commented Jan 5, 2022

Can you provide a test for your change?

@tdutrion
Copy link
Author

tdutrion commented Jan 5, 2022

Because the warning comes from the PHP driver/the database engine, I'm not really sure how to test it as a unit 🤔
Have you got any pointers to help test it?

@derrabus
Copy link
Member

derrabus commented Jan 5, 2022

Yes, you probably need a functional test for that. You should find some inspiration in the tests/Functional directory.

Ignore DB2 warning when reaching the end of a rowset.
Error in French: "Warning: db2_stmt_error(): La ligne n'a pas {t{ trouv{e pour C65399500002000003. SQLCODE=100" (I don't have an IBMi configured in English sorry, it says row not found for C65399500002000003).
@tdutrion
Copy link
Author

tdutrion commented Jan 5, 2022

Hum... I tried one, but it seems to have weird effects: https://github.com/tdutrion/dbal/runs/4718254375?check_suite_focus=true
When trying to run the tests without the fix, I get errors on Doctrine\DBAL\Tests\Functional\ResultTest::testExceptionHandling, which sort of make sense, but it looks like the $this->iniSet('error_reporting', (string) E_ALL); is the source of these errors (so a single test is creating side effects for all others).
Can you confirm my analysis is ok? Should we reset the ini parameter at the end of each test?

@derrabus
Copy link
Member

derrabus commented Jan 5, 2022

Why's the iniSet() call necessary anyway?

@derrabus derrabus closed this Jan 5, 2022
@derrabus derrabus reopened this Jan 5, 2022
// prevent the PHPUnit error handler from handling the errors that db2_execute() may trigger
$this->iniSet('error_reporting', (string) E_ALL);

$result = $stmt->execute([[]])->fetchAllAssociative();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is known that SELECT ... FROM sysibm.sysdummy1 will always return a single row. Why do you use fetchAllAssociative()?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error happens when trying to retrieve a line from a collection that does not exist (to know that the collection is finished). Using fetchAssociative there's no problem since a line exist.

@morozov
Copy link
Member

morozov commented Jan 5, 2022

FWIW, the newly added test passes without the fix, so it doesn't reproduce the problem. Additionally, I also cannot reproduce this issue without the DBAL:

<?php

error_reporting(E_ALL);

$conn = db2_connect(
    'HOSTNAME=localhost;UID=db2inst1;PWD=Passw0rd;DATABASE=doctrine',
    null,
    null
);

$stmt = db2_prepare($conn, 'SELECT current time FROM SYSIBM.SYSDUMMY1');
db2_execute($stmt);
$row1 = db2_fetch_array($stmt);
var_dump($row1);
// array(1) {
//   [0] =>
//   string(8) "21:58:29"
// }

$row2 = db2_fetch_array($stmt);
var_dump($row2);
// bool(false)

$error = db2_stmt_error($stmt);
var_dump($error);
// string(5) "02000"

@tdutrion are there any additional steps needed to reproduce the problem?

I used PHP 8.0 though:

php -v
PHP 8.0.14 (cli) (built: Dec 17 2021 14:16:47) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.14, Copyright (c) Zend Technologies
    with Zend OPcache v8.0.14, Copyright (c), by Zend Technologies
    with Xdebug v3.1.2, Copyright (c) 2002-2021, by Derick Rethans

Could you check if it's reproducible regardless of the PHP version?

@tdutrion
Copy link
Author

tdutrion commented Jan 6, 2022

The biggest difference I can see is that I am using DB2 For i and not the "standard" DB2 from this image.
I can try to setup a reproducer using an IBMi on pub400.com if that helps.

@morozov
Copy link
Member

morozov commented Jan 6, 2022

In my understanding, DB2 for IBM i, although compatible with DB2 LUW by the driver API, is a totally different platform that the DBAL doesn't support.

Supporting it completely would require some more changes than this error suppression (see #910 and #3016 for example) but we could do that only if we continuously test against a DB2 for IBM i instance on CI.

I can try to setup a reproducer using an IBMi on pub400.com if that helps.

It can only help make sure that it's an IBMi-specific bug.

Alternatively, could you try my snippet in #5162 (comment) and possibly confirm that the issue is reproducible in your environment?

@tdutrion
Copy link
Author

tdutrion commented Jan 6, 2022

Using your non-doctrine script, I managed to get the error message on IBMi using a combination of

error_reporting(E_ALL);
ini_set('display_errors', 1);

Using the display_errors, I still don't get the warning with the Docker DB2 though.

I raised an issue to get PHP cli on pub400.com since we can't access DB2 for I from outside without DB2 connect license (unless using ODBC). I'm not sure they will do that soon though, another request already exist in the forum.

Looks like a proper IBM i DB2 problem though, maybe @alanseiden you could tell us who/where to ask for help regarding the php extension directly (sorry to be adding you here so bluntly.

@alanseiden
Copy link

@tdutrion I can reproduce on our IBM i system. In one sense, it's proper Db2 behavior (RPG programs use that code 100 to stop fetching rows), but I admit I never noticed this warning before, so it's worth looking into. There is a Github repo for ibm_db2 but I'm not sure it's an ibm_db2 issue yet. I'll contact you offline as well.

Looks like a proper IBM i DB2 problem though, maybe @alanseiden you could tell us who/where to ask for help regarding the php extension directly (sorry to be adding you here so bluntly.

@tdutrion
Copy link
Author

tdutrion commented Jan 7, 2022

Thanks a lot for your insights @alanseiden! As stated by @morozov it seems to be IBMi specific, I'm afraid we will have to close this merge request, and I should contribute some more on https://github.com/alanseiden/doctrine-dbal-ibmi directly with a 3.x branch directly.

@tdutrion tdutrion closed this Jan 7, 2022
@alanseiden
Copy link

@tdutrion The warning seems to be triggered not by the fetch function, but by the db2_stmt_error() function. If you don't call db2_stmt_error(), you won't get the warning. But you can still call it in a different way if you wish.
Change:
$error = db2_stmt_error($stmt);
to
$error = db2_stmt_error();
that is, don't pass in the specific statement resource. Let the function find the last error for you. You will no longer get the warning. Try it.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jan 8, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants