Commit 1b4d41c1 authored by Benjamin Eberlei's avatar Benjamin Eberlei

[DBAL-216] Bugfixes and CS. Fixed LastInsertId and added test.

parent 4c300758
...@@ -29,16 +29,18 @@ class Driver implements \Doctrine\DBAL\Driver ...@@ -29,16 +29,18 @@ class Driver implements \Doctrine\DBAL\Driver
if (!isset($params['host'])) { if (!isset($params['host'])) {
throw new SQLSrvException("Missing 'host' in configuration for sqlsrv driver."); throw new SQLSrvException("Missing 'host' in configuration for sqlsrv driver.");
} }
if (!isset($params['dbname'])) {
throw new SQLSrvException("Missing 'dbname' in configuration for sqlsrv driver.");
}
$serverName = $params['host']; $serverName = $params['host'];
if (isset($params['port'])) { if (isset($params['port'])) {
$serverName .= ', ' . $params['port']; $serverName .= ', ' . $params['port'];
} }
if (!isset($params['dbname'])) {
throw new SQLSrvException("Missing 'dbname' in configuration for sqlsrv driver.");
}
$driverOptions['Database'] = $params['dbname']; $driverOptions['Database'] = $params['dbname'];
$driverOptions['UID'] = $username; $driverOptions['UID'] = $username;
$driverOptions['PWD'] = $password; $driverOptions['PWD'] = $password;
if (!isset($driverOptions['ReturnDatesAsStrings'])) { if (!isset($driverOptions['ReturnDatesAsStrings'])) {
$driverOptions['ReturnDatesAsStrings'] = 1; $driverOptions['ReturnDatesAsStrings'] = 1;
} }
......
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\SQLSrv;
/**
* Last Id Data Container
*
* @since 2.3
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class LastInsertId
{
private $id;
public function setId($id)
{
$this->id = $id;
}
public function getId()
{
return $this->id;
}
}
...@@ -27,14 +27,24 @@ namespace Doctrine\DBAL\Driver\SQLSrv; ...@@ -27,14 +27,24 @@ namespace Doctrine\DBAL\Driver\SQLSrv;
*/ */
class SQLSrvConnection implements \Doctrine\DBAL\Driver\Connection class SQLSrvConnection implements \Doctrine\DBAL\Driver\Connection
{ {
/**
* @var resource
*/
protected $conn; protected $conn;
/**
* @var LastInsertId
*/
protected $lastInsertId;
public function __construct($serverName, $connectionOptions) public function __construct($serverName, $connectionOptions)
{ {
$this->conn = sqlsrv_connect($serverName, $connectionOptions); $this->conn = sqlsrv_connect($serverName, $connectionOptions);
if (!$this->conn) { if (!$this->conn) {
throw SQLSrvException::fromSqlSrvErrors(); throw SQLSrvException::fromSqlSrvErrors();
} }
$this->lastInsertId = new LastInsertId();
} }
/** /**
...@@ -42,7 +52,7 @@ class SQLSrvConnection implements \Doctrine\DBAL\Driver\Connection ...@@ -42,7 +52,7 @@ class SQLSrvConnection implements \Doctrine\DBAL\Driver\Connection
*/ */
public function prepare($sql) public function prepare($sql)
{ {
return new SQLSrvStatement($this->conn, $sql); return new SQLSrvStatement($this->conn, $sql, $lastInsertId);
} }
/** /**
...@@ -87,17 +97,17 @@ class SQLSrvConnection implements \Doctrine\DBAL\Driver\Connection ...@@ -87,17 +97,17 @@ class SQLSrvConnection implements \Doctrine\DBAL\Driver\Connection
*/ */
public function lastInsertId($name = null) public function lastInsertId($name = null)
{ {
if ($name === null) { if ($name !== null) {
$sql = "SELECT SCOPE_IDENTITY() AS LastInsertId";
} else {
$sql = "SELECT IDENT_CURRENT(".$this->quote($name).") AS LastInsertId"; $sql = "SELECT IDENT_CURRENT(".$this->quote($name).") AS LastInsertId";
}
$stmt = $this->prepare($sql); $stmt = $this->prepare($sql);
$stmt->execute(); $stmt->execute();
return $stmt->fetchColumn(); return $stmt->fetchColumn();
} }
return $this->lastInsertId->getId();
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
......
...@@ -23,6 +23,12 @@ use PDO; ...@@ -23,6 +23,12 @@ use PDO;
use IteratorAggregate; use IteratorAggregate;
use Doctrine\DBAL\Driver\Statement; use Doctrine\DBAL\Driver\Statement;
/**
* SQL Server Statement
*
* @since 2.3
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class SQLSrvStatement implements IteratorAggregate, Statement class SQLSrvStatement implements IteratorAggregate, Statement
{ {
/** /**
...@@ -71,10 +77,27 @@ class SQLSrvStatement implements IteratorAggregate, Statement ...@@ -71,10 +77,27 @@ class SQLSrvStatement implements IteratorAggregate, Statement
*/ */
private $defaultFetchStyle = PDO::FETCH_BOTH; private $defaultFetchStyle = PDO::FETCH_BOTH;
public function __construct($conn, $sql) /**
* @var int|null
*/
private $lastInsertId;
/**
* Append to any INSERT query to retrieve the last insert id.
*
* @var string
*/
const LAST_INSERT_ID_SQL = ';SELECT SCOPE_IDENTITY() AS LastInsertId;';
public function __construct($conn, $sql, $lastInsertId = null)
{ {
$this->conn = $conn; $this->conn = $conn;
$this->sql = $sql; $this->sql = $sql;
if (stripos($sql, 'INSERT INTO ') === 0) {
$this->sql .= self::LAST_INSERT_ID_SQL;
$this->lastInsertId = $lastInsertId;
}
} }
public function bindValue($param, $value, $type = null) public function bindValue($param, $value, $type = null)
...@@ -135,18 +158,21 @@ class SQLSrvStatement implements IteratorAggregate, Statement ...@@ -135,18 +158,21 @@ class SQLSrvStatement implements IteratorAggregate, Statement
if ($params) { if ($params) {
$hasZeroIndex = array_key_exists(0, $params); $hasZeroIndex = array_key_exists(0, $params);
foreach ($params as $key => $val) { foreach ($params as $key => $val) {
if ($hasZeroIndex && is_numeric($key)) { $key = ($hasZeroIndex && is_numeric($key)) ? $key + 1 : $key;
$this->bindValue($key + 1, $val);
} else {
$this->bindValue($key, $val); $this->bindValue($key, $val);
} }
} }
}
$this->stmt = sqlsrv_query($this->conn, $this->sql, $this->params); $this->stmt = sqlsrv_query($this->conn, $this->sql, $this->params);
if (!$this->stmt) { if (!$this->stmt) {
throw SQLSrvException::fromSqlSrvErrors(); throw SQLSrvException::fromSqlSrvErrors();
} }
if ($this->lastInsertId) {
sqlsrv_next_result($this->stmt);
sqlsrv_fetch($this->stmt);
$this->lastInsertId->setId( sqlsrv_get_field($this->stmt, 0) );
}
} }
public function setFetchMode($fetchStyle = PDO::FETCH_BOTH) public function setFetchMode($fetchStyle = PDO::FETCH_BOTH)
...@@ -180,9 +206,9 @@ class SQLSrvStatement implements IteratorAggregate, Statement ...@@ -180,9 +206,9 @@ class SQLSrvStatement implements IteratorAggregate, Statement
$ctorArgs = (isset($args[2])) ? $args[2] : array(); $ctorArgs = (isset($args[2])) ? $args[2] : array();
} }
return sqlsrv_fetch_object($this->stmt, $className, $ctorArgs); return sqlsrv_fetch_object($this->stmt, $className, $ctorArgs);
} else {
throw new SQLSrvException("Fetch mode is not supported!");
} }
throw new SQLSrvException("Fetch mode is not supported!");
} }
/** /**
......
...@@ -65,7 +65,7 @@ class Connection extends \Doctrine\DBAL\Connection ...@@ -65,7 +65,7 @@ class Connection extends \Doctrine\DBAL\Connection
} else if ($this->_platform->getName() === "drizzle") { } else if ($this->_platform->getName() === "drizzle") {
$params['portability'] = self::PORTABILITY_DRIZZLE; $params['portability'] = self::PORTABILITY_DRIZZLE;
} else if ($this->_platform->getName() === 'sqlsrv') { } else if ($this->_platform->getName() === 'sqlsrv') {
$params['portaility'] = $params['portabililty'] & self::PORTABILITY_SQLSRV; $params['portability'] = $params['portabililty'] & self::PORTABILITY_SQLSRV;
} else { } else {
$params['portability'] = $params['portability'] & self::PORTABILITY_OTHERVENDORS; $params['portability'] = $params['portability'] & self::PORTABILITY_OTHERVENDORS;
} }
......
...@@ -15,7 +15,7 @@ class WriteTest extends \Doctrine\Tests\DbalFunctionalTestCase ...@@ -15,7 +15,7 @@ class WriteTest extends \Doctrine\Tests\DbalFunctionalTestCase
try { try {
/* @var $sm \Doctrine\DBAL\Schema\AbstractSchemaManager */ /* @var $sm \Doctrine\DBAL\Schema\AbstractSchemaManager */
$table = new \Doctrine\DBAL\Schema\Table("write_table"); $table = new \Doctrine\DBAL\Schema\Table("write_table");
$table->addColumn('test_int', 'integer'); $table->addColumn('test_int', 'integer', array('autoincrement' => true));
$table->addColumn('test_string', 'string', array('notnull' => false)); $table->addColumn('test_string', 'string', array('notnull' => false));
$table->setPrimaryKey(array('test_int')); $table->setPrimaryKey(array('test_int'));
...@@ -134,4 +134,17 @@ class WriteTest extends \Doctrine\Tests\DbalFunctionalTestCase ...@@ -134,4 +134,17 @@ class WriteTest extends \Doctrine\Tests\DbalFunctionalTestCase
$this->assertEquals(2, $this->_conn->update('write_table', array('test_string' => 'baz'), array('test_string' => 'bar'))); $this->assertEquals(2, $this->_conn->update('write_table', array('test_string' => 'baz'), array('test_string' => 'bar')));
$this->assertEquals(0, $this->_conn->update('write_table', array('test_string' => 'baz'), array('test_string' => 'bar'))); $this->assertEquals(0, $this->_conn->update('write_table', array('test_string' => 'baz'), array('test_string' => 'bar')));
} }
public function testLastInsertId()
{
if ( ! $this->_conn->getDatabasePlatform()->prefersIdentityColumns()) {
$this->markTestSkipped('Test only works on platforms with identity columns.');
}
$this->assertEquals(1, $this->_conn->insert('write_table', array('test_int' => 2, 'test_string' => 'bar')));
$num = $this->_conn->lastInsertId();
$this->assertNotNull($num, "LastInsertId() should not be null.");
$this->assertTrue($num > 0, "LastInsertId() should be non-negative number.");
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment