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

Revision 18774, 14.7 KB checked in by Seasoft, 16 years ago (diff)

#565(SC_DbConn クラスの削除)

  • 初回インストール時にエラーとなる問題を回避。
  • 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    var $option;
36    var $where;
37    var $conn;
38    var $groupby;
39    var $order;
40
41    /**
42     * コンストラクタ.
43     *
44     * @param $dsn
45     * @param boolean $err_disp エラー表示を行うかどうか
46     * @param boolean $new 新規に接続を行うかどうか
47     * @return SC_Query
48     */
49    function SC_Query($dsn = "", $err_disp = true, $new = false) {
50
51        if ($dsn == "") {
52            $dsn = DEFAULT_DSN;
53        }
54
55        // Debugモード指定
56        $options['debug'] = PEAR_DB_DEBUG;
57        // 持続的接続オプション
58        $options['persistent'] = PEAR_DB_PERSISTENT;
59
60        if ($new) {
61            $this->conn = MDB2::connect($dsn, $options);
62        } else {
63            $this->conn = MDB2::singleton($dsn, $options);
64        }
65
66        if (!$this->isError()) {
67            $this->conn->setCharset(CHAR_CODE);
68            $this->conn->setFetchMode(MDB2_FETCHMODE_ASSOC);
69        }
70        $this->dbFactory = SC_DB_DBFactory_Ex::getInstance();
71        $this->where = "";
72    }
73
74    /**
75     *  エラー判定を行う.
76     *
77     * @return boolean
78     */
79    function isError() {
80        if(PEAR::isError($this->conn)) {
81            return true;
82        }
83        return false;
84    }
85
86    /**
87     * COUNT文を実行する.
88     *
89     * @param string $table テーブル名
90     * @param string $where where句
91     * @param array $arrval プレースホルダ
92     * @return integer 件数
93     */
94    function count($table, $where = "", $arrval = array()) {
95        if(strlen($where) <= 0) {
96            $sqlse = "SELECT COUNT(*) FROM $table";
97        } else {
98            $sqlse = "SELECT COUNT(*) FROM $table WHERE $where";
99        }
100        $sqlse = $this->dbFactory->sfChangeMySQL($sqlse);
101        return $this->getOne($sqlse, $arrval);
102    }
103
104    /**
105     * SELECT文を実行する.
106     *
107     * @param string $col カラム名. 複数カラムの場合はカンマ区切りで書く
108     * @param string $table テーブル名
109     * @param string $where WHERE句
110     * @param array $arrval プレースホルダ
111     * @param integer $fetchmode 使用するフェッチモード。デフォルトは DB_FETCHMODE_ASSOC。
112     * @return array|null
113     */
114    function select($col, $table, $where = "", $arrval = array(), $fetchmode = MDB2_FETCHMODE_ASSOC) {
115        $sqlse = $this->getSql($col, $table, $where);
116        return $this->getAll($sqlse, $arrval, $fetchmode);
117    }
118
119    /**
120     * 直前に実行されたSQL文を取得する.
121     *
122     * @param boolean $disp trueの場合、画面出力を行う.
123     * @return string SQL文
124     */
125    function getLastQuery($disp = true) {
126        $sql = $this->conn->last_query;
127        if($disp) {
128            print($sql.";<br />\n");
129        }
130        return $sql;
131    }
132
133    function commit() {
134        $this->conn->commit();
135    }
136
137    function begin() {
138        $this->conn->beginTransaction();
139    }
140
141    function rollback() {
142        $this->conn->rollback();
143    }
144
145    function exec($str, $arrval = array()) {
146        // FIXME MDB2::exec() の実装であるべき
147        $this->query($str, $arrval);
148    }
149
150    /**
151     * クエリを実行し、全ての行を返す
152     *
153     * @param string $sql SQL クエリ
154     * @param array $arrVal プリペアドステートメントの実行時に使用される配列。配列の要素数は、クエリ内のプレースホルダの数と同じでなければなりません。
155     * @param integer $fetchmode 使用するフェッチモード。デフォルトは DB_FETCHMODE_ASSOC。
156     * @return array データを含む2次元配列。失敗した場合に 0 または DB_Error オブジェクトを返します。
157     */
158    function getAll($sql, $arrval = array(), $fetchmode = MDB2_FETCHMODE_ASSOC) {
159
160        $sql = $this->dbFactory->sfChangeMySQL($sql);
161
162        $sth = $this->conn->prepare($sql);
163        $affected = $sth->execute($arrval);
164
165        if (PEAR::isError($affected)) {
166            trigger_error($affected->getMessage(), E_USER_ERROR);
167        }
168
169        return $affected->fetchAll($fetchmode);
170    }
171
172    function getSql($col, $table, $where = '') {
173        $sqlse = "SELECT $col FROM $table";
174
175        // 引数の$whereを優先する。
176        if (strlen($where) >= 1) {
177            $sqlse .= " WHERE $where";
178        } elseif (strlen($this->where) >= 1) {
179            $where = $this->where;
180        }
181
182        $sqlse .= ' ' . $this->groupby . ' ' . $this->order . ' ' . $this->option;
183
184        return $sqlse;
185    }
186
187    function setOption($str) {
188        $this->option = $str;
189    }
190
191    // TODO MDB2::setLimit() を使用する
192    function setLimitOffset($limit, $offset = 0, $return = false) {
193        if (is_numeric($limit) && is_numeric($offset)){
194
195            $option = " LIMIT " . $limit;
196            $option.= " OFFSET " . $offset;
197
198            if($return){
199                return $option;
200            }else{
201                $this->option.= $option;
202            }
203        }
204    }
205
206    function setGroupBy($str) {
207        if (strlen($str) == 0) {
208            $this->groupby = '';
209        } else {
210            $this->groupby = "GROUP BY " . $str;
211        }
212    }
213
214    function andwhere($str) {
215        if($this->where != "") {
216            $this->where .= " AND " . $str;
217        } else {
218            $this->where = $str;
219        }
220    }
221
222    function orWhere($str) {
223        if($this->where != "") {
224            $this->where .= " OR " . $str;
225        } else {
226            $this->where = $str;
227        }
228    }
229
230    function setWhere($str) {
231        $this->where = $str;
232    }
233
234    function setOrder($str) {
235        if (strlen($str) == 0) {
236            $this->order = '';
237        } else {
238            $this->order = "ORDER BY " . $str;
239        }
240    }
241
242
243    function setLimit($limit){
244        if ( is_numeric($limit)){
245            $this->option = " LIMIT " .$limit;
246        }
247    }
248
249    function setOffset($offset) {
250        if ( is_numeric($offset)){
251            $this->offset = " OFFSET " .$offset;
252        }
253    }
254
255    /**
256     * INSERT文を実行する.
257     *
258     * @param string $table テーブル名
259     * @param array $sqlval array('カラム名' => '値',...)の連想配列
260     * @return
261     */
262    function insert($table, $sqlval) {
263        $strcol = '';
264        $strval = '';
265        $find = false;
266
267        if(count($sqlval) <= 0 ) return false;
268
269        foreach ($sqlval as $key => $val) {
270            $strcol .= $key . ',';
271            if(eregi("^Now\(\)$", $val)) {
272                $strval .= 'Now(),';
273            } else {
274                $strval .= '?,';
275                $arrval[] = $val;
276            }
277            $find = true;
278        }
279        if(!$find) {
280            return false;
281        }
282        // 文末の","を削除
283        $strcol = ereg_replace(",$","",$strcol);
284        // 文末の","を削除
285        $strval = ereg_replace(",$","",$strval);
286        $sqlin = "INSERT INTO $table(" . $strcol. ") VALUES (" . $strval . ")";
287        // INSERT文の実行
288        $ret = $this->query($sqlin, $arrval);
289
290        return $ret;
291    }
292
293    /**
294     * UPDATE文を実行する.
295     *
296     * @param string $table テーブル名
297     * @param array $sqlval array('カラム名' => '値',...)の連想配列
298     * @param string $where WHERE句
299     * @param array $arrValIn WHERE句用のプレースホルダ配列 (従来は追加カラム用も兼ねていた)
300     * @param array $arrRawSql 追加カラム
301     * @param array $arrRawSqlVal 追加カラム用のプレースホルダ配列
302     * @return
303     */
304    function update($table, $sqlval, $where = "", $arrValIn = array(), $arrRawSql = array(), $arrRawSqlVal = array()) {
305        $arrCol = array();
306        $arrVal = array();
307        $find = false;
308        foreach ($sqlval as $key => $val) {
309            if (eregi("^Now\(\)$", $val)) {
310                $arrCol[] = $key . '= Now()';
311            } else {
312                $arrCol[] = $key . '= ?';
313                $arrVal[] = $val;
314            }
315            $find = true;
316        }
317
318        if ($arrRawSql != "") {
319            foreach($arrRawSql as $key => $val) {
320                $arrCol[] = "$key = $val";
321            }
322        }
323       
324        $arrVal = array_merge($arrVal, $arrRawSqlVal);
325       
326        if (empty($arrCol)) {
327            return false;
328        }
329
330        // 文末の","を削除
331        $strcol = implode(', ', $arrCol);
332
333        if (is_array($arrValIn)) { // 旧版との互換用
334            // プレースホルダー用に配列を追加
335            $arrVal = array_merge($arrVal, $arrValIn);
336        }
337
338        $sqlup = "UPDATE $table SET $strcol";
339        if (strlen($where) >= 1) {
340            $sqlup .= " WHERE $where";
341        }
342
343        // UPDATE文の実行
344        return $this->query($sqlup, $arrVal);
345    }
346
347    // MAX文の実行
348    function max($table, $col, $where = "", $arrval = array()) {
349        $ret = $this->get($table, "MAX($col)", $where, $arrval);
350        return $ret;
351    }
352
353    // MIN文の実行
354    function min($table, $col, $where = "", $arrval = array()) {
355        $ret = $this->get($table, "MIN($col)", $where, $arrval);
356        return $ret;
357    }
358
359    // 特定のカラムの値を取得
360    function get($table, $col, $where = "", $arrval = array()) {
361        $sqlse = $this->getSql($col, $table, $where);
362        // SQL文の実行
363        $ret = $this->getOne($sqlse, $arrval);
364        return $ret;
365    }
366
367    function getOne($sql, $arrval = array()) {
368
369        $sql = $this->dbFactory->sfChangeMySQL($sql);
370
371        $sth = $this->conn->prepare($sql);
372        $affected = $sth->execute($arrval);
373
374        if (PEAR::isError($affected)) {
375            trigger_error($affected->getMessage(), E_USER_ERROR);
376        }
377
378        return $affected->fetchOne();
379    }
380
381    /**
382     * 一行をカラム名をキーとした連想配列として取得
383     *
384     * @param string $table テーブル名
385     * @param string $col カラム名
386     * @param string $where WHERE句
387     * @param array $arrVal プレースホルダ配列
388     * @param integer $fetchmode 使用するフェッチモード。デフォルトは DB_FETCHMODE_ASSOC。
389     * @return array array('カラム名' => '値', ...)の連想配列
390     */
391    function getRow($table, $col, $where = "", $arrVal = array(), $fetchmode = MDB2_FETCHMODE_ASSOC) {
392
393        $sql = $this->getSql($col, $table, $where);
394        $sql = $this->dbFactory->sfChangeMySQL($sql);
395
396        $sth = $this->conn->prepare($sql);
397        $affected = $sth->execute($arrVal);
398
399        if (PEAR::isError($affected)) {
400            trigger_error($affected->getMessage(), E_USER_ERROR);
401        }
402
403        return $affected->fetchRow($fetchmode);
404    }
405
406    // 1列取得
407    function getCol($table, $col, $where = "", $arrval = array()) {
408        $sql = $this->getSql($col, $table, $where);
409        $sql = $this->dbFactory->sfChangeMySQL($sql);
410
411        $sth = $this->conn->prepare($sql);
412        $affected = $sth->execute($arrval);
413
414        if (PEAR::isError($affected)) {
415            trigger_error($affected->getMessage(), E_USER_ERROR);
416        }
417
418        return $affected->fetchCol($col);
419    }
420
421    /**
422     * レコードの削除
423     *
424     * @param string $table テーブル名
425     * @param string $where WHERE句
426     * @param array $arrval プレースホルダ
427     * @return
428     */
429    function delete($table, $where = "", $arrval = array()) {
430        if(strlen($where) <= 0) {
431            $sqlde = "DELETE FROM $table";
432        } else {
433            $sqlde = "DELETE FROM $table WHERE $where";
434        }
435        $ret = $this->query($sqlde, $arrval);
436        return $ret;
437    }
438
439    function nextval($table, $colname) {
440        $sql = "";
441        // postgresqlとmysqlとで処理を分ける
442        if (DB_TYPE == "pgsql") {
443            $seqtable = $table . "_" . $colname . "_seq";
444            $sql = "SELECT NEXTVAL('$seqtable')";
445        }else if (DB_TYPE == "mysql") {
446            $sql = "SELECT last_insert_id();";
447        }
448        $ret = $this->getOne($sql);
449
450        return $ret;
451    }
452
453    function currval($table, $colname) {
454        $sql = "";
455        if (DB_TYPE == "pgsql") {
456            $seqtable = $table . "_" . $colname . "_seq";
457            $sql = "SELECT CURRVAL('$seqtable')";
458        }else if (DB_TYPE == "mysql") {
459            $sql = "SELECT last_insert_id();";
460        }
461        $ret = $this->getOne($sql);
462
463        return $ret;
464    }
465
466    function setval($table, $colname, $data) {
467        $sql = "";
468        if (DB_TYPE == "pgsql") {
469            $seqtable = $table . "_" . $colname . "_seq";
470            $sql = "SELECT SETVAL('$seqtable', $data)";
471            $ret = $this->getOne($sql);
472        }else if (DB_TYPE == "mysql") {
473            $sql = "ALTER TABLE $table AUTO_INCREMENT=$data";
474            $ret = $this->query($sql);
475        }
476
477        return $ret;
478    }
479
480    // XXX 更新系には exec() を使用するべき
481    function query($n ,$arr = array(), $ignore_err = false){
482
483        $n = $this->dbFactory->sfChangeMySQL($n);
484
485        $sth = $this->conn->prepare($n);
486        $result = $sth->execute($arr);
487
488        if (PEAR::isError($result)) {
489            trigger_error($result->getMessage(), E_USER_ERROR);
490        }
491
492        return $result;
493    }
494
495    /**
496     * auto_incrementを取得する.
497     *
498     * @param string $table_name テーブル名
499     * @return integer
500     */
501    function get_auto_increment($table_name){
502        // ロックする
503        $this->query("LOCK TABLES $table_name WRITE");
504
505        // 次のIncrementを取得
506        $arrRet = $this->getAll("SHOW TABLE STATUS LIKE ?", array($table_name));
507        $auto_inc_no = $arrRet[0]["Auto_increment"];
508
509        // 値をカウントアップしておく
510        $this->query("ALTER TABLE $table_name AUTO_INCREMENT=?" , $auto_inc_no + 1);
511
512        // 解除する
513        $this->query('UNLOCK TABLES');
514
515        return $auto_inc_no;
516    }
517}
518
519?>
Note: See TracBrowser for help on using the repository browser.