Firebird.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category ZendX
  16. * @package ZendX_Db
  17. * @subpackage Statement
  18. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id: $
  21. */
  22. /**
  23. * @see Zend_Db_Statement
  24. */
  25. require_once 'Zend/Db/Statement.php';
  26. /**
  27. * Extends for Firebird
  28. *
  29. * @category ZendX
  30. * @package ZendX_Db
  31. * @subpackage Statement
  32. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  33. * @license http://framework.zend.com/license/new-bsd New BSD License
  34. */
  35. class ZendX_Db_Statement_Firebird extends Zend_Db_Statement
  36. {
  37. /**
  38. * The firebird_stmtPrepared resource.
  39. *
  40. * @var firebird_stmtPrepared
  41. */
  42. protected $_stmtPrepared = null;
  43. /**
  44. * The firebird_stmtResult resource.
  45. *
  46. * @var firebird_result
  47. */
  48. protected $_stmtResult = null;
  49. /**
  50. * The firebird_stmtResult resource.
  51. *
  52. * @var firebird_result
  53. */
  54. protected $_stmtRowCount = 0;
  55. /**
  56. * The firebird_stmtResult resource.
  57. *
  58. * @var firebird_result
  59. */
  60. protected $_stmtColumnCount = 0;
  61. /**
  62. * Column names.
  63. *
  64. * @var array
  65. */
  66. protected $_keys = array();
  67. /**
  68. * Fetched result values.
  69. *
  70. * @var array
  71. */
  72. protected $_values = array();
  73. /**
  74. * @var array
  75. */
  76. protected $_meta = null;
  77. /**
  78. * @param string $sql
  79. * @return void
  80. * @throws ZendX_Db_Statement_Firebird_Exception
  81. */
  82. public function _prepare($sql)
  83. {
  84. $this->_stmtRowCount = 0;
  85. $this->_stmtColumnCount = 0;
  86. $connection = $this->_adapter->getConnection();
  87. if ($trans = $this->_adapter->getTransaction())
  88. $this->_stmtPrepared = @ibase_prepare($connection, $trans, $sql);
  89. else
  90. $this->_stmtPrepared = @ibase_prepare($connection, $sql);
  91. if ($this->_stmtPrepared === false) {
  92. /**
  93. * @see ZendX_Db_Statement_Firebird_Exception
  94. */
  95. require_once 'ZendX/Db/Statement/Firebird/Exception.php';
  96. throw new ZendX_Db_Statement_Firebird_Exception("Firebird prepare error: " . ibase_errmsg());
  97. }
  98. }
  99. /**
  100. * Binds a parameter to the specified variable name.
  101. *
  102. * @param mixed $parameter Name the parameter, either integer or string.
  103. * @param mixed $variable Reference to PHP variable containing the value.
  104. * @param mixed $type OPTIONAL Datatype of SQL parameter.
  105. * @param mixed $length OPTIONAL Length of SQL parameter.
  106. * @param mixed $options OPTIONAL Other options.
  107. * @return bool
  108. * @throws ZendX_Db_Statement_Firebird_Exception
  109. */
  110. protected function _bindParam($parameter, &$variable, $type = null, $length = null, $options = null)
  111. {
  112. return true;
  113. }
  114. /**
  115. * Closes the cursor and the statement.
  116. *
  117. * @return bool
  118. */
  119. public function close()
  120. {
  121. if ($stmt = $this->_stmtResult) {
  122. @ibase_free_result($this->_stmtResult);
  123. $this->_stmtResult = null;
  124. }
  125. if ($this->_stmtPrepared) {
  126. $r = @ibase_free_query($this->_stmtPrepared);
  127. $this->_stmtPrepared = null;
  128. return $r;
  129. }
  130. return false;
  131. }
  132. /**
  133. * Closes the cursor, allowing the statement to be executed again.
  134. *
  135. * @return bool
  136. */
  137. public function closeCursor()
  138. {
  139. if ($stmt = $this->_stmtResult) {
  140. return @ibase_free_result($this->_stmtResult);
  141. }
  142. return false;
  143. }
  144. /**
  145. * Returns the number of columns in the result set.
  146. * Returns null if the statement has no result set metadata.
  147. *
  148. * @return int The number of columns.
  149. */
  150. public function columnCount()
  151. {
  152. return $this->_stmtColumnCount ? $this->_stmtColumnCount : 0;
  153. }
  154. /**
  155. * Retrieves the error code, if any, associated with the last operation on
  156. * the statement handle.
  157. *
  158. * @return string error code.
  159. */
  160. public function errorCode()
  161. {
  162. if ($this->_stmtPrepared || $this->_stmtResult) {
  163. return ibase_errcode();
  164. }
  165. return false;
  166. }
  167. /**
  168. * Retrieves an array of error information, if any, associated with the
  169. * last operation on the statement handle.
  170. *
  171. * @return array
  172. */
  173. public function errorInfo()
  174. {
  175. if (!$this->_stmtPrepared) {
  176. return false;
  177. }
  178. return array(
  179. ibase_errcode(),
  180. ibase_errmsg()
  181. );
  182. }
  183. /**
  184. * Executes a prepared statement.
  185. *
  186. * @param array $params OPTIONAL Values to bind to parameter placeholders.
  187. * @return bool
  188. * @throws ZendX_Db_Statement_Firebird_Exception
  189. */
  190. public function _execute(array $params = null)
  191. {
  192. if (!$this->_stmtPrepared) {
  193. return false;
  194. }
  195. // if no params were given as an argument to execute(),
  196. // then default to the _bindParam array
  197. if ($params === null) {
  198. $params = $this->_bindParam;
  199. }
  200. // send $params as input parameters to the statement
  201. if ($params) {
  202. array_unshift($params, $this->_stmtPrepared);
  203. $retval = @call_user_func_array(
  204. 'ibase_execute',
  205. $params
  206. );
  207. } else
  208. // execute the statement
  209. $retval = @ibase_execute($this->_stmtPrepared);
  210. $this->_stmtResult = $retval;
  211. if ($retval === false) {
  212. $last_error = ibase_errmsg();
  213. $this->_stmtRowCount = 0;
  214. }
  215. //Firebird php ibase extension, auto-commit is not after each call, but at
  216. //end of script. Disabled when transaction is active
  217. if (!$this->_adapter->getTransaction())
  218. ibase_commit_ret();
  219. if ($retval === false) {
  220. /**
  221. * @see ZendX_Db_Statement_Firebird_Exception
  222. */
  223. require_once 'ZendX/Db/Statement/Firebird/Exception.php';
  224. throw new ZendX_Db_Statement_Firebird_Exception("Firebird statement execute error : " . $last_error);
  225. }
  226. // statements that have no result set do not return metadata
  227. if (is_resource($this->_stmtResult)) {
  228. // get the column names that will result
  229. $this->_keys = array();
  230. $coln = ibase_num_fields($this->_stmtResult);
  231. $this->_stmtColumnCount = $coln;
  232. for ($i = 0; $i < $coln; $i++) {
  233. $col_info = ibase_field_info($this->_stmtResult, $i);
  234. $this->_keys[] = $this->_adapter->foldCase($col_info['name']);
  235. }
  236. // set up a binding space for result variables
  237. $this->_values = array_fill(0, count($this->_keys), null);
  238. // set up references to the result binding space.
  239. // just passing $this->_values in the call_user_func_array()
  240. // below won't work, you need references.
  241. $refs = array();
  242. foreach ($this->_values as $i => &$f) {
  243. $refs[$i] = &$f;
  244. }
  245. }
  246. if ($trans = $this->_adapter->getTransaction())
  247. $this->_stmtRowCount = ibase_affected_rows($trans);
  248. else
  249. $this->_stmtRowCount = ibase_affected_rows($this->_adapter->getConnection());
  250. return true;
  251. }
  252. /**
  253. * Fetches a row from the result set.
  254. *
  255. * @param int $style OPTIONAL Fetch mode for this fetch operation.
  256. * @param int $cursor OPTIONAL Absolute, relative, or other.
  257. * @param int $offset OPTIONAL Number for absolute or relative cursors.
  258. * @return mixed Array, object, or scalar depending on fetch mode.
  259. * @throws Zend_Db_Statement_Exception
  260. */
  261. public function fetch($style = null, $cursor = null, $offset = null)
  262. {
  263. if (!$this->_stmtResult) {
  264. return false;
  265. }
  266. if ($style === null) {
  267. $style = $this->_fetchMode;
  268. }
  269. switch ($style) {
  270. case Zend_Db::FETCH_NUM:
  271. $row = ibase_fetch_row($this->_stmtResult, IBASE_TEXT);
  272. break;
  273. case Zend_Db::FETCH_ASSOC:
  274. $row = ibase_fetch_assoc($this->_stmtResult, IBASE_TEXT);
  275. break;
  276. case Zend_Db::FETCH_BOTH:
  277. $row = ibase_fetch_assoc($this->_stmtResult, IBASE_TEXT);
  278. if ($row !== false)
  279. $row = array_merge($row, array_values($row));
  280. break;
  281. case Zend_Db::FETCH_OBJ:
  282. $row = ibase_fetch_object($this->_stmtResult, IBASE_TEXT);
  283. break;
  284. case Zend_Db::FETCH_BOUND:
  285. $row = ibase_fetch_assoc($this->_stmtResult, IBASE_TEXT);
  286. if ($row !== false){
  287. $row = array_merge($row, array_values($row));
  288. $row = $this->_fetchBound($row);
  289. }
  290. break;
  291. default:
  292. /**
  293. * @see ZendX_Db_Adapter_Firebird_Exception
  294. */
  295. require_once 'ZendX/Db/Statement/Firebird/Exception.php';
  296. throw new ZendX_Db_Statement_Firebird_Exception(
  297. "Invalid fetch mode '$style' specified"
  298. );
  299. break;
  300. }
  301. return $row;
  302. }
  303. /**
  304. * Retrieves the next rowset (result set) for a SQL statement that has
  305. * multiple result sets. An example is a stored procedure that returns
  306. * the results of multiple queries.
  307. *
  308. * @return bool
  309. * @throws ZendX_Db_Statement_Firebird_Exception
  310. */
  311. public function nextRowset()
  312. {
  313. /**
  314. * @see ZendX_Db_Statement_Firebird_Exception
  315. */
  316. require_once 'ZendX/Db/Statement/Firebird/Exception.php';
  317. throw new ZendX_Db_Statement_Firebird_Exception(__FUNCTION__.'() is not implemented');
  318. }
  319. /**
  320. * Returns the number of rows affected by the execution of the
  321. * last INSERT, DELETE, or UPDATE statement executed by this
  322. * statement object.
  323. *
  324. * @return int The number of rows affected.
  325. * @throws Zend_Db_Statement_Exception
  326. */
  327. public function rowCount()
  328. {
  329. return $this->_stmtRowCount ? $this->_stmtRowCount : 0;
  330. }
  331. }