[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
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 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Oct 2 15:03:47 2013 | Cross-referenced by PHPXref 0.7.1 |