Skip to content
This repository was archived by the owner on Jan 29, 2020. It is now read-only.

Implement our own error handler for db2_prepare #273

Merged
merged 10 commits into from
Nov 23, 2017

Conversation

akrabat
Copy link
Contributor

@akrabat akrabat commented Oct 13, 2017

db2_prepare() may issue a warning in addition to returning false.
If you have an error handler set (e.g. in the Expressive pipeline) then
the message created is "db2_prepare(): Statement Prepare Failed" which
is not helpful.

Therefore, we create our own error handler and trap this ourselves so
that we can throw an ErrorException with more information from
db2_stmt_errormsg().

I've left the previous handling as I don't know PHP extension code well enough to be 100% sure that db2_prepare() always generates a warning when it returns false.

@Ocramius
Copy link
Member

@akrabat you know exactly what I'm gonna ask you :-P

@akrabat
Copy link
Contributor Author

akrabat commented Oct 13, 2017

I can't run the integration tests against this client's IBM i DB2 and don't have my own, so unclear how to run them…

@Ocramius
Copy link
Member

Yeah, I know the scenario very well, but we're also not merging anything without verification, sorry...

@akrabat
Copy link
Contributor Author

akrabat commented Oct 13, 2017

Travis error is:

PHP Parse error:  syntax error, unexpected ':', expecting ';' or '{' in /home/travis/build/zendframework/zend-db/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Instantiator.php on line 95

Thoughts on how to fix?

@Ocramius
Copy link
Member

@akrabat I think the wrong composer.lock was committed to this repository

@michalbundyra
Copy link
Member

@Ocramius @akrabat tests on travis should works despite of committed composer.lock, maybe #259 will help

BTW currently we don't have composer.lock in zend-db at all

@Ocramius
Copy link
Member

Hmm, not sure how this was installed during the composer update step

@michalbundyra
Copy link
Member

@Ocramius
composer install --no-interaction --ignore-platform-reqs

https://travis-ci.org/zendframework/zend-db/jobs/287492129#L568
https://github.com/zendframework/zend-db/blob/master/.travis.yml#L81

--ignore-platform-reqs !!!

@michalbundyra
Copy link
Member

@Ocramius and maybe composer.lock is cached on travis?

db2_prepare() may issue a [warning][1] in addition to returning false.
If you have an error handler set (e.g. in the Expressive pipeline) then
the message created is "db2_prepare(): Statement Prepare Failed" which
is not helpful.

Therefore, we create our own error handler and trap this ourselves so
that we can throw an ErrorException with more information from
db2_stmt_errormsg().

[1]: https://github.com/php/pecl-database-ibm_db2/blob/df913feb4dff56366ac4656b0bb6b39200794bde/ibm_db2.c#L4400
@akrabat akrabat force-pushed the ibmdb2-error-improvement branch from 7c54f1e to ddec03b Compare October 13, 2017 17:03
*
* @return callable
*/
private function createErrorHandler() : callable
Copy link
Contributor

Choose a reason for hiding this comment

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

zend-db still use php 5.5/5.6 so the return type won't work

* @return void
* @throws ErrorException if error is not within the error_reporting mask.
*/
return function (int $errno, string $errstr, string $errfile, int $errline) : void {
Copy link
Contributor

Choose a reason for hiding this comment

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

remove return type as well

Copy link
Contributor

@samsonasik samsonasik Oct 13, 2017

Choose a reason for hiding this comment

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

also, int and string type hint not supported in php 5.5/5.6

try {
set_error_handler($this->createErrorHandler());
$this->resource = db2_prepare($this->db2, $sql);
} catch (Throwable $e) {
Copy link
Contributor

Choose a reason for hiding this comment

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

should catch Exception for php 5.5/5.6 fallback as well ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No - in 5.6, nothing is thrown.

@akrabat
Copy link
Contributor Author

akrabat commented Oct 13, 2017

@Ocramius: Added an integration test. I can't prove it works on every IBM DB2 installation out there, but it does on one specific IBMI I:

$ vendor/phpunit/phpunit/phpunit test/Adapter/Driver/IbmDb2/StatementIntegrationTest.php
PHPUnit 4.8.36 by Sebastian Bergmann and contributors.

.....

Time: 1.58 seconds, Memory: 4.00MB

OK (5 tests, 8 assertions)

@akrabat
Copy link
Contributor Author

akrabat commented Oct 13, 2017

@samsonasik Addressed your comments.

@@ -86,6 +87,23 @@ public function testPrepare()
}

/**
* @covers Zend\Db\Adapter\Driver\IbmDb2\Statement::prepare
* @expectedException RuntimeException
Copy link
Member

Choose a reason for hiding this comment

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

I would move it to function use, because right now it's not clear, which line should thrown that exception.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@webimpress I can't - it doesn't work on the AS/400 when I do that. I have no idea why.

Copy link
Member

Choose a reason for hiding this comment

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

Hm... so maybe exception is thrown not where you expecting it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It was a PHP error. I'll have another look when I'm next connected to that computer.

@akrabat
Copy link
Contributor Author

akrabat commented Oct 16, 2017

@webimpress Dunno what I did wrong last time, but it works this time!

$ vendor/phpunit/phpunit/phpunit  test/Adapter/Driver/IbmDb2/StatementIntegrationTest.php
PHPUnit 4.8.36 by Sebastian Bergmann and contributors.

.....

Time: 1.71 seconds, Memory: 4.00MB

$statement->initialize($db2Resource);
$this->setExpectedException(RuntimeException::class);
$statement->prepare("SELECT");
unset($resource, $db2Resource);
Copy link
Member

Choose a reason for hiding this comment

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

I think this line will be not even hit.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It will if the test fails :)

Copy link
Contributor

@mwillbanks mwillbanks left a comment

Choose a reason for hiding this comment

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

Looks like everything is addressed 👍

@mwillbanks
Copy link
Contributor

@akrabat can you see if you can solve the coveralls although?

@akrabat
Copy link
Contributor Author

akrabat commented Oct 20, 2017

can you see if you can solve the coveralls although?

@mwillbanks The coveralls problem is that I've added new code that is covered by an integration test rather than a unit test.

That's what the error handler throws.
Mock the relevant db2_xxx functions by placing them into the
Zend\Db\Adapter\Driver\IbmDb2 namespace so that they are preferred
over the actual ones in the idm_db2 extension.
@akrabat
Copy link
Contributor Author

akrabat commented Oct 20, 2017

@mwillbanks Thought some more and then wrote some unit tests.

@ezimuel ezimuel merged commit 984e355 into zendframework:develop Nov 23, 2017
@ezimuel
Copy link
Contributor

ezimuel commented Nov 23, 2017

@akrabat thanks for your contribution!

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.

7 participants