source: aowow/includes/DbSimple/Mysql.php

Last change on this file was 170, checked in by maron, 16 years ago
  • Property svn:executable set to *
File size: 6.5 KB
Line 
1<?php
2/**
3 * DbSimple_Mysql: MySQL database.
4 * (C) Dk Lab, http://en.dklab.ru
5 *
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
11 *
12 * Placeholders end blobs are emulated.
13 *
14 * @author Dmitry Koterov, http://forum.dklab.ru/users/DmitryKoterov/
15 * @author Konstantin Zhinko, http://forum.dklab.ru/users/KonstantinGinkoTit/
16 *
17 * @version 2.x $Id: Mysql.php 163 2007-01-10 09:47:49Z dk $
18 */
19require_once dirname(__FILE__) . '/Generic.php';
20
21
22/**
23 * Database class for MySQL.
24 */
25class DbSimple_Mysql extends DbSimple_Generic_Database
26{
27 var $link;
28
29 /**
30 * constructor(string $dsn)
31 * Connect to MySQL.
32 */
33 function DbSimple_Mysql($dsn)
34 {
35 $p = DbSimple_Generic::parseDSN($dsn);
36 if (!is_callable('mysql_connect')) {
37 return $this->_setLastError("-1", "MySQL extension is not loaded", "mysql_connect");
38 }
39 $ok = $this->link = @mysql_connect(
40 $p['host'] . (empty($p['port'])? "" : ":".$p['port']),
41 $p['user'],
42 $p['pass'],
43 true
44 );
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 }
50
51
52 function _performEscape($s, $isIdent=false)
53 {
54 if (!$isIdent) {
55 return "'" . mysql_real_escape_string($s, $this->link) . "'";
56 } else {
57 return "`" . str_replace('`', '``', $s) . "`";
58 }
59 }
60
61
62 function _performTransaction($parameters=null)
63 {
64 return $this->query('BEGIN');
65 }
66
67
68 function& _performNewBlob($blobid=null)
69 {
70 $obj =& new DbSimple_Mysql_Blob($this, $blobid);
71 return $obj;
72 }
73
74
75 function _performGetBlobFieldNames($result)
76 {
77 $blobFields = array();
78 for ($i=mysql_num_fields($result)-1; $i>=0; $i--) {
79 $type = mysql_field_type($result, $i);
80 if (strpos($type, "BLOB") !== false) $blobFields[] = mysql_field_name($result, $i);
81 }
82 return $blobFields;
83 }
84
85
86 function _performGetPlaceholderIgnoreRe()
87 {
88 return '
89 " (?> [^"\\\\]+|\\\\"|\\\\)* " |
90 \' (?> [^\'\\\\]+|\\\\\'|\\\\)* \' |
91 ` (?> [^`]+ | ``)* ` | # backticks
92 /\* .*? \*/ # comments
93 ';
94 }
95
96
97 function _performCommit()
98 {
99 return $this->query('COMMIT');
100 }
101
102
103 function _performRollback()
104 {
105 return $this->query('ROLLBACK');
106 }
107
108
109 function _performTransformQuery(&$queryMain, $how)
110 {
111 // If we also need to calculate total number of found rows...
112 switch ($how) {
113 // Prepare total calculation (if possible)
114 case 'CALC_TOTAL':
115 $m = null;
116 if (preg_match('/^(\s* SELECT)(.*)/six', $queryMain[0], $m)) {
117 if ($this->_calcFoundRowsAvailable()) {
118 $queryMain[0] = $m[1] . ' SQL_CALC_FOUND_ROWS' . $m[2];
119 }
120 }
121 return true;
122
123 // Perform total calculation.
124 case 'GET_TOTAL':
125 // Built-in calculation available?
126 if ($this->_calcFoundRowsAvailable()) {
127 $queryMain = array('SELECT FOUND_ROWS()');
128 }
129 // Else use manual calculation.
130 // TODO: GROUP BY ... -> COUNT(DISTINCT ...)
131 $re = '/^
132 (?> -- [^\r\n]* | \s+)*
133 (\s* SELECT \s+) #1
134 (.*?) #2
135 (\s+ FROM \s+ .*?) #3
136 ((?:\s+ ORDER \s+ BY \s+ .*?)?) #4
137 ((?:\s+ LIMIT \s+ \S+ \s* (?:, \s* \S+ \s*)? )?) #5
138 $/six';
139 $m = null;
140 if (preg_match($re, $queryMain[0], $m)) {
141 $query[0] = $m[1] . $this->_fieldList2Count($m[2]) . " AS C" . $m[3];
142 $skipTail = substr_count($m[4] . $m[5], '?');
143 if ($skipTail) array_splice($query, -$skipTail);
144 }
145 return true;
146 }
147
148 return false;
149 }
150
151
152 function _performQuery($queryMain)
153 {
154 $this->_lastQuery = $queryMain;
155 $this->_expandPlaceholders($queryMain, false);
156 $result = @mysql_query($queryMain[0], $this->link);
157 if ($result === false) return $this->_setDbError($queryMain[0]);
158 if (!is_resource($result)) {
159 if (preg_match('/^\s* INSERT \s+/six', $queryMain[0])) {
160 // INSERT queries return generated ID.
161 return @mysql_insert_id($this->link);
162 }
163 // Non-SELECT queries return number of affected rows, SELECT - resource.
164 return @mysql_affected_rows($this->link);
165 }
166 return $result;
167 }
168
169
170 function _performFetch($result)
171 {
172 $row = @mysql_fetch_assoc($result);
173 if (mysql_error()) return $this->_setDbError($this->_lastQuery);
174 if ($row === false) return null;
175 return $row;
176 }
177
178
179 function _setDbError($query)
180 {
181 return $this->_setLastError(mysql_errno($this->link), mysql_error($this->link), $query);
182 }
183
184
185 function _calcFoundRowsAvailable()
186 {
187 $ok = version_compare(mysql_get_server_info($this->link), '4.0') >= 0;
188 return $ok;
189 }
190}
191
192
193class DbSimple_Mysql_Blob extends DbSimple_Generic_Blob
194{
195 // MySQL does not support separate BLOB fetching.
196 var $blobdata = null;
197 var $curSeek = 0;
198
199 function DbSimple_Mysql_Blob(&$database, $blobdata=null)
200 {
201 $this->blobdata = $blobdata;
202 $this->curSeek = 0;
203 }
204
205 function read($len)
206 {
207 $p = $this->curSeek;
208 $this->curSeek = min($this->curSeek + $len, strlen($this->blobdata));
209 return substr($this->blobdata, $this->curSeek, $len);
210 }
211
212 function write($data)
213 {
214 $this->blobdata .= $data;
215 }
216
217 function close()
218 {
219 return $this->blobdata;
220 }
221
222 function length()
223 {
224 return strlen($this->blobdata);
225 }
226}
227?>
Note: See TracBrowser for help on using the repository browser.