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

Revision 18775, 15.7 KB checked in by nanasess, 16 years ago (diff)

#565(SC_DbConn クラスの削除)

  • MySQL でインストーラ及び購入完了画面でエラーが発生していたのを修正
  • SC_Query::quote() を追加
  • 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        if (PEAR::isError($sth)) {
164            /*
165             * XXX インストーラのテーブルチェックに失敗してしまう.
166             * エラーハンドリングの方法を要検討
167             */
168            return;
169        }
170        $affected = $sth->execute($arrval);
171
172        if (PEAR::isError($affected)) {
173            trigger_error($affected->getMessage(), E_USER_ERROR);
174        }
175
176        return $affected->fetchAll($fetchmode);
177    }
178
179    function getSql($col, $table, $where = '') {
180        $sqlse = "SELECT $col FROM $table";
181
182        // 引数の$whereを優先する。
183        if (strlen($where) >= 1) {
184            $sqlse .= " WHERE $where";
185        } elseif (strlen($this->where) >= 1) {
186            $where = $this->where;
187        }
188
189        $sqlse .= ' ' . $this->groupby . ' ' . $this->order . ' ' . $this->option;
190
191        return $sqlse;
192    }
193
194    function setOption($str) {
195        $this->option = $str;
196    }
197
198    // TODO MDB2::setLimit() を使用する
199    function setLimitOffset($limit, $offset = 0, $return = false) {
200        if (is_numeric($limit) && is_numeric($offset)){
201
202            $option = " LIMIT " . $limit;
203            $option.= " OFFSET " . $offset;
204
205            if($return){
206                return $option;
207            }else{
208                $this->option.= $option;
209            }
210        }
211    }
212
213    function setGroupBy($str) {
214        if (strlen($str) == 0) {
215            $this->groupby = '';
216        } else {
217            $this->groupby = "GROUP BY " . $str;
218        }
219    }
220
221    function andwhere($str) {
222        if($this->where != "") {
223            $this->where .= " AND " . $str;
224        } else {
225            $this->where = $str;
226        }
227    }
228
229    function orWhere($str) {
230        if($this->where != "") {
231            $this->where .= " OR " . $str;
232        } else {
233            $this->where = $str;
234        }
235    }
236
237    function setWhere($str) {
238        $this->where = $str;
239    }
240
241    function setOrder($str) {
242        if (strlen($str) == 0) {
243            $this->order = '';
244        } else {
245            $this->order = "ORDER BY " . $str;
246        }
247    }
248
249
250    function setLimit($limit){
251        if ( is_numeric($limit)){
252            $this->option = " LIMIT " .$limit;
253        }
254    }
255
256    function setOffset($offset) {
257        if ( is_numeric($offset)){
258            $this->offset = " OFFSET " .$offset;
259        }
260    }
261
262    /**
263     * INSERT文を実行する.
264     *
265     * @param string $table テーブル名
266     * @param array $sqlval array('カラム名' => '値',...)の連想配列
267     * @return
268     */
269    function insert($table, $sqlval) {
270        $strcol = '';
271        $strval = '';
272        $find = false;
273
274        if(count($sqlval) <= 0 ) return false;
275
276        foreach ($sqlval as $key => $val) {
277            $strcol .= $key . ',';
278            if(eregi("^Now\(\)$", $val)) {
279                $strval .= 'Now(),';
280            } else {
281                $strval .= '?,';
282                $arrval[] = $val;
283            }
284            $find = true;
285        }
286        if(!$find) {
287            return false;
288        }
289        // 文末の","を削除
290        $strcol = ereg_replace(",$","",$strcol);
291        // 文末の","を削除
292        $strval = ereg_replace(",$","",$strval);
293        $sqlin = "INSERT INTO $table(" . $strcol. ") VALUES (" . $strval . ")";
294        // INSERT文の実行
295        $ret = $this->query($sqlin, $arrval);
296
297        return $ret;
298    }
299
300    /**
301     * UPDATE文を実行する.
302     *
303     * @param string $table テーブル名
304     * @param array $sqlval array('カラム名' => '値',...)の連想配列
305     * @param string $where WHERE句
306     * @param array $arrValIn WHERE句用のプレースホルダ配列 (従来は追加カラム用も兼ねていた)
307     * @param array $arrRawSql 追加カラム
308     * @param array $arrRawSqlVal 追加カラム用のプレースホルダ配列
309     * @return
310     */
311    function update($table, $sqlval, $where = "", $arrValIn = array(), $arrRawSql = array(), $arrRawSqlVal = array()) {
312        $arrCol = array();
313        $arrVal = array();
314        $find = false;
315        foreach ($sqlval as $key => $val) {
316            if (eregi("^Now\(\)$", $val)) {
317                $arrCol[] = $key . '= Now()';
318            } else {
319                $arrCol[] = $key . '= ?';
320                $arrVal[] = $val;
321            }
322            $find = true;
323        }
324
325        if ($arrRawSql != "") {
326            foreach($arrRawSql as $key => $val) {
327                $arrCol[] = "$key = $val";
328            }
329        }
330       
331        $arrVal = array_merge($arrVal, $arrRawSqlVal);
332       
333        if (empty($arrCol)) {
334            return false;
335        }
336
337        // 文末の","を削除
338        $strcol = implode(', ', $arrCol);
339
340        if (is_array($arrValIn)) { // 旧版との互換用
341            // プレースホルダー用に配列を追加
342            $arrVal = array_merge($arrVal, $arrValIn);
343        }
344
345        $sqlup = "UPDATE $table SET $strcol";
346        if (strlen($where) >= 1) {
347            $sqlup .= " WHERE $where";
348        }
349
350        // UPDATE文の実行
351        return $this->query($sqlup, $arrVal);
352    }
353
354    // MAX文の実行
355    function max($table, $col, $where = "", $arrval = array()) {
356        $ret = $this->get($table, "MAX($col)", $where, $arrval);
357        return $ret;
358    }
359
360    // MIN文の実行
361    function min($table, $col, $where = "", $arrval = array()) {
362        $ret = $this->get($table, "MIN($col)", $where, $arrval);
363        return $ret;
364    }
365
366    // 特定のカラムの値を取得
367    function get($table, $col, $where = "", $arrval = array()) {
368        $sqlse = $this->getSql($col, $table, $where);
369        // SQL文の実行
370        $ret = $this->getOne($sqlse, $arrval);
371        return $ret;
372    }
373
374    function getOne($sql, $arrval = array()) {
375
376        $sql = $this->dbFactory->sfChangeMySQL($sql);
377
378        $sth = $this->conn->prepare($sql);
379        $affected = $sth->execute($arrval);
380
381        if (PEAR::isError($affected)) {
382            trigger_error($affected->getMessage(), E_USER_ERROR);
383        }
384
385        return $affected->fetchOne();
386    }
387
388    /**
389     * 一行をカラム名をキーとした連想配列として取得
390     *
391     * @param string $table テーブル名
392     * @param string $col カラム名
393     * @param string $where WHERE句
394     * @param array $arrVal プレースホルダ配列
395     * @param integer $fetchmode 使用するフェッチモード。デフォルトは DB_FETCHMODE_ASSOC。
396     * @return array array('カラム名' => '値', ...)の連想配列
397     */
398    function getRow($table, $col, $where = "", $arrVal = array(), $fetchmode = MDB2_FETCHMODE_ASSOC) {
399
400        $sql = $this->getSql($col, $table, $where);
401        $sql = $this->dbFactory->sfChangeMySQL($sql);
402
403        $sth = $this->conn->prepare($sql);
404        $affected = $sth->execute($arrVal);
405
406        if (PEAR::isError($affected)) {
407            trigger_error($affected->getMessage(), E_USER_ERROR);
408        }
409
410        return $affected->fetchRow($fetchmode);
411    }
412
413    // 1列取得
414    function getCol($table, $col, $where = "", $arrval = array()) {
415        $sql = $this->getSql($col, $table, $where);
416        $sql = $this->dbFactory->sfChangeMySQL($sql);
417
418        $sth = $this->conn->prepare($sql);
419        $affected = $sth->execute($arrval);
420
421        if (PEAR::isError($affected)) {
422            trigger_error($affected->getMessage(), E_USER_ERROR);
423        }
424
425        return $affected->fetchCol($col);
426    }
427
428    /**
429     * レコードの削除
430     *
431     * @param string $table テーブル名
432     * @param string $where WHERE句
433     * @param array $arrval プレースホルダ
434     * @return
435     */
436    function delete($table, $where = "", $arrval = array()) {
437        if(strlen($where) <= 0) {
438            $sqlde = "DELETE FROM $table";
439        } else {
440            $sqlde = "DELETE FROM $table WHERE $where";
441        }
442        $ret = $this->query($sqlde, $arrval);
443        return $ret;
444    }
445
446    function nextval($table, $colname) {
447        $sql = "";
448        // postgresqlとmysqlとで処理を分ける
449        if (DB_TYPE == "pgsql") {
450            $seqtable = $table . "_" . $colname . "_seq";
451            $sql = "SELECT NEXTVAL('$seqtable')";
452        }else if (DB_TYPE == "mysql") {
453            $sql = "SELECT last_insert_id();";
454        }
455        $ret = $this->getOne($sql);
456
457        return $ret;
458    }
459
460    function currval($table, $colname) {
461        $sql = "";
462        if (DB_TYPE == "pgsql") {
463            $seqtable = $table . "_" . $colname . "_seq";
464            $sql = "SELECT CURRVAL('$seqtable')";
465        }else if (DB_TYPE == "mysql") {
466            $sql = "SELECT last_insert_id();";
467        }
468        $ret = $this->getOne($sql);
469
470        return $ret;
471    }
472
473    function setval($table, $colname, $data) {
474        $sql = "";
475        if (DB_TYPE == "pgsql") {
476            $seqtable = $table . "_" . $colname . "_seq";
477            $sql = "SELECT SETVAL('$seqtable', $data)";
478            $ret = $this->getOne($sql);
479        }else if (DB_TYPE == "mysql") {
480            $sql = "ALTER TABLE $table AUTO_INCREMENT=$data";
481            $ret = $this->query($sql);
482        }
483
484        return $ret;
485    }
486
487    // XXX 更新系には exec() を使用するべき
488    function query($n ,$arr = array(), $ignore_err = false){
489
490        $n = $this->dbFactory->sfChangeMySQL($n);
491
492        $sth = $this->conn->prepare($n);
493        $result = $sth->execute($arr);
494
495        if (PEAR::isError($result)) {
496            /*
497             * XXX インストーラのテーブルチェックに失敗してしまう.
498             * エラーハンドリングの方法を要検討
499             */
500            //trigger_error($result->getMessage(), E_USER_ERROR);
501        }
502
503        return $result;
504    }
505
506    /**
507     * auto_incrementを取得する.
508     *
509     * XXX MDB2 の sequence 関数を使用する
510     *
511     * @param string $table_name テーブル名
512     * @return integer
513     */
514    function get_auto_increment($table_name){
515        // ロックする
516        $this->conn->exec("LOCK TABLES $table_name WRITE");
517
518        // 次のIncrementを取得
519        $arrRet = $this->getAll("SHOW TABLE STATUS LIKE ". $this->quote($table_name));
520        $auto_inc_no = $arrRet[0]["Auto_increment"];
521
522        // 値をカウントアップしておく
523        $this->conn->exec("ALTER TABLE $table_name AUTO_INCREMENT=" . $this->quote($auto_inc_no + 1));
524
525        // 解除する
526        $this->conn->exec('UNLOCK TABLES');
527
528        return $auto_inc_no;
529    }
530
531    /**
532     * 値を適切にクォートする.
533     *
534     * TODO MDB2 に対応するための暫定的な措置.
535     *      ブレースホルダが使用できない実装があるため.
536     *      本来であれば, MDB2::prepare() を適切に使用するべき
537     *
538     * @see MDB2::quote()
539     * @param string $val クォートを行う文字列
540     * @return string クォートされた文字列
541     */
542    function quote($val) {
543        return $this->conn->quote($val);
544    }
545}
546
547?>
Note: See TracBrowser for help on using the repository browser.