[PHP-users 35449] 再投稿 WEBからMDB2のexecute文が実行できない

sakon konno @ me-h.ne.jp
2010年 12月 20日 (月) 14:20:00 JST


今回はautoExecute文を使用して切り分けをしてみた。
現象は、OSコマンドでプログラムを実行する。問題はないのだが、
WEBから実行すると「MDB2 Error: unknown error」のエラー
が返り実行できない。
OSとWEB上の違いはheader("content-type","html/text");
だけです。
切り分けた結果は、common.phpのquit関数
if(PEAR::isError($db)) {return $db;}と同じく_quoteText関数の
if(PEAR::isError($db)) {return $db;}でエラーが発生してreturn文
でエラーになっています。コメントアウトをすると正常に動作します。
仕事が忙しくisErrorの中身まで調べてきれていませんアドバスを
お願いします。
(1)環境 
CentOS release 5.3 (Final) 
PHP 5.1.6 
MDB2 2.5.0b2-beta 
MDB2_Driver_pgsql 1.5.0b2-beta 
(2)試験DB環境  
POSTGRESQL 8.1 
psql -l
              List of databases
         Name          |  Owner   | Encoding
-----------------------+----------+----------
test_db               | postgres | EUC_JP

test_db=# select * from test_table;
 test_char | test_varchar | test_integer
-----------+--------------+--------------
 90001111  | テスト       |            1
(1 row)

(3)試験プログラム
<?php
require_once("MDB2.php");

// エラーハンドラ
class test_db {
    const DSN = "pgsql://digisys:digisys@tcp(localhost:5432)/";
    protected $db;

    // コンストラクタ
    function __construct($db_name){
        $dsn = self::DSN . $db_name;
        $options = array('debug'=>2,'result_buffering' => false);
        $con =& MDB2::factory($dsn,$options);
        if(PEAR::isError($con)){
            die($con->getMessage());
        }
        $con->loadModule('Extended');
        $con->setFetchMode(MDB2_FETCHMODE_ASSOC);
         $this->db = $con;
        return $this;
    }
}
class test1 extends test_db {
    protected $mdb2;

    // コンストラクタ
    function __construct($db_name = 'test_db'){
        $this->mdb2 = parent::__construct($db_name);
    }

    function add(){
            $types = array('text','text','integer');
        $fields_values = array( 'test_char' =>    '90001111',
                                'test_varchar' =>     'テスト',
                                'test_integer' => 1
                                                                );
        $result =
$this->mdb2->db->autoExecute('test_table',$fields_values,MDB2_AUTOQUERY_INSERT,
null, $types);
        if(PEAR::isError($result)){
            return $result->getMessage();
        }
        return "DB_OK";
    }
}
$db = new test1();
$ret=$db->add();
header("content-type","html/text");
print_r($ret);
?>

