PageRenderTime 55ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/includes/db/firebird.php

https://github.com/lucanos/scuttle
PHP | 527 lines | 409 code | 88 blank | 30 comment | 67 complexity | 63ce4b95fa710b10f7d5c76beb1b2de4 MD5 | raw file
  1. <?php
  2. /**
  3. *
  4. * @package dbal_firebird
  5. * @version $Id: firebird.php,v 1.2 2005/06/10 08:52:03 devalley Exp $
  6. * @copyright (c) 2005 phpBB Group
  7. * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  8. *
  9. */
  10. /**
  11. * @ignore
  12. */
  13. if (!defined('SQL_LAYER'))
  14. {
  15. define('SQL_LAYER', 'firebird');
  16. /**
  17. * @package dbal_firebird
  18. * Firebird/Interbase Database Abstraction Layer
  19. * Minimum Requirement is Firebird 1.5+/Interbase 7.1+
  20. */
  21. class sql_db
  22. {
  23. var $db_connect_id;
  24. var $query_result;
  25. var $return_on_error = false;
  26. var $transaction = false;
  27. var $sql_time = 0;
  28. var $num_queries = 0;
  29. var $open_queries = array();
  30. var $last_query_text = '';
  31. function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false)
  32. {
  33. $this->persistency = $persistency;
  34. $this->user = $sqluser;
  35. $this->server = $sqlserver . (($port) ? ':' . $port : '');
  36. $this->dbname = $database;
  37. $this->db_connect_id = ($this->persistency) ? @ibase_pconnect($this->server . ':' . $this->dbname, $this->user, $sqlpassword, false, false, 3) : @ibase_connect($this->server . ':' . $this->dbname, $this->user, $sqlpassword, false, false, 3);
  38. return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error('');
  39. }
  40. //
  41. // Other base methods
  42. //
  43. function sql_close()
  44. {
  45. if (!$this->db_connect_id)
  46. {
  47. return false;
  48. }
  49. if ($this->transaction)
  50. {
  51. @ibase_commit($this->db_connect_id);
  52. }
  53. if (sizeof($this->open_queries))
  54. {
  55. foreach ($this->open_queries as $i_query_id => $query_id)
  56. {
  57. @ibase_free_query($query_id);
  58. }
  59. }
  60. return @ibase_close($this->db_connect_id);
  61. }
  62. function sql_return_on_error($fail = false)
  63. {
  64. $this->return_on_error = $fail;
  65. }
  66. function sql_num_queries()
  67. {
  68. return $this->num_queries;
  69. }
  70. function sql_transaction($status = 'begin')
  71. {
  72. switch ($status)
  73. {
  74. case 'begin':
  75. $this->transaction = true;
  76. break;
  77. case 'commit':
  78. $result = @ibase_commit();
  79. $this->transaction = false;
  80. if (!$result)
  81. {
  82. @ibase_rollback();
  83. }
  84. break;
  85. case 'rollback':
  86. $result = @ibase_rollback();
  87. $this->transaction = false;
  88. break;
  89. default:
  90. $result = true;
  91. }
  92. return $result;
  93. }
  94. // Base query method
  95. function sql_query($query = '', $cache_ttl = 0)
  96. {
  97. if ($query != '')
  98. {
  99. global $cache;
  100. $this->last_query_text = $query;
  101. $this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false;
  102. if (!$this->query_result)
  103. {
  104. $this->num_queries++;
  105. if (($this->query_result = @ibase_query($this->db_connect_id, $query)) === false)
  106. {
  107. $this->sql_error($query);
  108. }
  109. // TODO: have to debug the commit states in firebird
  110. if (!$this->transaction)
  111. {
  112. @ibase_commit_ret();
  113. }
  114. if ($cache_ttl && method_exists($cache, 'sql_save'))
  115. {
  116. $cache->sql_save($query, $this->query_result, $cache_ttl);
  117. }
  118. }
  119. }
  120. else
  121. {
  122. return false;
  123. }
  124. return ($this->query_result) ? $this->query_result : false;
  125. }
  126. function sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0)
  127. {
  128. if ($query != '')
  129. {
  130. $this->query_result = false;
  131. $query = 'SELECT FIRST ' . $total . ((!empty($offset)) ? ' SKIP ' . $offset : '') . substr($query, 6);
  132. return $this->sql_query($query, $cache_ttl);
  133. }
  134. else
  135. {
  136. return false;
  137. }
  138. }
  139. // Idea for this from Ikonboard
  140. function sql_build_array($query, $assoc_ary = false)
  141. {
  142. if (!is_array($assoc_ary))
  143. {
  144. return false;
  145. }
  146. $fields = array();
  147. $values = array();
  148. if ($query == 'INSERT')
  149. {
  150. foreach ($assoc_ary as $key => $var)
  151. {
  152. $fields[] = $key;
  153. if (is_null($var))
  154. {
  155. $values[] = 'NULL';
  156. }
  157. elseif (is_string($var))
  158. {
  159. $values[] = "'" . $this->sql_escape($var) . "'";
  160. }
  161. else
  162. {
  163. $values[] = (is_bool($var)) ? intval($var) : $var;
  164. }
  165. }
  166. $query = ' (' . implode(', ', $fields) . ') VALUES (' . implode(', ', $values) . ')';
  167. }
  168. else if ($query == 'UPDATE' || $query == 'SELECT')
  169. {
  170. $values = array();
  171. foreach ($assoc_ary as $key => $var)
  172. {
  173. if (is_null($var))
  174. {
  175. $values[] = "$key = NULL";
  176. }
  177. elseif (is_string($var))
  178. {
  179. $values[] = "$key = '" . $this->sql_escape($var) . "'";
  180. }
  181. else
  182. {
  183. $values[] = (is_bool($var)) ? "$key = " . intval($var) : "$key = $var";
  184. }
  185. }
  186. $query = implode(($query == 'UPDATE') ? ', ' : ' AND ', $values);
  187. }
  188. return $query;
  189. }
  190. // Other query methods
  191. //
  192. // NOTE :: Want to remove _ALL_ reliance on sql_numrows from core code ...
  193. // don't want this here by a middle Milestone
  194. function sql_numrows($query_id = false)
  195. {
  196. return FALSE;
  197. }
  198. function sql_affectedrows()
  199. {
  200. // TODO: hmm, maybe doing something similar as in mssql-odbc.php?
  201. return ($this->query_result) ? true : false;
  202. }
  203. function sql_fetchrow($query_id = false)
  204. {
  205. global $cache;
  206. if (!$query_id)
  207. {
  208. $query_id = $this->query_result;
  209. }
  210. if (isset($cache->sql_rowset[$query_id]))
  211. {
  212. return $cache->sql_fetchrow($query_id);
  213. }
  214. $row = array();
  215. $cur_row = @ibase_fetch_object($query_id, IBASE_TEXT);
  216. if (!$cur_row)
  217. {
  218. return false;
  219. }
  220. foreach (get_object_vars($cur_row) as $key => $value)
  221. {
  222. $row[strtolower($key)] = trim(str_replace("\\0", "\0", str_replace("\\n", "\n", $value)));
  223. }
  224. return ($query_id) ? $row : false;
  225. }
  226. function sql_fetchrowset($query_id = false)
  227. {
  228. if (!$query_id)
  229. {
  230. $query_id = $this->query_result;
  231. }
  232. if ($query_id)
  233. {
  234. unset($this->rowset[$query_id]);
  235. unset($this->row[$query_id]);
  236. $result = array();
  237. while ($this->rowset[$query_id] = get_object_vars(@ibase_fetch_object($query_id, IBASE_TEXT)))
  238. {
  239. $result[] = $this->rowset[$query_id];
  240. }
  241. return $result;
  242. }
  243. else
  244. {
  245. return false;
  246. }
  247. }
  248. function sql_fetchfield($field, $rownum = -1, $query_id = 0)
  249. {
  250. if (!$query_id)
  251. {
  252. $query_id = $this->query_result;
  253. }
  254. if ($query_id)
  255. {
  256. if ($rownum > -1)
  257. {
  258. // erm... ok, my bad, we always use zero. :/
  259. for ($i = 0; $i <= $rownum; $i++)
  260. {
  261. $row = $this->sql_fetchrow($query_id);
  262. }
  263. return $row[$field];
  264. }
  265. else
  266. {
  267. if (empty($this->row[$query_id]) && empty($this->rowset[$query_id]))
  268. {
  269. if ($this->sql_fetchrow($query_id))
  270. {
  271. $result = $this->row[$query_id][$field];
  272. }
  273. }
  274. else
  275. {
  276. if ($this->rowset[$query_id])
  277. {
  278. $result = $this->rowset[$query_id][$field];
  279. }
  280. else if ($this->row[$query_id])
  281. {
  282. $result = $this->row[$query_id][$field];
  283. }
  284. }
  285. }
  286. return $result;
  287. }
  288. else
  289. {
  290. return false;
  291. }
  292. }
  293. function sql_rowseek($rownum, $query_id = 0)
  294. {
  295. if (!$query_id)
  296. {
  297. $query_id = $this->query_result;
  298. }
  299. for($i = 1; $i < $rownum; $i++)
  300. {
  301. if (!$this->sql_fetchrow($query_id))
  302. {
  303. return false;
  304. }
  305. }
  306. return true;
  307. }
  308. function sql_nextid()
  309. {
  310. if ($this->query_result && preg_match('#^INSERT[\t\n ]+INTO[\t\n ]+([a-z0-9\_\-]+)#is', $this->last_query_text, $tablename))
  311. {
  312. $query = "SELECT GEN_ID('" . $tablename[1] . "_gen', 0) AS new_id
  313. FROM RDB\$DATABASE";
  314. if (!($temp_q_id = @ibase_query($this->db_connect_id, $query)))
  315. {
  316. return false;
  317. }
  318. $temp_result = @ibase_fetch_object($temp_q_id);
  319. $this->sql_freeresult($temp_q_id);
  320. return ($temp_result) ? $temp_result->last_value : false;
  321. }
  322. }
  323. function sql_freeresult($query_id = false)
  324. {
  325. if (!$query_id)
  326. {
  327. $query_id = $this->query_result;
  328. }
  329. if (!$this->transaction && $query_id)
  330. {
  331. @ibase_commit();
  332. }
  333. return ($query_id) ? @ibase_free_result($query_id) : false;
  334. }
  335. function sql_escape($msg)
  336. {
  337. return (@ini_get('magic_quotes_sybase') || strtolower(@ini_get('magic_quotes_sybase')) == 'on') ? str_replace('\\\'', '\'', addslashes($msg)) : str_replace('\'', '\'\'', stripslashes($msg));
  338. }
  339. function sql_error($sql = '')
  340. {
  341. if (!$this->return_on_error)
  342. {
  343. $this_page =(!empty($_SERVER['PHP_SELF'])) ? $_SERVER['PHP_SELF'] : $_ENV['PHP_SELF'];
  344. $this_page .= '&' .((!empty($_SERVER['QUERY_STRING'])) ? $_SERVER['QUERY_STRING'] : $_ENV['QUERY_STRING']);
  345. $message = '<u>SQL ERROR</u> [ ' . SQL_LAYER . ' ]<br /><br />' . @ibase_errmsg() . '<br /><br /><u>CALLING PAGE</u><br /><br />' . $this_page .(($sql != '') ? '<br /><br /><u>SQL</u><br /><br />' . $sql : '') . '<br />';
  346. if ($this->transaction)
  347. {
  348. $this->sql_transaction('rollback');
  349. }
  350. trigger_error($message, E_USER_ERROR);
  351. }
  352. $result['message'] = @ibase_errmsg();
  353. $result['code'] = '';
  354. return $result;
  355. }
  356. function sql_report($mode, $query = '')
  357. {
  358. if (empty($_GET['explain']))
  359. {
  360. return;
  361. }
  362. global $cache, $starttime, $phpbb_root_path;
  363. static $curtime, $query_hold, $html_hold;
  364. static $sql_report = '';
  365. static $cache_num_queries = 0;
  366. if (!$query && !empty($query_hold))
  367. {
  368. $query = $query_hold;
  369. }
  370. switch ($mode)
  371. {
  372. case 'display':
  373. if (!empty($cache))
  374. {
  375. $cache->unload();
  376. }
  377. $this->sql_close();
  378. $mtime = explode(' ', microtime());
  379. $totaltime = $mtime[0] + $mtime[1] - $starttime;
  380. echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><meta http-equiv="Content-Type" content="text/html; charset=iso-8869-1"><meta http-equiv="Content-Style-Type" content="text/css"><link rel="stylesheet" href="' . $phpbb_root_path . 'adm/subSilver.css" type="text/css"><style type="text/css">' . "\n";
  381. echo 'th { background-image: url(\'' . $phpbb_root_path . 'adm/images/cellpic3.gif\') }' . "\n";
  382. echo 'td.cat { background-image: url(\'' . $phpbb_root_path . 'adm/images/cellpic1.gif\') }' . "\n";
  383. echo '</style><title>' . $msg_title . '</title></head><body>';
  384. echo '<table width="100%" cellspacing="0" cellpadding="0" border="0"><tr><td><a href="' . htmlspecialchars(preg_replace('/&explain=([^&]*)/', '', $_SERVER['REQUEST_URI'])) . '"><img src="' . $phpbb_root_path . 'adm/images/header_left.jpg" width="200" height="60" alt="phpBB Logo" title="phpBB Logo" border="0"/></a></td><td width="100%" background="' . $phpbb_root_path . 'adm/images/header_bg.jpg" height="60" align="right" nowrap="nowrap"><span class="maintitle">SQL Report</span> &nbsp; &nbsp; &nbsp;</td></tr></table><br clear="all"/><table width="95%" cellspacing="1" cellpadding="4" border="0" align="center"><tr><td height="40" align="center" valign="middle"><b>Page generated in ' . round($totaltime, 4) . " seconds with {$this->num_queries} queries" . (($cache_num_queries) ? " + $cache_num_queries " . (($cache_num_queries == 1) ? 'query' : 'queries') . ' returning data from cache' : '') . '</b></td></tr><tr><td align="center" nowrap="nowrap">Time spent on MySQL queries: <b>' . round($this->sql_time, 5) . 's</b> | Time spent on PHP: <b>' . round($totaltime - $this->sql_time, 5) . 's</b></td></tr></table><table width="95%" cellspacing="1" cellpadding="4" border="0" align="center"><tr><td>';
  385. echo $sql_report;
  386. echo '</td></tr></table><br /></body></html>';
  387. exit;
  388. break;
  389. case 'start':
  390. $query_hold = $query;
  391. $html_hold = '';
  392. $curtime = explode(' ', microtime());
  393. $curtime = $curtime[0] + $curtime[1];
  394. break;
  395. case 'fromcache':
  396. $endtime = explode(' ', microtime());
  397. $endtime = $endtime[0] + $endtime[1];
  398. $result = @ibase_query($this->db_connect_id, $query);
  399. while ($void = @ibase_fetch_object($result, IBASE_TEXT))
  400. {
  401. // Take the time spent on parsing rows into account
  402. }
  403. $splittime = explode(' ', microtime());
  404. $splittime = $splittime[0] + $splittime[1];
  405. $time_cache = $endtime - $curtime;
  406. $time_db = $splittime - $endtime;
  407. $color = ($time_db > $time_cache) ? 'green' : 'red';
  408. $sql_report .= '<hr width="100%"/><br /><table class="bg" width="100%" cellspacing="1" cellpadding="4" border="0"><tr><th>Query results obtained from the cache</th></tr><tr><td class="row1"><textarea style="font-family:\'Courier New\',monospace;width:100%" rows="5">' . preg_replace('/\t(AND|OR)(\W)/', "\$1\$2", htmlspecialchars(preg_replace('/[\s]*[\n\r\t]+[\n\r\s\t]*/', "\n", $query))) . '</textarea></td></tr></table><p align="center">';
  409. $sql_report .= 'Before: ' . sprintf('%.5f', $curtime - $starttime) . 's | After: ' . sprintf('%.5f', $endtime - $starttime) . 's | Elapsed [cache]: <b style="color: ' . $color . '">' . sprintf('%.5f', ($time_cache)) . 's</b> | Elapsed [db]: <b>' . sprintf('%.5f', $time_db) . 's</b></p>';
  410. // Pad the start time to not interfere with page timing
  411. $starttime += $time_db;
  412. @ibase_freeresult($result);
  413. $cache_num_queries++;
  414. break;
  415. case 'stop':
  416. $endtime = explode(' ', microtime());
  417. $endtime = $endtime[0] + $endtime[1];
  418. $sql_report .= '<hr width="100%"/><br /><table class="bg" width="100%" cellspacing="1" cellpadding="4" border="0"><tr><th>Query #' . $this->num_queries . '</th></tr><tr><td class="row1"><textarea style="font-family:\'Courier New\',monospace;width:100%" rows="5">' . preg_replace('/\t(AND|OR)(\W)/', "\$1\$2", htmlspecialchars(preg_replace('/[\s]*[\n\r\t]+[\n\r\s\t]*/', "\n", $query))) . '</textarea></td></tr></table> ' . $html_hold . '<p align="center">';
  419. if ($this->query_result)
  420. {
  421. if (preg_match('/^(UPDATE|DELETE|REPLACE)/', $query))
  422. {
  423. $sql_report .= "Affected rows: <b>" . $this->sql_affectedrows($this->query_result) . '</b> | ';
  424. }
  425. $sql_report .= 'Before: ' . sprintf('%.5f', $curtime - $starttime) . 's | After: ' . sprintf('%.5f', $endtime - $starttime) . 's | Elapsed: <b>' . sprintf('%.5f', $endtime - $curtime) . 's</b>';
  426. }
  427. else
  428. {
  429. $error = $this->sql_error();
  430. $sql_report .= '<b style="color: red">FAILED</b> - ' . SQL_LAYER . ' Error ' . $error['code'] . ': ' . htmlspecialchars($error['message']);
  431. }
  432. $sql_report .= '</p>';
  433. $this->sql_time += $endtime - $curtime;
  434. break;
  435. }
  436. }
  437. } // class sql_db
  438. } // if ... define
  439. ?>