-
Notifications
You must be signed in to change notification settings - Fork 121
Implement our own error handler for db2_prepare #273
Implement our own error handler for db2_prepare #273
Conversation
@akrabat you know exactly what I'm gonna ask you :-P |
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… |
Yeah, I know the scenario very well, but we're also not merging anything without verification, sorry... |
Travis error is:
Thoughts on how to fix? |
@akrabat I think the wrong |
Hmm, not sure how this was installed during the composer update step |
@Ocramius https://travis-ci.org/zendframework/zend-db/jobs/287492129#L568
|
@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
7c54f1e
to
ddec03b
Compare
* | ||
* @return callable | ||
*/ | ||
private function createErrorHandler() : callable |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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 ?
There was a problem hiding this comment.
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.
@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:
|
@samsonasik Addressed your comments. |
@@ -86,6 +87,23 @@ public function testPrepare() | |||
} | |||
|
|||
/** | |||
* @covers Zend\Db\Adapter\Driver\IbmDb2\Statement::prepare | |||
* @expectedException RuntimeException |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
@webimpress Dunno what I did wrong last time, but it works this time!
|
$statement->initialize($db2Resource); | ||
$this->setExpectedException(RuntimeException::class); | ||
$statement->prepare("SELECT"); | ||
unset($resource, $db2Resource); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 :)
There was a problem hiding this 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 👍
@akrabat 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.
@mwillbanks Thought some more and then wrote some unit tests. |
@akrabat thanks for your contribution! |
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.