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';
23 * Database class for MySQL.
25 class DbSimple_Mysql
extends DbSimple_Generic_Database
30 * constructor(string $dsn)
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']),
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)
58 return "'" . mysql_real_escape_string($s, $this->link
) . "'";
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);
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);
89 function _performGetPlaceholderIgnoreRe()
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...
116 // Prepare total calculation (if possible)
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];
126 // Perform total calculation.
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 ...)
135 (?> -- [^\r\n]* | \s+)*
138 (\s+ FROM \s+ .*?) #3
139 ((?:\s+ ORDER \s+ BY \s+ .*?)?) #4
140 ((?:\s+ LIMIT \s+ \S+ \s* (?:, \s* \S+ \s*)? )?) #5
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);
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
);
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;
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;
196 class DbSimple_Mysql_Blob
extends DbSimple_Generic_Blob
198 // MySQL does not support separate BLOB fetching.
199 var $blobdata = null;
202 function DbSimple_Mysql_Blob(&$database, $blobdata=null)
204 $this->blobdata
= $blobdata;
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;
222 return $this->blobdata
;
227 return strlen($this->blobdata
);