/core/src/main/php/rdbms/sybase/SybaseConnection.class.php

https://github.com/oanas/xp-framework · PHP · 236 lines · 119 code · 25 blank · 92 comment · 21 complexity · 08d9593ad66cd5f6bceaf1c52c815a63 MD5 · raw file

  1. <?php
  2. /* This class is part of the XP framework
  3. *
  4. * $Id$
  5. */
  6. uses(
  7. 'rdbms.DBConnection',
  8. 'rdbms.sybase.SybaseResultSet',
  9. 'rdbms.Transaction',
  10. 'rdbms.StatementFormatter',
  11. 'rdbms.sybase.SybaseDialect'
  12. );
  13. /**
  14. * Connection to Sybase databases using client libraries
  15. *
  16. * @see http://sybase.com/
  17. * @ext sybase_ct
  18. * @test xp://net.xp_framework.unittest.rdbms.TokenizerTest
  19. * @test xp://net.xp_framework.unittest.rdbms.DBTest
  20. * @purpose Database connection
  21. */
  22. class SybaseConnection extends DBConnection {
  23. static function __static() {
  24. ini_set('sybct.deadlock_retry_count', 0);
  25. }
  26. /**
  27. * Constructor
  28. *
  29. * @param rdbms.DSN dsn
  30. */
  31. public function __construct($dsn) {
  32. parent::__construct($dsn);
  33. $this->formatter= new StatementFormatter($this, new SybaseDialect());
  34. }
  35. /**
  36. * Set Timeout
  37. *
  38. * @param int timeout
  39. */
  40. public function setTimeout($timeout) {
  41. ini_set('sybct.login_timeout', $timeout);
  42. parent::setTimeout($timeout);
  43. }
  44. /**
  45. * Connect
  46. *
  47. * @param bool reconnect default FALSE
  48. * @return bool success
  49. * @throws rdbms.SQLConnectException
  50. */
  51. public function connect($reconnect= FALSE) {
  52. if (is_resource($this->handle)) return TRUE; // Already connected
  53. if (!$reconnect && (FALSE === $this->handle)) return FALSE; // Previously failed connecting
  54. if ($this->flags & DB_PERSISTENT) {
  55. $this->handle= sybase_pconnect(
  56. $this->dsn->getHost(),
  57. $this->dsn->getUser(),
  58. $this->dsn->getPassword(),
  59. 'iso_1'
  60. );
  61. } else {
  62. $this->handle= sybase_connect(
  63. $this->dsn->getHost(),
  64. $this->dsn->getUser(),
  65. $this->dsn->getPassword(),
  66. 'iso_1'
  67. );
  68. }
  69. if (!is_resource($this->handle)) {
  70. $e= new SQLConnectException(trim(sybase_get_last_message()), $this->dsn);
  71. xp::gc(__FILE__);
  72. throw $e;
  73. }
  74. xp::gc(__FILE__);
  75. $this->_obs && $this->notifyObservers(new DBEvent(__FUNCTION__, $reconnect));
  76. return parent::connect();
  77. }
  78. /**
  79. * Disconnect
  80. *
  81. * @return bool success
  82. */
  83. public function close() {
  84. if ($this->handle && $r= sybase_close($this->handle)) {
  85. $this->handle= NULL;
  86. return $r;
  87. }
  88. return FALSE;
  89. }
  90. /**
  91. * Select database
  92. *
  93. * @param string db name of database to select
  94. * @return bool success
  95. * @throws rdbms.SQLStatementFailedException
  96. */
  97. public function selectdb($db) {
  98. if (!sybase_select_db($db, $this->handle)) {
  99. throw new SQLStatementFailedException(
  100. 'Cannot select database: '.trim(sybase_get_last_message()),
  101. 'use '.$db,
  102. current(sybase_fetch_row(sybase_query('select @@error', $this->handle)))
  103. );
  104. }
  105. return TRUE;
  106. }
  107. /**
  108. * Retrieve identity
  109. *
  110. * @return var identity value
  111. */
  112. public function identity($field= NULL) {
  113. $i= $this->query('select @@identity as i')->next('i');
  114. $this->_obs && $this->notifyObservers(new DBEvent(__FUNCTION__, $i));
  115. return $i;
  116. }
  117. /**
  118. * Retrieve number of affected rows for last query
  119. *
  120. * @return int
  121. */
  122. protected function affectedRows() {
  123. return sybase_affected_rows($this->handle);
  124. }
  125. /**
  126. * Execute any statement
  127. *
  128. * @param string sql
  129. * @param bool buffered default TRUE
  130. * @return rdbms.sybase.SybaseResultSet or TRUE if no resultset was created
  131. * @throws rdbms.SQLException
  132. */
  133. protected function query0($sql, $buffered= TRUE) {
  134. if (!is_resource($this->handle)) {
  135. if (!($this->flags & DB_AUTOCONNECT)) throw new SQLStateException('Not connected');
  136. $c= $this->connect();
  137. // Check for subsequent connection errors
  138. if (FALSE === $c) throw new SQLStateException('Previously failed to connect');
  139. }
  140. if (!$buffered) {
  141. $result= sybase_unbuffered_query($sql, $this->handle, FALSE);
  142. } else if ($this->flags & DB_UNBUFFERED) {
  143. $result= sybase_unbuffered_query($sql, $this->handle, $this->flags & DB_STORE_RESULT);
  144. } else {
  145. $result= sybase_query($sql, $this->handle);
  146. }
  147. if (FALSE === $result) {
  148. $message= 'Statement failed: '.trim(sybase_get_last_message()).' @ '.$this->dsn->getHost();
  149. if (!is_resource($error= sybase_query('select @@error', $this->handle))) {
  150. // The only case selecting @@error should fail is if we receive a
  151. // disconnect. We could also check on the warnings stack if we can
  152. // find the following:
  153. //
  154. // Sybase: Client message: Read from SQL server failed. (severity 78)
  155. //
  156. // but that seems a bit errorprone.
  157. throw new SQLConnectionClosedException($message, $sql);
  158. }
  159. $code= current(sybase_fetch_row($error));
  160. switch ($code) {
  161. case 1205: // Deadlock
  162. throw new SQLDeadlockException($message, $sql, $code);
  163. default: // Other error
  164. throw new SQLStatementFailedException($message, $sql, $code);
  165. }
  166. }
  167. return (TRUE === $result
  168. ? $result
  169. : new SybaseResultSet($result, $this->tz)
  170. );
  171. }
  172. /**
  173. * Begin a transaction
  174. *
  175. * @param rdbms.Transaction transaction
  176. * @return rdbms.Transaction
  177. */
  178. public function begin($transaction) {
  179. $this->query('begin transaction xp_%c', $transaction->name);
  180. $transaction->db= $this;
  181. return $transaction;
  182. }
  183. /**
  184. * Retrieve transaction state
  185. *
  186. * @param string name
  187. * @return var state
  188. */
  189. public function transtate($name) {
  190. return $this->query('select @@transtate as transtate')->next('transtate');
  191. }
  192. /**
  193. * Rollback a transaction
  194. *
  195. * @param string name
  196. * @return bool success
  197. */
  198. public function rollback($name) {
  199. return $this->query('rollback transaction xp_%c', $name);
  200. }
  201. /**
  202. * Commit a transaction
  203. *
  204. * @param string name
  205. * @return bool success
  206. */
  207. public function commit($name) {
  208. return $this->query('commit transaction xp_%c', $name);
  209. }
  210. }
  211. ?>