Verzeichnisstruktur phpBB-3.3.15
- Veröffentlicht
- 28.08.2024
So funktioniert es
|
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
mssqlnative.php
001 <?php
002 /**
003 *
004 * This file is part of the phpBB Forum Software package.
005 *
006 * @copyright (c) phpBB Limited <https://www.phpbb.com>
007 * @license GNU General Public License, version 2 (GPL-2.0)
008 *
009 * For full copyright and license information, please see
010 * the docs/CREDITS.txt file.
011 *
012 */
013
014 /**
015 * This is the MS SQL Server Native database abstraction layer.
016 * PHP mssql native driver required.
017 * @author Chris Pucci
018 *
019 */
020
021 namespace phpbb\db\driver;
022
023 class mssqlnative extends \phpbb\db\driver\mssql_base
024 {
025 var $m_insert_id = null;
026 var $last_query_text = '';
027 var $query_options = array();
028 var $connect_error = '';
029
030 /**
031 * {@inheritDoc}
032 */
033 function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
034 {
035 // Test for driver support, to avoid suppressed fatal error
036 if (!function_exists('sqlsrv_connect'))
037 {
038 $this->connect_error = 'Native MS SQL Server driver for PHP is missing or needs to be updated. Version 1.1 or later is required to install phpBB3. You can download the driver from: http://www.microsoft.com/sqlserver/2005/en/us/PHP-Driver.aspx';
039 return $this->sql_error('');
040 }
041
042 //set up connection variables
043 $this->persistency = $persistency;
044 $this->user = $sqluser;
045 $this->dbname = $database;
046 $port_delimiter = (defined('PHP_OS') && substr(PHP_OS, 0, 3) === 'WIN') ? ',' : ':';
047 $this->server = $sqlserver . (($port) ? $port_delimiter . $port : '');
048
049 //connect to database
050 $this->db_connect_id = sqlsrv_connect($this->server, array(
051 'Database' => $this->dbname,
052 'UID' => $this->user,
053 'PWD' => $sqlpassword,
054 'CharacterSet' => 'UTF-8'
055 ));
056
057 return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error('');
058 }
059
060 /**
061 * {@inheritDoc}
062 */
063 function sql_server_info($raw = false, $use_cache = true)
064 {
065 global $cache;
066
067 if (!$use_cache || empty($cache) || ($this->sql_server_version = $cache->get('mssql_version')) === false)
068 {
069 $arr_server_info = sqlsrv_server_info($this->db_connect_id);
070 $this->sql_server_version = $arr_server_info['SQLServerVersion'];
071
072 if (!empty($cache) && $use_cache)
073 {
074 $cache->put('mssql_version', $this->sql_server_version);
075 }
076 }
077
078 if ($raw)
079 {
080 return $this->sql_server_version;
081 }
082
083 return ($this->sql_server_version) ? 'MSSQL<br />' . $this->sql_server_version : 'MSSQL';
084 }
085
086 /**
087 * {@inheritDoc}
088 */
089 function sql_buffer_nested_transactions()
090 {
091 return true;
092 }
093
094 /**
095 * SQL Transaction
096 * @access private
097 */
098 function _sql_transaction($status = 'begin')
099 {
100 switch ($status)
101 {
102 case 'begin':
103 return sqlsrv_begin_transaction($this->db_connect_id);
104 break;
105
106 case 'commit':
107 return sqlsrv_commit($this->db_connect_id);
108 break;
109
110 case 'rollback':
111 return sqlsrv_rollback($this->db_connect_id);
112 break;
113 }
114 return true;
115 }
116
117 /**
118 * {@inheritDoc}
119 */
120 function sql_query($query = '', $cache_ttl = 0)
121 {
122 if ($query != '')
123 {
124 global $cache;
125
126 if ($this->debug_sql_explain)
127 {
128 $this->sql_report('start', $query);
129 }
130 else if ($this->debug_load_time)
131 {
132 $this->curtime = microtime(true);
133 }
134
135 $this->last_query_text = $query;
136 $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;
137 $this->sql_add_num_queries($this->query_result);
138
139 if ($this->query_result === false)
140 {
141 try
142 {
143 $this->query_result = @sqlsrv_query($this->db_connect_id, $query, array(), $this->query_options);
144 }
145 catch (\Error $e)
146 {
147 // Do nothing as SQL driver will report the error
148 }
149
150 if ($this->query_result === false)
151 {
152 $this->sql_error($query);
153 }
154
155 // Reset options for the next query
156 $this->query_options = [];
157
158 if ($this->debug_sql_explain)
159 {
160 $this->sql_report('stop', $query);
161 }
162 else if ($this->debug_load_time)
163 {
164 $this->sql_time += microtime(true) - $this->curtime;
165 }
166
167 if (!$this->query_result)
168 {
169 return false;
170 }
171
172 $safe_query_id = $this->clean_query_id($this->query_result);
173
174 if ($cache && $cache_ttl)
175 {
176 $this->open_queries[$safe_query_id] = $this->query_result;
177 $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
178 }
179 else if (strpos($query, 'SELECT') === 0)
180 {
181 $this->open_queries[$safe_query_id] = $this->query_result;
182 }
183 }
184 else if ($this->debug_sql_explain)
185 {
186 $this->sql_report('fromcache', $query);
187 }
188 }
189 else
190 {
191 return false;
192 }
193 return $this->query_result;
194 }
195
196 /**
197 * Build LIMIT query
198 */
199 function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0)
200 {
201 $this->query_result = false;
202
203 // total == 0 means all results - not zero results
204 if ($offset == 0 && $total !== 0)
205 {
206 if (strpos($query, "SELECT") === false)
207 {
208 $query = "TOP {$total} " . $query;
209 }
210 else
211 {
212 $query = preg_replace('/SELECT(\s*DISTINCT)?/Dsi', 'SELECT$1 TOP '.$total, $query);
213 }
214 }
215 else if ($offset > 0)
216 {
217 $query = preg_replace('/SELECT(\s*DISTINCT)?/Dsi', 'SELECT$1 TOP(10000000) ', $query);
218 $query = 'SELECT *
219 FROM (SELECT sub2.*, ROW_NUMBER() OVER(ORDER BY sub2.line2) AS line3
220 FROM (SELECT 1 AS line2, sub1.* FROM (' . $query . ') AS sub1) as sub2) AS sub3';
221
222 if ($total > 0)
223 {
224 $query .= ' WHERE line3 BETWEEN ' . ($offset+1) . ' AND ' . ($offset + $total);
225 }
226 else
227 {
228 $query .= ' WHERE line3 > ' . $offset;
229 }
230 }
231
232 $result = $this->sql_query($query, $cache_ttl);
233
234 return $result;
235 }
236
237 /**
238 * {@inheritDoc}
239 */
240 function sql_affectedrows()
241 {
242 return ($this->db_connect_id) ? @sqlsrv_rows_affected($this->query_result) : false;
243 }
244
245 /**
246 * {@inheritDoc}
247 */
248 function sql_fetchrow($query_id = false)
249 {
250 global $cache;
251
252 if ($query_id === false)
253 {
254 $query_id = $this->query_result;
255 }
256
257 $safe_query_id = $this->clean_query_id($query_id);
258 if ($cache && $cache->sql_exists($safe_query_id))
259 {
260 return $cache->sql_fetchrow($safe_query_id);
261 }
262
263 if (!$query_id)
264 {
265 return false;
266 }
267
268 $row = sqlsrv_fetch_array($query_id, SQLSRV_FETCH_ASSOC);
269
270 if ($row)
271 {
272 foreach ($row as $key => $value)
273 {
274 $row[$key] = ($value === ' ' || $value === null) ? '' : $value;
275 }
276
277 // remove helper values from LIMIT queries
278 if (isset($row['line2']))
279 {
280 unset($row['line2'], $row['line3']);
281 }
282 }
283 return ($row !== null) ? $row : false;
284 }
285
286 /**
287 * {@inheritdoc}
288 */
289 public function sql_last_inserted_id()
290 {
291 $result_id = @sqlsrv_query($this->db_connect_id, 'SELECT @@IDENTITY');
292
293 if ($result_id)
294 {
295 $row = sqlsrv_fetch_array($result_id);
296 $id = $row[0];
297 sqlsrv_free_stmt($result_id);
298 return $id;
299 }
300 else
301 {
302 return false;
303 }
304 }
305
306 /**
307 * {@inheritDoc}
308 */
309 function sql_freeresult($query_id = false)
310 {
311 global $cache;
312
313 if ($query_id === false)
314 {
315 $query_id = $this->query_result;
316 }
317
318 $safe_query_id = $this->clean_query_id($query_id);
319 if ($cache && $cache->sql_exists($safe_query_id))
320 {
321 return $cache->sql_freeresult($safe_query_id);
322 }
323
324 if (isset($this->open_queries[$safe_query_id]))
325 {
326 unset($this->open_queries[$safe_query_id]);
327 return sqlsrv_free_stmt($query_id);
328 }
329
330 return false;
331 }
332
333 /**
334 * return sql error array
335 * @access private
336 */
337 function _sql_error()
338 {
339 if (function_exists('sqlsrv_errors'))
340 {
341 $errors = @sqlsrv_errors(SQLSRV_ERR_ERRORS);
342 $error_message = '';
343 $code = 0;
344
345 if ($errors != null)
346 {
347 foreach ($errors as $error)
348 {
349 $error_message .= "SQLSTATE: " . $error['SQLSTATE'] . "\n";
350 $error_message .= "code: " . $error['code'] . "\n";
351 $code = $error['code'];
352 $error_message .= "message: " . $error['message'] . "\n";
353 }
354 $this->last_error_result = $error_message;
355 $error = $this->last_error_result;
356 }
357 else
358 {
359 $error = (isset($this->last_error_result) && $this->last_error_result) ? $this->last_error_result : array();
360 }
361
362 $error = array(
363 'message' => $error,
364 'code' => $code,
365 );
366 }
367 else
368 {
369 $error = array(
370 'message' => $this->connect_error,
371 'code' => '',
372 );
373 }
374
375 return $error;
376 }
377
378 /**
379 * Close sql connection
380 * @access private
381 */
382 function _sql_close()
383 {
384 return @sqlsrv_close($this->db_connect_id);
385 }
386
387 /**
388 * Build db-specific report
389 * @access private
390 */
391 function _sql_report($mode, $query = '')
392 {
393 switch ($mode)
394 {
395 case 'start':
396 $html_table = false;
397 @sqlsrv_query($this->db_connect_id, 'SET SHOWPLAN_TEXT ON;');
398 if ($result = @sqlsrv_query($this->db_connect_id, $query))
399 {
400 sqlsrv_next_result($result);
401 while ($row = sqlsrv_fetch_array($result))
402 {
403 $html_table = $this->sql_report('add_select_row', $query, $html_table, $row);
404 }
405 sqlsrv_free_stmt($result);
406 }
407 @sqlsrv_query($this->db_connect_id, 'SET SHOWPLAN_TEXT OFF;');
408
409 if ($html_table)
410 {
411 $this->html_hold .= '</table>';
412 }
413 break;
414
415 case 'fromcache':
416 $endtime = explode(' ', microtime());
417 $endtime = $endtime[0] + $endtime[1];
418
419 $result = @sqlsrv_query($this->db_connect_id, $query);
420 if ($result)
421 {
422 while ($void = sqlsrv_fetch_array($result))
423 {
424 // Take the time spent on parsing rows into account
425 }
426 sqlsrv_free_stmt($result);
427 }
428
429 $splittime = explode(' ', microtime());
430 $splittime = $splittime[0] + $splittime[1];
431
432 $this->sql_report('record_fromcache', $query, $endtime, $splittime);
433
434 break;
435 }
436 }
437
438 /**
439 * Utility method used to retrieve number of rows
440 * Emulates mysql_num_rows
441 * Used in acp_database.php -> write_data_mssqlnative()
442 * Requires a static or keyset cursor to be definde via
443 * mssqlnative_set_query_options()
444 */
445 function mssqlnative_num_rows($res)
446 {
447 if ($res !== false)
448 {
449 return sqlsrv_num_rows($res);
450 }
451 else
452 {
453 return false;
454 }
455 }
456
457 /**
458 * Allows setting mssqlnative specific query options passed to sqlsrv_query as 4th parameter.
459 */
460 function mssqlnative_set_query_options($options)
461 {
462 $this->query_options = $options;
463 }
464 }
465