odbc_driver.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  1. <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
  2. /**
  3. * CodeIgniter
  4. *
  5. * An open source application development framework for PHP 5.1.6 or newer
  6. *
  7. * @package CodeIgniter
  8. * @author EllisLab Dev Team
  9. * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
  10. * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
  11. * @license http://codeigniter.com/user_guide/license.html
  12. * @link http://codeigniter.com
  13. * @since Version 1.0
  14. * @filesource
  15. */
  16. // ------------------------------------------------------------------------
  17. /**
  18. * ODBC Database Adapter Class
  19. *
  20. * Note: _DB is an extender class that the app controller
  21. * creates dynamically based on whether the active record
  22. * class is being used or not.
  23. *
  24. * @package CodeIgniter
  25. * @subpackage Drivers
  26. * @category Database
  27. * @author EllisLab Dev Team
  28. * @link http://codeigniter.com/user_guide/database/
  29. */
  30. class CI_DB_odbc_driver extends CI_DB {
  31. var $dbdriver = 'odbc';
  32. // the character used to excape - not necessary for ODBC
  33. var $_escape_char = '';
  34. // clause and character used for LIKE escape sequences
  35. var $_like_escape_str = " {escape '%s'} ";
  36. var $_like_escape_chr = '!';
  37. /**
  38. * The syntax to count rows is slightly different across different
  39. * database engines, so this string appears in each driver and is
  40. * used for the count_all() and count_all_results() functions.
  41. */
  42. var $_count_string = "SELECT COUNT(*) AS ";
  43. var $_random_keyword;
  44. function __construct($params)
  45. {
  46. parent::__construct($params);
  47. $this->_random_keyword = ' RND('.time().')'; // database specific random keyword
  48. }
  49. /**
  50. * Non-persistent database connection
  51. *
  52. * @access private called by the base class
  53. * @return resource
  54. */
  55. function db_connect()
  56. {
  57. return @odbc_connect($this->hostname, $this->username, $this->password);
  58. }
  59. // --------------------------------------------------------------------
  60. /**
  61. * Persistent database connection
  62. *
  63. * @access private called by the base class
  64. * @return resource
  65. */
  66. function db_pconnect()
  67. {
  68. return @odbc_pconnect($this->hostname, $this->username, $this->password);
  69. }
  70. // --------------------------------------------------------------------
  71. /**
  72. * Reconnect
  73. *
  74. * Keep / reestablish the db connection if no queries have been
  75. * sent for a length of time exceeding the server's idle timeout
  76. *
  77. * @access public
  78. * @return void
  79. */
  80. function reconnect()
  81. {
  82. // not implemented in odbc
  83. }
  84. // --------------------------------------------------------------------
  85. /**
  86. * Select the database
  87. *
  88. * @access private called by the base class
  89. * @return resource
  90. */
  91. function db_select()
  92. {
  93. // Not needed for ODBC
  94. return TRUE;
  95. }
  96. // --------------------------------------------------------------------
  97. /**
  98. * Set client character set
  99. *
  100. * @access public
  101. * @param string
  102. * @param string
  103. * @return resource
  104. */
  105. function db_set_charset($charset, $collation)
  106. {
  107. // @todo - add support if needed
  108. return TRUE;
  109. }
  110. // --------------------------------------------------------------------
  111. /**
  112. * Version number query string
  113. *
  114. * @access public
  115. * @return string
  116. */
  117. function _version()
  118. {
  119. return "SELECT version() AS ver";
  120. }
  121. // --------------------------------------------------------------------
  122. /**
  123. * Execute the query
  124. *
  125. * @access private called by the base class
  126. * @param string an SQL query
  127. * @return resource
  128. */
  129. function _execute($sql)
  130. {
  131. $sql = $this->_prep_query($sql);
  132. return @odbc_exec($this->conn_id, $sql);
  133. }
  134. // --------------------------------------------------------------------
  135. /**
  136. * Prep the query
  137. *
  138. * If needed, each database adapter can prep the query string
  139. *
  140. * @access private called by execute()
  141. * @param string an SQL query
  142. * @return string
  143. */
  144. function _prep_query($sql)
  145. {
  146. return $sql;
  147. }
  148. // --------------------------------------------------------------------
  149. /**
  150. * Begin Transaction
  151. *
  152. * @access public
  153. * @return bool
  154. */
  155. function trans_begin($test_mode = FALSE)
  156. {
  157. if ( ! $this->trans_enabled)
  158. {
  159. return TRUE;
  160. }
  161. // When transactions are nested we only begin/commit/rollback the outermost ones
  162. if ($this->_trans_depth > 0)
  163. {
  164. return TRUE;
  165. }
  166. // Reset the transaction failure flag.
  167. // If the $test_mode flag is set to TRUE transactions will be rolled back
  168. // even if the queries produce a successful result.
  169. $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
  170. return odbc_autocommit($this->conn_id, FALSE);
  171. }
  172. // --------------------------------------------------------------------
  173. /**
  174. * Commit Transaction
  175. *
  176. * @access public
  177. * @return bool
  178. */
  179. function trans_commit()
  180. {
  181. if ( ! $this->trans_enabled)
  182. {
  183. return TRUE;
  184. }
  185. // When transactions are nested we only begin/commit/rollback the outermost ones
  186. if ($this->_trans_depth > 0)
  187. {
  188. return TRUE;
  189. }
  190. $ret = odbc_commit($this->conn_id);
  191. odbc_autocommit($this->conn_id, TRUE);
  192. return $ret;
  193. }
  194. // --------------------------------------------------------------------
  195. /**
  196. * Rollback Transaction
  197. *
  198. * @access public
  199. * @return bool
  200. */
  201. function trans_rollback()
  202. {
  203. if ( ! $this->trans_enabled)
  204. {
  205. return TRUE;
  206. }
  207. // When transactions are nested we only begin/commit/rollback the outermost ones
  208. if ($this->_trans_depth > 0)
  209. {
  210. return TRUE;
  211. }
  212. $ret = odbc_rollback($this->conn_id);
  213. odbc_autocommit($this->conn_id, TRUE);
  214. return $ret;
  215. }
  216. // --------------------------------------------------------------------
  217. /**
  218. * Escape String
  219. *
  220. * @access public
  221. * @param string
  222. * @param bool whether or not the string will be used in a LIKE condition
  223. * @return string
  224. */
  225. function escape_str($str, $like = FALSE)
  226. {
  227. if (is_array($str))
  228. {
  229. foreach ($str as $key => $val)
  230. {
  231. $str[$key] = $this->escape_str($val, $like);
  232. }
  233. return $str;
  234. }
  235. // ODBC doesn't require escaping
  236. $str = remove_invisible_characters($str);
  237. // escape LIKE condition wildcards
  238. if ($like === TRUE)
  239. {
  240. $str = str_replace( array('%', '_', $this->_like_escape_chr),
  241. array($this->_like_escape_chr.'%', $this->_like_escape_chr.'_', $this->_like_escape_chr.$this->_like_escape_chr),
  242. $str);
  243. }
  244. return $str;
  245. }
  246. // --------------------------------------------------------------------
  247. /**
  248. * Affected Rows
  249. *
  250. * @access public
  251. * @return integer
  252. */
  253. function affected_rows()
  254. {
  255. return @odbc_num_rows($this->conn_id);
  256. }
  257. // --------------------------------------------------------------------
  258. /**
  259. * Insert ID
  260. *
  261. * @access public
  262. * @return integer
  263. */
  264. function insert_id()
  265. {
  266. return @odbc_insert_id($this->conn_id);
  267. }
  268. // --------------------------------------------------------------------
  269. /**
  270. * "Count All" query
  271. *
  272. * Generates a platform-specific query string that counts all records in
  273. * the specified database
  274. *
  275. * @access public
  276. * @param string
  277. * @return string
  278. */
  279. function count_all($table = '')
  280. {
  281. if ($table == '')
  282. {
  283. return 0;
  284. }
  285. $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE));
  286. if ($query->num_rows() == 0)
  287. {
  288. return 0;
  289. }
  290. $row = $query->row();
  291. $this->_reset_select();
  292. return (int) $row->numrows;
  293. }
  294. // --------------------------------------------------------------------
  295. /**
  296. * Show table query
  297. *
  298. * Generates a platform-specific query string so that the table names can be fetched
  299. *
  300. * @access private
  301. * @param boolean
  302. * @return string
  303. */
  304. function _list_tables($prefix_limit = FALSE)
  305. {
  306. $sql = "SHOW TABLES FROM `".$this->database."`";
  307. if ($prefix_limit !== FALSE AND $this->dbprefix != '')
  308. {
  309. //$sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr);
  310. return FALSE; // not currently supported
  311. }
  312. return $sql;
  313. }
  314. // --------------------------------------------------------------------
  315. /**
  316. * Show column query
  317. *
  318. * Generates a platform-specific query string so that the column names can be fetched
  319. *
  320. * @access public
  321. * @param string the table name
  322. * @return string
  323. */
  324. function _list_columns($table = '')
  325. {
  326. return "SHOW COLUMNS FROM ".$table;
  327. }
  328. // --------------------------------------------------------------------
  329. /**
  330. * Field data query
  331. *
  332. * Generates a platform-specific query so that the column data can be retrieved
  333. *
  334. * @access public
  335. * @param string the table name
  336. * @return object
  337. */
  338. function _field_data($table)
  339. {
  340. return "SELECT TOP 1 FROM ".$table;
  341. }
  342. // --------------------------------------------------------------------
  343. /**
  344. * The error message string
  345. *
  346. * @access private
  347. * @return string
  348. */
  349. function _error_message()
  350. {
  351. return odbc_errormsg($this->conn_id);
  352. }
  353. // --------------------------------------------------------------------
  354. /**
  355. * The error message number
  356. *
  357. * @access private
  358. * @return integer
  359. */
  360. function _error_number()
  361. {
  362. return odbc_error($this->conn_id);
  363. }
  364. // --------------------------------------------------------------------
  365. /**
  366. * Escape the SQL Identifiers
  367. *
  368. * This function escapes column and table names
  369. *
  370. * @access private
  371. * @param string
  372. * @return string
  373. */
  374. function _escape_identifiers($item)
  375. {
  376. if ($this->_escape_char == '')
  377. {
  378. return $item;
  379. }
  380. foreach ($this->_reserved_identifiers as $id)
  381. {
  382. if (strpos($item, '.'.$id) !== FALSE)
  383. {
  384. $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item);
  385. // remove duplicates if the user already included the escape
  386. return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
  387. }
  388. }
  389. if (strpos($item, '.') !== FALSE)
  390. {
  391. $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;
  392. }
  393. else
  394. {
  395. $str = $this->_escape_char.$item.$this->_escape_char;
  396. }
  397. // remove duplicates if the user already included the escape
  398. return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
  399. }
  400. // --------------------------------------------------------------------
  401. /**
  402. * From Tables
  403. *
  404. * This function implicitly groups FROM tables so there is no confusion
  405. * about operator precedence in harmony with SQL standards
  406. *
  407. * @access public
  408. * @param type
  409. * @return type
  410. */
  411. function _from_tables($tables)
  412. {
  413. if ( ! is_array($tables))
  414. {
  415. $tables = array($tables);
  416. }
  417. return '('.implode(', ', $tables).')';
  418. }
  419. // --------------------------------------------------------------------
  420. /**
  421. * Insert statement
  422. *
  423. * Generates a platform-specific insert string from the supplied data
  424. *
  425. * @access public
  426. * @param string the table name
  427. * @param array the insert keys
  428. * @param array the insert values
  429. * @return string
  430. */
  431. function _insert($table, $keys, $values)
  432. {
  433. return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
  434. }
  435. // --------------------------------------------------------------------
  436. /**
  437. * Update statement
  438. *
  439. * Generates a platform-specific update string from the supplied data
  440. *
  441. * @access public
  442. * @param string the table name
  443. * @param array the update data
  444. * @param array the where clause
  445. * @param array the orderby clause
  446. * @param array the limit clause
  447. * @return string
  448. */
  449. function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
  450. {
  451. foreach ($values as $key => $val)
  452. {
  453. $valstr[] = $key." = ".$val;
  454. }
  455. $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
  456. $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
  457. $sql = "UPDATE ".$table." SET ".implode(', ', $valstr);
  458. $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
  459. $sql .= $orderby.$limit;
  460. return $sql;
  461. }
  462. // --------------------------------------------------------------------
  463. /**
  464. * Truncate statement
  465. *
  466. * Generates a platform-specific truncate string from the supplied data
  467. * If the database does not support the truncate() command
  468. * This function maps to "DELETE FROM table"
  469. *
  470. * @access public
  471. * @param string the table name
  472. * @return string
  473. */
  474. function _truncate($table)
  475. {
  476. return $this->_delete($table);
  477. }
  478. // --------------------------------------------------------------------
  479. /**
  480. * Delete statement
  481. *
  482. * Generates a platform-specific delete string from the supplied data
  483. *
  484. * @access public
  485. * @param string the table name
  486. * @param array the where clause
  487. * @param string the limit clause
  488. * @return string
  489. */
  490. function _delete($table, $where = array(), $like = array(), $limit = FALSE)
  491. {
  492. $conditions = '';
  493. if (count($where) > 0 OR count($like) > 0)
  494. {
  495. $conditions = "\nWHERE ";
  496. $conditions .= implode("\n", $this->ar_where);
  497. if (count($where) > 0 && count($like) > 0)
  498. {
  499. $conditions .= " AND ";
  500. }
  501. $conditions .= implode("\n", $like);
  502. }
  503. $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
  504. return "DELETE FROM ".$table.$conditions.$limit;
  505. }
  506. // --------------------------------------------------------------------
  507. /**
  508. * Limit string
  509. *
  510. * Generates a platform-specific LIMIT clause
  511. *
  512. * @access public
  513. * @param string the sql query string
  514. * @param integer the number of rows to limit the query to
  515. * @param integer the offset value
  516. * @return string
  517. */
  518. function _limit($sql, $limit, $offset)
  519. {
  520. // Does ODBC doesn't use the LIMIT clause?
  521. return $sql;
  522. }
  523. // --------------------------------------------------------------------
  524. /**
  525. * Close DB Connection
  526. *
  527. * @access public
  528. * @param resource
  529. * @return void
  530. */
  531. function _close($conn_id)
  532. {
  533. @odbc_close($conn_id);
  534. }
  535. }
  536. /* End of file odbc_driver.php */
  537. /* Location: ./system/database/drivers/odbc/odbc_driver.php */