source: www/forum/includes/db/mysql.php@ 54

Last change on this file since 54 was 54, checked in by george, 17 years ago

Přidáno: Forum phpBB 3.

  • Property svn:executable set to *
File size: 10.3 KB
Line 
1<?php
2/**
3*
4* @package dbal
5* @version $Id: mysql.php,v 1.62 2007/10/05 14:36:32 acydburn Exp $
6* @copyright (c) 2005 phpBB Group
7* @license http://opensource.org/licenses/gpl-license.php GNU Public License
8*
9*/
10
11/**
12* @ignore
13*/
14if (!defined('IN_PHPBB'))
15{
16 exit;
17}
18
19include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
20
21/**
22* MySQL4 Database Abstraction Layer
23* Compatible with:
24* MySQL 3.23+
25* MySQL 4.0+
26* MySQL 4.1+
27* MySQL 5.0+
28* @package dbal
29*/
30class dbal_mysql extends dbal
31{
32 var $mysql_version;
33 var $multi_insert = true;
34
35 /**
36 * Connect to server
37 * @access public
38 */
39 function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
40 {
41 $this->persistency = $persistency;
42 $this->user = $sqluser;
43 $this->server = $sqlserver . (($port) ? ':' . $port : '');
44 $this->dbname = $database;
45
46 $this->sql_layer = 'mysql4';
47
48 $this->db_connect_id = ($this->persistency) ? @mysql_pconnect($this->server, $this->user, $sqlpassword, $new_link) : @mysql_connect($this->server, $this->user, $sqlpassword, $new_link);
49
50 if ($this->db_connect_id && $this->dbname != '')
51 {
52 if (@mysql_select_db($this->dbname, $this->db_connect_id))
53 {
54 // Determine what version we are using and if it natively supports UNICODE
55 $this->mysql_version = mysql_get_server_info($this->db_connect_id);
56
57 if (version_compare($this->mysql_version, '4.1.3', '>='))
58 {
59 @mysql_query("SET NAMES 'utf8'", $this->db_connect_id);
60 // enforce strict mode on databases that support it
61 if (version_compare($this->mysql_version, '5.0.2', '>='))
62 {
63 $result = @mysql_query('SELECT @@session.sql_mode AS sql_mode', $this->db_connect_id);
64 $row = @mysql_fetch_assoc($result);
65 @mysql_free_result($result);
66 $modes = array_map('trim', explode(',', $row['sql_mode']));
67
68 // TRADITIONAL includes STRICT_ALL_TABLES and STRICT_TRANS_TABLES
69 if (!in_array('TRADITIONAL', $modes))
70 {
71 if (!in_array('STRICT_ALL_TABLES', $modes))
72 {
73 $modes[] = 'STRICT_ALL_TABLES';
74 }
75
76 if (!in_array('STRICT_TRANS_TABLES', $modes))
77 {
78 $modes[] = 'STRICT_TRANS_TABLES';
79 }
80 }
81
82 $mode = implode(',', $modes);
83 @mysql_query("SET SESSION sql_mode='{$mode}'", $this->db_connect_id);
84 }
85 }
86 else if (version_compare($this->mysql_version, '4.0.0', '<'))
87 {
88 $this->sql_layer = 'mysql';
89 }
90
91 return $this->db_connect_id;
92 }
93 }
94
95 return $this->sql_error('');
96 }
97
98 /**
99 * Version information about used database
100 */
101 function sql_server_info()
102 {
103 return 'MySQL ' . $this->mysql_version;
104 }
105
106 /**
107 * SQL Transaction
108 * @access private
109 */
110 function _sql_transaction($status = 'begin')
111 {
112 switch ($status)
113 {
114 case 'begin':
115 return @mysql_query('BEGIN', $this->db_connect_id);
116 break;
117
118 case 'commit':
119 return @mysql_query('COMMIT', $this->db_connect_id);
120 break;
121
122 case 'rollback':
123 return @mysql_query('ROLLBACK', $this->db_connect_id);
124 break;
125 }
126
127 return true;
128 }
129
130 /**
131 * Base query method
132 *
133 * @param string $query Contains the SQL query which shall be executed
134 * @param int $cache_ttl Either 0 to avoid caching or the time in seconds which the result shall be kept in cache
135 * @return mixed When casted to bool the returned value returns true on success and false on failure
136 *
137 * @access public
138 */
139 function sql_query($query = '', $cache_ttl = 0)
140 {
141 if ($query != '')
142 {
143 global $cache;
144
145 // EXPLAIN only in extra debug mode
146 if (defined('DEBUG_EXTRA'))
147 {
148 $this->sql_report('start', $query);
149 }
150
151 $this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false;
152 $this->sql_add_num_queries($this->query_result);
153
154 if ($this->query_result === false)
155 {
156 if (($this->query_result = @mysql_query($query, $this->db_connect_id)) === false)
157 {
158 $this->sql_error($query);
159 }
160
161 if (defined('DEBUG_EXTRA'))
162 {
163 $this->sql_report('stop', $query);
164 }
165
166 if ($cache_ttl && method_exists($cache, 'sql_save'))
167 {
168 $this->open_queries[(int) $this->query_result] = $this->query_result;
169 $cache->sql_save($query, $this->query_result, $cache_ttl);
170 }
171 else if (strpos($query, 'SELECT') === 0 && $this->query_result)
172 {
173 $this->open_queries[(int) $this->query_result] = $this->query_result;
174 }
175 }
176 else if (defined('DEBUG_EXTRA'))
177 {
178 $this->sql_report('fromcache', $query);
179 }
180 }
181 else
182 {
183 return false;
184 }
185
186 return ($this->query_result) ? $this->query_result : false;
187 }
188
189 /**
190 * Build LIMIT query
191 */
192 function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0)
193 {
194 $this->query_result = false;
195
196 // if $total is set to 0 we do not want to limit the number of rows
197 if ($total == 0)
198 {
199 // Having a value of -1 was always a bug
200 $total = '18446744073709551615';
201 }
202
203 $query .= "\n LIMIT " . ((!empty($offset)) ? $offset . ', ' . $total : $total);
204
205 return $this->sql_query($query, $cache_ttl);
206 }
207
208 /**
209 * Return number of affected rows
210 */
211 function sql_affectedrows()
212 {
213 return ($this->db_connect_id) ? @mysql_affected_rows($this->db_connect_id) : false;
214 }
215
216 /**
217 * Fetch current row
218 */
219 function sql_fetchrow($query_id = false)
220 {
221 global $cache;
222
223 if ($query_id === false)
224 {
225 $query_id = $this->query_result;
226 }
227
228 if (isset($cache->sql_rowset[$query_id]))
229 {
230 return $cache->sql_fetchrow($query_id);
231 }
232
233 return ($query_id !== false) ? @mysql_fetch_assoc($query_id) : false;
234 }
235
236 /**
237 * Seek to given row number
238 * rownum is zero-based
239 */
240 function sql_rowseek($rownum, &$query_id)
241 {
242 global $cache;
243
244 if ($query_id === false)
245 {
246 $query_id = $this->query_result;
247 }
248
249 if (isset($cache->sql_rowset[$query_id]))
250 {
251 return $cache->sql_rowseek($rownum, $query_id);
252 }
253
254 return ($query_id !== false) ? @mysql_data_seek($query_id, $rownum) : false;
255 }
256
257 /**
258 * Get last inserted id after insert statement
259 */
260 function sql_nextid()
261 {
262 return ($this->db_connect_id) ? @mysql_insert_id($this->db_connect_id) : false;
263 }
264
265 /**
266 * Free sql result
267 */
268 function sql_freeresult($query_id = false)
269 {
270 global $cache;
271
272 if ($query_id === false)
273 {
274 $query_id = $this->query_result;
275 }
276
277 if (isset($cache->sql_rowset[$query_id]))
278 {
279 return $cache->sql_freeresult($query_id);
280 }
281
282 if (isset($this->open_queries[(int) $query_id]))
283 {
284 unset($this->open_queries[(int) $query_id]);
285 return @mysql_free_result($query_id);
286 }
287
288 return false;
289 }
290
291 /**
292 * Escape string used in sql query
293 */
294 function sql_escape($msg)
295 {
296 if (!$this->db_connect_id)
297 {
298 return @mysql_real_escape_string($msg);
299 }
300
301 return @mysql_real_escape_string($msg, $this->db_connect_id);
302 }
303
304 /**
305 * Build LIKE expression
306 * @access private
307 */
308 function _sql_like_expression($expression)
309 {
310 return $expression;
311 }
312
313 /**
314 * Build db-specific query data
315 * @access private
316 */
317 function _sql_custom_build($stage, $data)
318 {
319 switch ($stage)
320 {
321 case 'FROM':
322 $data = '(' . $data . ')';
323 break;
324 }
325
326 return $data;
327 }
328
329 /**
330 * return sql error array
331 * @access private
332 */
333 function _sql_error()
334 {
335 if (!$this->db_connect_id)
336 {
337 return array(
338 'message' => @mysql_error(),
339 'code' => @mysql_errno()
340 );
341 }
342
343 return array(
344 'message' => @mysql_error($this->db_connect_id),
345 'code' => @mysql_errno($this->db_connect_id)
346 );
347 }
348
349 /**
350 * Close sql connection
351 * @access private
352 */
353 function _sql_close()
354 {
355 return @mysql_close($this->db_connect_id);
356 }
357
358 /**
359 * Build db-specific report
360 * @access private
361 */
362 function _sql_report($mode, $query = '')
363 {
364 static $test_prof;
365
366 // current detection method, might just switch to see the existance of INFORMATION_SCHEMA.PROFILING
367 if ($test_prof === null)
368 {
369 $test_prof = false;
370 if (strpos($this->mysql_version, 'community') !== false)
371 {
372 $ver = substr($this->mysql_version, 0, strpos($this->mysql_version, '-'));
373 if (version_compare($ver, '5.0.37', '>=') && version_compare($ver, '5.1', '<'))
374 {
375 $test_prof = true;
376 }
377 }
378 }
379
380 switch ($mode)
381 {
382 case 'start':
383
384 $explain_query = $query;
385 if (preg_match('/UPDATE ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m))
386 {
387 $explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2];
388 }
389 else if (preg_match('/DELETE FROM ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m))
390 {
391 $explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2];
392 }
393
394 if (preg_match('/^SELECT/', $explain_query))
395 {
396 $html_table = false;
397
398 // begin profiling
399 if ($test_prof)
400 {
401 @mysql_query('SET profiling = 1;', $this->db_connect_id);
402 }
403
404 if ($result = @mysql_query("EXPLAIN $explain_query", $this->db_connect_id))
405 {
406 while ($row = @mysql_fetch_assoc($result))
407 {
408 $html_table = $this->sql_report('add_select_row', $query, $html_table, $row);
409 }
410 }
411 @mysql_free_result($result);
412
413 if ($html_table)
414 {
415 $this->html_hold .= '</table>';
416 }
417
418 if ($test_prof)
419 {
420 $html_table = false;
421
422 // get the last profile
423 if ($result = @mysql_query('SHOW PROFILE ALL;', $this->db_connect_id))
424 {
425 $this->html_hold .= '<br />';
426 while ($row = @mysql_fetch_assoc($result))
427 {
428 // make <unknown> HTML safe
429 if (!empty($row['Source_function']))
430 {
431 $row['Source_function'] = str_replace(array('<', '>'), array('&lt;', '&gt;'), $row['Source_function']);
432 }
433
434 // remove unsupported features
435 foreach ($row as $key => $val)
436 {
437 if ($val === null)
438 {
439 unset($row[$key]);
440 }
441 }
442 $html_table = $this->sql_report('add_select_row', $query, $html_table, $row);
443 }
444 }
445 @mysql_free_result($result);
446
447 if ($html_table)
448 {
449 $this->html_hold .= '</table>';
450 }
451
452 @mysql_query('SET profiling = 0;', $this->db_connect_id);
453 }
454 }
455
456 break;
457
458 case 'fromcache':
459 $endtime = explode(' ', microtime());
460 $endtime = $endtime[0] + $endtime[1];
461
462 $result = @mysql_query($query, $this->db_connect_id);
463 while ($void = @mysql_fetch_assoc($result))
464 {
465 // Take the time spent on parsing rows into account
466 }
467 @mysql_free_result($result);
468
469 $splittime = explode(' ', microtime());
470 $splittime = $splittime[0] + $splittime[1];
471
472 $this->sql_report('record_fromcache', $query, $endtime, $splittime);
473
474 break;
475 }
476 }
477}
478
479?>
Note: See TracBrowser for help on using the repository browser.