00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 if (!function_exists('sybase_connect'))
00021 trigger_error('sybase_* functions not defined. Install php*-sybase.', E_USER_ERROR);
00022 require_once(dirname(__FILE__) . '/KjwSql.php');
00023 require_once(dirname(__FILE__) . '/KjwArrayResultSet.php');
00024 require_once(dirname(__FILE__) . '/KjwMsResultSet.php');
00025
00034 class KjwMsSql extends KjwSql {
00035 var $_dbconn;
00036 var $_quotedDbname;
00037 var $_insertId;
00038 var $_affectedRows;
00039 var $_messages;
00050 function KjwMsSql($hostname, $portnum, $username, $password, $database) {
00051 parent::KjwSql('mssql', $hostname, $portnum ? $portnum : 1433, $username, $password, $database);
00052 $this->_dbconn = null;
00053 $this->_quotedDbname = $this->nameQuote($database);
00054 $this->_insertId = $this->_affectedRows = null;
00055 $this->_messages = array();
00056 sybase_min_client_severity(0);
00057 sybase_min_server_severity(0);
00058 }
00059
00060
00061 function destroy() {
00062 $this->disconnect();
00063 parent::destroy();
00064 }
00065
00066
00067 function connect() {
00068 if ($this->_dbconn)
00069 return true;
00070 $this->_dbconn = false;
00071
00072
00073
00074
00075 for ($i = 1; ; ++$i) {
00076 if (($res = @sybase_connect($this->_hostname . ':' . $this->_portnum, $this->_username, $this->_password, 'KjwApp')) != false)
00077 break;
00078 if ($i == 5 && $res == false) {
00079 global $kjw_suppressed_error;
00080 $this->setError("Connection to database (temporarily) failed after {$i}th try; host={$this->_hostname}:{$this->_portnum}, "
00081 . "user={$this->_username}, db={$this->_database}. "
00082 . $kjw_suppressed_error);
00083 if (KJW_DIE_ON_TRANSIENT_ERROR)
00084 $this->croak('Database Connection Failure', $this->getError(), 2);
00085 return false;
00086 }
00087 usleep(max(500000 << $i, 8000000));
00088 }
00089
00090 if (@sybase_set_message_handler(array(&$this, '_messageHandler'), $res) == false) {
00091 global $kjw_suppressed_error;
00092 $this->setError("sybase_set_message_handler failed: $kjw_suppressed_error ({$this->_hostname}:{$this->_portnum})");
00093 if (KJW_DIE_ON_TRANSIENT_ERROR)
00094 $this->croak('Database Connection Failure', $this->getError(), 2);
00095 return false;
00096 }
00097 if (@sybase_select_db($this->nameQuote($this->_database), $res) == false) {
00098 $this->setError($this->getLastMessage());
00099 if (KJW_DIE_ON_TRANSIENT_ERROR)
00100 $this->croak('Database Connection Failure', $this->getError(), 2);
00101 @sybase_close($res);
00102 return false;
00103 }
00104 $this->_dbconn = $res;
00105 return true;
00106 }
00107
00108
00109 function disconnect() {
00110 if (!$this->_dbconn)
00111 return true;
00112 if ($ret = @sybase_close($this->_dbconn))
00113 $this->_dbconn = null;
00114 return $ret;
00115 }
00116
00117
00118 function beginWork() {
00119
00120 return $this->execute('BEGIN TRANSACTION');
00121 }
00122
00123
00124 function execute($query) {
00125
00126 if (!$this->_execute_1($query))
00127 return false;
00128
00129 list($query, $is_insert_update, $is_select) = $this->_execute_2($query);
00130
00131 $sybase_result = $this->_execute_3($query);
00132
00133 return $this->_execute_4($sybase_result, $is_insert_update, $is_select);
00134 }
00135
00152 function executeLowLevel($query) {
00153
00154 $this->_insertId = $this->_affectedRows = null;
00155
00156 if (!$this->_execute_1($query))
00157 return false;
00158
00159 $sybase_result = $this->_execute_3($query);
00160 if (is_bool($sybase_result))
00161 return $sybase_result;
00162 sybase_free_result($sybase_result);
00163 return true;
00164 }
00165
00172 function _execute_1($query) {
00173 $this->_setLastQuery($query);
00174 if ($this->_dbconn === null)
00175 $this->connect();
00176 if ($this->_dbconn === false)
00177 return false;
00178 return true;
00179 }
00180
00188 function _execute_2($query) {
00189
00190 if (preg_match('!^\s*(insert|update)\s+!i', $query)) {
00191 $this->_insertId = $this->_affectedRows = null;
00192 $is_insert_update = true;
00193 $is_select = false;
00194
00195 $query = "BEGIN TRANSACTION ; $query ; SELECT @@ROWCOUNT AS rc, @@IDENTITY AS id ; COMMIT";
00196 } elseif (preg_match('!^\s*select\s+!i', $query)) {
00197 $this->_insertId = $this->_affectedRows = null;
00198 $is_insert_update = false;
00199 $is_select = true;
00200 } else {
00201 $is_insert_update = $is_select = false;
00202 }
00203
00204
00205
00206
00207 return array("USE {$this->_quotedDbname} ; $query", $is_insert_update, $is_select);
00208 }
00209
00216 function _execute_3($query) {
00217
00218 $this->_clearLastMessage();
00219 if (sybase_set_message_handler(array(&$this, '_messageHandler'), $this->_dbconn) == false
00220 || ($sybase_result = @sybase_query($query, $this->_dbconn)) === false) {
00221 $errmsg = $this->getLastMessage();
00222
00223
00224
00225
00226 $errmsg .= "\n Query was: " . $this->_getLastQuery();
00227 $this->croak('Database Data Transfer Failure', "sybase_query failed: $errmsg", 3);
00228 return false;
00229 }
00230 return $sybase_result;
00231 }
00232
00241 function _execute_4($sybase_result, $is_insert_update, $is_select) {
00242 if (is_bool($sybase_result)) {
00243
00244 if ($is_select)
00245 return new KjwArrayResultSet(array());
00246 return true;
00247 } elseif ($is_insert_update && sybase_num_rows($sybase_result) == 1) {
00248 $row = sybase_fetch_assoc($sybase_result);
00249 sybase_free_result($sybase_result);
00250 $this->_affectedRows = array_shift($row);
00251 if (is_integer($this->_affectedRows))
00252 $this->_affectedRows = (int)$this->_affectedRows;
00253 $this->_insertId = array_shift($row);
00254 if (is_integer($this->_insertId))
00255 $this->_insertId = (int)$this->_insertId;
00256 return true;
00257 }
00258 return new KjwMsResultSet($sybase_result);
00259 }
00260
00261
00262 function safeQuote($mixed) {
00263 if (is_string($mixed))
00264
00265
00266
00267
00268 return "N'" . str_replace("'", "''", str_replace("\x00", "", $mixed)) . "'";
00269 return parent::safeQuote($mixed);
00270 }
00271
00272
00273 function nameQuote($string) {
00274 return '[' . str_replace(']', ']]', preg_replace("/[\x01-\x1f]/", '',
00275 str_replace("\x00", '', $string))) . ']';
00276 }
00277
00278
00279 function affectedRows() {
00280
00281
00282
00283
00284 return $this->_affectedRows;
00285 }
00286
00287
00288 function insertId() {
00289
00290 return $this->_insertId;
00291 }
00292
00298 function getLastMessage() {
00299 return implode("\n ", $this->_messages);
00300 }
00301
00305 function _clearLastMessage() {
00306 $this->_messages = array();
00307 }
00308
00324 function _messageHandler($message, $severity, $state, $lineNumber, $description) {
00325 array_push($this->_messages, "$description [err=$message, line=$lineNumber, sev=$severity, stat=$state]");
00326 }
00327 }
00328
00329 ?>