(4)エラー追跡結果
①autoExecute関数
MDB2/Extended.php
function &autoExecute($table, $fields_values, $mode = MDB2_AUTOQUERY_INSERT,
        $where = false, $types = null, $result_class = true, $result_types =
MDB2_PREPARE_MANIP)
{
        $fields_values = (array)$fields_values;
        if ($mode == MDB2_AUTOQUERY_SELECT) {
            if (is_array($result_types)) {
                $keys = array_keys($result_types);
            } elseif (!empty($fields_values)) {
                $keys = $fields_values;
            } else {
                $keys = array();
            }
        } else {
            $keys = array_keys($fields_values);
        }
        $params = array_values($fields_values);
        if (empty($params)) {
            $query = $this->buildManipSQL($table, $keys, $mode, $where);

            $db =& $this->getDBInstance();
            if (PEAR::isError($db)) {
                return $db;
            }
            if ($mode == MDB2_AUTOQUERY_SELECT) {
                $result =& $db->query($query, $result_types, $result_class);
            } else {
                $result = $db->exec($query);
            }
        } else {
            $stmt = $this->autoPrepare($table, $keys, $mode, $where, $types,
$result_types);
            if (PEAR::isError($stmt)) {
                return $stmt;
            }
       【以降からエラー発生】
            $result =& $stmt->execute($params, $result_class);
            $stmt->free();
        }
        return $result;
}
②executeメソッド
function &execute($values = null, $result_class = true, $result_wrap_class =
false)
{
        if (is_null($this->positions)) {
            return $this->db->raiseError(MDB2_ERROR, null, null,
                'Prepared statement has already been freed', __FUNCTION__);
        }

        $values = (array)$values;
        if (!empty($values)) {
            $err = $this->bindValueArray($values);
            if (PEAR::isError($err)) {
                return $this->db->raiseError(MDB2_ERROR, null, null,
                                            'Binding Values failed with
message: ' . $err->getMessage(), __FUNCTION__);
            }
        }
    【以降からエラー発生】
        $result =& $this->_execute($result_class, $result_wrap_class);
        return $result;
}

③オーバーライド_executeメソッド
MDB2/driver/pgsql.php
class MDB2_Statement_pgsql extends MDB2_Statement_Common
function &_execute($result_class = true, $result_wrap_class = false)
{
        if (is_null($this->statement)) {
            $result =& parent::_execute($result_class, $result_wrap_class);
            return $result;
        }
        $this->db->last_query = $this->query;
        $this->db->debug($this->query, 'execute', array('is_manip' =>
$this->is_manip, 'when' => 'pre', 'parameters' => $this->values));
        if ($this->db->getOption('disable_query')) {
            $result = $this->is_manip ? 0 : null;
            return $result;
        }

        $connection = $this->db->getConnection();
        if (PEAR::isError($connection)) {
            return $connection;
        }

        $query = false;
        $parameters = array();
        // todo: disabled until pg_execute() bytea issues are cleared up
        if (true || !function_exists('pg_execute')) {
            $query = 'EXECUTE '.$this->statement;
        }
        if (!empty($this->positions)) {
            foreach ($this->positions as $parameter) {
                if (!array_key_exists($parameter, $this->values)) {
                    return $this->db->raiseError(MDB2_ERROR_NOT_FOUND, null,
null,
                        'Unable to bind to missing placeholder:
'.$parameter, __FUNCTION__);
                }
                $value = $this->values[$parameter];
                $type = array_key_exists($parameter, $this->types) ?
$this->types[$parameter] : null;
                if (is_resource($value) || $type == 'clob' || $type ==
'blob' || $this->db->options['lob_allow_url_include']) {
                    if (!is_resource($value) &&
preg_match('/^(\w+:\/\/)(.*)$/', $value, $match)) {
                        if ($match[1] == 'file://') {
                            $value = $match[2];
                        }
                        $value = @fopen($value, 'r');
                        $close = true;
                    }
                    if (is_resource($value)) {
                        $data = '';
                        while (!@feof($value)) {
                            $data.= @fread($value,
$this->db->options['lob_buffer_length']);
                        }
                        if ($close) {
                            @fclose($value);
                        }
                        $value = $data;
                    }
                }
         【以降からエラー発生】
                $quoted = $this->db->quote($value, $type, $query);
                if (PEAR::isError($quoted)) {
                    return $quoted;
                }
                $parameters[] = $quoted;
            }
            if ($query) {
                $query.= ' ('.implode(', ', $parameters).')';
            }
        }

        if (!$query) {
            $result = @pg_execute($connection, $this->statement,
$parameters);
            if (!$result) {
                $err =& $this->db->raiseError(null, null, null,
                    'Unable to execute statement', __FUNCTION__);
                return $err;
            }
        } else {
            $result = $this->db->_doQuery($query, $this->is_manip,
$connection);
            if (PEAR::isError($result)) {
                return $result;
}
        }

        if ($this->is_manip) {
            $affected_rows = $this->db->_affectedRows($connection, $result);
            return $affected_rows;
        }

        $result =& $this->db->_wrapResult($result, $this->result_types,
            $result_class, $result_wrap_class, $this->limit, $this->offset);
        $this->db->debug($this->query, 'execute', array('is_manip' =>
$this->is_manip, 'when' => 'post', 'result' => $result));
        return $result;
}
④quoteメソッド
MDB2/Driver/Datatype/common.php
function quote($value, $type = null, $quote = true, $escape_wildcards =
false)
{
        $db =& $this->getDBInstance();
       以降からエラー:下記の発生コメントアウトすればquoteTextメソッドからエラー
        /*
        if (PEAR::isError($db)) {
            return $db;
        }
        */
        if (is_null($value)
            || ($value === '' && $db->options['portability'] &
MDB2_PORTABILITY_EMPTY_TO_NULL)
        ) {
            if (!$quote) {
                return null;
            }
            return 'NULL';
        }

        if (is_null($type)) {
            switch (gettype($value)) {
            case 'integer':
                $type = 'integer';
                break;
            case 'double':
                // todo: default to decimal as float is quite unusual
                // $type = 'float';
                $type = 'decimal';
                break;
            case 'boolean':
                $type = 'boolean';
                break;
            case 'array':
                 $value = serialize($value);
            case 'object':
                 $type = 'text';
                break;
            default:
                if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/', $value))
{
                    $type = 'timestamp';
                } elseif (preg_match('/^\d{2}:\d{2}$/', $value)) {
                    $type = 'time';
                } elseif (preg_match('/^\d{4}-\d{2}-\d{2}$/', $value)) {
                    $type = 'date';
                } else {
                    $type = 'text';
                }
                break;
            }
        } elseif (!empty($db->options['datatype_map'][$type])) {
            $type = $db->options['datatype_map'][$type];
            if (!empty($db->options['datatype_map_callback'][$type])) {
                $parameter = array('type' => $type, 'value' => $value,
'quote' => $quote, 'escape_wildcards' => $escape_wildcards);
                return
call_user_func_array($db->options['datatype_map_callback'][$type],
array(&$db, __FUNCTION__, $parameter));
            }
        }

        if (!method_exists($this, "_quote{$type}")) {
            return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
                'type not defined: '.$type, __FUNCTION__);
        }
        $value = $this->{"_quote{$type}"}($value, $quote,
$escape_wildcards);
        if ($quote && $escape_wildcards &&
$db->string_quoting['escape_pattern']
            && $db->string_quoting['escape'] !==
$db->string_quoting['escape_pattern']
        ) {
            $value.= $this->patternEscapeString();
        }
        return $value;
}
⑤quoteTextメソッド
MDB2/Driver/Datatype/common.php
function _quoteText($value, $quote, $escape_wildcards)
{
        if (!$quote) {
            return $value;
        }

        $db =& $this->getDBInstance();
        【以降からエラー発生:quoteメソッドのコメントアウトと下記のコメントアウトすると正常に処理する】
        /*if (PEAR::isError($db)) {
            return $db;
        }
        */
        $value = $db->escape($value, $escape_wildcards);
        if (PEAR::isError($value)) {
            return $value;
        }
        return "'".$value."'";
}

-- 
View this message in context: http://old.nabble.com/%E5%86%8D%E6%8A%95%E7%A8%BF%E3%80%80WEB%E3%81%8B%E3%82%89MDB2%E3%81%AEexecute%E6%96%87%E3%81%8C%E5%AE%9F%E8%A1%8C%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%84-tp30496061p30496061.html
Sent from the Php Japan - PHP-users mailing list archive at Nabble.com.



PHP-users メーリングリストの案内