source: branches/version-2_12-dev/data/class/SC_Query.php @ 21441

Revision 21441, 33.7 KB checked in by Seasoft, 12 years ago (diff)

#1613 (ソース整形・ソースコメントの改善)

  • Zend Framework PHP 標準コーディング規約への準拠を高めた
  • Property svn:eol-style set to LF
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-httpd-php; charset=UTF-8
Line 
1<?php
2/*
3 * This file is part of EC-CUBE
4 *
5 * Copyright(c) 2000-2011 LOCKON CO.,LTD. All Rights Reserved.
6 *
7 * http://www.lockon.co.jp/
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22 */
23
24require_once realpath(dirname(__FILE__)) . '/../module/MDB2.php';
25
26/**
27 * SQLの構築・実行を行う
28 *
29 * TODO エラーハンドリング, ロギング方法を見直す
30 *
31 * @author LOCKON CO.,LTD.
32 * @version $Id$
33 */
34class SC_Query {
35
36    var $option = '';
37    var $where = '';
38    var $arrWhereVal = array();
39    var $conn;
40    var $groupby = '';
41    var $order = '';
42    var $force_run;
43
44    /**
45     * コンストラクタ.
46     *
47     * @param string $dsn データソース名
48     * @param boolean $force_run エラーが発生しても処理を続行する場合 true
49     * @param boolean $new 新規に接続を行うかどうか
50     */
51    function SC_Query($dsn = "", $force_run = false, $new = false) {
52
53        if ($dsn == "") {
54            $dsn = DEFAULT_DSN;
55        }
56
57        // Debugモード指定
58        // 常時ONにするとメモリが解放されない。
59        // 連続クエリ実行時に問題が生じる。
60        if (DEBUG_MODE) {
61            $options['debug'] = PEAR_DB_DEBUG;
62        } else {
63            $options['debug'] = 0;
64        }
65
66        // 持続的接続オプション
67        $options['persistent'] = PEAR_DB_PERSISTENT;
68
69        // バッファリング trueにするとメモリが解放されない。
70        // 連続クエリ実行時に問題が生じる。
71        $options['result_buffering'] = false;
72
73        if ($new) {
74            $this->conn = MDB2::connect($dsn, $options);
75        } else {
76            $this->conn = MDB2::singleton($dsn, $options);
77        }
78        if (!PEAR::isError($this->conn)) {
79            $this->conn->setCharset("utf8");
80            $this->conn->setFetchMode(MDB2_FETCHMODE_ASSOC);
81        }
82        $this->dbFactory = SC_DB_DBFactory_Ex::getInstance();
83        $this->force_run = $force_run;
84    }
85
86    /**
87     * シングルトンの SC_Query インスタンスを取得する.
88     *
89     * @param string $dsn データソース名
90     * @param boolean $force_run エラーが発生しても処理を続行する場合 true
91     * @param boolean $new 新規に接続を行うかどうか
92     * @return SC_Query シングルトンの SC_Query インスタンス
93     */
94    function getSingletonInstance($dsn = "", $force_run = false, $new = false) {
95        if (!isset($GLOBALS['_SC_Query_instance'])
96            || is_null($GLOBALS['_SC_Query_instance'])) {
97            $GLOBALS['_SC_Query_instance'] =& new SC_Query_Ex($dsn, $force_run, $new);
98        }
99        $GLOBALS['_SC_Query_instance']->where = '';
100        $GLOBALS['_SC_Query_instance']->arrWhereVal = array();
101        $GLOBALS['_SC_Query_instance']->order = '';
102        $GLOBALS['_SC_Query_instance']->groupby = '';
103        $GLOBALS['_SC_Query_instance']->option = '';
104        return $GLOBALS['_SC_Query_instance'];
105    }
106
107    /**
108     * エラー判定を行う.
109     *
110     * @deprecated PEAR::isError() を使用して下さい
111     * @return boolean
112     */
113    function isError() {
114        if (PEAR::isError($this->conn)) {
115            return true;
116        }
117        return false;
118    }
119
120    /**
121     * COUNT文を実行する.
122     *
123     * @param string $table テーブル名
124     * @param string $where where句
125     * @param array $arrWhereVal プレースホルダ
126     * @return integer 件数
127     */
128    function count($table, $where = '', $arrWhereVal = array()) {
129        return $this->get('COUNT(*)', $table, $where, $arrWhereVal);
130    }
131
132    /**
133     * EXISTS文を実行する.
134     *
135     * @param string $table テーブル名
136     * @param string $where where句
137     * @param array $arrWhereVal プレースホルダ
138     * @return boolean 有無
139     */
140    function exists($table, $where = '', $arrWhereVal = array()) {
141        $sql_inner = $this->getSql('*', $table, $where, $arrWhereVal);
142        $sql = "SELECT CASE WHEN EXISTS($sql_inner) THEN 1 ELSE 0 END";
143        $res = $this->getOne($sql, $arrWhereVal);
144        return (bool)$res;
145    }
146
147    /**
148     * SELECT文を実行する.
149     *
150     * @param string $col カラム名. 複数カラムの場合はカンマ区切りで書く
151     * @param string $table テーブル名
152     * @param string $where WHERE句
153     * @param array $arrWhereVal プレースホルダ
154     * @param integer $fetchmode 使用するフェッチモード。デフォルトは MDB2_FETCHMODE_ASSOC。
155     * @return array|null
156     */
157    function select($col, $table, $where = "", $arrWhereVal = array(), $fetchmode = MDB2_FETCHMODE_ASSOC) {
158        $sqlse = $this->getSql($col, $table, $where, $arrWhereVal);
159        return $this->getAll($sqlse, $arrWhereVal, $fetchmode);
160    }
161
162    /**
163     * 直前に実行されたSQL文を取得する.
164     *
165     * @param boolean $disp trueの場合、画面出力を行う.
166     * @return string SQL文
167     */
168    function getLastQuery($disp = true) {
169        $sql = $this->conn->last_query;
170        if ($disp) {
171            echo $sql . ";<br />\n";
172        }
173        return $sql;
174    }
175
176    /**
177     * トランザクションをコミットする.
178     *
179     * @return MDB2_OK 成功した場合は MDB2_OK;
180     *         失敗した場合は PEAR::Error オブジェクト
181     */
182    function commit() {
183        return $this->conn->commit();
184    }
185
186    /**
187     * トランザクションを開始する.
188     *
189     * @return MDB2_OK 成功した場合は MDB2_OK;
190     *         失敗した場合は PEAR::Error オブジェクト
191     */
192    function begin() {
193        return $this->conn->beginTransaction();
194    }
195
196    /**
197     * トランザクションをロールバックする.
198     *
199     * @return MDB2_OK 成功した場合は MDB2_OK;
200     *         失敗した場合は PEAR::Error オブジェクト
201     */
202    function rollback() {
203        return $this->conn->rollback();
204    }
205
206    /**
207     * トランザクションが開始されているかチェックする.
208     *
209     * @return boolean トランザクションが開始されている場合 true
210     */
211    function inTransaction() {
212        return $this->conn->inTransaction();
213    }
214
215    /**
216     * 更新系の SQL を実行する.
217     *
218     * この関数は SC_Query::query() のエイリアスです.
219     *
220     * FIXME MDB2::exec() の実装であるべき
221     */
222    function exec($str, $arrval = array()) {
223        return $this->query($str, $arrval);
224    }
225
226    /**
227     * クエリを実行し、結果行毎にコールバック関数を適用する
228     *
229     * @param callback $function コールバック先
230     * @param string $sql SQL クエリ
231     * @param array $arrVal プリペアドステートメントの実行時に使用される配列。配列の要素数は、クエリ内のプレースホルダの数と同じでなければなりません。
232     * @param integer $fetchmode 使用するフェッチモード。デフォルトは DB_FETCHMODE_ASSOC。
233     * @return boolean 結果
234     */
235    function doCallbackAll($cbFunc, $sql, $arrval = array(), $fetchmode = MDB2_FETCHMODE_ASSOC) {
236
237        $sql = $this->dbFactory->sfChangeMySQL($sql);
238
239        $sth =& $this->prepare($sql);
240        if (PEAR::isError($sth) && $this->force_run) {
241            return;
242        }
243
244        $affected =& $this->execute($sth, $arrval);
245        if (PEAR::isError($affected) && $this->force_run) {
246            return;
247        }
248
249        while ($data = $affected->fetchRow($fetchmode)) {
250            $result = call_user_func($cbFunc, $data);
251            if ($result === false) {
252                break;
253            }
254        }
255        $sth->free();
256        return $result;
257    }
258
259    /**
260     * クエリを実行し、全ての行を返す
261     *
262     * @param string $sql SQL クエリ
263     * @param array $arrVal プリペアドステートメントの実行時に使用される配列。配列の要素数は、クエリ内のプレースホルダの数と同じでなければなりません。
264     * @param integer $fetchmode 使用するフェッチモード。デフォルトは DB_FETCHMODE_ASSOC。
265     * @return array データを含む2次元配列。失敗した場合に 0 または DB_Error オブジェクトを返します。
266     */
267    function getAll($sql, $arrval = array(), $fetchmode = MDB2_FETCHMODE_ASSOC) {
268
269        $sql = $this->dbFactory->sfChangeMySQL($sql);
270
271        $sth =& $this->prepare($sql);
272        if (PEAR::isError($sth) && $this->force_run) {
273            return;
274        }
275
276        $affected =& $this->execute($sth, $arrval);
277        if (PEAR::isError($affected) && $this->force_run) {
278            return;
279        }
280
281        // MySQL での不具合対応のため、一旦変数に退避
282        $arrRet = $affected->fetchAll($fetchmode);
283
284        // PREPAREの解放
285        $sth->free();
286
287        return $arrRet;
288    }
289
290    /**
291     * 構築した SELECT 文を取得する.
292     *
293     * クラス変数から WHERE 句を組み立てる場合、$arrWhereVal を経由してプレースホルダもクラス変数のもので上書きする。
294     * @param string $col SELECT 文に含めるカラム名
295     * @param string $table SELECT 文に含めるテーブル名
296     * @param string $where SELECT 文に含める WHERE 句
297     * @param mixed $arrWhereVal プレースホルダ(参照)
298     * @return string 構築済みの SELECT 文
299     */
300    function getSql($col, $table, $where = '', &$arrWhereVal = null) {
301        $sqlse = "SELECT $col FROM $table";
302
303        // 引数の$whereを優先する。
304        if (strlen($where) >= 1) {
305            $sqlse .= " WHERE $where";
306        } elseif (strlen($this->where) >= 1) {
307            $sqlse .= " WHERE " . $this->where;
308            // 実行時と同じくキャストしてから評価する (空文字を要素1の配列と評価させる意図)
309            $arrWhereValForEval = (array)$arrWhereVal;
310            if (empty($arrWhereValForEval)) {
311                $arrWhereVal = $this->arrWhereVal;
312            }
313        }
314
315        $sqlse .= ' ' . $this->groupby . ' ' . $this->order . ' ' . $this->option;
316
317        return $sqlse;
318    }
319
320    /**
321     * SELECT 文の末尾に付与する SQL を設定する.
322     *
323     * この関数で設定した値は SC_Query::getSql() で使用されます.
324     *
325     * @param string $str 付与する SQL 文
326     * @return SC_Query 自分自身のインスタンス
327     */
328    function setOption($str) {
329        $this->option = $str;
330        return $this;
331    }
332
333    /**
334     * SELECT 文に付与する LIMIT, OFFSET 句を設定する.
335     *
336     * この関数で設定した値は SC_Query::getSql() で使用されます.
337     * TODO MDB2::setLimit() を使用する
338     *
339     * @param integer $limit LIMIT 句に付与する値
340     * @param integer $offset OFFSET 句に付与する値
341     * @return SC_Query 自分自身のインスタンス
342     */
343    function setLimitOffset($limit, $offset = 0) {
344        if (is_numeric($limit) && is_numeric($offset)) {
345
346            $option = " LIMIT " . $limit;
347            $option.= " OFFSET " . $offset;
348            $this->option .= $option;
349        }
350        return $this;
351    }
352
353    /**
354     * SELECT 文に付与する GROUP BY 句を設定する.
355     *
356     * この関数で設定した値は SC_Query::getSql() で使用されます.
357     *
358     * @param string $str GROUP BY 句に付与する文字列
359     * @return SC_Query 自分自身のインスタンス
360     */
361    function setGroupBy($str) {
362        if (strlen($str) == 0) {
363            $this->groupby = '';
364        } else {
365            $this->groupby = "GROUP BY " . $str;
366        }
367        return $this;
368    }
369
370    /**
371     * SELECT 文の WHERE 句に付与する AND 条件を設定する.
372     *
373     * この関数で設定した値は SC_Query::getSql() で使用されます.
374     *
375     * @param string $str WHERE 句に付与する AND 条件の文字列
376     * @return SC_Query 自分自身のインスタンス
377     */
378    function andWhere($str) {
379        if ($this->where != "") {
380            $this->where .= " AND " . $str;
381        } else {
382            $this->where = $str;
383        }
384        return $this;
385    }
386
387    /**
388     * SELECT 文の WHERE 句に付与する OR 条件を設定する.
389     *
390     * この関数で設定した値は SC_Query::getSql() で使用されます.
391     *
392     * @param string $str WHERE 句に付与する OR 条件の文字列
393     * @return SC_Query 自分自身のインスタンス
394     */
395    function orWhere($str) {
396        if ($this->where != "") {
397            $this->where .= " OR " . $str;
398        } else {
399            $this->where = $str;
400        }
401        return $this;
402    }
403
404    /**
405     * SELECT 文に付与する WHERE 句を設定する.
406     *
407     * この関数で設定した値は SC_Query::getSql() で使用されます.
408     *
409     * @param string $where WHERE 句に付与する文字列
410     * @param mixed $arrWhereVal プレースホルダ
411     * @return SC_Query 自分自身のインスタンス
412     */
413    function setWhere($where = '', $arrWhereVal = array()) {
414        $this->where = $where;
415        $this->arrWhereVal = $arrWhereVal;
416        return $this;
417    }
418
419    /**
420     * SELECT 文に付与する ORDER BY 句を設定する.
421     *
422     * この関数で設定した値は SC_Query::getSql() で使用されます.
423     *
424     * @param string $str ORDER BY 句に付与する文字列
425     * @return SC_Query 自分自身のインスタンス
426     */
427    function setOrder($str) {
428        if (strlen($str) == 0) {
429            $this->order = '';
430        } else {
431            $this->order = "ORDER BY " . $str;
432        }
433        return $this;
434    }
435
436    /**
437     * SELECT 文に付与する LIMIT 句を設定する.
438     *
439     * この関数で設定した値は SC_Query::getSql() で使用されます.
440     *
441     * @param integer $limit LIMIT 句に設定する値
442     * @return SC_Query 自分自身のインスタンス
443     */
444    function setLimit($limit){
445        if (is_numeric($limit)) {
446            $this->option = " LIMIT " .$limit;
447        }
448        return $this;
449    }
450
451    /**
452     * SELECT 文に付与する OFFSET 句を設定する.
453     *
454     * この関数で設定した値は SC_Query::getSql() で使用されます.
455     *
456     * @param integer $offset LIMIT 句に設定する値
457     * @return SC_Query 自分自身のインスタンス
458     */
459    function setOffset($offset) {
460        if (is_numeric($offset)) {
461            $this->offset = " OFFSET " .$offset;
462        }
463        return $this;
464    }
465
466    /**
467     * INSERT文を実行する.
468     *
469     * @param string $table テーブル名
470     * @param array $sqlval array('カラム名' => '値',...)の連想配列
471     * @param array $arrSql array('カラム名' => 'SQL文',...)の連想配列
472     * @param array $arrSqlVal SQL文の中で使用するプレースホルダ配列
473     * @return
474     */
475    function insert($table, $sqlval, $arrSql = array(), $arrSqlVal = array()) {
476        $strcol = '';
477        $strval = '';
478        $find = false;
479        $arrVal = array();
480
481        if(count($sqlval) <= 0 ) return false;
482        foreach ($sqlval as $key => $val) {
483            $strcol .= $key . ',';
484            if (strcasecmp("Now()", $val) === 0) {
485                $strval .= 'Now(),';
486            } else if (strcasecmp('CURRENT_TIMESTAMP', $val) === 0) {
487                $strval .= 'CURRENT_TIMESTAMP,';
488            } else {
489                $strval .= '?,';
490                $arrVal[] = $val;
491            }
492            $find = true;
493        }
494
495        foreach ($arrSql as $key => $val) {
496            $strcol .= $key . ',';
497            $strval .= $val . ',';
498        }
499
500        $arrVal = array_merge($arrVal, $arrSqlVal);
501
502        if (!$find) {
503            return false;
504        }
505        // 文末の","を削除
506        $strcol = preg_replace("/,$/", "", $strcol);
507        $strval = preg_replace("/,$/", "", $strval);
508        $sqlin = "INSERT INTO $table(" . $strcol. ") VALUES (" . $strval . ")";
509        // INSERT文の実行
510        $ret = $this->query($sqlin, $arrVal, false, null, MDB2_PREPARE_MANIP);
511
512        return $ret;
513    }
514
515    /**
516     * UPDATE文を実行する.
517     *
518     * @param string $table テーブル名
519     * @param array $sqlval array('カラム名' => '値',...)の連想配列
520     * @param string $where WHERE句
521     * @param array $arrWhereVal WHERE句用のプレースホルダ配列 (従来は追加カラム用も兼ねていた)
522     * @param array $arrRawSql 追加カラム
523     * @param array $arrRawSqlVal 追加カラム用のプレースホルダ配列
524     * @return
525     */
526    function update($table, $sqlval, $where = "", $arrWhereVal = array(), $arrRawSql = array(), $arrRawSqlVal = array()) {
527        $arrCol = array();
528        $arrVal = array();
529        $find = false;
530
531        foreach ($sqlval as $key => $val) {
532            if (strcasecmp("Now()", $val) === 0) {
533                $arrCol[] = $key . '= Now()';
534            } else if (strcasecmp('CURRENT_TIMESTAMP', $val) === 0) {
535                $arrCol[] = $key . '= CURRENT_TIMESTAMP';
536            } else {
537                $arrCol[] = $key . '= ?';
538                $arrVal[] = $val;
539            }
540            $find = true;
541        }
542
543        if ($arrRawSql != "") {
544            foreach ($arrRawSql as $key => $val) {
545                $arrCol[] = "$key = $val";
546            }
547        }
548
549        $arrVal = array_merge($arrVal, $arrRawSqlVal);
550
551        if (empty($arrCol)) {
552            return false;
553        }
554
555        // 文末の","を削除
556        $strcol = implode(', ', $arrCol);
557
558        if (is_array($arrWhereVal)) { // 旧版との互換用
559            // プレースホルダー用に配列を追加
560            $arrVal = array_merge($arrVal, $arrWhereVal);
561        }
562
563        $sqlup = "UPDATE $table SET $strcol";
564        if (strlen($where) >= 1) {
565            $sqlup .= " WHERE $where";
566        }
567
568        // UPDATE文の実行
569        return $this->query($sqlup, $arrVal, false, null, MDB2_PREPARE_MANIP);
570    }
571
572    /**
573     * MAX文を実行する.
574     *
575     * @param string $table テーブル名
576     * @param string $col カラム名
577     * @param string $where 付与する WHERE 句
578     * @param array $arrval プレースホルダに挿入する値
579     * @return integer MAX文の実行結果
580     */
581    function max($col, $table, $where = "", $arrval = array()) {
582        $ret = $this->get("MAX($col)", $table, $where, $arrval);
583        return $ret;
584    }
585
586    /**
587     * MIN文を実行する.
588     *
589     * @param string $table テーブル名
590     * @param string $col カラム名
591     * @param string $where 付与する WHERE 句
592     * @param array $arrval プレースホルダに挿入する値
593     * @return integer MIN文の実行結果
594     */
595    function min($col, $table, $where = "", $arrval = array()) {
596        $ret = $this->get("MIN($col)", $table, $where, $arrval);
597        return $ret;
598    }
599
600    /**
601     * SQL を構築して, 特定のカラムの値を取得する.
602     *
603     * @param string $table テーブル名
604     * @param string $col カラム名
605     * @param string $where 付与する WHERE 句
606     * @param array $arrWhereVal プレースホルダに挿入する値
607     * @return mixed SQL の実行結果
608     */
609    function get($col, $table, $where = "", $arrWhereVal = array()) {
610        $sqlse = $this->getSql($col, $table, $where, $arrWhereVal);
611        // SQL文の実行
612        $ret = $this->getOne($sqlse, $arrWhereVal);
613        return $ret;
614    }
615
616    /**
617     * SQL を指定して, 特定のカラムの値を取得する.
618     *
619     * @param string $sql 実行する SQL
620     * @param array $arrval プレースホルダに挿入する値
621     * @return mixed SQL の実行結果
622     */
623    function getOne($sql, $arrval = array()) {
624
625        $sql = $this->dbFactory->sfChangeMySQL($sql);
626
627        $sth =& $this->prepare($sql);
628        if (PEAR::isError($sth) && $this->force_run) {
629            return;
630        }
631
632        $affected =& $this->execute($sth, $arrval);
633        if (PEAR::isError($affected) && $this->force_run) {
634            return;
635        }
636
637        // MySQL での不具合対応のため、一旦変数に退避
638        $arrRet = $affected->fetchOne();
639
640        // PREPAREの解放
641        $sth->free();
642
643        return $arrRet;
644    }
645
646    /**
647     * 一行をカラム名をキーとした連想配列として取得
648     *
649     * @param string $table テーブル名
650     * @param string $col カラム名
651     * @param string $where WHERE句
652     * @param array $arrWhereVal プレースホルダ配列
653     * @param integer $fetchmode 使用するフェッチモード。デフォルトは MDB2_FETCHMODE_ASSOC。
654     * @return array array('カラム名' => '値', ...)の連想配列
655     */
656    function getRow($col, $table, $where = "", $arrWhereVal = array(), $fetchmode = MDB2_FETCHMODE_ASSOC) {
657
658        $sql = $this->getSql($col, $table, $where, $arrWhereVal);
659        $sql = $this->dbFactory->sfChangeMySQL($sql);
660
661        $sth =& $this->prepare($sql);
662        if (PEAR::isError($sth) && $this->force_run) {
663            return;
664        }
665
666        $affected =& $this->execute($sth, $arrWhereVal);
667        if (PEAR::isError($affected) && $this->force_run) {
668            return;
669        }
670
671        // MySQL での不具合対応のため、一旦変数に退避
672        $arrRet = $affected->fetchRow($fetchmode);
673
674        // PREPAREの解放
675        $sth->free();
676
677        return $arrRet;
678    }
679
680    /**
681     * SELECT 文の実行結果を 1列のみ取得する.
682     *
683     * @param string $table テーブル名
684     * @param string $col カラム名
685     * @param string $where 付与する WHERE 句
686     * @param array $arrWhereVal プレースホルダに挿入する値
687     * @return array SQL の実行結果の配列
688     */
689    function getCol($col, $table, $where = "", $arrWhereVal = array()) {
690        $sql = $this->getSql($col, $table, $where, $arrWhereVal);
691        $sql = $this->dbFactory->sfChangeMySQL($sql);
692
693        $sth =& $this->prepare($sql);
694        if (PEAR::isError($sth) && $this->force_run) {
695            return;
696        }
697
698        $affected =& $this->execute($sth, $arrWhereVal);
699        if (PEAR::isError($affected) && $this->force_run) {
700            return;
701        }
702
703        // MySQL での不具合対応のため、一旦変数に退避
704        $arrRet = $affected->fetchCol();
705
706        // PREPAREの解放
707        $sth->free();
708
709        return $arrRet;
710    }
711
712    /**
713     * レコードの削除
714     *
715     * @param string $table テーブル名
716     * @param string $where WHERE句
717     * @param array $arrval プレースホルダ
718     * @return
719     */
720    function delete($table, $where = "", $arrval = array()) {
721        if (strlen($where) <= 0) {
722            $sqlde = "DELETE FROM $table";
723        } else {
724            $sqlde = "DELETE FROM $table WHERE $where";
725        }
726        $ret = $this->query($sqlde, $arrval, false, null, MDB2_PREPARE_MANIP);
727        return $ret;
728    }
729
730    /**
731     * 次のシーケンス値を取得する.
732     *
733     * @param string $seq_name 取得するシーケンス名
734     * @param integer 次のシーケンス値
735     */
736    function nextVal($seq_name) {
737        return $this->conn->nextID($seq_name);
738    }
739
740    /**
741     * 現在のシーケンス値を取得する.
742     *
743     * @param string $seq_name 取得するシーケンス名
744     * @return integer 現在のシーケンス値
745     */
746    function currVal($seq_name) {
747        return $this->conn->currID($seq_name);
748    }
749
750    /**
751     * シーケンス値を設定する.
752     *
753     * @param string $seq_name シーケンス名
754     * @param integer $start 設定するシーケンス値
755     * @return MDB2_OK
756     */
757    function setVal($seq_name, $start) {
758        $objManager =& $this->conn->loadModule('Manager');
759        // XXX エラーハンドリングを行う
760        $objManager->dropSequence($seq_name);
761        return $objManager->createSequence($seq_name, $start);
762    }
763
764    /**
765     * SQL を実行する.
766     *
767     * FIXME $ignore_errが無視されるようになっているが互換性として問題が無いか確認が必要
768     *
769     * @param string $n 実行する SQL 文
770     * @param array $arr プレースホルダに挿入する値
771     * @param boolean $ignore_err MDB2切替で無効化されている (エラーが発生しても処理を続行する場合 true)
772     * @param mixed $types プレースホルダの型指定 デフォルトnull = string
773     * @param mixed $result_types 返値の型指定またはDML実行(MDB2_PREPARE_MANIP)
774     * @return array SQL の実行結果の配列
775     */
776    function query($n ,$arr = array(), $ignore_err = false, $types = null, $result_types = MDB2_PREPARE_RESULT ){
777
778        $n = $this->dbFactory->sfChangeMySQL($n);
779
780        $sth =& $this->prepare($n, $types, $result_types);
781        if (PEAR::isError($sth) && $this->force_run) {
782            return $sth;
783        }
784
785        $result = $this->execute($sth, $arr);
786        if (PEAR::isError($result) && $this->force_run) {
787            return $sth;
788        }
789
790        // PREPAREの解放
791        $sth->free();
792
793        return $result;
794    }
795
796    /**
797     * シーケンスの一覧を取得する.
798     *
799     * @return array シーケンス名の配列
800     */
801    function listSequences() {
802        $objManager =& $this->conn->loadModule('Manager');
803        return $objManager->listSequences();
804    }
805
806    /**
807     * テーブル一覧を取得する.
808     *
809     * @return array テーブル名の配列
810     */
811    function listTables() {
812        $objManager =& $this->conn->loadModule('Manager');
813        return $objManager->listTables();
814    }
815
816    /**
817     * テーブルのカラム一覧を取得する.
818     *
819     * @param string $table テーブル名
820     * @return array 指定のテーブルのカラム名の配列
821     */
822    function listTableFields($table) {
823        $objManager =& $this->conn->loadModule('Manager');
824        return $objManager->listTableFields($table);
825    }
826
827    /**
828     * テーブルのインデックス一覧を取得する.
829     *
830     * @param string $table テーブル名
831     * @return array 指定のテーブルのインデックス一覧
832     */
833    function listTableIndexes($table) {
834        $objManager =& $this->conn->loadModule('Manager');
835        return $objManager->listTableIndexes($table);
836    }
837
838    /**
839     * テーブルにインデックスを付与する
840     *
841     * @param string $table テーブル名
842     * @param string $name インデックス名
843     * @param array $definition フィールド名など 通常のフィールド指定時は、$definition=array('fields' => array('フィールド名' => array()));
844     *               MySQLのtext型フィールドを指定する場合は $definition['length'] = 'text_field(NNN)' が必要
845     */
846    function createIndex($table, $name, $definition) {
847        $definition = $this->dbFactory->sfGetCreateIndexDefinition($table, $name, $definition);
848        $objManager =& $this->conn->loadModule('Manager');
849        return $objManager->createIndex($table, $name, $definition);
850    }
851
852    /**
853     * テーブルにインデックスを破棄する
854     *
855     * @param string $table テーブル名
856     * @param string $name インデックス名
857     */
858    function dropIndex($table, $name) {
859        $objManager =& $this->conn->loadModule('Manager');
860        return $objManager->dropIndex($table, $name);
861    }
862
863    /**
864     * テーブルの詳細情報を取得する。
865     *
866     * @param string $table テーブル名
867     * @return array テーブル情報の配列
868     */
869    function getTableInfo($table) {
870        $objManager =& $this->conn->loadModule('Reverse');
871        return $objManager->tableInfo($table, NULL);
872    }
873
874    /**
875     * 値を適切にクォートする.
876     *
877     * TODO MDB2 に対応するための暫定的な措置.
878     *      プレースホルダが使用できない実装があるため.
879     *      本来であれば, MDB2::prepare() を適切に使用するべき
880     *
881     * @see MDB2::quote()
882     * @param string $val クォートを行う文字列
883     * @return string クォートされた文字列
884     */
885    function quote($val) {
886        return $this->conn->quote($val);
887    }
888
889    /**
890     * パラメーターの連想配列から, テーブルに存在する列のみを取得する.
891     *
892     * @param string $table テーブル名
893     * @param array プレースホルダの連想配列
894     * @return array テーブルに存在する列のみ抽出した連想配列
895     */
896    function extractOnlyColsOf($table, $arrParams) {
897        $arrCols = $this->listTableFields($table);
898        $arrResults = array();
899        foreach ($arrParams as $key => $val) {
900            if (in_array($key, $arrCols)) {
901                $arrResults[$key] = $val;
902            }
903        }
904        return $arrResults;
905    }
906
907    /**
908     * プリペアドステートメントを構築する.
909     *
910     * @access private
911     * @param string $sql プリペアドステートメントを構築する SQL
912     * @param mixed $types プレースホルダの型指定 デフォルト null
913     * @param mixed $result_types 返値の型指定またはDML実行(MDB2_PREPARE_MANIP)、nullは指定無し
914     * @return MDB2_Statement_Common プリペアドステートメントインスタンス
915     */
916    function prepare($sql, $types = null, $result_types = MDB2_PREPARE_RESULT) {
917        $sth =& $this->conn->prepare($sql, $types, $result_types);
918        if (PEAR::isError($sth)) {
919            if (!$this->force_run) {
920                trigger_error($this->traceError($sth, $sql), E_USER_ERROR);
921            } else {
922                error_log($this->traceError($sth, $sql), 3, LOG_REALFILE);
923            }
924        }
925        return $sth;
926    }
927
928    /**
929     * プリペアドクエリを実行する.
930     *
931     * @access private
932     * @param MDB2_Statement_Common プリペアドステートメントインスタンス
933     * @param array $arrVal プレースホルダに挿入する配列
934     * @return MDB2_Result 結果セットのインスタンス
935     */
936    function execute(&$sth, $arrVal = array()) {
937        $timeStart = SC_Utils_Ex::sfMicrotimeFloat();
938        $affected =& $sth->execute((array)$arrVal);
939
940        // 一定以上時間かかったSQLの場合、ログ出力する。
941        if (defined('SQL_QUERY_LOG_MODE') && SQL_QUERY_LOG_MODE == true) {
942            $timeEnd = SC_Utils_Ex::sfMicrotimeFloat();;
943            $timeExecTime = $timeEnd - $timeStart;
944            if (defined('SQL_QUERY_LOG_MIN_EXEC_TIME') && $timeExecTime >= (float)SQL_QUERY_LOG_MIN_EXEC_TIME) {
945                $logMsg = sprintf("SQL_LOG [%.2fsec]\n%s", $timeExecTime, $sth->query) . "\n";
946                error_log($logMsg, 3, LOG_REALFILE);
947            }
948        }
949
950        if (PEAR::isError($affected)) {
951            $sql = isset($sth->query) ? $sth->query : '';
952            if (!$this->force_run) {
953                trigger_error($this->traceError($affected, $sql, $arrVal), E_USER_ERROR);
954            } else {
955                error_log($this->traceError($affected, $sql, $arrVal), 3, LOG_REALFILE);
956            }
957        }
958        $this->conn->last_query = stripslashes($sth->query);
959        return $affected;
960    }
961
962    /**
963     * エラーの内容をトレースする.
964     *
965     * @access private
966     * @param PEAR::Error $error PEAR::Error インスタンス
967     * @param string $sql エラーの発生した SQL 文
968     * @param array $arrVal プレースホルダ
969     * @return string トレースしたエラー文字列
970     */
971    function traceError($error, $sql = "", $arrVal = false) {
972        $scheme = '';
973        if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') {
974            $scheme = "http://";
975        } else {
976            $scheme = "https://";
977        }
978
979        $err = $scheme . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] . "\n\n"
980            . "SERVER_ADDR: " . $_SERVER['SERVER_ADDR'] . "\n"
981            . "REMOTE_ADDR: " . $_SERVER['REMOTE_ADDR'] . "\n"
982            . "USER_AGENT: " . $_SERVER['HTTP_USER_AGENT'] . "\n\n"
983            . "SQL: " . $sql . "\n\n";
984        if ($arrVal !== false) {
985            $err .= "PlaceHolder: " . var_export($arrVal, true) . "\n\n";
986        }
987        $err .= $error->getMessage() . "\n\n";
988        $err .= $error->getUserInfo() . "\n\n";
989
990        $err .= SC_Utils_Ex::sfBacktraceToString($error->getBackTrace());
991
992        return $err;
993    }
994
995    /**
996     * SQLクエリの結果セットのカラム名だけを取得する
997     *
998     * @param string $n 実行する SQL 文
999     * @param array $arr プレースホルダに挿入する値
1000     * @param boolean エラーが発生しても処理を続行する場合 true
1001     * @param mixed $types プレースホルダの型指定 デフォルトnull = string
1002     * @param mixed $result_types 返値の型指定またはDML実行(MDB2_PREPARE_MANIP)
1003     * @return array 実行結果の配列
1004     */
1005    function getQueryDefsFields($n ,$arr = array(), $ignore_err = false, $types = null, $result_types = MDB2_PREPARE_RESULT ){
1006
1007        $n = $this->dbFactory->sfChangeMySQL($n);
1008
1009        $sth =& $this->prepare($n, $types, $result_types);
1010        if (PEAR::isError($sth) && ($this->force_run || $ignore_err)) {
1011            return;
1012        }
1013
1014        $result = $this->execute($sth, $arr);
1015        if (PEAR::isError($result) && ($this->force_run || $ignore_err)) {
1016            return;
1017        }
1018        $arrRet = $result->getColumnNames();
1019        // PREPAREの解放
1020        $sth->free();
1021
1022        return $arrRet;
1023    }
1024
1025}
Note: See TracBrowser for help on using the repository browser.