[ Index ]

PHP Cross Reference of phpBB-3.3.5-deutsch

title

Body

[close]

/phpbb/db/driver/ -> sqlite3.php (source)

   1  <?php
   2  /**
   3  *
   4  * This file is part of the phpBB Forum Software package.
   5  *
   6  * @copyright (c) phpBB Limited <https://www.phpbb.com>
   7  * @license GNU General Public License, version 2 (GPL-2.0)
   8  *
   9  * For full copyright and license information, please see
  10  * the docs/CREDITS.txt file.
  11  *
  12  */
  13  
  14  namespace phpbb\db\driver;
  15  
  16  /**
  17  * SQLite3 Database Abstraction Layer
  18  * Minimum Requirement: 3.6.15+
  19  */
  20  class sqlite3 extends \phpbb\db\driver\driver
  21  {
  22      /**
  23      * @var    string        Stores errors during connection setup in case the driver is not available
  24      */
  25      protected $connect_error = '';
  26  
  27      /**
  28      * @var    \SQLite3    The SQLite3 database object to operate against
  29      */
  30      protected $dbo = null;
  31  
  32      /**
  33      * {@inheritDoc}
  34      */
  35  	public function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
  36      {
  37          $this->persistency = false;
  38          $this->user = $sqluser;
  39          $this->server = $sqlserver . (($port) ? ':' . $port : '');
  40          $this->dbname = $database;
  41  
  42          if (!class_exists('SQLite3', false))
  43          {
  44              $this->connect_error = 'SQLite3 not found, is the extension installed?';
  45              return $this->sql_error('');
  46          }
  47  
  48          try
  49          {
  50              $this->dbo = new \SQLite3($this->server, SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE);
  51              $this->dbo->busyTimeout(60000);
  52              $this->db_connect_id = true;
  53          }
  54          catch (\Exception $e)
  55          {
  56              $this->connect_error = $e->getMessage();
  57              return array('message' => $this->connect_error);
  58          }
  59  
  60          return true;
  61      }
  62  
  63      /**
  64      * {@inheritDoc}
  65      */
  66  	public function sql_server_info($raw = false, $use_cache = true)
  67      {
  68          global $cache;
  69  
  70          if (!$use_cache || empty($cache) || ($this->sql_server_version = $cache->get('sqlite_version')) === false)
  71          {
  72              $version = \SQLite3::version();
  73  
  74              $this->sql_server_version = $version['versionString'];
  75  
  76              if (!empty($cache) && $use_cache)
  77              {
  78                  $cache->put('sqlite_version', $this->sql_server_version);
  79              }
  80          }
  81  
  82          return ($raw) ? $this->sql_server_version : 'SQLite ' . $this->sql_server_version;
  83      }
  84  
  85      /**
  86      * SQL Transaction
  87      *
  88      * @param    string    $status        Should be one of the following strings:
  89      *                                begin, commit, rollback
  90      * @return    bool    Success/failure of the transaction query
  91      */
  92  	protected function _sql_transaction($status = 'begin')
  93      {
  94          switch ($status)
  95          {
  96              case 'begin':
  97                  return $this->dbo->exec('BEGIN IMMEDIATE');
  98              break;
  99  
 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              if ($this->debug_sql_explain)
 122              {
 123                  $this->sql_report('start', $query);
 124              }
 125              else if ($this->debug_load_time)
 126              {
 127                  $this->curtime = microtime(true);
 128              }
 129  
 130              $this->last_query_text = $query;
 131              $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;
 132              $this->sql_add_num_queries($this->query_result);
 133  
 134              if ($this->query_result === false)
 135              {
 136                  if ($this->transaction === true && strpos($query, 'INSERT') === 0)
 137                  {
 138                      $query = preg_replace('/^INSERT INTO/', 'INSERT OR ROLLBACK INTO', $query);
 139                  }
 140  
 141                  if (($this->query_result = @$this->dbo->query($query)) === false)
 142                  {
 143                      // Try to recover a lost database connection
 144                      if ($this->dbo && !@$this->dbo->lastErrorMsg())
 145                      {
 146                          if ($this->sql_connect($this->server, $this->user, '', $this->dbname))
 147                          {
 148                              $this->query_result = @$this->dbo->query($query);
 149                          }
 150                      }
 151  
 152                      if ($this->query_result === false)
 153                      {
 154                          $this->sql_error($query);
 155                      }
 156                  }
 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                  if ($cache && $cache_ttl)
 173                  {
 174                      $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
 175                  }
 176              }
 177              else if ($this->debug_sql_explain)
 178              {
 179                  $this->sql_report('fromcache', $query);
 180              }
 181          }
 182          else
 183          {
 184              return false;
 185          }
 186  
 187          return $this->query_result;
 188      }
 189  
 190      /**
 191      * Build LIMIT query
 192      *
 193      * @param    string    $query        The SQL query to execute
 194      * @param    int        $total        The number of rows to select
 195      * @param    int        $offset
 196      * @param    int        $cache_ttl    Either 0 to avoid caching or
 197      *                the time in seconds which the result shall be kept in cache
 198      * @return    mixed    Buffered, seekable result handle, false on error
 199      */
 200  	protected function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0)
 201      {
 202          $this->query_result = false;
 203  
 204          // if $total is set to 0 we do not want to limit the number of rows
 205          if ($total == 0)
 206          {
 207              $total = -1;
 208          }
 209  
 210          $query .= "\n LIMIT " . ((!empty($offset)) ? $offset . ', ' . $total : $total);
 211  
 212          return $this->sql_query($query, $cache_ttl);
 213      }
 214  
 215      /**
 216      * {@inheritDoc}
 217      */
 218  	public function sql_affectedrows()
 219      {
 220          return ($this->db_connect_id) ? $this->dbo->changes() : false;
 221      }
 222  
 223      /**
 224      * {@inheritDoc}
 225      */
 226  	public function sql_fetchrow($query_id = false)
 227      {
 228          global $cache;
 229  
 230          if ($query_id === false)
 231          {
 232              /** @var \SQLite3Result $query_id */
 233              $query_id = $this->query_result;
 234          }
 235  
 236          if ($cache && !is_object($query_id) && $cache->sql_exists($query_id))
 237          {
 238              return $cache->sql_fetchrow($query_id);
 239          }
 240  
 241          return is_object($query_id) ? @$query_id->fetchArray(SQLITE3_ASSOC) : false;
 242      }
 243  
 244      /**
 245      * {@inheritDoc}
 246      */
 247  	public function sql_nextid()
 248      {
 249          return ($this->db_connect_id) ? $this->dbo->lastInsertRowID() : false;
 250      }
 251  
 252      /**
 253      * {@inheritDoc}
 254      */
 255  	public function sql_freeresult($query_id = false)
 256      {
 257          global $cache;
 258  
 259          if ($query_id === false)
 260          {
 261              $query_id = $this->query_result;
 262          }
 263  
 264          if ($cache && !is_object($query_id) && $cache->sql_exists($query_id))
 265          {
 266              return $cache->sql_freeresult($query_id);
 267          }
 268  
 269          if ($query_id)
 270          {
 271              return @$query_id->finalize();
 272          }
 273      }
 274  
 275      /**
 276      * {@inheritDoc}
 277      */
 278  	public function sql_escape($msg)
 279      {
 280          return \SQLite3::escapeString($msg);
 281      }
 282  
 283      /**
 284      * {@inheritDoc}
 285      *
 286      * For SQLite an underscore is an unknown character.
 287      */
 288  	public function sql_like_expression($expression)
 289      {
 290          // Unlike LIKE, GLOB is unfortunately case sensitive.
 291          // We only catch * and ? here, not the character map possible on file globbing.
 292          $expression = str_replace(array(chr(0) . '_', chr(0) . '%'), array(chr(0) . '?', chr(0) . '*'), $expression);
 293  
 294          $expression = str_replace(array('?', '*'), array("\?", "\*"), $expression);
 295          $expression = str_replace(array(chr(0) . "\?", chr(0) . "\*"), array('?', '*'), $expression);
 296  
 297          return 'GLOB \'' . $this->sql_escape($expression) . '\'';
 298      }
 299  
 300      /**
 301      * {@inheritDoc}
 302      *
 303      * For SQLite an underscore is an unknown character.
 304      */
 305  	public function sql_not_like_expression($expression)
 306      {
 307          // Unlike NOT LIKE, NOT GLOB is unfortunately case sensitive
 308          // We only catch * and ? here, not the character map possible on file globbing.
 309          $expression = str_replace(array(chr(0) . '_', chr(0) . '%'), array(chr(0) . '?', chr(0) . '*'), $expression);
 310  
 311          $expression = str_replace(array('?', '*'), array("\?", "\*"), $expression);
 312          $expression = str_replace(array(chr(0) . "\?", chr(0) . "\*"), array('?', '*'), $expression);
 313  
 314          return 'NOT GLOB \'' . $this->sql_escape($expression) . '\'';
 315      }
 316  
 317      /**
 318      * return sql error array
 319      *
 320      * @return array
 321      */
 322  	protected function _sql_error()
 323      {
 324          if (class_exists('SQLite3', false) && isset($this->dbo))
 325          {
 326              $error = array(
 327                  'message'    => $this->dbo->lastErrorMsg(),
 328                  'code'        => $this->dbo->lastErrorCode(),
 329              );
 330          }
 331          else
 332          {
 333              $error = array(
 334                  'message'    => $this->connect_error,
 335                  'code'        => '',
 336              );
 337          }
 338  
 339          return $error;
 340      }
 341  
 342      /**
 343      * Build db-specific query data
 344      *
 345      * @param    string    $stage        Available stages: FROM, WHERE
 346      * @param    mixed    $data        A string containing the CROSS JOIN query or an array of WHERE clauses
 347      *
 348      * @return    string    The db-specific query fragment
 349      */
 350  	protected function _sql_custom_build($stage, $data)
 351      {
 352          return $data;
 353      }
 354  
 355      /**
 356      * Close sql connection
 357      *
 358      * @return    bool        False if failure
 359      */
 360  	protected function _sql_close()
 361      {
 362          return $this->dbo->close();
 363      }
 364  
 365      /**
 366      * Build db-specific report
 367      *
 368      * @param    string    $mode        Available modes: display, start, stop,
 369      *                                add_select_row, fromcache, record_fromcache
 370      * @param    string    $query        The Query that should be explained
 371      * @return    mixed        Either a full HTML page, boolean or null
 372      */
 373  	protected function _sql_report($mode, $query = '')
 374      {
 375          switch ($mode)
 376          {
 377              case 'start':
 378  
 379                  $explain_query = $query;
 380                  if (preg_match('/UPDATE ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m))
 381                  {
 382                      $explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2];
 383                  }
 384                  else if (preg_match('/DELETE FROM ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m))
 385                  {
 386                      $explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2];
 387                  }
 388  
 389                  if (preg_match('/^SELECT/', $explain_query))
 390                  {
 391                      $html_table = false;
 392  
 393                      if ($result = $this->dbo->query("EXPLAIN QUERY PLAN $explain_query"))
 394                      {
 395                          while ($row = $result->fetchArray(SQLITE3_ASSOC))
 396                          {
 397                              $html_table = $this->sql_report('add_select_row', $query, $html_table, $row);
 398                          }
 399                      }
 400  
 401                      if ($html_table)
 402                      {
 403                          $this->html_hold .= '</table>';
 404                      }
 405                  }
 406  
 407              break;
 408  
 409              case 'fromcache':
 410                  $endtime = explode(' ', microtime());
 411                  $endtime = $endtime[0] + $endtime[1];
 412  
 413                  $result = $this->dbo->query($query);
 414                  if ($result)
 415                  {
 416                          while ($void = $result->fetchArray(SQLITE3_ASSOC))
 417                          {
 418                              // Take the time spent on parsing rows into account
 419                          }
 420                  }
 421  
 422                  $splittime = explode(' ', microtime());
 423                  $splittime = $splittime[0] + $splittime[1];
 424  
 425                  $this->sql_report('record_fromcache', $query, $endtime, $splittime);
 426  
 427              break;
 428          }
 429      }
 430  
 431      /**
 432      * {@inheritDoc}
 433      */
 434  	function sql_quote($msg)
 435      {
 436          return '\'' . $msg . '\'';
 437      }
 438  }


Generated: Mon Oct 4 17:42:11 2021 Cross-referenced by PHPXref 0.7.1