source: branches/version-2_5-dev/data/class/SC_Query.php @ 20671

Revision 20671, 31.4 KB checked in by nanasess, 13 years ago (diff)

#1001 (ログローテーションでFatal errorが出ている)

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