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

sakon konno @ me-h.ne.jp
2010年 12月 23日 (木) 20:30:54 JST


もう少し詳細エラー出力すようにテストプログラムを改造した。

require_once 'PEAR/ErrorStack.php';
class test1 extends test_db {
    protected $mdb2;

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

    function add(){
                $errorStack = new PEAR_ErrorStack('TEST_MDB2');
                $errorStack->pushCallback(array($this,'handleError'));
        $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(MDB2::isError($result)){
            $errorStack->push(
                1,
                'error',
                array(
                        $result->getMessage() . "<br>",
                $result->getUserInfo() . "<br>",
                $result->getDebugInfo() . "<br>"
                ),
                $result->getMessage() . "<br>"
                );
                 return;
        }
        return "DB_OK";
    }
    function handleError($err)
    {
         print_r($err);
    }
}
出力は
Array ( [code] => 1 [params] => Array ( [0] => MDB2 Error: unknown error
[1] => _doQuery: [Error message: Could not execute statement] [Last executed
query: EXECUTE
mdb2_statement_pgsql_1a50a539ebab33432c575e52a2ee0ba16836df92e ('90001111',
'テスト', 1)] [Native message: ] 
[2] => _doQuery: [Error message: Could not execute statement] [Last executed
query: EXECUTE
mdb2_statement_pgsql_1a50a539ebab33432c575e52a2ee0ba16836df92e ('90001111',
'テスト', 1)] [Native message: ] 
) [package] => TEST_MDB2 [level] => error [time] => 1293102774.8693
[context] => Array ( [file] => /home/test/db_class.php [line] => 57
[function] => add [class] => test1 ) [message] => MDB2 Error: unknown error
) 



sakon wrote:
> 
> 今回はautoExecute文を使用して切り分けをしてみた。
> 現象は、OSコマンドでプログラムを実行すると問題はないのだが、
> WEBから実行すると「MDB2 Error: unknown error」のエラー
> が返り実行できない。
> OSとWEB上の違いはheader("content-type","html/text");
> だけです。
> 切り分けた結果は、common.phpのqouteメソッド
> 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://xxxxx:xxxxx@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-tp30496061p30520234.html
Sent from the Php Japan - PHP-users mailing list archive at Nabble.com.



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