Skip to content

Commit e2cbc08

Browse files
alouafimarksteward
authored andcommitted
Fix "database in use" error in tests (#776)
- Use autocommit in database_exists like other DDL - Consolidate autocommit a bit more in drop_database (after a4154bd) - Remove now-redundant code to kill idle postgres sessions
1 parent a4d8b5b commit e2cbc08

File tree

1 file changed

+12
-23
lines changed

1 file changed

+12
-23
lines changed

sqlalchemy_utils/functions/database.py

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,7 @@ def database_exists(url):
485485
text = "SELECT 1 FROM pg_database WHERE datname='%s'" % database
486486
for db in (database, 'postgres', 'template1', 'template0', None):
487487
url = _set_url_database(url, database=db)
488-
engine = sa.create_engine(url)
488+
engine = sa.create_engine(url, isolation_level='AUTOCOMMIT')
489489
try:
490490
return bool(_get_scalar_result(engine, sa.text(text)))
491491
except (ProgrammingError, OperationalError):
@@ -508,6 +508,14 @@ def database_exists(url):
508508
# The default SQLAlchemy database is in memory, and :memory: is
509509
# not required, thus we should support that use case.
510510
return True
511+
elif dialect_name == 'mssql':
512+
text = "SELECT 1 FROM sys.databases WHERE name = '%s'" % database
513+
url = _set_url_database(url, database='master')
514+
engine = sa.create_engine(url, isolation_level='AUTOCOMMIT')
515+
try:
516+
return bool(_get_scalar_result(engine, sa.text(text)))
517+
except (ProgrammingError, OperationalError):
518+
return False
511519
else:
512520
text = 'SELECT 1'
513521
try:
@@ -626,35 +634,16 @@ def drop_database(url):
626634
elif not dialect_name == 'sqlite':
627635
url = _set_url_database(url, database=None)
628636

629-
if dialect_name == 'mssql' and dialect_driver in {'pymssql', 'pyodbc'}:
630-
engine = sa.create_engine(url, connect_args={'autocommit': True})
631-
elif dialect_name == 'postgresql' and dialect_driver in {
632-
'asyncpg', 'pg8000', 'psycopg', 'psycopg2', 'psycopg2cffi'}:
637+
if (dialect_name == 'mssql' and dialect_driver in {'pymssql', 'pyodbc'}) \
638+
or (dialect_name == 'postgresql' and dialect_driver in {
639+
'asyncpg', 'pg8000', 'psycopg', 'psycopg2', 'psycopg2cffi'}):
633640
engine = sa.create_engine(url, isolation_level='AUTOCOMMIT')
634641
else:
635642
engine = sa.create_engine(url)
636643

637644
if dialect_name == 'sqlite' and database != ':memory:':
638645
if database:
639646
os.remove(database)
640-
elif dialect_name == 'postgresql':
641-
with engine.begin() as conn:
642-
# Disconnect all users from the database we are dropping.
643-
version = conn.dialect.server_version_info
644-
pid_column = (
645-
'pid' if (version >= (9, 2)) else 'procpid'
646-
)
647-
text = '''
648-
SELECT pg_terminate_backend(pg_stat_activity.{pid_column})
649-
FROM pg_stat_activity
650-
WHERE pg_stat_activity.datname = '{database}'
651-
AND {pid_column} <> pg_backend_pid();
652-
'''.format(pid_column=pid_column, database=database)
653-
conn.execute(sa.text(text))
654-
655-
# Drop the database.
656-
text = f'DROP DATABASE {quote(conn, database)}'
657-
conn.execute(sa.text(text))
658647
else:
659648
with engine.begin() as conn:
660649
text = f'DROP DATABASE {quote(conn, database)}'

0 commit comments

Comments
 (0)