You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

413 lines
10 KiB

7 years ago
  1. <?php
  2. /**
  3. * CodeIgniter
  4. *
  5. * An open source application development framework for PHP
  6. *
  7. * This content is released under the MIT License (MIT)
  8. *
  9. * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
  10. *
  11. * Permission is hereby granted, free of charge, to any person obtaining a copy
  12. * of this software and associated documentation files (the "Software"), to deal
  13. * in the Software without restriction, including without limitation the rights
  14. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  15. * copies of the Software, and to permit persons to whom the Software is
  16. * furnished to do so, subject to the following conditions:
  17. *
  18. * The above copyright notice and this permission notice shall be included in
  19. * all copies or substantial portions of the Software.
  20. *
  21. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  22. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  23. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  24. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  25. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  26. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  27. * THE SOFTWARE.
  28. *
  29. * @package CodeIgniter
  30. * @author EllisLab Dev Team
  31. * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
  32. * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
  33. * @license http://opensource.org/licenses/MIT MIT License
  34. * @link https://codeigniter.com
  35. * @since Version 3.0.0
  36. * @filesource
  37. */
  38. defined('BASEPATH') OR exit('No direct script access allowed');
  39. /**
  40. * Firebird/Interbase Database Adapter Class
  41. *
  42. * Note: _DB is an extender class that the app controller
  43. * creates dynamically based on whether the query builder
  44. * class is being used or not.
  45. *
  46. * @package CodeIgniter
  47. * @subpackage Drivers
  48. * @category Database
  49. * @author EllisLab Dev Team
  50. * @link https://codeigniter.com/user_guide/database/
  51. */
  52. class CI_DB_ibase_driver extends CI_DB {
  53. /**
  54. * Database driver
  55. *
  56. * @var string
  57. */
  58. public $dbdriver = 'ibase';
  59. // --------------------------------------------------------------------
  60. /**
  61. * ORDER BY random keyword
  62. *
  63. * @var array
  64. */
  65. protected $_random_keyword = array('RAND()', 'RAND()');
  66. /**
  67. * IBase Transaction status flag
  68. *
  69. * @var resource
  70. */
  71. protected $_ibase_trans;
  72. // --------------------------------------------------------------------
  73. /**
  74. * Non-persistent database connection
  75. *
  76. * @param bool $persistent
  77. * @return resource
  78. */
  79. public function db_connect($persistent = FALSE)
  80. {
  81. return ($persistent === TRUE)
  82. ? ibase_pconnect($this->hostname.':'.$this->database, $this->username, $this->password, $this->char_set)
  83. : ibase_connect($this->hostname.':'.$this->database, $this->username, $this->password, $this->char_set);
  84. }
  85. // --------------------------------------------------------------------
  86. /**
  87. * Database version number
  88. *
  89. * @return string
  90. */
  91. public function version()
  92. {
  93. if (isset($this->data_cache['version']))
  94. {
  95. return $this->data_cache['version'];
  96. }
  97. if (($service = ibase_service_attach($this->hostname, $this->username, $this->password)))
  98. {
  99. $this->data_cache['version'] = ibase_server_info($service, IBASE_SVC_SERVER_VERSION);
  100. // Don't keep the service open
  101. ibase_service_detach($service);
  102. return $this->data_cache['version'];
  103. }
  104. return FALSE;
  105. }
  106. // --------------------------------------------------------------------
  107. /**
  108. * Execute the query
  109. *
  110. * @param string $sql an SQL query
  111. * @return resource
  112. */
  113. protected function _execute($sql)
  114. {
  115. return ibase_query(isset($this->_ibase_trans) ? $this->_ibase_trans : $this->conn_id, $sql);
  116. }
  117. // --------------------------------------------------------------------
  118. /**
  119. * Begin Transaction
  120. *
  121. * @return bool
  122. */
  123. protected function _trans_begin()
  124. {
  125. if (($trans_handle = ibase_trans($this->conn_id)) === FALSE)
  126. {
  127. return FALSE;
  128. }
  129. $this->_ibase_trans = $trans_handle;
  130. return TRUE;
  131. }
  132. // --------------------------------------------------------------------
  133. /**
  134. * Commit Transaction
  135. *
  136. * @return bool
  137. */
  138. protected function _trans_commit()
  139. {
  140. if (ibase_commit($this->_ibase_trans))
  141. {
  142. $this->_ibase_trans = NULL;
  143. return TRUE;
  144. }
  145. return FALSE;
  146. }
  147. // --------------------------------------------------------------------
  148. /**
  149. * Rollback Transaction
  150. *
  151. * @return bool
  152. */
  153. protected function _trans_rollback()
  154. {
  155. if (ibase_rollback($this->_ibase_trans))
  156. {
  157. $this->_ibase_trans = NULL;
  158. return TRUE;
  159. }
  160. return FALSE;
  161. }
  162. // --------------------------------------------------------------------
  163. /**
  164. * Affected Rows
  165. *
  166. * @return int
  167. */
  168. public function affected_rows()
  169. {
  170. return ibase_affected_rows($this->conn_id);
  171. }
  172. // --------------------------------------------------------------------
  173. /**
  174. * Insert ID
  175. *
  176. * @param string $generator_name
  177. * @param int $inc_by
  178. * @return int
  179. */
  180. public function insert_id($generator_name, $inc_by = 0)
  181. {
  182. //If a generator hasn't been used before it will return 0
  183. return ibase_gen_id('"'.$generator_name.'"', $inc_by);
  184. }
  185. // --------------------------------------------------------------------
  186. /**
  187. * List table query
  188. *
  189. * Generates a platform-specific query string so that the table names can be fetched
  190. *
  191. * @param bool $prefix_limit
  192. * @return string
  193. */
  194. protected function _list_tables($prefix_limit = FALSE)
  195. {
  196. $sql = 'SELECT TRIM("RDB$RELATION_NAME") AS TABLE_NAME FROM "RDB$RELATIONS" WHERE "RDB$RELATION_NAME" NOT LIKE \'RDB$%\' AND "RDB$RELATION_NAME" NOT LIKE \'MON$%\'';
  197. if ($prefix_limit !== FALSE && $this->dbprefix !== '')
  198. {
  199. return $sql.' AND TRIM("RDB$RELATION_NAME") AS TABLE_NAME LIKE \''.$this->escape_like_str($this->dbprefix)."%' "
  200. .sprintf($this->_like_escape_str, $this->_like_escape_chr);
  201. }
  202. return $sql;
  203. }
  204. // --------------------------------------------------------------------
  205. /**
  206. * Show column query
  207. *
  208. * Generates a platform-specific query string so that the column names can be fetched
  209. *
  210. * @param string $table
  211. * @return string
  212. */
  213. protected function _list_columns($table = '')
  214. {
  215. return 'SELECT TRIM("RDB$FIELD_NAME") AS COLUMN_NAME FROM "RDB$RELATION_FIELDS" WHERE "RDB$RELATION_NAME" = '.$this->escape($table);
  216. }
  217. // --------------------------------------------------------------------
  218. /**
  219. * Returns an object with field data
  220. *
  221. * @param string $table
  222. * @return array
  223. */
  224. public function field_data($table)
  225. {
  226. $sql = 'SELECT "rfields"."RDB$FIELD_NAME" AS "name",
  227. CASE "fields"."RDB$FIELD_TYPE"
  228. WHEN 7 THEN \'SMALLINT\'
  229. WHEN 8 THEN \'INTEGER\'
  230. WHEN 9 THEN \'QUAD\'
  231. WHEN 10 THEN \'FLOAT\'
  232. WHEN 11 THEN \'DFLOAT\'
  233. WHEN 12 THEN \'DATE\'
  234. WHEN 13 THEN \'TIME\'
  235. WHEN 14 THEN \'CHAR\'
  236. WHEN 16 THEN \'INT64\'
  237. WHEN 27 THEN \'DOUBLE\'
  238. WHEN 35 THEN \'TIMESTAMP\'
  239. WHEN 37 THEN \'VARCHAR\'
  240. WHEN 40 THEN \'CSTRING\'
  241. WHEN 261 THEN \'BLOB\'
  242. ELSE NULL
  243. END AS "type",
  244. "fields"."RDB$FIELD_LENGTH" AS "max_length",
  245. "rfields"."RDB$DEFAULT_VALUE" AS "default"
  246. FROM "RDB$RELATION_FIELDS" "rfields"
  247. JOIN "RDB$FIELDS" "fields" ON "rfields"."RDB$FIELD_SOURCE" = "fields"."RDB$FIELD_NAME"
  248. WHERE "rfields"."RDB$RELATION_NAME" = '.$this->escape($table).'
  249. ORDER BY "rfields"."RDB$FIELD_POSITION"';
  250. return (($query = $this->query($sql)) !== FALSE)
  251. ? $query->result_object()
  252. : FALSE;
  253. }
  254. // --------------------------------------------------------------------
  255. /**
  256. * Error
  257. *
  258. * Returns an array containing code and message of the last
  259. * database error that has occurred.
  260. *
  261. * @return array
  262. */
  263. public function error()
  264. {
  265. return array('code' => ibase_errcode(), 'message' => ibase_errmsg());
  266. }
  267. // --------------------------------------------------------------------
  268. /**
  269. * Update statement
  270. *
  271. * Generates a platform-specific update string from the supplied data
  272. *
  273. * @param string $table
  274. * @param array $values
  275. * @return string
  276. */
  277. protected function _update($table, $values)
  278. {
  279. $this->qb_limit = FALSE;
  280. return parent::_update($table, $values);
  281. }
  282. // --------------------------------------------------------------------
  283. /**
  284. * Truncate statement
  285. *
  286. * Generates a platform-specific truncate string from the supplied data
  287. *
  288. * If the database does not support the TRUNCATE statement,
  289. * then this method maps to 'DELETE FROM table'
  290. *
  291. * @param string $table
  292. * @return string
  293. */
  294. protected function _truncate($table)
  295. {
  296. return 'DELETE FROM '.$table;
  297. }
  298. // --------------------------------------------------------------------
  299. /**
  300. * Delete statement
  301. *
  302. * Generates a platform-specific delete string from the supplied data
  303. *
  304. * @param string $table
  305. * @return string
  306. */
  307. protected function _delete($table)
  308. {
  309. $this->qb_limit = FALSE;
  310. return parent::_delete($table);
  311. }
  312. // --------------------------------------------------------------------
  313. /**
  314. * LIMIT
  315. *
  316. * Generates a platform-specific LIMIT clause
  317. *
  318. * @param string $sql SQL Query
  319. * @return string
  320. */
  321. protected function _limit($sql)
  322. {
  323. // Limit clause depends on if Interbase or Firebird
  324. if (stripos($this->version(), 'firebird') !== FALSE)
  325. {
  326. $select = 'FIRST '.$this->qb_limit
  327. .($this->qb_offset ? ' SKIP '.$this->qb_offset : '');
  328. }
  329. else
  330. {
  331. $select = 'ROWS '
  332. .($this->qb_offset ? $this->qb_offset.' TO '.($this->qb_limit + $this->qb_offset) : $this->qb_limit);
  333. }
  334. return preg_replace('`SELECT`i', 'SELECT '.$select, $sql, 1);
  335. }
  336. // --------------------------------------------------------------------
  337. /**
  338. * Insert batch statement
  339. *
  340. * Generates a platform-specific insert string from the supplied data.
  341. *
  342. * @param string $table Table name
  343. * @param array $keys INSERT keys
  344. * @param array $values INSERT values
  345. * @return string|bool
  346. */
  347. protected function _insert_batch($table, $keys, $values)
  348. {
  349. return ($this->db_debug) ? $this->display_error('db_unsupported_feature') : FALSE;
  350. }
  351. // --------------------------------------------------------------------
  352. /**
  353. * Close DB Connection
  354. *
  355. * @return void
  356. */
  357. protected function _close()
  358. {
  359. ibase_close($this->conn_id);
  360. }
  361. }