Проба показа активных событий.)
[cswowd.git] / include / DbSimple / Mysql.php
blob7bd364e6c661ba08c4513bfd63f97ff9f4d91116
1 <?php
2 /**
3 * DbSimple_Mysql: MySQL database.
4 * (C) Dk Lab, http://en.dklab.ru
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 * See http://www.gnu.org/copyleft/lesser.html
12 * Placeholders end blobs are emulated.
14 * @author Dmitry Koterov, http://forum.dklab.ru/users/DmitryKoterov/
15 * @author Konstantin Zhinko, http://forum.dklab.ru/users/KonstantinGinkoTit/
17 * @version 2.x $Id: Mysql.php 247 2008-08-18 21:17:08Z dk $
19 require_once dirname(__FILE__) . '/Generic.php';
22 /**
23 * Database class for MySQL.
25 class DbSimple_Mysql extends DbSimple_Generic_Database
27 var $link;
29 /**
30 * constructor(string $dsn)
31 * Connect to MySQL.
33 function DbSimple_Mysql($dsn)
35 $p = DbSimple_Generic::parseDSN($dsn);
36 if (!is_callable('mysql_connect')) {
37 return $this->_setLastError("-1", "MySQL extension is not loaded", "mysql_connect");
39 $ok = $this->link = @mysql_connect(
40 $p['host'] . (empty($p['port'])? "" : ":".$p['port']),
41 $p['user'],
42 $p['pass'],
43 true
45 $this->_resetLastError();
46 if (!$ok) return $this->_setDbError('mysql_connect()');
47 $ok = @mysql_select_db(preg_replace('{^/}s', '', $p['path']), $this->link);
48 if (!$ok) return $this->_setDbError('mysql_select_db()');
49 if (isset($p["charset"])) {
50 $this->query('SET NAMES ?', $p["charset"]);
55 function _performEscape($s, $isIdent=false)
57 if (!$isIdent) {
58 return "'" . mysql_real_escape_string($s, $this->link) . "'";
59 } else {
60 return "`" . str_replace('`', '``', $s) . "`";
65 function _performTransaction($parameters=null)
67 return $this->query('BEGIN');
71 function& _performNewBlob($blobid=null)
73 $obj =& new DbSimple_Mysql_Blob($this, $blobid);
74 return $obj;
78 function _performGetBlobFieldNames($result)
80 $blobFields = array();
81 for ($i=mysql_num_fields($result)-1; $i>=0; $i--) {
82 $type = mysql_field_type($result, $i);
83 if (strpos($type, "BLOB") !== false) $blobFields[] = mysql_field_name($result, $i);
85 return $blobFields;
89 function _performGetPlaceholderIgnoreRe()
91 return '
92 " (?> [^"\\\\]+|\\\\"|\\\\)* " |
93 \' (?> [^\'\\\\]+|\\\\\'|\\\\)* \' |
94 ` (?> [^`]+ | ``)* ` | # backticks
95 /\* .*? \*/ # comments
100 function _performCommit()
102 return $this->query('COMMIT');
106 function _performRollback()
108 return $this->query('ROLLBACK');
112 function _performTransformQuery(&$queryMain, $how)
114 // If we also need to calculate total number of found rows...
115 switch ($how) {
116 // Prepare total calculation (if possible)
117 case 'CALC_TOTAL':
118 $m = null;
119 if (preg_match('/^(\s* SELECT)(.*)/six', $queryMain[0], $m)) {
120 if ($this->_calcFoundRowsAvailable()) {
121 $queryMain[0] = $m[1] . ' SQL_CALC_FOUND_ROWS' . $m[2];
124 return true;
126 // Perform total calculation.
127 case 'GET_TOTAL':
128 // Built-in calculation available?
129 if ($this->_calcFoundRowsAvailable()) {
130 $queryMain = array('SELECT FOUND_ROWS()');
132 // Else use manual calculation.
133 // TODO: GROUP BY ... -> COUNT(DISTINCT ...)
134 $re = '/^
135 (?> -- [^\r\n]* | \s+)*
136 (\s* SELECT \s+) #1
137 (.*?) #2
138 (\s+ FROM \s+ .*?) #3
139 ((?:\s+ ORDER \s+ BY \s+ .*?)?) #4
140 ((?:\s+ LIMIT \s+ \S+ \s* (?:, \s* \S+ \s*)? )?) #5
141 $/six';
142 $m = null;
143 if (preg_match($re, $queryMain[0], $m)) {
144 $query[0] = $m[1] . $this->_fieldList2Count($m[2]) . " AS C" . $m[3];
145 $skipTail = substr_count($m[4] . $m[5], '?');
146 if ($skipTail) array_splice($query, -$skipTail);
148 return true;
151 return false;
155 function _performQuery($queryMain)
157 $this->_lastQuery = $queryMain;
158 $this->_expandPlaceholders($queryMain, false);
159 $result = @mysql_query($queryMain[0], $this->link);
160 if ($result === false) return $this->_setDbError($queryMain[0]);
161 if (!is_resource($result)) {
162 if (preg_match('/^\s* INSERT \s+/six', $queryMain[0])) {
163 // INSERT queries return generated ID.
164 return @mysql_insert_id($this->link);
166 // Non-SELECT queries return number of affected rows, SELECT - resource.
167 return @mysql_affected_rows($this->link);
169 return $result;
173 function _performFetch($result)
175 $row = @mysql_fetch_assoc($result);
176 if (mysql_error()) return $this->_setDbError($this->_lastQuery);
177 if ($row === false) return null;
178 return $row;
182 function _setDbError($query)
184 return $this->_setLastError(mysql_errno($this->link), mysql_error($this->link), $query);
188 function _calcFoundRowsAvailable()
190 $ok = version_compare(mysql_get_server_info($this->link), '4.0') >= 0;
191 return $ok;
196 class DbSimple_Mysql_Blob extends DbSimple_Generic_Blob
198 // MySQL does not support separate BLOB fetching.
199 var $blobdata = null;
200 var $curSeek = 0;
202 function DbSimple_Mysql_Blob(&$database, $blobdata=null)
204 $this->blobdata = $blobdata;
205 $this->curSeek = 0;
208 function read($len)
210 $p = $this->curSeek;
211 $this->curSeek = min($this->curSeek + $len, strlen($this->blobdata));
212 return substr($this->blobdata, $this->curSeek, $len);
215 function write($data)
217 $this->blobdata .= $data;
220 function close()
222 return $this->blobdata;
225 function length()
227 return strlen($this->blobdata);