_dbconn = null; $this->_insertId = $this->_affectedRows = null; } /* [INHERITED DOCS] */ function destroy() { $this->disconnect(); parent::destroy(); } /* [INHERITED DOCS] */ function connect() { if ($this->_dbconn) return true; $this->_dbconn = false; // If we fail, we'll be false instead of null. if (($res = @sybase_connect($this->_hostname . ':' . $this->_portnum, $this->_username, $this->_password, 'KjwApp')) == false) { global $kjw_suppressed_error; $this->setError("Connection to database (temporarily) failed; host={$this->_hostname}:{$this->_portnum}, " . "user={$this->_username}, db={$this->_database}. " . $kjw_suppressed_error); if (KJW_DIE_ON_TRANSIENT_ERROR) $this->croak('Database Connection Failure', $this->getError()); return false; } if (@sybase_select_db($this->nameQuote($this->_database), $res) == false) { $this->setError(sybase_get_last_message()); if (KJW_DIE_ON_TRANSIENT_ERROR) $this->croak('Database Connection Failure', $this->getError()); @sybase_close($res); return false; } $this->_dbconn = $res; return true; } /* [INHERITED DOCS] */ function disconnect() { if (!$this->_dbconn) return true; if ($ret = @sybase_close($this->_dbconn)) $this->_dbconn = null; return $ret; } /* [INHERITED DOCS] */ function beginWork() { // BEGIN WORK does not work on MsSql. return $this->execute('BEGIN TRANSACTION'); } /* [INHERITED DOCS] */ function execute($query) { if ($this->_dbconn === null) $this->connect(); // Auto-connect once. $this->_setLastQuery($query); $is_select = $is_insert_update = false; // As seen in bugs: http://bugs.php.net/bug.php?id=36639 and http://bugs.php.net/bug.php?id=42544 // All MSSQL links started with the same arguments, share the same link. // Therefore we have to reselect the database. if (@sybase_select_db($this->nameQuote($this->_database), $this->_dbconn) === false) $this->croak('Database Data Transfer Failure', 'Second sybase_select_db failed. Error in bugfix. Dying.'); // If query is an insert/update, we add code to select @@IDENTITY/@@ROWCOUNT. if (preg_match('!^\s*(insert|update)\s+!i', $query)) { $this->_insertId = $this->_affectedRows = null; $is_insert_update = true; // Some databases require a BEGIN TRANSACTION around the @@ROWCOUNT as well... haven't found out why. $query = "BEGIN TRANSACTION ; $query ; SELECT @@ROWCOUNT AS rc, @@IDENTITY AS id ; COMMIT"; } elseif (preg_match('!^\s*select\s+!i', $query)) { $this->_insertId = $this->_affectedRows = null; $is_select = true; } // Run it. if (($res = @sybase_query($query, $this->_dbconn)) === false) { $errmsg = @sybase_get_last_message(); if (($res = sybase_query('SELECT @@ERROR AS error', $this->_dbconn)) !== false) { $row = sybase_fetch_assoc($res); $errmsg .= ' [' . array_shift($row) . ']'; } $errmsg .= ' Query was: ' . $this->_getLastQuery(); $this->croak('Database Data Transfer Failure', "sybase_query failed: $errmsg"); } if (is_bool($res)) { // Ms Sql returns true instead of an empty result on empty select. if ($is_select) return new KjwArrayResultSet(array()); return true; } elseif ($is_insert_update && sybase_num_rows($res) == 1) { $row = sybase_fetch_assoc($res); sybase_free_result($res); $this->_affectedRows = array_shift($row); if (is_integer($this->_affectedRows)) $this->_affectedRows = (int)$this->_affectedRows; $this->_insertId = array_shift($row); if (is_integer($this->_insertId)) $this->_insertId = (int)$this->_insertId; return true; } return new KjwMsResultSet($res); } /* [INHERITED DOCS] */ /* NB: Can't find docs on exact escaping. We'll do s/'/''/g and s/\0//g. */ function safeQuote($mixed) { if(is_string($mixed)) return "N'" . str_replace("'", "''", str_replace("\x00", "", $mixed)) . "'"; $ret = parent::safeQuote($mixed); // We usually use UTF8.. this is converted to UCS2 if we use NVARCHARs. // We do need to give the N'string' instead of 'string'. return $ret[0] == "'" ? 'N' . $ret : $ret; } /* [INHERITED DOCS] */ function nameQuote($string) { return '[' . str_replace(']', ']]', preg_replace("/[\x01-\x1f]/", '', str_replace("\x00", '', $string))) . ']'; } /* [INHERITED DOCS] */ function affectedRows() { // sybase_affected_rows($this->_dbconn) does *not* work with MsSql or something.. // SELECT @@ROWCOUNT *only* works within the same execute statement //if ($this->_affectedRows === null) // $this->_affectedRows = $this->selectAtom('@@ROWCOUNT'); return $this->_affectedRows; } /* [INHERITED DOCS] */ function insertId() { //return $this->selectAtom('@@IDENTITY'); return $this->_insertId; } } ?>