source: branches/version-2_11-dev/data/class/SC_Query.php @ 21372

Revision 21372, 32.9 KB checked in by Seasoft, 15 years ago (diff)

#1576 (データ生成スクリプトが動作しない)

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