Verzeichnisstruktur phpBB-3.2.0


Veröffentlicht
06.01.2017

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.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

sqlite3.php

Zuletzt modifiziert: 09.10.2024, 12:54 - Dateigröße: 9.56 KiB


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  namespace phpbb\db\driver;
015   
016  /**
017  * SQLite3 Database Abstraction Layer
018  * Minimum Requirement: 3.6.15+
019  */
020  class sqlite3 extends \phpbb\db\driver\driver
021  {
022      /**
023      * @var    string        Stores errors during connection setup in case the driver is not available
024      */
025      protected $connect_error = '';
026   
027      /**
028      * @var    \SQLite3    The SQLite3 database object to operate against
029      */
030      protected $dbo = null;
031   
032      /**
033      * {@inheritDoc}
034      */
035      public function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
036      {
037          $this->persistency = false;
038          $this->user = $sqluser;
039          $this->server = $sqlserver . (($port) ? ':' . $port : '');
040          $this->dbname = $database;
041   
042          if (!class_exists('SQLite3', false))
043          {
044              $this->connect_error = 'SQLite3 not found, is the extension installed?';
045              return $this->sql_error('');
046          }
047   
048          try
049          {
050              $this->dbo = new \SQLite3($this->server, SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE);
051              $this->dbo->busyTimeout(60000);
052              $this->db_connect_id = true;
053          }
054          catch (\Exception $e)
055          {
056              $this->connect_error = $e->getMessage();
057              return array('message' => $this->connect_error);
058          }
059   
060          return true;
061      }
062   
063      /**
064      * {@inheritDoc}
065      */
066      public function sql_server_info($raw = false, $use_cache = true)
067      {
068          global $cache;
069   
070          if (!$use_cache || empty($cache) || ($this->sql_server_version = $cache->get('sqlite_version')) === false)
071          {
072              $version = \SQLite3::version();
073   
074              $this->sql_server_version = $version['versionString'];
075   
076              if (!empty($cache) && $use_cache)
077              {
078                  $cache->put('sqlite_version', $this->sql_server_version);
079              }
080          }
081   
082          return ($raw) ? $this->sql_server_version : 'SQLite ' . $this->sql_server_version;
083      }
084   
085      /**
086      * SQL Transaction
087      *
088      * @param    string    $status        Should be one of the following strings:
089      *                                begin, commit, rollback
090      * @return    bool    Success/failure of the transaction query
091      */
092      protected function _sql_transaction($status = 'begin')
093      {
094          switch ($status)
095          {
096              case 'begin':
097                  return $this->dbo->exec('BEGIN IMMEDIATE');
098              break;
099   
100              case 'commit':
101                  return $this->dbo->exec('COMMIT');
102              break;
103   
104              case 'rollback':
105                  return @$this->dbo->exec('ROLLBACK');
106              break;
107          }
108   
109          return true;
110      }
111   
112      /**
113      * {@inheritDoc}
114      */
115      public function sql_query($query = '', $cache_ttl = 0)
116      {
117          if ($query != '')
118          {
119              global $cache;
120   
121              // EXPLAIN only in extra debug mode
122              if (defined('DEBUG'))
123              {
124                  $this->sql_report('start', $query);
125              }
126              else if (defined('PHPBB_DISPLAY_LOAD_TIME'))
127              {
128                  $this->curtime = microtime(true);
129              }
130   
131              $this->last_query_text = $query;
132              $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;
133              $this->sql_add_num_queries($this->query_result);
134   
135              if ($this->query_result === false)
136              {
137                  if ($this->transaction === true && strpos($query, 'INSERT') === 0)
138                  {
139                      $query = preg_replace('/^INSERT INTO/', 'INSERT OR ROLLBACK INTO', $query);
140                  }
141   
142                  if (($this->query_result = @$this->dbo->query($query)) === false)
143                  {
144                      // Try to recover a lost database connection
145                      if ($this->dbo && !@$this->dbo->lastErrorMsg())
146                      {
147                          if ($this->sql_connect($this->server, $this->user, '', $this->dbname))
148                          {
149                              $this->query_result = @$this->dbo->query($query);
150                          }
151                      }
152   
153                      if ($this->query_result === false)
154                      {
155                          $this->sql_error($query);
156                      }
157                  }
158   
159                  if (defined('DEBUG'))
160                  {
161                      $this->sql_report('stop', $query);
162                  }
163                  else if (defined('PHPBB_DISPLAY_LOAD_TIME'))
164                  {
165                      $this->sql_time += microtime(true) - $this->curtime;
166                  }
167   
168                  if (!$this->query_result)
169                  {
170                      return false;
171                  }
172   
173                  if ($cache && $cache_ttl)
174                  {
175                      $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
176                  }
177              }
178              else if (defined('DEBUG'))
179              {
180                  $this->sql_report('fromcache', $query);
181              }
182          }
183          else
184          {
185              return false;
186          }
187   
188          return $this->query_result;
189      }
190   
191      /**
192      * Build LIMIT query
193      *
194      * @param    string    $query        The SQL query to execute
195      * @param    int        $total        The number of rows to select
196      * @param    int        $offset
197      * @param    int        $cache_ttl    Either 0 to avoid caching or
198      *                the time in seconds which the result shall be kept in cache
199      * @return    mixed    Buffered, seekable result handle, false on error
200      */
201      protected function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0)
202      {
203          $this->query_result = false;
204   
205          // if $total is set to 0 we do not want to limit the number of rows
206          if ($total == 0)
207          {
208              $total = -1;
209          }
210   
211          $query .= "\n LIMIT " . ((!empty($offset)) ? $offset . ', ' . $total : $total);
212   
213          return $this->sql_query($query, $cache_ttl);
214      }
215   
216      /**
217      * {@inheritDoc}
218      */
219      public function sql_affectedrows()
220      {
221          return ($this->db_connect_id) ? $this->dbo->changes() : false;
222      }
223   
224      /**
225      * {@inheritDoc}
226      */
227      public function sql_fetchrow($query_id = false)
228      {
229          global $cache;
230   
231          if ($query_id === false)
232          {
233              /** @var \SQLite3Result $query_id */
234              $query_id = $this->query_result;
235          }
236   
237          if ($cache && !is_object($query_id) && $cache->sql_exists($query_id))
238          {
239              return $cache->sql_fetchrow($query_id);
240          }
241   
242          return is_object($query_id) ? @$query_id->fetchArray(SQLITE3_ASSOC) : false;
243      }
244   
245      /**
246      * {@inheritDoc}
247      */
248      public function sql_nextid()
249      {
250          return ($this->db_connect_id) ? $this->dbo->lastInsertRowID() : false;
251      }
252   
253      /**
254      * {@inheritDoc}
255      */
256      public function sql_freeresult($query_id = false)
257      {
258          global $cache;
259   
260          if ($query_id === false)
261          {
262              $query_id = $this->query_result;
263          }
264   
265          if ($cache && !is_object($query_id) && $cache->sql_exists($query_id))
266          {
267              return $cache->sql_freeresult($query_id);
268          }
269   
270          if ($query_id)
271          {
272              return @$query_id->finalize();
273          }
274      }
275   
276      /**
277      * {@inheritDoc}
278      */
279      public function sql_escape($msg)
280      {
281          return \SQLite3::escapeString($msg);
282      }
283   
284      /**
285      * {@inheritDoc}
286      *
287      * For SQLite an underscore is an unknown character.
288      */
289      public function sql_like_expression($expression)
290      {
291          // Unlike LIKE, GLOB is unfortunately case sensitive.
292          // We only catch * and ? here, not the character map possible on file globbing.
293          $expression = str_replace(array(chr(0) . '_', chr(0) . '%'), array(chr(0) . '?', chr(0) . '*'), $expression);
294   
295          $expression = str_replace(array('?', '*'), array("\?", "\*"), $expression);
296          $expression = str_replace(array(chr(0) . "\?", chr(0) . "\*"), array('?', '*'), $expression);
297   
298          return 'GLOB \'' . $this->sql_escape($expression) . '\'';
299      }
300   
301      /**
302      * {@inheritDoc}
303      *
304      * For SQLite an underscore is an unknown character.
305      */
306      public function sql_not_like_expression($expression)
307      {
308          // Unlike NOT LIKE, NOT GLOB is unfortunately case sensitive
309          // We only catch * and ? here, not the character map possible on file globbing.
310          $expression = str_replace(array(chr(0) . '_', chr(0) . '%'), array(chr(0) . '?', chr(0) . '*'), $expression);
311   
312          $expression = str_replace(array('?', '*'), array("\?", "\*"), $expression);
313          $expression = str_replace(array(chr(0) . "\?", chr(0) . "\*"), array('?', '*'), $expression);
314   
315          return 'NOT GLOB \'' . $this->sql_escape($expression) . '\'';
316      }
317   
318      /**
319      * return sql error array
320      *
321      * @return array
322      */
323      protected function _sql_error()
324      {
325          if (class_exists('SQLite3', false) && isset($this->dbo))
326          {
327              $error = array(
328                  'message'    => $this->dbo->lastErrorMsg(),
329                  'code'        => $this->dbo->lastErrorCode(),
330              );
331          }
332          else
333          {
334              $error = array(
335                  'message'    => $this->connect_error,
336                  'code'        => '',
337              );
338          }
339   
340          return $error;
341      }
342   
343      /**
344      * Build db-specific query data
345      *
346      * @param    string    $stage        Available stages: FROM, WHERE
347      * @param    mixed    $data        A string containing the CROSS JOIN query or an array of WHERE clauses
348      *
349      * @return    string    The db-specific query fragment
350      */
351      protected function _sql_custom_build($stage, $data)
352      {
353          return $data;
354      }
355   
356      /**
357      * Close sql connection
358      *
359      * @return    bool        False if failure
360      */
361      protected function _sql_close()
362      {
363          return $this->dbo->close();
364      }
365   
366      /**
367      * Build db-specific report
368      *
369      * @param    string    $mode        Available modes: display, start, stop,
370      *                                add_select_row, fromcache, record_fromcache
371      * @param    string    $query        The Query that should be explained
372      * @return    mixed        Either a full HTML page, boolean or null
373      */
374      protected function _sql_report($mode, $query = '')
375      {
376          switch ($mode)
377          {
378              case 'start':
379   
380                  $explain_query = $query;
381                  if (preg_match('/UPDATE ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m))
382                  {
383                      $explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2];
384                  }
385                  else if (preg_match('/DELETE FROM ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m))
386                  {
387                      $explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2];
388                  }
389   
390                  if (preg_match('/^SELECT/', $explain_query))
391                  {
392                      $html_table = false;
393   
394                      if ($result = $this->dbo->query("EXPLAIN QUERY PLAN $explain_query"))
395                      {
396                          while ($row = $result->fetchArray(SQLITE3_ASSOC))
397                          {
398                              $html_table = $this->sql_report('add_select_row', $query, $html_table, $row);
399                          }
400                      }
401   
402                      if ($html_table)
403                      {
404                          $this->html_hold .= '</table>';
405                      }
406                  }
407   
408              break;
409   
410              case 'fromcache':
411                  $endtime = explode(' ', microtime());
412                  $endtime = $endtime[0] + $endtime[1];
413   
414                  $result = $this->dbo->query($query);
415                  if ($result)
416                  {
417                          while ($void = $result->fetchArray(SQLITE3_ASSOC))
418                          {
419                              // Take the time spent on parsing rows into account
420                          }
421                  }
422   
423                  $splittime = explode(' ', microtime());
424                  $splittime = $splittime[0] + $splittime[1];
425   
426                  $this->sql_report('record_fromcache', $query, $endtime, $splittime);
427   
428              break;
429          }
430      }
431  }
432