Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DBAL-1114] Drop database without having it opened #368

Merged
merged 1 commit into from
Jan 17, 2015

Conversation

deeky666
Copy link
Member

A recent fix in DBAL doctrine/dbal@4a603c7 makes the drop database command fail on PostgreSQL. PostgreSQL does not allow dropping a database currently opened by a connection so instead a "temporary" connection without database name specified should be used to drop the database (as already done in create database command).
Successfully tested this with MySQL, SQLite, PostgreSQL, SQL Anywhere, SQL Server (DB2 and Oracle do not support dropping and creating databases anyways).

See: http://www.doctrine-project.org/jira/browse/DBAL-1114

@nicolas-grekas
Copy link
Member

I've just been hit by this bug. Is it possible to add a test that would fail without this patch?

@tucksaun
Copy link
Contributor

👍 for the test

guilhermeblanco added a commit that referenced this pull request Jan 17, 2015
[DBAL-1114] Drop database without having it opened
@guilhermeblanco guilhermeblanco merged commit 5397467 into doctrine:master Jan 17, 2015
@guilhermeblanco
Copy link
Member

That would be overly complex to test... I don't see the point since this is a once bug.

@nervo
Copy link

nervo commented Feb 16, 2015

Same issue here.

@axalix
Copy link

axalix commented Apr 7, 2015

The problem is still there. The suggested fix didn't help.

@steve-todorov
Copy link

The issue is definitely still here. I'm experiencing this issue as well and it seems this fix is not working properly. I have the feeling Doctrine reconnects to the database somewhere in the DriverManager::getConnection() chain.

@deeky666
Copy link
Member Author

deeky666 commented Apr 8, 2015

Please don't just comment "it's not working" and rather provide some more error details. Otherwise It's really hard to do any statement on this. Thanks.

@steve-todorov
Copy link

@deeky666 I'm sorry, I should have mentioned the error - it's the same as the one in the jira ticket:

./app/console doctrine:database:drop --force
Could not drop database for connection named "test"
An exception occurred while executing 'DROP DATABASE "test"':
SQLSTATE[55006]: Object in use: 7 ERROR: cannot drop the currently open database

I'm running the console on a Windows 8.1 machine with PHP 5.6.7 installed (but the same happens on a OpenSUSE machine as well). The database is PostgreSQL 9.2.7 which is running on OpenSUSE as well.

After doing some debugging I'm beginning to thinking this might be a PDO core problem. In my case, the username and database are the same - lets say testing. The following code returns the exception above (SQLSTATE[55006]...) :

$db_host = '127.0.0.1';
$db_user = 'testing';
$db_pass = 'mypass';
$db_name = 'testing';

$currentDbQueryRaw = 'SELECT CURRENT_DATABASE();';
$dropDbQueryRaw = 'DROP DATABASE "'.$db_name .'"';

try{
    $db = new PDO('pgsql:host='.$db_host, $db_user, $db_pass);
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    try {
        $currentDatabase = $db->query($currentDbQueryRaw)->fetchAll(PDO::FETCH_ASSOC);

        // Returns current database which is the same as $db_name even though we haven't specified a dbname in the dsn.
        print_r($currentDatabase);

        // Fails with "ERROR:  cannot drop the currently open database" due to the fact we're actually connected to the db.
        try {
            $db->exec($dropDbQueryRaw);
        }
        catch(PDOException $e)
        {
            print("Could not drop table!\n");
            print_r($db->errorInfo());
            print_r($e->getTraceAsString()."\n");
        }

    }
    catch (PDOException $e) {
        print("Could not get current database.\n");
        print_r($e->getTraceAsString());
    }

}
catch (PDOException $e) {
    print("Cannot connect to database!\n");
    print_r($e);
}

I made a new user & database with different names which had nothing in common and tried the same code again:

$db_host = '127.0.0.1';
$db_user = 'testing-new';
$db_pass = 'mypass';
$db_name = 'totally_different';

$currentDbQueryRaw = 'SELECT CURRENT_DATABASE();';
$dropDbQueryRaw = 'DROP DATABASE "'.$db_name .'"';

// Fails to connect at all returning:
//  SQLSTATE[08006] [7] FATAL:  database "testing-new" does not exist
// As we can see - it's assuming that the database name is "testing-new" - the same as the username.
try{
    $db = new PDO('pgsql:host='.$db_host, $db_user, $db_pass);
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    // The rest of the code doesn't even get executed.
}
catch (PDOException $e) {
    print("Cannot connect to database!\n");
    print_r($e);
}

I believe we might need to open up a bug report in PHP. The same thing happens if you use the pg_* functions. Because I know this works in phpPgAdmin, I took the liberty of checking out how they did it. What they do is to connect to a template database such as template0 or template1 and then perform the drop query. I've tried it and it seems to be working fine.

$db_host = '127.0.0.1';
$db_user = 'testing-new';
$db_pass = 'mypass';
$db_name = 'totally_different';

$currentDbQueryRaw = 'SELECT CURRENT_DATABASE();';
$dropDbQueryRaw = 'DROP DATABASE "'.$db_name .'"';

try{
    $db = new PDO('pgsql:host='.$db_host.';dbname=template1', $db_user, $db_pass);
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    try {
        $currentDatabase = $db->query($currentDbQueryRaw)->fetchAll(PDO::FETCH_ASSOC);

        print_r($currentDatabase);

        try {
            // Works fine and drops the database.
            $db->exec($dropDbQueryRaw);
        }
        catch(PDOException $e)
        {
            print("Could not drop table!\n");
            print_r($db->errorInfo());
            print_r($e->getTraceAsString()."\n");
        }

    }
    catch (PDOException $e) {
        print("Could not get current database.\n");
        print_r($e->getTraceAsString());
    }
}
catch (PDOException $e) {
    print("Cannot connect to database!\n");
    print_r($e);
}

I made a fork of the code with a fix. Could you please check it out here? I had to change the CreateDatabase command as well due to the same problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants