php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #57158 Suggested bugfix
Submitted: 2006-07-26 10:13 UTC Modified: 2006-10-30 06:37 UTC
From: mim at serverconnect dot org Assigned: slaws (profile)
Status: Closed Package: SCA_SDO (PECL)
PHP Version: 5.1.4 OS: Debian GNU/Linux
Private report: No CVE-ID: None
 [2006-07-26 10:13 UTC] mim at serverconnect dot org
Description:
------------
Using SDO 1.0.2

If I create a situation where I load some data from a Relational DB and the DB data gets changed outside of SDO in the meantime, I'd expect an attempt to write my modifications on that data to cause an SDO_DAS_Relational_Exception, but it doesn't. So I'm left thinking my data got written when it didn't.


Reproduce code:
---------------
/*
MySql statements:

CREATE DATABASE sdo_user;

USE sdo_user;

CREATE TABLE `Mbr` (
    `id` INTEGER auto_increment,
    `name` VARCHAR( 40 ) NULL,
    PRIMARY KEY ( `id` )
    ) COMMENT = 'Members';

CREATE TABLE `Profile` (
    `id` INTEGER auto_increment,
    `parent` VARCHAR( 40 ) NOT NULL,
    `address` VARCHAR( 100 ) NULL,
    PRIMARY KEY ( `id` )
    ) COMMENT = 'Contact address details';

INSERT INTO Mbr VALUES(NULL, "Jimmy");
*/
// Member table structure
$mbr = array(
    'name' => 'Mbr',
    'columns' => array('id', 'name'),
    'PK' => 'id'
    );

// Profile table structure
$profile = array (
    'name' => 'Profile',
    'columns' => array('id', 'parent', 'address'),
    'PK' => 'id',
    'FK' => array ('from' => 'parent', 'to' => 'Mbr')
    );

$table_lib = array($mbr, $profile);

// Table containment structure
$table_tree = array('parent' => 'Mbr', 'child' => 'Profile');

// Constants
define('PDO_DSN', 'mysql:host=localhost;dbname=sdo_user');
define('DATABASE_USER', 'mim');
define('DATABASE_PASSWORD', '????????');

// Get SDO/DAS

require 'SDO/DAS/Relational.php';

$dbh = new PDO(PDO_DSN, DATABASE_USER, DATABASE_PASSWORD);
$das = new SDO_DAS_Relational($table_lib, 'Mbr', array($table_tree));

$pdo_stmt = $dbh->prepare('select id, name from Mbr where id=?');

//ob_start(); // :BUG: dirty fix prevents two spaces appearing
$root = $das->executePreparedQuery($dbh, $pdo_stmt, array(2), array('Mbr.id', 'Mbr.name'));
//ob_end_clean();

$mbr = $root['Mbr'][0];

$mbr->name = 'Norbett';

// Now let's change the DB behind SDO's back
$result = $dbh->query('update Mbr set name="Silly Name" where id="2"');

echo "BugStart=#8280: Undefined variable: settings_as_array, The second argument should be either an array or an object\n";
$das->applyChanges($dbh, $root);
echo "BugEnd\n";
echo "Done\n";


Expected result:
----------------
An SDO_DAS_Relational_Exception thrown

Actual result:
--------------
(With DEBUG_BUILD_PLAN=true in Relational.php)

  BugStart=#8280: Undefined variable: settings_as_array, The second argument should be either an array or an object
===============================
Executing plan as follows:
executing the following SQL statement:
UPDATE Mbr SET name = ? WHERE id = ? AND name = ?;
using the following list of values:
   string(7) "Norbett"
   string(1) "2"
   string(5) "Jimmy"
BugEnd
Done


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2006-07-26 10:48 UTC] simonslaws at googlemail dot com
Thanks Mark for reporting this. I have constructed a fix for this as part of bug 7879. It's the same piece of code causing the problem. Just testing it at the moment so it's not checked into CVS just yet.
 [2006-07-28 08:29 UTC] mim at serverconnect dot org
I got some more time to look at this, and have come up with a bugfix suggestion that hopefully covers all the fault scenarios:

DatabaseHelper.php:
<?php
public static function executeStatement($dbh,$stmt,$value_list)
{
    if (SDO_DAS_Relational::DEBUG_EXECUTE_PLAN) {
        echo "executing the following SQL statement:\n" . $stmt . "\n";
        echo "using the following list of values:\n";
        foreach ($value_list as $value) {
            ob_start();
            var_dump($value);
            $content = ob_get_contents();
            ob_end_clean();
            echo "   $content";
        }
    }

    // Detect all possible error scenarios whilst attempting the update (see PDO return values for details)
    $pdo_stmt = $dbh->prepare($stmt);
    $is_pdo_success = $pdo_stmt === false ? false : $pdo_stmt->execute($value_list);
    $rows_affected = $is_pdo_success === true ? $pdo_stmt->rowCount() : 0;
    $is_sdo_success = ($is_pdo_success === true and $rows_affected) > 0 ? true : false;

    if ($is_sdo_success === false) {
        $msg = "\nSDO/DAS/Relational.php::applyChanges encountered an error when attempting to execute $stmt";
        if ($is_pdo_success === false) {
            // SQL statement encountered and SQL error
            $pdo_error_info = $dbh->errorInfo();
            $msg .= "\nThe error information returned from PDO::errorInfo() was:";
            $msg .= "\n  SQLSTATE: " . $pdo_error_info[0];
            $msg .= "\n  Driver-specific error code: " . $pdo_error_info[1];
            $msg .= "\n  Driver-specific error message: " . $pdo_error_info[2];
        } else {
            // SQL completed but affected 0 rows, and with no SQL error, under SDO, this becomes a concurrency fault
            $msg .= "\nPDO reported no rows affected by the SQL statement.";
            $msg .= "\nThis occurs when data retrieved and updated has been changed by another ";
            $msg .= "processs in the database in the meantime. An optimistic conurrency failure.";
        }
        $dbh->rollback();
        $msg .= "\nAll changes have been rolled back.";
        throw new SDO_DAS_Relational_Exception($msg);
    }
}
?>
 [2006-08-09 07:16 UTC] simonslaws at googlemail dot com
Already fixed in 1.0.3
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Tue May 21 22:01:26 2019 UTC