Skip to content

Commit

Permalink
fix dropping inuse databases on Oracle
Browse files Browse the repository at this point in the history
  • Loading branch information
deeky666 committed Feb 7, 2017
1 parent eec58de commit 7b631e7
Showing 1 changed file with 68 additions and 0 deletions.
68 changes: 68 additions & 0 deletions lib/Doctrine/DBAL/Schema/OracleSchemaManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

namespace Doctrine\DBAL\Schema;

use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Driver\DriverException;
use Doctrine\DBAL\Types\Type;

/**
Expand All @@ -31,6 +33,34 @@
*/
class OracleSchemaManager extends AbstractSchemaManager
{
/**
* {@inheritdoc}
*/
public function dropDatabase($database)
{
try {
parent::dropDatabase($database);
} catch (DBALException $exception) {
$exception = $exception->getPrevious();

if (! $exception instanceof DriverException) {
throw $exception;
}

// If we have a error code 1940 (ORA-01940), the drop database operation failed
// because of active connections on the database.
// To force dropping the database, we first have to close all active connections
// on that database and issue the drop database operation again.
if ($exception->getErrorCode() !== 1940) {
throw $exception;
}

$this->killUserSessions($database);

parent::dropDatabase($database);
}
}

/**
* {@inheritdoc}
*/
Expand Down Expand Up @@ -354,4 +384,42 @@ private function getQuotedIdentifierName($identifier)

return $identifier;
}

/**
* Kills sessions connected with the given user.
*
* This is useful to force DROP USER operations which could fail because of active user sessions.
*
* @param string $user The name of the user to kill sessions for.
*
* @return void
*/
private function killUserSessions($user)
{
$sql = <<<SQL
SELECT
s.sid,
s.serial#
FROM
gv\$session s,
gv\$process p
WHERE
s.username = ?
AND p.addr(+) = s.paddr
SQL;

$activeUserSessions = $this->_conn->fetchAll($sql, array(strtoupper($user)));

foreach ($activeUserSessions as $activeUserSession) {
$activeUserSession = array_change_key_case($activeUserSession, \CASE_LOWER);

$this->_execSql(
sprintf(
"ALTER SYSTEM KILL SESSION '%s, %s' IMMEDIATE",
$activeUserSession['sid'],
$activeUserSession['serial#']
)
);
}
}
}

0 comments on commit 7b631e7

Please sign in to comment.