[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/includes/db/ -> firebird.php (source)

   1  <?php
   2  /**
   3  *
   4  * @package dbal
   5  * @version $Id$
   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  */
  14  if (!defined('IN_PHPBB'))
  15  {
  16      exit;
  17  }
  18  
  19  include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
  20  
  21  /**
  22  * Firebird/Interbase Database Abstraction Layer
  23  * Minimum Requirement is Firebird 2.1
  24  * @package dbal
  25  */
  26  class dbal_firebird extends dbal
  27  {
  28      var $last_query_text = '';
  29      var $service_handle = false;
  30      var $affected_rows = 0;
  31      var $connect_error = '';
  32  
  33      /**
  34      * Connect to server
  35      */
  36  	function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
  37      {
  38          $this->persistency = $persistency;
  39          $this->user = $sqluser;
  40          $this->server = $sqlserver . (($port) ? ':' . $port : '');
  41          $this->dbname = str_replace('\\', '/', $database);
  42  
  43          // There are three possibilities to connect to an interbase db
  44          if (!$this->server)
  45          {
  46              $use_database = $this->dbname;
  47          }
  48          else if (strpos($this->server, '//') === 0)
  49          {
  50              $use_database = $this->server . $this->dbname;
  51          }
  52          else
  53          {
  54              $use_database = $this->server . ':' . $this->dbname;
  55          }
  56  
  57          if ($this->persistency)
  58          {
  59              if (!function_exists('ibase_pconnect'))
  60              {
  61                  $this->connect_error = 'ibase_pconnect function does not exist, is interbase extension installed?';
  62                  return $this->sql_error('');
  63              }
  64              $this->db_connect_id = @ibase_pconnect($use_database, $this->user, $sqlpassword, false, false, 3);
  65          }
  66          else
  67          {
  68              if (!function_exists('ibase_connect'))
  69              {
  70                  $this->connect_error = 'ibase_connect function does not exist, is interbase extension installed?';
  71                  return $this->sql_error('');
  72              }
  73              $this->db_connect_id = @ibase_connect($use_database, $this->user, $sqlpassword, false, false, 3);
  74          }
  75  
  76          // Do not call ibase_service_attach if connection failed,
  77          // otherwise error message from ibase_(p)connect call will be clobbered.
  78          if ($this->db_connect_id && function_exists('ibase_service_attach') && $this->server)
  79          {
  80              $this->service_handle = @ibase_service_attach($this->server, $this->user, $sqlpassword);
  81          }
  82          else
  83          {
  84              $this->service_handle = false;
  85          }
  86  
  87          return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error('');
  88      }
  89  
  90      /**
  91      * Version information about used database
  92      * @param bool $raw if true, only return the fetched sql_server_version
  93      * @param bool $use_cache forced to false for Interbase
  94      * @return string sql server version
  95      */
  96  	function sql_server_info($raw = false, $use_cache = true)
  97      {
  98          /**
  99          * force $use_cache false.  I didn't research why the caching code there is no caching code
 100          * but I assume its because the IB extension provides a direct method to access it
 101          * without a query.
 102          */
 103  
 104          $use_cache = false;
 105  
 106          if ($this->service_handle !== false && function_exists('ibase_server_info'))
 107          {
 108              return @ibase_server_info($this->service_handle, IBASE_SVC_SERVER_VERSION);
 109          }
 110  
 111          return ($raw) ? '2.1' : 'Firebird/Interbase';
 112      }
 113  
 114      /**
 115      * SQL Transaction
 116      * @access private
 117      */
 118  	function _sql_transaction($status = 'begin')
 119      {
 120          switch ($status)
 121          {
 122              case 'begin':
 123                  return true;
 124              break;
 125  
 126              case 'commit':
 127                  return @ibase_commit();
 128              break;
 129  
 130              case 'rollback':
 131                  return @ibase_rollback();
 132              break;
 133          }
 134  
 135          return true;
 136      }
 137  
 138      /**
 139      * Base query method
 140      *
 141      * @param    string    $query        Contains the SQL query which shall be executed
 142      * @param    int        $cache_ttl    Either 0 to avoid caching or the time in seconds which the result shall be kept in cache
 143      * @return    mixed                When casted to bool the returned value returns true on success and false on failure
 144      *
 145      * @access    public
 146      */
 147  	function sql_query($query = '', $cache_ttl = 0)
 148      {
 149          if ($query != '')
 150          {
 151              global $cache;
 152  
 153              // EXPLAIN only in extra debug mode
 154              if (defined('DEBUG_EXTRA'))
 155              {
 156                  $this->sql_report('start', $query);
 157              }
 158  
 159              $this->last_query_text = $query;
 160              $this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false;
 161              $this->sql_add_num_queries($this->query_result);
 162  
 163              if ($this->query_result === false)
 164              {
 165                  $array = array();
 166                  // We overcome Firebird's 32767 char limit by binding vars
 167                  if (strlen($query) > 32767)
 168                  {
 169                      if (preg_match('/^(INSERT INTO[^(]++)\\(([^()]+)\\) VALUES[^(]++\\((.*?)\\)$/s', $query, $regs))
 170                      {
 171                          if (strlen($regs[3]) > 32767)
 172                          {
 173                              preg_match_all('/\'(?:[^\']++|\'\')*+\'|[\d-.]+/', $regs[3], $vals, PREG_PATTERN_ORDER);
 174  
 175                              $inserts = $vals[0];
 176                              unset($vals);
 177  
 178                              foreach ($inserts as $key => $value)
 179                              {
 180                                  if (!empty($value) && $value[0] === "'" && strlen($value) > 32769) // check to see if this thing is greater than the max + 'x2
 181                                  {
 182                                      $inserts[$key] = '?';
 183                                      $array[] = str_replace("''", "'", substr($value, 1, -1));
 184                                  }
 185                              }
 186  
 187                              $query = $regs[1] . '(' . $regs[2] . ') VALUES (' . implode(', ', $inserts) . ')';
 188                          }
 189                      }
 190                      else if (preg_match('/^(UPDATE ([\\w_]++)\\s+SET )([\\w_]++\\s*=\\s*(?:\'(?:[^\']++|\'\')*+\'|\\d+)(?:,\\s*[\\w_]++\\s*=\\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]+))*+)\\s+(WHERE.*)$/s', $query, $data))
 191                      {
 192                          if (strlen($data[3]) > 32767)
 193                          {
 194                              $update = $data[1];
 195                              $where = $data[4];
 196                              preg_match_all('/(\\w++)\\s*=\\s*(\'(?:[^\']++|\'\')*+\'|[\d-.]++)/', $data[3], $temp, PREG_SET_ORDER);
 197                              unset($data);
 198  
 199                              $cols = array();
 200                              foreach ($temp as $value)
 201                              {
 202                                  if (!empty($value[2]) && $value[2][0] === "'" && strlen($value[2]) > 32769) // check to see if this thing is greater than the max + 'x2
 203                                  {
 204                                      $array[] = str_replace("''", "'", substr($value[2], 1, -1));
 205                                      $cols[] = $value[1] . '=?';
 206                                  }
 207                                  else
 208                                  {
 209                                      $cols[] = $value[1] . '=' . $value[2];
 210                                  }
 211                              }
 212  
 213                              $query = $update . implode(', ', $cols) . ' ' . $where;
 214                              unset($cols);
 215                          }
 216                      }
 217                  }
 218  
 219                  if (!function_exists('ibase_affected_rows') && (preg_match('/^UPDATE ([\w_]++)\s+SET [\w_]++\s*=\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]+)(?:,\s*[\w_]++\s*=\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]+))*+\s+(WHERE.*)?$/s', $query, $regs) || preg_match('/^DELETE FROM ([\w_]++)\s*(WHERE\s*.*)?$/s', $query, $regs)))
 220                  {
 221                      $affected_sql = 'SELECT COUNT(*) as num_rows_affected FROM ' . $regs[1];
 222                      if (!empty($regs[2]))
 223                      {
 224                          $affected_sql .= ' ' . $regs[2];
 225                      }
 226  
 227                      if (!($temp_q_id = @ibase_query($this->db_connect_id, $affected_sql)))
 228                      {
 229                          return false;
 230                      }
 231  
 232                      $temp_result = @ibase_fetch_assoc($temp_q_id);
 233                      @ibase_free_result($temp_q_id);
 234  
 235                      $this->affected_rows = ($temp_result) ? $temp_result['NUM_ROWS_AFFECTED'] : false;
 236                  }
 237  
 238                  if (sizeof($array))
 239                  {
 240                      $p_query = @ibase_prepare($this->db_connect_id, $query);
 241                      array_unshift($array, $p_query);
 242                      $this->query_result = call_user_func_array('ibase_execute', $array);
 243                      unset($array);
 244  
 245                      if ($this->query_result === false)
 246                      {
 247                          $this->sql_error($query);
 248                      }
 249                  }
 250                  else if (($this->query_result = @ibase_query($this->db_connect_id, $query)) === false)
 251                  {
 252                      $this->sql_error($query);
 253                  }
 254  
 255                  if (defined('DEBUG_EXTRA'))
 256                  {
 257                      $this->sql_report('stop', $query);
 258                  }
 259  
 260                  if (!$this->transaction)
 261                  {
 262                      if (function_exists('ibase_commit_ret'))
 263                      {
 264                          @ibase_commit_ret();
 265                      }
 266                      else
 267                      {
 268                          // way cooler than ibase_commit_ret :D
 269                          @ibase_query('COMMIT RETAIN;');
 270                      }
 271                  }
 272  
 273                  if ($cache_ttl && method_exists($cache, 'sql_save'))
 274                  {
 275                      $this->open_queries[(int) $this->query_result] = $this->query_result;
 276                      $cache->sql_save($query, $this->query_result, $cache_ttl);
 277                  }
 278                  else if (strpos($query, 'SELECT') === 0 && $this->query_result)
 279                  {
 280                      $this->open_queries[(int) $this->query_result] = $this->query_result;
 281                  }
 282              }
 283              else if (defined('DEBUG_EXTRA'))
 284              {
 285                  $this->sql_report('fromcache', $query);
 286              }
 287          }
 288          else
 289          {
 290              return false;
 291          }
 292  
 293          return $this->query_result;
 294      }
 295  
 296      /**
 297      * Build LIMIT query
 298      */
 299  	function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0)
 300      {
 301          $this->query_result = false;
 302  
 303          $query = 'SELECT FIRST ' . $total . ((!empty($offset)) ? ' SKIP ' . $offset : '') . substr($query, 6);
 304  
 305          return $this->sql_query($query, $cache_ttl);
 306      }
 307  
 308      /**
 309      * Return number of affected rows
 310      */
 311  	function sql_affectedrows()
 312      {
 313          // PHP 5+ function
 314          if (function_exists('ibase_affected_rows'))
 315          {
 316              return ($this->db_connect_id) ? @ibase_affected_rows($this->db_connect_id) : false;
 317          }
 318          else
 319          {
 320              return $this->affected_rows;
 321          }
 322      }
 323  
 324      /**
 325      * Fetch current row
 326      */
 327  	function sql_fetchrow($query_id = false)
 328      {
 329          global $cache;
 330  
 331          if ($query_id === false)
 332          {
 333              $query_id = $this->query_result;
 334          }
 335  
 336          if (isset($cache->sql_rowset[$query_id]))
 337          {
 338              return $cache->sql_fetchrow($query_id);
 339          }
 340  
 341          if ($query_id === false)
 342          {
 343              return false;
 344          }
 345  
 346          $row = array();
 347          $cur_row = @ibase_fetch_object($query_id, IBASE_TEXT);
 348  
 349          if (!$cur_row)
 350          {
 351              return false;
 352          }
 353  
 354          foreach (get_object_vars($cur_row) as $key => $value)
 355          {
 356              $row[strtolower($key)] = (is_string($value)) ? trim(str_replace(array("\\0", "\\n"), array("\0", "\n"), $value)) : $value;
 357          }
 358  
 359          return (sizeof($row)) ? $row : false;
 360      }
 361  
 362      /**
 363      * Get last inserted id after insert statement
 364      */
 365  	function sql_nextid()
 366      {
 367          $query_id = $this->query_result;
 368  
 369          if ($query_id !== false && $this->last_query_text != '')
 370          {
 371              if ($this->query_result && preg_match('#^INSERT[\t\n ]+INTO[\t\n ]+([a-z0-9\_\-]+)#i', $this->last_query_text, $tablename))
 372              {
 373                  $sql = 'SELECT GEN_ID(' . $tablename[1] . '_gen, 0) AS new_id FROM RDB$DATABASE';
 374  
 375                  if (!($temp_q_id = @ibase_query($this->db_connect_id, $sql)))
 376                  {
 377                      return false;
 378                  }
 379  
 380                  $temp_result = @ibase_fetch_assoc($temp_q_id);
 381                  @ibase_free_result($temp_q_id);
 382  
 383                  return ($temp_result) ? $temp_result['NEW_ID'] : false;
 384              }
 385          }
 386  
 387          return false;
 388      }
 389  
 390      /**
 391      * Free sql result
 392      */
 393  	function sql_freeresult($query_id = false)
 394      {
 395          global $cache;
 396  
 397          if ($query_id === false)
 398          {
 399              $query_id = $this->query_result;
 400          }
 401  
 402          if (isset($cache->sql_rowset[$query_id]))
 403          {
 404              return $cache->sql_freeresult($query_id);
 405          }
 406  
 407          if (isset($this->open_queries[(int) $query_id]))
 408          {
 409              unset($this->open_queries[(int) $query_id]);
 410              return @ibase_free_result($query_id);
 411          }
 412  
 413          return false;
 414      }
 415  
 416      /**
 417      * Escape string used in sql query
 418      */
 419  	function sql_escape($msg)
 420      {
 421          return str_replace(array("'", "\0"), array("''", ''), $msg);
 422      }
 423  
 424      /**
 425      * Build LIKE expression
 426      * @access private
 427      */
 428  	function _sql_like_expression($expression)
 429      {
 430          return $expression . " ESCAPE '\\'";
 431      }
 432  
 433      /**
 434      * Build db-specific query data
 435      * @access private
 436      */
 437  	function _sql_custom_build($stage, $data)
 438      {
 439          return $data;
 440      }
 441  
 442  	function _sql_bit_and($column_name, $bit, $compare = '')
 443      {
 444          return 'BIN_AND(' . $column_name . ', ' . (1 << $bit) . ')' . (($compare) ? ' ' . $compare : '');
 445      }
 446  
 447  	function _sql_bit_or($column_name, $bit, $compare = '')
 448      {
 449          return 'BIN_OR(' . $column_name . ', ' . (1 << $bit) . ')' . (($compare) ? ' ' . $compare : '');
 450      }
 451  
 452      /**
 453      * return sql error array
 454      * @access private
 455      */
 456  	function _sql_error()
 457      {
 458          // Need special handling here because ibase_errmsg returns
 459          // connection errors, however if the interbase extension
 460          // is not installed then ibase_errmsg does not exist and
 461          // we cannot call it.
 462          if (function_exists('ibase_errmsg'))
 463          {
 464              $msg = @ibase_errmsg();
 465              if (!$msg)
 466              {
 467                  $msg = $this->connect_error;
 468              }
 469          }
 470          else
 471          {
 472              $msg = $this->connect_error;
 473          }
 474          return array(
 475              'message'    => $msg,
 476              'code'        => (@function_exists('ibase_errcode') ? @ibase_errcode() : '')
 477          );
 478      }
 479  
 480      /**
 481      * Close sql connection
 482      * @access private
 483      */
 484  	function _sql_close()
 485      {
 486          if ($this->service_handle !== false)
 487          {
 488              @ibase_service_detach($this->service_handle);
 489          }
 490  
 491          return @ibase_close($this->db_connect_id);
 492      }
 493  
 494      /**
 495      * Build db-specific report
 496      * @access private
 497      */
 498  	function _sql_report($mode, $query = '')
 499      {
 500          switch ($mode)
 501          {
 502              case 'start':
 503              break;
 504  
 505              case 'fromcache':
 506                  $endtime = explode(' ', microtime());
 507                  $endtime = $endtime[0] + $endtime[1];
 508  
 509                  $result = @ibase_query($this->db_connect_id, $query);
 510                  while ($void = @ibase_fetch_object($result, IBASE_TEXT))
 511                  {
 512                      // Take the time spent on parsing rows into account
 513                  }
 514                  @ibase_free_result($result);
 515  
 516                  $splittime = explode(' ', microtime());
 517                  $splittime = $splittime[0] + $splittime[1];
 518  
 519                  $this->sql_report('record_fromcache', $query, $endtime, $splittime);
 520  
 521              break;
 522          }
 523      }
 524  }
 525  
 526  ?>


Generated: Wed Oct 2 15:03:47 2013 Cross-referenced by PHPXref 0.7.1