. */ Doctrine::autoload('Doctrine_Connection'); /** * Doctrine_Connection_Mssql * * @package Doctrine * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @author Konsta Vesterinen * @author Lukas Smith (PEAR MDB2 library) * @version $Revision$ * @category Object Relational Mapping * @link www.phpdoctrine.com * @since 1.0 */ class Doctrine_Connection_Mssql extends Doctrine_Connection { /** * @var string $driverName the name of this connection driver */ protected $driverName = 'Mssql'; /** * the constructor * * @param Doctrine_Manager $manager * @param PDO $pdo database handle */ public function __construct(Doctrine_Manager $manager, $adapter) { // initialize all driver options $this->supported = array( 'sequences' => 'emulated', 'indexes' => true, 'affected_rows' => true, 'transactions' => true, 'summary_functions' => true, 'order_by_text' => true, 'current_id' => 'emulated', 'limit_queries' => 'emulated', 'LOBs' => true, 'replace' => 'emulated', 'sub_selects' => true, 'auto_increment' => true, 'primary_key' => true, 'result_introspection' => true, 'prepared_statements' => 'emulated', ); parent::__construct($manager, $adapter); } /** * quoteIdentifier * Quote a string so it can be safely used as a table / column name * * Quoting style depends on which database driver is being used. * * @param string $identifier identifier name to be quoted * @param bool $checkOption check the 'quote_identifier' option * * @return string quoted identifier string */ public function quoteIdentifier($identifier, $checkOption = false) { if ($check_option && ! $this->options['quote_identifier']) { return $identifier; } return '[' . str_replace(']', ']]', $identifier) . ']'; } /** * returns the next value in the given sequence * * @param string $sequence name of the sequence * @return integer the next value in the given sequence */ public function nextId($sequence) { $this->query("INSERT INTO $sequence (vapor) VALUES (0)"); $stmt = $this->query("SELECT @@IDENTITY FROM $sequence"); $data = $stmt->fetch(PDO::FETCH_NUM); return $data[0]; } /** * Adds an adapter-specific LIMIT clause to the SELECT statement. * [ borrowed from Zend Framework ] * * @param string $query * @param mixed $limit * @param mixed $offset * @link http://lists.bestpractical.com/pipermail/rt-devel/2005-June/007339.html * @return string */ public function modifyLimitQuery($query, $limit, $offset, $isManip = false) { if($limit > 0) { // we need the starting SELECT clause for later $select = 'SELECT '; if (preg_match('/^[[:space:]*SELECT[[:space:]]*DISTINCT/i', $query, $matches) == 1) $select .= 'DISTINCT '; $length = strlen($select); // is there an offset? if (! $offset) { // no offset, it's a simple TOP count return $select . ' TOP ' . $limit . substr($query, $length); } // the total of the count **and** the offset, combined. // this will be used in the "internal" portion of the // hacked-up statement. $total = $limit + $offset; // build the "real" order for the external portion. $order = implode(',', $parts['order']); // build a "reverse" order for the internal portion. $reverse = $order; $reverse = str_ireplace(" ASC", " \xFF", $reverse); $reverse = str_ireplace(" DESC", " ASC", $reverse); $reverse = str_ireplace(" \xFF", " DESC", $reverse); // create a main statement that replaces the SELECT // with a SELECT TOP $main = $select . ' TOP ' . $total . substr($query, $length); // build the hacked-up statement. // do we really need the "as" aliases here? $query = 'SELECT * FROM (' . 'SELECT TOP ' . $count . ' * FROM (' . $main . ') AS select_limit_rev ORDER BY '. $reverse . ') AS select_limit ORDER BY ' . $order; } return $query; } /** * Returns the autoincrement ID if supported or $id or fetches the current * ID in a sequence called: $table.(empty($field) ? '' : '_'.$field) * * @param string $table name of the table into which a new row was inserted * @param string $field name of the field into which a new row was inserted * @return integer */ public function lastInsertID($table = null, $field = null) { $server_info = $this->getServerVersion(); if (is_array($server_info) && !is_null($server_info['major']) && $server_info['major'] >= 8) { $query = "SELECT SCOPE_IDENTITY()"; } else { $query = "SELECT @@IDENTITY"; } return $this->queryOne($query); } }