Skip to content

Commit

Permalink
[DBAL-278] Implement OCI8Connection::lastInsertId() when a sequence i…
Browse files Browse the repository at this point in the history
…s passed.
  • Loading branch information
beberlei committed May 22, 2012
1 parent 004854f commit 5f837d4
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 15 deletions.
53 changes: 39 additions & 14 deletions lib/Doctrine/DBAL/Driver/OCI8/OCI8Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,24 @@

namespace Doctrine\DBAL\Driver\OCI8;

use Doctrine\DBAL\Platforms\OraclePlatform;

/**
* OCI8 implementation of the Connection interface.
*
* @since 2.0
*/
class OCI8Connection implements \Doctrine\DBAL\Driver\Connection
{
protected $_dbh;
/**
* @var resource
*/
protected $dbh;

protected $_executeMode = OCI_COMMIT_ON_SUCCESS;
/**
* @var int
*/
protected $executeMode = OCI_COMMIT_ON_SUCCESS;

/**
* Create a Connection to an Oracle Database using oci8 extension.
Expand All @@ -43,11 +51,11 @@ public function __construct($username, $password, $db, $charset = null, $session
define('OCI_NO_AUTO_COMMIT', 0);
}

$this->_dbh = $persistent
$this->dbh = $persistent
? @oci_pconnect($username, $password, $db, $charset, $sessionMode)
: @oci_connect($username, $password, $db, $charset, $sessionMode);

if ( ! $this->_dbh) {
if ( ! $this->dbh) {
throw OCI8Exception::fromErrorInfo(oci_error());
}
}
Expand All @@ -60,7 +68,7 @@ public function __construct($username, $password, $db, $charset = null, $session
*/
public function prepare($prepareString)
{
return new OCI8Statement($this->_dbh, $prepareString, $this);
return new OCI8Statement($this->dbh, $prepareString, $this);
}

/**
Expand Down Expand Up @@ -105,17 +113,34 @@ public function exec($statement)
return $stmt->rowCount();
}

/**
* {@inheritDoc}
*/
public function lastInsertId($name = null)
{
//TODO: throw exception or support sequences?
if ($name === null) {
return false;
}

OraclePlatform::assertValidIdentifier($name);

$sql = 'SELECT ' . $name . '.CURRVAL FROM DUAL';
$stmt = $this->query($sql);
$result = $stmt->fetch(\PDO::FETCH_ASSOC);

if ($result === false || !isset($result['CURRVAL'])) {
throw new OCI8Exception("lastInsertId failed: Query was executed but no result was returned.");
}

return (int) $result['CURRVAL'];
}

/**
* Return the current execution mode.
*/
public function getExecuteMode()
{
return $this->_executeMode;
return $this->executeMode;
}

/**
Expand All @@ -129,7 +154,7 @@ public function getExecuteMode()
*/
public function beginTransaction()
{
$this->_executeMode = OCI_NO_AUTO_COMMIT;
$this->executeMode = OCI_NO_AUTO_COMMIT;
return true;
}

Expand All @@ -139,10 +164,10 @@ public function beginTransaction()
*/
public function commit()
{
if (!oci_commit($this->_dbh)) {
if (!oci_commit($this->dbh)) {
throw OCI8Exception::fromErrorInfo($this->errorInfo());
}
$this->_executeMode = OCI_COMMIT_ON_SUCCESS;
$this->executeMode = OCI_COMMIT_ON_SUCCESS;
return true;
}

Expand All @@ -152,16 +177,16 @@ public function commit()
*/
public function rollBack()
{
if (!oci_rollback($this->_dbh)) {
if (!oci_rollback($this->dbh)) {
throw OCI8Exception::fromErrorInfo($this->errorInfo());
}
$this->_executeMode = OCI_COMMIT_ON_SUCCESS;
$this->executeMode = OCI_COMMIT_ON_SUCCESS;
return true;
}

public function errorCode()
{
$error = oci_error($this->_dbh);
$error = oci_error($this->dbh);
if ($error !== false) {
$error = $error['code'];
}
Expand All @@ -170,6 +195,6 @@ public function errorCode()

public function errorInfo()
{
return oci_error($this->_dbh);
return oci_error($this->dbh);
}
}
15 changes: 15 additions & 0 deletions lib/Doctrine/DBAL/Platforms/OraclePlatform.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
namespace Doctrine\DBAL\Platforms;

use Doctrine\DBAL\Schema\TableDiff;
use Doctrine\DBAL\DBALException;

/**
* OraclePlatform.
Expand All @@ -31,6 +32,20 @@
*/
class OraclePlatform extends AbstractPlatform
{
/**
* Assertion for Oracle identifiers
*
* @link http://docs.oracle.com/cd/B19306_01/server.102/b14200/sql_elements008.htm
* @param string
* @throws DBALException
*/
static public function assertValidIdentifier($identifier)
{
if ( ! preg_match('(^(([a-zA-Z]{1}[a-zA-Z0-9_$#]{0,})|("[^"]+"))$)', $identifier)) {
throw new DBALException("Invalid Oracle identifier");
}
}

/**
* return string to call a function to get a substring inside an SQL statement
*
Expand Down
31 changes: 31 additions & 0 deletions tests/Doctrine/Tests/DBAL/Functional/WriteTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -146,4 +146,35 @@ public function testLastInsertId()
$this->assertNotNull($num, "LastInsertId() should not be null.");
$this->assertTrue($num > 0, "LastInsertId() should be non-negative number.");
}

public function testLastInsertIdSequence()
{
if ( ! $this->_conn->getDatabasePlatform()->supportsSequences()) {
$this->markTestSkipped('Test only works on platforms with sequences.');
}

$sequence = new \Doctrine\DBAL\Schema\Sequence('write_table_seq');
try {
$this->_conn->getSchemaManager()->dropSequence($sequence);
} catch(\Exception $e) {}
$this->_conn->getSchemaManager()->createSequence($sequence);

$stmt = $this->_conn->query($this->_conn->getDatabasePlatform()->getSequenceNextValSQL('write_table_seq'));
$nextSequenceVal = $stmt->fetchColumn();

$lastInsertId = $this->_conn->lastInsertId('write_table_seq');

$this->assertTrue($lastInsertId > 0);
$this->assertEquals($nextSequenceVal, $lastInsertId);
}

public function testLastInsertIdNoSequenceGiven()
{
if ( ! $this->_conn->getDatabasePlatform()->supportsSequences()) {
$this->markTestSkipped('Test only works on platforms with sequences.');
}

$this->assertFalse($this->_conn->lastInsertId( null ));

}
}
47 changes: 46 additions & 1 deletion tests/Doctrine/Tests/DBAL/Platforms/OraclePlatformTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,51 @@

class OraclePlatformTest extends AbstractPlatformTestCase
{
static public function dataValidIdentifiers()
{
return array(
array('a'),
array('foo'),
array('Foo'),
array('Foo123'),
array('Foo#bar_baz$'),
array('"a"'),
array('"1"'),
array('"foo_bar"'),
array('"@$%&!"'),
);
}

/**
* @dataProvider dataValidIdentifiers
*/
public function testValidIdentifiers($identifier)
{
$platform = $this->createPlatform();
$platform->assertValidIdentifier($identifier);
}

static public function dataInvalidIdentifiers()
{
return array(
array('1'),
array('abc&'),
array('abc-def'),
array('"'),
array('"foo"bar"'),
);
}

/**
* @dataProvider dataInvalidIdentifiers
*/
public function testInvalidIdentifiers($identifier)
{
$this->setExpectedException('Doctrine\DBAL\DBALException');
$platform = $this->createPlatform();
$platform->assertValidIdentifier($identifier);
}

public function createPlatform()
{
return new OraclePlatform;
Expand Down Expand Up @@ -224,4 +269,4 @@ public function getBitOrComparisonExpressionSql($value1, $value2)
$this->getBitAndComparisonExpressionSql($value1, $value2)
. '+' . $value2 . ')';
}
}
}

0 comments on commit 5f837d4

Please sign in to comment.