ZF-1475: DB2: Support parameter and result binding
Description
Please implement logic in Zend_Db_Statement_Db2 to support the methods: - bindParam() - bindValue() - bindColumn()
Please implement logic in Zend_Db_Statement_Db2 to support the methods: - bindParam() - bindValue() - bindColumn()
Comments
Posted by Bill Karwin (bkarwin) on 2007-06-01T19:51:28.000+0000
Some additional information:
We're trying to make the Statement class match the behavior of PDOStatement, with respect to methods like bindParam(), bindValue, and bindColumn().
See: http://php.net/manual/en/… http://php.net/manual/en/… http://php.net/manual/en/…
We have unit tests for these in /tests/Zend/Db/Statement/TestCommon.php.
The tests are currently overridden in /tests/Zend/Db/Statement/Db2Test.php because the functionality does not work. So to test, just comment out the functions in Db2Test.php so it uses the implementations of the tests from TestCommon.php.
Posted by Salvador Ledezma (ledezma) on 2007-06-04T22:52:47.000+0000
Patch for bindColumn() only.
Posted by Salvador Ledezma (ledezma) on 2007-06-04T22:53:44.000+0000
Removed bindColumn() no-op tests
Posted by Salvador Ledezma (ledezma) on 2007-06-04T22:54:30.000+0000
Added new test for bindColumn() with a combination of bind column by name and position operations
Posted by Bill Karwin (bkarwin) on 2007-06-18T21:16:14.000+0000
Unit tests confirm that {{bindColumn()}} is working with the IBM_DB2 adapter at this time, but parameter binding is not. There are apparently confirmed bugs at the driver level in the ibm_db2 extension, and we're waiting for fixes.
Another option would be to "simulate" the bound parameters and simply pass them to the statement execution during the {{execute()}} method of the Zend_Db_Statement_Db2 class.
But it seems that this fix is of very low priority, so I'm going to mark this issue POSTPONED at this time.
Posted by Thomas Weidner (thomas) on 2008-03-12T14:47:02.000+0000
Hy Salvador,
if you are not able to commit this patch, you should un-assign this issue so anyone with commit-rights will do this.
Otherwise please commit your changes and close this issue. ;-)
When this issue is partitially fixed you should write this, and probably open a new issue for the not-fixed part so this one with the fixed half can be closed
Posted by Salvador Ledezma (ledezma) on 2008-03-12T18:02:07.000+0000
I had submitted these patches for review by someone with commit authority.
Please use as you see fit, though I believe the fix is still incomplete.
Posted by Aaron S. Hawley (ashawley) on 2010-07-22T14:05:30.000+0000
bkarwin mentions that bindParam() is broken because of a known bug at the driver level. I can only see mention of it as a note in http://pecl.php.net/bugs/15062 on 2010-04-20. Is it a reported issue?
Posted by Aaron S. Hawley (ashawley) on 2010-07-28T19:20:46.000+0000
I didn't find the issue to ever be sufficiently reported so I added a new bug:
http://pecl.php.net/bugs/17868
Posted by Dolf Schimmel (Freeaqingme) (freak) on 2010-07-28T19:46:02.000+0000
Do I understand correctly that this is an issue that should be fixed upstream (read: in the php core)? If so, shouldn't this issue be closed?
Posted by Aaron S. Hawley (ashawley) on 2010-07-29T05:30:30.000+0000
No, this issue is far from closed. There will probably still need to be changes made to the Zend Framework -- assuming the issue is upstream, which hasn't been confirmed (nor fixed), yet.
Posted by Aaron S. Hawley (ashawley) on 2011-01-12T05:27:59.000+0000
So, the bug is fixed upstream, but indeed the way binding works for db2_bind_param is different than PDO. Binding is done by the name of a variable, not by a reference to a variable. This issue is intractable unless Zend_Db_Statement is rewritten to consider this case.
Posted by Jason Estrada (jason.estrada) on 2012-07-30T19:46:06.000+0000
I am proposing a possible solution for db2_bind_param() binding by variable name and not by variable reference issue. It appears this issue has been around for quite some time now, and waiting on a driver fix doesn't seem to be working.
The solution is simple:
Generate the variable +name+ used for binding within _bindParam(), and use this name for db2_bind_param(). This covers all cases.
Create the variables from the names generated/bound from above and bind by reference to the _bindParam array elements within _execute().
The variables have to be created and [re]bound on each execute since these will only be in scope for the duration of _execute(). It is also not necessary to perform this binding within _execute() when parameters are passed-in, since db2_execute() will use what's supplied on the call and not what was previously bound (if anything).
I know this is not the most elegant of solutions since it relies upon eval'd code (flame on), but I do not see another alternative at this stage. If and when the ibm_db2 extension is later modified to bind by variable reference, this binding could be easily adapted back into the Statement class, and the eval can be removed. However, in the meantime, this should at least allow parameter binding to function as advertised by the Zend_Db_Statement_Interface.
Index: library/Zend/Db/Statement/Db2.php =================================================================== --- library/Zend/Db/Statement/Db2.php (revision 25028) +++ library/Zend/Db/Statement/Db2.php (working copy) @@ -37,6 +37,13 @@ { /** + * Bound query parameter-to-variable name mapping. + * + * @var array + */ + protected $_bindParamNames = array(); + + /** * Column names. */ protected $_keys; @@ -96,7 +103,12 @@ $datatype = DB2_CHAR; } - if (!db2_bind_param($this->_stmt, $parameter, "variable", $type, $datatype)) { + // ZF-1475: support parameter and result binding. + // db2_bind_param() binds by variable name and not by reference. + // Generate the variable name here for the associated parameter, the + // variable will be later created and bound in scope during _execute() + $this->_bindParamNames[$parameter] = 'zf_bind_param_'.$parameter; + if (!db2_bind_param($this->_stmt, $parameter, $this->_bindParamNames[$parameter], $type, $datatype)) { /** * @see Zend_Db_Statement_Db2_Exception */ @@ -201,6 +213,12 @@ if ($params !== null) { $retval = @db2_execute($this->_stmt, $params); } else { + // Expose any bound parameter variables set in _bindParam() + if (empty($this->_bindParam) === false) { + foreach ($this->_bindParamNames as $param => $bind_param) { + eval('$$bind_param =& $this->_bindParam[$param];'); + } + } $retval = @db2_execute($this->_stmt); }