ZF-1475: DB2: Support parameter and result binding

Description

Please implement logic in Zend_Db_Statement_Db2 to support the methods: - bindParam() - bindValue() - bindColumn()

Comments

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.

Patch for bindColumn() only.

Removed bindColumn() no-op tests

Added new test for bindColumn() with a combination of bind column by name and position operations

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.

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

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.

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?

I didn't find the issue to ever be sufficiently reported so I added a new bug:

http://pecl.php.net/bugs/17868

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?

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.

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.

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);
         }