[PHP-users 14928]Re: [PHP-users14665]PEARでクエリが実行されるときとされない時がある

Osamu Shigematsu m5issige @ mr.hitachi-medical.co.jp
2003年 4月 25日 (金) 15:17:01 JST


重松です。こんにちは。

今回のケースでは、PostgreSQL を使うと明示してあるので、まず、
PostgreSQL に限定して、考えてみました。

その上で、

>  rollback()メソッドを呼んで実際にロールバックが行われるのは、
> autocommitをデフォルトのtrueからfalseに変えた後に、更新系のsqlが
> 成功している場合のみのようです。
> 
> sorako yamamotoさんの場合はtrueのままなのでロールバックは
> この場合、query('ROLLBACK')メソッドのコールですね。

で、これなんですけど、私は思いっきり誤解していたようなので、
整理してみました。

# きっと他の人にも参考になるはず。長いですがご容赦を。

rollback() は以下のように実装されています。

function rollback()
{
if ($this->transaction_opcount > 0) {
    $result = @pg_exec($this->connection, "abort;");
    $this->transaction_opcount = 0;
    if (!$result) {
	return $this->pgsqlRaiseError();
    }
}
return DB_OK;
}

つまり、rollback 処理が実行されるかどうか、それは即ち、
transaction_opcount が 0 より大きな場合のようです。

そして、この transaction_opcount を ++ しているのは、
ただ一箇所、simpleQuery() 内部であり、

function simpleQuery($query)
{
$ismanip = DB::isManip($query);
$this->last_query = $query;
$query = $this->modifyQuery($query);
if (!$this->autocommit && $ismanip) {
    if ($this->transaction_opcount == 0) {
	$result = @pg_exec($this->connection, "begin;");
	if (!$result) {
	    return $this->pgsqlRaiseError();
	}
    }
    $this->transaction_opcount++;
}
// 省略
}

のようになっており、transaction_opcount が increment されるのは、

(1) ! autocommit、即ち autocommit が false の場合、かつ、
(2) 更新処理が行われる SQL 文である。即ち、DB::isManip() の戻り値が真。
	-> 行えたかどうかではなく、構文の確認の結果である。

ということのようですね。

だとすると、明示的に autoCommit(false) した場合に、自動的に BEGIN,
COMMIT 等が実行され (もちろん、DB によって変わると思います)、
デフォルトでは、自前処理することがあるってことですね。

また、今回の PostgreSQL の場合は、modifyQuery() は空っぽでしたが、
MySQL の場合、この部分で query を実行しているようです。

なので、このあたりは、処理系によって、実行される内容が違う、
ということのようです。

逆説的に言えば、simpleQuery() は、どのような関数として定義されているか、
それをまず明確にした方がいいのかもしれません。

けど、
http://pear.php.net/manual/ja/core.db.php
には、そういうレベルの文章は、見当たりませんでした。

Mashiki さん、細かいなんてとんでもない。
誤りをフォローしてくださって、ありがとうございました。

まだ、誤解しているところなんかがありそうなので、
嘘がありましたら、指摘 (& 訂正) いただければと思います。

-- 
Osamu Shigematsu <m5issige @ mr.hitachi-medical.co.jp>




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